Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit67a91f7

Browse files
authored
gh-109094: replace frame->prev_instr by frame->instr_ptr (#109095)
1 parent573eff3 commit67a91f7

23 files changed

+249
-164
lines changed

‎Include/internal/pycore_frame.h‎

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -58,26 +58,16 @@ typedef struct _PyInterpreterFrame {
5858
PyObject*f_builtins;/* Borrowed reference. Only valid if not on C stack */
5959
PyObject*f_locals;/* Strong reference, may be NULL. Only valid if not on C stack */
6060
PyFrameObject*frame_obj;/* Strong reference, may be NULL. Only valid if not on C stack */
61-
// NOTE: This is not necessarily the last instruction started in the given
62-
// frame. Rather, it is the code unit *prior to* the *next* instruction. For
63-
// example, it may be an inline CACHE entry, an instruction we just jumped
64-
// over, or (in the case of a newly-created frame) a totally invalid value:
65-
_Py_CODEUNIT*prev_instr;
61+
_Py_CODEUNIT*instr_ptr;/* Instruction currently executing (or about to begin) */
6662
intstacktop;/* Offset of TOS from localsplus */
67-
/* The return_offset determines where a `RETURN` should go in the caller,
68-
* relative to `prev_instr`.
69-
* It is only meaningful to the callee,
70-
* so it needs to be set in any CALL (to a Python function)
71-
* or SEND (to a coroutine or generator).
72-
* If there is no callee, then it is meaningless. */
73-
uint16_treturn_offset;
63+
uint16_treturn_offset;/* Only relevant during a function call */
7464
charowner;
7565
/* Locals and stack */
7666
PyObject*localsplus[1];
7767
}_PyInterpreterFrame;
7868

7969
#define_PyInterpreterFrame_LASTI(IF) \
80-
((int)((IF)->prev_instr - _PyCode_CODE(_PyFrame_GetCode(IF))))
70+
((int)((IF)->instr_ptr - _PyCode_CODE(_PyFrame_GetCode(IF))))
8171

8272
staticinlinePyCodeObject*_PyFrame_GetCode(_PyInterpreterFrame*f) {
8373
assert(PyCode_Check(f->f_executable));
@@ -134,7 +124,7 @@ _PyFrame_Initialize(
134124
frame->f_locals=locals;
135125
frame->stacktop=code->co_nlocalsplus;
136126
frame->frame_obj=NULL;
137-
frame->prev_instr=_PyCode_CODE(code)-1;
127+
frame->instr_ptr=_PyCode_CODE(code);
138128
frame->return_offset=0;
139129
frame->owner=FRAME_OWNED_BY_THREAD;
140130

@@ -185,7 +175,7 @@ _PyFrame_IsIncomplete(_PyInterpreterFrame *frame)
185175
return true;
186176
}
187177
returnframe->owner!=FRAME_OWNED_BY_GENERATOR&&
188-
frame->prev_instr<_PyCode_CODE(_PyFrame_GetCode(frame))+_PyFrame_GetCode(frame)->_co_firsttraceable;
178+
frame->instr_ptr<_PyCode_CODE(_PyFrame_GetCode(frame))+_PyFrame_GetCode(frame)->_co_firsttraceable;
189179
}
190180

191181
staticinline_PyInterpreterFrame*
@@ -297,7 +287,7 @@ _PyFrame_PushTrampolineUnchecked(PyThreadState *tstate, PyCodeObject *code, int
297287
frame->f_locals=NULL;
298288
frame->stacktop=code->co_nlocalsplus+stackdepth;
299289
frame->frame_obj=NULL;
300-
frame->prev_instr=_PyCode_CODE(code);
290+
frame->instr_ptr=_PyCode_CODE(code);
301291
frame->owner=FRAME_OWNED_BY_THREAD;
302292
frame->return_offset=0;
303293
returnframe;

‎Include/internal/pycore_opcode_metadata.h‎

Lines changed: 8 additions & 8 deletions
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.

‎Include/internal/pycore_runtime.h‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ typedef struct _Py_DebugOffsets {
8787
struct_interpreter_frame {
8888
off_tprevious;
8989
off_texecutable;
90-
off_tprev_instr;
90+
off_tinstr_ptr;
9191
off_tlocalsplus;
9292
off_towner;
9393
}interpreter_frame;

‎Include/internal/pycore_runtime_init.h‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ extern PyTypeObject _PyExc_MemoryError;
5858
.interpreter_frame = { \
5959
.previous = offsetof(_PyInterpreterFrame, previous), \
6060
.executable = offsetof(_PyInterpreterFrame, f_executable), \
61-
.prev_instr = offsetof(_PyInterpreterFrame,prev_instr), \
61+
.instr_ptr = offsetof(_PyInterpreterFrame,instr_ptr), \
6262
.localsplus = offsetof(_PyInterpreterFrame, localsplus), \
6363
.owner = offsetof(_PyInterpreterFrame, owner), \
6464
}, \
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Replace ``prev_instr`` on the interpreter frame by ``instr_ptr`` which
2+
points to the beginning of the instruction that is currently executing (or
3+
will execute once the frame resumes).

‎Objects/frame_layout.md‎

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,3 +130,28 @@ returns. This extra frame is inserted so that `RETURN_VALUE`, `YIELD_VALUE`, and
130130
`RETURN_GENERATOR` do not need to check whether the current frame is the entry frame.
131131
The shim frame points to a special code object containing the`INTERPRETER_EXIT`
132132
instruction which cleans up the shim frame and returns.
133+
134+
135+
###The Instruction Pointer
136+
137+
`_PyInterpreterFrame` has two fields which are used to maintain the instruction
138+
pointer:`instr_ptr` and`return_offset`.
139+
140+
When a frame is executing,`instr_ptr` points to the instruction currently being
141+
executed. In a suspended frame, it points to the instruction that would execute
142+
if the frame were to resume. After`frame.f_lineno` is set,`instr_ptr` points to
143+
the next instruction to be executed. During a call to a python function,
144+
`instr_ptr` points to the call instruction, because this is what we would expect
145+
to see in an exception traceback.
146+
147+
The`return_offset` field determines where a`RETURN` should go in the caller,
148+
relative to`instr_ptr`. It is only meaningful to the callee, so it needs to
149+
be set in any instruction that implements a call (to a Python function),
150+
including CALL, SEND and BINARY_SUBSCR_GETITEM, among others. If there is no
151+
callee, then return_offset is meaningless. It is necessary to have a separate
152+
field for the return offset because (1) if we apply this offset to`instr_ptr`
153+
while executing the`RETURN`, this is too early and would lose us information
154+
about the previous instruction which we could need for introspecting and
155+
debugging. (2)`SEND` needs to pass two offsets to the generator: one for
156+
`RETURN` and one for`YIELD`. It uses the`oparg` for one, and the
157+
`return_offset` for the other.

‎Objects/frameobject.c‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -821,7 +821,7 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno, void *Py_UNUSED(ignore
821821
}
822822
/* Finally set the new lasti and return OK. */
823823
f->f_lineno=0;
824-
f->f_frame->prev_instr=_PyCode_CODE(code)+best_addr;
824+
f->f_frame->instr_ptr=_PyCode_CODE(code)+best_addr;
825825
return0;
826826
}
827827

@@ -1079,7 +1079,7 @@ PyFrame_New(PyThreadState *tstate, PyCodeObject *code,
10791079
f->f_frame= (_PyInterpreterFrame*)f->_f_frame_data;
10801080
f->f_frame->owner=FRAME_OWNED_BY_FRAME_OBJECT;
10811081
// This frame needs to be "complete", so pretend that the first RESUME ran:
1082-
f->f_frame->prev_instr=_PyCode_CODE(code)+code->_co_firsttraceable;
1082+
f->f_frame->instr_ptr=_PyCode_CODE(code)+code->_co_firsttraceable+1;
10831083
assert(!_PyFrame_IsIncomplete(f->f_frame));
10841084
Py_DECREF(func);
10851085
_PyObject_GC_TRACK(f);
@@ -1093,7 +1093,7 @@ _PyFrame_OpAlreadyRan(_PyInterpreterFrame *frame, int opcode, int oparg)
10931093
assert(_PyOpcode_Deopt[opcode]==opcode);
10941094
intcheck_oparg=0;
10951095
for (_Py_CODEUNIT*instruction=_PyCode_CODE(_PyFrame_GetCode(frame));
1096-
instruction<frame->prev_instr;instruction++)
1096+
instruction<frame->instr_ptr;instruction++)
10971097
{
10981098
intcheck_opcode=_PyOpcode_Deopt[instruction->op.code];
10991099
check_oparg |=instruction->op.arg;
@@ -1135,7 +1135,7 @@ frame_init_get_vars(_PyInterpreterFrame *frame)
11351135
frame->localsplus[offset+i]=Py_NewRef(o);
11361136
}
11371137
// COPY_FREE_VARS doesn't have inline CACHEs, either:
1138-
frame->prev_instr=_PyCode_CODE(_PyFrame_GetCode(frame));
1138+
frame->instr_ptr=_PyCode_CODE(_PyFrame_GetCode(frame));
11391139
}
11401140

11411141

‎Objects/genobject.c‎

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include"pycore_genobject.h"// struct _Py_async_gen_state
1010
#include"pycore_modsupport.h"// _PyArg_CheckPositional()
1111
#include"pycore_object.h"// _PyObject_GC_UNTRACK()
12+
#include"pycore_opcode_metadata.h"// _PyOpcode_Caches
1213
#include"pycore_pyerrors.h"// _PyErr_ClearExcState()
1314
#include"pycore_pystate.h"// _PyThreadState_GET()
1415

@@ -362,8 +363,7 @@ _PyGen_yf(PyGenObject *gen)
362363
assert(_PyCode_CODE(_PyGen_GetCode(gen))[0].op.code!=SEND);
363364
returnNULL;
364365
}
365-
_Py_CODEUNITnext=frame->prev_instr[1];
366-
if (!is_resume(&next)||next.op.arg<2)
366+
if (!is_resume(frame->instr_ptr)||frame->instr_ptr->op.arg<2)
367367
{
368368
/* Not in a yield from */
369369
returnNULL;
@@ -398,9 +398,12 @@ gen_close(PyGenObject *gen, PyObject *args)
398398
_PyInterpreterFrame*frame= (_PyInterpreterFrame*)gen->gi_iframe;
399399
/* It is possible for the previous instruction to not be a
400400
* YIELD_VALUE if the debugger has changed the lineno. */
401-
if (err==0&&is_yield(frame->prev_instr)) {
402-
assert(is_resume(frame->prev_instr+1));
403-
intexception_handler_depth=frame->prev_instr[0].op.arg;
401+
assert(_PyOpcode_Caches[YIELD_VALUE]==0);
402+
assert(_PyOpcode_Caches[INSTRUMENTED_YIELD_VALUE]==0);
403+
if (err==0&&is_yield(frame->instr_ptr-1)) {
404+
_Py_CODEUNIT*yield_instr=frame->instr_ptr-1;
405+
assert(is_resume(frame->instr_ptr));
406+
intexception_handler_depth=yield_instr->op.arg;
404407
assert(exception_handler_depth>0);
405408
/* We can safely ignore the outermost try block
406409
* as it automatically generated to handle

‎Python/abstract_interp_cases.c.h‎

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp