diff options
Diffstat (limited to 'Python')
-rw-r--r-- | Python/ceval.c | 39 | ||||
-rw-r--r-- | Python/compile.c | 8 | ||||
-rw-r--r-- | Python/marshal.c | 8 | ||||
-rw-r--r-- | Python/opcode_targets.h | 70 | ||||
-rw-r--r-- | Python/specialize.c | 100 |
5 files changed, 75 insertions, 150 deletions
diff --git a/Python/ceval.c b/Python/ceval.c index 6f449e3..7c6bfd4 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1327,9 +1327,8 @@ eval_frame_handle_pending(PyThreadState *tstate) /* Get opcode and oparg from original instructions, not quickened form. */ #define TRACING_NEXTOPARG() do { \ - _Py_CODEUNIT word = ((_Py_CODEUNIT *)PyBytes_AS_STRING(frame->f_code->co_code))[INSTR_OFFSET()]; \ - opcode = _Py_OPCODE(word); \ - oparg = _Py_OPARG(word); \ + NEXTOPARG(); \ + opcode = _PyOpcode_Deopt[opcode]; \ } while (0) /* OpCode prediction macros @@ -1650,9 +1649,10 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int PyCodeObject *co = frame->f_code; \ names = co->co_names; \ consts = co->co_consts; \ - first_instr = co->co_firstinstr; \ + first_instr = _PyCode_CODE(co); \ } \ assert(frame->f_lasti >= -1); \ + /* Jump back to the last instruction executed... */ \ next_instr = first_instr + frame->f_lasti + 1; \ stack_pointer = _PyFrame_GetStackPointer(frame); \ /* Set stackdepth to -1. \ @@ -1722,16 +1722,7 @@ handle_eval_breaker: } TARGET(RESUME) { - int err = _Py_IncrementCountAndMaybeQuicken(frame->f_code); - if (err) { - if (err < 0) { - goto error; - } - /* Update first_instr and next_instr to point to newly quickened code */ - int nexti = INSTR_OFFSET(); - first_instr = frame->f_code->co_firstinstr; - next_instr = first_instr + nexti; - } + _PyCode_Warmup(frame->f_code); JUMP_TO_INSTRUCTION(RESUME_QUICK); } @@ -4067,16 +4058,7 @@ handle_eval_breaker: TARGET(JUMP_ABSOLUTE) { PREDICTED(JUMP_ABSOLUTE); - int err = _Py_IncrementCountAndMaybeQuicken(frame->f_code); - if (err) { - if (err < 0) { - goto error; - } - /* Update first_instr and next_instr to point to newly quickened code */ - int nexti = INSTR_OFFSET(); - first_instr = frame->f_code->co_firstinstr; - next_instr = first_instr + nexti; - } + _PyCode_Warmup(frame->f_code); JUMP_TO_INSTRUCTION(JUMP_ABSOLUTE_QUICK); } @@ -5425,6 +5407,7 @@ handle_eval_breaker: } TARGET(EXTENDED_ARG) { + assert(oparg); int oldoparg = oparg; NEXTOPARG(); oparg |= oldoparg << 8; @@ -6739,8 +6722,8 @@ maybe_call_line_trace(Py_tracefunc func, PyObject *obj, */ initialize_trace_info(&tstate->trace_info, frame); int entry_point = 0; - _Py_CODEUNIT *code = (_Py_CODEUNIT *)PyBytes_AS_STRING(frame->f_code->co_code); - while (_Py_OPCODE(code[entry_point]) != RESUME) { + _Py_CODEUNIT *code = _PyCode_CODE(frame->f_code); + while (_PyOpcode_Deopt[_Py_OPCODE(code[entry_point])] != RESUME) { entry_point++; } int lastline; @@ -6759,7 +6742,9 @@ maybe_call_line_trace(Py_tracefunc func, PyObject *obj, /* Trace backward edges (except in 'yield from') or if line number has changed */ int trace = line != lastline || (frame->f_lasti < instr_prev && - _Py_OPCODE(frame->f_code->co_firstinstr[frame->f_lasti]) != SEND); + // SEND has no quickened forms, so no need to use _PyOpcode_Deopt + // here: + _Py_OPCODE(_PyCode_CODE(frame->f_code)[frame->f_lasti]) != SEND); if (trace) { result = call_trace(func, obj, tstate, frame, PyTrace_LINE, Py_None); } diff --git a/Python/compile.c b/Python/compile.c index 950c44a..e24f425 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -134,9 +134,9 @@ static int instr_size(struct instr *instruction) { int opcode = instruction->i_opcode; - int oparg = instruction->i_oparg; + int oparg = HAS_ARG(opcode) ? instruction->i_oparg : 0; int extended_args = (0xFFFFFF < oparg) + (0xFFFF < oparg) + (0xFF < oparg); - int caches = _PyOpcode_InlineCacheEntries[opcode]; + int caches = _PyOpcode_Caches[opcode]; return extended_args + 1 + caches; } @@ -144,8 +144,8 @@ static void write_instr(_Py_CODEUNIT *codestr, struct instr *instruction, int ilen) { int opcode = instruction->i_opcode; - int oparg = instruction->i_oparg; - int caches = _PyOpcode_InlineCacheEntries[opcode]; + int oparg = HAS_ARG(opcode) ? instruction->i_oparg : 0; + int caches = _PyOpcode_Caches[opcode]; switch (ilen - caches) { case 4: *codestr++ = _Py_MAKECODEUNIT(EXTENDED_ARG, (oparg >> 24) & 0xFF); diff --git a/Python/marshal.c b/Python/marshal.c index 810244b..e7cf655 100644 --- a/Python/marshal.c +++ b/Python/marshal.c @@ -544,13 +544,18 @@ w_complex_object(PyObject *v, char flag, WFILE *p) } else if (PyCode_Check(v)) { PyCodeObject *co = (PyCodeObject *)v; + PyObject *co_code = _PyCode_GetCode(co); + if (co_code == NULL) { + p->error = WFERR_NOMEMORY; + return; + } W_TYPE(TYPE_CODE, p); w_long(co->co_argcount, p); w_long(co->co_posonlyargcount, p); w_long(co->co_kwonlyargcount, p); w_long(co->co_stacksize, p); w_long(co->co_flags, p); - w_object(co->co_code, p); + w_object(co_code, p); w_object(co->co_consts, p); w_object(co->co_names, p); w_object(co->co_localsplusnames, p); @@ -563,6 +568,7 @@ w_complex_object(PyObject *v, char flag, WFILE *p) w_object(co->co_endlinetable, p); w_object(co->co_columntable, p); w_object(co->co_exceptiontable, p); + Py_DECREF(co_code); } else if (PyObject_CheckBuffer(v)) { /* Write unknown bytes-like objects as a bytes object */ diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h index 7c94999..2aa6471 100644 --- a/Python/opcode_targets.h +++ b/Python/opcode_targets.h @@ -3,49 +3,49 @@ static void *opcode_targets[256] = { &&TARGET_POP_TOP, &&TARGET_PUSH_NULL, &&TARGET_BINARY_OP_ADAPTIVE, - &&TARGET_BINARY_OP_ADD_INT, &&TARGET_BINARY_OP_ADD_FLOAT, + &&TARGET_BINARY_OP_ADD_INT, &&TARGET_BINARY_OP_ADD_UNICODE, &&TARGET_BINARY_OP_INPLACE_ADD_UNICODE, - &&TARGET_BINARY_OP_MULTIPLY_INT, + &&TARGET_BINARY_OP_MULTIPLY_FLOAT, &&TARGET_NOP, &&TARGET_UNARY_POSITIVE, &&TARGET_UNARY_NEGATIVE, &&TARGET_UNARY_NOT, - &&TARGET_BINARY_OP_MULTIPLY_FLOAT, - &&TARGET_BINARY_OP_SUBTRACT_INT, - &&TARGET_UNARY_INVERT, + &&TARGET_BINARY_OP_MULTIPLY_INT, &&TARGET_BINARY_OP_SUBTRACT_FLOAT, - &&TARGET_COMPARE_OP_ADAPTIVE, - &&TARGET_COMPARE_OP_FLOAT_JUMP, - &&TARGET_COMPARE_OP_INT_JUMP, - &&TARGET_COMPARE_OP_STR_JUMP, + &&TARGET_UNARY_INVERT, + &&TARGET_BINARY_OP_SUBTRACT_INT, &&TARGET_BINARY_SUBSCR_ADAPTIVE, + &&TARGET_BINARY_SUBSCR_DICT, &&TARGET_BINARY_SUBSCR_GETITEM, &&TARGET_BINARY_SUBSCR_LIST_INT, &&TARGET_BINARY_SUBSCR_TUPLE_INT, + &&TARGET_CALL_ADAPTIVE, + &&TARGET_CALL_PY_EXACT_ARGS, + &&TARGET_CALL_PY_WITH_DEFAULTS, &&TARGET_BINARY_SUBSCR, - &&TARGET_BINARY_SUBSCR_DICT, - &&TARGET_STORE_SUBSCR_ADAPTIVE, - &&TARGET_STORE_SUBSCR_LIST_INT, - &&TARGET_STORE_SUBSCR_DICT, + &&TARGET_COMPARE_OP_ADAPTIVE, + &&TARGET_COMPARE_OP_FLOAT_JUMP, + &&TARGET_COMPARE_OP_INT_JUMP, + &&TARGET_COMPARE_OP_STR_JUMP, &&TARGET_GET_LEN, &&TARGET_MATCH_MAPPING, &&TARGET_MATCH_SEQUENCE, &&TARGET_MATCH_KEYS, - &&TARGET_CALL_ADAPTIVE, - &&TARGET_PUSH_EXC_INFO, - &&TARGET_CALL_PY_EXACT_ARGS, - &&TARGET_CALL_PY_WITH_DEFAULTS, &&TARGET_JUMP_ABSOLUTE_QUICK, + &&TARGET_PUSH_EXC_INFO, &&TARGET_LOAD_ATTR_ADAPTIVE, &&TARGET_LOAD_ATTR_INSTANCE_VALUE, - &&TARGET_LOAD_ATTR_WITH_HINT, - &&TARGET_LOAD_ATTR_SLOT, &&TARGET_LOAD_ATTR_MODULE, + &&TARGET_LOAD_ATTR_SLOT, + &&TARGET_LOAD_ATTR_WITH_HINT, + &&TARGET_LOAD_CONST__LOAD_FAST, + &&TARGET_LOAD_FAST__LOAD_CONST, + &&TARGET_LOAD_FAST__LOAD_FAST, &&TARGET_LOAD_GLOBAL_ADAPTIVE, - &&TARGET_LOAD_GLOBAL_MODULE, &&TARGET_LOAD_GLOBAL_BUILTIN, + &&TARGET_LOAD_GLOBAL_MODULE, &&TARGET_LOAD_METHOD_ADAPTIVE, &&TARGET_LOAD_METHOD_CLASS, &&TARGET_WITH_EXCEPT_START, @@ -61,26 +61,26 @@ static void *opcode_targets[256] = { &&TARGET_PRECALL_ADAPTIVE, &&TARGET_STORE_SUBSCR, &&TARGET_DELETE_SUBSCR, + &&TARGET_PRECALL_BOUND_METHOD, &&TARGET_PRECALL_BUILTIN_CLASS, - &&TARGET_PRECALL_NO_KW_BUILTIN_O, - &&TARGET_PRECALL_NO_KW_BUILTIN_FAST, &&TARGET_PRECALL_BUILTIN_FAST_WITH_KEYWORDS, - &&TARGET_PRECALL_NO_KW_LEN, + &&TARGET_PRECALL_NO_KW_BUILTIN_FAST, + &&TARGET_PRECALL_NO_KW_BUILTIN_O, &&TARGET_PRECALL_NO_KW_ISINSTANCE, &&TARGET_GET_ITER, &&TARGET_GET_YIELD_FROM_ITER, &&TARGET_PRINT_EXPR, &&TARGET_LOAD_BUILD_CLASS, + &&TARGET_PRECALL_NO_KW_LEN, &&TARGET_PRECALL_NO_KW_LIST_APPEND, - &&TARGET_PRECALL_NO_KW_METHOD_DESCRIPTOR_O, &&TARGET_LOAD_ASSERTION_ERROR, &&TARGET_RETURN_GENERATOR, + &&TARGET_PRECALL_NO_KW_METHOD_DESCRIPTOR_FAST, &&TARGET_PRECALL_NO_KW_METHOD_DESCRIPTOR_NOARGS, + &&TARGET_PRECALL_NO_KW_METHOD_DESCRIPTOR_O, &&TARGET_PRECALL_NO_KW_STR_1, &&TARGET_PRECALL_NO_KW_TUPLE_1, &&TARGET_PRECALL_NO_KW_TYPE_1, - &&TARGET_PRECALL_NO_KW_METHOD_DESCRIPTOR_FAST, - &&TARGET_PRECALL_BOUND_METHOD, &&TARGET_LIST_TO_TUPLE, &&TARGET_RETURN_VALUE, &&TARGET_IMPORT_STAR, @@ -157,23 +157,23 @@ static void *opcode_targets[256] = { &&TARGET_FORMAT_VALUE, &&TARGET_BUILD_CONST_KEY_MAP, &&TARGET_BUILD_STRING, - &&TARGET_UNPACK_SEQUENCE_ADAPTIVE, - &&TARGET_UNPACK_SEQUENCE_LIST, + &&TARGET_STORE_FAST__LOAD_FAST, + &&TARGET_STORE_FAST__STORE_FAST, &&TARGET_LOAD_METHOD, - &&TARGET_UNPACK_SEQUENCE_TUPLE, + &&TARGET_STORE_SUBSCR_ADAPTIVE, &&TARGET_LIST_EXTEND, &&TARGET_SET_UPDATE, &&TARGET_DICT_MERGE, &&TARGET_DICT_UPDATE, &&TARGET_PRECALL, - &&TARGET_UNPACK_SEQUENCE_TWO_TUPLE, - &&TARGET_LOAD_FAST__LOAD_FAST, - &&TARGET_STORE_FAST__LOAD_FAST, - &&TARGET_LOAD_FAST__LOAD_CONST, + &&TARGET_STORE_SUBSCR_DICT, + &&TARGET_STORE_SUBSCR_LIST_INT, + &&TARGET_UNPACK_SEQUENCE_ADAPTIVE, + &&TARGET_UNPACK_SEQUENCE_LIST, &&TARGET_CALL, &&TARGET_KW_NAMES, - &&TARGET_LOAD_CONST__LOAD_FAST, - &&TARGET_STORE_FAST__STORE_FAST, + &&TARGET_UNPACK_SEQUENCE_TUPLE, + &&TARGET_UNPACK_SEQUENCE_TWO_TUPLE, &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, diff --git a/Python/specialize.c b/Python/specialize.c index d84adac..ce091a2 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -15,31 +15,6 @@ * ./adaptive.md */ - -/* We layout the quickened data as a bi-directional array: - * Instructions upwards, cache entries downwards. - * first_instr is aligned to a SpecializedCacheEntry. - * The nth instruction is located at first_instr[n] - * The nth cache is located at ((SpecializedCacheEntry *)first_instr)[-1-n] - * The first (index 0) cache entry is reserved for the count, to enable finding - * the first instruction from the base pointer. - * The cache_count argument must include space for the count. - * We use the SpecializedCacheOrInstruction union to refer to the data - * to avoid type punning. - - Layout of quickened data, each line 8 bytes for M cache entries and N instructions: - - <cache_count> <---- co->co_quickened - <cache M-1> - <cache M-2> - ... - <cache 0> - <instr 0> <instr 1> <instr 2> <instr 3> <--- co->co_first_instr - <instr 4> <instr 5> <instr 6> <instr 7> - ... - <instr N-1> -*/ - /* Map from opcode to adaptive opcode. Values of zero are ignored. */ static uint8_t adaptive_opcodes[256] = { @@ -275,26 +250,14 @@ _Py_PrintSpecializationStats(int to_file) #define SPECIALIZATION_FAIL(opcode, kind) ((void)0) #endif -static _Py_CODEUNIT * -allocate(int instruction_count) +// Insert adaptive instructions and superinstructions. This cannot fail. +void +_PyCode_Quicken(PyCodeObject *code) { - assert(instruction_count > 0); - void *array = PyMem_Malloc(sizeof(_Py_CODEUNIT) * instruction_count); - if (array == NULL) { - PyErr_NoMemory(); - return NULL; - } _Py_QuickenedCount++; - return (_Py_CODEUNIT *)array; -} - - -// Insert adaptive instructions and superinstructions. -static void -optimize(_Py_CODEUNIT *instructions, int len) -{ int previous_opcode = -1; - for(int i = 0; i < len; i++) { + _Py_CODEUNIT *instructions = _PyCode_CODE(code); + for (int i = 0; i < Py_SIZE(code); i++) { int opcode = _Py_OPCODE(instructions[i]); uint8_t adaptive_opcode = adaptive_opcodes[opcode]; if (adaptive_opcode) { @@ -302,10 +265,10 @@ optimize(_Py_CODEUNIT *instructions, int len) // Make sure the adaptive counter is zero: assert(instructions[i + 1] == 0); previous_opcode = -1; - i += _PyOpcode_InlineCacheEntries[opcode]; + i += _PyOpcode_Caches[opcode]; } else { - assert(!_PyOpcode_InlineCacheEntries[opcode]); + assert(!_PyOpcode_Caches[opcode]); switch (opcode) { case JUMP_ABSOLUTE: _Py_SET_OPCODE(instructions[i], JUMP_ABSOLUTE_QUICK); @@ -347,28 +310,6 @@ optimize(_Py_CODEUNIT *instructions, int len) } } -int -_Py_Quicken(PyCodeObject *code) { - if (code->co_quickened) { - return 0; - } - Py_ssize_t size = PyBytes_GET_SIZE(code->co_code); - int instr_count = (int)(size/sizeof(_Py_CODEUNIT)); - if (instr_count > MAX_SIZE_TO_QUICKEN) { - code->co_warmup = QUICKENING_WARMUP_COLDEST; - return 0; - } - _Py_CODEUNIT *quickened = allocate(instr_count); - if (quickened == NULL) { - return -1; - } - memcpy(quickened, code->co_firstinstr, size); - optimize(quickened, instr_count); - code->co_quickened = quickened; - code->co_firstinstr = quickened; - return 0; -} - static inline int initial_counter_value(void) { /* Starting value for the counter. @@ -705,8 +646,7 @@ specialize_dict_access( int _Py_Specialize_LoadAttr(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name) { - assert(_PyOpcode_InlineCacheEntries[LOAD_ATTR] == - INLINE_CACHE_ENTRIES_LOAD_ATTR); + assert(_PyOpcode_Caches[LOAD_ATTR] == INLINE_CACHE_ENTRIES_LOAD_ATTR); _PyAttrCache *cache = (_PyAttrCache *)(instr + 1); if (PyModule_CheckExact(owner)) { int err = specialize_module_load_attr(owner, instr, name, LOAD_ATTR, @@ -804,8 +744,7 @@ success: int _Py_Specialize_StoreAttr(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name) { - assert(_PyOpcode_InlineCacheEntries[STORE_ATTR] == - INLINE_CACHE_ENTRIES_STORE_ATTR); + assert(_PyOpcode_Caches[STORE_ATTR] == INLINE_CACHE_ENTRIES_STORE_ATTR); _PyAttrCache *cache = (_PyAttrCache *)(instr + 1); PyTypeObject *type = Py_TYPE(owner); if (PyModule_CheckExact(owner)) { @@ -965,8 +904,7 @@ typedef enum { int _Py_Specialize_LoadMethod(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name) { - assert(_PyOpcode_InlineCacheEntries[LOAD_METHOD] == - INLINE_CACHE_ENTRIES_LOAD_METHOD); + assert(_PyOpcode_Caches[LOAD_METHOD] == INLINE_CACHE_ENTRIES_LOAD_METHOD); _PyLoadMethodCache *cache = (_PyLoadMethodCache *)(instr + 1); PyTypeObject *owner_cls = Py_TYPE(owner); @@ -1098,8 +1036,7 @@ _Py_Specialize_LoadGlobal( PyObject *globals, PyObject *builtins, _Py_CODEUNIT *instr, PyObject *name) { - assert(_PyOpcode_InlineCacheEntries[LOAD_GLOBAL] == - INLINE_CACHE_ENTRIES_LOAD_GLOBAL); + assert(_PyOpcode_Caches[LOAD_GLOBAL] == INLINE_CACHE_ENTRIES_LOAD_GLOBAL); /* Use inline cache */ _PyLoadGlobalCache *cache = (_PyLoadGlobalCache *)(instr + 1); assert(PyUnicode_CheckExact(name)); @@ -1235,7 +1172,7 @@ int _Py_Specialize_BinarySubscr( PyObject *container, PyObject *sub, _Py_CODEUNIT *instr) { - assert(_PyOpcode_InlineCacheEntries[BINARY_SUBSCR] == + assert(_PyOpcode_Caches[BINARY_SUBSCR] == INLINE_CACHE_ENTRIES_BINARY_SUBSCR); _PyBinarySubscrCache *cache = (_PyBinarySubscrCache *)(instr + 1); PyTypeObject *container_type = Py_TYPE(container); @@ -1663,8 +1600,7 @@ int _Py_Specialize_Precall(PyObject *callable, _Py_CODEUNIT *instr, int nargs, PyObject *kwnames, int oparg) { - assert(_PyOpcode_InlineCacheEntries[PRECALL] == - INLINE_CACHE_ENTRIES_PRECALL); + assert(_PyOpcode_Caches[PRECALL] == INLINE_CACHE_ENTRIES_PRECALL); _PyPrecallCache *cache = (_PyPrecallCache *)(instr + 1); int fail; if (PyCFunction_CheckExact(callable)) { @@ -1710,7 +1646,7 @@ int _Py_Specialize_Call(PyObject *callable, _Py_CODEUNIT *instr, int nargs, PyObject *kwnames) { - assert(_PyOpcode_InlineCacheEntries[CALL] == INLINE_CACHE_ENTRIES_CALL); + assert(_PyOpcode_Caches[CALL] == INLINE_CACHE_ENTRIES_CALL); _PyCallCache *cache = (_PyCallCache *)(instr + 1); int fail; if (PyFunction_Check(callable)) { @@ -1808,8 +1744,7 @@ void _Py_Specialize_BinaryOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr, int oparg) { - assert(_PyOpcode_InlineCacheEntries[BINARY_OP] == - INLINE_CACHE_ENTRIES_BINARY_OP); + assert(_PyOpcode_Caches[BINARY_OP] == INLINE_CACHE_ENTRIES_BINARY_OP); _PyBinaryOpCache *cache = (_PyBinaryOpCache *)(instr + 1); switch (oparg) { case NB_ADD: @@ -1936,8 +1871,7 @@ void _Py_Specialize_CompareOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr, int oparg) { - assert(_PyOpcode_InlineCacheEntries[COMPARE_OP] == - INLINE_CACHE_ENTRIES_COMPARE_OP); + assert(_PyOpcode_Caches[COMPARE_OP] == INLINE_CACHE_ENTRIES_COMPARE_OP); _PyCompareOpCache *cache = (_PyCompareOpCache *)(instr + 1); int next_opcode = _Py_OPCODE(instr[INLINE_CACHE_ENTRIES_COMPARE_OP + 1]); if (next_opcode != POP_JUMP_IF_FALSE && next_opcode != POP_JUMP_IF_TRUE) { @@ -2019,7 +1953,7 @@ unpack_sequence_fail_kind(PyObject *seq) void _Py_Specialize_UnpackSequence(PyObject *seq, _Py_CODEUNIT *instr, int oparg) { - assert(_PyOpcode_InlineCacheEntries[UNPACK_SEQUENCE] == + assert(_PyOpcode_Caches[UNPACK_SEQUENCE] == INLINE_CACHE_ENTRIES_UNPACK_SEQUENCE); _PyUnpackSequenceCache *cache = (_PyUnpackSequenceCache *)(instr + 1); if (PyTuple_CheckExact(seq)) { |