diff options
author | mpage <mpage@meta.com> | 2025-04-01 17:18:42 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-04-01 17:18:42 (GMT) |
commit | 053c285f6b41f92fbdd1d4ff0c959cceefacd7cd (patch) | |
tree | c30af215989dca6fdd8f8ebb74396f29abdca308 /Python/bytecodes.c | |
parent | e9556e100452ed5a92fcf0e333ab75b0da29cf5b (diff) | |
download | cpython-053c285f6b41f92fbdd1d4ff0c959cceefacd7cd.zip cpython-053c285f6b41f92fbdd1d4ff0c959cceefacd7cd.tar.gz cpython-053c285f6b41f92fbdd1d4ff0c959cceefacd7cd.tar.bz2 |
gh-130704: Strength reduce `LOAD_FAST{_LOAD_FAST}` (#130708)
Optimize `LOAD_FAST` opcodes into faster versions that load borrowed references onto the operand stack when we can prove that the lifetime of the local outlives the lifetime of the temporary that is loaded onto the stack.
Diffstat (limited to 'Python/bytecodes.c')
-rw-r--r-- | Python/bytecodes.c | 28 |
1 files changed, 19 insertions, 9 deletions
diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 4342444..83847e3 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -270,6 +270,11 @@ dummy_func( value = PyStackRef_DUP(GETLOCAL(oparg)); } + replicate(8) pure inst (LOAD_FAST_BORROW, (-- value)) { + assert(!PyStackRef_IsNull(GETLOCAL(oparg))); + value = PyStackRef_Borrow(GETLOCAL(oparg)); + } + inst(LOAD_FAST_AND_CLEAR, (-- value)) { value = GETLOCAL(oparg); GETLOCAL(oparg) = PyStackRef_NULL; @@ -282,6 +287,13 @@ dummy_func( value2 = PyStackRef_DUP(GETLOCAL(oparg2)); } + inst(LOAD_FAST_BORROW_LOAD_FAST_BORROW, ( -- value1, value2)) { + uint32_t oparg1 = oparg >> 4; + uint32_t oparg2 = oparg & 15; + value1 = PyStackRef_Borrow(GETLOCAL(oparg1)); + value2 = PyStackRef_Borrow(GETLOCAL(oparg2)); + } + family(LOAD_CONST, 0) = { LOAD_CONST_MORTAL, LOAD_CONST_IMMORTAL, @@ -741,9 +753,8 @@ dummy_func( // At the end we just skip over the STORE_FAST. op(_BINARY_OP_INPLACE_ADD_UNICODE, (left, right --)) { PyObject *left_o = PyStackRef_AsPyObjectBorrow(left); - PyObject *right_o = PyStackRef_AsPyObjectSteal(right); assert(PyUnicode_CheckExact(left_o)); - assert(PyUnicode_CheckExact(right_o)); + assert(PyUnicode_CheckExact(PyStackRef_AsPyObjectBorrow(right))); int next_oparg; #if TIER_ONE @@ -767,10 +778,11 @@ dummy_func( * only the locals reference, so PyUnicode_Append knows * that the string is safe to mutate. */ - assert(Py_REFCNT(left_o) >= 2); + assert(Py_REFCNT(left_o) >= 2 || !PyStackRef_IsHeapSafe(left)); PyStackRef_CLOSE_SPECIALIZED(left, _PyUnicode_ExactDealloc); DEAD(left); PyObject *temp = PyStackRef_AsPyObjectSteal(*target_local); + PyObject *right_o = PyStackRef_AsPyObjectSteal(right); PyUnicode_Append(&temp, right_o); *target_local = PyStackRef_FromPyObjectSteal(temp); Py_DECREF(right_o); @@ -1110,8 +1122,7 @@ dummy_func( // is pushed to a different frame, the callers' frame. inst(RETURN_VALUE, (retval -- res)) { assert(frame->owner != FRAME_OWNED_BY_INTERPRETER); - _PyStackRef temp = retval; - assert(PyStackRef_IsHeapSafe(temp)); + _PyStackRef temp = PyStackRef_MakeHeapSafe(retval); DEAD(retval); SAVE_STACK(); assert(EMPTY()); @@ -1206,7 +1217,6 @@ dummy_func( op(_SEND, (receiver, v -- receiver, retval)) { PyObject *receiver_o = PyStackRef_AsPyObjectBorrow(receiver); - PyObject *retval_o; assert(frame->owner != FRAME_OWNED_BY_INTERPRETER); if ((tstate->interp->eval_frame == NULL) && @@ -1216,7 +1226,7 @@ dummy_func( PyGenObject *gen = (PyGenObject *)receiver_o; _PyInterpreterFrame *gen_frame = &gen->gi_iframe; STACK_SHRINK(1); - _PyFrame_StackPush(gen_frame, v); + _PyFrame_StackPush(gen_frame, PyStackRef_MakeHeapSafe(v)); gen->gi_frame_state = FRAME_EXECUTING; gen->gi_exc_state.previous_item = tstate->exc_info; tstate->exc_info = &gen->gi_exc_state; @@ -1261,7 +1271,7 @@ dummy_func( DEOPT_IF(gen->gi_frame_state >= FRAME_EXECUTING); STAT_INC(SEND, hit); gen_frame = &gen->gi_iframe; - _PyFrame_StackPush(gen_frame, v); + _PyFrame_StackPush(gen_frame, PyStackRef_MakeHeapSafe(v)); DEAD(v); gen->gi_frame_state = FRAME_EXECUTING; gen->gi_exc_state.previous_item = tstate->exc_info; @@ -1308,7 +1318,7 @@ dummy_func( #endif RELOAD_STACK(); LOAD_IP(1 + INLINE_CACHE_ENTRIES_SEND); - value = temp; + value = PyStackRef_MakeHeapSafe(temp); LLTRACE_RESUME_FRAME(); } |