aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Python/optimizer_analysis.c
diff options
context:
space:
mode:
Diffstat (limited to 'Python/optimizer_analysis.c')
-rw-r--r--Python/optimizer_analysis.c87
1 files changed, 37 insertions, 50 deletions
diff --git a/Python/optimizer_analysis.c b/Python/optimizer_analysis.c
index 6c0aadb87e6..29a05088e62 100644
--- a/Python/optimizer_analysis.c
+++ b/Python/optimizer_analysis.c
@@ -93,26 +93,27 @@ type_watcher_callback(PyTypeObject* type)
}
static PyObject *
-convert_global_to_const(_PyUOpInstruction *inst, PyObject *obj)
+convert_global_to_const(_PyUOpInstruction *inst, PyObject *obj, bool pop)
{
- assert(inst->opcode == _LOAD_GLOBAL_MODULE || inst->opcode == _LOAD_GLOBAL_BUILTINS || inst->opcode == _LOAD_ATTR_MODULE_FROM_KEYS);
+ 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->operand0 <= UINT16_MAX);
- if ((int)inst->operand0 >= dict->ma_keys->dk_nentries) {
+ int64_t index = inst->operand1;
+ assert(index <= UINT16_MAX);
+ if ((int)index >= dict->ma_keys->dk_nentries) {
return NULL;
}
- PyObject *res = entries[inst->operand0].me_value;
+ PyObject *res = entries[index].me_value;
if (res == NULL) {
return NULL;
}
if (_Py_IsImmortal(res)) {
- inst->opcode = _LOAD_CONST_INLINE_BORROW;
+ inst->opcode = pop ? _POP_TOP_LOAD_CONST_INLINE_BORROW : _LOAD_CONST_INLINE_BORROW;
}
else {
- inst->opcode = _LOAD_CONST_INLINE;
+ inst->opcode = pop ? _POP_TOP_LOAD_CONST_INLINE : _LOAD_CONST_INLINE;
}
if (inst->oparg & 1) {
assert(inst[1].opcode == _PUSH_NULL_CONDITIONAL);
@@ -198,21 +199,18 @@ remove_globals(_PyInterpreterFrame *frame, _PyUOpInstruction *buffer,
_PyUOpInstruction *inst = &buffer[pc];
int opcode = inst->opcode;
switch(opcode) {
- case _GUARD_BUILTINS_VERSION_PUSH_KEYS:
- if (incorrect_keys(inst, builtins)) {
+ case _GUARD_GLOBALS_VERSION:
+ if (incorrect_keys(inst, globals)) {
OPT_STAT_INC(remove_globals_incorrect_keys);
return 0;
}
- if (interp->rare_events.builtin_dict >= _Py_MAX_ALLOWED_BUILTINS_MODIFICATIONS) {
- continue;
- }
- if (!check_next_uop(buffer, buffer_size, pc,
- _LOAD_GLOBAL_BUILTINS_FROM_KEYS)) {
+ if (get_mutations(globals) >= _Py_MAX_ALLOWED_GLOBALS_MODIFICATIONS) {
continue;
}
- if ((builtins_watched & 1) == 0) {
- PyDict_Watch(BUILTINS_WATCHER_ID, builtins);
- builtins_watched |= 1;
+ if ((globals_watched & 1) == 0) {
+ PyDict_Watch(GLOBALS_WATCHER_ID, globals);
+ _Py_BloomFilter_Add(dependencies, globals);
+ globals_watched |= 1;
}
if (function_checked & 1) {
buffer[pc].opcode = NOP;
@@ -222,24 +220,29 @@ remove_globals(_PyInterpreterFrame *frame, _PyUOpInstruction *buffer,
buffer[pc].operand0 = function_version;
function_checked |= 1;
}
- // We're no longer pushing the builtins keys; rewrite the
- // instruction that consumed the keys to load them from the
- // frame.
- buffer[pc + 1].opcode = _LOAD_GLOBAL_BUILTINS;
break;
- case _GUARD_GLOBALS_VERSION:
- case _GUARD_GLOBALS_VERSION_PUSH_KEYS:
- if (incorrect_keys(inst, globals)) {
+ case _LOAD_GLOBAL_BUILTINS:
+ if (incorrect_keys(inst, builtins)) {
OPT_STAT_INC(remove_globals_incorrect_keys);
return 0;
}
- uint64_t watched_mutations = get_mutations(globals);
- if (watched_mutations >= _Py_MAX_ALLOWED_GLOBALS_MODIFICATIONS) {
+ if (interp->rare_events.builtin_dict >= _Py_MAX_ALLOWED_BUILTINS_MODIFICATIONS) {
continue;
}
- if (opcode == _GUARD_GLOBALS_VERSION_PUSH_KEYS &&
- !check_next_uop(buffer, buffer_size, pc,
- _LOAD_GLOBAL_MODULE_FROM_KEYS)) {
+ if ((builtins_watched & 1) == 0) {
+ PyDict_Watch(BUILTINS_WATCHER_ID, builtins);
+ builtins_watched |= 1;
+ }
+ if (function_checked & globals_watched & 1) {
+ convert_global_to_const(inst, builtins, false);
+ }
+ break;
+ case _LOAD_GLOBAL_MODULE:
+ if (incorrect_keys(inst, globals)) {
+ OPT_STAT_INC(remove_globals_incorrect_keys);
+ return 0;
+ }
+ if (get_mutations(globals) >= _Py_MAX_ALLOWED_GLOBALS_MODIFICATIONS) {
continue;
}
if ((globals_watched & 1) == 0) {
@@ -247,29 +250,13 @@ remove_globals(_PyInterpreterFrame *frame, _PyUOpInstruction *buffer,
_Py_BloomFilter_Add(dependencies, globals);
globals_watched |= 1;
}
- if (function_checked & 1) {
- buffer[pc].opcode = NOP;
- }
- else {
- buffer[pc].opcode = _CHECK_FUNCTION;
- buffer[pc].operand0 = function_version;
+ if ((function_checked & 1) == 0 && buffer[pc-1].opcode == _NOP) {
+ buffer[pc-1].opcode = _CHECK_FUNCTION;
+ buffer[pc-1].operand0 = function_version;
function_checked |= 1;
}
- if (opcode == _GUARD_GLOBALS_VERSION_PUSH_KEYS) {
- // We're no longer pushing the globals keys; rewrite the
- // instruction that consumed the keys to load them from the
- // frame.
- buffer[pc + 1].opcode = _LOAD_GLOBAL_MODULE;
- }
- break;
- case _LOAD_GLOBAL_BUILTINS:
- if (function_checked & globals_watched & builtins_watched & 1) {
- convert_global_to_const(inst, builtins);
- }
- break;
- case _LOAD_GLOBAL_MODULE:
- if (function_checked & globals_watched & 1) {
- convert_global_to_const(inst, globals);
+ if (function_checked & 1) {
+ convert_global_to_const(inst, globals, false);
}
break;
case _PUSH_FRAME: