Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion Include/internal/pycore_code.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ typedef struct {
uint8_t original_oparg;
uint8_t counter;
uint16_t index;
uint16_t left_version;
uint16_t right_version;
} _PyAdaptiveEntry;


Expand All @@ -35,6 +37,10 @@ typedef struct {
PyObject *obj;
} _PyObjectCache;

typedef struct {
binaryfunc function;
} _PyFuncPtrCache;

/* Add specialized versions of entries to this union.
*
* Do not break the invariant: sizeof(SpecializedCacheEntry) == 8
Expand All @@ -51,6 +57,7 @@ typedef union {
_PyAttrCache attr;
_PyLoadGlobalCache load_global;
_PyObjectCache obj;
_PyFuncPtrCache func_ptr;
} SpecializedCacheEntry;

#define INSTRUCTIONS_PER_ENTRY (sizeof(SpecializedCacheEntry)/sizeof(_Py_CODEUNIT))
Expand Down Expand Up @@ -307,7 +314,7 @@ int _Py_Specialize_StoreAttr(PyObject *owner, _Py_CODEUNIT *instr, PyObject *nam
int _Py_Specialize_LoadGlobal(PyObject *globals, PyObject *builtins, _Py_CODEUNIT *instr, PyObject *name, SpecializedCacheEntry *cache);
int _Py_Specialize_LoadMethod(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name, SpecializedCacheEntry *cache);
int _Py_Specialize_BinarySubscr(PyObject *sub, PyObject *container, _Py_CODEUNIT *instr);
int _Py_Specialize_BinaryAdd(PyObject *left, PyObject *right, _Py_CODEUNIT *instr);
int _Py_Specialize_BinaryAdd(PyObject *left, PyObject *right, _Py_CODEUNIT *instr, SpecializedCacheEntry *cache);
int _Py_Specialize_BinaryMultiply(PyObject *left, PyObject *right, _Py_CODEUNIT *instr);

#define PRINT_SPECIALIZATION_STATS 0
Expand Down
69 changes: 35 additions & 34 deletions Include/opcode.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Lib/opcode.py
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ def jabs_op(name, op):

_specialized_instructions = [
"BINARY_ADD_ADAPTIVE",
"BINARY_ADD_CACHED",
"BINARY_ADD_INT",
"BINARY_ADD_FLOAT",
"BINARY_ADD_UNICODE",
Expand Down
49 changes: 41 additions & 8 deletions Python/ceval.c
Original file line number Diff line number Diff line change
Expand Up @@ -2080,18 +2080,19 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr
}

TARGET(BINARY_ADD_ADAPTIVE) {
if (oparg == 0) {
SpecializedCacheEntry *cache = GET_CACHE();
if (cache->adaptive.counter == 0) {
PyObject *left = SECOND();
PyObject *right = TOP();
next_instr--;
if (_Py_Specialize_BinaryAdd(left, right, next_instr) < 0) {
if (_Py_Specialize_BinaryAdd(left, right, next_instr, cache) < 0) {
goto error;
}
DISPATCH();
}
else {
STAT_INC(BINARY_ADD, deferred);
UPDATE_PREV_INSTR_OPARG(next_instr, oparg - 1);
cache->adaptive.counter--;
STAT_DEC(BINARY_ADD, unquickened);
JUMP_TO_INSTRUCTION(BINARY_ADD);
}
Expand All @@ -2103,7 +2104,9 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr
DEOPT_IF(!PyUnicode_CheckExact(left), BINARY_ADD);
DEOPT_IF(Py_TYPE(right) != Py_TYPE(left), BINARY_ADD);
STAT_INC(BINARY_ADD, hit);
record_hit_inline(next_instr, oparg);
SpecializedCacheEntry *caches = GET_CACHE();
_PyAdaptiveEntry *cache0 = &caches[0].adaptive;
record_cache_hit(cache0);
PyObject *res = PyUnicode_Concat(left, right);
STACK_SHRINK(1);
SET_TOP(res);
Expand Down Expand Up @@ -2132,7 +2135,9 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr
PyObject *var = GETLOCAL(next_oparg);
DEOPT_IF(var != left, BINARY_ADD);
STAT_INC(BINARY_ADD, hit);
record_hit_inline(next_instr, oparg);
SpecializedCacheEntry *caches = GET_CACHE();
_PyAdaptiveEntry *cache0 = &caches[0].adaptive;
record_cache_hit(cache0);
GETLOCAL(next_oparg) = NULL;
Py_DECREF(left);
STACK_SHRINK(1);
Expand All @@ -2150,7 +2155,9 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr
DEOPT_IF(!PyFloat_CheckExact(left), BINARY_ADD);
DEOPT_IF(Py_TYPE(right) != Py_TYPE(left), BINARY_ADD);
STAT_INC(BINARY_ADD, hit);
record_hit_inline(next_instr, oparg);
SpecializedCacheEntry *caches = GET_CACHE();
_PyAdaptiveEntry *cache0 = &caches[0].adaptive;
record_cache_hit(cache0);
double dsum = ((PyFloatObject *)left)->ob_fval +
((PyFloatObject *)right)->ob_fval;
PyObject *sum = PyFloat_FromDouble(dsum);
Expand All @@ -2170,7 +2177,9 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr
DEOPT_IF(!PyLong_CheckExact(left), BINARY_ADD);
DEOPT_IF(Py_TYPE(right) != Py_TYPE(left), BINARY_ADD);
STAT_INC(BINARY_ADD, hit);
record_hit_inline(next_instr, oparg);
SpecializedCacheEntry *caches = GET_CACHE();
_PyAdaptiveEntry *cache0 = &caches[0].adaptive;
record_cache_hit(cache0);
PyObject *sum = _PyLong_Add((PyLongObject *)left, (PyLongObject *)right);
SET_SECOND(sum);
Py_DECREF(right);
Expand All @@ -2182,6 +2191,30 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr
DISPATCH();
}

TARGET(BINARY_ADD_CACHED) {
SpecializedCacheEntry *caches = GET_CACHE();
_PyAdaptiveEntry *cache0 = &caches[0].adaptive;
PyObject *left = SECOND();
PyObject *right = TOP();
DEOPT_IF(Py_TYPE(left)->tp_version_tag != cache0->left_version, BINARY_ADD);
DEOPT_IF(Py_TYPE(right)->tp_version_tag != cache0->right_version, BINARY_ADD);
record_cache_hit(cache0);
binaryfunc function = caches[-1].func_ptr.function;
PyObject *sum = function(left, right);
if (sum == Py_NotImplemented) {
Py_DECREF(sum);
sum = NULL;
Comment on lines +2184 to +2185

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You may want to consider replacing this with

Suggested change
Py_DECREF(sum);
sum = NULL;
Py_SETREF(sum, NULL);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or:

Suggested change
Py_DECREF(sum);
sum = NULL;
Py_CLEAR(sum);

}
SET_SECOND(sum);
Py_DECREF(right);
Py_DECREF(left);
STACK_SHRINK(1);
if (sum == NULL) {
goto error;
}
DISPATCH();
}

TARGET(BINARY_SUBTRACT) {
PyObject *right = POP();
PyObject *left = TOP();
Expand Down Expand Up @@ -4983,7 +5016,7 @@ MISS_WITH_CACHE(STORE_ATTR)
MISS_WITH_CACHE(LOAD_GLOBAL)
MISS_WITH_CACHE(LOAD_METHOD)
MISS_WITH_OPARG_COUNTER(BINARY_SUBSCR)
MISS_WITH_OPARG_COUNTER(BINARY_ADD)
MISS_WITH_CACHE(BINARY_ADD)
MISS_WITH_OPARG_COUNTER(BINARY_MULTIPLY)

binary_subscr_dict_error:
Expand Down
34 changes: 17 additions & 17 deletions Python/opcode_targets.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading