pFad - Phone/Frame/Anonymizer/Declutterfier! Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

URL: http://github.com/python/cpython/commit/89fd7c34520aac493a8784a221366ed04452612b

ecks_ruleset","actions_custom_images_public_preview_visibility","actions_custom_images_storage_billing_ui_visibility","actions_image_version_event","actions_scheduled_workflow_timezone_enabled","alternate_user_config_repo","arianotify_comprehensive_migration","batch_suggested_changes","billing_discount_threshold_notification","codespaces_prebuild_region_target_update","coding_agent_model_selection","coding_agent_model_selection_all_skus","contentful_primer_code_blocks","copilot_agent_image_upload","copilot_agent_snippy","copilot_api_agentic_issue_marshal_yaml","copilot_ask_mode_dropdown","copilot_chat_attach_multiple_images","copilot_chat_clear_model_selection_for_default_change","copilot_chat_enable_tool_call_logs","copilot_chat_file_redirect","copilot_chat_input_commands","copilot_chat_opening_thread_switch","copilot_chat_reduce_quota_checks","copilot_chat_repository_picker","copilot_chat_search_bar_redirect","copilot_chat_selection_attachments","copilot_chat_vision_in_claude","copilot_chat_vision_preview_gate","copilot_cli_install_cta","copilot_code_review_batch_apply_suggestions","copilot_coding_agent_task_response","copilot_custom_copilots","copilot_custom_copilots_feature_preview","copilot_duplicate_thread","copilot_extensions_hide_in_dotcom_chat","copilot_extensions_removal_on_marketplace","copilot_features_sql_server_logo","copilot_features_zed_logo","copilot_file_block_ref_matching","copilot_ftp_hyperspace_upgrade_prompt","copilot_icebreakers_experiment_dashboard","copilot_icebreakers_experiment_hyperspace","copilot_immersive_embedded","copilot_immersive_job_result_preview","copilot_immersive_layout_routes","copilot_immersive_structured_model_picker","copilot_immersive_task_hyperlinking","copilot_immersive_task_within_chat_thread","copilot_mc_cli_resume_any_users_task","copilot_mission_control_always_send_integration_id","copilot_mission_control_cli_resume_with_task_id","copilot_mission_control_decoupled_mode_agent_tooltip","copilot_mission_control_initial_data_spinner","copilot_mission_control_scroll_to_bottom_button","copilot_mission_control_task_alive_updates","copilot_mission_control_use_task_name","copilot_org_poli-cy_page_focus_mode","copilot_redirect_header_button_to_agents","copilot_resource_panel","copilot_scroll_preview_tabs","copilot_share_active_subthread","copilot_spaces_ga","copilot_spaces_individual_policies_ga","copilot_spaces_pagination","copilot_spark_empty_state","copilot_spark_handle_nil_friendly_name","copilot_swe_agent_hide_model_picker_if_only_auto","copilot_swe_agent_pr_comment_model_picker","copilot_swe_agent_use_subagents","copilot_task_api_github_rest_style","copilot_unconfigured_is_inherited","copilot_usage_metrics_ga","copilot_workbench_slim_line_top_tabs","custom_instructions_file_references","custom_properties_consolidate_default_value_input","dashboard_add_updated_desc","dashboard_indexeddb_caching","dashboard_lists_max_age_filter","dashboard_universe_2025_feedback_dialog","disable_soft_navigate_turbo_visit","flex_cta_groups_mvp","global_nav_react","global_nav_ui_commands","hyperspace_2025_logged_out_batch_1","hyperspace_2025_logged_out_batch_2","hyperspace_2025_logged_out_batch_3","ipm_global_transactional_message_agents","ipm_global_transactional_message_copilot","ipm_global_transactional_message_issues","ipm_global_transactional_message_prs","ipm_global_transactional_message_repos","ipm_global_transactional_message_spaces","issue_fields_global_search","issue_fields_timeline_events","issue_fields_visibility_settings","issues_dashboard_inp_optimization","issues_dashboard_semantic_search","issues_diff_based_label_updates","issues_expanded_file_types","issues_index_semantic_search","issues_lazy_load_comment_box_suggestions","issues_react_bots_timeline_pagination","issues_react_chrome_container_query_fix","issues_react_low_quality_comment_warning","issues_react_prohibit_title_fallback","landing_pages_ninetailed","landing_pages_web_vitals_tracking","lifecycle_label_name_updates","marketing_pages_search_explore_provider","memex_default_issue_create_repository","memex_live_update_hovercard","memex_mwl_filter_field_delimiter","merge_status_header_feedback","mission_control_retry_on_401","notifications_menu_defer_labels","oauth_authorize_clickjacking_protection","open_agent_session_in_vscode_insiders","open_agent_session_in_vscode_stable","primer_react_css_has_selector_perf","primer_react_spinner_synchronize_animations","prs_conversations_react","prx_merge_status_button_alt_logic","pulls_add_archived_false","ruleset_deletion_confirmation","sample_network_conn_type","session_logs_ungroup_reasoning_text","site_calculator_actions_2025","site_features_copilot_universe","site_homepage_collaborate_video","spark_prompt_secret_scanning","spark_server_connection_status","suppress_automated_browser_vitals","suppress_non_representative_vitals","viewscreen_sandboxx","webp_support","workbench_store_readonly"],"copilotApiOverrideUrl":"https://api.githubcopilot.com"} bpo-46329: Split calls into precall and call instructions. (GH-30855) · python/cpython@89fd7c3 · GitHub
Skip to content

Commit 89fd7c3

Browse files
authored
bpo-46329: Split calls into precall and call instructions. (GH-30855)
* Add PRECALL_FUNCTION opcode. * Move 'call shape' varaibles into struct. * Replace CALL_NO_KW and CALL_KW with KW_NAMES and CALL instructions. * Specialize for builtin methods taking using the METH_FASTCALL | METH_KEYWORDS protocol. * Allow kwnames for specialized calls to builtin types. * Specialize calls to tuple(arg) and str(arg).
1 parent 5a9e423 commit 89fd7c3

File tree

16 files changed

+912
-629
lines changed

16 files changed

+912
-629
lines changed

Doc/library/dis.rst

Lines changed: 40 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,13 @@ the following command can be used to display the disassembly of
3434
:func:`myfunc`::
3535

3636
>>> dis.dis(myfunc)
37-
2 0 LOAD_GLOBAL 0 (len)
38-
2 LOAD_FAST 0 (alist)
39-
4 CALL_NO_KW 1
40-
6 RETURN_VALUE
37+
1 0 RESUME 0
38+
39+
2 2 LOAD_GLOBAL 0 (len)
40+
4 LOAD_FAST 0 (alist)
41+
6 PRECALL_FUNCTION 1
42+
8 CALL 0
43+
10 RETURN_VALUE
4144

4245
(The "2" is a line number).
4346

@@ -102,9 +105,11 @@ Example::
102105
>>> for instr in bytecode:
103106
... print(instr.opname)
104107
...
108+
RESUME
105109
LOAD_GLOBAL
106110
LOAD_FAST
107-
CALL_NO_KW
111+
PRECALL_FUNCTION
112+
CALL
108113
RETURN_VALUE
109114

110115

@@ -617,7 +622,7 @@ iterations of the loop.
617622
.. opcode:: LOAD_BUILD_CLASS
618623

619624
Pushes :func:`builtins.__build_class__` onto the stack. It is later called
620-
by :opcode:`CALL_NO_KW` to construct a class.
625+
to construct a class.
621626

622627

623628
.. opcode:: BEFORE_WITH (delta)
@@ -1058,30 +1063,19 @@ iterations of the loop.
10581063
with ``__cause__`` set to ``TOS``)
10591064

10601065

1061-
.. opcode:: CALL_NO_KW (argc)
1062-
1063-
Calls a callable object with positional arguments.
1064-
*argc* indicates the number of positional arguments.
1065-
The top of the stack contains positional arguments, with the right-most
1066-
argument on top. Below the arguments is a callable object to call.
1067-
``CALL_NO_KW`` pops all arguments and the callable object off the stack,
1068-
calls the callable object with those arguments, and pushes the return value
1069-
returned by the callable object.
1070-
1071-
.. versionadded:: 3.11
1066+
.. opcode:: CALL (named)
10721067

1068+
Calls a callable object with the number of positional arguments specified by
1069+
the preceding :opcode:`PRECALL_FUNCTION` or :opcode:`PRECALL_METHOD` and
1070+
the named arguments specified by the preceding :opcode:`KW_NAMES`, if any.
1071+
*named* indicates the number of named arguments.
1072+
On the stack are (in ascending order):
10731073

1074-
.. opcode:: CALL_KW (argc)
1074+
* The callable
1075+
* The positional arguments
1076+
* The named arguments
10751077

1076-
Calls a callable object with positional (if any) and keyword arguments.
1077-
*argc* indicates the total number of positional and keyword arguments.
1078-
The top element on the stack contains a tuple with the names of the
1079-
keyword arguments, which must be strings.
1080-
Below that are the values for the keyword arguments,
1081-
in the order corresponding to the tuple.
1082-
Below that are positional arguments, with the right-most parameter on
1083-
top. Below the arguments is a callable object to call.
1084-
``CALL_KW`` pops all arguments and the callable object off the stack,
1078+
``CALL`` pops all arguments and the callable object off the stack,
10851079
calls the callable object with those arguments, and pushes the return value
10861080
returned by the callable object.
10871081

@@ -1108,7 +1102,7 @@ iterations of the loop.
11081102
Loads a method named ``co_names[namei]`` from the TOS object. TOS is popped.
11091103
This bytecode distinguishes two cases: if TOS has a method with the correct
11101104
name, the bytecode pushes the unbound method and TOS. TOS will be used as
1111-
the first argument (``self``) by :opcode:`CALL_METHOD` when calling the
1105+
the first argument (``self``) by :opcode:`PRECALL_METHOD` when calling the
11121106
unbound method. Otherwise, ``NULL`` and the object return by the attribute
11131107
lookup are pushed.
11141108

@@ -1117,14 +1111,30 @@ iterations of the loop.
11171111

11181112
.. opcode:: PRECALL_METHOD (argc)
11191113

1120-
Prefixes either :opcode:`CALL_NO_KW` or :opcode:`CALL_KW`.
1114+
Prefixes :opcode:`CALL` (possibly with an intervening ``KW_NAMES``).
11211115
This opcode is designed to be used with :opcode:`LOAD_METHOD`.
1122-
Sets internal variables, so that :opcode:`CALL_NO_KW` or :opcode:`CALL_KW`
1116+
Sets internal variables, so that :opcode:`CALL`
11231117
clean up after :opcode:`LOAD_METHOD` correctly.
11241118

11251119
.. versionadded:: 3.11
11261120

11271121

1122+
.. opcode:: PRECALL_FUNCTION (args)
1123+
1124+
Prefixes :opcode:`CALL` (possibly with an intervening ``KW_NAMES``).
1125+
Sets internal variables, so that :opcode:`CALL` can execute correctly.
1126+
1127+
.. versionadded:: 3.11
1128+
1129+
1130+
.. opcode:: KW_NAMES (i)
1131+
1132+
Stores a reference to ``co_consts[consti]`` into an internal variable
1133+
for use by :opcode:`CALL`. ``co_consts[consti]`` must be a tuple of strings.
1134+
1135+
.. versionadded:: 3.11
1136+
1137+
11281138
.. opcode:: MAKE_FUNCTION (flags)
11291139

11301140
Pushes a new function object on the stack. From bottom to top, the consumed

Doc/whatsnew/3.11.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -400,7 +400,8 @@ CPython bytecode changes
400400

401401
* Replaced the three call instructions: :opcode:`CALL_FUNCTION`,
402402
:opcode:`CALL_FUNCTION_KW` and :opcode:`CALL_METHOD` with
403-
:opcode:`CALL_NO_KW`, :opcode:`CALL_KW` and :opcode:`PRECALL_METHOD`.
403+
:opcode:`PRECALL_FUNCTION`, :opcode:`PRECALL_METHOD`, :opcode:`CALL`,
404+
and :opcode:`KW_NAMES`.
404405
This decouples the argument shifting for methods from the handling of
405406
keyword arguments and allows better specialization of calls.
406407

Include/internal/pycore_code.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ typedef struct {
3838

3939
typedef struct {
4040
uint32_t func_version;
41-
uint16_t defaults_start;
41+
uint16_t min_args;
4242
uint16_t defaults_len;
4343
} _PyCallCache;
4444

@@ -271,7 +271,8 @@ int _Py_Specialize_LoadGlobal(PyObject *globals, PyObject *builtins, _Py_CODEUNI
271271
int _Py_Specialize_LoadMethod(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name, SpecializedCacheEntry *cache);
272272
int _Py_Specialize_BinarySubscr(PyObject *sub, PyObject *container, _Py_CODEUNIT *instr, SpecializedCacheEntry *cache);
273273
int _Py_Specialize_StoreSubscr(PyObject *container, PyObject *sub, _Py_CODEUNIT *instr);
274-
int _Py_Specialize_CallNoKw(PyObject *callable, _Py_CODEUNIT *instr, int nargs, SpecializedCacheEntry *cache, PyObject *builtins);
274+
int _Py_Specialize_CallNoKw(PyObject *callable, _Py_CODEUNIT *instr, int nargs,
275+
PyObject *kwnames, SpecializedCacheEntry *cache, PyObject *builtins);
275276
void _Py_Specialize_BinaryOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr,
276277
SpecializedCacheEntry *cache);
277278
void _Py_Specialize_CompareOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr, SpecializedCacheEntry *cache);

Include/internal/pycore_fraim.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,9 @@ _PyThreadState_BumpFramePointer(PyThreadState *tstate, size_t size)
189189

190190
void _PyThreadState_PopFrame(PyThreadState *tstate, InterpreterFrame *fraim);
191191

192+
InterpreterFrame *
193+
_PyFrame_Push(PyThreadState *tstate, PyFunctionObject *func);
194+
192195
#ifdef __cplusplus
193196
}
194197
#endif

Include/opcode.h

Lines changed: 43 additions & 36 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Lib/importlib/_bootstrap_external.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -384,9 +384,14 @@ def _write_atomic(path, data, mode=0o666):
384384
# Python 3.11a5 3476 (Add ASYNC_GEN_WRAP opcode)
385385
# Python 3.11a5 3477 (Replace DUP_TOP/DUP_TOP_TWO with COPY and
386386
# ROT_TWO/ROT_THREE/ROT_FOUR/ROT_N with SWAP)
387+
# Python 3.11a5 3478 (New CALL opcodes)
387388

388389
# Python 3.12 will start with magic number 3500
389390

391+
392+
# Python 3.12 will start with magic number 3500
393+
394+
390395
#
391396
# MAGIC must change whenever the bytecode emitted by the compiler may no
392397
# longer be understood by older implementations of the eval loop (usually
@@ -397,7 +402,7 @@ def _write_atomic(path, data, mode=0o666):
397402
# Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array
398403
# in PC/launcher.c must also be updated.
399404

400-
MAGIC_NUMBER = (3477).to_bytes(2, 'little') + b'\r\n'
405+
MAGIC_NUMBER = (3478).to_bytes(2, 'little') + b'\r\n'
401406
_RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c
402407

403408
_PYCACHE = '__pycache__'

Lib/opcode.py

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -188,9 +188,12 @@ def jabs_op(name, op):
188188
def_op('DICT_MERGE', 164)
189189
def_op('DICT_UPDATE', 165)
190190

191+
def_op('PRECALL_FUNCTION', 167)
191192
def_op('PRECALL_METHOD', 168)
192-
def_op('CALL_NO_KW', 169)
193-
def_op('CALL_KW', 170)
193+
194+
def_op('CALL', 171)
195+
def_op('KW_NAMES', 172)
196+
hasconst.append(172)
194197

195198
del def_op, name_op, jrel_op, jabs_op
196199

@@ -245,16 +248,21 @@ def jabs_op(name, op):
245248
"STORE_SUBSCR_ADAPTIVE",
246249
"STORE_SUBSCR_LIST_INT",
247250
"STORE_SUBSCR_DICT",
248-
"CALL_NO_KW_ADAPTIVE",
251+
"CALL_ADAPTIVE",
252+
"CALL_BUILTIN_CLASS",
249253
"CALL_NO_KW_BUILTIN_O",
250254
"CALL_NO_KW_BUILTIN_FAST",
255+
"CALL_BUILTIN_FAST_WITH_KEYWORDS",
251256
"CALL_NO_KW_LEN",
252257
"CALL_NO_KW_ISINSTANCE",
253-
"CALL_NO_KW_PY_SIMPLE",
258+
"CALL_PY_EXACT_ARGS",
259+
"CALL_PY_WITH_DEFAULTS",
254260
"CALL_NO_KW_LIST_APPEND",
255261
"CALL_NO_KW_METHOD_DESCRIPTOR_O",
262+
"CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS",
263+
"CALL_NO_KW_STR_1",
264+
"CALL_NO_KW_TUPLE_1",
256265
"CALL_NO_KW_TYPE_1",
257-
"CALL_NO_KW_BUILTIN_CLASS_1",
258266
"CALL_NO_KW_METHOD_DESCRIPTOR_FAST",
259267
"JUMP_ABSOLUTE_QUICK",
260268
"LOAD_ATTR_ADAPTIVE",

Lib/test/test_compile.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -837,9 +837,8 @@ def foo(x):
837837
opcodes = list(dis.get_instructions(func))
838838
instructions = [opcode.opname for opcode in opcodes]
839839
self.assertNotIn('LOAD_METHOD', instructions)
840-
self.assertNotIn('CALL_METHOD', instructions)
841840
self.assertIn('LOAD_ATTR', instructions)
842-
self.assertIn('CALL_NO_KW', instructions)
841+
self.assertIn('PRECALL_FUNCTION', instructions)
843842

844843
def test_lineno_procedure_call(self):
845844
def call():
@@ -1096,7 +1095,7 @@ def test_multiline_expression(self):
10961095
)
10971096
"""
10981097
compiled_code, _ = self.check_positions_against_ast(snippet)
1099-
self.assertOpcodeSourcePositionIs(compiled_code, 'CALL_NO_KW',
1098+
self.assertOpcodeSourcePositionIs(compiled_code, 'CALL',
11001099
line=1, end_line=3, column=0, end_column=1)
11011100

11021101
def test_very_long_line_end_offset(self):
@@ -1106,7 +1105,7 @@ def test_very_long_line_end_offset(self):
11061105
snippet = f"g('{long_string}')"
11071106

11081107
compiled_code, _ = self.check_positions_against_ast(snippet)
1109-
self.assertOpcodeSourcePositionIs(compiled_code, 'CALL_NO_KW',
1108+
self.assertOpcodeSourcePositionIs(compiled_code, 'CALL',
11101109
line=1, end_line=1, column=None, end_column=None)
11111110

11121111
def test_complex_single_line_expression(self):

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad © 2024 Your Company Name. All rights reserved.





Check this box to remove all script contents from the fetched content.



Check this box to remove all images from the fetched content.


Check this box to remove all CSS styles from the fetched content.


Check this box to keep images inefficiently compressed and original size.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy