Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit ea525a2

Browse files
Issue #27078: Added BUILD_STRING opcode. Optimized f-strings evaluation.
1 parent 620bb27 commit ea525a2

14 files changed

Lines changed: 396 additions & 356 deletions

File tree

Doc/library/dis.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -777,6 +777,14 @@ All of the following opcodes use their arguments.
777777
.. versionadded:: 3.6
778778

779779

780+
.. opcode:: BUILD_STRING (count)
781+
782+
Concatenates *count* strings from the stack and pushes the resulting string
783+
onto the stack.
784+
785+
.. versionadded:: 3.6
786+
787+
780788
.. opcode:: LOAD_ATTR (namei)
781789

782790
Replaces TOS with ``getattr(TOS, co_names[namei])``.

Include/opcode.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ extern "C" {
123123
#define SETUP_ASYNC_WITH 154
124124
#define FORMAT_VALUE 155
125125
#define BUILD_CONST_KEY_MAP 156
126+
#define BUILD_STRING 157
126127

127128
/* EXCEPT_HANDLER is a special, implicit block type which is created when
128129
entering an except handler. It is not an opcode but we define it here

Include/unicodeobject.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1955,6 +1955,14 @@ PyAPI_FUNC(PyObject*) PyUnicode_Join(
19551955
PyObject *seq /* Sequence object */
19561956
);
19571957

1958+
#ifndef Py_LIMITED_API
1959+
PyAPI_FUNC(PyObject *) _PyUnicode_JoinArray(
1960+
PyObject *separator,
1961+
PyObject **items,
1962+
Py_ssize_t seqlen
1963+
);
1964+
#endif /* Py_LIMITED_API */
1965+
19581966
/* Return 1 if substr matches str[start:end] at the given tail end, 0
19591967
otherwise. */
19601968

Lib/importlib/_bootstrap_external.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,8 @@ def _write_atomic(path, data, mode=0o666):
232232
# Python 3.6a1 3370 (16 bit wordcode)
233233
# Python 3.6a1 3371 (add BUILD_CONST_KEY_MAP opcode #27140)
234234
# Python 3.6a1 3372 (MAKE_FUNCTION simplification, remove MAKE_CLOSURE
235-
#27095)
235+
# #27095)
236+
# Python 3.6b1 3373 (add BUILD_STRING opcode #27078)
236237
#
237238
# MAGIC must change whenever the bytecode emitted by the compiler may no
238239
# longer be understood by older implementations of the eval loop (usually
@@ -241,7 +242,7 @@ def _write_atomic(path, data, mode=0o666):
241242
# Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array
242243
# in PC/launcher.c must also be updated.
243244

244-
MAGIC_NUMBER = (3372).to_bytes(2, 'little') + b'\r\n'
245+
MAGIC_NUMBER = (3373).to_bytes(2, 'little') + b'\r\n'
245246
_RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c
246247

247248
_PYCACHE = '__pycache__'

Lib/opcode.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,5 +213,6 @@ def jabs_op(name, op):
213213

214214
def_op('FORMAT_VALUE', 155)
215215
def_op('BUILD_CONST_KEY_MAP', 156)
216+
def_op('BUILD_STRING', 157)
216217

217218
del def_op, name_op, jrel_op, jabs_op

Misc/NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ What's New in Python 3.6.0 beta 1
1010
Core and Builtins
1111
-----------------
1212

13+
- Issue #27078: Added BUILD_STRING opcode. Optimized f-strings evaluation.
14+
1315
- Issue #17884: Python now requires systems with inttypes.h and stdint.h
1416

1517
- Issue #27961: Require platforms to support ``long long``. Python hasn't

Objects/abstract.c

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -675,13 +675,31 @@ PyObject_Format(PyObject *obj, PyObject *format_spec)
675675
PyObject *result = NULL;
676676
_Py_IDENTIFIER(__format__);
677677

678+
if (format_spec != NULL && !PyUnicode_Check(format_spec)) {
679+
PyErr_Format(PyExc_SystemError,
680+
"Format specifier must be a string, not %.200s",
681+
Py_TYPE(format_spec)->tp_name);
682+
return NULL;
683+
}
684+
685+
/* Fast path for common types. */
686+
if (format_spec == NULL || PyUnicode_GET_LENGTH(format_spec) == 0) {
687+
if (PyUnicode_CheckExact(obj)) {
688+
Py_INCREF(obj);
689+
return obj;
690+
}
691+
if (PyLong_CheckExact(obj)) {
692+
return PyObject_Str(obj);
693+
}
694+
}
695+
678696
/* If no format_spec is provided, use an empty string */
679697
if (format_spec == NULL) {
680698
empty = PyUnicode_New(0, 0);
681699
format_spec = empty;
682700
}
683701

684-
/* Find the (unbound!) __format__ method (a borrowed reference) */
702+
/* Find the (unbound!) __format__ method */
685703
meth = _PyObject_LookupSpecial(obj, &PyId___format__);
686704
if (meth == NULL) {
687705
if (!PyErr_Occurred())

Objects/unicodeobject.c

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9892,20 +9892,10 @@ case_operation(PyObject *self,
98929892
PyObject *
98939893
PyUnicode_Join(PyObject *separator, PyObject *seq)
98949894
{
9895-
PyObject *sep = NULL;
9896-
Py_ssize_t seplen;
9897-
PyObject *res = NULL; /* the result */
9898-
PyObject *fseq; /* PySequence_Fast(seq) */
9899-
Py_ssize_t seqlen; /* len(fseq) -- number of items in sequence */
9895+
PyObject *res;
9896+
PyObject *fseq;
9897+
Py_ssize_t seqlen;
99009898
PyObject **items;
9901-
PyObject *item;
9902-
Py_ssize_t sz, i, res_offset;
9903-
Py_UCS4 maxchar;
9904-
Py_UCS4 item_maxchar;
9905-
int use_memcpy;
9906-
unsigned char *res_data = NULL, *sep_data = NULL;
9907-
PyObject *last_obj;
9908-
unsigned int kind = 0;
99099899

99109900
fseq = PySequence_Fast(seq, "can only join an iterable");
99119901
if (fseq == NULL) {
@@ -9916,21 +9906,39 @@ PyUnicode_Join(PyObject *separator, PyObject *seq)
99169906
* so we are sure that fseq won't be mutated.
99179907
*/
99189908

9909+
items = PySequence_Fast_ITEMS(fseq);
99199910
seqlen = PySequence_Fast_GET_SIZE(fseq);
9911+
res = _PyUnicode_JoinArray(separator, items, seqlen);
9912+
Py_DECREF(fseq);
9913+
return res;
9914+
}
9915+
9916+
PyObject *
9917+
_PyUnicode_JoinArray(PyObject *separator, PyObject **items, Py_ssize_t seqlen)
9918+
{
9919+
PyObject *res = NULL; /* the result */
9920+
PyObject *sep = NULL;
9921+
Py_ssize_t seplen;
9922+
PyObject *item;
9923+
Py_ssize_t sz, i, res_offset;
9924+
Py_UCS4 maxchar;
9925+
Py_UCS4 item_maxchar;
9926+
int use_memcpy;
9927+
unsigned char *res_data = NULL, *sep_data = NULL;
9928+
PyObject *last_obj;
9929+
unsigned int kind = 0;
9930+
99209931
/* If empty sequence, return u"". */
99219932
if (seqlen == 0) {
9922-
Py_DECREF(fseq);
99239933
_Py_RETURN_UNICODE_EMPTY();
99249934
}
99259935

99269936
/* If singleton sequence with an exact Unicode, return that. */
99279937
last_obj = NULL;
9928-
items = PySequence_Fast_ITEMS(fseq);
99299938
if (seqlen == 1) {
99309939
if (PyUnicode_CheckExact(items[0])) {
99319940
res = items[0];
99329941
Py_INCREF(res);
9933-
Py_DECREF(fseq);
99349942
return res;
99359943
}
99369944
seplen = 0;
@@ -10065,13 +10073,11 @@ PyUnicode_Join(PyObject *separator, PyObject *seq)
1006510073
assert(res_offset == PyUnicode_GET_LENGTH(res));
1006610074
}
1006710075

10068-
Py_DECREF(fseq);
1006910076
Py_XDECREF(sep);
1007010077
assert(_PyUnicode_CheckConsistency(res, 1));
1007110078
return res;
1007210079

1007310080
onError:
10074-
Py_DECREF(fseq);
1007510081
Py_XDECREF(sep);
1007610082
Py_XDECREF(res);
1007710083
return NULL;

PC/launcher.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1089,7 +1089,7 @@ static PYC_MAGIC magic_values[] = {
10891089
{ 3190, 3230, L"3.3" },
10901090
{ 3250, 3310, L"3.4" },
10911091
{ 3320, 3351, L"3.5" },
1092-
{ 3360, 3371, L"3.6" },
1092+
{ 3360, 3373, L"3.6" },
10931093
{ 0 }
10941094
};
10951095

Python/ceval.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2538,6 +2538,24 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
25382538
DISPATCH();
25392539
}
25402540

2541+
TARGET(BUILD_STRING) {
2542+
PyObject *str;
2543+
PyObject *empty = PyUnicode_New(0, 0);
2544+
if (empty == NULL) {
2545+
goto error;
2546+
}
2547+
str = _PyUnicode_JoinArray(empty, stack_pointer - oparg, oparg);
2548+
Py_DECREF(empty);
2549+
if (str == NULL)
2550+
goto error;
2551+
while (--oparg >= 0) {
2552+
PyObject *item = POP();
2553+
Py_DECREF(item);
2554+
}
2555+
PUSH(str);
2556+
DISPATCH();
2557+
}
2558+
25412559
TARGET(BUILD_TUPLE) {
25422560
PyObject *tup = PyTuple_New(oparg);
25432561
if (tup == NULL)

0 commit comments

Comments
 (0)