1111import six
1212from six .moves import reprlib
1313
14- from xdis import PYTHON3 , PYTHON_VERSION
14+ from xdis import PYTHON3 , PYTHON_VERSION , instruction_size , op_has_argument
15+ from xdis .util import code2num
1516from xdis .op_imports import get_opcode_module
1617
1718from xpython .pyobj import Frame , Block , Function , Generator
@@ -56,6 +57,7 @@ def __init__(self, python_version=PYTHON_VERSION):
5657 int_vers = int (python_version * 10 )
5758 version_info = (int_vers // 10 , int_vers % 10 )
5859 self .opc = get_opcode_module (version_info )
60+ self .extended_arg_size = instruction_size (self .opc .EXTENDED_ARG , self .opc )
5961 if int_vers < 30 :
6062 if int_vers == 27 :
6163 from xpython .byteop .byteop27 import ByteOp27
@@ -64,36 +66,20 @@ def __init__(self, python_version=PYTHON_VERSION):
6466 from xpython .byteop .byteop26 import ByteOp26
6567 self .byteop = ByteOp26 (self )
6668 pass
67- elif int_vers == 25 :
68- from xpython .byteop .byteop25 import ByteOp25
69- self .byteop = ByteOp25 (self )
70- pass
71- else :
72- raise RuntimeError ("Version %s not supported yet" % python_version )
7369 pass
7470 else :
7571 # 3.0 or greater
76- if int_vers >= 34 :
77- if int_vers == 34 :
78- from xpython .byteop .byteop34 import ByteOp34
79- self .byteop = ByteOp34 (self )
80- elif int_vers == 35 :
81- from xpython .byteop .byteop35 import ByteOp35
82- self .byteop = ByteOp35 (self )
83- pass
84- else :
85- raise RuntimeError ("Version %s not supported yet" % python_version )
86- pass
72+ if int_vers == 33 :
73+ from xpython .byteop .byteop33 import ByteOp33
74+ self .byteop = ByteOp33 (self )
75+ elif int_vers == 34 :
76+ from xpython .byteop .byteop34 import ByteOp34
77+ self .byteop = ByteOp34 (self )
78+ elif int_vers == 35 :
79+ from xpython .byteop .byteop35 import ByteOp35
80+ self .byteop = ByteOp35 (self )
8781 else :
88- if int_vers == 32 :
89- from xpython .byteop .byteop32 import ByteOp32
90- self .byteop = ByteOp32 (self )
91- elif int_vers == 33 :
92- from xpython .byteop .byteop33 import ByteOp33
93- self .byteop = ByteOp33 (self )
94- else :
95- raise RuntimeError ("Version %s not supported yet" % python_version )
96-
82+ self .byteop = None
9783
9884 def top (self ):
9985 """Return the value at the top of the stack, with no changes."""
@@ -216,39 +202,61 @@ def unwind_block(self, block):
216202 def parse_byte_and_args (self ):
217203 """ Parse 1 - 3 bytes of bytecode into
218204 an instruction and optionally arguments."""
205+
219206 f = self .frame
220- opoffset = f .f_lasti
221- line_number = self .linestarts .get (opoffset , None )
222207 f_code = f .f_code
223208 co_code = f_code .co_code
224- byteCode = byteint (co_code [opoffset ])
225- f .f_lasti += 1
226- byteName = self .opc .opname [byteCode ]
227- arg = None
228- arguments = []
229- if byteCode >= self .opc .HAVE_ARGUMENT :
230- arg = co_code [f .f_lasti : f .f_lasti + 2 ]
231- f .f_lasti += 2
232- intArg = byteint (arg [0 ]) + (byteint (arg [1 ]) << 8 )
233- if byteCode in self .opc .CONST_OPS :
234- arg = f_code .co_consts [intArg ]
235- elif byteCode in self .opc .FREE_OPS :
236- if intArg < len (f_code .co_cellvars ):
237- arg = f_code .co_cellvars [intArg ]
209+ extended_arg = 0
210+
211+ while True :
212+ opoffset = f .f_lasti
213+ line_number = self .linestarts .get (opoffset , None )
214+ byteCode = byteint (co_code [opoffset ])
215+ byteName = self .opc .opname [byteCode ]
216+ f .f_lasti += 1
217+ arg = None
218+ arguments = []
219+ if op_has_argument (byteCode , self .opc ):
220+ if PYTHON_VERSION >= 3.6 :
221+ intArg = code2num (co_code , f .f_lasti ) | extended_arg
222+ # Note: Python 3.6.0a1 is 2, for 3.6.a3 and beyond we have 1
223+ f .f_lasti += 1
224+ if byteCode == self .opc .EXTENDED_ARG :
225+ extended_arg = (intArg << 8 )
226+ continue
227+ else :
228+ extended_arg = 0
238229 else :
239- var_idx = intArg - len (f .f_code .co_cellvars )
240- arg = f_code .co_freevars [var_idx ]
241- elif byteCode in self .opc .NAME_OPS :
242- arg = f_code .co_names [intArg ]
243- elif byteCode in self .opc .JREL_OPS :
244- arg = f .f_lasti + intArg
245- elif byteCode in self .opc .JABS_OPS :
246- arg = intArg
247- elif byteCode in self .opc .LOCAL_OPS :
248- arg = f_code .co_varnames [intArg ]
249- else :
250- arg = intArg
251- arguments = [arg ]
230+ intArg = code2num (co_code , f .f_lasti ) + code2num (co_code , f .f_lasti + 1 )* 256 + extended_arg
231+ f .f_lasti += 2
232+ if byteCode == self .opc .EXTENDED_ARG :
233+ extended_arg = intArg * 65536
234+ continue
235+ else :
236+ extended_arg = 0
237+
238+ if byteCode in self .opc .CONST_OPS :
239+ arg = f_code .co_consts [intArg ]
240+ elif byteCode in self .opc .FREE_OPS :
241+ if intArg < len (f_code .co_cellvars ):
242+ arg = f_code .co_cellvars [intArg ]
243+ else :
244+ var_idx = intArg - len (f .f_code .co_cellvars )
245+ arg = f_code .co_freevars [var_idx ]
246+ elif byteCode in self .opc .NAME_OPS :
247+ arg = f_code .co_names [intArg ]
248+ elif byteCode in self .opc .JREL_OPS :
249+ arg = f .f_lasti + intArg
250+ elif byteCode in self .opc .JABS_OPS :
251+ arg = intArg
252+ elif byteCode in self .opc .LOCAL_OPS :
253+ arg = f_code .co_varnames [intArg ]
254+ else :
255+ arg = intArg
256+ arguments = [arg ]
257+ elif PYTHON_VERSION >= 3.6 :
258+ f .f_lasti += 1
259+ break
252260
253261 return byteName , arguments , opoffset , line_number
254262
@@ -420,7 +428,7 @@ def run_frame(self, frame):
420428 self .pop_frame ()
421429
422430 if why == "exception" :
423- if self .last_exception :
431+ if self .last_exception and self . last_exception [ 0 ] :
424432 six .reraise (* self .last_exception )
425433 else :
426434 raise VirtualMachineError ("Borked exception recording" )
@@ -716,7 +724,7 @@ def byte_SETUP_WITH(self, dest):
716724 ## Functions
717725
718726 def byte_MAKE_CLOSURE (self , argc ):
719- if PYTHON_VERSION >= 3.3 :
727+ if PYTHON3 :
720728 # TODO: the py3 docs don't mention this change.
721729 name = self .pop ()
722730 else :
0 commit comments