javaclass

bytecode.py

14:946dca5710ea
2004-11-09 Paul Boddie Changed the Python equivalent of <init> to be a special __java_init__ method.
     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                 # NOTE: Insert jump beyond handlers.   496                 # NOTE: program.jump_forward/absolute(...)   497                 program.end_exception()   498                 # NOTE: Insert a check for the correct exception at the start of each handler.   499                 # NOTE: Insert end finally at end of handlers as well as where "ret" occurs.   500                 # NOTE: Ensure that pop_block is reachable by possibly inserting it at the start of finally handlers.   501    502             # Where handlers are begun, do not produce equivalent bytecode since   503             # the first handler instruction typically involves saving a local   504             # variable that is not applicable to the Python VM.   505             #if not exception_block_handler.get(self.java_position, []):   506    507             # Process the bytecode at the current position.   508             bytecode = ord(code[self.java_position])   509             mnemonic, number_of_arguments = self.java_bytecodes[bytecode]   510             number_of_arguments = self.process_bytecode(mnemonic, number_of_arguments, code, program)   511             next_java_position = self.java_position + 1 + number_of_arguments   512    513             # Insert exception handler end instructions.   514             for exception in exception_block_end.get(next_java_position, []):   515                 program.pop_block()   516    517             # Only advance the JVM position after sneaking in extra Python   518             # instructions.   519             self.java_position = next_java_position   520    521     def process_bytecode(self, mnemonic, number_of_arguments, code, program):   522         if number_of_arguments is not None:   523             arguments = []   524             for j in range(0, number_of_arguments):   525                 arguments.append(ord(code[self.java_position + 1 + j]))   526    527             # Call the handler.   528             getattr(self, mnemonic)(arguments, program)   529             return number_of_arguments   530         else:   531             # Call the handler.   532             return getattr(self, mnemonic)(code[self.java_position+1:], program)   533    534     java_bytecodes = {   535         # code : (mnemonic, number of following bytes, change in stack)   536         0 : ("nop", 0),   537         1 : ("aconst_null", 0),   538         2 : ("iconst_m1", 0),   539         3 : ("iconst_0", 0),   540         4 : ("iconst_1", 0),   541         5 : ("iconst_2", 0),   542         6 : ("iconst_3", 0),   543         7 : ("iconst_4", 0),   544         8 : ("iconst_5", 0),   545         9 : ("lconst_0", 0),   546         10 : ("lconst_1", 0),   547         11 : ("fconst_0", 0),   548         12 : ("fconst_1", 0),   549         13 : ("fconst_2", 0),   550         14 : ("dconst_0", 0),   551         15 : ("dconst_1", 0),   552         16 : ("bipush", 1),   553         17 : ("sipush", 2),   554         18 : ("ldc", 1),   555         19 : ("ldc_w", 2),   556         20 : ("ldc2_w", 2),   557         21 : ("iload", 1),   558         22 : ("lload", 1),   559         23 : ("fload", 1),   560         24 : ("dload", 1),   561         25 : ("aload", 1),   562         26 : ("iload_0", 0),   563         27 : ("iload_1", 0),   564         28 : ("iload_2", 0),   565         29 : ("iload_3", 0),   566         30 : ("lload_0", 0),   567         31 : ("lload_1", 0),   568         32 : ("lload_2", 0),   569         33 : ("lload_3", 0),   570         34 : ("fload_0", 0),   571         35 : ("fload_1", 0),   572         36 : ("fload_2", 0),   573         37 : ("fload_3", 0),   574         38 : ("dload_0", 0),   575         39 : ("dload_1", 0),   576         40 : ("dload_2", 0),   577         41 : ("dload_3", 0),   578         42 : ("aload_0", 0),   579         43 : ("aload_1", 0),   580         44 : ("aload_2", 0),   581         45 : ("aload_3", 0),   582         46 : ("iaload", 0),   583         47 : ("laload", 0),   584         48 : ("faload", 0),   585         49 : ("daload", 0),   586         50 : ("aaload", 0),   587         51 : ("baload", 0),   588         52 : ("caload", 0),   589         53 : ("saload", 0),   590         54 : ("istore", 1),   591         55 : ("lstore", 1),   592         56 : ("fstore", 1),   593         57 : ("dstore", 1),   594         58 : ("astore", 1),   595         59 : ("istore_0", 0),   596         60 : ("istore_1", 0),   597         61 : ("istore_2", 0),   598         62 : ("istore_3", 0),   599         63 : ("lstore_0", 0),   600         64 : ("lstore_1", 0),   601         65 : ("lstore_2", 0),   602         66 : ("lstore_3", 0),   603         67 : ("fstore_0", 0),   604         68 : ("fstore_1", 0),   605         69 : ("fstore_2", 0),   606         70 : ("fstore_3", 0),   607         71 : ("dstore_0", 0),   608         72 : ("dstore_1", 0),   609         73 : ("dstore_2", 0),   610         74 : ("dstore_3", 0),   611         75 : ("astore_0", 0),   612         76 : ("astore_1", 0),   613         77 : ("astore_2", 0),   614         78 : ("astore_3", 0),   615         79 : ("iastore", 0),   616         80 : ("lastore", 0),   617         81 : ("fastore", 0),   618         82 : ("dastore", 0),   619         83 : ("aastore", 0),   620         84 : ("bastore", 0),   621         85 : ("castore", 0),   622         86 : ("sastore", 0),   623         87 : ("pop", 0),   624         88 : ("pop2", 0),   625         89 : ("dup", 0),   626         90 : ("dup_x1", 0),   627         91 : ("dup_x2", 0),   628         92 : ("dup2", 0),   629         93 : ("dup2_x1", 0),   630         94 : ("dup2_x2", 0),   631         95 : ("swap", 0),   632         96 : ("iadd", 0),   633         97 : ("ladd", 0),   634         98 : ("fadd", 0),   635         99 : ("dadd", 0),   636         100 : ("isub", 0),   637         101 : ("lsub", 0),   638         102 : ("fsub", 0),   639         103 : ("dsub", 0),   640         104 : ("imul", 0),   641         105 : ("lmul", 0),   642         106 : ("fmul", 0),   643         107 : ("dmul", 0),   644         108 : ("idiv", 0),   645         109 : ("ldiv", 0),   646         110 : ("fdiv", 0),   647         111 : ("ddiv", 0),   648         112 : ("irem", 0),   649         113 : ("lrem", 0),   650         114 : ("frem", 0),   651         115 : ("drem", 0),   652         116 : ("ineg", 0),   653         117 : ("lneg", 0),   654         118 : ("fneg", 0),   655         119 : ("dneg", 0),   656         120 : ("ishl", 0),   657         121 : ("lshl", 0),   658         122 : ("ishr", 0),   659         123 : ("lshr", 0),   660         124 : ("iushr", 0),   661         125 : ("lushr", 0),   662         126 : ("iand", 0),   663         127 : ("land", 0),   664         128 : ("ior", 0),   665         129 : ("lor", 0),   666         130 : ("ixor", 0),   667         131 : ("lxor", 0),   668         132 : ("iinc", 2),   669         133 : ("i2l", 0),   670         134 : ("i2f", 0),   671         135 : ("i2d", 0),   672         136 : ("l2i", 0),   673         137 : ("l2f", 0),   674         138 : ("l2d", 0),   675         139 : ("f2i", 0),   676         140 : ("f2l", 0),   677         141 : ("f2d", 0),   678         142 : ("d2i", 0),   679         143 : ("d2l", 0),   680         144 : ("d2f", 0),   681         145 : ("i2b", 0),   682         146 : ("i2c", 0),   683         147 : ("i2s", 0),   684         148 : ("lcmp", 0),   685         149 : ("fcmpl", 0),   686         150 : ("fcmpg", 0),   687         151 : ("dcmpl", 0),   688         152 : ("dcmpg", 0),   689         153 : ("ifeq", 2),   690         154 : ("ifne", 2),   691         155 : ("iflt", 2),   692         156 : ("ifge", 2),   693         157 : ("ifgt", 2),   694         158 : ("ifle", 2),   695         159 : ("if_icmpeq", 2),   696         160 : ("if_icmpne", 2),   697         161 : ("if_icmplt", 2),   698         162 : ("if_icmpge", 2),   699         163 : ("if_icmpgt", 2),   700         164 : ("if_icmple", 2),   701         165 : ("if_acmpeq", 2),   702         166 : ("if_acmpne", 2),   703         167 : ("goto", 2),   704         168 : ("jsr", 2),   705         169 : ("ret", 1),   706         170 : ("tableswitch", None), # variable number of arguments   707         171 : ("lookupswitch", None), # variable number of arguments   708         172 : ("ireturn", 0),   709         173 : ("lreturn", 0),   710         174 : ("freturn", 0),   711         175 : ("dreturn", 0),   712         176 : ("areturn", 0),   713         177 : ("return_", 0),   714         178 : ("getstatic", 2),   715         179 : ("putstatic", 2),   716         180 : ("getfield", 2),   717         181 : ("putfield", 2),   718         182 : ("invokevirtual", 2),   719         183 : ("invokespecial", 2),   720         184 : ("invokestatic", 2),   721         185 : ("invokeinterface", 4),   722         187 : ("new", 2),   723         188 : ("newarray", 1),   724         189 : ("anewarray", 2),   725         190 : ("arraylength", 0),   726         191 : ("athrow", 0),   727         192 : ("checkcast", 2),   728         193 : ("instanceof", 2),   729         194 : ("monitorenter", 0),   730         195 : ("monitorexit", 0),   731         196 : ("wide", None), # 3 or 5 arguments, stack changes according to modified element   732         197 : ("multianewarray", 3),   733         198 : ("ifnull", 2),   734         199 : ("ifnonnull", 2),   735         200 : ("goto_w", 4),   736         201 : ("jsr_w", 4),   737         }   738    739 class BytecodeDisassembler(BytecodeReader):   740    741     "A Java bytecode disassembler."   742    743     bytecode_methods = [spec[0] for spec in BytecodeReader.java_bytecodes.values()]   744    745     def __getattr__(self, name):   746         if name in self.bytecode_methods:   747             print name,   748             return self.generic   749         else:   750             raise AttributeError, name   751    752     def generic(self, arguments, program):   753         print arguments   754    755 class BytecodeDisassemblerProgram:   756     position = 0   757     def setup_except(self, target):   758         print "(setup_except %s)" % target   759     def setup_finally(self, target):   760         print "(setup_finally %s)" % target   761     def end_exception(self):   762         print "(end_exception)"   763     def pop_block(self):   764         print "(pop_block)"   765    766 class BytecodeTranslator(BytecodeReader):   767    768     "A Java bytecode translator which uses a Python bytecode writer."   769    770     def aaload(self, arguments, program):   771         # NOTE: No type checking performed.   772         program.binary_subscr()   773    774     def aastore(self, arguments, program):   775         # NOTE: No type checking performed.   776         # Stack: arrayref, index, value   777         program.rot_three() # Stack: value, arrayref, index   778         program.store_subscr()   779    780     def aconst_null(self, arguments, program):   781         program.load_global(None)   782    783     def aload(self, arguments, program):   784         program.load_fast(arguments[0])   785    786     def aload_0(self, arguments, program):   787         program.load_fast(0)   788    789     def aload_1(self, arguments, program):   790         program.load_fast(1)   791    792     def aload_2(self, arguments, program):   793         program.load_fast(2)   794    795     def aload_3(self, arguments, program):   796         program.load_fast(3)   797    798     def anewarray(self, arguments, program):   799         # NOTE: Does not raise NegativeArraySizeException.   800         # NOTE: Not using the index to type the list/array.   801         index = (arguments[0] << 8) + arguments[1]   802         self._newarray(program)   803    804     def _newarray(self, program):   805         program.build_list()        # Stack: count, list   806         program.rot_two()           # Stack: list, count   807         program.setup_loop()   808         program.load_global("range")   809         program.load_const(0)       # Stack: list, count, range, 0   810         program.rot_three()         # Stack: list, 0, count, range   811         program.rot_three()         # Stack: list, range, 0, count   812         program.call_function(2)    # Stack: list, range_list   813         program.get_iter()          # Stack: list, iter   814         program.for_iter()          # Stack: list, iter, value   815         program.pop_top()           # Stack: list, iter   816         program.rot_two()           # Stack: iter, list   817         program.dup_top()           # Stack: iter, list, list   818         program.load_attr("append") # Stack: iter, list, append   819         program.load_global(None)   # Stack: iter, list, append, None   820         program.call_function(1)    # Stack: iter, list, None   821         program.pop_top()           # Stack: iter, list   822         program.rot_two()           # Stack: list, iter   823         program.end_loop()          # Back to for_iter above   824    825     def areturn(self, arguments, program):   826         program.return_value()   827    828     def arraylength(self, arguments, program):   829         program.load_global("len")  # Stack: arrayref, len   830         program.rot_two()           # Stack: len, arrayref   831         program.call_function(1)   832    833     def astore(self, arguments, program):   834         program.store_fast(arguments[0])   835    836     def astore_0(self, arguments, program):   837         program.store_fast(0)   838    839     def astore_1(self, arguments, program):   840         program.store_fast(1)   841    842     def astore_2(self, arguments, program):   843         program.store_fast(2)   844    845     def astore_3(self, arguments, program):   846         program.store_fast(3)   847    848     def athrow(self, arguments, program):   849         # NOTE: NullPointerException not raised where null/None is found on the stack.   850         program.raise_varargs(1)   851    852     baload = aaload   853     bastore = aastore   854    855     def bipush(self, arguments, program):   856         program.load_const(arguments[0])   857    858     caload = aaload   859     castore = aastore   860    861     def checkcast(self, arguments, program):   862         index = (arguments[0] << 8) + arguments[1]   863         target_name = self.class_file.constants[index - 1].get_name()   864         # NOTE: Using the string version of the name which may contain incompatible characters.   865         target_components = str(target_name).split("/")   866    867         program.dup_top()                   # Stack: objectref, objectref   868         program.load_global("isinstance")   # Stack: objectref, objectref, isinstance   869         program.rot_two()                   # Stack: objectref, isinstance, objectref   870         program.load_global(target_components[0])   871         for target_component in target_components[1:]:   872             program.load_attr(target_component)   873         program.call_function(2)            # Stack: objectref   874    875     def d2f(self, arguments, program):   876         pass   877    878     def d2i(self, arguments, program):   879         program.load_global("int")  # Stack: value, int   880         program.rot_two()           # Stack: int, value   881         program.call_function(1)    # Stack: result   882    883     d2l = d2i # Preserving Java semantics   884    885     def dadd(self, arguments, program):   886         # NOTE: No type checking performed.   887         program.binary_add()   888    889     daload = aaload   890     dastore = aastore   891    892     def dcmpg(self, arguments, program):   893         # NOTE: No type checking performed.   894         program.compare_op(">")   895    896     def dcmpl(self, arguments, program):   897         # NOTE: No type checking performed.   898         program.compare_op("<")   899    900     def dconst_0(self, arguments, program):   901         program.load_const(0.0)   902    903     def dconst_1(self, arguments, program):   904         program.load_const(1.0)   905    906     def ddiv(self, arguments, program):   907         # NOTE: No type checking performed.   908         program.binary_divide()   909    910     dload = aload   911     dload_0 = aload_0   912     dload_1 = aload_1   913     dload_2 = aload_2   914     dload_3 = aload_3   915    916     def dmul(self, arguments, program):   917         # NOTE: No type checking performed.   918         program.binary_multiply()   919    920     def dneg(self, arguments, program):   921         # NOTE: No type checking performed.   922         program.unary_negative()   923    924     def drem(self, arguments, program):   925         # NOTE: No type checking performed.   926         program.binary_modulo()   927    928     dreturn = areturn   929     dstore = astore   930     dstore_0 = astore_0   931     dstore_1 = astore_1   932     dstore_2 = astore_2   933     dstore_3 = astore_3   934    935     def dsub(self, arguments, program):   936         # NOTE: No type checking performed.   937         program.binary_subtract()   938    939     def dup(self, arguments, program):   940         program.dup_top()   941    942     def dup_x1(self, arguments, program):   943         # Ignoring computational type categories.   944         program.dup_top()   945         program.rot_three()   946    947     def dup_x2(self, arguments, program):   948         # Ignoring computational type categories.   949         program.dup_top()   950         program.rot_four()   951    952     dup2 = dup # Ignoring computational type categories   953     dup2_x1 = dup_x1 # Ignoring computational type categories   954     dup2_x2 = dup_x2 # Ignoring computational type categories   955    956     def f2d(self, arguments, program):   957         pass # Preserving Java semantics   958    959     def f2i(self, arguments, program):   960         program.load_global("int")  # Stack: value, int   961         program.rot_two()           # Stack: int, value   962         program.call_function(1)    # Stack: result   963    964     f2l = f2i # Preserving Java semantics   965     fadd = dadd   966     faload = daload   967     fastore = dastore   968     fcmpg = dcmpg   969     fcmpl = dcmpl   970     fconst_0 = dconst_0   971     fconst_1 = dconst_1   972    973     def fconst_2(self, arguments, program):   974         program.load_const(2.0)   975    976     fdiv = ddiv   977     fload = dload   978     fload_0 = dload_0   979     fload_1 = dload_1   980     fload_2 = dload_2   981     fload_3 = dload_3   982     fmul = dmul   983     fneg = dneg   984     frem = drem   985     freturn = dreturn   986     fstore = dstore   987     fstore_0 = dstore_0   988     fstore_1 = dstore_1   989     fstore_2 = dstore_2   990     fstore_3 = dstore_3   991     fsub = dsub   992    993     def getfield(self, arguments, program):   994         index = (arguments[0] << 8) + arguments[1]   995         target_name = self.class_file.constants[index - 1].get_python_name()   996         # NOTE: Using the string version of the name which may contain incompatible characters.   997         program.load_attr(str(target_name))   998    999     def getstatic(self, arguments, program):  1000         index = (arguments[0] << 8) + arguments[1]  1001         target_name = self.class_file.constants[index - 1].get_python_name()  1002         program.load_name("self")  1003         program.load_attr("__class__")  1004         # NOTE: Using the string version of the name which may contain incompatible characters.  1005         program.load_attr(str(target_name))  1006   1007     def goto(self, arguments, program):  1008         offset = signed2((arguments[0] << 8) + arguments[1])  1009         java_absolute = self.java_position + offset  1010         program.jump_absolute(self.position_mapping[java_absolute])  1011   1012     def goto_w(self, arguments, program):  1013         offset = signed4((arguments[0] << 24) + (arguments[1] << 16) + (arguments[2] << 8) + arguments[3])  1014         java_absolute = self.java_position + offset  1015         program.jump_absolute(self.position_mapping[java_absolute])  1016   1017     def i2b(self, arguments, program):  1018         pass  1019   1020     def i2c(self, arguments, program):  1021         program.load_global("chr")  # Stack: value, chr  1022         program.rot_two()           # Stack: chr, value  1023         program.call_function(1)    # Stack: result  1024   1025     def i2d(self, arguments, program):  1026         program.load_global("float")    # Stack: value, float  1027         program.rot_two()               # Stack: float, value  1028         program.call_function(1)        # Stack: result  1029   1030     i2f = i2d # Not distinguishing between float and double  1031   1032     def i2l(self, arguments, program):  1033         pass # Preserving Java semantics  1034   1035     def i2s(self, arguments, program):  1036         pass # Not distinguishing between int and short  1037   1038     iadd = fadd  1039     iaload = faload  1040   1041     def iand(self, arguments, program):  1042         # NOTE: No type checking performed.  1043         program.binary_and()  1044   1045     iastore = fastore  1046   1047     def iconst_m1(self, arguments, program):  1048         program.load_const(-1)  1049   1050     def iconst_0(self, arguments, program):  1051         program.load_const(0)  1052   1053     def iconst_1(self, arguments, program):  1054         program.load_const(1)  1055   1056     def iconst_2(self, arguments, program):  1057         program.load_const(2)  1058   1059     def iconst_3(self, arguments, program):  1060         program.load_const(3)  1061   1062     def iconst_4(self, arguments, program):  1063         program.load_const(4)  1064   1065     def iconst_5(self, arguments, program):  1066         program.load_const(5)  1067   1068     idiv = fdiv  1069   1070     def _if_xcmpx(self, arguments, program, op):  1071         offset = signed2((arguments[0] << 8) + arguments[1])  1072         java_absolute = self.java_position + offset  1073         program.compare_op(op)  1074         program.jump_to_label(0, "next") # skip if false  1075         program.goto(offset)  1076         program.start_label("next")  1077   1078     def if_acmpeq(self, arguments, program):  1079         # NOTE: No type checking performed.  1080         self._if_xcmpx(arguments, program, "is")  1081   1082     def if_acmpne(self, arguments, program):  1083         # NOTE: No type checking performed.  1084         self._if_xcmpx(arguments, program, "is not")  1085   1086     def if_icmpeq(self, arguments, program):  1087         # NOTE: No type checking performed.  1088         self._if_xcmpx(arguments, program, "==")  1089   1090     def if_icmpne(self, arguments, program):  1091         # NOTE: No type checking performed.  1092         self._if_xcmpx(arguments, program, "!=")  1093   1094     def if_icmplt(self, arguments, program):  1095         # NOTE: No type checking performed.  1096         self._if_xcmpx(arguments, program, "<")  1097   1098     def if_icmpge(self, arguments, program):  1099         # NOTE: No type checking performed.  1100         self._if_xcmpx(arguments, program, ">=")  1101   1102     def if_icmpgt(self, arguments, program):  1103         # NOTE: No type checking performed.  1104         self._if_xcmpx(arguments, program, ">")  1105   1106     def if_icmple(self, arguments, program):  1107         # NOTE: No type checking performed.  1108         self._if_xcmpx(arguments, program, "<=")  1109   1110     def ifeq(self, arguments, program):  1111         # NOTE: No type checking performed.  1112         program.load_const(0)  1113         self._if_xcmpx(arguments, program, "==")  1114   1115     def ifne(self, arguments, program):  1116         # NOTE: No type checking performed.  1117         program.load_const(0)  1118         self._if_xcmpx(arguments, program, "!=")  1119   1120     def iflt(self, arguments, program):  1121         # NOTE: No type checking performed.  1122         program.load_const(0)  1123         self._if_xcmpx(arguments, program, "<")  1124   1125     def ifge(self, arguments, program):  1126         # NOTE: No type checking performed.  1127         program.load_const(0)  1128         self._if_xcmpx(arguments, program, ">=")  1129   1130     def ifgt(self, arguments, program):  1131         # NOTE: No type checking performed.  1132         program.load_const(0)  1133         self._if_xcmpx(arguments, program, ">")  1134   1135     def ifle(self, arguments, program):  1136         # NOTE: No type checking performed.  1137         program.load_const(0)  1138         self._if_xcmpx(arguments, program, "<=")  1139   1140     def ifnonnull(self, arguments, program):  1141         # NOTE: No type checking performed.  1142         program.load_const(None)  1143         self._if_xcmpx(arguments, program, "is not")  1144   1145     def ifnull(self, arguments, program):  1146         # NOTE: No type checking performed.  1147         program.load_const(None)  1148         self._if_xcmpx(arguments, program, "is")  1149   1150     def iinc(self, arguments, program):  1151         # NOTE: No type checking performed.  1152         program.load_fast(arguments[0])  1153         program.load_const(arguments[1])  1154         program.binary_add()  1155   1156     iload = fload  1157     iload_0 = fload_0  1158     iload_1 = fload_1  1159     iload_2 = fload_2  1160     iload_3 = fload_3  1161     imul = fmul  1162     ineg = fneg  1163   1164     def instanceof(self, arguments, program):  1165         index = (arguments[0] << 8) + arguments[1]  1166         target_name = self.class_file.constants[index - 1].get_name()  1167         # NOTE: Using the string version of the name which may contain incompatible characters.  1168         target_components = str(target_name).split("/")  1169   1170         program.load_global("isinstance")   # Stack: objectref, isinstance  1171         program.rot_two()                   # Stack: isinstance, objectref  1172         program.load_global(target_components[0])  1173         for target_component in target_components[1:]:  1174             program.load_attr(target_component)  1175         program.call_function(2)            # Stack: result  1176   1177     def _invoke(self, target_name, program):  1178         # NOTE: Using the string version of the name which may contain incompatible characters.  1179         program.load_attr(str(target_name)) # Stack: tuple, method  1180         program.rot_two()                   # Stack: method, tuple  1181         program.load_global("apply")        # Stack: method, tuple, apply  1182         program.rot_three()                 # Stack: apply, method, tuple  1183         program.call_function(2)  1184   1185     def invokeinterface(self, arguments, program):  1186         # NOTE: This implementation does not perform the necessary checks for  1187         # NOTE: signature-based polymorphism.  1188         # NOTE: Java rules not specifically obeyed.  1189         index = (arguments[0] << 8) + arguments[1]  1190         count = arguments[2]  1191         target_name = self.class_file.constants[index - 1].get_python_name()  1192         # Stack: objectref, arg1, arg2, ...  1193         program.build_tuple(count)          # Stack: objectref, tuple  1194         program.rot_two()                   # Stack: tuple, objectref  1195         self._invoke(target_name, program)  1196   1197     def invokespecial(self, arguments, program):  1198         # NOTE: This implementation does not perform the necessary checks for  1199         # NOTE: signature-based polymorphism.  1200         # NOTE: Java rules not specifically obeyed.  1201         index = (arguments[0] << 8) + arguments[1]  1202         target = self.class_file.constants[index - 1]  1203         target_name = target.get_python_name()  1204         # Get the number of parameters from the descriptor.  1205         count = len(target.get_descriptor()[0])  1206         # Stack: objectref, arg1, arg2, ...  1207         program.build_tuple(count + 1)  # Stack: tuple  1208         # Use the class to provide access to static methods.  1209         program.load_name("self")       # Stack: tuple, self  1210         program.load_attr("__class__")  # Stack: tuple, class  1211         program.load_attr("__bases__")  # Stack: tuple, base-classes  1212         program.dup_top()               # Stack: tuple, base-classes, base-classes  1213         program.load_global("len")      # Stack: tuple, base-classes, base-classes, len  1214         program.rot_two()               # Stack: tuple, base-classes, len, base-classes  1215         program.call_function(1)        # Stack: tuple, base-classes, count  1216         program.load_const(0)           # Stack: tuple, base-classes, count, 0  1217         program.compare_op("==")        # Stack: tuple, base-classes, result  1218         program.jump_to_label(1, "next")  1219         program.pop_top()               # Stack: tuple, base-classes  1220         program.load_const(0)           # Stack: tuple, base-classes, 0  1221         program.binary_subscr()         # Stack: tuple, superclass  1222         self._invoke(target_name, program)  1223         program.jump_to_label(None, "next2")  1224         program.start_label("next")  1225         program.pop_top()               # Stack: tuple, base-classes  1226         program.pop_top()               # Stack: tuple  1227         program.pop_top()               # Stack:  1228         program.start_label("next2")  1229   1230     def invokestatic(self, arguments, program):  1231         # NOTE: This implementation does not perform the necessary checks for  1232         # NOTE: signature-based polymorphism.  1233         # NOTE: Java rules not specifically obeyed.  1234         index = (arguments[0] << 8) + arguments[1]  1235         target = self.class_file.constants[index - 1]  1236         target_name = target.get_python_name()  1237         # Get the number of parameters from the descriptor.  1238         count = len(target.get_descriptor()[0])  1239         # Stack: arg1, arg2, ...  1240         program.build_tuple(count)      # Stack: tuple  1241         # Use the class to provide access to static methods.  1242         program.load_name("self")       # Stack: tuple, self  1243         program.load_attr("__class__")  # Stack: tuple, class  1244         self._invoke(target_name, program)  1245   1246     invokevirtual = invokeinterface # Ignoring Java rules  1247   1248     def ior(self, arguments, program):  1249         # NOTE: No type checking performed.  1250         program.binary_or()  1251   1252     irem = frem  1253     ireturn = freturn  1254   1255     def ishl(self, arguments, program):  1256         # NOTE: No type checking performed.  1257         # NOTE: Not verified.  1258         program.binary_lshift()  1259   1260     def ishr(self, arguments, program):  1261         # NOTE: No type checking performed.  1262         # NOTE: Not verified.  1263         program.binary_rshift()  1264   1265     istore = fstore  1266     istore_0 = fstore_0  1267     istore_1 = fstore_1  1268     istore_2 = fstore_2  1269     istore_3 = fstore_3  1270     isub = fsub  1271     iushr = ishr # Ignoring distinctions between arithmetic and logical shifts  1272   1273     def ixor(self, arguments, program):  1274         # NOTE: No type checking performed.  1275         program.binary_xor()  1276   1277     def jsr(self, arguments, program):  1278         offset = signed2((arguments[0] << 8) + arguments[1])  1279         java_absolute = self.java_position + offset  1280         # Store the address of the next instruction.  1281         program.load_const_ret(self.position_mapping[self.java_position + 3])  1282         program.jump_absolute(self.position_mapping[java_absolute])  1283   1284     def jsr_w(self, arguments, program):  1285         offset = signed4((arguments[0] << 24) + (arguments[1] << 16) + (arguments[2] << 8) + arguments[3])  1286         java_absolute = self.java_position + offset  1287         # Store the address of the next instruction.  1288         program.load_const_ret(self.position_mapping[self.java_position + 5])  1289         program.jump_absolute(self.position_mapping[java_absolute])  1290   1291     l2d = i2d  1292     l2f = i2f  1293   1294     def l2i(self, arguments, program):  1295         pass # Preserving Java semantics  1296   1297     ladd = iadd  1298     laload = iaload  1299     land = iand  1300     lastore = iastore  1301   1302     def lcmp(self, arguments, program):  1303         # NOTE: No type checking performed.  1304         program.dup_topx(2)                 # Stack: value1, value2, value1, value2  1305         program.compare_op(">")             # Stack: value1, value2, result  1306         program.jump_to_label(0, "equals")  1307         # True - produce result and branch.  1308         program.pop_top()                   # Stack: value1, value2  1309         program.pop_top()                   # Stack: value1  1310         program.pop_top()                   # Stack:  1311         program.load_const(1)               # Stack: 1  1312         program.jump_to_label(None, "next")  1313         # False - test equality.  1314         program.start_label("equals")  1315         program.pop_top()                   # Stack: value1, value2  1316         program.dup_topx(2)                 # Stack: value1, value2, value1, value2  1317         program.compare_op("==")            # Stack: value1, value2, result  1318         program.jump_to_label(0, "less")  1319         # True - produce result and branch.  1320         program.pop_top()                   # Stack: value1, value2  1321         program.pop_top()                   # Stack: value1  1322         program.pop_top()                   # Stack:  1323         program.load_const(0)               # Stack: 0  1324         program.jump_to_label(None, "next")  1325         # False - produce result.  1326         program.start_label("less")  1327         program.pop_top()                   # Stack: value1, value2  1328         program.pop_top()                   # Stack: value1  1329         program.pop_top()                   # Stack:  1330         program.load_const(-1)              # Stack: -1  1331         program.start_label("next")  1332   1333     lconst_0 = iconst_0  1334     lconst_1 = iconst_1  1335   1336     def ldc(self, arguments, program):  1337         program.load_const(self.class_file.constants[arguments[0] - 1])  1338   1339     def ldc_w(self, arguments, program):  1340         program.load_const(self.class_file.constants[(arguments[0] << 8) + arguments[1] - 1])  1341   1342     ldc2_w = ldc_w  1343     ldiv = idiv  1344     lload = iload  1345     lload_0 = iload_0  1346     lload_1 = iload_1  1347     lload_2 = iload_2  1348     lload_3 = iload_3  1349     lmul = imul  1350     lneg = ineg  1351   1352     def lookupswitch(self, arguments, program):  1353         # Find the offset to the next 4 byte boundary in the code.  1354         d, r = divmod(self.java_position, 4)  1355         to_boundary = (4 - r) % 4  1356         # Get the pertinent arguments.  1357         arguments = arguments[to_boundary:]  1358         default = (arguments[0] << 24) + (arguments[1] << 16) + (arguments[2] << 8) + arguments[3]  1359         npairs = (arguments[4] << 24) + (arguments[5] << 16) + (arguments[6] << 8) + arguments[7]  1360         # Process the pairs.  1361         # NOTE: This is not the most optimal implementation.  1362         pair_index = 8  1363         for pair in range(0, npairs):  1364             match = ((arguments[pair_index] << 24) + (arguments[pair_index + 1] << 16) +  1365                 (arguments[pair_index + 2] << 8) + arguments[pair_index + 3])  1366             offset = signed4((arguments[pair_index + 4] << 24) + (arguments[pair_index + 5] << 16) +  1367                 (arguments[pair_index + 6] << 8) + arguments[pair_index + 7])  1368             # Calculate the branch target.  1369             java_absolute = self.java_position + offset  1370             # Generate branching code.  1371             program.dup_top()                                           # Stack: key, key  1372             program.load_const(match)                                   # Stack: key, key, match  1373             program.compare_op("==")                                    # Stack: key, result  1374             program.jump_to_label(0, "end")  1375             program.pop_top()                                           # Stack: key  1376             program.pop_top()                                           # Stack:  1377             program.jump_absolute(self.position_mapping[java_absolute])  1378             # Generate the label for the end of the branching code.  1379             program.start_label("end")  1380             program.pop_top()                                           # Stack: key  1381             # Update the index.  1382             pair_index += 8  1383         # Generate the default.  1384         java_absolute = self.java_position + default  1385         program.jump_absolute(self.position_mapping[java_absolute])  1386   1387     lor = ior  1388     lrem = irem  1389     lreturn = ireturn  1390     lshl = ishl  1391     lshr = ishr  1392     lstore = istore  1393     lstore_0 = istore_0  1394     lstore_1 = istore_1  1395     lstore_2 = istore_2  1396     lstore_3 = istore_3  1397     lsub = isub  1398     lushr = iushr  1399     lxor = ixor  1400   1401     def monitorenter(self, arguments, program):  1402         # NOTE: To be implemented.  1403         pass  1404   1405     def monitorexit(self, arguments, program):  1406         # NOTE: To be implemented.  1407         pass  1408   1409     def multianewarray(self, arguments, program):  1410         # NOTE: To be implemented.  1411         pass  1412   1413     def new(self, arguments, program):  1414         # This operation is considered to be the same as the calling of the  1415         # initialisation method of the given class with no arguments.  1416         index = (arguments[0] << 8) + arguments[1]  1417         target_name = self.class_file.constants[index - 1].get_name()  1418         # NOTE: Using the string version of the name which may contain incompatible characters.  1419         program.load_global(str(target_name))  1420         program.call_function(0)  1421   1422     def newarray(self, arguments, program):  1423         # NOTE: Does not raise NegativeArraySizeException.  1424         # NOTE: Not using the arguments to type the list/array.  1425         self._newarray(program)  1426   1427     def nop(self, arguments, program):  1428         pass  1429   1430     def pop(self, arguments, program):  1431         program.pop_top()  1432   1433     pop2 = pop # ignoring Java stack value distinctions  1434   1435     def putfield(self, arguments, program):  1436         index = (arguments[0] << 8) + arguments[1]  1437         target_name = self.class_file.constants[index - 1].get_python_name()  1438         program.rot_two()  1439         # NOTE: Using the string version of the name which may contain incompatible characters.  1440         program.store_attr(str(target_name))  1441   1442     def putstatic(self, arguments, program):  1443         index = (arguments[0] << 8) + arguments[1]  1444         target_name = self.class_file.constants[index - 1].get_python_name()  1445         program.load_name("self")  1446         program.load_attr("__class__")  1447         # NOTE: Using the string version of the name which may contain incompatible characters.  1448         program.store_attr(str(target_name))  1449   1450     def ret(self, arguments, program):  1451         program.ret(arguments[0])  1452   1453     def return_(self, arguments, program):  1454         program.load_const(None)  1455         program.return_value()  1456   1457     saload = laload  1458     sastore = lastore  1459   1460     def sipush(self, arguments, program):  1461         program.load_const((arguments[0] << 8) + arguments[1])  1462   1463     def swap(self, arguments, program):  1464         program.rot_two()  1465   1466     def tableswitch(self, arguments, program):  1467         # Find the offset to the next 4 byte boundary in the code.  1468         d, r = divmod(self.java_position, 4)  1469         to_boundary = (4 - r) % 4  1470         # Get the pertinent arguments.  1471         arguments = arguments[to_boundary:]  1472         default = (arguments[0] << 24) + (arguments[1] << 16) + (arguments[2] << 8) + arguments[3]  1473         low = (arguments[4] << 24) + (arguments[5] << 16) + (arguments[6] << 8) + arguments[7]  1474         high = (arguments[8] << 24) + (arguments[9] << 16) + (arguments[10] << 8) + arguments[11]  1475         # Process the jump entries.  1476         # NOTE: This is not the most optimal implementation.  1477         jump_index = 8  1478         for jump in range(low, high + 1):  1479             offset = signed4((arguments[jump_index] << 24) + (arguments[jump_index + 1] << 16) +  1480                 (arguments[jump_index + 2] << 8) + arguments[jump_index + 3])  1481             # Calculate the branch target.  1482             java_absolute = self.java_position + offset  1483             # Generate branching code.  1484             program.dup_top()                                           # Stack: key, key  1485             program.load_const(jump)                                    # Stack: key, key, jump  1486             program.compare_op("==")                                    # Stack: key, result  1487             program.jump_to_label(0, "end")  1488             program.pop_top()                                           # Stack: key  1489             program.pop_top()                                           # Stack:  1490             program.jump_absolute(self.position_mapping[java_absolute])  1491             # Generate the label for the end of the branching code.  1492             program.start_label("end")  1493             program.pop_top()                                           # Stack: key  1494             # Update the index.  1495             jump_index += 8  1496         # Generate the default.  1497         java_absolute = self.java_position + default  1498         program.jump_absolute(self.position_mapping[java_absolute])  1499   1500     def wide(self, code, program):  1501         # NOTE: To be implemented.  1502         return number_of_arguments  1503   1504 def disassemble(class_file, code, exception_table):  1505     disassembler = BytecodeDisassembler(class_file)  1506     disassembler.process(code, exception_table, BytecodeDisassemblerProgram())  1507   1508 def translate(class_file, code, exception_table):  1509     translator = BytecodeTranslator(class_file)  1510     writer = BytecodeWriter()  1511     translator.process(code, exception_table, writer)  1512     return translator, writer  1513   1514 if __name__ == "__main__":  1515     import sys  1516     from classfile import ClassFile  1517     f = open(sys.argv[1])  1518     c = ClassFile(f.read())  1519   1520 # vim: tabstop=4 expandtab shiftwidth=4