4848)
4949from .opcode_cinder import opcode as cinder_opcode
5050from .opcodebase import Opcode
51- from .opcodes import opcode as opcodes_opcode
51+ from .opcodes import opcode as opcodes_opcode , STATIC_OPCODES
5252from .symbols import ClassScope , Scope
5353
5454
@@ -832,7 +832,7 @@ def compute_stack_depth(self) -> None:
832832 self .stacksize = self .stackdepth_walk (block )
833833 break
834834
835- def instrsize (self , opname : str , oparg : int ) -> int :
835+ def instrsize (self , instr : Instruction , oparg : int ) -> int :
836836 if oparg <= 0xFF :
837837 return 1
838838 elif oparg <= 0xFFFF :
@@ -878,17 +878,17 @@ def flatten_graph(self) -> None:
878878
879879 for inst in b .getInstructions ():
880880 insts .append (inst )
881- pc += self .instrsize (inst . opname , inst .ioparg )
881+ pc += self .instrsize (inst , inst .ioparg )
882882
883883 pc = 0
884884 for inst in insts :
885- pc += self .instrsize (inst . opname , inst .ioparg )
885+ pc += self .instrsize (inst , inst .ioparg )
886886 op = self .opcode .opmap [inst .opname ]
887887 if self .opcode .has_jump (op ):
888888 offset = self .flatten_jump (inst , pc )
889889
890- if self .instrsize (inst . opname , inst .ioparg ) != self .instrsize (
891- inst . opname , offset
890+ if self .instrsize (inst , inst .ioparg ) != self .instrsize (
891+ inst , offset
892892 ):
893893 extended_arg_recompile = True
894894
@@ -1092,7 +1092,7 @@ def make_line_table(self) -> bytes:
10921092 lnotab .nextLine (t .lineno , prev_offset , offset )
10931093 prev_offset = offset
10941094
1095- offset += self .instrsize (t . opname , t .ioparg ) * self .opcode .CODEUNIT_SIZE
1095+ offset += self .instrsize (t , t .ioparg ) * self .opcode .CODEUNIT_SIZE
10961096
10971097 # Since the linetable format writes the end offset of bytecodes, we can't commit the
10981098 # last write until all the instructions are iterated over.
@@ -2022,7 +2022,8 @@ def prepare_localsplus(self) -> int:
20222022 assert nlocalsplus >= 0
20232023 return nlocalsplus
20242024
2025- def instrsize (self , opname : str , oparg : int ) -> int :
2025+ def instrsize (self , instr : Instruction , oparg : int ) -> int :
2026+ opname = instr .opname
20262027 opcode_index = opcodes_opcode .opmap [opname ]
20272028 if opcode_index >= len (_inline_cache_entries ):
20282029 # T190611021: This should never happen as we should remove pseudo
@@ -2133,7 +2134,7 @@ def make_line_table(self) -> bytes:
21332134 size = 0
21342135
21352136 # The size is in terms of code units
2136- size += self .instrsize (t . opname , t .ioparg )
2137+ size += self .instrsize (t , t .ioparg )
21372138
21382139 # Since the linetable format writes the end offset of bytecodes, we can't commit the
21392140 # last write until all the instructions are iterated over.
@@ -2152,7 +2153,7 @@ def make_exception_table(self) -> bytes:
21522153 exception_table .emit_entry (start , ioffset , handler )
21532154 start = ioffset
21542155 handler = instr .exc_handler
2155- ioffset += self .instrsize (instr . opname , instr .ioparg )
2156+ ioffset += self .instrsize (instr , instr .ioparg )
21562157 if handler :
21572158 exception_table .emit_entry (start , ioffset , handler )
21582159 return exception_table .getTable ()
@@ -2356,6 +2357,9 @@ def flatten_jump(self, inst: Instruction, pc: int) -> int:
23562357 # sys.monitoring needs to be able to find the matching END_SEND
23572358 # but the target is the SEND, so we adjust it here.
23582359 res -= self .END_SEND_OFFSET
2360+ elif inst .opname in STATIC_OPCODES :
2361+ # Account for EXTENDED_OPCODE
2362+ res += 2
23592363
23602364 return res
23612365
@@ -2470,7 +2474,7 @@ def flatten_graph(self) -> None:
24702474 for b in self .getBlocksInOrder ():
24712475 for inst in b .getInstructions ():
24722476 if inst .is_jump (self .opcode ):
2473- assert inst .target is not None
2477+ assert inst .target is not None , inst
24742478 inst .ioparg = label_map [inst .target ]
24752479
24762480 super ().flatten_graph ()
@@ -2543,8 +2547,23 @@ def _convert_compare_op(self: PyFlowGraph, arg: object) -> int:
25432547 "COMPARE_OP" : _convert_compare_op ,
25442548 }
25452549
2546- def instrsize (self , opname : str , oparg : int ) -> int :
2550+ def get_ext_oparg (self , inst : Instruction ) -> int :
2551+ pushed = self .opcode .get_num_pushed (inst .opname , inst .oparg )
2552+ popped = self .opcode .get_num_popped (inst .opname , inst .oparg )
2553+ assert pushed < 4 , pushed
2554+ return popped << 2 | pushed
2555+
2556+ def instrsize (self , instr : Instruction , oparg : int ) -> int :
2557+ opname = instr .opname
25472558 base_size = _inline_cache_entries .get (opname , 0 )
2559+ if opname in STATIC_OPCODES :
2560+ # extended opcode
2561+ base_size += 1
2562+ extoparg = self .get_ext_oparg (instr )
2563+ while extoparg >= 256 :
2564+ extoparg >>= 8
2565+ base_size += 1
2566+
25482567 if oparg <= 0xFF :
25492568 return 1 + base_size
25502569 elif oparg <= 0xFFFF :
@@ -2554,6 +2573,43 @@ def instrsize(self, opname: str, oparg: int) -> int:
25542573 else :
25552574 return 4 + base_size
25562575
2576+ def make_byte_code (self ) -> bytes :
2577+ assert self .stage == FLAT , self .stage
2578+
2579+ code : bytearray = bytearray ()
2580+
2581+ def addCode (opcode : int , oparg : int ) -> None :
2582+ assert opcode < 256 , opcode
2583+ assert oparg < 256 , oparg
2584+ code .append (opcode )
2585+ code .append (oparg )
2586+
2587+ for t in self .insts :
2588+ if t .opname in STATIC_OPCODES :
2589+ extoparg = self .get_ext_oparg (t )
2590+
2591+ if extoparg > 0xFFFFFF :
2592+ addCode (self .opcode .EXTENDED_ARG , (extoparg >> 24 ) & 0xFF )
2593+ if extoparg > 0xFFFF :
2594+ addCode (self .opcode .EXTENDED_ARG , (extoparg >> 16 ) & 0xFF )
2595+ if extoparg > 0xFF :
2596+ addCode (self .opcode .EXTENDED_ARG , (extoparg >> 8 ) & 0xFF )
2597+ addCode (self .opcode .EXTENDED_OPCODE , extoparg & 0xFF )
2598+
2599+ oparg = t .ioparg
2600+ assert 0 <= oparg <= 0xFFFFFFFF , oparg
2601+ if oparg > 0xFFFFFF :
2602+ addCode (self .opcode .EXTENDED_ARG , (oparg >> 24 ) & 0xFF )
2603+ if oparg > 0xFFFF :
2604+ addCode (self .opcode .EXTENDED_ARG , (oparg >> 16 ) & 0xFF )
2605+ if oparg > 0xFF :
2606+ addCode (self .opcode .EXTENDED_ARG , (oparg >> 8 ) & 0xFF )
2607+ addCode (self .opcode .opmap [t .opname ], oparg & 0xFF )
2608+ self .emit_inline_cache (t .opname , addCode )
2609+
2610+ self .stage = DONE
2611+ return bytes (code )
2612+
25572613 def emit_inline_cache (
25582614 self , opcode : str , addCode : Callable [[int , int ], None ]
25592615 ) -> None :
0 commit comments