10000 gh-97933: add opcode for more efficient comprehension execution by carljm · Pull Request #101310 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content

gh-97933: add opcode for more efficient comprehension execution #101310

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
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
Prev Previous commit
Merge branch 'main' into inlinecomp
* main: (225 commits)
  gh-102056: Fix a few bugs in error handling of exception printing code (#102078)
  gh-102011: use sys.exception() instead of sys.exc_info() in docs where possible (#102012)
  gh-101566: Sync with zipp 3.14. (GH-102018)
  GH-99818: improve the documentation for zipfile.Path and Traversable (GH-101589)
  gh-88233: zipfile: handle extras after a zip64 extra (GH-96161)
  gh-101981: Apply HOMEBREW related environment variables (gh-102074)
  gh-101907: Stop using `_Py_OPCODE` and `_Py_OPARG` macros (GH-101912)
  gh-101819: Adapt _io types to heap types, batch 1 (GH-101949)
  gh-101981: Build macOS as recommended by the devguide (GH-102070)
  gh-97786: Fix compiler warnings in pytime.c (#101826)
  gh-101578: Amend PyErr_{Set,Get}RaisedException docs (#101962)
  Misc improvements to the float tutorial (GH-102052)
  gh-85417: Clarify behaviour on branch cuts in cmath module (#102046)
  gh-100425: Update tutorial docs related to sum() accuracy (FH-101854)
  Add missing 'is' to `cmath.log()` docstring (#102049)
  gh-100210: Correct the comment link for unescaping HTML (#100212)
  gh-97930: Also include subdirectory in makefile. (#102030)
  gh-99735: Use required=True in argparse subparsers example (#100927)
  Fix incorrectly documented attribute in csv docs (#101250)
  GH-84783: Make the slice object hashable (GH-101264)
  ...
  • Loading branch information
carljm committed Feb 22, 2023
commit 544b30cc80e180494f2679a4a52f6b1219ff88f5
1 change: 0 additions & 1 deletion Include/internal/pycore_frame.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ typedef struct _PyInterpreterFrame {
// For comprehensions, f_closure and f_code may not match func_closure and
// func_code from f_funcobj above; f_funcobj will be the calling function.
PyObject *f_closure; /* Strong reference, may be NULL. Only valid if not on C stack */
PyCodeObject *f_code; /* Strong reference */
PyFrameObject *frame_obj; /* Strong reference, may be NULL. Only valid if not on C stack */
// NOTE: This is not necessarily the last instruction started in the given
// frame. Rather, it is the code unit *prior to* the *next* instruction. For
Expand Down
1 change: 0 additions & 1 deletion Include/internal/pycore_opcode.h

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

23 changes: 13 additions & 10 deletions Lib/importlib/_bootstrap_external.py
Original file line number Diff line number Diff line change
Expand Up @@ -423,15 +423,18 @@ def _write_atomic(path, data, mode=0o666):
# Python 3.12a1 3507 (Set lineno of module's RESUME to 0)
# Python 3.12a1 3508 (Add CLEANUP_THROW)
# Python 3.12a1 3509 (Conditional jumps only jump forward)
# Python 3.12a1 3510 (FOR_ITER leaves iterator on the stack)
# Python 3.12a1 3511 (Add STOPITERATION_ERROR instruction)
# Python 3.12a1 3512 (Remove all unused consts from code objects)
# Python 3.12a1 3513 (Add CALL_INTRINSIC_1 instruction, removed STOPITERATION_ERROR, PRINT_EXPR, IMPORT_STAR)
# Python 3.12a1 3514 (Remove ASYNC_GEN_WRAP, LIST_TO_TUPLE, and UNARY_POSITIVE)
# Python 3.12a1 3515 (Embed jump mask in COMPARE_OP oparg)
# Python 3.12a1 3516 (Add COMPARE_AND_BRANCH instruction)
# Python 3.12a1 3517 (Change YIELD_VALUE oparg to exception block depth)
# Python 3.12a1 3518 (Add COMPREHENSION instruction)
# Python 3.12a2 3510 (FOR_ITER leaves iterator on the stack)
# Python 3.12a2 3511 (Add STOPITERATION_ERROR instruction)
# Python 3.12a2 3512 (Remove all unused consts from code objects)
# Python 3.12a4 3513 (Add CALL_INTRINSIC_1 instruction, removed STOPITERATION_ERROR, PRINT_EXPR, IMPORT_STAR)
# Python 3.12a4 3514 (Remove ASYNC_GEN_WRAP, LIST_TO_TUPLE, and UNARY_POSITIVE)
# Python 3.12a5 3515 (Embed jump mask in COMPARE_OP oparg)
# Python 3.12a5 3516 (Add COMPARE_AND_BRANCH instruction)
# Python 3.12a5 3517 (Change YIELD_VALUE oparg to exception block depth)
# Python 3.12a5 3518 (Add RETURN_CONST instruction)
# Python 3.12a5 3519 (Modify SEND instruction)
# Python 3.12a5 3520 (Remove PREP_RERAISE_STAR, add CALL_INTRINSIC_2)
# Python 3.12a5 3521 (Add COMPREHENSION instruction)

# Python 3.13 will start with 3550

Expand All @@ -444,7 +447,7 @@ def _write_atomic(path, data, mode=0o666):
# Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array
# in PC/launcher.c must also be updated.

MAGIC_NUMBER = (3518).to_bytes(2, 'little') + b'\r\n'
MAGIC_NUMBER = (3521).to_bytes(2, 'little') + b'\r\n'

_RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c

Expand Down
58 changes: 45 additions & 13 deletions Python/bytecodes.c
Original file line number Diff line number Diff line change
Expand Up @@ -2382,13 +2382,10 @@ dummy_func(
kwnames = GETITEM(consts, oparg);
}

// stack effect: (__0, __1, __array[oparg] --)
inst(COMPREHENSION) {
PyObject *code = PEEK(2);
PyObject *closure = oparg ? PEEK(3) : NULL;
inst(COMPREHENSION, (closure if (oparg), code, unused -- res)) {
_PyInterpreterFrame *new_frame = _PyEvalFramePushAndInit(
tstate, Py_NewRef(frame->f_funcobj), code, closure, NULL,
stack_pointer - 1, 1, NULL
tstate, (PyFunctionObject *)Py_NewRef(frame->f_funcobj), code,
closure, NULL, stack_pointer - 1, 1, NULL
);
Py_XDECREF(code);
Py_XDECREF(closure);
Expand All @@ -2399,8 +2396,44 @@ dummy_func(
DISPATCH_INLINED(new_frame);
}

// stack effect: (__0, __array[oparg] -- )
inst(CALL) {
// Cache layout: counter/1, func_version/2, min_args/1
// Neither CALL_INTRINSIC_1/2 nor CALL_FUNCTION_EX are members!
family(call, INLINE_CACHE_ENTRIES_CALL) = {
CALL,
CALL_BOUND_METHOD_EXACT_ARGS,
CALL_PY_EXACT_ARGS,
CALL_PY_WITH_DEFAULTS,
CALL_NO_KW_TYPE_1,
CALL_NO_KW_STR_1,
CALL_NO_KW_TUPLE_1,
CALL_BUILTIN_CLASS,
CALL_NO_KW_BUILTIN_O,
CALL_NO_KW_BUILTIN_FAST,
CALL_BUILTIN_FAST_WITH_KEYWORDS,
CALL_NO_KW_LEN,
CALL_NO_KW_ISINSTANCE,
CALL_NO_KW_LIST_APPEND,
CALL_NO_KW_METHOD_DESCRIPTOR_O,
CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS,
CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS,
CALL_NO_KW_METHOD_DESCRIPTOR_FAST,
};

// On entry, the stack is either
// [NULL, callable, arg1, arg2, ...]
// or
// [method, self, arg1, arg2, ...]
// (Some args may be keywords, see KW_NAMES, which sets 'kwnames'.)
// On exit, the stack is [result].
// When calling Python, inline the call using DISPATCH_INLINED().
inst(CALL, (unused/1, unused/2, unused/1, method, callable, args[oparg] -- res)) {
int is_meth = method != NULL;
int total_args = oparg;
if (is_meth) {
callable = method;
args--;
total_args++;
}
#if ENABLE_SPECIALIZATION
_PyCallCache *cache = (_PyCallCache *)next_instr;
if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) {
Expand Down Expand Up @@ -2429,13 +2462,12 @@ dummy_func(
tstate->interp->eval_frame == NULL &&
((PyFunctionObject *)callable)->vectorcall == _PyFunction_Vectorcall)
{
int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(function))->co_flags;
PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(function));
STACK_SHRINK(total_args);
PyFunctionObject *func = (PyFunctionObject *)function;
int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(callable))->co_flags;
PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(callable));
PyFunctionObject *func = (PyFunctionObject *)callable;
_PyInterpreterFrame *new_frame = _PyEvalFramePushAndInit(
tstate, func, func->func_code, func->func_closure, locals,
stack_pointer, positional_args, kwnames
args, positional_args, kwnames
);
kwnames = NULL;
// Manipulate stack directly since we leave using DISPATCH_INLINED().
Expand Down
72 changes: 0 additions & 72 deletions Python/compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -1133,78 +1133,6 @@ stack_effect(int opcode, int oparg, int jump)
* if an exception be raised. */
return jump ? 1 : 0;

case WITH_EXCEPT_START:
return 1;

case LOAD_FAST:
case LOAD_FAST_CHECK:
return 1;
case STORE_FAST:
return -1;
case DELETE_FAST:
return 0;

case RETURN_GENERATOR:
return 0;

case RAISE_VARARGS:
return -oparg;

/* Functions and calls */
case KW_NAMES:
return 0;
case COMPREHENSION:
return -1-oparg;
case CALL:
return -1-oparg;
case CALL_INTRINSIC_1:
return 0;
case CALL_FUNCTION_EX:
return -2 - ((oparg & 0x01) != 0);
case MAKE_FUNCTION:
return 0 - ((oparg & 0x01) != 0) - ((oparg & 0x02) != 0) -
((oparg & 0x04) != 0) - ((oparg & 0x08) != 0);
case BUILD_SLICE:
if (oparg == 3)
return -2;
else
return -1;

/* Closures */
case MAKE_CELL:
case COPY_FREE_VARS:
return 0;
case LOAD_CLOSURE:
return 1;
case LOAD_DEREF:
case LOAD_CLASSDEREF:
return 1;
case STORE_DEREF:
return -1;
case DELETE_DEREF:
return 0;

/* Iterators and generators */
case GET_AWAITABLE:
return 0;

case BEFORE_ASYNC_WITH:
case BEFORE_WITH:
return 1;
case GET_AITER:
return 0;
case GET_ANEXT:
return 1;
case GET_YIELD_FROM_ITER:
return 0;
case END_ASYNC_FOR:
return -2;
case CLEANUP_THROW:
return -2;
case FORMAT_VALUE:
/* If there's a fmt_spec on the stack, we go from 2->1,
else 1->1. */
return (oparg & FVS_MASK) == FVS_HAVE_SPEC ? -1 : 0;
case LOAD_METHOD:
return 1;
default:
Expand Down
16 changes: 8 additions & 8 deletions Python/generated_cases.c.h

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

Loading
You are viewing a condensed version of this merge commit. You can view the full changes here.
0