javaclass

bytecode.py

11:4184dc282002
2004-11-09 Paul Boddie Added supposedly improved exception handling in order to use Python VM features. The problem is that the JVM athrow instruction is dynamic and best translates to the Python VM RAISE_VARARGS instruction. However, in order to support RAISE_VARARGS, the SETUP_EXCEPT, SETUP_FINALLY, POP_BLOCK and END_FINALLY instructions are also required, yet the JVM supports try... catch...finally (whereas the Python VM only supports try...except and try...finally), and anticipates finally handling using very low-level subroutine calling and arcane usage of local variables. Changed the result of the translate convenience function and the parameter specification of the translate and disassemble functions. Fixed the get_value method in LazySubValue and the LazyValue portion of the _write_value method in BytecodeWriter.
     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 from dis import opmap, cmp_op # for access to Python bytecode values and operators    11 from UserDict import UserDict    12     13 # Bytecode production classes.    14     15 class BytecodeWriter:    16     17     "A Python bytecode writer."    18     19     def __init__(self):    20         # A stack of loop block or exception block start positions.    21         self.blocks = []    22     23         # A stack of exception block handler pointers.    24         self.exception_handlers = []    25     26         # A dictionary mapping labels to jump instructions referencing such labels.    27         self.jumps = {}    28     29         # The output values, including "lazy" subvalues which will need evaluating.    30         self.output = []    31     32         # The current Python bytecode instruction position.    33         self.position = 0    34     35         # Stack depth estimation.    36         self.stack_depth = 0    37         self.max_stack_depth = 0    38     39         # Mapping from values to indexes.    40         self.constants = {}    41     42         # Mapping from names to indexes.    43         # NOTE: This may be acquired from elsewhere.    44         #self.globals = {}    45     46         # Mapping from names to indexes.    47         self.names = {}    48     49         # A list of constants used as exception handler return addresses.    50         self.constants_for_exceptions = []    51     52     def get_output(self):    53         output = []    54         for element in self.output:    55             if isinstance(element, LazySubValue):    56                 value = element.value    57             else:    58                 value = element    59             output.append(chr(value))    60         return "".join(output)    61     62     def get_constants(self):    63         l = self._get_list(self._invert(self.constants))    64         result = []    65         for i in l:    66             if isinstance(i, LazyValue):    67                 result.append(i.get_value())    68             else:    69                 result.append(i)    70         return result    71     72     #def get_globals(self):    73     #    return self._get_list(self._invert(self.globals))    74     75     def get_names(self):    76         return self._get_list(self._invert(self.names))    77     78     def _invert(self, d):    79         inverted = {}    80         for k, v in d.items():    81             inverted[v] = k    82         return inverted    83     84     def _get_list(self, d):    85         l = []    86         for i in range(0, len(d.keys())):    87             l.append(d[i])    88         return l    89     90     # Administrative methods.    91     92     def update_stack_depth(self, change):    93         self.stack_depth += change    94         if self.stack_depth > self.max_stack_depth:    95             self.max_stack_depth = self.stack_depth    96     97     # Special methods.    98     99     def _write_value(self, value):   100         if isinstance(value, LazyValue):   101             # NOTE: Assume a 16-bit value.   102             self.output.append(value.values[0])   103             self.output.append(value.values[1])   104             self.position += 2   105         elif value <= 0xffff:   106             self.output.append(value & 0xff)   107             self.output.append((value & 0xff00) >> 8)   108             self.position += 2   109         else:   110             # NOTE: EXTENDED_ARG not yet supported.   111             raise ValueError, value   112    113     def setup_loop(self):   114         self.blocks.append(self.position)   115         self.output.append(opmap["SETUP_LOOP"])   116         self.position += 1   117         self._write_value(0) # To be filled in later   118    119     def end_loop(self):   120         current_loop_start = self.blocks.pop()   121         self.jump_absolute(current_loop_start)   122         # NOTE: Using 3 as the assumed length of the SETUP_LOOP instruction.   123         # NOTE: 8-bit limit.   124         self.output[current_loop_start + 1] = self.position - current_loop_start - 3   125         self.output[current_loop_start + 2] = 0   126         self.pop_block()   127    128     def jump_to_label(self, status, name):   129         # Record the instruction using the jump.   130         jump_instruction = self.position   131         if status is None:   132             self.jump_forward()   133         elif status:   134             self.jump_if_true()   135         else:   136             self.jump_if_false()   137         # Record the following instruction, too.   138         if not self.jumps.has_key(name):   139             self.jumps[name] = []   140         self.jumps[name].append((jump_instruction, self.position))   141    142     def start_label(self, name):   143         # Fill in all jump instructions.   144         for jump_instruction, following_instruction in self.jumps[name]:   145             # NOTE: 8-bit limit.   146             self.output[jump_instruction + 1] = self.position - following_instruction   147             self.output[jump_instruction + 2] = 0   148         del self.jumps[name]   149    150     def load_const_ret(self, value):   151         self.constants_for_exceptions.append(value)   152         self.load_const(value)   153    154     def ret(self, index):   155         self.end_finally()   156    157     def setup_except(self, target):   158         self.blocks.append(self.position)   159         self.exception_handlers.append(target)   160         self.output.append(opmap["SETUP_EXCEPT"])   161         self.position += 1   162         self._write_value(0) # To be filled in later   163    164     def setup_finally(self, target):   165         self.blocks.append(self.position)   166         self.exception_handlers.append(target)   167         self.output.append(opmap["SETUP_FINALLY"])   168         self.position += 1   169         self._write_value(0) # To be filled in later   170    171     def end_exception(self):   172         current_exception_start = self.blocks.pop()   173         # Convert the "lazy" absolute value.   174         current_exception_target = self.exception_handlers.pop()   175         target = current_exception_target.get_value()   176         # NOTE: Using 3 as the assumed length of the SETUP_* instruction.   177         # NOTE: 8-bit limit.   178         self.output[current_exception_start + 1] = target - current_exception_start - 3   179         self.output[current_exception_start + 2] = 0   180         # NOTE: The POP_BLOCK instruction gets slipped in before this method is called.   181    182     # Complicated methods.   183    184     def load_const(self, value):   185         self.output.append(opmap["LOAD_CONST"])   186         if not self.constants.has_key(value):   187             self.constants[value] = len(self.constants.keys())   188         self.position += 1   189         self._write_value(self.constants[value])   190         self.update_stack_depth(1)   191    192     def load_global(self, name):   193         self.output.append(opmap["LOAD_GLOBAL"])   194         if not self.names.has_key(name):   195             self.names[name] = len(self.names.keys())   196         self.position += 1   197         self._write_value(self.names[name])   198         self.update_stack_depth(1)   199    200     def load_attr(self, name):   201         self.output.append(opmap["LOAD_ATTR"])   202         if not self.names.has_key(name):   203             self.names[name] = len(self.names.keys())   204         self.position += 1   205         self._write_value(self.names[name])   206    207     def load_name(self, name):   208         self.output.append(opmap["LOAD_NAME"])   209         if not self.names.has_key(name):   210             self.names[name] = len(self.names.keys())   211         self.position += 1   212         self._write_value(self.names[name])   213         self.update_stack_depth(1)   214    215     def load_fast(self, index):   216         self.output.append(opmap["LOAD_FAST"])   217         self.position += 1   218         self._write_value(index)   219         self.update_stack_depth(1)   220    221     def store_attr(self, name):   222         self.output.append(opmap["STORE_ATTR"])   223         if not self.names.has_key(name):   224             self.names[name] = len(self.names.keys())   225         self.position += 1   226         self._write_value(self.names[name])   227         self.update_stack_depth(-1)   228    229     def store_fast(self, index):   230         self.output.append(opmap["STORE_FAST"])   231         self.position += 1   232         self._write_value(index)   233         self.update_stack_depth(-1)   234    235     # Normal bytecode generators.   236    237     def for_iter(self):   238         self.blocks.append(self.position)   239         self.output.append(opmap["FOR_ITER"])   240         self.position += 1   241         self._write_value(0) # To be filled in later   242         self.update_stack_depth(1)   243    244     def jump_if_false(self, offset=0):   245         self.output.append(opmap["JUMP_IF_FALSE"])   246         self.position += 1   247         self._write_value(offset) # May be filled in later   248    249     def jump_if_true(self, offset=0):   250         self.output.append(opmap["JUMP_IF_TRUE"])   251         self.position += 1   252         self._write_value(offset) # May be filled in later   253    254     def jump_forward(self, offset=0):   255         self.output.append(opmap["JUMP_FORWARD"])   256         self.position += 1   257         self._write_value(offset) # May be filled in later   258    259     def jump_absolute(self, address=0):   260         self.output.append(opmap["JUMP_ABSOLUTE"])   261         self.position += 1   262         self._write_value(address) # May be filled in later   263    264     def build_tuple(self, count):   265         self.output.append(opmap["BUILD_TUPLE"])   266         self.position += 1   267         self._write_value(count)   268         self.update_stack_depth(-(count - 1))   269    270     def build_list(self, count):   271         self.output.append(opmap["BUILD_LIST"])   272         self.position += 1   273         self._write_value(count)   274         self.update_stack_depth(-(count - 1))   275    276     def pop_top(self):   277         self.output.append(opmap["POP_TOP"])   278         self.position += 1   279         self.update_stack_depth(-1)   280    281     def dup_top(self):   282         self.output.append(opmap["DUP_TOP"])   283         self.position += 1   284         self.update_stack_depth(1)   285    286     def rot_two(self):   287         self.output.append(opmap["ROT_TWO"])   288         self.position += 1   289    290     def rot_three(self):   291         self.output.append(opmap["ROT_THREE"])   292         self.position += 1   293    294     def rot_four(self):   295         self.output.append(opmap["ROT_FOUR"])   296         self.position += 1   297    298     def call_function(self, count):   299         self.output.append(opmap["CALL_FUNCTION"])   300         self.position += 1   301         self._write_value(count)   302         self.update_stack_depth(-count)   303    304     def binary_subscr(self):   305         self.output.append(opmap["BINARY_SUBSCR"])   306         self.position += 1   307         self.update_stack_depth(-1)   308    309     def binary_add(self):   310         self.output.append(opmap["BINARY_ADD"])   311         self.position += 1   312         self.update_stack_depth(-1)   313    314     def binary_divide(self):   315         self.output.append(opmap["BINARY_DIVIDE"])   316         self.position += 1   317         self.update_stack_depth(-1)   318    319     def binary_multiply(self):   320         self.output.append(opmap["BINARY_MULTIPLY"])   321         self.position += 1   322         self.update_stack_depth(-1)   323    324     def binary_modulo(self):   325         self.output.append(opmap["BINARY_MODULO"])   326         self.position += 1   327         self.update_stack_depth(-1)   328    329     def binary_subtract(self):   330         self.output.append(opmap["BINARY_SUBTRACT"])   331         self.position += 1   332         self.update_stack_depth(-1)   333    334     def binary_and(self):   335         self.output.append(opmap["BINARY_AND"])   336         self.position += 1   337         self.update_stack_depth(-1)   338    339     def binary_or(self):   340         self.output.append(opmap["BINARY_XOR"])   341         self.position += 1   342         self.update_stack_depth(-1)   343    344     def binary_lshift(self):   345         self.output.append(opmap["BINARY_LSHIFT"])   346         self.position += 1   347         self.update_stack_depth(-1)   348    349     def binary_rshift(self):   350         self.output.append(opmap["BINARY_RSHIFT"])   351         self.position += 1   352         self.update_stack_depth(-1)   353    354     def binary_xor(self):   355         self.output.append(opmap["BINARY_XOR"])   356         self.position += 1   357         self.update_stack_depth(-1)   358    359     def compare_op(self, op):   360         self.output.append(opmap["COMPARE_OP"])   361         self.position += 1   362         self._write_value(list(cmp_op).index(op))   363         self.update_stack_depth(-1)   364    365     def return_value(self):   366         self.output.append(opmap["RETURN_VALUE"])   367         self.position += 1   368         self.update_stack_depth(-1)   369    370     def raise_varargs(self, count):   371         self.output.append(opmap["RAISE_VARARGS"])   372         self.position += 1   373         self._write_value(count)   374    375     def pop_block(self):   376         self.output.append(opmap["POP_BLOCK"])   377         self.position += 1   378    379     def end_finally(self):   380         self.output.append(opmap["END_FINALLY"])   381         self.position += 1   382    383 # Utility classes and functions.   384    385 class LazyDict(UserDict):   386     def __getitem__(self, key):   387         if not self.data.has_key(key):   388             # NOTE: Assume 16-bit value.   389             self.data[key] = LazyValue(2)   390         return self.data[key]   391     def __setitem__(self, key, value):   392         if self.data.has_key(key):   393             existing_value = self.data[key]   394             if isinstance(existing_value, LazyValue):   395                 existing_value.set_value(value)   396                 return   397         self.data[key] = value   398    399 class LazyValue:   400     def __init__(self, nvalues):   401         self.values = []   402         for i in range(0, nvalues):   403             self.values.append(LazySubValue())   404     def set_value(self, value):   405         # NOTE: Assume at least 16-bit value. No "filling" performed.   406         if value <= 0xffff:   407             self.values[0].set_value(value & 0xff)   408             self.values[1].set_value((value & 0xff00) >> 8)   409         else:   410             # NOTE: EXTENDED_ARG not yet supported.   411             raise ValueError, value   412     def get_value(self):   413         value = 0   414         values = self.values[:]   415         for i in range(0, len(values)):   416             value = (value << 8) + values.pop().value   417         return value   418    419 class LazySubValue:   420     def __init__(self):   421         self.value = 0   422     def set_value(self, value):   423         self.value = value   424    425 def signed(value, limit):   426    427     """   428     Return the signed integer from the unsigned 'value', where 'limit' (a value   429     one greater than the highest possible positive integer) is used to determine   430     whether a negative or positive result is produced.   431     """   432    433     d, r = divmod(value, limit)   434     if d == 1:   435         mask = limit * 2 - 1   436         return -1 - (value ^ mask)   437     else:   438         return value   439    440 def signed2(value):   441     return signed(value, 0x8000)   442    443 def signed4(value):   444     return signed(value, 0x80000000)   445    446 # Bytecode conversion.   447    448 class BytecodeReader:   449    450     "A generic Java bytecode reader."   451    452     def __init__(self, class_file):   453         self.class_file = class_file   454         self.position_mapping = LazyDict()   455    456     def process(self, code, exception_table, program):   457         self.java_position = 0   458    459         # Produce a structure which permits fast access to exception details.   460         exception_block_start = {}   461         exception_block_end = {}   462         exception_block_handler = {}   463         reversed_exception_table = exception_table[:]   464         reversed_exception_table.reverse()   465    466         # Later entries have wider coverage than earlier entries.   467         for exception in reversed_exception_table:   468             # Index start positions.   469             if not exception_block_start.has_key(exception.start_pc):   470                 exception_block_start[exception.start_pc] = []   471             exception_block_start[exception.start_pc].append(exception)   472             # Index end positions.   473             if not exception_block_end.has_key(exception.end_pc):   474                 exception_block_end[exception.end_pc] = []   475             exception_block_end[exception.end_pc].append(exception)   476             # Index handler positions.   477             if not exception_block_handler.has_key(exception.handler_pc):   478                 exception_block_handler[exception.handler_pc] = []   479             exception_block_handler[exception.handler_pc].append(exception)   480    481         # Process each instruction in the code.   482         while self.java_position < len(code):   483             self.position_mapping[self.java_position] = program.position   484    485             # Insert exception handling constructs.   486             for exception in exception_block_start.get(self.java_position, []):   487                 # Note that the absolute position is used.   488                 if exception.catch_type == 0:   489                     program.setup_finally(self.position_mapping[exception.handler_pc])   490                 else:   491                     program.setup_except(self.position_mapping[exception.handler_pc])   492    493             # Insert exception handler end details.   494             for exception in exception_block_end.get(self.java_position, []):   495                 program.end_exception()   496    497             # Where handlers are begun, do not produce equivalent bytecode since   498             # the first handler instruction typically involves saving a local   499             # variable that is not applicable to the Python VM.   500             #if not exception_block_handler.get(self.java_position, []):   501    502             # Process the bytecode at the current position.   503             bytecode = ord(code[self.java_position])   504             mnemonic, number_of_arguments = self.java_bytecodes[bytecode]   505             number_of_arguments = self.process_bytecode(mnemonic, number_of_arguments, code, program)   506             next_java_position = self.java_position + 1 + number_of_arguments   507    508             # Insert exception handler end instructions.   509             for exception in exception_block_end.get(next_java_position, []):   510                 program.pop_block()   511    512             # Only advance the JVM position after sneaking in extra Python   513             # instructions.   514             self.java_position = next_java_position   515    516     def process_bytecode(self, mnemonic, number_of_arguments, code, program):   517         if number_of_arguments is not None:   518             arguments = []   519             for j in range(0, number_of_arguments):   520                 arguments.append(ord(code[self.java_position + 1 + j]))   521    522             # Call the handler.   523             getattr(self, mnemonic)(arguments, program)   524             return number_of_arguments   525         else:   526             # Call the handler.   527             return getattr(self, mnemonic)(code[self.java_position+1:], program)   528    529     java_bytecodes = {   530         # code : (mnemonic, number of following bytes, change in stack)   531         0 : ("nop", 0),   532         1 : ("aconst_null", 0),   533         2 : ("iconst_m1", 0),   534         3 : ("iconst_0", 0),   535         4 : ("iconst_1", 0),   536         5 : ("iconst_2", 0),   537         6 : ("iconst_3", 0),   538         7 : ("iconst_4", 0),   539         8 : ("iconst_5", 0),   540         9 : ("lconst_0", 0),   541         10 : ("lconst_1", 0),   542         11 : ("fconst_0", 0),   543         12 : ("fconst_1", 0),   544         13 : ("fconst_2", 0),   545         14 : ("dconst_0", 0),   546         15 : ("dconst_1", 0),   547         16 : ("bipush", 1),   548         17 : ("sipush", 2),   549         18 : ("ldc", 1),   550         19 : ("ldc_w", 2),   551         20 : ("ldc2_w", 2),   552         21 : ("iload", 1),   553         22 : ("lload", 1),   554         23 : ("fload", 1),   555         24 : ("dload", 1),   556         25 : ("aload", 1),   557         26 : ("iload_0", 0),   558         27 : ("iload_1", 0),   559         28 : ("iload_2", 0),   560         29 : ("iload_3", 0),   561         30 : ("lload_0", 0),   562         31 : ("lload_1", 0),   563         32 : ("lload_2", 0),   564         33 : ("lload_3", 0),   565         34 : ("fload_0", 0),   566         35 : ("fload_1", 0),   567         36 : ("fload_2", 0),   568         37 : ("fload_3", 0),   569         38 : ("dload_0", 0),   570         39 : ("dload_1", 0),   571         40 : ("dload_2", 0),   572         41 : ("dload_3", 0),   573         42 : ("aload_0", 0),   574         43 : ("aload_1", 0),   575         44 : ("aload_2", 0),   576         45 : ("aload_3", 0),   577         46 : ("iaload", 0),   578         47 : ("laload", 0),   579         48 : ("faload", 0),   580         49 : ("daload", 0),   581         50 : ("aaload", 0),   582         51 : ("baload", 0),   583         52 : ("caload", 0),   584         53 : ("saload", 0),   585         54 : ("istore", 1),   586         55 : ("lstore", 1),   587         56 : ("fstore", 1),   588         57 : ("dstore", 1),   589         58 : ("astore", 1),   590         59 : ("istore_0", 0),   591         60 : ("istore_1", 0),   592         61 : ("istore_2", 0),   593         62 : ("istore_3", 0),   594         63 : ("lstore_0", 0),   595         64 : ("lstore_1", 0),   596         65 : ("lstore_2", 0),   597         66 : ("lstore_3", 0),   598         67 : ("fstore_0", 0),   599         68 : ("fstore_1", 0),   600         69 : ("fstore_2", 0),   601         70 : ("fstore_3", 0),   602         71 : ("dstore_0", 0),   603         72 : ("dstore_1", 0),   604         73 : ("dstore_2", 0),   605         74 : ("dstore_3", 0),   606         75 : ("astore_0", 0),   607         76 : ("astore_1", 0),   608         77 : ("astore_2", 0),   609         78 : ("astore_3", 0),   610         79 : ("iastore", 0),   611         80 : ("lastore", 0),   612         81 : ("fastore", 0),   613         82 : ("dastore", 0),   614         83 : ("aastore", 0),   615         84 : ("bastore", 0),   616         85 : ("castore", 0),   617         86 : ("sastore", 0),   618         87 : ("pop", 0),   619         88 : ("pop2", 0),   620         89 : ("dup", 0),   621         90 : ("dup_x1", 0),   622         91 : ("dup_x2", 0),   623         92 : ("dup2", 0),   624         93 : ("dup2_x1", 0),   625         94 : ("dup2_x2", 0),   626         95 : ("swap", 0),   627         96 : ("iadd", 0),   628         97 : ("ladd", 0),   629         98 : ("fadd", 0),   630         99 : ("dadd", 0),   631         100 : ("isub", 0),   632         101 : ("lsub", 0),   633         102 : ("fsub", 0),   634         103 : ("dsub", 0),   635         104 : ("imul", 0),   636         105 : ("lmul", 0),   637         106 : ("fmul", 0),   638         107 : ("dmul", 0),   639         108 : ("idiv", 0),   640         109 : ("ldiv", 0),   641         110 : ("fdiv", 0),   642         111 : ("ddiv", 0),   643         112 : ("irem", 0),   644         113 : ("lrem", 0),   645         114 : ("frem", 0),   646         115 : ("drem", 0),   647         116 : ("ineg", 0),   648         117 : ("lneg", 0),   649         118 : ("fneg", 0),   650         119 : ("dneg", 0),   651         120 : ("ishl", 0),   652         121 : ("lshl", 0),   653         122 : ("ishr", 0),   654         123 : ("lshr", 0),   655         124 : ("iushr", 0),   656         125 : ("lushr", 0),   657         126 : ("iand", 0),   658         127 : ("land", 0),   659         128 : ("ior", 0),   660         129 : ("lor", 0),   661         130 : ("ixor", 0),   662         131 : ("lxor", 0),   663         132 : ("iinc", 2),   664         133 : ("i2l", 0),   665         134 : ("i2f", 0),   666         135 : ("i2d", 0),   667         136 : ("l2i", 0),   668         137 : ("l2f", 0),   669         138 : ("l2d", 0),   670         139 : ("f2i", 0),   671         140 : ("f2l", 0),   672         141 : ("f2d", 0),   673         142 : ("d2i", 0),   674         143 : ("d2l", 0),   675         144 : ("d2f", 0),   676         145 : ("i2b", 0),   677         146 : ("i2c", 0),   678         147 : ("i2s", 0),   679         148 : ("lcmp", 0),   680         149 : ("fcmpl", 0),   681         150 : ("fcmpg", 0),   682         151 : ("dcmpl", 0),   683         152 : ("dcmpg", 0),   684         153 : ("ifeq", 2),   685         154 : ("ifne", 2),   686         155 : ("iflt", 2),   687         156 : ("ifge", 2),   688         157 : ("ifgt", 2),   689         158 : ("ifle", 2),   690         159 : ("if_icmpeq", 2),   691         160 : ("if_icmpne", 2),   692         161 : ("if_icmplt", 2),   693         162 : ("if_icmpge", 2),   694         163 : ("if_icmpgt", 2),   695         164 : ("if_icmple", 2),   696         165 : ("if_acmpeq", 2),   697         166 : ("if_acmpne", 2),   698         167 : ("goto", 2),   699         168 : ("jsr", 2),   700         169 : ("ret", 1),   701         170 : ("tableswitch", None), # variable number of arguments   702         171 : ("lookupswitch", None), # variable number of arguments   703         172 : ("ireturn", 0),   704         173 : ("lreturn", 0),   705         174 : ("freturn", 0),   706         175 : ("dreturn", 0),   707         176 : ("areturn", 0),   708         177 : ("return_", 0),   709         178 : ("getstatic", 2),   710         179 : ("putstatic", 2),   711         180 : ("getfield", 2),   712         181 : ("putfield", 2),   713         182 : ("invokevirtual", 2),   714         183 : ("invokespecial", 2),   715         184 : ("invokestatic", 2),   716         185 : ("invokeinterface", 4),   717         187 : ("new", 2),   718         188 : ("newarray", 1),   719         189 : ("anewarray", 2),   720         190 : ("arraylength", 0),   721         191 : ("athrow", 0),   722         192 : ("checkcast", 2),   723         193 : ("instanceof", 2),   724         194 : ("monitorenter", 0),   725         195 : ("monitorexit", 0),   726         196 : ("wide", None), # 3 or 5 arguments, stack changes according to modified element   727         197 : ("multianewarray", 3),   728         198 : ("ifnull", 2),   729         199 : ("ifnonnull", 2),   730         200 : ("goto_w", 4),   731         201 : ("jsr_w", 4),   732         }   733    734 class BytecodeDisassembler(BytecodeReader):   735    736     "A Java bytecode disassembler."   737    738     bytecode_methods = [spec[0] for spec in BytecodeReader.java_bytecodes.values()]   739    740     def __getattr__(self, name):   741         if name in self.bytecode_methods:   742             print name,   743             return self.generic   744         else:   745             raise AttributeError, name   746    747     def generic(self, arguments, program):   748         print arguments   749    750 class BytecodeDisassemblerProgram:   751     position = 0   752     def setup_except(self, target):   753         print "(setup_except %s)" % target   754     def setup_finally(self, target):   755         print "(setup_finally %s)" % target   756     def end_exception(self):   757         print "(end_exception)"   758     def pop_block(self):   759         print "(pop_block)"   760    761 class BytecodeTranslator(BytecodeReader):   762    763     "A Java bytecode translator which uses a Python bytecode writer."   764    765     def aaload(self, arguments, program):   766         # NOTE: No type checking performed.   767         program.binary_subscr()   768    769     def aastore(self, arguments, program):   770         # NOTE: No type checking performed.   771         # Stack: arrayref, index, value   772         program.rot_three() # Stack: value, arrayref, index   773         program.store_subscr()   774    775     def aconst_null(self, arguments, program):   776         program.load_global(None)   777    778     def aload(self, arguments, program):   779         program.load_fast(arguments[0])   780    781     def aload_0(self, arguments, program):   782         program.load_fast(0)   783    784     def aload_1(self, arguments, program):   785         program.load_fast(1)   786    787     def aload_2(self, arguments, program):   788         program.load_fast(2)   789    790     def aload_3(self, arguments, program):   791         program.load_fast(3)   792    793     def anewarray(self, arguments, program):   794         # NOTE: Does not raise NegativeArraySizeException.   795         # NOTE: Not using the index to type the list/array.   796         index = (arguments[0] << 8) + arguments[1]   797         self._newarray(program)   798    799     def _newarray(self, program):   800         program.build_list()        # Stack: count, list   801         program.rot_two()           # Stack: list, count   802         program.setup_loop()   803         program.load_global("range")   804         program.load_const(0)       # Stack: list, count, range, 0   805         program.rot_three()         # Stack: list, 0, count, range   806         program.rot_three()         # Stack: list, range, 0, count   807         program.call_function(2)    # Stack: list, range_list   808         program.get_iter()          # Stack: list, iter   809         program.for_iter()          # Stack: list, iter, value   810         program.pop_top()           # Stack: list, iter   811         program.rot_two()           # Stack: iter, list   812         program.dup_top()           # Stack: iter, list, list   813         program.load_attr("append") # Stack: iter, list, append   814         program.load_global(None)   # Stack: iter, list, append, None   815         program.call_function(1)    # Stack: iter, list, None   816         program.pop_top()           # Stack: iter, list   817         program.rot_two()           # Stack: list, iter   818         program.end_loop()          # Back to for_iter above   819    820     def areturn(self, arguments, program):   821         program.return_value()   822    823     def arraylength(self, arguments, program):   824         program.load_global("len")  # Stack: arrayref, len   825         program.rot_two()           # Stack: len, arrayref   826         program.call_function(1)   827    828     def astore(self, arguments, program):   829         program.store_fast(arguments[0])   830    831     def astore_0(self, arguments, program):   832         program.store_fast(0)   833    834     def astore_1(self, arguments, program):   835         program.store_fast(1)   836    837     def astore_2(self, arguments, program):   838         program.store_fast(2)   839    840     def astore_3(self, arguments, program):   841         program.store_fast(3)   842    843     def athrow(self, arguments, program):   844         # NOTE: NullPointerException not raised where null/None is found on the stack.   845         program.raise_varargs(1)   846    847     baload = aaload   848     bastore = aastore   849    850     def bipush(self, arguments, program):   851         program.load_const(arguments[0])   852    853     caload = aaload   854     castore = aastore   855    856     def checkcast(self, arguments, program):   857         index = (arguments[0] << 8) + arguments[1]   858         target_name = self.class_file.constants[index - 1].get_name()   859         # NOTE: Using the string version of the name which may contain incompatible characters.   860         target_components = str(target_name).split("/")   861    862         program.dup_top()                   # Stack: objectref, objectref   863         program.load_global("isinstance")   # Stack: objectref, objectref, isinstance   864         program.rot_two()                   # Stack: objectref, isinstance, objectref   865         program.load_global(target_components[0])   866         for target_component in target_components[1:]:   867             program.load_attr(target_component)   868         program.call_function(2)            # Stack: objectref   869    870     def d2f(self, arguments, program):   871         pass   872    873     def d2i(self, arguments, program):   874         program.load_global("int")  # Stack: value, int   875         program.rot_two()           # Stack: int, value   876         program.call_function(1)    # Stack: result   877    878     d2l = d2i # Preserving Java semantics   879    880     def dadd(self, arguments, program):   881         # NOTE: No type checking performed.   882         program.binary_add()   883    884     daload = aaload   885     dastore = aastore   886    887     def dcmpg(self, arguments, program):   888         # NOTE: No type checking performed.   889         program.compare_op(">")   890    891     def dcmpl(self, arguments, program):   892         # NOTE: No type checking performed.   893         program.compare_op("<")   894    895     def dconst_0(self, arguments, program):   896         program.load_const(0.0)   897    898     def dconst_1(self, arguments, program):   899         program.load_const(1.0)   900    901     def ddiv(self, arguments, program):   902         # NOTE: No type checking performed.   903         program.binary_divide()   904    905     dload = aload   906     dload_0 = aload_0   907     dload_1 = aload_1   908     dload_2 = aload_2   909     dload_3 = aload_3   910    911     def dmul(self, arguments, program):   912         # NOTE: No type checking performed.   913         program.binary_multiply()   914    915     def dneg(self, arguments, program):   916         # NOTE: No type checking performed.   917         program.unary_negative()   918    919     def drem(self, arguments, program):   920         # NOTE: No type checking performed.   921         program.binary_modulo()   922    923     dreturn = areturn   924     dstore = astore   925     dstore_0 = astore_0   926     dstore_1 = astore_1   927     dstore_2 = astore_2   928     dstore_3 = astore_3   929    930     def dsub(self, arguments, program):   931         # NOTE: No type checking performed.   932         program.binary_subtract()   933    934     def dup(self, arguments, program):   935         program.dup_top()   936    937     def dup_x1(self, arguments, program):   938         # Ignoring computational type categories.   939         program.dup_top()   940         program.rot_three()   941    942     def dup_x2(self, arguments, program):   943         # Ignoring computational type categories.   944         program.dup_top()   945         program.rot_four()   946    947     dup2 = dup # Ignoring computational type categories   948     dup2_x1 = dup_x1 # Ignoring computational type categories   949     dup2_x2 = dup_x2 # Ignoring computational type categories   950    951     def f2d(self, arguments, program):   952         pass # Preserving Java semantics   953    954     def f2i(self, arguments, program):   955         program.load_global("int")  # Stack: value, int   956         program.rot_two()           # Stack: int, value   957         program.call_function(1)    # Stack: result   958    959     f2l = f2i # Preserving Java semantics   960     fadd = dadd   961     faload = daload   962     fastore = dastore   963     fcmpg = dcmpg   964     fcmpl = dcmpl   965     fconst_0 = dconst_0   966     fconst_1 = dconst_1   967    968     def fconst_2(self, arguments, program):   969         program.load_const(2.0)   970    971     fdiv = ddiv   972     fload = dload   973     fload_0 = dload_0   974     fload_1 = dload_1   975     fload_2 = dload_2   976     fload_3 = dload_3   977     fmul = dmul   978     fneg = dneg   979     frem = drem   980     freturn = dreturn   981     fstore = dstore   982     fstore_0 = dstore_0   983     fstore_1 = dstore_1   984     fstore_2 = dstore_2   985     fstore_3 = dstore_3   986     fsub = dsub   987    988     def getfield(self, arguments, program):   989         index = (arguments[0] << 8) + arguments[1]   990         target_name = self.class_file.constants[index - 1].get_name()   991         # NOTE: Using the string version of the name which may contain incompatible characters.   992         program.load_attr(str(target_name))   993    994     def getstatic(self, arguments, program):   995         index = (arguments[0] << 8) + arguments[1]   996         target_name = self.class_file.constants[index - 1].get_name()   997         program.load_name("self")   998         program.load_attr("__class__")   999         # NOTE: Using the string version of the name which may contain incompatible characters.  1000         program.load_attr(str(target_name))  1001   1002     def goto(self, arguments, program):  1003         offset = signed2((arguments[0] << 8) + arguments[1])  1004         java_absolute = self.java_position + offset  1005         program.jump_absolute(self.position_mapping[java_absolute])  1006   1007     def goto_w(self, arguments, program):  1008         offset = signed4((arguments[0] << 24) + (arguments[1] << 16) + (arguments[2] << 8) + arguments[3])  1009         java_absolute = self.java_position + offset  1010         program.jump_absolute(self.position_mapping[java_absolute])  1011   1012     def i2b(self, arguments, program):  1013         pass  1014   1015     def i2c(self, arguments, program):  1016         program.load_global("chr")  # Stack: value, chr  1017         program.rot_two()           # Stack: chr, value  1018         program.call_function(1)    # Stack: result  1019   1020     def i2d(self, arguments, program):  1021         program.load_global("float")    # Stack: value, float  1022         program.rot_two()               # Stack: float, value  1023         program.call_function(1)        # Stack: result  1024   1025     i2f = i2d # Not distinguishing between float and double  1026   1027     def i2l(self, arguments, program):  1028         pass # Preserving Java semantics  1029   1030     def i2s(self, arguments, program):  1031         pass # Not distinguishing between int and short  1032   1033     iadd = fadd  1034     iaload = faload  1035   1036     def iand(self, arguments, program):  1037         # NOTE: No type checking performed.  1038         program.binary_and()  1039   1040     iastore = fastore  1041   1042     def iconst_m1(self, arguments, program):  1043         program.load_const(-1)  1044   1045     def iconst_0(self, arguments, program):  1046         program.load_const(0)  1047   1048     def iconst_1(self, arguments, program):  1049         program.load_const(1)  1050   1051     def iconst_2(self, arguments, program):  1052         program.load_const(2)  1053   1054     def iconst_3(self, arguments, program):  1055         program.load_const(3)  1056   1057     def iconst_4(self, arguments, program):  1058         program.load_const(4)  1059   1060     def iconst_5(self, arguments, program):  1061         program.load_const(5)  1062   1063     idiv = fdiv  1064   1065     def _if_xcmpx(self, arguments, program, op):  1066         offset = signed2((arguments[0] << 8) + arguments[1])  1067         java_absolute = self.java_position + offset  1068         program.compare_op(op)  1069         program.jump_to_label(0, "next") # skip if false  1070         program.goto(offset)  1071         program.start_label("next")  1072   1073     def if_acmpeq(self, arguments, program):  1074         # NOTE: No type checking performed.  1075         self._if_xcmpx(arguments, program, "is")  1076   1077     def if_acmpne(self, arguments, program):  1078         # NOTE: No type checking performed.  1079         self._if_xcmpx(arguments, program, "is not")  1080   1081     def if_icmpeq(self, arguments, program):  1082         # NOTE: No type checking performed.  1083         self._if_xcmpx(arguments, program, "==")  1084   1085     def if_icmpne(self, arguments, program):  1086         # NOTE: No type checking performed.  1087         self._if_xcmpx(arguments, program, "!=")  1088   1089     def if_icmplt(self, arguments, program):  1090         # NOTE: No type checking performed.  1091         self._if_xcmpx(arguments, program, "<")  1092   1093     def if_icmpge(self, arguments, program):  1094         # NOTE: No type checking performed.  1095         self._if_xcmpx(arguments, program, ">=")  1096   1097     def if_icmpgt(self, arguments, program):  1098         # NOTE: No type checking performed.  1099         self._if_xcmpx(arguments, program, ">")  1100   1101     def if_icmple(self, arguments, program):  1102         # NOTE: No type checking performed.  1103         self._if_xcmpx(arguments, program, "<=")  1104   1105     def ifeq(self, arguments, program):  1106         # NOTE: No type checking performed.  1107         program.load_const(0)  1108         self._if_xcmpx(arguments, program, "==")  1109   1110     def ifne(self, arguments, program):  1111         # NOTE: No type checking performed.  1112         program.load_const(0)  1113         self._if_xcmpx(arguments, program, "!=")  1114   1115     def iflt(self, arguments, program):  1116         # NOTE: No type checking performed.  1117         program.load_const(0)  1118         self._if_xcmpx(arguments, program, "<")  1119   1120     def ifge(self, arguments, program):  1121         # NOTE: No type checking performed.  1122         program.load_const(0)  1123         self._if_xcmpx(arguments, program, ">=")  1124   1125     def ifgt(self, arguments, program):  1126         # NOTE: No type checking performed.  1127         program.load_const(0)  1128         self._if_xcmpx(arguments, program, ">")  1129   1130     def ifle(self, arguments, program):  1131         # NOTE: No type checking performed.  1132         program.load_const(0)  1133         self._if_xcmpx(arguments, program, "<=")  1134   1135     def ifnonnull(self, arguments, program):  1136         # NOTE: No type checking performed.  1137         program.load_const(None)  1138         self._if_xcmpx(arguments, program, "is not")  1139   1140     def ifnull(self, arguments, program):  1141         # NOTE: No type checking performed.  1142         program.load_const(None)  1143         self._if_xcmpx(arguments, program, "is")  1144   1145     def iinc(self, arguments, program):  1146         # NOTE: No type checking performed.  1147         program.load_fast(arguments[0])  1148         program.load_const(arguments[1])  1149         program.binary_add()  1150   1151     iload = fload  1152     iload_0 = fload_0  1153     iload_1 = fload_1  1154     iload_2 = fload_2  1155     iload_3 = fload_3  1156     imul = fmul  1157     ineg = fneg  1158   1159     def instanceof(self, arguments, program):  1160         index = (arguments[0] << 8) + arguments[1]  1161         target_name = self.class_file.constants[index - 1].get_name()  1162         # NOTE: Using the string version of the name which may contain incompatible characters.  1163         target_components = str(target_name).split("/")  1164   1165         program.load_global("isinstance")   # Stack: objectref, isinstance  1166         program.rot_two()                   # Stack: isinstance, objectref  1167         program.load_global(target_components[0])  1168         for target_component in target_components[1:]:  1169             program.load_attr(target_component)  1170         program.call_function(2)            # Stack: result  1171   1172     def _invoke(self, target_name, program):  1173         # NOTE: Using the string version of the name which may contain incompatible characters.  1174         program.load_attr(str(target_name)) # Stack: tuple, method  1175         program.rot_two()                   # Stack: method, tuple  1176         program.load_global("apply")        # Stack: method, tuple, apply  1177         program.rot_three()                 # Stack: apply, method, tuple  1178         program.call_function(2)  1179   1180     def invokeinterface(self, arguments, program):  1181         # NOTE: This implementation does not perform the necessary checks for  1182         # NOTE: signature-based polymorphism.  1183         # NOTE: Java rules not specifically obeyed.  1184         index = (arguments[0] << 8) + arguments[1]  1185         count = arguments[2]  1186         target_name = self.class_file.constants[index - 1].get_name()  1187         # Stack: objectref, arg1, arg2, ...  1188         program.build_tuple(count)          # Stack: objectref, tuple  1189         program.rot_two()                   # Stack: tuple, objectref  1190         self._invoke(target_name, program)  1191   1192     def invokespecial(self, arguments, program):  1193         # NOTE: This implementation does not perform the necessary checks for  1194         # NOTE: signature-based polymorphism.  1195         # NOTE: Java rules not specifically obeyed.  1196         index = (arguments[0] << 8) + arguments[1]  1197         target = self.class_file.constants[index - 1]  1198         target_name = target.get_name()  1199         # Get the number of parameters from the descriptor.  1200         count = len(target.get_descriptor()[0])  1201         # Stack: objectref, arg1, arg2, ...  1202         program.build_tuple(count + 1)  # Stack: tuple  1203         # Use the class to provide access to static methods.  1204         program.load_name("self")       # Stack: tuple, self  1205         program.load_attr("__class__")  # Stack: tuple, class  1206         program.load_attr("__bases__")  # Stack: tuple, base-classes  1207         program.dup_top()               # Stack: tuple, base-classes, base-classes  1208         program.load_global("len")      # Stack: tuple, base-classes, base-classes, len  1209         program.rot_two()               # Stack: tuple, base-classes, len, base-classes  1210         program.call_function(1)        # Stack: tuple, base-classes, count  1211         program.load_const(0)           # Stack: tuple, base-classes, count, 0  1212         program.compare_op("==")        # Stack: tuple, base-classes, result  1213         program.jump_to_label(1, "next")  1214         program.pop_top()               # Stack: tuple, base-classes  1215         program.load_const(0)           # Stack: tuple, base-classes, 0  1216         program.binary_subscr()         # Stack: tuple, superclass  1217         self._invoke(target_name, program)  1218         program.jump_to_label(None, "next2")  1219         program.start_label("next")  1220         program.pop_top()               # Stack: tuple, base-classes  1221         program.pop_top()               # Stack: tuple  1222         program.pop_top()               # Stack:  1223         program.start_label("next2")  1224   1225     def invokestatic(self, arguments, program):  1226         # NOTE: This implementation does not perform the necessary checks for  1227         # NOTE: signature-based polymorphism.  1228         # NOTE: Java rules not specifically obeyed.  1229         index = (arguments[0] << 8) + arguments[1]  1230         target = self.class_file.constants[index - 1]  1231         target_name = target.get_name()  1232         # Get the number of parameters from the descriptor.  1233         count = len(target.get_descriptor()[0])  1234         # Stack: arg1, arg2, ...  1235         program.build_tuple(count)      # Stack: tuple  1236         # Use the class to provide access to static methods.  1237         program.load_name("self")       # Stack: tuple, self  1238         program.load_attr("__class__")  # Stack: tuple, class  1239         self._invoke(target_name, program)  1240   1241     invokevirtual = invokeinterface # Ignoring Java rules  1242   1243     def ior(self, arguments, program):  1244         # NOTE: No type checking performed.  1245         program.binary_or()  1246   1247     irem = frem  1248     ireturn = freturn  1249   1250     def ishl(self, arguments, program):  1251         # NOTE: No type checking performed.  1252         # NOTE: Not verified.  1253         program.binary_lshift()  1254   1255     def ishr(self, arguments, program):  1256         # NOTE: No type checking performed.  1257         # NOTE: Not verified.  1258         program.binary_rshift()  1259   1260     istore = fstore  1261     istore_0 = fstore_0  1262     istore_1 = fstore_1  1263     istore_2 = fstore_2  1264     istore_3 = fstore_3  1265     isub = fsub  1266     iushr = ishr # Ignoring distinctions between arithmetic and logical shifts  1267   1268     def ixor(self, arguments, program):  1269         # NOTE: No type checking performed.  1270         program.binary_xor()  1271   1272     def jsr(self, arguments, program):  1273         offset = signed2((arguments[0] << 8) + arguments[1])  1274         java_absolute = self.java_position + offset  1275         # Store the address of the next instruction.  1276         program.load_const_ret(self.position_mapping[self.java_position + 3])  1277         program.jump_absolute(self.position_mapping[java_absolute])  1278   1279     def jsr_w(self, arguments, program):  1280         offset = signed4((arguments[0] << 24) + (arguments[1] << 16) + (arguments[2] << 8) + arguments[3])  1281         java_absolute = self.java_position + offset  1282         # Store the address of the next instruction.  1283         program.load_const_ret(self.position_mapping[self.java_position + 5])  1284         program.jump_absolute(self.position_mapping[java_absolute])  1285   1286     l2d = i2d  1287     l2f = i2f  1288   1289     def l2i(self, arguments, program):  1290         pass # Preserving Java semantics  1291   1292     ladd = iadd  1293     laload = iaload  1294     land = iand  1295     lastore = iastore  1296   1297     def lcmp(self, arguments, program):  1298         # NOTE: No type checking performed.  1299         program.dup_topx(2)                 # Stack: value1, value2, value1, value2  1300         program.compare_op(">")             # Stack: value1, value2, result  1301         program.jump_to_label(0, "equals")  1302         # True - produce result and branch.  1303         program.pop_top()                   # Stack: value1, value2  1304         program.pop_top()                   # Stack: value1  1305         program.pop_top()                   # Stack:  1306         program.load_const(1)               # Stack: 1  1307         program.jump_to_label(None, "next")  1308         # False - test equality.  1309         program.start_label("equals")  1310         program.pop_top()                   # Stack: value1, value2  1311         program.dup_topx(2)                 # Stack: value1, value2, value1, value2  1312         program.compare_op("==")            # Stack: value1, value2, result  1313         program.jump_to_label(0, "less")  1314         # True - produce result and branch.  1315         program.pop_top()                   # Stack: value1, value2  1316         program.pop_top()                   # Stack: value1  1317         program.pop_top()                   # Stack:  1318         program.load_const(0)               # Stack: 0  1319         program.jump_to_label(None, "next")  1320         # False - produce result.  1321         program.start_label("less")  1322         program.pop_top()                   # Stack: value1, value2  1323         program.pop_top()                   # Stack: value1  1324         program.pop_top()                   # Stack:  1325         program.load_const(-1)              # Stack: -1  1326         program.start_label("next")  1327   1328     lconst_0 = iconst_0  1329     lconst_1 = iconst_1  1330   1331     def ldc(self, arguments, program):  1332         program.load_const(self.class_file.constants[arguments[0] - 1])  1333   1334     def ldc_w(self, arguments, program):  1335         program.load_const(self.class_file.constants[(arguments[0] << 8) + arguments[1] - 1])  1336   1337     ldc2_w = ldc_w  1338     ldiv = idiv  1339     lload = iload  1340     lload_0 = iload_0  1341     lload_1 = iload_1  1342     lload_2 = iload_2  1343     lload_3 = iload_3  1344     lmul = imul  1345     lneg = ineg  1346   1347     def lookupswitch(self, arguments, program):  1348         # Find the offset to the next 4 byte boundary in the code.  1349         d, r = divmod(self.java_position, 4)  1350         to_boundary = (4 - r) % 4  1351         # Get the pertinent arguments.  1352         arguments = arguments[to_boundary:]  1353         default = (arguments[0] << 24) + (arguments[1] << 16) + (arguments[2] << 8) + arguments[3]  1354         npairs = (arguments[4] << 24) + (arguments[5] << 16) + (arguments[6] << 8) + arguments[7]  1355         # Process the pairs.  1356         # NOTE: This is not the most optimal implementation.  1357         pair_index = 8  1358         for pair in range(0, npairs):  1359             match = ((arguments[pair_index] << 24) + (arguments[pair_index + 1] << 16) +  1360                 (arguments[pair_index + 2] << 8) + arguments[pair_index + 3])  1361             offset = signed4((arguments[pair_index + 4] << 24) + (arguments[pair_index + 5] << 16) +  1362                 (arguments[pair_index + 6] << 8) + arguments[pair_index + 7])  1363             # Calculate the branch target.  1364             java_absolute = self.java_position + offset  1365             # Generate branching code.  1366             program.dup_top()                                           # Stack: key, key  1367             program.load_const(match)                                   # Stack: key, key, match  1368             program.compare_op("==")                                    # Stack: key, result  1369             program.jump_to_label(0, "end")  1370             program.pop_top()                                           # Stack: key  1371             program.pop_top()                                           # Stack:  1372             program.jump_absolute(self.position_mapping[java_absolute])  1373             # Generate the label for the end of the branching code.  1374             program.start_label("end")  1375             program.pop_top()                                           # Stack: key  1376             # Update the index.  1377             pair_index += 8  1378         # Generate the default.  1379         java_absolute = self.java_position + default  1380         program.jump_absolute(self.position_mapping[java_absolute])  1381   1382     lor = ior  1383     lrem = irem  1384     lreturn = ireturn  1385     lshl = ishl  1386     lshr = ishr  1387     lstore = istore  1388     lstore_0 = istore_0  1389     lstore_1 = istore_1  1390     lstore_2 = istore_2  1391     lstore_3 = istore_3  1392     lsub = isub  1393     lushr = iushr  1394     lxor = ixor  1395   1396     def monitorenter(self, arguments, program):  1397         # NOTE: To be implemented.  1398         pass  1399   1400     def monitorexit(self, arguments, program):  1401         # NOTE: To be implemented.  1402         pass  1403   1404     def multianewarray(self, arguments, program):  1405         # NOTE: To be implemented.  1406         pass  1407   1408     def new(self, arguments, program):  1409         # This operation is considered to be the same as the calling of the  1410         # initialisation method of the given class with no arguments.  1411         index = (arguments[0] << 8) + arguments[1]  1412         target_name = self.class_file.constants[index - 1].get_name()  1413         # NOTE: Using the string version of the name which may contain incompatible characters.  1414         program.load_global(str(target_name))  1415         program.call_function(0)  1416   1417     def newarray(self, arguments, program):  1418         # NOTE: Does not raise NegativeArraySizeException.  1419         # NOTE: Not using the arguments to type the list/array.  1420         self._newarray(program)  1421   1422     def nop(self, arguments, program):  1423         pass  1424   1425     def pop(self, arguments, program):  1426         program.pop_top()  1427   1428     pop2 = pop # ignoring Java stack value distinctions  1429   1430     def putfield(self, arguments, program):  1431         index = (arguments[0] << 8) + arguments[1]  1432         target_name = self.class_file.constants[index - 1].get_name()  1433         program.rot_two()  1434         # NOTE: Using the string version of the name which may contain incompatible characters.  1435         program.store_attr(str(target_name))  1436   1437     def putstatic(self, arguments, program):  1438         index = (arguments[0] << 8) + arguments[1]  1439         target_name = self.class_file.constants[index - 1].get_name()  1440         program.load_name("self")  1441         program.load_attr("__class__")  1442         # NOTE: Using the string version of the name which may contain incompatible characters.  1443         program.store_attr(str(target_name))  1444   1445     def ret(self, arguments, program):  1446         program.ret(arguments[0])  1447   1448     def return_(self, arguments, program):  1449         program.load_const(None)  1450         program.return_value()  1451   1452     saload = laload  1453     sastore = lastore  1454   1455     def sipush(self, arguments, program):  1456         program.load_const((arguments[0] << 8) + arguments[1])  1457   1458     def swap(self, arguments, program):  1459         program.rot_two()  1460   1461     def tableswitch(self, arguments, program):  1462         # Find the offset to the next 4 byte boundary in the code.  1463         d, r = divmod(self.java_position, 4)  1464         to_boundary = (4 - r) % 4  1465         # Get the pertinent arguments.  1466         arguments = arguments[to_boundary:]  1467         default = (arguments[0] << 24) + (arguments[1] << 16) + (arguments[2] << 8) + arguments[3]  1468         low = (arguments[4] << 24) + (arguments[5] << 16) + (arguments[6] << 8) + arguments[7]  1469         high = (arguments[8] << 24) + (arguments[9] << 16) + (arguments[10] << 8) + arguments[11]  1470         # Process the jump entries.  1471         # NOTE: This is not the most optimal implementation.  1472         jump_index = 8  1473         for jump in range(low, high + 1):  1474             offset = signed4((arguments[jump_index] << 24) + (arguments[jump_index + 1] << 16) +  1475                 (arguments[jump_index + 2] << 8) + arguments[jump_index + 3])  1476             # Calculate the branch target.  1477             java_absolute = self.java_position + offset  1478             # Generate branching code.  1479             program.dup_top()                                           # Stack: key, key  1480             program.load_const(jump)                                    # Stack: key, key, jump  1481             program.compare_op("==")                                    # Stack: key, result  1482             program.jump_to_label(0, "end")  1483             program.pop_top()                                           # Stack: key  1484             program.pop_top()                                           # Stack:  1485             program.jump_absolute(self.position_mapping[java_absolute])  1486             # Generate the label for the end of the branching code.  1487             program.start_label("end")  1488             program.pop_top()                                           # Stack: key  1489             # Update the index.  1490             jump_index += 8  1491         # Generate the default.  1492         java_absolute = self.java_position + default  1493         program.jump_absolute(self.position_mapping[java_absolute])  1494   1495     def wide(self, code, program):  1496         # NOTE: To be implemented.  1497         return number_of_arguments  1498   1499 def disassemble(class_file, code, exception_table):  1500     disassembler = BytecodeDisassembler(class_file)  1501     disassembler.process(code, exception_table, BytecodeDisassemblerProgram())  1502   1503 def translate(class_file, code, exception_table):  1504     translator = BytecodeTranslator(class_file)  1505     writer = BytecodeWriter()  1506     translator.process(code, exception_table, writer)  1507     return translator, writer  1508   1509 if __name__ == "__main__":  1510     import sys  1511     from classfile import ClassFile  1512     f = open(sys.argv[1])  1513     c = ClassFile(f.read())  1514   1515 # vim: tabstop=4 expandtab shiftwidth=4