Rework CALL_FUNCTION* opcodes

Issue #27213: Rework CALL_FUNCTION* opcodes to produce shorter and more
efficient bytecode:

* CALL_FUNCTION now only accepts position arguments
* CALL_FUNCTION_KW accepts position arguments and keyword arguments, but keys
  of keyword arguments are packed into a constant tuple.
* CALL_FUNCTION_EX is the most generic, it expects a tuple and a dict for
  positional and keyword arguments.

CALL_FUNCTION_VAR and CALL_FUNCTION_VAR_KW opcodes have been removed.

2 tests of test_traceback are currently broken: skip test, the issue #28050 was
created to track the issue.

Patch by Demur Rumed, design by Serhiy Storchaka, reviewed by Serhiy Storchaka
and Victor Stinner.
This commit is contained in:
Victor Stinner 2016-09-09 10:17:08 -07:00
parent e53592091a
commit f9b760f48a
12 changed files with 3372 additions and 3478 deletions

View File

@ -108,9 +108,8 @@ extern "C" {
#define LOAD_DEREF 136 #define LOAD_DEREF 136
#define STORE_DEREF 137 #define STORE_DEREF 137
#define DELETE_DEREF 138 #define DELETE_DEREF 138
#define CALL_FUNCTION_VAR 140
#define CALL_FUNCTION_KW 141 #define CALL_FUNCTION_KW 141
#define CALL_FUNCTION_VAR_KW 142 #define CALL_FUNCTION_EX 142
#define SETUP_WITH 143 #define SETUP_WITH 143
#define EXTENDED_ARG 144 #define EXTENDED_ARG 144
#define LIST_APPEND 145 #define LIST_APPEND 145

View File

@ -314,7 +314,7 @@ def _get_instructions_bytes(code, varnames=None, names=None, constants=None,
argrepr = argval argrepr = argval
elif op in hasfree: elif op in hasfree:
argval, argrepr = _get_name_info(arg, cells) argval, argrepr = _get_name_info(arg, cells)
elif op in hasnargs: elif op in hasnargs: # unused
argrepr = "%d positional, %d keyword pair" % (arg%256, arg//256) argrepr = "%d positional, %d keyword pair" % (arg%256, arg//256)
yield Instruction(opname[op], op, yield Instruction(opname[op], op,
arg, argval, argrepr, arg, argval, argrepr,

View File

@ -236,6 +236,7 @@ _code_type = type(_write_atomic.__code__)
# Python 3.6b1 3373 (add BUILD_STRING opcode #27078) # Python 3.6b1 3373 (add BUILD_STRING opcode #27078)
# Python 3.6b1 3375 (add SETUP_ANNOTATIONS and STORE_ANNOTATION opcodes # Python 3.6b1 3375 (add SETUP_ANNOTATIONS and STORE_ANNOTATION opcodes
# #27985) # #27985)
# Python 3.6a1 3376 (simplify CALL_FUNCTIONs & BUILD_MAP_UNPACK_WITH_CALL)
# #
# MAGIC must change whenever the bytecode emitted by the compiler may no # MAGIC must change whenever the bytecode emitted by the compiler may no
# longer be understood by older implementations of the eval loop (usually # longer be understood by older implementations of the eval loop (usually
@ -244,7 +245,7 @@ _code_type = type(_write_atomic.__code__)
# Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array # Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array
# in PC/launcher.c must also be updated. # in PC/launcher.c must also be updated.
MAGIC_NUMBER = (3375).to_bytes(2, 'little') + b'\r\n' MAGIC_NUMBER = (3376).to_bytes(2, 'little') + b'\r\n'
_RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c _RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c
_PYCACHE = '__pycache__' _PYCACHE = '__pycache__'

View File

@ -31,7 +31,7 @@ hasjabs = []
haslocal = [] haslocal = []
hascompare = [] hascompare = []
hasfree = [] hasfree = []
hasnargs = [] hasnargs = [] # unused
opmap = {} opmap = {}
opname = ['<%r>' % (op,) for op in range(256)] opname = ['<%r>' % (op,) for op in range(256)]
@ -172,8 +172,7 @@ haslocal.append(126)
name_op('STORE_ANNOTATION', 127) # Index in name list name_op('STORE_ANNOTATION', 127) # Index in name list
def_op('RAISE_VARARGS', 130) # Number of raise arguments (1, 2, or 3) def_op('RAISE_VARARGS', 130) # Number of raise arguments (1, 2, or 3)
def_op('CALL_FUNCTION', 131) # #args + (#kwargs << 8) def_op('CALL_FUNCTION', 131) # #args
hasnargs.append(131)
def_op('MAKE_FUNCTION', 132) # Flags def_op('MAKE_FUNCTION', 132) # Flags
def_op('BUILD_SLICE', 133) # Number of items def_op('BUILD_SLICE', 133) # Number of items
def_op('LOAD_CLOSURE', 135) def_op('LOAD_CLOSURE', 135)
@ -185,12 +184,8 @@ hasfree.append(137)
def_op('DELETE_DEREF', 138) def_op('DELETE_DEREF', 138)
hasfree.append(138) hasfree.append(138)
def_op('CALL_FUNCTION_VAR', 140) # #args + (#kwargs << 8) def_op('CALL_FUNCTION_KW', 141) # #args + #kwargs
hasnargs.append(140) def_op('CALL_FUNCTION_EX', 142) # Flags
def_op('CALL_FUNCTION_KW', 141) # #args + (#kwargs << 8)
hasnargs.append(141)
def_op('CALL_FUNCTION_VAR_KW', 142) # #args + (#kwargs << 8)
hasnargs.append(142)
jrel_op('SETUP_WITH', 143) jrel_op('SETUP_WITH', 143)

View File

@ -96,7 +96,7 @@ def _f(a):
dis_f = """\ dis_f = """\
%3d 0 LOAD_GLOBAL 0 (print) %3d 0 LOAD_GLOBAL 0 (print)
2 LOAD_FAST 0 (a) 2 LOAD_FAST 0 (a)
4 CALL_FUNCTION 1 (1 positional, 0 keyword pair) 4 CALL_FUNCTION 1
6 POP_TOP 6 POP_TOP
%3d 8 LOAD_CONST 1 (1) %3d 8 LOAD_CONST 1 (1)
@ -108,7 +108,7 @@ dis_f = """\
dis_f_co_code = """\ dis_f_co_code = """\
0 LOAD_GLOBAL 0 (0) 0 LOAD_GLOBAL 0 (0)
2 LOAD_FAST 0 (0) 2 LOAD_FAST 0 (0)
4 CALL_FUNCTION 1 (1 positional, 0 keyword pair) 4 CALL_FUNCTION 1
6 POP_TOP 6 POP_TOP
8 LOAD_CONST 1 (1) 8 LOAD_CONST 1 (1)
10 RETURN_VALUE 10 RETURN_VALUE
@ -126,7 +126,7 @@ dis_bug708901 = """\
4 LOAD_CONST 1 (1) 4 LOAD_CONST 1 (1)
%3d 6 LOAD_CONST 2 (10) %3d 6 LOAD_CONST 2 (10)
8 CALL_FUNCTION 2 (2 positional, 0 keyword pair) 8 CALL_FUNCTION 2
10 GET_ITER 10 GET_ITER
>> 12 FOR_ITER 4 (to 18) >> 12 FOR_ITER 4 (to 18)
14 STORE_FAST 0 (res) 14 STORE_FAST 0 (res)
@ -154,11 +154,11 @@ dis_bug1333982 = """\
10 MAKE_FUNCTION 0 10 MAKE_FUNCTION 0
12 LOAD_FAST 0 (x) 12 LOAD_FAST 0 (x)
14 GET_ITER 14 GET_ITER
16 CALL_FUNCTION 1 (1 positional, 0 keyword pair) 16 CALL_FUNCTION 1
%3d 18 LOAD_CONST 4 (1) %3d 18 LOAD_CONST 4 (1)
20 BINARY_ADD 20 BINARY_ADD
22 CALL_FUNCTION 1 (1 positional, 0 keyword pair) 22 CALL_FUNCTION 1
24 RAISE_VARARGS 1 24 RAISE_VARARGS 1
%3d >> 26 LOAD_CONST 0 (None) %3d >> 26 LOAD_CONST 0 (None)
@ -224,14 +224,14 @@ dis_annot_stmt_str = """\
3 10 LOAD_NAME 2 (fun) 3 10 LOAD_NAME 2 (fun)
12 LOAD_CONST 0 (1) 12 LOAD_CONST 0 (1)
14 CALL_FUNCTION 1 (1 positional, 0 keyword pair) 14 CALL_FUNCTION 1
16 STORE_ANNOTATION 3 (y) 16 STORE_ANNOTATION 3 (y)
4 18 LOAD_CONST 0 (1) 4 18 LOAD_CONST 0 (1)
20 LOAD_NAME 4 (lst) 20 LOAD_NAME 4 (lst)
22 LOAD_NAME 2 (fun) 22 LOAD_NAME 2 (fun)
24 LOAD_CONST 1 (0) 24 LOAD_CONST 1 (0)
26 CALL_FUNCTION 1 (1 positional, 0 keyword pair) 26 CALL_FUNCTION 1
28 STORE_SUBSCR 28 STORE_SUBSCR
30 LOAD_NAME 1 (int) 30 LOAD_NAME 1 (int)
32 POP_TOP 32 POP_TOP
@ -698,7 +698,7 @@ expected_opinfo_outer = [
Instruction(opname='BUILD_LIST', opcode=103, arg=0, argval=0, argrepr='', offset=26, starts_line=None, is_jump_target=False), Instruction(opname='BUILD_LIST', opcode=103, arg=0, argval=0, argrepr='', offset=26, starts_line=None, is_jump_target=False),
Instruction(opname='BUILD_MAP', opcode=105, arg=0, argval=0, argrepr='', offset=28, starts_line=None, is_jump_target=False), Instruction(opname='BUILD_MAP', opcode=105, arg=0, argval=0, argrepr='', offset=28, starts_line=None, is_jump_target=False),
Instruction(opname='LOAD_CONST', opcode=100, arg=7, argval='Hello world!', argrepr="'Hello world!'", offset=30, starts_line=None, is_jump_target=False), Instruction(opname='LOAD_CONST', opcode=100, arg=7, argval='Hello world!', argrepr="'Hello world!'", offset=30, starts_line=None, is_jump_target=False),
Instruction(opname='CALL_FUNCTION', opcode=131, arg=7, argval=7, argrepr='7 positional, 0 keyword pair', offset=32, starts_line=None, is_jump_target=False), Instruction(opname='CALL_FUNCTION', opcode=131, arg=7, argval=7, argrepr='', offset=32, starts_line=None, is_jump_target=False),
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=34, starts_line=None, is_jump_target=False), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=34, starts_line=None, is_jump_target=False),
Instruction(opname='LOAD_FAST', opcode=124, arg=2, argval='f', argrepr='f', offset=36, starts_line=8, is_jump_target=False), Instruction(opname='LOAD_FAST', opcode=124, arg=2, argval='f', argrepr='f', offset=36, starts_line=8, is_jump_target=False),
Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=38, starts_line=None, is_jump_target=False), Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=38, starts_line=None, is_jump_target=False),
@ -720,7 +720,7 @@ expected_opinfo_f = [
Instruction(opname='LOAD_DEREF', opcode=136, arg=3, argval='b', argrepr='b', offset=24, starts_line=None, is_jump_target=False), Instruction(opname='LOAD_DEREF', opcode=136, arg=3, argval='b', argrepr='b', offset=24, starts_line=None, is_jump_target=False),
Instruction(opname='LOAD_DEREF', opcode=136, arg=0, argval='c', argrepr='c', offset=26, starts_line=None, is_jump_target=False), Instruction(opname='LOAD_DEREF', opcode=136, arg=0, argval='c', argrepr='c', offset=26, starts_line=None, is_jump_target=False),
Instruction(opname='LOAD_DEREF', opcode=136, arg=1, argval='d', argrepr='d', offset=28, starts_line=None, is_jump_target=False), Instruction(opname='LOAD_DEREF', opcode=136, arg=1, argval='d', argrepr='d', offset=28, starts_line=None, is_jump_target=False),
Instruction(opname='CALL_FUNCTION', opcode=131, arg=4, argval=4, argrepr='4 positional, 0 keyword pair', offset=30, starts_line=None, is_jump_target=False), Instruction(opname='CALL_FUNCTION', opcode=131, arg=4, argval=4, argrepr='', offset=30, starts_line=None, is_jump_target=False),
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=32, starts_line=None, is_jump_target=False), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=32, starts_line=None, is_jump_target=False),
Instruction(opname='LOAD_FAST', opcode=124, arg=2, argval='inner', argrepr='inner', offset=34, starts_line=6, is_jump_target=False), Instruction(opname='LOAD_FAST', opcode=124, arg=2, argval='inner', argrepr='inner', offset=34, starts_line=6, is_jump_target=False),
Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=36, starts_line=None, is_jump_target=False), Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=36, starts_line=None, is_jump_target=False),
@ -734,7 +734,7 @@ expected_opinfo_inner = [
Instruction(opname='LOAD_DEREF', opcode=136, arg=3, argval='d', argrepr='d', offset=8, starts_line=None, is_jump_target=False), Instruction(opname='LOAD_DEREF', opcode=136, arg=3, argval='d', argrepr='d', offset=8, starts_line=None, is_jump_target=False),
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='e', argrepr='e', offset=10, starts_line=None, is_jump_target=False), Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='e', argrepr='e', offset=10, starts_line=None, is_jump_target=False),
Instruction(opname='LOAD_FAST', opcode=124, arg=1, argval='f', argrepr='f', offset=12, starts_line=None, is_jump_target=False), Instruction(opname='LOAD_FAST', opcode=124, arg=1, argval='f', argrepr='f', offset=12, starts_line=None, is_jump_target=False),
Instruction(opname='CALL_FUNCTION', opcode=131, arg=6, argval=6, argrepr='6 positional, 0 keyword pair', offset=14, starts_line=None, is_jump_target=False), Instruction(opname='CALL_FUNCTION', opcode=131, arg=6, argval=6, argrepr='', offset=14, starts_line=None, is_jump_target=False),
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=16, starts_line=None, is_jump_target=False), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=16, starts_line=None, is_jump_target=False),
Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=18, starts_line=None, is_jump_target=False), Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=18, starts_line=None, is_jump_target=False),
Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=20, starts_line=None, is_jump_target=False), Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=20, starts_line=None, is_jump_target=False),
@ -744,13 +744,13 @@ expected_opinfo_jumpy = [
Instruction(opname='SETUP_LOOP', opcode=120, arg=52, argval=54, argrepr='to 54', offset=0, starts_line=3, is_jump_target=False), Instruction(opname='SETUP_LOOP', opcode=120, arg=52, argval=54, argrepr='to 54', offset=0, starts_line=3, is_jump_target=False),
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=0, argval='range', argrepr='range', offset=2, starts_line=None, is_jump_target=False), Instruction(opname='LOAD_GLOBAL', opcode=116, arg=0, argval='range', argrepr='range', offset=2, starts_line=None, is_jump_target=False),
Instruction(opname='LOAD_CONST', opcode=100, arg=1, argval=10, argrepr='10', offset=4, starts_line=None, is_jump_target=False), Instruction(opname='LOAD_CONST', opcode=100, arg=1, argval=10, argrepr='10', offset=4, starts_line=None, is_jump_target=False),
Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='1 positional, 0 keyword pair', offset=6, starts_line=None, is_jump_target=False), Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=6, starts_line=None, is_jump_target=False),
Instruction(opname='GET_ITER', opcode=68, arg=None, argval=None, argrepr='', offset=8, starts_line=None, is_jump_target=False), Instruction(opname='GET_ITER', opcode=68, arg=None, argval=None, argrepr='', offset=8, starts_line=None, is_jump_target=False),
Instruction(opname='FOR_ITER', opcode=93, arg=32, argval=44, argrepr='to 44', offset=10, starts_line=None, is_jump_target=True), Instruction(opname='FOR_ITER', opcode=93, arg=32, argval=44, argrepr='to 44', offset=10, starts_line=None, is_jump_target=True),
Instruction(opname='STORE_FAST', opcode=125, arg=0, argval='i', argrepr='i', offset=12, starts_line=None, is_jump_target=False), Instruction(opname='STORE_FAST', opcode=125, arg=0, argval='i', argrepr='i', offset=12, starts_line=None, is_jump_target=False),
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=14, starts_line=4, is_jump_target=False), Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=14, starts_line=4, is_jump_target=False),
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=16, starts_line=None, is_jump_target=False), Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=16, starts_line=None, is_jump_target=False),
Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='1 positional, 0 keyword pair', offset=18, starts_line=None, is_jump_target=False), Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=18, starts_line=None, is_jump_target=False),
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=20, starts_line=None, is_jump_target=False), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=20, starts_line=None, is_jump_target=False),
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=22, starts_line=5, is_jump_target=False), Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=22, starts_line=5, is_jump_target=False),
Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=4, argrepr='4', offset=24, starts_line=None, is_jump_target=False), Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=4, argrepr='4', offset=24, starts_line=None, is_jump_target=False),
@ -766,14 +766,14 @@ expected_opinfo_jumpy = [
Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=44, starts_line=None, is_jump_target=True), Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=44, starts_line=None, is_jump_target=True),
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=46, starts_line=10, is_jump_target=False), Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=46, starts_line=10, is_jump_target=False),
Instruction(opname='LOAD_CONST', opcode=100, arg=4, argval='I can haz else clause?', argrepr="'I can haz else clause?'", offset=48, starts_line=None, is_jump_target=False), Instruction(opname='LOAD_CONST', opcode=100, arg=4, argval='I can haz else clause?', argrepr="'I can haz else clause?'", offset=48, starts_line=None, is_jump_target=False),
Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='1 positional, 0 keyword pair', offset=50, starts_line=None, is_jump_target=False), Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=50, starts_line=None, is_jump_target=False),
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=52, starts_line=None, is_jump_target=False), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=52, starts_line=None, is_jump_target=False),
Instruction(opname='SETUP_LOOP', opcode=120, arg=52, argval=108, argrepr='to 108', offset=54, starts_line=11, is_jump_target=True), Instruction(opname='SETUP_LOOP', opcode=120, arg=52, argval=108, argrepr='to 108', offset=54, starts_line=11, is_jump_target=True),
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=56, starts_line=None, is_jump_target=True), Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=56, starts_line=None, is_jump_target=True),
Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=98, argval=98, argrepr='', offset=58, starts_line=None, is_jump_target=False), Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=98, argval=98, argrepr='', offset=58, starts_line=None, is_jump_target=False),
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=60, starts_line=12, is_jump_target=False), Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=60, starts_line=12, is_jump_target=False),
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=62, starts_line=None, is_jump_target=False), Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=62, starts_line=None, is_jump_target=False),
Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='1 positional, 0 keyword pair', offset=64, starts_line=None, is_jump_target=False), Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=64, starts_line=None, is_jump_target=False),
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=66, starts_line=None, is_jump_target=False), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=66, starts_line=None, is_jump_target=False),
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=68, starts_line=13, is_jump_target=False), Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=68, starts_line=13, is_jump_target=False),
Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=70, starts_line=None, is_jump_target=False), Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=70, starts_line=None, is_jump_target=False),
@ -793,7 +793,7 @@ expected_opinfo_jumpy = [
Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=98, starts_line=None, is_jump_target=True), Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=98, starts_line=None, is_jump_target=True),
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=100, starts_line=19, is_jump_target=False), Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=100, starts_line=19, is_jump_target=False),
Instruction(opname='LOAD_CONST', opcode=100, arg=6, argval='Who let lolcatz into this test suite?', argrepr="'Who let lolcatz into this test suite?'", offset=102, starts_line=None, is_jump_target=False), Instruction(opname='LOAD_CONST', opcode=100, arg=6, argval='Who let lolcatz into this test suite?', argrepr="'Who let lolcatz into this test suite?'", offset=102, starts_line=None, is_jump_target=False),
Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='1 positional, 0 keyword pair', offset=104, starts_line=None, is_jump_target=False), Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=104, starts_line=None, is_jump_target=False),
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=106, starts_line=None, is_jump_target=False), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=106, starts_line=None, is_jump_target=False),
Instruction(opname='SETUP_FINALLY', opcode=122, arg=70, argval=180, argrepr='to 180', offset=108, starts_line=20, is_jump_target=True), Instruction(opname='SETUP_FINALLY', opcode=122, arg=70, argval=180, argrepr='to 180', offset=108, starts_line=20, is_jump_target=True),
Instruction(opname='SETUP_EXCEPT', opcode=121, arg=12, argval=124, argrepr='to 124', offset=110, starts_line=None, is_jump_target=False), Instruction(opname='SETUP_EXCEPT', opcode=121, arg=12, argval=124, argrepr='to 124', offset=110, starts_line=None, is_jump_target=False),
@ -812,7 +812,7 @@ expected_opinfo_jumpy = [
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=136, starts_line=None, is_jump_target=False), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=136, starts_line=None, is_jump_target=False),
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=138, starts_line=23, is_jump_target=False), Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=138, starts_line=23, is_jump_target=False),
Instruction(opname='LOAD_CONST', opcode=100, arg=8, argval='Here we go, here we go, here we go...', argrepr="'Here we go, here we go, here we go...'", offset=140, starts_line=None, is_jump_target=False), Instruction(opname='LOAD_CONST', opcode=100, arg=8, argval='Here we go, here we go, here we go...', argrepr="'Here we go, here we go, here we go...'", offset=140, starts_line=None, is_jump_target=False),
Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='1 positional, 0 keyword pair', offset=142, starts_line=None, is_jump_target=False), Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=142, starts_line=None, is_jump_target=False),
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=144, starts_line=None, is_jump_target=False), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=144, starts_line=None, is_jump_target=False),
Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=146, starts_line=None, is_jump_target=False), Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=146, starts_line=None, is_jump_target=False),
Instruction(opname='JUMP_FORWARD', opcode=110, arg=26, argval=176, argrepr='to 176', offset=148, starts_line=None, is_jump_target=False), Instruction(opname='JUMP_FORWARD', opcode=110, arg=26, argval=176, argrepr='to 176', offset=148, starts_line=None, is_jump_target=False),
@ -822,7 +822,7 @@ expected_opinfo_jumpy = [
Instruction(opname='STORE_FAST', opcode=125, arg=1, argval='dodgy', argrepr='dodgy', offset=156, starts_line=None, is_jump_target=False), Instruction(opname='STORE_FAST', opcode=125, arg=1, argval='dodgy', argrepr='dodgy', offset=156, starts_line=None, is_jump_target=False),
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=158, starts_line=26, is_jump_target=False), Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=158, starts_line=26, is_jump_target=False),
Instruction(opname='LOAD_CONST', opcode=100, arg=9, argval='Never reach this', argrepr="'Never reach this'", offset=160, starts_line=None, is_jump_target=False), Instruction(opname='LOAD_CONST', opcode=100, arg=9, argval='Never reach this', argrepr="'Never reach this'", offset=160, starts_line=None, is_jump_target=False),
Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='1 positional, 0 keyword pair', offset=162, starts_line=None, is_jump_target=False), Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=162, starts_line=None, is_jump_target=False),
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=164, starts_line=None, is_jump_target=False), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=164, starts_line=None, is_jump_target=False),
Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=166, starts_line=None, is_jump_target=False), Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=166, starts_line=None, is_jump_target=False),
Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=168, starts_line=None, is_jump_target=False), Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=168, starts_line=None, is_jump_target=False),
@ -833,7 +833,7 @@ expected_opinfo_jumpy = [
Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=178, starts_line=None, is_jump_target=False), Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=178, starts_line=None, is_jump_target=False),
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=180, starts_line=28, is_jump_target=True), Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=180, starts_line=28, is_jump_target=True),
Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=182, starts_line=None, is_jump_target=False), Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=182, starts_line=None, is_jump_target=False),
Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='1 positional, 0 keyword pair', offset=184, starts_line=None, is_jump_target=False), Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=184, starts_line=None, is_jump_target=False),
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=186, starts_line=None, is_jump_target=False), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=186, starts_line=None, is_jump_target=False),
Instruction(opname='END_FINALLY', opcode=88, arg=None, argval=None, argrepr='', offset=188, starts_line=None, is_jump_target=False), Instruction(opname='END_FINALLY', opcode=88, arg=None, argval=None, argrepr='', offset=188, starts_line=None, is_jump_target=False),
Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=190, starts_line=None, is_jump_target=False), Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=190, starts_line=None, is_jump_target=False),

View File

@ -118,7 +118,7 @@ Verify clearing of SF bug #733667
>>> g(*Nothing()) >>> g(*Nothing())
Traceback (most recent call last): Traceback (most recent call last):
... ...
TypeError: g() argument after * must be an iterable, not Nothing TypeError: 'Nothing' object is not iterable
>>> class Nothing: >>> class Nothing:
... def __len__(self): return 5 ... def __len__(self): return 5
@ -127,7 +127,7 @@ Verify clearing of SF bug #733667
>>> g(*Nothing()) >>> g(*Nothing())
Traceback (most recent call last): Traceback (most recent call last):
... ...
TypeError: g() argument after * must be an iterable, not Nothing TypeError: 'Nothing' object is not iterable
>>> class Nothing(): >>> class Nothing():
... def __len__(self): return 5 ... def __len__(self): return 5
@ -231,34 +231,32 @@ What about willful misconduct?
>>> h(*h) >>> h(*h)
Traceback (most recent call last): Traceback (most recent call last):
... ...
TypeError: h() argument after * must be an iterable, not function TypeError: 'function' object is not iterable
>>> dir(*h) >>> dir(*h)
Traceback (most recent call last): Traceback (most recent call last):
... ...
TypeError: dir() argument after * must be an iterable, not function TypeError: 'function' object is not iterable
>>> None(*h) >>> None(*h)
Traceback (most recent call last): Traceback (most recent call last):
... ...
TypeError: NoneType object argument after * must be an iterable, \ TypeError: 'function' object is not iterable
not function
>>> h(**h) >>> h(**h)
Traceback (most recent call last): Traceback (most recent call last):
... ...
TypeError: h() argument after ** must be a mapping, not function TypeError: 'function' object is not a mapping
>>> dir(**h) >>> dir(**h)
Traceback (most recent call last): Traceback (most recent call last):
... ...
TypeError: dir() argument after ** must be a mapping, not function TypeError: 'function' object is not a mapping
>>> None(**h) >>> None(**h)
Traceback (most recent call last): Traceback (most recent call last):
... ...
TypeError: NoneType object argument after ** must be a mapping, \ TypeError: 'function' object is not a mapping
not function
>>> dir(b=1, **{'b': 1}) >>> dir(b=1, **{'b': 1})
Traceback (most recent call last): Traceback (most recent call last):

View File

@ -304,6 +304,7 @@ class TracebackFormatTests(unittest.TestCase):
]) ])
# issue 26823 - Shrink recursive tracebacks # issue 26823 - Shrink recursive tracebacks
@unittest.skipIf(True, "FIXME: test broken, see issue #28050")
def _check_recursive_traceback_display(self, render_exc): def _check_recursive_traceback_display(self, render_exc):
# Always show full diffs when this test fails # Always show full diffs when this test fails
# Note that rearranging things may require adjusting # Note that rearranging things may require adjusting

View File

@ -109,19 +109,15 @@ typedef PyObject *(*callproc)(PyObject *, PyObject *, PyObject *);
/* Forward declarations */ /* Forward declarations */
#ifdef WITH_TSC #ifdef WITH_TSC
static PyObject * call_function(PyObject ***, int, uint64*, uint64*); static PyObject * call_function(PyObject ***, Py_ssize_t, PyObject *, uint64*, uint64*);
#else #else
static PyObject * call_function(PyObject ***, int); static PyObject * call_function(PyObject ***, Py_ssize_t, PyObject *);
#endif #endif
static PyObject * fast_function(PyObject *, PyObject **, Py_ssize_t, Py_ssize_t); static PyObject * fast_function(PyObject *, PyObject ***, Py_ssize_t, PyObject *);
static PyObject * do_call(PyObject *, PyObject ***, Py_ssize_t, Py_ssize_t); static PyObject * do_call(PyObject *, PyObject ***, Py_ssize_t, PyObject *);
static PyObject * ext_do_call(PyObject *, PyObject ***, int, Py_ssize_t, Py_ssize_t); static PyObject * do_call_core(PyObject *, PyObject *, PyObject *);
static PyObject * update_keyword_args(PyObject *, Py_ssize_t, PyObject ***, static PyObject * create_keyword_args(PyObject *, PyObject ***, PyObject *);
PyObject *);
static PyObject * update_star_args(Py_ssize_t, Py_ssize_t, PyObject *, PyObject ***);
static PyObject * load_args(PyObject ***, Py_ssize_t); static PyObject * load_args(PyObject ***, Py_ssize_t);
#define CALL_FLAG_VAR 1
#define CALL_FLAG_KW 2
#ifdef LLTRACE #ifdef LLTRACE
static int lltrace; static int lltrace;
@ -2659,8 +2655,14 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
TARGET(BUILD_LIST_UNPACK) { TARGET(BUILD_LIST_UNPACK) {
int convert_to_tuple = opcode == BUILD_TUPLE_UNPACK; int convert_to_tuple = opcode == BUILD_TUPLE_UNPACK;
Py_ssize_t i; Py_ssize_t i;
PyObject *sum = PyList_New(0); PyObject *sum;
PyObject *return_value; PyObject *return_value;
if (convert_to_tuple && oparg == 1 && PyTuple_CheckExact(TOP())) {
DISPATCH();
}
sum = PyList_New(0);
if (sum == NULL) if (sum == NULL)
goto error; goto error;
@ -2847,29 +2849,25 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
TARGET(BUILD_MAP_UNPACK_WITH_CALL) TARGET(BUILD_MAP_UNPACK_WITH_CALL)
TARGET(BUILD_MAP_UNPACK) { TARGET(BUILD_MAP_UNPACK) {
int with_call = opcode == BUILD_MAP_UNPACK_WITH_CALL; int with_call = opcode == BUILD_MAP_UNPACK_WITH_CALL;
int num_maps;
int function_location;
Py_ssize_t i; Py_ssize_t i;
PyObject *sum = PyDict_New(); PyObject *sum;
if (sum == NULL)
goto error; if (with_call && oparg == 1 && PyDict_CheckExact(TOP())) {
if (with_call) { DISPATCH();
num_maps = oparg & 0xff;
function_location = (oparg>>8) & 0xff;
}
else {
num_maps = oparg;
} }
for (i = num_maps; i > 0; i--) { sum = PyDict_New();
if (sum == NULL)
goto error;
for (i = oparg; i > 0; i--) {
PyObject *arg = PEEK(i); PyObject *arg = PEEK(i);
if (with_call) { if (with_call && PyDict_Size(sum)) {
PyObject *intersection = _PyDictView_Intersect(sum, arg); PyObject *intersection = _PyDictView_Intersect(sum, arg);
if (intersection == NULL) { if (intersection == NULL) {
if (PyErr_ExceptionMatches(PyExc_AttributeError)) { if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
PyObject *func = ( PyObject *func = PEEK(2 + oparg);
PEEK(function_location + num_maps));
PyErr_Format(PyExc_TypeError, PyErr_Format(PyExc_TypeError,
"%.200s%.200s argument after ** " "%.200s%.200s argument after ** "
"must be a mapping, not %.200s", "must be a mapping, not %.200s",
@ -2884,7 +2882,7 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
if (PySet_GET_SIZE(intersection)) { if (PySet_GET_SIZE(intersection)) {
Py_ssize_t idx = 0; Py_ssize_t idx = 0;
PyObject *key; PyObject *key;
PyObject *func = PEEK(function_location + num_maps); PyObject *func = PEEK(2 + oparg);
Py_hash_t hash; Py_hash_t hash;
_PySet_NextEntry(intersection, &idx, &key, &hash); _PySet_NextEntry(intersection, &idx, &key, &hash);
if (!PyUnicode_Check(key)) { if (!PyUnicode_Check(key)) {
@ -2918,7 +2916,7 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
} }
} }
while (num_maps--) while (oparg--)
Py_DECREF(POP()); Py_DECREF(POP());
PUSH(sum); PUSH(sum);
DISPATCH(); DISPATCH();
@ -3409,63 +3407,62 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
PCALL(PCALL_ALL); PCALL(PCALL_ALL);
sp = stack_pointer; sp = stack_pointer;
#ifdef WITH_TSC #ifdef WITH_TSC
res = call_function(&sp, oparg, &intr0, &intr1); res = call_function(&sp, oparg, NULL, &intr0, &intr1);
#else #else
res = call_function(&sp, oparg); res = call_function(&sp, oparg, NULL);
#endif #endif
stack_pointer = sp; stack_pointer = sp;
PUSH(res); PUSH(res);
if (res == NULL) if (res == NULL) {
goto error; goto error;
}
DISPATCH(); DISPATCH();
} }
TARGET(CALL_FUNCTION_VAR) TARGET(CALL_FUNCTION_KW) {
TARGET(CALL_FUNCTION_KW) PyObject **sp, *res, *names;
TARGET(CALL_FUNCTION_VAR_KW) {
Py_ssize_t nargs = oparg & 0xff; names = POP();
Py_ssize_t nkwargs = (oparg>>8) & 0xff; assert(PyTuple_CheckExact(names) && PyTuple_GET_SIZE(names) <= oparg);
int flags = (opcode - CALL_FUNCTION) & 3;
Py_ssize_t n;
PyObject **pfunc, *func, **sp, *res;
PCALL(PCALL_ALL); PCALL(PCALL_ALL);
n = nargs + 2 * nkwargs;
if (flags & CALL_FLAG_VAR) {
n++;
}
if (flags & CALL_FLAG_KW) {
n++;
}
pfunc = stack_pointer - n - 1;
func = *pfunc;
if (PyMethod_Check(func)
&& PyMethod_GET_SELF(func) != NULL) {
PyObject *self = PyMethod_GET_SELF(func);
Py_INCREF(self);
func = PyMethod_GET_FUNCTION(func);
Py_INCREF(func);
Py_SETREF(*pfunc, self);
nargs++;
}
else {
Py_INCREF(func);
}
sp = stack_pointer; sp = stack_pointer;
READ_TIMESTAMP(intr0); #ifdef WITH_TSC
res = ext_do_call(func, &sp, flags, nargs, nkwargs); res = call_function(&sp, oparg, names, &intr0, &intr1);
READ_TIMESTAMP(intr1); #else
res = call_function(&sp, oparg, names);
#endif
stack_pointer = sp; stack_pointer = sp;
Py_DECREF(func);
while (stack_pointer > pfunc) {
PyObject *o = POP();
Py_DECREF(o);
}
PUSH(res); PUSH(res);
if (res == NULL) Py_DECREF(names);
if (res == NULL) {
goto error; goto error;
}
DISPATCH();
}
TARGET(CALL_FUNCTION_EX) {
PyObject *func, *callargs, *kwargs = NULL, *result;
PCALL(PCALL_ALL);
if (oparg & 0x01) {
kwargs = POP();
assert(PyDict_CheckExact(kwargs));
}
callargs = POP();
assert(PyTuple_CheckExact(callargs));
func = TOP();
READ_TIMESTAMP(intr0);
result = do_call_core(func, callargs, kwargs);
READ_TIMESTAMP(intr1);
Py_DECREF(func);
Py_DECREF(callargs);
Py_XDECREF(kwargs);
SET_TOP(result);
if (result == NULL) {
goto error;
}
DISPATCH(); DISPATCH();
} }
@ -3950,7 +3947,6 @@ too_many_positional(PyCodeObject *co, Py_ssize_t given, Py_ssize_t defcount,
Py_DECREF(kwonly_sig); Py_DECREF(kwonly_sig);
} }
/* This is gonna seem *real weird*, but if you put some other code between /* This is gonna seem *real weird*, but if you put some other code between
PyEval_EvalFrame() and PyEval_EvalCodeEx() you will need to adjust PyEval_EvalFrame() and PyEval_EvalCodeEx() you will need to adjust
the test in the if statements in Misc/gdbinit (pystack and pystackv). */ the test in the if statements in Misc/gdbinit (pystack and pystackv). */
@ -3959,6 +3955,7 @@ static PyObject *
_PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals, _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
PyObject **args, Py_ssize_t argcount, PyObject **args, Py_ssize_t argcount,
PyObject **kws, Py_ssize_t kwcount, PyObject **kws, Py_ssize_t kwcount,
PyObject *kwnames, PyObject **kwstack,
PyObject **defs, Py_ssize_t defcount, PyObject **defs, Py_ssize_t defcount,
PyObject *kwdefs, PyObject *closure, PyObject *kwdefs, PyObject *closure,
PyObject *name, PyObject *qualname) PyObject *name, PyObject *qualname)
@ -3972,6 +3969,7 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
const Py_ssize_t total_args = co->co_argcount + co->co_kwonlyargcount; const Py_ssize_t total_args = co->co_argcount + co->co_kwonlyargcount;
Py_ssize_t i, n; Py_ssize_t i, n;
PyObject *kwdict; PyObject *kwdict;
Py_ssize_t kwcount2 = kwnames == NULL ? 0 : PyTuple_GET_SIZE(kwnames);
assert((kwcount == 0) || (kws != NULL)); assert((kwcount == 0) || (kws != NULL));
@ -4033,7 +4031,7 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
} }
} }
/* Handle keyword arguments (passed as an array of (key, value)) */ /* Handle keyword arguments passed as an array of (key, value) pairs */
for (i = 0; i < kwcount; i++) { for (i = 0; i < kwcount; i++) {
PyObject **co_varnames; PyObject **co_varnames;
PyObject *keyword = kws[2*i]; PyObject *keyword = kws[2*i];
@ -4092,6 +4090,61 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
SETLOCAL(j, value); SETLOCAL(j, value);
} }
/* Handle keyword arguments passed as keys tuple + values array */
for (i = 0; i < kwcount2; i++) {
PyObject **co_varnames;
PyObject *keyword = PyTuple_GET_ITEM(kwnames, i);
PyObject *value = kwstack[i];
int j;
if (keyword == NULL || !PyUnicode_Check(keyword)) {
PyErr_Format(PyExc_TypeError,
"%U() keywords must be strings",
co->co_name);
goto fail;
}
/* Speed hack: do raw pointer compares. As names are
normally interned this should almost always hit. */
co_varnames = ((PyTupleObject *)(co->co_varnames))->ob_item;
for (j = 0; j < total_args; j++) {
PyObject *nm = co_varnames[j];
if (nm == keyword)
goto kw_found2;
}
/* Slow fallback, just in case */
for (j = 0; j < total_args; j++) {
PyObject *nm = co_varnames[j];
int cmp = PyObject_RichCompareBool(
keyword, nm, Py_EQ);
if (cmp > 0)
goto kw_found2;
else if (cmp < 0)
goto fail;
}
if (j >= total_args && kwdict == NULL) {
PyErr_Format(PyExc_TypeError,
"%U() got an unexpected "
"keyword argument '%S'",
co->co_name,
keyword);
goto fail;
}
if (PyDict_SetItem(kwdict, keyword, value) == -1) {
goto fail;
}
continue;
kw_found2:
if (GETLOCAL(j) != NULL) {
PyErr_Format(PyExc_TypeError,
"%U() got multiple "
"values for argument '%S'",
co->co_name,
keyword);
goto fail;
}
Py_INCREF(value);
SETLOCAL(j, value);
}
/* Check the number of positional arguments */ /* Check the number of positional arguments */
if (argcount > co->co_argcount && !(co->co_flags & CO_VARARGS)) { if (argcount > co->co_argcount && !(co->co_flags & CO_VARARGS)) {
too_many_positional(co, argcount, defcount, fastlocals); too_many_positional(co, argcount, defcount, fastlocals);
@ -4244,6 +4297,7 @@ PyEval_EvalCodeEx(PyObject *_co, PyObject *globals, PyObject *locals,
return _PyEval_EvalCodeWithName(_co, globals, locals, return _PyEval_EvalCodeWithName(_co, globals, locals,
args, argcount, args, argcount,
kws, kwcount, kws, kwcount,
NULL, NULL,
defs, defcount, defs, defcount,
kwdefs, closure, kwdefs, closure,
NULL, NULL); NULL, NULL);
@ -4886,28 +4940,27 @@ if (tstate->use_tracing && tstate->c_profilefunc) { \
} }
static PyObject * static PyObject *
call_function(PyObject ***pp_stack, int oparg call_function(PyObject ***pp_stack, Py_ssize_t oparg, PyObject *names
#ifdef WITH_TSC #ifdef WITH_TSC
, uint64* pintr0, uint64* pintr1 , uint64* pintr0, uint64* pintr1
#endif #endif
) )
{ {
Py_ssize_t nargs = oparg & 0xff; PyObject **pfunc = (*pp_stack) - oparg - 1;
Py_ssize_t nkwargs = (oparg>>8) & 0xff;
int n = nargs + 2 * nkwargs;
PyObject **pfunc = (*pp_stack) - n - 1;
PyObject *func = *pfunc; PyObject *func = *pfunc;
PyObject *x, *w; PyObject *x, *w;
Py_ssize_t nk = names == NULL ? 0 : PyTuple_GET_SIZE(names);
Py_ssize_t nargs = oparg - nk;
/* Always dispatch PyCFunction first, because these are /* Always dispatch PyCFunction first, because these are
presumed to be the most frequent callable object. presumed to be the most frequent callable object.
*/ */
if (PyCFunction_Check(func) && nkwargs == 0) { if (PyCFunction_Check(func)) {
int flags = PyCFunction_GET_FLAGS(func); int flags = PyCFunction_GET_FLAGS(func);
PyThreadState *tstate = PyThreadState_GET(); PyThreadState *tstate = PyThreadState_GET();
PCALL(PCALL_CFUNCTION); PCALL(PCALL_CFUNCTION);
if (flags & (METH_NOARGS | METH_O)) { if (names == NULL && flags & (METH_NOARGS | METH_O)) {
PyCFunction meth = PyCFunction_GET_FUNCTION(func); PyCFunction meth = PyCFunction_GET_FUNCTION(func);
PyObject *self = PyCFunction_GET_SELF(func); PyObject *self = PyCFunction_GET_SELF(func);
if (flags & METH_NOARGS && nargs == 0) { if (flags & METH_NOARGS && nargs == 0) {
@ -4928,48 +4981,57 @@ call_function(PyObject ***pp_stack, int oparg
} }
} }
else { else {
PyObject *callargs; PyObject *callargs, *kwdict = NULL;
if (names != NULL) {
kwdict = create_keyword_args(names, pp_stack, func);
if (kwdict == NULL) {
x = NULL;
goto cfuncerror;
}
}
callargs = load_args(pp_stack, nargs); callargs = load_args(pp_stack, nargs);
if (callargs != NULL) { if (callargs != NULL) {
READ_TIMESTAMP(*pintr0); READ_TIMESTAMP(*pintr0);
C_TRACE(x, PyCFunction_Call(func,callargs,NULL)); C_TRACE(x, PyCFunction_Call(func, callargs, kwdict));
READ_TIMESTAMP(*pintr1); READ_TIMESTAMP(*pintr1);
Py_XDECREF(callargs); Py_DECREF(callargs);
} }
else { else {
x = NULL; x = NULL;
} }
Py_XDECREF(kwdict);
} }
} }
else { else {
if (PyMethod_Check(func) && PyMethod_GET_SELF(func) != NULL) { if (PyMethod_Check(func) && PyMethod_GET_SELF(func) != NULL) {
/* optimize access to bound methods */ /* optimize access to bound methods */
PyObject *self = PyMethod_GET_SELF(func); PyObject *self = PyMethod_GET_SELF(func);
PCALL(PCALL_METHOD); PCALL(PCALL_METHOD);
PCALL(PCALL_BOUND_METHOD); PCALL(PCALL_BOUND_METHOD);
Py_INCREF(self); Py_INCREF(self);
func = PyMethod_GET_FUNCTION(func); func = PyMethod_GET_FUNCTION(func);
Py_INCREF(func); Py_INCREF(func);
Py_SETREF(*pfunc, self); Py_SETREF(*pfunc, self);
nargs++; nargs++;
n++; }
} else {
else { Py_INCREF(func);
Py_INCREF(func); }
}
READ_TIMESTAMP(*pintr0);
if (PyFunction_Check(func)) {
x = fast_function(func, (*pp_stack) - n, nargs, nkwargs);
}
else {
x = do_call(func, pp_stack, nargs, nkwargs);
}
READ_TIMESTAMP(*pintr1);
Py_DECREF(func);
assert((x != NULL) ^ (PyErr_Occurred() != NULL)); READ_TIMESTAMP(*pintr0);
if (PyFunction_Check(func)) {
x = fast_function(func, pp_stack, nargs, names);
} else {
x = do_call(func, pp_stack, nargs, names);
}
READ_TIMESTAMP(*pintr1);
Py_DECREF(func);
} }
cfuncerror:
assert((x != NULL) ^ (PyErr_Occurred() != NULL));
/* Clear the stack of the function object. Also removes /* Clear the stack of the function object. Also removes
the arguments in case they weren't consumed already the arguments in case they weren't consumed already
(fast_function() and err_args() leave them on the stack). (fast_function() and err_args() leave them on the stack).
@ -4980,7 +5042,6 @@ call_function(PyObject ***pp_stack, int oparg
PCALL(PCALL_POP); PCALL(PCALL_POP);
} }
assert((x != NULL) ^ (PyErr_Occurred() != NULL));
return x; return x;
} }
@ -5033,19 +5094,16 @@ _PyFunction_FastCallNoKw(PyCodeObject *co, PyObject **args, Py_ssize_t nargs,
/* Similar to _PyFunction_FastCall() but keywords are passed a (key, value) /* Similar to _PyFunction_FastCall() but keywords are passed a (key, value)
pairs in stack */ pairs in stack */
static PyObject * static PyObject *
fast_function(PyObject *func, PyObject **stack, Py_ssize_t nargs, Py_ssize_t nkwargs) fast_function(PyObject *func, PyObject ***pp_stack, Py_ssize_t nargs, PyObject *names)
{ {
PyCodeObject *co = (PyCodeObject *)PyFunction_GET_CODE(func); PyCodeObject *co = (PyCodeObject *)PyFunction_GET_CODE(func);
PyObject *globals = PyFunction_GET_GLOBALS(func); PyObject *globals = PyFunction_GET_GLOBALS(func);
PyObject *argdefs = PyFunction_GET_DEFAULTS(func); PyObject *argdefs = PyFunction_GET_DEFAULTS(func);
PyObject *kwdefs, *closure, *name, *qualname; PyObject *kwdefs, *closure, *name, *qualname;
PyObject **d; PyObject **d;
int nd; Py_ssize_t nkwargs = names == NULL ? 0 : PyTuple_GET_SIZE(names);
Py_ssize_t nd;
assert(func != NULL); PyObject **stack = (*pp_stack)-nargs-nkwargs;
assert(nargs >= 0);
assert(nkwargs >= 0);
assert((nargs == 0 && nkwargs == 0) || stack != NULL);
PCALL(PCALL_FUNCTION); PCALL(PCALL_FUNCTION);
PCALL(PCALL_FAST_FUNCTION); PCALL(PCALL_FAST_FUNCTION);
@ -5081,8 +5139,9 @@ fast_function(PyObject *func, PyObject **stack, Py_ssize_t nargs, Py_ssize_t nkw
} }
return _PyEval_EvalCodeWithName((PyObject*)co, globals, (PyObject *)NULL, return _PyEval_EvalCodeWithName((PyObject*)co, globals, (PyObject *)NULL,
stack, nargs, stack, nargs,
stack + nargs, nkwargs, NULL, 0,
d, nd, kwdefs, names, stack + nargs,
d, (int)nd, kwdefs,
closure, name, qualname); closure, name, qualname);
} }
@ -5166,6 +5225,7 @@ _PyFunction_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs,
result = _PyEval_EvalCodeWithName((PyObject*)co, globals, (PyObject *)NULL, result = _PyEval_EvalCodeWithName((PyObject*)co, globals, (PyObject *)NULL,
args, nargs, args, nargs,
k, nk, k, nk,
NULL, NULL,
d, nd, kwdefs, d, nd, kwdefs,
closure, name, qualname); closure, name, qualname);
Py_XDECREF(kwtuple); Py_XDECREF(kwtuple);
@ -5173,22 +5233,17 @@ _PyFunction_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs,
} }
static PyObject * static PyObject *
update_keyword_args(PyObject *orig_kwdict, Py_ssize_t nk, PyObject ***pp_stack, create_keyword_args(PyObject *names, PyObject ***pp_stack,
PyObject *func) PyObject *func)
{ {
PyObject *kwdict = NULL; Py_ssize_t nk = PyTuple_GET_SIZE(names);
if (orig_kwdict == NULL) PyObject *kwdict = _PyDict_NewPresized(nk);
kwdict = PyDict_New();
else {
kwdict = PyDict_Copy(orig_kwdict);
Py_DECREF(orig_kwdict);
}
if (kwdict == NULL) if (kwdict == NULL)
return NULL; return NULL;
while (--nk >= 0) { while (--nk >= 0) {
int err; int err;
PyObject *value = EXT_POP(*pp_stack); PyObject *value = EXT_POP(*pp_stack);
PyObject *key = EXT_POP(*pp_stack); PyObject *key = PyTuple_GET_ITEM(names, nk);
if (PyDict_GetItem(kwdict, key) != NULL) { if (PyDict_GetItem(kwdict, key) != NULL) {
PyErr_Format(PyExc_TypeError, PyErr_Format(PyExc_TypeError,
"%.200s%s got multiple values " "%.200s%s got multiple values "
@ -5196,13 +5251,11 @@ update_keyword_args(PyObject *orig_kwdict, Py_ssize_t nk, PyObject ***pp_stack,
PyEval_GetFuncName(func), PyEval_GetFuncName(func),
PyEval_GetFuncDesc(func), PyEval_GetFuncDesc(func),
key); key);
Py_DECREF(key);
Py_DECREF(value); Py_DECREF(value);
Py_DECREF(kwdict); Py_DECREF(kwdict);
return NULL; return NULL;
} }
err = PyDict_SetItem(kwdict, key, value); err = PyDict_SetItem(kwdict, key, value);
Py_DECREF(key);
Py_DECREF(value); Py_DECREF(value);
if (err) { if (err) {
Py_DECREF(kwdict); Py_DECREF(kwdict);
@ -5213,183 +5266,51 @@ update_keyword_args(PyObject *orig_kwdict, Py_ssize_t nk, PyObject ***pp_stack,
} }
static PyObject * static PyObject *
update_star_args(Py_ssize_t nstack, Py_ssize_t nstar, PyObject *stararg, load_args(PyObject ***pp_stack, Py_ssize_t nargs)
PyObject ***pp_stack)
{ {
PyObject *callargs, *w; PyObject *args = PyTuple_New(nargs);
if (!nstack) { if (args == NULL) {
if (!stararg) {
/* There are no positional arguments on the stack and there is no
sequence to be unpacked. */
return PyTuple_New(0);
}
if (PyTuple_CheckExact(stararg)) {
/* No arguments are passed on the stack and the sequence is not a
tuple subclass so we can just pass the stararg tuple directly
to the function. */
Py_INCREF(stararg);
return stararg;
}
}
callargs = PyTuple_New(nstack + nstar);
if (callargs == NULL) {
return NULL; return NULL;
} }
if (nstar) { while (--nargs >= 0) {
Py_ssize_t i; PyObject *arg= EXT_POP(*pp_stack);
for (i = 0; i < nstar; i++) { PyTuple_SET_ITEM(args, nargs, arg);
PyObject *arg = PyTuple_GET_ITEM(stararg, i);
Py_INCREF(arg);
PyTuple_SET_ITEM(callargs, nstack + i, arg);
}
}
while (--nstack >= 0) {
w = EXT_POP(*pp_stack);
PyTuple_SET_ITEM(callargs, nstack, w);
}
return callargs;
}
static PyObject *
load_args(PyObject ***pp_stack, Py_ssize_t na)
{
PyObject *args = PyTuple_New(na);
PyObject *w;
if (args == NULL)
return NULL;
while (--na >= 0) {
w = EXT_POP(*pp_stack);
PyTuple_SET_ITEM(args, na, w);
} }
return args; return args;
} }
static PyObject * static PyObject *
do_call(PyObject *func, PyObject ***pp_stack, Py_ssize_t nargs, Py_ssize_t nkwargs) do_call(PyObject *func, PyObject ***pp_stack, Py_ssize_t nargs, PyObject *kwnames)
{ {
PyObject *callargs = NULL; PyObject *callargs, *kwdict, *result;
PyObject *kwdict = NULL;
PyObject *result = NULL;
if (nkwargs > 0) { if (kwnames != NULL) {
kwdict = update_keyword_args(NULL, nkwargs, pp_stack, func); kwdict = create_keyword_args(kwnames, pp_stack, func);
if (kwdict == NULL) if (kwdict == NULL) {
goto call_fail; return NULL;
}
} }
else {
kwdict = NULL;
}
callargs = load_args(pp_stack, nargs); callargs = load_args(pp_stack, nargs);
if (callargs == NULL) if (callargs == NULL) {
goto call_fail; Py_XDECREF(kwdict);
#ifdef CALL_PROFILE return NULL;
/* At this point, we have to look at the type of func to
update the call stats properly. Do it here so as to avoid
exposing the call stats machinery outside ceval.c
*/
if (PyFunction_Check(func))
PCALL(PCALL_FUNCTION);
else if (PyMethod_Check(func))
PCALL(PCALL_METHOD);
else if (PyType_Check(func))
PCALL(PCALL_TYPE);
else if (PyCFunction_Check(func))
PCALL(PCALL_CFUNCTION);
else
PCALL(PCALL_OTHER);
#endif
if (PyCFunction_Check(func)) {
PyThreadState *tstate = PyThreadState_GET();
C_TRACE(result, PyCFunction_Call(func, callargs, kwdict));
} }
else
result = PyObject_Call(func, callargs, kwdict); result = do_call_core(func, callargs, kwdict);
call_fail:
Py_XDECREF(callargs); Py_XDECREF(callargs);
Py_XDECREF(kwdict); Py_XDECREF(kwdict);
return result; return result;
} }
static PyObject * static PyObject *
ext_do_call(PyObject *func, PyObject ***pp_stack, int flags, do_call_core(PyObject *func, PyObject *callargs, PyObject *kwdict)
Py_ssize_t nargs, Py_ssize_t nkwargs)
{ {
Py_ssize_t nstar;
PyObject *callargs = NULL;
PyObject *stararg = NULL;
PyObject *kwdict = NULL;
PyObject *result = NULL;
if (flags & CALL_FLAG_KW) {
kwdict = EXT_POP(*pp_stack);
if (!PyDict_CheckExact(kwdict)) {
PyObject *d;
d = PyDict_New();
if (d == NULL)
goto ext_call_fail;
if (PyDict_Update(d, kwdict) != 0) {
Py_DECREF(d);
/* PyDict_Update raises attribute
* error (percolated from an attempt
* to get 'keys' attribute) instead of
* a type error if its second argument
* is not a mapping.
*/
if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
PyErr_Format(PyExc_TypeError,
"%.200s%.200s argument after ** "
"must be a mapping, not %.200s",
PyEval_GetFuncName(func),
PyEval_GetFuncDesc(func),
kwdict->ob_type->tp_name);
}
goto ext_call_fail;
}
Py_DECREF(kwdict);
kwdict = d;
}
}
if (nkwargs > 0) {
kwdict = update_keyword_args(kwdict, nkwargs, pp_stack, func);
if (kwdict == NULL)
goto ext_call_fail;
}
if (flags & CALL_FLAG_VAR) {
stararg = EXT_POP(*pp_stack);
if (!PyTuple_Check(stararg)) {
PyObject *t = NULL;
if (Py_TYPE(stararg)->tp_iter == NULL &&
!PySequence_Check(stararg)) {
PyErr_Format(PyExc_TypeError,
"%.200s%.200s argument after * "
"must be an iterable, not %.200s",
PyEval_GetFuncName(func),
PyEval_GetFuncDesc(func),
stararg->ob_type->tp_name);
goto ext_call_fail;
}
t = PySequence_Tuple(stararg);
if (t == NULL) {
goto ext_call_fail;
}
Py_DECREF(stararg);
stararg = t;
}
nstar = PyTuple_GET_SIZE(stararg);
}
else {
nstar = 0;
}
callargs = update_star_args(nargs, nstar, stararg, pp_stack);
if (callargs == NULL) {
goto ext_call_fail;
}
#ifdef CALL_PROFILE #ifdef CALL_PROFILE
/* At this point, we have to look at the type of func to /* At this point, we have to look at the type of func to
update the call stats properly. Do it here so as to avoid update the call stats properly. Do it here so as to avoid
@ -5406,19 +5327,16 @@ ext_do_call(PyObject *func, PyObject ***pp_stack, int flags,
else else
PCALL(PCALL_OTHER); PCALL(PCALL_OTHER);
#endif #endif
if (PyCFunction_Check(func)) { if (PyCFunction_Check(func)) {
PyObject *result;
PyThreadState *tstate = PyThreadState_GET(); PyThreadState *tstate = PyThreadState_GET();
C_TRACE(result, PyCFunction_Call(func, callargs, kwdict)); C_TRACE(result, PyCFunction_Call(func, callargs, kwdict));
return result;
} }
else { else {
result = PyObject_Call(func, callargs, kwdict); return PyObject_Call(func, callargs, kwdict);
} }
ext_call_fail:
Py_XDECREF(callargs);
Py_XDECREF(kwdict);
Py_XDECREF(stararg);
return result;
} }
/* Extract a slice index from a PyLong or an object with the /* Extract a slice index from a PyLong or an object with the

View File

@ -991,7 +991,7 @@ PyCompile_OpcodeStackEffect(int opcode, int oparg)
case BUILD_MAP_UNPACK: case BUILD_MAP_UNPACK:
return 1 - oparg; return 1 - oparg;
case BUILD_MAP_UNPACK_WITH_CALL: case BUILD_MAP_UNPACK_WITH_CALL:
return 1 - (oparg & 0xFF); return 1 - oparg;
case BUILD_MAP: case BUILD_MAP:
return 1 - 2*oparg; return 1 - 2*oparg;
case BUILD_CONST_KEY_MAP: case BUILD_CONST_KEY_MAP:
@ -1038,15 +1038,12 @@ PyCompile_OpcodeStackEffect(int opcode, int oparg)
case RAISE_VARARGS: case RAISE_VARARGS:
return -oparg; return -oparg;
#define NARGS(o) (((o) % 256) + 2*(((o) / 256) % 256))
case CALL_FUNCTION: case CALL_FUNCTION:
return -NARGS(oparg); return -oparg;
case CALL_FUNCTION_VAR:
case CALL_FUNCTION_KW: case CALL_FUNCTION_KW:
return -NARGS(oparg)-1; return -oparg-1;
case CALL_FUNCTION_VAR_KW: case CALL_FUNCTION_EX:
return -NARGS(oparg)-2; return - ((oparg & 0x01) != 0) - ((oparg & 0x02) != 0);
#undef NARGS
case MAKE_FUNCTION: case MAKE_FUNCTION:
return -1 - ((oparg & 0x01) != 0) - ((oparg & 0x02) != 0) - return -1 - ((oparg & 0x01) != 0) - ((oparg & 0x02) != 0) -
((oparg & 0x04) != 0) - ((oparg & 0x08) != 0); ((oparg & 0x04) != 0) - ((oparg & 0x08) != 0);
@ -3500,22 +3497,29 @@ compiler_call_helper(struct compiler *c,
asdl_seq *args, asdl_seq *args,
asdl_seq *keywords) asdl_seq *keywords)
{ {
int code = 0; Py_ssize_t i, nseen, nelts, nkwelts;
Py_ssize_t nelts, i, nseen; int musttupleunpack = 0, mustdictunpack = 0;
int nkw;
/* the number of tuples and dictionaries on the stack */ /* the number of tuples and dictionaries on the stack */
Py_ssize_t nsubargs = 0, nsubkwargs = 0; Py_ssize_t nsubargs = 0, nsubkwargs = 0;
nkw = 0;
nseen = 0; /* the number of positional arguments on the stack */
nelts = asdl_seq_LEN(args); nelts = asdl_seq_LEN(args);
nkwelts = asdl_seq_LEN(keywords);
for (i = 0; i < nkwelts; i++) {
keyword_ty kw = asdl_seq_GET(keywords, i);
if (kw->arg == NULL) {
mustdictunpack = 1;
break;
}
}
nseen = n; /* the number of positional arguments on the stack */
for (i = 0; i < nelts; i++) { for (i = 0; i < nelts; i++) {
expr_ty elt = asdl_seq_GET(args, i); expr_ty elt = asdl_seq_GET(args, i);
if (elt->kind == Starred_kind) { if (elt->kind == Starred_kind) {
/* A star-arg. If we've seen positional arguments, /* A star-arg. If we've seen positional arguments,
pack the positional arguments into a pack the positional arguments into a tuple. */
tuple. */
if (nseen) { if (nseen) {
ADDOP_I(c, BUILD_TUPLE, nseen); ADDOP_I(c, BUILD_TUPLE, nseen);
nseen = 0; nseen = 0;
@ -3523,102 +3527,80 @@ compiler_call_helper(struct compiler *c,
} }
VISIT(c, expr, elt->v.Starred.value); VISIT(c, expr, elt->v.Starred.value);
nsubargs++; nsubargs++;
} musttupleunpack = 1;
else if (nsubargs) {
/* We've seen star-args already, so we
count towards items-to-pack-into-tuple. */
VISIT(c, expr, elt);
nseen++;
} }
else { else {
/* Positional arguments before star-arguments
are left on the stack. */
VISIT(c, expr, elt); VISIT(c, expr, elt);
n++; nseen++;
}
}
if (nseen) {
/* Pack up any trailing positional arguments. */
ADDOP_I(c, BUILD_TUPLE, nseen);
nsubargs++;
}
if (nsubargs) {
code |= 1;
if (nsubargs > 1) {
/* If we ended up with more than one stararg, we need
to concatenate them into a single sequence. */
ADDOP_I(c, BUILD_LIST_UNPACK, nsubargs);
} }
} }
/* Same dance again for keyword arguments */ /* Same dance again for keyword arguments */
nseen = 0; /* the number of keyword arguments on the stack following */ if (musttupleunpack || mustdictunpack) {
nelts = asdl_seq_LEN(keywords); if (nseen) {
for (i = 0; i < nelts; i++) { /* Pack up any trailing positional arguments. */
keyword_ty kw = asdl_seq_GET(keywords, i); ADDOP_I(c, BUILD_TUPLE, nseen);
if (kw->arg == NULL) { nsubargs++;
/* A keyword argument unpacking. */ }
if (nseen) { if (musttupleunpack || nsubargs > 1) {
if (nsubkwargs) { /* If we ended up with more than one stararg, we need
to concatenate them into a single sequence. */
ADDOP_I(c, BUILD_TUPLE_UNPACK, nsubargs);
}
else if (nsubargs == 0) {
ADDOP_I(c, BUILD_TUPLE, 0);
}
nseen = 0; /* the number of keyword arguments on the stack following */
for (i = 0; i < nkwelts; i++) {
keyword_ty kw = asdl_seq_GET(keywords, i);
if (kw->arg == NULL) {
/* A keyword argument unpacking. */
if (nseen) {
if (!compiler_subkwargs(c, keywords, i - nseen, i)) if (!compiler_subkwargs(c, keywords, i - nseen, i))
return 0; return 0;
nsubkwargs++; nsubkwargs++;
nseen = 0;
} }
else { VISIT(c, expr, kw->value);
Py_ssize_t j; nsubkwargs++;
for (j = 0; j < nseen; j++) { }
VISIT(c, keyword, asdl_seq_GET(keywords, j)); else {
} nseen++;
nkw = nseen;
}
nseen = 0;
} }
VISIT(c, expr, kw->value);
nsubkwargs++;
} }
else { if (nseen) {
nseen++;
}
}
if (nseen) {
if (nsubkwargs) {
/* Pack up any trailing keyword arguments. */ /* Pack up any trailing keyword arguments. */
if (!compiler_subkwargs(c, keywords, nelts - nseen, nelts)) if (!compiler_subkwargs(c, keywords, nkwelts - nseen, nkwelts))
return 0; return 0;
nsubkwargs++; nsubkwargs++;
} }
else { if (mustdictunpack || nsubkwargs > 1) {
VISIT_SEQ(c, keyword, keywords);
nkw = nseen;
}
}
if (nsubkwargs) {
code |= 2;
if (nsubkwargs > 1) {
/* Pack it all up */ /* Pack it all up */
int function_pos = n + (code & 1) + 2 * nkw + 1; ADDOP_I(c, BUILD_MAP_UNPACK_WITH_CALL, nsubkwargs);
ADDOP_I(c, BUILD_MAP_UNPACK_WITH_CALL, nsubkwargs | (function_pos << 8));
} }
ADDOP_I(c, CALL_FUNCTION_EX, nsubkwargs > 0);
return 1;
} }
assert(n < 1<<8); else if (nkwelts) {
assert(nkw < 1<<24); PyObject *names;
n |= nkw << 8; VISIT_SEQ(c, keyword, keywords);
names = PyTuple_New(nkwelts);
switch (code) { if (names == NULL) {
case 0: return 0;
ADDOP_I(c, CALL_FUNCTION, n); }
break; for (i = 0; i < nkwelts; i++) {
case 1: keyword_ty kw = asdl_seq_GET(keywords, i);
ADDOP_I(c, CALL_FUNCTION_VAR, n); Py_INCREF(kw->arg);
break; PyTuple_SET_ITEM(names, i, kw->arg);
case 2: }
ADDOP_I(c, CALL_FUNCTION_KW, n); ADDOP_N(c, LOAD_CONST, names, consts);
break; ADDOP_I(c, CALL_FUNCTION_KW, n + nelts + nkwelts);
case 3: return 1;
ADDOP_I(c, CALL_FUNCTION_VAR_KW, n); }
break; else {
ADDOP_I(c, CALL_FUNCTION, n + nelts);
return 1;
} }
return 1;
} }
@ -4040,7 +4022,6 @@ compiler_dictcomp(struct compiler *c, expr_ty e)
static int static int
compiler_visit_keyword(struct compiler *c, keyword_ty k) compiler_visit_keyword(struct compiler *c, keyword_ty k)
{ {
ADDOP_O(c, LOAD_CONST, k->arg, consts);
VISIT(c, expr, k->value); VISIT(c, expr, k->value);
return 1; return 1;
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -139,9 +139,9 @@ static void *opcode_targets[256] = {
&&TARGET_STORE_DEREF, &&TARGET_STORE_DEREF,
&&TARGET_DELETE_DEREF, &&TARGET_DELETE_DEREF,
&&_unknown_opcode, &&_unknown_opcode,
&&TARGET_CALL_FUNCTION_VAR, &&_unknown_opcode,
&&TARGET_CALL_FUNCTION_KW, &&TARGET_CALL_FUNCTION_KW,
&&TARGET_CALL_FUNCTION_VAR_KW, &&TARGET_CALL_FUNCTION_EX,
&&TARGET_SETUP_WITH, &&TARGET_SETUP_WITH,
&&TARGET_EXTENDED_ARG, &&TARGET_EXTENDED_ARG,
&&TARGET_LIST_APPEND, &&TARGET_LIST_APPEND,