javaclass

bytecode.py

6:a714f8355910
2004-11-07 Paul Boddie Added label-based jumping (rather than permitting only simple jumping forward to a single point). Added "lazy" dictionary support for the instruction mapping (from Java to Python bytecodes) along with a class which provides the "lazy" value for each case where the value is not known initially but is provided later. Added more bytecode translations and some Python bytecode sequence methods. Fixed the interpretation of various signed values.
     1 #!/usr/bin/env python     2      3 """     4 Java bytecode conversion. Specification found at the following URL:     5 http://java.sun.com/docs/books/vmspec/2nd-edition/html/Instructions2.doc.html     6      7 NOTE: Synchronized constructs are not actually supported.     8 """     9     10 import dis # for access to Python bytecode values    11 from UserDict import UserDict    12     13 # Bytecode production classes.    14     15 class BytecodeWriter:    16     def __init__(self):    17         self.loops = []    18         self.jumps = {}    19         self.output = []    20         self.position = 0    21     22         # Mapping from values to indexes.    23         self.constants = {}    24     25         # Mapping from names to indexes.    26         # NOTE: This may be acquired from elsewhere.    27         self.globals = {}    28     29     def get_output(self):    30         output = []    31         for element in self.output:    32             if isinstance(element, LazyValue):    33                 output.append(chr(element.value))    34             else:    35                 output.append(chr(element))    36         return "".join(output)    37     38     # Special methods.    39     40     def end_loop(self):    41         current_loop_start = self.loops.pop()    42         self.jump_absolute(current_loop_start)    43         self.output[current_loop_start + 1] = self.position    44         self.pop_block()    45     46     def jump_to_label(self, status, name):    47         # Record the instruction using the jump.    48         if not self.jumps.has_key(name):    49             self.jumps[name] = []    50         self.jumps[name].append(self.position)    51         if status is None:    52             self.jump_forward()    53         elif status:    54             self.jump_if_true()    55         else:    56             self.jump_if_false()    57     58     def start_label(self, name):    59         # Fill in all jump instructions.    60         for jump_instruction in self.jumps[name]:    61             self.output[jump_instruction + 1] = self.position    62     63     # Complicated methods.    64     65     def load_const(self, value):    66         self.output.append(opmap["LOAD_CONST"])    67         if not self.constants.has_key(value):    68             self.constants[value] = len(self.constants.keys())    69         self.output.append(self.constants[value])    70     71     def load_global(self, name):    72         self.output.append(opmap["LOAD_GLOBAL"])    73         if not self.globals.has_key(value):    74             self.globals[name] = len(self.globals.keys())    75         self.output.append(self.globals[name])    76     77     def load_fast(self, index):    78         self.output.append(opmap["LOAD_FAST"])    79         self.output.append(index)    80     81     # Normal bytecode generators.    82     83     def for_iter(self):    84         self.loops.push(self.position)    85         self.output.append(opmap["FOR_ITER"])    86         self.output.append(None) # To be filled in later    87         self.position += 2    88     89     def jump_if_false(self, offset=None):    90         self.output.append(opmap["JUMP_IF_FALSE"])    91         self.output.append(offset) # May be filled in later    92         self.position += 2    93     94     def jump_if_true(self, offset=None):    95         self.output.append(opmap["JUMP_IF_TRUE"])    96         self.output.append(offset) # May be filled in later    97         self.position += 2    98     99     def jump_forward(self, offset=None):   100         self.output.append(opmap["JUMP_FORWARD"])   101         self.output.append(offset) # May be filled in later   102         self.position += 2   103    104 # Utility classes and functions.   105    106 class LazyDict(UserDict):   107     def __getitem__(self, key):   108         if not self.data.has_key(key):   109             self.data[key] = LazyValue()   110         return self.data[key]   111     def __setitem__(self, key, value):   112         if self.data.has_key(key):   113             existing_value = self.data[key]   114             if isinstance(existing_value, LazyValue):   115                 existing_value.value = value   116                 return   117         self.data[key] = value   118    119 class LazyValue:   120     def __init__(self, value=None):   121         self.value = value   122    123 def signed(value, limit):   124    125     """   126     Return the signed integer from the unsigned 'value', where 'limit' (a value   127     one greater than the highest possible positive integer) is used to determine   128     whether a negative or positive result is produced.   129     """   130    131     d, r = divmod(value, limit)   132     if d == 1:   133         mask = limit * 2 - 1   134         return -1 - (value ^ mask)   135     else:   136         return value   137    138 def signed2(value):   139     return signed(value, 0x8000)   140    141 def signed4(value):   142     return signed(value, 0x80000000)   143    144 # Bytecode conversion.   145    146 class BytecodeReader:   147     def __init__(self, class_file):   148         self.class_file = class_file   149         self.position_mapping = LazyDict()   150    151     def process(self, code, program):   152         self.java_position = 0   153         while self.java_position < len(code):   154             self.position_mapping[self.java_position] = program.position   155             bytecode = ord(code[self.java_position])   156             mnemonic, number_of_arguments = self.java_bytecodes[bytecode]   157             self.process_bytecode(mnemonic, number_of_arguments)   158    159     def process_bytecode(self, mnemonic, number_of_arguments):   160         if number_of_arguments is not None:   161             arguments = []   162             for j in range(0, number_of_arguments):   163                 arguments.append(ord(code[self.java_position + 1 + j]))   164    165             # Call the handler.   166             getattr(self, mnemonic)(arguments, program)   167         else:   168             # Call the handler.   169             number_of_arguments = getattr(self, mnemonic)(code[self.java_position+1:], program)   170    171         self.java_position = self.java_position + 1 + number_of_arguments   172    173     def nop(self, arguments, program):   174         pass   175    176     def aaload(self, arguments, program):   177         # NOTE: No type checking performed.   178         program.binary_subscr()   179    180     def aastore(self, arguments, program):   181         # NOTE: No type checking performed.   182         # Stack: arrayref, index, value   183         program.rot_three() # Stack: value, arrayref, index   184         program.store_subscr()   185    186     def aconst_null(self, arguments, program):   187         program.load_global(None)   188    189     def aload(self, arguments, program):   190         program.load_fast(arguments[0])   191    192     def aload_0(self, arguments, program):   193         program.load_fast(0)   194    195     def aload_1(self, arguments, program):   196         program.load_fast(1)   197    198     def aload_2(self, arguments, program):   199         program.load_fast(2)   200    201     def aload_3(self, arguments, program):   202         program.load_fast(3)   203    204     def anewarray(self, arguments, program):   205         # NOTE: Does not raise NegativeArraySizeException.   206         # NOTE: Not using the index to type the list/array.   207         index = arguments[0] << 8 + arguments[1]   208    209         program.build_list()        # Stack: count, list   210         program.rot_two()           # Stack: list, count   211         program.setup_loop()   212         program.load_global("range")   213         program.load_const(0)       # Stack: list, count, range, 0   214         program.rot_three()         # Stack: list, 0, count, range   215         program.rot_three()         # Stack: list, range, 0, count   216         program.call_function(2)    # Stack: list, range_list   217         program.get_iter()          # Stack: list, iter   218         program.for_iter()          # Stack: list, iter, value   219         program.pop_top()           # Stack: list, iter   220         program.rot_two()           # Stack: iter, list   221         program.dup_top()           # Stack: iter, list, list   222         program.load_attr("append") # Stack: iter, list, append   223         program.load_global(None)   # Stack: iter, list, append, None   224         program.call_function(1)    # Stack: iter, list, None   225         program.pop_top()           # Stack: iter, list   226         program.rot_two()           # Stack: list, iter   227         program.end_loop()          # Back to for_iter above   228    229     def areturn(self, arguments, program):   230         program.return_value()   231    232     def arraylength(self, arguments, program):   233         program.load_global("len")  # Stack: arrayref, len   234         program.rot_two()           # Stack: len, arrayref   235         program.call_function(1)   236    237     def astore(self, arguments, program):   238         program.store_fast(arguments[0])   239    240     def astore_0(self, arguments, program):   241         program.store_fast(0)   242    243     def astore_1(self, arguments, program):   244         program.store_fast(1)   245    246     def astore_2(self, arguments, program):   247         program.store_fast(2)   248    249     def astore_3(self, arguments, program):   250         program.store_fast(3)   251    252     def athrow(self, arguments, program):   253         # NOTE: NullPointerException not raised where null/None is found on the stack.   254         program.raise_varargs(1)   255    256     baload = aaload   257     bastore = aastore   258    259     def bipush(self, arguments, program):   260         program.load_const(arguments[0])   261    262     caload = aaload   263     castore = aastore   264    265     def checkcast(self, arguments, program):   266         index = arguments[0] << 8 + arguments[1]   267         target_name = self.class_file.constants[index - 1].get_name()   268         target_components = target_name.split("/")   269    270         program.dup_top()                   # Stack: objectref, objectref   271         program.load_global("isinstance")   # Stack: objectref, objectref, isinstance   272         program.rot_two()                   # Stack: objectref, isinstance, objectref   273         program.load_global(target_components[0])   274         for target_component in target_components[1:]:   275             program.load_attr(target_component)   276         program.call_function(2)            # Stack: objectref   277    278     def d2f(self, arguments, program):   279         pass   280    281     def d2i(self, arguments, program):   282         program.load_global("int")  # Stack: value, int   283         program.rot_two()           # Stack: int, value   284         program.call_function(1)    # Stack: result   285    286     d2l = d2i # Preserving Java semantics   287    288     def dadd(self, arguments, program):   289         # NOTE: No type checking performed.   290         program.binary_add()   291    292     daload = aaload   293     dastore = aastore   294    295     def dcmpg(self, arguments, program):   296         # NOTE: No type checking performed.   297         program.compare_op(">")   298    299     def dcmpl(self, arguments, program):   300         # NOTE: No type checking performed.   301         program.compare_op("<")   302    303     def dconst_0(self, arguments, program):   304         program.load_const(0.0)   305    306     def dconst_1(self, arguments, program):   307         program.load_const(1.0)   308    309     def ddiv(self, arguments, program):   310         # NOTE: No type checking performed.   311         program.binary_divide()   312    313     dload = aload   314     dload_0 = aload_0   315     dload_1 = aload_1   316     dload_2 = aload_2   317     dload_3 = aload_3   318    319     def dmul(self, arguments, program):   320         # NOTE: No type checking performed.   321         program.binary_multiply()   322    323     def dneg(self, arguments, program):   324         # NOTE: No type checking performed.   325         program.unary_negative()   326    327     def drem(self, arguments, program):   328         # NOTE: No type checking performed.   329         program.binary_modulo()   330    331     dreturn = areturn   332     dstore = astore   333     dstore_0 = astore_0   334     dstore_1 = astore_1   335     dstore_2 = astore_2   336     dstore_3 = astore_3   337    338     def dsub(self, arguments, program):   339         # NOTE: No type checking performed.   340         program.binary_subtract()   341    342     def dup(self, arguments, program):   343         program.dup_top()   344    345     def dup_x1(self, arguments, program):   346         # Ignoring computational type categories.   347         program.dup_top()   348         program.rot_three()   349    350     def dup_x2(self, arguments, program):   351         # Ignoring computational type categories.   352         program.dup_top()   353         program.rot_four()   354    355     dup2 = dup # Ignoring computational type categories   356     dup2_x1 = dup_x1 # Ignoring computational type categories   357     dup2_x2 = dup_x2 # Ignoring computational type categories   358    359     def f2d(self, arguments, program):   360         pass # Preserving Java semantics   361    362     def f2i(self, arguments, program):   363         program.load_global("int")  # Stack: value, int   364         program.rot_two()           # Stack: int, value   365         program.call_function(1)    # Stack: result   366    367     f2l = f2i # Preserving Java semantics   368     fadd = dadd   369     faload = daload   370     fastore = dastore   371     fcmpg = dcmpg   372     fcmpl = dcmpl   373     fconst_0 = dconst_0   374     fconst_1 = dconst_1   375    376     def fconst_2(self, arguments, program):   377         program.load_const(2.0)   378    379     fdiv = ddiv   380     fload = dload   381     fload_0 = dload_0   382     fload_1 = dload_1   383     fload_2 = dload_2   384     fload_3 = dload_3   385     fmul = dmul   386     fneg = dneg   387     frem = drem   388     freturn = dreturn   389     fstore = dstore   390     fstore_0 = dstore_0   391     fstore_1 = dstore_1   392     fstore_2 = dstore_2   393     fstore_3 = dstore_3   394     fsub = dsub   395    396     def getfield(self, arguments, program):   397         index = arguments[0] << 8 + arguments[1]   398         target_name = self.class_file.constants[index - 1].get_name()   399         # NOTE: Using the string version of the name which may contain incompatible characters.   400         program.load_attr(str(target_name))   401    402     getstatic = getfield # Ignoring Java restrictions   403    404     def goto(self, arguments, program):   405         offset = signed2(arguments[0] << 8 + arguments[1])   406         java_absolute = self.java_position + offset   407         program.jump_absolute(self.position_mapping[java_absolute])   408    409     def goto_w(self, arguments, program):   410         offset = signed4(arguments[0] << 24 + arguments[1] << 16 + arguments[2] << 8 + arguments[3])   411         java_absolute = self.java_position + offset   412         program.jump_absolute(self.position_mapping[java_absolute])   413    414     def i2b(self, arguments, program):   415         pass   416    417     def i2c(self, arguments, program):   418         program.load_global("chr")  # Stack: value, chr   419         program.rot_two()           # Stack: chr, value   420         program.call_function(1)    # Stack: result   421    422     def i2d(self, arguments, program):   423         program.load_global("float")    # Stack: value, float   424         program.rot_two()               # Stack: float, value   425         program.call_function(1)        # Stack: result   426    427     i2f = i2d # Not distinguishing between float and double   428    429     def i2l(self, arguments, program):   430         pass # Preserving Java semantics   431    432     def i2s(self, arguments, program):   433         pass # Not distinguishing between int and short   434    435     iadd = fadd   436     iaload = faload   437    438     def iand(self, arguments, program):   439         # NOTE: No type checking performed.   440         program.binary_and()   441    442     iastore = fastore   443    444     def iconst_m1(self, arguments, program):   445         program.load_const(-1)   446    447     def iconst_0(self, arguments, program):   448         program.load_const(0)   449    450     def iconst_1(self, arguments, program):   451         program.load_const(1)   452    453     def iconst_2(self, arguments, program):   454         program.load_const(2)   455    456     def iconst_3(self, arguments, program):   457         program.load_const(3)   458    459     def iconst_4(self, arguments, program):   460         program.load_const(4)   461    462     def iconst_5(self, arguments, program):   463         program.load_const(5)   464    465     idiv = fdiv   466    467     def _if_xcmpx(self, arguments, program, op):   468         offset = signed2(arguments[0] << 8 + arguments[1])   469         java_absolute = self.java_position + offset   470         program.compare_op(op)   471         program.jump_to_label(0, "next") # skip if false   472         program.goto(offset)   473         program.start_label("next")   474    475     def if_acmpeq(self, arguments, program):   476         # NOTE: No type checking performed.   477         self._if_xcmpx(arguments, program, "is")   478    479     def if_acmpne(self, arguments, program):   480         # NOTE: No type checking performed.   481         self._if_xcmpx(arguments, program, "is not")   482    483     def if_icmpeq(self, arguments, program):   484         # NOTE: No type checking performed.   485         self._if_xcmpx(arguments, program, "==")   486    487     def if_icmpne(self, arguments, program):   488         # NOTE: No type checking performed.   489         self._if_xcmpx(arguments, program, "!=")   490    491     def if_icmplt(self, arguments, program):   492         # NOTE: No type checking performed.   493         self._if_xcmpx(arguments, program, "<")   494    495     def if_icmpge(self, arguments, program):   496         # NOTE: No type checking performed.   497         self._if_xcmpx(arguments, program, ">=")   498    499     def if_icmpgt(self, arguments, program):   500         # NOTE: No type checking performed.   501         self._if_xcmpx(arguments, program, ">")   502    503     def if_icmple(self, arguments, program):   504         # NOTE: No type checking performed.   505         self._if_xcmpx(arguments, program, "<=")   506    507     def ifeq(self, arguments, program):   508         # NOTE: No type checking performed.   509         program.load_const(0)   510         self._if_xcmpx(arguments, program, "==")   511    512     def ifne(self, arguments, program):   513         # NOTE: No type checking performed.   514         program.load_const(0)   515         self._if_xcmpx(arguments, program, "!=")   516    517     def iflt(self, arguments, program):   518         # NOTE: No type checking performed.   519         program.load_const(0)   520         self._if_xcmpx(arguments, program, "<")   521    522     def ifge(self, arguments, program):   523         # NOTE: No type checking performed.   524         program.load_const(0)   525         self._if_xcmpx(arguments, program, ">=")   526    527     def ifgt(self, arguments, program):   528         # NOTE: No type checking performed.   529         program.load_const(0)   530         self._if_xcmpx(arguments, program, ">")   531    532     def ifle(self, arguments, program):   533         # NOTE: No type checking performed.   534         program.load_const(0)   535         self._if_xcmpx(arguments, program, "<=")   536    537     def ifnonnull(self, arguments, program):   538         # NOTE: No type checking performed.   539         program.load_const(None)   540         self._if_xcmpx(arguments, program, "is not")   541    542     def ifnull(self, arguments, program):   543         # NOTE: No type checking performed.   544         program.load_const(None)   545         self._if_xcmpx(arguments, program, "is")   546    547     def iinc(self, arguments, program):   548         # NOTE: No type checking performed.   549         program.load_fast(arguments[0])   550         program.load_const(arguments[1])   551         program.binary_add()   552    553     iload = fload   554     iload_0 = fload_0   555     iload_1 = fload_1   556     iload_2 = fload_2   557     iload_3 = fload_3   558     imul = fmul   559     ineg = fneg   560    561     def instanceof(self, arguments, program):   562         index = arguments[0] << 8 + arguments[1]   563         target_name = self.class_file.constants[index - 1].get_name()   564         target_components = target_name.split("/")   565    566         program.load_global("isinstance")   # Stack: objectref, isinstance   567         program.rot_two()                   # Stack: isinstance, objectref   568         program.load_global(target_components[0])   569         for target_component in target_components[1:]:   570             program.load_attr(target_component)   571         program.call_function(2)            # Stack: result   572    573     def _invoke(self, target_name, program):   574         program.rot_two()                   # Stack: tuple, objectref   575         # NOTE: Using the string version of the name which may contain incompatible characters.   576         program.load_attr(str(target_name)) # Stack: tuple, method   577         program.rot_two()                   # Stack: method, tuple   578         program.load_global("apply")        # Stack: method, tuple, apply   579         program.rot_three()                 # Stack: apply, method, tuple   580         program.call_function(2)   581    582     def invokeinterface(self, arguments, program):   583         # NOTE: This implementation does not perform the necessary checks for   584         # NOTE: signature-based polymorphism.   585         # NOTE: Java rules not specifically obeyed.   586         index = arguments[0] << 8 + arguments[1]   587         count = arguments[2]   588         target_name = self.class_file.constants[index - 1].get_name()   589         # Stack: objectref, arg1, arg2, ...   590         program.build_tuple(count)          # Stack: objectref, tuple   591         self._invoke(target_name, program)   592    593     def invokespecial(self, arguments, program):   594         # NOTE: This implementation does not perform the necessary checks for   595         # NOTE: signature-based polymorphism.   596         # NOTE: Java rules not specifically obeyed.   597         index = arguments[0] << 8 + arguments[1]   598         target = self.class_file.constants[index - 1]   599         target_name = target.get_name()   600         # Get the number of parameters from the descriptor.   601         count = len(target.get_descriptor()[0])   602         # Stack: objectref, arg1, arg2, ...   603         program.build_tuple(count)          # Stack: objectref, tuple   604         self._invoke(target_name, program)   605    606     def invokestatic(self, arguments, program):   607         # NOTE: This implementation does not perform the necessary checks for   608         # NOTE: signature-based polymorphism.   609         # NOTE: Java rules not specifically obeyed.   610         index = arguments[0] << 8 + arguments[1]   611         target = self.class_file.constants[index - 1]   612         target_name = target.get_name()   613         # Get the number of parameters from the descriptor.   614         count = len(target.get_descriptor()[0])   615         # Stack: arg1, arg2, ...   616         program.build_tuple(count)  # Stack: tuple   617         # NOTE: Should probably use Python static methods.   618         program.load_name("self")   # Stack: tuple, self   619         self._invoke(target_name, program)   620    621     invokevirtual = invokeinterface # Ignoring Java rules   622    623     def ior(self, arguments, program):   624         # NOTE: No type checking performed.   625         program.binary_or()   626    627     irem = frem   628     ireturn = freturn   629    630     def ishl(self, arguments, program):   631         # NOTE: No type checking performed.   632         # NOTE: Not verified.   633         program.binary_lshift()   634    635     def ishr(self, arguments, program):   636         # NOTE: No type checking performed.   637         # NOTE: Not verified.   638         program.binary_rshift()   639    640     istore = fstore   641     istore_0 = fstore_0   642     istore_1 = fstore_1   643     istore_2 = fstore_2   644     istore_3 = fstore_3   645     isub = fsub   646     iushr = ishr # Ignoring distinctions between arithmetic and logical shifts   647    648     def ixor(self, arguments, program):   649         # NOTE: No type checking performed.   650         program.binary_xor()   651    652     def jsr(self, arguments, program):   653         offset = signed2(arguments[0] << 8 + arguments[1])   654         java_absolute = self.java_position + offset   655         # Store the address of the next instruction.   656         program.load_const(self.position_mapping[self.java_position + 3])   657         program.jump_absolute(self.position_mapping[java_absolute])   658    659     def jsr_w(self, arguments, program):   660         offset = signed4(arguments[0] << 24 + arguments[1] << 16 + arguments[2] << 8 + arguments[3])   661         java_absolute = self.java_position + offset   662         # Store the address of the next instruction.   663         program.load_const(self.position_mapping[self.java_position + 5])   664         program.jump_absolute(self.position_mapping[java_absolute])   665    666     l2d = i2d   667     l2f = i2f   668    669     def l2i(self, arguments, program):   670         pass # Preserving Java semantics   671    672     ladd = iadd   673     laload = iaload   674     land = iand   675     lastore = iastore   676    677     def lcmp(self, arguments, program):   678         # NOTE: No type checking performed.   679         program.dup_topx(2)                 # Stack: value1, value2, value1, value2   680         program.compare_op(">")             # Stack: value1, value2, result   681         program.jump_to_label(0, "equals")   682         # True - produce result and branch.   683         program.pop_top()                   # Stack: value1, value2   684         program.pop_top()                   # Stack: value1   685         program.pop_top()                   # Stack:   686         program.load_const(1)               # Stack: 1   687         program.jump_to_label(None, "next")   688         # False - test equality.   689         program.start_label("equals")   690         program.pop_top()                   # Stack: value1, value2   691         program.dup_topx(2)                 # Stack: value1, value2, value1, value2   692         program.compare_op("==")            # Stack: value1, value2, result   693         program.jump_to_label(0, "less")   694         # True - produce result and branch.   695         program.pop_top()                   # Stack: value1, value2   696         program.pop_top()                   # Stack: value1   697         program.pop_top()                   # Stack:   698         program.load_const(0)               # Stack: 0   699         program.jump_to_label(None, "next")   700         # False - produce result.   701         program.start_label("less")   702         program.pop_top()                   # Stack: value1, value2   703         program.pop_top()                   # Stack: value1   704         program.pop_top()                   # Stack:   705         program.load_const(-1)              # Stack: -1   706         program.start_label("next")   707    708     lconst_0 = iconst_0   709     lconst_1 = iconst_1   710    711     def ldc(self, arguments, program):   712         program.load_const(self.class_file.constants[arguments[0] - 1])   713    714     def ldc_w(self, arguments, program):   715         program.load_const(self.class_file.constants[arguments[0] << 8 + arguments[1] - 1])   716    717     ldc2_w = ldc_w   718     ldiv = idiv   719     lload = iload   720     lload_0 = iload_0   721     lload_1 = iload_1   722     lload_2 = iload_2   723     lload_3 = iload_3   724     lmul = imul   725     lneg = ineg   726    727     def lookupswitch(self, arguments, program):   728         # Find the offset to the next 4 byte boundary in the code.   729         d, r = divmod(self.java_position, 4)   730         to_boundary = (4 - r) % 4   731         # Get the pertinent arguments.   732         arguments = arguments[to_boundary:]   733         default = arguments[0] << 24 + arguments[1] << 16 + arguments[2] << 8 + arguments[3]   734         npairs = arguments[4] << 24 + arguments[5] << 16 + arguments[6] << 8 + arguments[7]   735         # Process the pairs.   736         # NOTE: This is not the most optimal implementation.   737         pair_index = 8   738         for pair in range(0, npairs):   739             match = (arguments[pair_index] << 24 + arguments[pair_index + 1] << 16 +   740                 arguments[pair_index + 2] << 8 + arguments[pair_index + 3])   741             offset = signed4(arguments[pair_index + 4] << 24 + arguments[pair_index + 5] << 16 +   742                 arguments[pair_index + 6] << 8 + arguments[pair_index + 7])   743             # Calculate the branch target.   744             java_absolute = self.java_position + offset   745             # Generate branching code.   746             program.dup_top()                                           # Stack: key, key   747             program.load_const(match)                                   # Stack: key, key, match   748             program.compare_op("==")                                    # Stack: key, result   749             program.jump_to_label(0, "end" + str(pair))   750             program.pop_top()                                           # Stack: key   751             program.pop_top()                                           # Stack:   752             program.jump_absolute(self.position_mapping[java_absolute])   753             # Generate the label for the end of the branching code.   754             program.start_label("end" + str(pair))   755             program.pop_top()                                           # Stack: key   756             # Update the index.   757             pair_index += 8   758         # Generate the default.   759         java_absolute = self.java_position + default   760         program.jump_absolute(self.position_mapping[java_absolute])   761    762     lor = ior   763     lrem = irem   764     lreturn = ireturn   765     lshl = ishl   766     lshr = ishr   767     lstore = istore   768     lstore_0 = istore_0   769     lstore_1 = istore_1   770     lstore_2 = istore_2   771     lstore_3 = istore_3   772     lsub = isub   773     lushr = iushr   774     lxor = ixor   775    776     def monitorenter(self, arguments, program):   777         # NOTE: To be implemented.   778         pass   779    780     def monitorexit(self, arguments, program):   781         # NOTE: To be implemented.   782         pass   783    784     def multianewarray(self, arguments, program):   785         program.build_list()        # Stack: count1, count2, ..., countN, list   786         program.rot_two()           # Stack: count1, count2, ..., list, countN   787         program.setup_loop()   788         program.load_global("range")   789         program.load_const(0)       # Stack: list, count, range, 0   790         program.rot_three()         # Stack: list, 0, count, range   791         program.rot_three()         # Stack: list, range, 0, count   792         program.call_function(2)    # Stack: list, range_list   793         program.get_iter()          # Stack: list, iter   794         program.for_iter()          # Stack: list, iter, value   795         for i in range(0, arguments[2]):   796                                                 # Stack:    797             self.anewarray(arguments, program)  # Stack: list, iter   798    799     def wide(self, code, program):   800         # NOTE: To be implemented.   801         return number_of_arguments   802    803     java_bytecodes = {   804         # code : (mnemonic, number of following bytes, change in stack)   805         0 : ("nop", 0),   806         1 : ("aconst_null", 0),   807         2 : ("iconst_m1", 0),   808         3 : ("iconst_0", 0),   809         4 : ("iconst_1", 0),   810         5 : ("iconst_2", 0),   811         6 : ("iconst_3", 0),   812         7 : ("iconst_4", 0),   813         8 : ("iconst_5", 0),   814         9 : ("lconst_0", 0),   815         10 : ("lconst_1", 0),   816         11 : ("fconst_0", 0),   817         12 : ("fconst_1", 0),   818         13 : ("fconst_2", 0),   819         14 : ("dconst_0", 0),   820         15 : ("dconst_1", 0),   821         16 : ("bipush", 1),   822         17 : ("sipush", 2),   823         18 : ("ldc", 1),   824         19 : ("ldc_w", 2),   825         20 : ("ldc2_w", 2),   826         21 : ("iload", 1),   827         22 : ("lload", 1),   828         23 : ("fload", 1),   829         24 : ("dload", 1),   830         25 : ("aload", 1),   831         26 : ("iload_0", 0),   832         27 : ("iload_1", 0),   833         28 : ("iload_2", 0),   834         29 : ("iload_3", 0),   835         30 : ("lload_0", 0),   836         31 : ("lload_1", 0),   837         32 : ("lload_2", 0),   838         33 : ("lload_3", 0),   839         34 : ("fload_0", 0),   840         35 : ("fload_1", 0),   841         36 : ("fload_2", 0),   842         37 : ("fload_3", 0),   843         38 : ("dload_0", 0),   844         39 : ("dload_1", 0),   845         40 : ("dload_2", 0),   846         41 : ("dload_3", 0),   847         42 : ("aload_0", 0),   848         43 : ("aload_1", 0),   849         44 : ("aload_2", 0),   850         45 : ("aload_3", 0),   851         46 : ("iaload", 0),   852         47 : ("laload", 0),   853         48 : ("faload", 0),   854         49 : ("daload", 0),   855         50 : ("aaload", 0),   856         51 : ("baload", 0),   857         52 : ("caload", 0),   858         53 : ("saload", 0),   859         54 : ("istore", 1),   860         55 : ("lstore", 1),   861         56 : ("fstore", 1),   862         57 : ("dstore", 1),   863         58 : ("astore", 1),   864         59 : ("istore_0", 0),   865         60 : ("istore_1", 0),   866         61 : ("istore_2", 0),   867         62 : ("istore_3", 0),   868         63 : ("lstore_0", 0),   869         64 : ("lstore_1", 0),   870         65 : ("lstore_2", 0),   871         66 : ("lstore_3", 0),   872         67 : ("fstore_0", 0),   873         68 : ("fstore_1", 0),   874         69 : ("fstore_2", 0),   875         70 : ("fstore_3", 0),   876         71 : ("dstore_0", 0),   877         72 : ("dstore_1", 0),   878         73 : ("dstore_2", 0),   879         74 : ("dstore_3", 0),   880         75 : ("astore_0", 0),   881         76 : ("astore_1", 0),   882         77 : ("astore_2", 0),   883         78 : ("astore_3", 0),   884         79 : ("iastore", 0),   885         80 : ("lastore", 0),   886         81 : ("fastore", 0),   887         82 : ("dastore", 0),   888         83 : ("aastore", 0),   889         84 : ("bastore", 0),   890         85 : ("castore", 0),   891         86 : ("sastore", 0),   892         87 : ("pop", 0),   893         88 : ("pop2", 0),   894         89 : ("dup", 0),   895         90 : ("dup_x1", 0),   896         91 : ("dup_x2", 0),   897         92 : ("dup2", 0),   898         93 : ("dup2_x1", 0),   899         94 : ("dup2_x2", 0),   900         95 : ("swap", 0),   901         96 : ("iadd", 0),   902         97 : ("ladd", 0),   903         98 : ("fadd", 0),   904         99 : ("dadd", 0),   905         100 : ("isub", 0),   906         101 : ("lsub", 0),   907         102 : ("fsub", 0),   908         103 : ("dsub", 0),   909         104 : ("imul", 0),   910         105 : ("lmul", 0),   911         106 : ("fmul", 0),   912         107 : ("dmul", 0),   913         108 : ("idiv", 0),   914         109 : ("ldiv", 0),   915         110 : ("fdiv", 0),   916         111 : ("ddiv", 0),   917         112 : ("irem", 0),   918         113 : ("lrem", 0),   919         114 : ("frem", 0),   920         115 : ("drem", 0),   921         116 : ("ineg", 0),   922         117 : ("lneg", 0),   923         118 : ("fneg", 0),   924         119 : ("dneg", 0),   925         120 : ("ishl", 0),   926         121 : ("lshl", 0),   927         122 : ("ishr", 0),   928         123 : ("lshr", 0),   929         124 : ("iushr", 0),   930         125 : ("lushr", 0),   931         126 : ("iand", 0),   932         127 : ("land", 0),   933         128 : ("ior", 0),   934         129 : ("lor", 0),   935         130 : ("ixor", 0),   936         131 : ("lxor", 0),   937         132 : ("iinc", 2),   938         133 : ("i2l", 0),   939         134 : ("i2f", 0),   940         135 : ("i2d", 0),   941         136 : ("l2i", 0),   942         137 : ("l2f", 0),   943         138 : ("l2d", 0),   944         139 : ("f2i", 0),   945         140 : ("f2l", 0),   946         141 : ("f2d", 0),   947         142 : ("d2i", 0),   948         143 : ("d2l", 0),   949         144 : ("d2f", 0),   950         145 : ("i2b", 0),   951         146 : ("i2c", 0),   952         147 : ("i2s", 0),   953         148 : ("lcmp", 0),   954         149 : ("fcmpl", 0),   955         150 : ("fcmpg", 0),   956         151 : ("dcmpl", 0),   957         152 : ("dcmpg", 0),   958         153 : ("ifeq", 2),   959         154 : ("ifne", 2),   960         155 : ("iflt", 2),   961         156 : ("ifge", 2),   962         157 : ("ifgt", 2),   963         158 : ("ifle", 2),   964         159 : ("if_icmpeq", 2),   965         160 : ("if_icmpne", 2),   966         161 : ("if_icmplt", 2),   967         162 : ("if_icmpge", 2),   968         163 : ("if_icmpgt", 2),   969         164 : ("if_icmple", 2),   970         165 : ("if_acmpeq", 2),   971         166 : ("if_acmpne", 2),   972         167 : ("goto", 2),   973         168 : ("jsr", 2),   974         169 : ("ret", 1),   975         170 : ("tableswitch", None), # variable number of arguments   976         171 : ("lookupswitch", None), # variable number of arguments   977         172 : ("ireturn", 0),   978         173 : ("lreturn", 0),   979         174 : ("freturn", 0),   980         175 : ("dreturn", 0),   981         176 : ("areturn", 0),   982         177 : ("return", 0),   983         178 : ("getstatic", 2),   984         179 : ("putstatic", 2),   985         180 : ("getfield", 2),   986         181 : ("putfield", 2),   987         182 : ("invokevirtual", 2),   988         183 : ("invokespecial", 2),   989         184 : ("invokestatic", 2),   990         185 : ("invokeinterface", 4),   991         187 : ("new", 2),   992         188 : ("newarray", 1),   993         189 : ("anewarray", 2),   994         190 : ("arraylength", 0),   995         191 : ("athrow", 0),   996         192 : ("checkcast", 2),   997         193 : ("instanceof", 2),   998         194 : ("monitorenter", 0),   999         195 : ("monitorexit", 0),  1000         196 : ("wide", None), # 3 or 5 arguments, stack changes according to modified element  1001         197 : ("multianewarray", 3),  1002         198 : ("ifnull", 2),  1003         199 : ("ifnonnull", 2),  1004         200 : ("goto_w", 4),  1005         201 : ("jsr_w", 4),  1006         }  1007   1008 if __name__ == "__main__":  1009     import sys  1010     from classfile import ClassFile  1011     f = open(sys.argv[1])  1012     c = ClassFile(f.read())  1013   1014 # vim: tabstop=4 expandtab shiftwidth=4