diff options
| author | Terry Jan Reedy <tjreedy@udel.edu> | 2016-07-16 18:27:11 -0400 |
|---|---|---|
| committer | Terry Jan Reedy <tjreedy@udel.edu> | 2016-07-16 18:27:11 -0400 |
| commit | 61537aeaa3e0a9548a16ce3bfc9c4dd629ce7211 (patch) | |
| tree | fabfded1dfc58221baa18a9a5a21aa2add31933f /Python/ceval.c | |
| parent | a9ae1d67054fc0a8ad272082c41919044d1c1e9c (diff) | |
| parent | 8f310e95a73a11c4184b7cd40bfb0d04609a171c (diff) | |
| download | cpython-61537aeaa3e0a9548a16ce3bfc9c4dd629ce7211.tar.gz | |
Issue #25507: Merge from 3.5 with ttk replacing colorchooser.
IDLE no longer runs buggy code because of its tkinter imports.
Users must include the same imports required to run directly in Python.
Diffstat (limited to 'Python/ceval.c')
| -rw-r--r-- | Python/ceval.c | 448 |
1 files changed, 241 insertions, 207 deletions
diff --git a/Python/ceval.c b/Python/ceval.c index 3d69038444..2b4f7ccfaa 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -125,7 +125,7 @@ static PyObject * load_args(PyObject ***, int); #ifdef LLTRACE static int lltrace; -static int prtrace(PyObject *, char *); +static int prtrace(PyObject *, const char *); #endif static int call_trace(Py_tracefunc, PyObject *, PyThreadState *, PyFrameObject *, @@ -144,7 +144,7 @@ static int import_all_from(PyObject *, PyObject *); static void format_exc_check_arg(PyObject *, const char *, PyObject *); static void format_exc_unbound(PyCodeObject *co, int oparg); static PyObject * unicode_concatenate(PyObject *, PyObject *, - PyFrameObject *, unsigned char *); + PyFrameObject *, const unsigned short *); static PyObject * special_lookup(PyObject *, _Py_Identifier *); #define NAME_ERROR_MSG \ @@ -800,7 +800,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) int lastopcode = 0; #endif PyObject **stack_pointer; /* Next free slot in value stack */ - unsigned char *next_instr; + const unsigned short *next_instr; int opcode; /* Current opcode */ int oparg; /* Current opcode argument, if any */ enum why_code why; /* Reason for block stack unwind */ @@ -818,7 +818,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) time it is tested. */ int instr_ub = -1, instr_lb = 0, instr_prev = -1; - unsigned char *first_instr; + const unsigned short *first_instr; PyObject *names; PyObject *consts; @@ -886,24 +886,10 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) /* Import the static jump table */ #include "opcode_targets.h" -/* This macro is used when several opcodes defer to the same implementation - (e.g. SETUP_LOOP, SETUP_FINALLY) */ -#define TARGET_WITH_IMPL(op, impl) \ - TARGET_##op: \ - opcode = op; \ - if (HAS_ARG(op)) \ - oparg = NEXTARG(); \ - case op: \ - goto impl; \ - #define TARGET(op) \ TARGET_##op: \ - opcode = op; \ - if (HAS_ARG(op)) \ - oparg = NEXTARG(); \ case op: - #define DISPATCH() \ { \ if (!_Py_atomic_load_relaxed(&eval_breaker)) { \ @@ -917,7 +903,8 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) { \ if (!lltrace && !_Py_TracingPossible) { \ f->f_lasti = INSTR_OFFSET(); \ - goto *opcode_targets[*next_instr++]; \ + NEXTOPARG(); \ + goto *opcode_targets[opcode]; \ } \ goto fast_next_opcode; \ } @@ -926,7 +913,8 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) { \ if (!_Py_TracingPossible) { \ f->f_lasti = INSTR_OFFSET(); \ - goto *opcode_targets[*next_instr++]; \ + NEXTOPARG(); \ + goto *opcode_targets[opcode]; \ } \ goto fast_next_opcode; \ } @@ -935,10 +923,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) #else #define TARGET(op) \ case op: -#define TARGET_WITH_IMPL(op, impl) \ - /* silence compiler warnings about `impl` unused */ \ - if (0) goto impl; \ - case op: + #define DISPATCH() continue #define FAST_DISPATCH() goto fast_next_opcode #endif @@ -994,28 +979,38 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) /* Code access macros */ -#define INSTR_OFFSET() ((int)(next_instr - first_instr)) -#define NEXTOP() (*next_instr++) -#define NEXTARG() (next_instr += 2, (next_instr[-1]<<8) + next_instr[-2]) -#define PEEKARG() ((next_instr[2]<<8) + next_instr[1]) -#define JUMPTO(x) (next_instr = first_instr + (x)) -#define JUMPBY(x) (next_instr += (x)) +#ifdef WORDS_BIGENDIAN + #define OPCODE(word) ((word) >> 8) + #define OPARG(word) ((word) & 255) +#else + #define OPCODE(word) ((word) & 255) + #define OPARG(word) ((word) >> 8) +#endif +/* The integer overflow is checked by an assertion below. */ +#define INSTR_OFFSET() (2*(int)(next_instr - first_instr)) +#define NEXTOPARG() do { \ + unsigned short word = *next_instr; \ + opcode = OPCODE(word); \ + oparg = OPARG(word); \ + next_instr++; \ + } while (0) +#define JUMPTO(x) (next_instr = first_instr + (x)/2) +#define JUMPBY(x) (next_instr += (x)/2) /* OpCode prediction macros Some opcodes tend to come in pairs thus making it possible to predict the second code when the first is run. For example, - COMPARE_OP is often followed by JUMP_IF_FALSE or JUMP_IF_TRUE. And, - those opcodes are often followed by a POP_TOP. + COMPARE_OP is often followed by POP_JUMP_IF_FALSE or POP_JUMP_IF_TRUE. Verifying the prediction costs a single high-speed test of a register variable against a constant. If the pairing was good, then the processor's own internal branch predication has a high likelihood of success, resulting in a nearly zero-overhead transition to the next opcode. A successful prediction saves a trip through the eval-loop - including its two unpredictable branches, the HAS_ARG test and the - switch-case. Combined with the processor's internal branch prediction, - a successful PREDICT has the effect of making the two opcodes run as if - they were a single new opcode with the bodies combined. + including its unpredictable switch-case branch. Combined with the + processor's internal branch prediction, a successful PREDICT has the + effect of making the two opcodes run as if they were a single new opcode + with the bodies combined. If collecting opcode statistics, your choices are to either keep the predictions turned-on and interpret the results as if some opcodes @@ -1030,13 +1025,19 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) #if defined(DYNAMIC_EXECUTION_PROFILE) || USE_COMPUTED_GOTOS #define PREDICT(op) if (0) goto PRED_##op -#define PREDICTED(op) PRED_##op: -#define PREDICTED_WITH_ARG(op) PRED_##op: #else -#define PREDICT(op) if (*next_instr == op) goto PRED_##op -#define PREDICTED(op) PRED_##op: next_instr++ -#define PREDICTED_WITH_ARG(op) PRED_##op: oparg = PEEKARG(); next_instr += 3 +#define PREDICT(op) \ + do{ \ + unsigned short word = *next_instr; \ + opcode = OPCODE(word); \ + if (opcode == op){ \ + oparg = OPARG(word); \ + next_instr++; \ + goto PRED_##op; \ + } \ + } while(0) #endif +#define PREDICTED(op) PRED_##op: /* Stack manipulation macros */ @@ -1100,7 +1101,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) } #define UNWIND_EXCEPT_HANDLER(b) \ - { \ + do { \ PyObject *type, *value, *traceback; \ assert(STACK_LEVEL() >= (b)->b_level + 3); \ while (STACK_LEVEL() > (b)->b_level + 3) { \ @@ -1116,7 +1117,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) Py_XDECREF(type); \ Py_XDECREF(value); \ Py_XDECREF(traceback); \ - } + } while(0) /* Start of code */ @@ -1165,16 +1166,16 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) consts = co->co_consts; fastlocals = f->f_localsplus; freevars = f->f_localsplus + co->co_nlocals; - first_instr = (unsigned char*) PyBytes_AS_STRING(co->co_code); - /* An explanation is in order for the next line. - - f->f_lasti now refers to the index of the last instruction - executed. You might think this was obvious from the name, but - this wasn't always true before 2.3! PyFrame_New now sets - f->f_lasti to -1 (i.e. the index *before* the first instruction) - and YIELD_VALUE doesn't fiddle with f_lasti any more. So this - does work. Promise. - YIELD_FROM sets f_lasti to itself, in order to repeated yield + assert(PyBytes_Check(co->co_code)); + assert(PyBytes_GET_SIZE(co->co_code) <= INT_MAX); + assert(PyBytes_GET_SIZE(co->co_code) % 2 == 0); + assert(_Py_IS_ALIGNED(PyBytes_AS_STRING(co->co_code), 2)); + first_instr = (unsigned short*) PyBytes_AS_STRING(co->co_code); + /* + f->f_lasti refers to the index of the last instruction, + unless it's -1 in which case next_instr should be first_instr. + + YIELD_FROM sets f_lasti to itself, in order to repeatedly yield multiple values. When the PREDICT() macros are enabled, some opcode pairs follow in @@ -1183,9 +1184,13 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) were a single new opcode; accordingly,f->f_lasti will point to the first code in the pair (for instance, GET_ITER followed by FOR_ITER is effectively a single opcode and f->f_lasti will point - at to the beginning of the combined pair.) + to the beginning of the combined pair.) */ - next_instr = first_instr + f->f_lasti + 1; + next_instr = first_instr; + if (f->f_lasti >= 0) { + assert(f->f_lasti % 2 == 0); + next_instr += f->f_lasti/2 + 1; + } stack_pointer = f->f_stacktop; assert(stack_pointer != NULL); f->f_stacktop = NULL; /* remains NULL unless yield suspends frame */ @@ -1249,7 +1254,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) Py_MakePendingCalls() above. */ if (_Py_atomic_load_relaxed(&eval_breaker)) { - if (*next_instr == SETUP_FINALLY) { + if (OPCODE(*next_instr) == SETUP_FINALLY) { /* Make the last opcode before a try: finally: block uninterruptible. */ goto fast_next_opcode; @@ -1322,11 +1327,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) /* Extract opcode and argument */ - opcode = NEXTOP(); - oparg = 0; /* allows oparg to be stored in a register because - it doesn't have to be remembered across a full loop */ - if (HAS_ARG(opcode)) - oparg = NEXTARG(); + NEXTOPARG(); dispatch_opcode: #ifdef DYNAMIC_EXECUTION_PROFILE #ifdef DXPAIRS @@ -1377,6 +1378,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) FAST_DISPATCH(); } + PREDICTED(LOAD_CONST); TARGET(LOAD_CONST) { PyObject *value = GETITEM(consts, oparg); Py_INCREF(value); @@ -1384,7 +1386,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) FAST_DISPATCH(); } - PREDICTED_WITH_ARG(STORE_FAST); + PREDICTED(STORE_FAST); TARGET(STORE_FAST) { PyObject *value = POP(); SETLOCAL(oparg, value); @@ -2006,6 +2008,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) } SET_TOP(awaitable); + PREDICT(LOAD_CONST); DISPATCH(); } @@ -2048,9 +2051,11 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) Py_DECREF(next_iter); PUSH(awaitable); + PREDICT(LOAD_CONST); DISPATCH(); } + PREDICTED(GET_AWAITABLE); TARGET(GET_AWAITABLE) { PyObject *iterable = TOP(); PyObject *iter = _PyCoro_GetAwaitableIter(iterable); @@ -2078,6 +2083,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) goto error; } + PREDICT(LOAD_CONST); DISPATCH(); } @@ -2111,7 +2117,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) f->f_stacktop = stack_pointer; why = WHY_YIELD; /* and repeat... */ - f->f_lasti--; + f->f_lasti -= 2; goto fast_yield; } @@ -2133,6 +2139,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) DISPATCH(); } + PREDICTED(POP_BLOCK); TARGET(POP_BLOCK) { PyTryBlock *b = PyFrame_BlockPop(f); UNWIND_BLOCK(b); @@ -2249,7 +2256,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) DISPATCH(); } - PREDICTED_WITH_ARG(UNPACK_SEQUENCE); + PREDICTED(UNPACK_SEQUENCE); TARGET(UNPACK_SEQUENCE) { PyObject *seq = POP(), *item, **items; if (PyTuple_CheckExact(seq) && @@ -2358,7 +2365,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) } else { v = PyObject_GetItem(locals, name); - if (v == NULL && _PyErr_OCCURRED()) { + if (v == NULL) { if (!PyErr_ExceptionMatches(PyExc_KeyError)) goto error; PyErr_Clear(); @@ -2398,26 +2405,33 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) PyObject *name = GETITEM(names, oparg); PyObject *v; if (PyDict_CheckExact(f->f_globals) - && PyDict_CheckExact(f->f_builtins)) { + && PyDict_CheckExact(f->f_builtins)) + { v = _PyDict_LoadGlobal((PyDictObject *)f->f_globals, (PyDictObject *)f->f_builtins, name); if (v == NULL) { - if (!_PyErr_OCCURRED()) + if (!_PyErr_OCCURRED()) { + /* _PyDict_LoadGlobal() returns NULL without raising + * an exception if the key doesn't exist */ format_exc_check_arg(PyExc_NameError, NAME_ERROR_MSG, name); + } goto error; } Py_INCREF(v); } else { /* Slow-path if globals or builtins is not a dict */ + + /* namespace 1: globals */ v = PyObject_GetItem(f->f_globals, name); if (v == NULL) { if (!PyErr_ExceptionMatches(PyExc_KeyError)) goto error; PyErr_Clear(); + /* namespace 2: builtins */ v = PyObject_GetItem(f->f_builtins, name); if (v == NULL) { if (PyErr_ExceptionMatches(PyExc_KeyError)) @@ -2477,7 +2491,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) } else { value = PyObject_GetItem(locals, name); - if (value == NULL && PyErr_Occurred()) { + if (value == NULL) { if (!PyErr_ExceptionMatches(PyExc_KeyError)) goto error; PyErr_Clear(); @@ -2540,9 +2554,8 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) DISPATCH(); } - TARGET_WITH_IMPL(BUILD_TUPLE_UNPACK, _build_list_unpack) - TARGET(BUILD_LIST_UNPACK) - _build_list_unpack: { + TARGET(BUILD_TUPLE_UNPACK) + TARGET(BUILD_LIST_UNPACK) { int convert_to_tuple = opcode == BUILD_TUPLE_UNPACK; int i; PyObject *sum = PyList_New(0); @@ -2639,9 +2652,41 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) DISPATCH(); } - TARGET_WITH_IMPL(BUILD_MAP_UNPACK_WITH_CALL, _build_map_unpack) - TARGET(BUILD_MAP_UNPACK) - _build_map_unpack: { + TARGET(BUILD_CONST_KEY_MAP) { + int i; + PyObject *map; + PyObject *keys = TOP(); + if (!PyTuple_CheckExact(keys) || + PyTuple_GET_SIZE(keys) != (Py_ssize_t)oparg) { + PyErr_SetString(PyExc_SystemError, + "bad BUILD_CONST_KEY_MAP keys argument"); + goto error; + } + map = _PyDict_NewPresized((Py_ssize_t)oparg); + if (map == NULL) { + goto error; + } + for (i = oparg; i > 0; i--) { + int err; + PyObject *key = PyTuple_GET_ITEM(keys, oparg - i); + PyObject *value = PEEK(i + 1); + err = PyDict_SetItem(map, key, value); + if (err != 0) { + Py_DECREF(map); + goto error; + } + } + + Py_DECREF(POP()); + while (oparg--) { + Py_DECREF(POP()); + } + PUSH(map); + DISPATCH(); + } + + TARGET(BUILD_MAP_UNPACK_WITH_CALL) + TARGET(BUILD_MAP_UNPACK) { int with_call = opcode == BUILD_MAP_UNPACK_WITH_CALL; int num_maps; int function_location; @@ -2775,21 +2820,13 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) Py_INCREF(func); from = POP(); level = TOP(); - if (PyLong_AsLong(level) != -1 || PyErr_Occurred()) - args = PyTuple_Pack(5, + args = PyTuple_Pack(5, name, f->f_globals, f->f_locals == NULL ? Py_None : f->f_locals, from, level); - else - args = PyTuple_Pack(4, - name, - f->f_globals, - f->f_locals == NULL ? - Py_None : f->f_locals, - from); Py_DECREF(level); Py_DECREF(from); if (args == NULL) { @@ -2848,7 +2885,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) FAST_DISPATCH(); } - PREDICTED_WITH_ARG(POP_JUMP_IF_FALSE); + PREDICTED(POP_JUMP_IF_FALSE); TARGET(POP_JUMP_IF_FALSE) { PyObject *cond = POP(); int err; @@ -2872,7 +2909,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) DISPATCH(); } - PREDICTED_WITH_ARG(POP_JUMP_IF_TRUE); + PREDICTED(POP_JUMP_IF_TRUE); TARGET(POP_JUMP_IF_TRUE) { PyObject *cond = POP(); int err; @@ -2949,7 +2986,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) DISPATCH(); } - PREDICTED_WITH_ARG(JUMP_ABSOLUTE); + PREDICTED(JUMP_ABSOLUTE); TARGET(JUMP_ABSOLUTE) { JUMPTO(oparg); #if FAST_LOOPS @@ -2975,6 +3012,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) if (iter == NULL) goto error; PREDICT(FOR_ITER); + PREDICT(CALL_FUNCTION); DISPATCH(); } @@ -3003,10 +3041,11 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) if (iter == NULL) goto error; } + PREDICT(LOAD_CONST); DISPATCH(); } - PREDICTED_WITH_ARG(FOR_ITER); + PREDICTED(FOR_ITER); TARGET(FOR_ITER) { /* before: [iter]; after: [iter, iter()] *or* [] */ PyObject *iter = TOP(); @@ -3028,6 +3067,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) STACKADJ(-1); Py_DECREF(iter); JUMPBY(oparg); + PREDICT(POP_BLOCK); DISPATCH(); } @@ -3044,10 +3084,9 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) goto fast_block_end; } - TARGET_WITH_IMPL(SETUP_LOOP, _setup_finally) - TARGET_WITH_IMPL(SETUP_EXCEPT, _setup_finally) - TARGET(SETUP_FINALLY) - _setup_finally: { + TARGET(SETUP_LOOP) + TARGET(SETUP_EXCEPT) + TARGET(SETUP_FINALLY) { /* NOTE: If you add any new block-setup opcodes that are not try/except/finally handlers, you may need to update the PyGen_NeedsFinalizing() function. @@ -3078,6 +3117,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) if (res == NULL) goto error; PUSH(res); + PREDICT(GET_AWAITABLE); DISPATCH(); } @@ -3226,6 +3266,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) DISPATCH(); } + PREDICTED(CALL_FUNCTION); TARGET(CALL_FUNCTION) { PyObject **sp, *res; PCALL(PCALL_ALL); @@ -3242,10 +3283,9 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) DISPATCH(); } - TARGET_WITH_IMPL(CALL_FUNCTION_VAR, _call_function_var_kw) - TARGET_WITH_IMPL(CALL_FUNCTION_KW, _call_function_var_kw) - TARGET(CALL_FUNCTION_VAR_KW) - _call_function_var_kw: { + TARGET(CALL_FUNCTION_VAR) + TARGET(CALL_FUNCTION_KW) + TARGET(CALL_FUNCTION_VAR_KW) { int na = oparg & 0xff; int nk = (oparg>>8) & 0xff; int flags = (opcode - CALL_FUNCTION) & 3; @@ -3287,117 +3327,36 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) DISPATCH(); } - TARGET_WITH_IMPL(MAKE_CLOSURE, _make_function) - TARGET(MAKE_FUNCTION) - _make_function: { - int posdefaults = oparg & 0xff; - int kwdefaults = (oparg>>8) & 0xff; - int num_annotations = (oparg >> 16) & 0x7fff; + TARGET(MAKE_FUNCTION) { + PyObject *qualname = POP(); + PyObject *codeobj = POP(); + PyFunctionObject *func = (PyFunctionObject *) + PyFunction_NewWithQualName(codeobj, f->f_globals, qualname); - PyObject *qualname = POP(); /* qualname */ - PyObject *code = POP(); /* code object */ - PyObject *func = PyFunction_NewWithQualName(code, f->f_globals, qualname); - Py_DECREF(code); + Py_DECREF(codeobj); Py_DECREF(qualname); - - if (func == NULL) + if (func == NULL) { goto error; - - if (opcode == MAKE_CLOSURE) { - PyObject *closure = POP(); - if (PyFunction_SetClosure(func, closure) != 0) { - /* Can't happen unless bytecode is corrupt. */ - Py_DECREF(func); - Py_DECREF(closure); - goto error; - } - Py_DECREF(closure); } - if (num_annotations > 0) { - Py_ssize_t name_ix; - PyObject *names = POP(); /* names of args with annotations */ - PyObject *anns = PyDict_New(); - if (anns == NULL) { - Py_DECREF(func); - Py_DECREF(names); - goto error; - } - name_ix = PyTuple_Size(names); - assert(num_annotations == name_ix+1); - while (name_ix > 0) { - PyObject *name, *value; - int err; - --name_ix; - name = PyTuple_GET_ITEM(names, name_ix); - value = POP(); - err = PyDict_SetItem(anns, name, value); - Py_DECREF(value); - if (err != 0) { - Py_DECREF(anns); - Py_DECREF(func); - Py_DECREF(names); - goto error; - } - } - Py_DECREF(names); - - if (PyFunction_SetAnnotations(func, anns) != 0) { - /* Can't happen unless - PyFunction_SetAnnotations changes. */ - Py_DECREF(anns); - Py_DECREF(func); - goto error; - } - Py_DECREF(anns); + if (oparg & 0x08) { + assert(PyTuple_CheckExact(TOP())); + func ->func_closure = POP(); } - - /* XXX Maybe this should be a separate opcode? */ - if (kwdefaults > 0) { - PyObject *defs = PyDict_New(); - if (defs == NULL) { - Py_DECREF(func); - goto error; - } - while (--kwdefaults >= 0) { - PyObject *v = POP(); /* default value */ - PyObject *key = POP(); /* kw only arg name */ - int err = PyDict_SetItem(defs, key, v); - Py_DECREF(v); - Py_DECREF(key); - if (err != 0) { - Py_DECREF(defs); - Py_DECREF(func); - goto error; - } - } - if (PyFunction_SetKwDefaults(func, defs) != 0) { - /* Can't happen unless - PyFunction_SetKwDefaults changes. */ - Py_DECREF(func); - Py_DECREF(defs); - goto error; - } - Py_DECREF(defs); + if (oparg & 0x04) { + assert(PyDict_CheckExact(TOP())); + func->func_annotations = POP(); } - if (posdefaults > 0) { - PyObject *defs = PyTuple_New(posdefaults); - if (defs == NULL) { - Py_DECREF(func); - goto error; - } - while (--posdefaults >= 0) - PyTuple_SET_ITEM(defs, posdefaults, POP()); - if (PyFunction_SetDefaults(func, defs) != 0) { - /* Can't happen unless - PyFunction_SetDefaults changes. */ - Py_DECREF(defs); - Py_DECREF(func); - goto error; - } - Py_DECREF(defs); + if (oparg & 0x02) { + assert(PyDict_CheckExact(TOP())); + func->func_kwdefaults = POP(); + } + if (oparg & 0x01) { + assert(PyTuple_CheckExact(TOP())); + func->func_defaults = POP(); } - PUSH(func); + + PUSH((PyObject *)func); DISPATCH(); } @@ -3419,9 +3378,68 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) DISPATCH(); } + TARGET(FORMAT_VALUE) { + /* Handles f-string value formatting. */ + PyObject *result; + PyObject *fmt_spec; + PyObject *value; + PyObject *(*conv_fn)(PyObject *); + int which_conversion = oparg & FVC_MASK; + int have_fmt_spec = (oparg & FVS_MASK) == FVS_HAVE_SPEC; + + fmt_spec = have_fmt_spec ? POP() : NULL; + value = POP(); + + /* See if any conversion is specified. */ + switch (which_conversion) { + case FVC_STR: conv_fn = PyObject_Str; break; + case FVC_REPR: conv_fn = PyObject_Repr; break; + case FVC_ASCII: conv_fn = PyObject_ASCII; break; + + /* Must be 0 (meaning no conversion), since only four + values are allowed by (oparg & FVC_MASK). */ + default: conv_fn = NULL; break; + } + + /* If there's a conversion function, call it and replace + value with that result. Otherwise, just use value, + without conversion. */ + if (conv_fn != NULL) { + result = conv_fn(value); + Py_DECREF(value); + if (result == NULL) { + Py_XDECREF(fmt_spec); + goto error; + } + value = result; + } + + /* If value is a unicode object, and there's no fmt_spec, + then we know the result of format(value) is value + itself. In that case, skip calling format(). I plan to + move this optimization in to PyObject_Format() + itself. */ + if (PyUnicode_CheckExact(value) && fmt_spec == NULL) { + /* Do nothing, just transfer ownership to result. */ + result = value; + } else { + /* Actually call format(). */ + result = PyObject_Format(value, fmt_spec); + Py_DECREF(value); + Py_XDECREF(fmt_spec); + if (result == NULL) { + goto error; + } + } + + PUSH(result); + DISPATCH(); + } + TARGET(EXTENDED_ARG) { - opcode = NEXTOP(); - oparg = oparg<<16 | NEXTARG(); + int oldoparg = oparg; + NEXTOPARG(); + oparg |= oldoparg << 8; goto dispatch_opcode; } @@ -4297,7 +4315,7 @@ Error: #ifdef LLTRACE static int -prtrace(PyObject *v, char *str) +prtrace(PyObject *v, const char *str) { printf("%s ", str); if (PyObject_Print(v, stdout, 0) != 0) @@ -4863,6 +4881,21 @@ update_star_args(int nstack, int nstar, PyObject *stararg, { PyObject *callargs, *w; + if (!nstack) { + if (!stararg) { + /* There are no positional arguments on the stack and there is no + sequence to be unpacked. */ + return PyTuple_New(0); + } + if (PyTuple_CheckExact(stararg)) { + /* No arguments are passed on the stack and the sequence is not a + tuple subclass so we can just pass the stararg tuple directly + to the function. */ + Py_INCREF(stararg); + return stararg; + } + } + callargs = PyTuple_New(nstack + nstar); if (callargs == NULL) { return NULL; @@ -4951,7 +4984,7 @@ ext_do_call(PyObject *func, PyObject ***pp_stack, int flags, int na, int nk) if (flags & CALL_FLAG_KW) { kwdict = EXT_POP(*pp_stack); - if (!PyDict_Check(kwdict)) { + if (!PyDict_CheckExact(kwdict)) { PyObject *d; d = PyDict_New(); if (d == NULL) @@ -5261,7 +5294,7 @@ format_exc_unbound(PyCodeObject *co, int oparg) static PyObject * unicode_concatenate(PyObject *v, PyObject *w, - PyFrameObject *f, unsigned char *next_instr) + PyFrameObject *f, const unsigned short *next_instr) { PyObject *res; if (Py_REFCNT(v) == 2) { @@ -5271,10 +5304,11 @@ unicode_concatenate(PyObject *v, PyObject *w, * 'variable'. We try to delete the variable now to reduce * the refcnt to 1. */ - switch (*next_instr) { + int opcode, oparg; + NEXTOPARG(); + switch (opcode) { case STORE_FAST: { - int oparg = PEEKARG(); PyObject **fastlocals = f->f_localsplus; if (GETLOCAL(oparg) == v) SETLOCAL(oparg, NULL); @@ -5284,7 +5318,7 @@ unicode_concatenate(PyObject *v, PyObject *w, { PyObject **freevars = (f->f_localsplus + f->f_code->co_nlocals); - PyObject *c = freevars[PEEKARG()]; + PyObject *c = freevars[oparg]; if (PyCell_GET(c) == v) PyCell_Set(c, NULL); break; @@ -5292,7 +5326,7 @@ unicode_concatenate(PyObject *v, PyObject *w, case STORE_NAME: { PyObject *names = f->f_code->co_names; - PyObject *name = GETITEM(names, PEEKARG()); + PyObject *name = GETITEM(names, oparg); PyObject *locals = f->f_locals; if (PyDict_CheckExact(locals) && PyDict_GetItem(locals, name) == v) { |
