Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
4 changes: 2 additions & 2 deletions Python/bytecodes.c
Original file line numberDiff line numberDiff line change
Expand Up@@ -1933,11 +1933,11 @@ dummy_func(
_LOAD_ATTR_INSTANCE_VALUE +
unused/5; // Skip over rest of cache

op(_CHECK_ATTR_MODULE, (type_version/2, owner -- owner)){
op(_CHECK_ATTR_MODULE, (dict_version/2, owner -- owner)){
DEOPT_IF(!PyModule_CheckExact(owner));
PyDictObject *dict = (PyDictObject *)((PyModuleObject *)owner)->md_dict;
assert(dict != NULL);
DEOPT_IF(dict->ma_keys->dk_version != type_version);
DEOPT_IF(dict->ma_keys->dk_version != dict_version);
}

op(_LOAD_ATTR_MODULE, (index/1, owner -- attr, null if (oparg & 1))){
Expand Down
4 changes: 2 additions & 2 deletions Python/executor_cases.c.h

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

4 changes: 2 additions & 2 deletions Python/generated_cases.c.h

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

68 changes: 44 additions & 24 deletions Python/optimizer_analysis.c
Original file line numberDiff line numberDiff line change
Expand Up@@ -276,6 +276,20 @@ sym_is_null(_Py_UOpsSymType *sym)
return (sym->flags & (IS_NULL | NOT_NULL)) == IS_NULL;
}

static inline bool
sym_is_const(_Py_UOpsSymType *sym)
{
return (sym->flags & TRUE_CONST) != 0;
}

static inline PyObject *
sym_get_const(_Py_UOpsSymType *sym)
{
assert(sym_is_const(sym));
assert(sym->const_val);
return sym->const_val;
}

static inline void
sym_set_type(_Py_UOpsSymType *sym, PyTypeObject *tp)
{
Expand DownExpand Up@@ -341,18 +355,6 @@ sym_new_const(_Py_UOpsAbstractInterpContext *ctx, PyObject *const_val)
return temp;
}

static inline bool
is_const(_Py_UOpsSymType *sym)
{
return sym->const_val != NULL;
}

static inline PyObject *
get_const(_Py_UOpsSymType *sym)
{
return sym->const_val;
}

static _Py_UOpsSymType*
sym_new_null(_Py_UOpsAbstractInterpContext *ctx)
{
Expand DownExpand Up@@ -413,18 +415,21 @@ globals_watcher_callback(PyDict_WatchEvent event, PyObject* dict,
return 0;
}

static void
global_to_const(_PyUOpInstruction *inst, PyObject *obj)
static PyObject *
convert_global_to_const(_PyUOpInstruction *inst, PyObject *obj)
{
assert(inst->opcode == _LOAD_GLOBAL_MODULE || inst->opcode == _LOAD_GLOBAL_BUILTINS);
assert(inst->opcode == _LOAD_GLOBAL_MODULE || inst->opcode == _LOAD_GLOBAL_BUILTINS || inst->opcode == _LOAD_ATTR_MODULE);
assert(PyDict_CheckExact(obj));
PyDictObject *dict = (PyDictObject *)obj;
assert(dict->ma_keys->dk_kind == DICT_KEYS_UNICODE);
PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(dict->ma_keys);
assert(inst->operand <= UINT16_MAX);
if ((int)inst->operand >= dict->ma_keys->dk_nentries){
return NULL;
}
PyObject *res = entries[inst->operand].me_value;
if (res == NULL){
return;
return NULL;
}
if (_Py_IsImmortal(res)){
inst->opcode = (inst->oparg & 1) ? _LOAD_CONST_INLINE_BORROW_WITH_NULL : _LOAD_CONST_INLINE_BORROW;
Expand All@@ -433,6 +438,7 @@ global_to_const(_PyUOpInstruction *inst, PyObject *obj)
inst->opcode = (inst->oparg & 1) ? _LOAD_CONST_INLINE_WITH_NULL : _LOAD_CONST_INLINE;
}
inst->operand = (uint64_t)res;
return res;
}

static int
Expand DownExpand Up@@ -529,12 +535,12 @@ remove_globals(_PyInterpreterFrame *frame, _PyUOpInstruction *buffer,
break;
case _LOAD_GLOBAL_BUILTINS:
if (globals_checked & builtins_checked & globals_watched & builtins_watched & 1){
global_to_const(inst, builtins);
convert_global_to_const(inst, builtins);
}
break;
case _LOAD_GLOBAL_MODULE:
if (globals_checked & globals_watched & 1){
global_to_const(inst, globals);
convert_global_to_const(inst, globals);
}
break;
case _PUSH_FRAME:
Expand DownExpand Up@@ -608,7 +614,8 @@ uop_redundancy_eliminator(
PyCodeObject *co,
_PyUOpInstruction *trace,
int trace_len,
int curr_stacklen
int curr_stacklen,
_PyBloomFilter *dependencies
)
{

Expand DownExpand Up@@ -670,7 +677,7 @@ remove_unneeded_uops(_PyUOpInstruction *buffer, int buffer_size)
* could error. _CHECK_VALIDITY is needed if the previous
* instruction could have escaped. */
int last_set_ip = -1;
bool may_have_escaped = false;
bool may_have_escaped = true;
for (int pc = 0; pc < buffer_size; pc++){
int opcode = buffer[pc].opcode;
switch (opcode){
Expand All@@ -696,6 +703,22 @@ remove_unneeded_uops(_PyUOpInstruction *buffer, int buffer_size)
}
last_set_ip = pc;
break;
case _POP_TOP:
{
_PyUOpInstruction *last = &buffer[pc-1];
while (last->opcode == _NOP){
last--;
}
if (last->opcode == _LOAD_CONST_INLINE ||
last->opcode == _LOAD_CONST_INLINE_BORROW ||
last->opcode == _LOAD_FAST ||
last->opcode == _COPY
){
last->opcode = _NOP;
buffer[pc].opcode = NOP;
}
break;
}
case _JUMP_TO_TOP:
case _EXIT_TRACE:
return;
Expand All@@ -709,9 +732,6 @@ remove_unneeded_uops(_PyUOpInstruction *buffer, int buffer_size)
if (_PyUop_Flags[opcode] & HAS_ERROR_FLAG){
needs_ip = true;
}
if (opcode == _PUSH_FRAME){
needs_ip = true;
}
if (needs_ip && last_set_ip >= 0){
if (buffer[last_set_ip].opcode == _CHECK_VALIDITY){
buffer[last_set_ip].opcode = _CHECK_VALIDITY_AND_SET_IP;
Expand DownExpand Up@@ -796,7 +816,7 @@ _Py_uop_analyze_and_optimize(

err = uop_redundancy_eliminator(
(PyCodeObject *)frame->f_executable, buffer,
buffer_size, curr_stacklen);
buffer_size, curr_stacklen, dependencies);

if (err == 0){
goto not_ready;
Expand Down
100 changes: 67 additions & 33 deletions Python/tier2_redundancy_eliminator_bytecodes.c
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
#include "Python.h"
#include "pycore_uops.h"
#include "pycore_uop_ids.h"
#include "internal/pycore_moduleobject.h"

#define op(name, ...) /* NAME is ignored */

Expand DownExpand Up@@ -79,11 +80,11 @@ dummy_func(void){


op(_BINARY_OP_ADD_INT, (left, right -- res)){
if (is_const(left) && is_const(right)){
assert(PyLong_CheckExact(get_const(left)));
assert(PyLong_CheckExact(get_const(right)));
PyObject *temp = _PyLong_Add((PyLongObject *)get_const(left),
(PyLongObject *)get_const(right));
if (sym_is_const(left) && sym_is_const(right)){
assert(PyLong_CheckExact(sym_get_const(left)));
assert(PyLong_CheckExact(sym_get_const(right)));
PyObject *temp = _PyLong_Add((PyLongObject *)sym_get_const(left),
(PyLongObject *)sym_get_const(right));
if (temp == NULL){
goto error;
}
Expand All@@ -97,11 +98,11 @@ dummy_func(void){
}

op(_BINARY_OP_SUBTRACT_INT, (left, right -- res)){
if (is_const(left) && is_const(right)){
assert(PyLong_CheckExact(get_const(left)));
assert(PyLong_CheckExact(get_const(right)));
PyObject *temp = _PyLong_Subtract((PyLongObject *)get_const(left),
(PyLongObject *)get_const(right));
if (sym_is_const(left) && sym_is_const(right)){
assert(PyLong_CheckExact(sym_get_const(left)));
assert(PyLong_CheckExact(sym_get_const(right)));
PyObject *temp = _PyLong_Subtract((PyLongObject *)sym_get_const(left),
(PyLongObject *)sym_get_const(right));
if (temp == NULL){
goto error;
}
Expand All@@ -115,11 +116,11 @@ dummy_func(void){
}

op(_BINARY_OP_MULTIPLY_INT, (left, right -- res)){
if (is_const(left) && is_const(right)){
assert(PyLong_CheckExact(get_const(left)));
assert(PyLong_CheckExact(get_const(right)));
PyObject *temp = _PyLong_Multiply((PyLongObject *)get_const(left),
(PyLongObject *)get_const(right));
if (sym_is_const(left) && sym_is_const(right)){
assert(PyLong_CheckExact(sym_get_const(left)));
assert(PyLong_CheckExact(sym_get_const(right)));
PyObject *temp = _PyLong_Multiply((PyLongObject *)sym_get_const(left),
(PyLongObject *)sym_get_const(right));
if (temp == NULL){
goto error;
}
Expand All@@ -133,12 +134,12 @@ dummy_func(void){
}

op(_BINARY_OP_ADD_FLOAT, (left, right -- res)){
if (is_const(left) && is_const(right)){
assert(PyFloat_CheckExact(get_const(left)));
assert(PyFloat_CheckExact(get_const(right)));
if (sym_is_const(left) && sym_is_const(right)){
assert(PyFloat_CheckExact(sym_get_const(left)));
assert(PyFloat_CheckExact(sym_get_const(right)));
PyObject *temp = PyFloat_FromDouble(
PyFloat_AS_DOUBLE(get_const(left)) +
PyFloat_AS_DOUBLE(get_const(right)));
PyFloat_AS_DOUBLE(sym_get_const(left)) +
PyFloat_AS_DOUBLE(sym_get_const(right)));
if (temp == NULL){
goto error;
}
Expand All@@ -152,12 +153,12 @@ dummy_func(void){
}

op(_BINARY_OP_SUBTRACT_FLOAT, (left, right -- res)){
if (is_const(left) && is_const(right)){
assert(PyFloat_CheckExact(get_const(left)));
assert(PyFloat_CheckExact(get_const(right)));
if (sym_is_const(left) && sym_is_const(right)){
assert(PyFloat_CheckExact(sym_get_const(left)));
assert(PyFloat_CheckExact(sym_get_const(right)));
PyObject *temp = PyFloat_FromDouble(
PyFloat_AS_DOUBLE(get_const(left)) -
PyFloat_AS_DOUBLE(get_const(right)));
PyFloat_AS_DOUBLE(sym_get_const(left)) -
PyFloat_AS_DOUBLE(sym_get_const(right)));
if (temp == NULL){
goto error;
}
Expand All@@ -171,12 +172,12 @@ dummy_func(void){
}

op(_BINARY_OP_MULTIPLY_FLOAT, (left, right -- res)){
if (is_const(left) && is_const(right)){
assert(PyFloat_CheckExact(get_const(left)));
assert(PyFloat_CheckExact(get_const(right)));
if (sym_is_const(left) && sym_is_const(right)){
assert(PyFloat_CheckExact(sym_get_const(left)));
assert(PyFloat_CheckExact(sym_get_const(right)));
PyObject *temp = PyFloat_FromDouble(
PyFloat_AS_DOUBLE(get_const(left)) *
PyFloat_AS_DOUBLE(get_const(right)));
PyFloat_AS_DOUBLE(sym_get_const(left)) *
PyFloat_AS_DOUBLE(sym_get_const(right)));
if (temp == NULL){
goto error;
}
Expand DownExpand Up@@ -229,10 +230,43 @@ dummy_func(void){
(void)owner;
}

op(_CHECK_ATTR_MODULE, (dict_version/2, owner -- owner)){
(void)dict_version;
if (sym_is_const(owner)){
PyObject *cnst = sym_get_const(owner);
if (PyModule_CheckExact(cnst)){
PyModuleObject *mod = (PyModuleObject *)cnst;
PyObject *dict = mod->md_dict;
uint64_t watched_mutations = get_mutations(dict);
if (watched_mutations < _Py_MAX_ALLOWED_GLOBALS_MODIFICATIONS){
PyDict_Watch(GLOBALS_WATCHER_ID, dict);
_Py_BloomFilter_Add(dependencies, dict);
this_instr->opcode = _NOP;
}
}
}
}

op(_LOAD_ATTR_MODULE, (index/1, owner -- attr, null if (oparg & 1))){
_LOAD_ATTR_NOT_NULL
(void)index;
(void)owner;
OUT_OF_SPACE_IF_NULL(null = sym_new_null(ctx));
attr = NULL;
if (this_instr[-1].opcode == _NOP){
// Preceding _CHECK_ATTR_MODULE was removed: mod is const and dict is watched.
assert(sym_is_const(owner));
PyModuleObject *mod = (PyModuleObject *)sym_get_const(owner);
assert(PyModule_CheckExact(mod));
PyObject *dict = mod->md_dict;
PyObject *res = convert_global_to_const(this_instr, dict);
if (res != NULL){
this_instr[-1].opcode = _POP_TOP;
OUT_OF_SPACE_IF_NULL(attr = sym_new_const(ctx, res));
}
}
if (attr == NULL){
/* No conversion made. We don't know what `attr` is. */
OUT_OF_SPACE_IF_NULL(attr = sym_new_known_notnull(ctx));
}
}

op(_LOAD_ATTR_WITH_HINT, (hint/1, owner -- attr, null if (oparg & 1))){
Expand DownExpand Up@@ -339,4 +373,4 @@ dummy_func(void){

// END BYTECODES //

}
}
Loading