javaclass

Changeset

5:d18e689a422d
2004-10-29 Paul Boddie raw files shortlog changelog graph Added a class for the reading and conversion of Java bytecodes, moved the bytecode table into this class, added some initial conversion methods.
bytecode.py (file)
     1.1 --- a/bytecode.py	Thu Oct 28 20:47:25 2004 +0200
     1.2 +++ b/bytecode.py	Fri Oct 29 18:48:35 2004 +0200
     1.3 @@ -3,238 +3,783 @@
     1.4  """
     1.5  Java bytecode conversion. Specification found at the following URL:
     1.6  http://java.sun.com/docs/books/vmspec/2nd-edition/html/Instructions2.doc.html
     1.7 +
     1.8 +NOTE: Synchronized constructs are not actually supported.
     1.9  """
    1.10  
    1.11  import dis # for access to Python bytecode values
    1.12  
    1.13 +# Bytecode production classes.
    1.14 +
    1.15 +class BytecodeWriter:
    1.16 +    def __init__(self):
    1.17 +        self.loops = []
    1.18 +        self.jumps = []
    1.19 +        self.output = []
    1.20 +        self.position = 0
    1.21 +
    1.22 +    # Special methods.
    1.23 +
    1.24 +    def end_loop(self):
    1.25 +        current_loop_start = self.loops.pop()
    1.26 +        self.jump_absolute(current_loop_start)
    1.27 +        self.output[current_loop_start + 1] = self.position
    1.28 +        self.pop_block()
    1.29 +
    1.30 +    def jump_to_next(self, status):
    1.31 +        self.jumps.push(self.position)
    1.32 +        if status:
    1.33 +            self.jump_if_true()
    1.34 +        else:
    1.35 +            self.jump_if_false()
    1.36 +
    1.37 +    def start_next(self):
    1.38 +        current_jump_start = self.jumps.pop()
    1.39 +        self.output[current_jump_start + 1] = self.position
    1.40 +
    1.41 +    # Normal bytecode generators.
    1.42 +
    1.43 +    def for_iter(self):
    1.44 +        self.loops.push(self.position)
    1.45 +        self.output.append(opmap["FOR_ITER"])
    1.46 +        self.output.append(None) # To be filled in later
    1.47 +        self.position += 2
    1.48 +
    1.49 +    def jump_if_false(self, offset=None):
    1.50 +        self.output.append(opmap["JUMP_IF_FALSE"])
    1.51 +        self.output.append(offset) # May be filled in later
    1.52 +        self.position += 2
    1.53 +
    1.54 +    def jump_if_true(self, offset=None):
    1.55 +        self.output.append(opmap["JUMP_IF_TRUE"])
    1.56 +        self.output.append(offset) # May be filled in later
    1.57 +        self.position += 2
    1.58 +
    1.59  # Bytecode conversion.
    1.60  
    1.61 -def get_instructions(code):
    1.62 -    global java_bytecodes
    1.63 +class BytecodeReader:
    1.64 +    def __init__(self, class_file):
    1.65 +        self.class_file = class_file
    1.66 +        self.position_mapping = {}
    1.67 +
    1.68 +    def process(self, code, program):
    1.69 +        self.java_position = 0
    1.70 +        while self.java_position < len(code):
    1.71 +            self.position_mapping[self.java_position] = program.position
    1.72 +            bytecode = ord(code[self.java_position])
    1.73 +            mnemonic, number_of_arguments = self.java_bytecodes[bytecode]
    1.74 +            self.process_bytecode(mnemonic, number_of_arguments)
    1.75 +
    1.76 +    def process_bytecode(self, mnemonic, number_of_arguments):
    1.77 +        if number_of_arguments is not None:
    1.78 +            arguments = []
    1.79 +            for j in range(0, number_of_arguments):
    1.80 +                arguments.append(ord(code[self.java_position + 1 + j]))
    1.81 +
    1.82 +            # Call the handler.
    1.83 +            getattr(self, mnemonic)(arguments, program)
    1.84 +        else:
    1.85 +            # Call the handler.
    1.86 +            number_of_arguments = getattr(self, mnemonic)(code[self.java_position+1:], program)
    1.87 +
    1.88 +        self.java_position = self.java_position + 1 + number_of_arguments
    1.89 +
    1.90 +    def nop(self, arguments, program):
    1.91 +        pass
    1.92 +
    1.93 +    def aaload(self, arguments, program):
    1.94 +        # NOTE: No type checking performed.
    1.95 +        program.binary_subscr()
    1.96 +
    1.97 +    def aastore(self, arguments, program):
    1.98 +        # NOTE: No type checking performed.
    1.99 +        # Stack: arrayref, index, value
   1.100 +        program.rot_three() # Stack: value, arrayref, index
   1.101 +        program.store_subscr()
   1.102 +
   1.103 +    def aconst_null(self, arguments, program):
   1.104 +        program.load_global(None)
   1.105 +
   1.106 +    def aload(self, arguments, program):
   1.107 +        program.load_fast(arguments[0])
   1.108 +
   1.109 +    def aload_0(self, arguments, program):
   1.110 +        program.load_fast(0)
   1.111 +
   1.112 +    def aload_1(self, arguments, program):
   1.113 +        program.load_fast(1)
   1.114 +
   1.115 +    def aload_2(self, arguments, program):
   1.116 +        program.load_fast(2)
   1.117 +
   1.118 +    def aload_3(self, arguments, program):
   1.119 +        program.load_fast(3)
   1.120 +
   1.121 +    def anewarray(self, arguments, program):
   1.122 +        # NOTE: Does not raise NegativeArraySizeException.
   1.123 +        # NOTE: Not using the index to type the list/array.
   1.124 +        index = arguments[0] << 8 + arguments[1]
   1.125 +
   1.126 +        program.build_list()
   1.127 +        program.setup_loop()
   1.128 +        program.load_global("range")
   1.129 +        program.load_const(0)       # Stack: list, count, range, 0
   1.130 +        program.rot_three()         # Stack: list, 0, count, range
   1.131 +        program.rot_three()         # Stack: list, range, 0, count
   1.132 +        program.call_function(2)    # Stack: list, range_list
   1.133 +        program.get_iter()          # Stack: list, iter
   1.134 +        program.for_iter()          # Stack: list, iter, value
   1.135 +        program.pop_top()           # Stack: list, iter
   1.136 +        program.rot_two()           # Stack: iter, list
   1.137 +        program.dup_top()           # Stack: iter, list, list
   1.138 +        program.load_attr("append") # Stack: iter, list, append
   1.139 +        program.load_global(None)   # Stack: iter, list, append, None
   1.140 +        program.call_function(1)    # Stack: iter, list, None
   1.141 +        program.pop_top()           # Stack: iter, list
   1.142 +        program.rot_two()           # Stack: list, iter
   1.143 +        program.end_loop()          # Back to for_iter above
   1.144 +
   1.145 +    def areturn(self, arguments, program):
   1.146 +        program.return_value()
   1.147 +
   1.148 +    def arraylength(self, arguments, program):
   1.149 +        program.load_global("len")  # Stack: arrayref, len
   1.150 +        program.rot_two()           # Stack: len, arrayref
   1.151 +        program.call_function(1)
   1.152  
   1.153 -    i = 0
   1.154 -    instructions = []
   1.155 -    while i < len(code):
   1.156 -        bytecode = ord(code[i])
   1.157 -        mnemonic, number_of_arguments, stack_change = java_bytecodes[bytecode]
   1.158 +    def astore(self, arguments, program):
   1.159 +        program.store_fast(arguments[0])
   1.160 +
   1.161 +    def astore_0(self, arguments, program):
   1.162 +        program.store_fast(0)
   1.163 +
   1.164 +    def astore_1(self, arguments, program):
   1.165 +        program.store_fast(1)
   1.166 +
   1.167 +    def astore_2(self, arguments, program):
   1.168 +        program.store_fast(2)
   1.169 +
   1.170 +    def astore_3(self, arguments, program):
   1.171 +        program.store_fast(3)
   1.172 +
   1.173 +    def athrow(self, arguments, program):
   1.174 +        # NOTE: NullPointerException not raised where null/None is found on the stack.
   1.175 +        program.raise_varargs(1)
   1.176 +
   1.177 +    baload = aaload
   1.178 +    bastore = aastore
   1.179 +
   1.180 +    def bipush(self, arguments, program):
   1.181 +        program.load_const(arguments[0])
   1.182 +
   1.183 +    caload = aaload
   1.184 +    castore = aastore
   1.185 +
   1.186 +    def checkcast(self, arguments, program):
   1.187 +        index = arguments[0] << 8 + arguments[1]
   1.188 +        target_name = self.class_file.constants[index - 1].get_name()
   1.189 +        target_components = target_name.split("/")
   1.190 +
   1.191 +        program.dup_top()                   # Stack: objectref, objectref
   1.192 +        program.load_global("isinstance")   # Stack: objectref, objectref, isinstance
   1.193 +        program.rot_two()                   # Stack: objectref, isinstance, objectref
   1.194 +        program.load_global(target_components[0])
   1.195 +        for target_component in target_components[1:]:
   1.196 +            program.load_attr(target_component)
   1.197 +        program.call_function(2)            # Stack: objectref
   1.198 +
   1.199 +    def d2f(self, arguments, program):
   1.200 +        pass
   1.201 +
   1.202 +    def d2i(self, arguments, program):
   1.203 +        program.load_global("int")  # Stack: value, int
   1.204 +        program.rot_two()           # Stack: int, value
   1.205 +        program.call_function(1)    # Stack: result
   1.206 +
   1.207 +    d2l = d2i # Preserving Java semantics
   1.208 +
   1.209 +    def dadd(self, arguments, program):
   1.210 +        # NOTE: No type checking performed.
   1.211 +        program.binary_add()
   1.212 +
   1.213 +    daload = aaload
   1.214 +    dastore = aastore
   1.215 +
   1.216 +    def dcmpg(self, arguments, program):
   1.217 +        # NOTE: No type checking performed.
   1.218 +        program.compare_op(">")
   1.219 +
   1.220 +    def dcmpl(self, arguments, program):
   1.221 +        # NOTE: No type checking performed.
   1.222 +        program.compare_op("<")
   1.223 +
   1.224 +    def dconst_0(self, arguments, program):
   1.225 +        program.load_const(0.0)
   1.226 +
   1.227 +    def dconst_1(self, arguments, program):
   1.228 +        program.load_const(1.0)
   1.229 +
   1.230 +    def ddiv(self, arguments, program):
   1.231 +        # NOTE: No type checking performed.
   1.232 +        program.binary_divide()
   1.233 +
   1.234 +    dload = aload
   1.235 +    dload_0 = aload_0
   1.236 +    dload_1 = aload_1
   1.237 +    dload_2 = aload_2
   1.238 +    dload_3 = aload_3
   1.239 +
   1.240 +    def dmul(self, arguments, program):
   1.241 +        # NOTE: No type checking performed.
   1.242 +        program.binary_multiply()
   1.243 +
   1.244 +    def dneg(self, arguments, program):
   1.245 +        # NOTE: No type checking performed.
   1.246 +        program.unary_negative()
   1.247  
   1.248 -        # NOTE: To be fixed.
   1.249 -        if number_of_arguments is None:
   1.250 -            print "Stop at", mnemonic
   1.251 -            return instructions
   1.252 +    def drem(self, arguments, program):
   1.253 +        # NOTE: No type checking performed.
   1.254 +        program.binary_modulo()
   1.255 +
   1.256 +    dreturn = areturn
   1.257 +    dstore = astore
   1.258 +    dstore_0 = astore_0
   1.259 +    dstore_1 = astore_1
   1.260 +    dstore_2 = astore_2
   1.261 +    dstore_3 = astore_3
   1.262 +
   1.263 +    def dsub(self, arguments, program):
   1.264 +        # NOTE: No type checking performed.
   1.265 +        program.binary_subtract()
   1.266 +
   1.267 +    def dup(self, arguments, program):
   1.268 +        program.dup_top()
   1.269 +
   1.270 +    def dup_x1(self, arguments, program):
   1.271 +        # Ignoring computational type categories.
   1.272 +        program.dup_top()
   1.273 +        program.rot_three()
   1.274 +
   1.275 +    def dup_x2(self, arguments, program):
   1.276 +        # Ignoring computational type categories.
   1.277 +        program.dup_top()
   1.278 +        program.rot_four()
   1.279 +
   1.280 +    dup2 = dup # Ignoring computational type categories
   1.281 +    dup2_x1 = dup_x1 # Ignoring computational type categories
   1.282 +    dup2_x2 = dup_x2 # Ignoring computational type categories
   1.283 +
   1.284 +    def f2d(self, arguments, program):
   1.285 +        pass # Preserving Java semantics
   1.286 +
   1.287 +    def f2i(self, arguments, program):
   1.288 +        program.load_global("int")  # Stack: value, int
   1.289 +        program.rot_two()           # Stack: int, value
   1.290 +        program.call_function(1)    # Stack: result
   1.291 +
   1.292 +    f2l = f2i # Preserving Java semantics
   1.293 +    fadd = dadd
   1.294 +    faload = daload
   1.295 +    fastore = dastore
   1.296 +    fcmpg = dcmpg
   1.297 +    fcmpl = dcmpl
   1.298 +    fconst_0 = dconst_0
   1.299 +    fconst_1 = dconst_1
   1.300 +
   1.301 +    def fconst_2(self, arguments, program):
   1.302 +        program.load_const(2.0)
   1.303 +
   1.304 +    fdiv = ddiv
   1.305 +    fload = dload
   1.306 +    fload_0 = dload_0
   1.307 +    fload_1 = dload_1
   1.308 +    fload_2 = dload_2
   1.309 +    fload_3 = dload_3
   1.310 +    fmul = dmul
   1.311 +    fneg = dneg
   1.312 +    frem = drem
   1.313 +    freturn = dreturn
   1.314 +    fstore = dstore
   1.315 +    fstore_0 = dstore_0
   1.316 +    fstore_1 = dstore_1
   1.317 +    fstore_2 = dstore_2
   1.318 +    fstore_3 = dstore_3
   1.319 +    fsub = dsub
   1.320 +
   1.321 +    def getfield(self, arguments, program):
   1.322 +        index = arguments[0] << 8 + arguments[1]
   1.323 +        target_name = self.class_file.constants[index - 1].get_name()
   1.324 +        # NOTE: Using the string version of the name which may contain incompatible characters.
   1.325 +        program.load_attr(str(target_name))
   1.326 +
   1.327 +    getstatic = getfield # Ignoring Java restrictions
   1.328 +
   1.329 +    def goto(self, arguments, program):
   1.330 +        offset = arguments[0] << 8 + arguments[1]
   1.331 +        java_absolute = self.java_position + offset
   1.332 +        program.jump_absolute(self.position_mapping[java_absolute])
   1.333 +
   1.334 +    def goto_w(self, arguments, program):
   1.335 +        offset = arguments[0] << 24 + arguments[1] << 16 + arguments[2] << 8 + arguments[3]
   1.336 +        java_absolute = self.java_position + offset
   1.337 +        program.jump_absolute(self.position_mapping[java_absolute])
   1.338 +
   1.339 +    def i2b(self, arguments, program):
   1.340 +        pass
   1.341  
   1.342 -        arguments = []
   1.343 -        for j in range(0, number_of_arguments):
   1.344 -            arguments.append(ord(code[i + 1 + j]))
   1.345 +    def i2c(self, arguments, program):
   1.346 +        program.load_global("chr")  # Stack: value, chr
   1.347 +        program.rot_two()           # Stack: chr, value
   1.348 +        program.call_function(1)    # Stack: result
   1.349 +
   1.350 +    def i2d(self, arguments, program):
   1.351 +        program.load_global("float")    # Stack: value, float
   1.352 +        program.rot_two()               # Stack: float, value
   1.353 +        program.call_function(1)        # Stack: result
   1.354 +
   1.355 +    i2f = i2d # Not distinguishing between float and double
   1.356 +
   1.357 +    def i2l(self, arguments, program):
   1.358 +        pass # Preserving Java semantics
   1.359 +
   1.360 +    def i2s(self, arguments, program):
   1.361 +        pass # Not distinguishing between int and short
   1.362 +
   1.363 +    iadd = fadd
   1.364 +    iaload = faload
   1.365 +
   1.366 +    def iand(self, arguments, program):
   1.367 +        # NOTE: No type checking performed.
   1.368 +        program.binary_and()
   1.369 +
   1.370 +    iastore = fastore
   1.371 +
   1.372 +    def iconst_m1(self, arguments, program):
   1.373 +        program.load_const(-1)
   1.374 +
   1.375 +    def iconst_0(self, arguments, program):
   1.376 +        program.load_const(0)
   1.377 +
   1.378 +    def iconst_1(self, arguments, program):
   1.379 +        program.load_const(1)
   1.380 +
   1.381 +    def iconst_2(self, arguments, program):
   1.382 +        program.load_const(2)
   1.383 +
   1.384 +    def iconst_3(self, arguments, program):
   1.385 +        program.load_const(3)
   1.386 +
   1.387 +    def iconst_4(self, arguments, program):
   1.388 +        program.load_const(4)
   1.389  
   1.390 -        i = i + 1 + number_of_arguments
   1.391 -        instructions.append((mnemonic, arguments))
   1.392 +    def iconst_5(self, arguments, program):
   1.393 +        program.load_const(5)
   1.394 +
   1.395 +    idiv = fdiv
   1.396 +
   1.397 +    def _if_xcmpx(self, arguments, program, op):
   1.398 +        offset = arguments[0] << 8 + arguments[1]
   1.399 +        java_absolute = self.java_position + offset
   1.400 +        program.compare_op(op)
   1.401 +        program.jump_to_next(0) # skip if false
   1.402 +        program.goto(offset)
   1.403 +        program.start_next()
   1.404 +
   1.405 +    def if_acmpeq(self, arguments, program):
   1.406 +        # NOTE: No type checking performed.
   1.407 +        self._if_xcmpx(arguments, program, "is")
   1.408 +
   1.409 +    def if_acmpne(self, arguments, program):
   1.410 +        # NOTE: No type checking performed.
   1.411 +        self._if_xcmpx(arguments, program, "is not")
   1.412  
   1.413 -    return instructions
   1.414 +    def if_icmpeq(self, arguments, program):
   1.415 +        # NOTE: No type checking performed.
   1.416 +        self._if_xcmpx(arguments, program, "==")
   1.417 +
   1.418 +    def if_icmpne(self, arguments, program):
   1.419 +        # NOTE: No type checking performed.
   1.420 +        self._if_xcmpx(arguments, program, "!=")
   1.421 +
   1.422 +    def if_icmplt(self, arguments, program):
   1.423 +        # NOTE: No type checking performed.
   1.424 +        self._if_xcmpx(arguments, program, "<")
   1.425 +
   1.426 +    def if_icmpge(self, arguments, program):
   1.427 +        # NOTE: No type checking performed.
   1.428 +        self._if_xcmpx(arguments, program, ">=")
   1.429 +
   1.430 +    def if_icmpgt(self, arguments, program):
   1.431 +        # NOTE: No type checking performed.
   1.432 +        self._if_xcmpx(arguments, program, ">")
   1.433 +
   1.434 +    def if_icmple(self, arguments, program):
   1.435 +        # NOTE: No type checking performed.
   1.436 +        self._if_xcmpx(arguments, program, "<=")
   1.437  
   1.438 -java_bytecodes = {
   1.439 -    # code : (mnemonic, number of following bytes, change in stack)
   1.440 -    0 : ("nop", 0, 0),
   1.441 -    1 : ("aconst_null", 0, 1),
   1.442 -    2 : ("iconst_m1", 0, 1),
   1.443 -    3 : ("iconst_0", 0, 1),
   1.444 -    4 : ("iconst_1", 0, 1),
   1.445 -    5 : ("iconst_2", 0, 1),
   1.446 -    6 : ("iconst_3", 0, 1),
   1.447 -    7 : ("iconst_4", 0, 1),
   1.448 -    8 : ("iconst_5", 0, 1),
   1.449 -    9 : ("lconst_0", 0, 1),
   1.450 -    10 : ("lconst_1", 0, 1),
   1.451 -    11 : ("fconst_0", 0, 1),
   1.452 -    12 : ("fconst_1", 0, 1),
   1.453 -    13 : ("fconst_2", 0, 1),
   1.454 -    14 : ("dconst_0", 0, 1),
   1.455 -    15 : ("dconst_1", 0, 1),
   1.456 -    16 : ("bipush", 1, 1),
   1.457 -    17 : ("sipush", 2, 1),
   1.458 -    18 : ("ldc", 1, 1),
   1.459 -    19 : ("ldc_w", 2, 1),
   1.460 -    20 : ("ldc2_w", 2, 1),
   1.461 -    21 : ("iload", 1, 1),
   1.462 -    22 : ("lload", 1, 1),
   1.463 -    23 : ("fload", 1, 1),
   1.464 -    24 : ("dload", 1, 1),
   1.465 -    25 : ("aload", 1, 1),
   1.466 -    26 : ("iload_0", 0, 1),
   1.467 -    27 : ("iload_1", 0, 1),
   1.468 -    28 : ("iload_2", 0, 1),
   1.469 -    29 : ("iload_3", 0, 1),
   1.470 -    30 : ("lload_0", 0, 1),
   1.471 -    31 : ("lload_1", 0, 1),
   1.472 -    32 : ("lload_2", 0, 1),
   1.473 -    33 : ("lload_3", 0, 1),
   1.474 -    34 : ("fload_0", 0, 1),
   1.475 -    35 : ("fload_1", 0, 1),
   1.476 -    36 : ("fload_2", 0, 1),
   1.477 -    37 : ("fload_3", 0, 1),
   1.478 -    38 : ("dload_0", 0, 1),
   1.479 -    39 : ("dload_1", 0, 1),
   1.480 -    40 : ("dload_2", 0, 1),
   1.481 -    41 : ("dload_3", 0, 1),
   1.482 -    42 : ("aload_0", 0, 1),
   1.483 -    43 : ("aload_1", 0, 1),
   1.484 -    44 : ("aload_2", 0, 1),
   1.485 -    45 : ("aload_3", 0, 1),
   1.486 -    46 : ("iaload", 0, -1),
   1.487 -    47 : ("laload", 0, -1),
   1.488 -    48 : ("faload", 0, -1),
   1.489 -    49 : ("daload", 0, -1),
   1.490 -    50 : ("aaload", 0, -1),
   1.491 -    51 : ("baload", 0, -1),
   1.492 -    52 : ("caload", 0, -1),
   1.493 -    53 : ("saload", 0, -1),
   1.494 -    54 : ("istore", 1, -1),
   1.495 -    55 : ("lstore", 1, -1),
   1.496 -    56 : ("fstore", 1, -1),
   1.497 -    57 : ("dstore", 1, -1),
   1.498 -    58 : ("astore", 1, -1),
   1.499 -    59 : ("istore_0", 0, -1),
   1.500 -    60 : ("istore_1", 0, -1),
   1.501 -    61 : ("istore_2", 0, -1),
   1.502 -    62 : ("istore_3", 0, -1),
   1.503 -    63 : ("lstore_0", 0, -1),
   1.504 -    64 : ("lstore_1", 0, -1),
   1.505 -    65 : ("lstore_2", 0, -1),
   1.506 -    66 : ("lstore_3", 0, -1),
   1.507 -    67 : ("fstore_0", 0, -1),
   1.508 -    68 : ("fstore_1", 0, -1),
   1.509 -    69 : ("fstore_2", 0, -1),
   1.510 -    70 : ("fstore_3", 0, -1),
   1.511 -    71 : ("dstore_0", 0, -1),
   1.512 -    72 : ("dstore_1", 0, -1),
   1.513 -    73 : ("dstore_2", 0, -1),
   1.514 -    74 : ("dstore_3", 0, -1),
   1.515 -    75 : ("astore_0", 0, -1),
   1.516 -    76 : ("astore_1", 0, -1),
   1.517 -    77 : ("astore_2", 0, -1),
   1.518 -    78 : ("astore_3", 0, -1),
   1.519 -    79 : ("iastore", 0, -3),
   1.520 -    80 : ("lastore", 0, -3),
   1.521 -    81 : ("fastore", 0, -3),
   1.522 -    82 : ("dastore", 0, -3),
   1.523 -    83 : ("aastore", 0, -3),
   1.524 -    84 : ("bastore", 0, -3),
   1.525 -    85 : ("castore", 0, -3),
   1.526 -    86 : ("sastore", 0, -3),
   1.527 -    87 : ("pop", 0, -1),
   1.528 -    88 : ("pop2", 0, None), # variable number of elements removed
   1.529 -    89 : ("dup", 0, 1),
   1.530 -    90 : ("dup_x1", 0, 1),
   1.531 -    91 : ("dup_x2", 0, 1),
   1.532 -    92 : ("dup2", 0, 2), # or 1 extra stack value
   1.533 -    93 : ("dup2_x1", 0, 2), # or 1 extra stack value
   1.534 -    94 : ("dup2_x2", 0, 2), # or 1 extra stack value
   1.535 -    95 : ("swap", 0, 0),
   1.536 -    96 : ("iadd", 0, -1),
   1.537 -    97 : ("ladd", 0, -1),
   1.538 -    98 : ("fadd", 0, -1),
   1.539 -    99 : ("dadd", 0, -1),
   1.540 -    100 : ("isub", 0, -1),
   1.541 -    101 : ("lsub", 0, -1),
   1.542 -    102 : ("fsub", 0, -1),
   1.543 -    103 : ("dsub", 0, -1),
   1.544 -    104 : ("imul", 0, -1),
   1.545 -    105 : ("lmul", 0, -1),
   1.546 -    106 : ("fmul", 0, -1),
   1.547 -    107 : ("dmul", 0, -1),
   1.548 -    108 : ("idiv", 0, -1),
   1.549 -    109 : ("ldiv", 0, -1),
   1.550 -    110 : ("fdiv", 0, -1),
   1.551 -    111 : ("ddiv", 0, -1),
   1.552 -    112 : ("irem", 0, -1),
   1.553 -    113 : ("lrem", 0, -1),
   1.554 -    114 : ("frem", 0, -1),
   1.555 -    115 : ("drem", 0, -1),
   1.556 -    116 : ("ineg", 0, 0),
   1.557 -    117 : ("lneg", 0, 0),
   1.558 -    118 : ("fneg", 0, 0),
   1.559 -    119 : ("dneg", 0, 0),
   1.560 -    120 : ("ishl", 0, -1),
   1.561 -    121 : ("lshl", 0, -1),
   1.562 -    122 : ("ishr", 0, -1),
   1.563 -    123 : ("lshr", 0, -1),
   1.564 -    124 : ("iushr", 0, -1),
   1.565 -    125 : ("lushr", 0, -1),
   1.566 -    126 : ("iand", 0, -1),
   1.567 -    127 : ("land", 0, -1),
   1.568 -    128 : ("ior", 0, -1),
   1.569 -    129 : ("lor", 0, -1),
   1.570 -    130 : ("ixor", 0, -1),
   1.571 -    131 : ("lxor", 0, -1),
   1.572 -    132 : ("iinc", 2, 0),
   1.573 -    133 : ("i2l", 0, 0),
   1.574 -    134 : ("i2f", 0, 0),
   1.575 -    135 : ("i2d", 0, 0),
   1.576 -    136 : ("l2i", 0, 0),
   1.577 -    137 : ("l2f", 0, 0),
   1.578 -    138 : ("l2d", 0, 0),
   1.579 -    139 : ("f2i", 0, 0),
   1.580 -    140 : ("f2l", 0, 0),
   1.581 -    141 : ("f2d", 0, 0),
   1.582 -    142 : ("d2i", 0, 0),
   1.583 -    143 : ("d2l", 0, 0),
   1.584 -    144 : ("d2f", 0, 0),
   1.585 -    145 : ("i2b", 0, 0),
   1.586 -    146 : ("i2c", 0, 0),
   1.587 -    147 : ("i2s", 0, 0),
   1.588 -    148 : ("lcmp", 0, -1),
   1.589 -    149 : ("fcmpl", 0, -1),
   1.590 -    150 : ("fcmpg", 0, -1),
   1.591 -    151 : ("dcmpl", 0, -1),
   1.592 -    152 : ("dcmpg", 0, -1),
   1.593 -    153 : ("ifeq", 2, -1),
   1.594 -    154 : ("ifne", 2, -1),
   1.595 -    155 : ("iflt", 2, -1),
   1.596 -    156 : ("ifge", 2, -1),
   1.597 -    157 : ("ifgt", 2, -1),
   1.598 -    158 : ("ifle", 2, -1),
   1.599 -    159 : ("if_icmpeq", 2, -2),
   1.600 -    160 : ("if_icmpne", 2, -2),
   1.601 -    161 : ("if_icmplt", 2, -2),
   1.602 -    162 : ("if_icmpge", 2, -2),
   1.603 -    163 : ("if_icmpgt", 2, -2),
   1.604 -    164 : ("if_icmple", 2, -2),
   1.605 -    165 : ("if_acmpeq", 2, -2),
   1.606 -    166 : ("if_acmpne", 2, -2),
   1.607 -    167 : ("goto", 2, 0),
   1.608 -    168 : ("jsr", 2, 1),
   1.609 -    169 : ("ret", 1, 0),
   1.610 -    170 : ("tableswitch", None, -1), # variable number of arguments
   1.611 -    171 : ("lookupswitch", None, -1), # variable number of arguments
   1.612 -    172 : ("ireturn", 0, -1),
   1.613 -    173 : ("lreturn", 0, -1),
   1.614 -    174 : ("freturn", 0, -1),
   1.615 -    175 : ("dreturn", 0, -1),
   1.616 -    176 : ("areturn", 0, -1),
   1.617 -    177 : ("return", 0, 0),
   1.618 -    178 : ("getstatic", 2, 1),
   1.619 -    179 : ("putstatic", 2, -1),
   1.620 -    180 : ("getfield", 2, 0),
   1.621 -    181 : ("putfield", 2, -2),
   1.622 -    182 : ("invokevirtual", 2, None), # variable number of elements removed
   1.623 -    183 : ("invokespecial", 2, None), # variable number of elements removed
   1.624 -    184 : ("invokestatic", 2, None), # variable number of elements removed
   1.625 -    185 : ("invokeinterface", 4, None), # variable number of elements removed
   1.626 -    187 : ("new", 2, 1),
   1.627 -    188 : ("newarray", 1, 0),
   1.628 -    189 : ("anewarray", 2, 0),
   1.629 -    190 : ("arraylength", 0, 0),
   1.630 -    191 : ("athrow", 0, 0),
   1.631 -    192 : ("checkcast", 2, 0),
   1.632 -    193 : ("instanceof", 2, 0),
   1.633 -    194 : ("monitorenter", 0, -1),
   1.634 -    195 : ("monitorexit", 0, -1),
   1.635 -    196 : ("wide", None, None), # 3 or 5 arguments, stack changes according to modified element
   1.636 -    197 : ("multianewarray", 3, None), # variable number of elements removed
   1.637 -    198 : ("ifnull", 2, -1),
   1.638 -    199 : ("ifnonnull", 2, -1),
   1.639 -    200 : ("goto_w", 4, 0),
   1.640 -    201 : ("jsr_w", 4, 1),
   1.641 -    }
   1.642 +    def ifeq(self, arguments, program):
   1.643 +        # NOTE: No type checking performed.
   1.644 +        program.load_const(0)
   1.645 +        self._if_xcmpx(arguments, program, "==")
   1.646 +
   1.647 +    def ifne(self, arguments, program):
   1.648 +        # NOTE: No type checking performed.
   1.649 +        program.load_const(0)
   1.650 +        self._if_xcmpx(arguments, program, "!=")
   1.651 +
   1.652 +    def iflt(self, arguments, program):
   1.653 +        # NOTE: No type checking performed.
   1.654 +        program.load_const(0)
   1.655 +        self._if_xcmpx(arguments, program, "<")
   1.656 +
   1.657 +    def ifge(self, arguments, program):
   1.658 +        # NOTE: No type checking performed.
   1.659 +        program.load_const(0)
   1.660 +        self._if_xcmpx(arguments, program, ">=")
   1.661 +
   1.662 +    def ifgt(self, arguments, program):
   1.663 +        # NOTE: No type checking performed.
   1.664 +        program.load_const(0)
   1.665 +        self._if_xcmpx(arguments, program, ">")
   1.666 +
   1.667 +    def ifle(self, arguments, program):
   1.668 +        # NOTE: No type checking performed.
   1.669 +        program.load_const(0)
   1.670 +        self._if_xcmpx(arguments, program, "<=")
   1.671 +
   1.672 +    def ifnonnull(self, arguments, program):
   1.673 +        # NOTE: No type checking performed.
   1.674 +        program.load_const(None)
   1.675 +        self._if_xcmpx(arguments, program, "is not")
   1.676 +
   1.677 +    def ifnull(self, arguments, program):
   1.678 +        # NOTE: No type checking performed.
   1.679 +        program.load_const(None)
   1.680 +        self._if_xcmpx(arguments, program, "is")
   1.681 +
   1.682 +    def iinc(self, arguments, program):
   1.683 +        # NOTE: No type checking performed.
   1.684 +        program.load_fast(arguments[0])
   1.685 +        program.load_const(arguments[1])
   1.686 +        program.binary_add()
   1.687 +
   1.688 +    iload = fload
   1.689 +    iload_0 = fload_0
   1.690 +    iload_1 = fload_1
   1.691 +    iload_2 = fload_2
   1.692 +    iload_3 = fload_3
   1.693 +    imul = fmul
   1.694 +    ineg = fneg
   1.695 +
   1.696 +    def instanceof(self, arguments, program):
   1.697 +        index = arguments[0] << 8 + arguments[1]
   1.698 +        target_name = self.class_file.constants[index - 1].get_name()
   1.699 +        target_components = target_name.split("/")
   1.700 +
   1.701 +        program.load_global("isinstance")   # Stack: objectref, isinstance
   1.702 +        program.rot_two()                   # Stack: isinstance, objectref
   1.703 +        program.load_global(target_components[0])
   1.704 +        for target_component in target_components[1:]:
   1.705 +            program.load_attr(target_component)
   1.706 +        program.call_function(2)            # Stack: result
   1.707 +
   1.708 +    def _invoke(self, target_name, program):
   1.709 +        program.rot_two()                   # Stack: tuple, objectref
   1.710 +        # NOTE: Using the string version of the name which may contain incompatible characters.
   1.711 +        program.load_attr(str(target_name)) # Stack: tuple, method
   1.712 +        program.rot_two()                   # Stack: method, tuple
   1.713 +        program.load_global("apply")        # Stack: method, tuple, apply
   1.714 +        program.rot_three()                 # Stack: apply, method, tuple
   1.715 +        program.call_function(2)
   1.716 +
   1.717 +    def invokeinterface(self, arguments, program):
   1.718 +        # NOTE: This implementation does not perform the necessary checks for
   1.719 +        # NOTE: signature-based polymorphism.
   1.720 +        # NOTE: Java rules not specifically obeyed.
   1.721 +        index = arguments[0] << 8 + arguments[1]
   1.722 +        count = arguments[2]
   1.723 +        target_name = self.class_file.constants[index - 1].get_name()
   1.724 +        # Stack: objectref, arg1, arg2, ...
   1.725 +        program.build_tuple(count)          # Stack: objectref, tuple
   1.726 +        self._invoke(target_name, program)
   1.727 +
   1.728 +    def invokespecial(self, arguments, program):
   1.729 +        # NOTE: This implementation does not perform the necessary checks for
   1.730 +        # NOTE: signature-based polymorphism.
   1.731 +        # NOTE: Java rules not specifically obeyed.
   1.732 +        index = arguments[0] << 8 + arguments[1]
   1.733 +        target = self.class_file.constants[index - 1]
   1.734 +        target_name = target.get_name()
   1.735 +        # Get the number of parameters from the descriptor.
   1.736 +        count = len(target.get_descriptor()[0])
   1.737 +        # Stack: objectref, arg1, arg2, ...
   1.738 +        program.build_tuple(count)          # Stack: objectref, tuple
   1.739 +        self._invoke(target_name, program)
   1.740 +
   1.741 +    def invokestatic(self, arguments, program):
   1.742 +        # NOTE: This implementation does not perform the necessary checks for
   1.743 +        # NOTE: signature-based polymorphism.
   1.744 +        # NOTE: Java rules not specifically obeyed.
   1.745 +        index = arguments[0] << 8 + arguments[1]
   1.746 +        target = self.class_file.constants[index - 1]
   1.747 +        target_name = target.get_name()
   1.748 +        # Get the number of parameters from the descriptor.
   1.749 +        count = len(target.get_descriptor()[0])
   1.750 +        # Stack: arg1, arg2, ...
   1.751 +        program.build_tuple(count)  # Stack: tuple
   1.752 +        # NOTE: Should probably use Python static methods.
   1.753 +        program.load_name("self")   # Stack: tuple, self
   1.754 +        self._invoke(target_name, program)
   1.755 +
   1.756 +    invokevirtual = invokeinterface # Ignoring Java rules
   1.757 +
   1.758 +    def ior(self, arguments, program):
   1.759 +        # NOTE: No type checking performed.
   1.760 +        program.binary_or()
   1.761 +
   1.762 +    irem = frem
   1.763 +    ireturn = freturn
   1.764 +
   1.765 +    def ishl(self, arguments, program):
   1.766 +        # NOTE: No type checking performed.
   1.767 +        # NOTE: Not verified.
   1.768 +        program.binary_lshift()
   1.769 +
   1.770 +    def ishr(self, arguments, program):
   1.771 +        # NOTE: No type checking performed.
   1.772 +        # NOTE: Not verified.
   1.773 +        program.binary_rshift()
   1.774 +
   1.775 +    istore = fstore
   1.776 +    istore_0 = fstore_0
   1.777 +    istore_1 = fstore_1
   1.778 +    istore_2 = fstore_2
   1.779 +    istore_3 = fstore_3
   1.780 +    isub = fsub
   1.781 +    iushr = ishr # Ignoring distinctions between arithmetic and logical shifts
   1.782 +
   1.783 +    def ishr(self, arguments, program):
   1.784 +        # NOTE: No type checking performed.
   1.785 +        program.binary_xor()
   1.786 +
   1.787 +    def jsr(self, arguments, program):
   1.788 +        offset = arguments[0] << 8 + arguments[1]
   1.789 +        java_absolute = self.java_position + offset
   1.790 +        # NOTE: To be implemented.
   1.791 +
   1.792 +    def wide(self, code, program):
   1.793 +        # NOTE: To be implemented.
   1.794 +        return number_of_arguments
   1.795 +
   1.796 +    java_bytecodes = {
   1.797 +        # code : (mnemonic, number of following bytes, change in stack)
   1.798 +        0 : ("nop", 0),
   1.799 +        1 : ("aconst_null", 0),
   1.800 +        2 : ("iconst_m1", 0),
   1.801 +        3 : ("iconst_0", 0),
   1.802 +        4 : ("iconst_1", 0),
   1.803 +        5 : ("iconst_2", 0),
   1.804 +        6 : ("iconst_3", 0),
   1.805 +        7 : ("iconst_4", 0),
   1.806 +        8 : ("iconst_5", 0),
   1.807 +        9 : ("lconst_0", 0),
   1.808 +        10 : ("lconst_1", 0),
   1.809 +        11 : ("fconst_0", 0),
   1.810 +        12 : ("fconst_1", 0),
   1.811 +        13 : ("fconst_2", 0),
   1.812 +        14 : ("dconst_0", 0),
   1.813 +        15 : ("dconst_1", 0),
   1.814 +        16 : ("bipush", 1),
   1.815 +        17 : ("sipush", 2),
   1.816 +        18 : ("ldc", 1),
   1.817 +        19 : ("ldc_w", 2),
   1.818 +        20 : ("ldc2_w", 2),
   1.819 +        21 : ("iload", 1),
   1.820 +        22 : ("lload", 1),
   1.821 +        23 : ("fload", 1),
   1.822 +        24 : ("dload", 1),
   1.823 +        25 : ("aload", 1),
   1.824 +        26 : ("iload_0", 0),
   1.825 +        27 : ("iload_1", 0),
   1.826 +        28 : ("iload_2", 0),
   1.827 +        29 : ("iload_3", 0),
   1.828 +        30 : ("lload_0", 0),
   1.829 +        31 : ("lload_1", 0),
   1.830 +        32 : ("lload_2", 0),
   1.831 +        33 : ("lload_3", 0),
   1.832 +        34 : ("fload_0", 0),
   1.833 +        35 : ("fload_1", 0),
   1.834 +        36 : ("fload_2", 0),
   1.835 +        37 : ("fload_3", 0),
   1.836 +        38 : ("dload_0", 0),
   1.837 +        39 : ("dload_1", 0),
   1.838 +        40 : ("dload_2", 0),
   1.839 +        41 : ("dload_3", 0),
   1.840 +        42 : ("aload_0", 0),
   1.841 +        43 : ("aload_1", 0),
   1.842 +        44 : ("aload_2", 0),
   1.843 +        45 : ("aload_3", 0),
   1.844 +        46 : ("iaload", 0),
   1.845 +        47 : ("laload", 0),
   1.846 +        48 : ("faload", 0),
   1.847 +        49 : ("daload", 0),
   1.848 +        50 : ("aaload", 0),
   1.849 +        51 : ("baload", 0),
   1.850 +        52 : ("caload", 0),
   1.851 +        53 : ("saload", 0),
   1.852 +        54 : ("istore", 1),
   1.853 +        55 : ("lstore", 1),
   1.854 +        56 : ("fstore", 1),
   1.855 +        57 : ("dstore", 1),
   1.856 +        58 : ("astore", 1),
   1.857 +        59 : ("istore_0", 0),
   1.858 +        60 : ("istore_1", 0),
   1.859 +        61 : ("istore_2", 0),
   1.860 +        62 : ("istore_3", 0),
   1.861 +        63 : ("lstore_0", 0),
   1.862 +        64 : ("lstore_1", 0),
   1.863 +        65 : ("lstore_2", 0),
   1.864 +        66 : ("lstore_3", 0),
   1.865 +        67 : ("fstore_0", 0),
   1.866 +        68 : ("fstore_1", 0),
   1.867 +        69 : ("fstore_2", 0),
   1.868 +        70 : ("fstore_3", 0),
   1.869 +        71 : ("dstore_0", 0),
   1.870 +        72 : ("dstore_1", 0),
   1.871 +        73 : ("dstore_2", 0),
   1.872 +        74 : ("dstore_3", 0),
   1.873 +        75 : ("astore_0", 0),
   1.874 +        76 : ("astore_1", 0),
   1.875 +        77 : ("astore_2", 0),
   1.876 +        78 : ("astore_3", 0),
   1.877 +        79 : ("iastore", 0),
   1.878 +        80 : ("lastore", 0),
   1.879 +        81 : ("fastore", 0),
   1.880 +        82 : ("dastore", 0),
   1.881 +        83 : ("aastore", 0),
   1.882 +        84 : ("bastore", 0),
   1.883 +        85 : ("castore", 0),
   1.884 +        86 : ("sastore", 0),
   1.885 +        87 : ("pop", 0),
   1.886 +        88 : ("pop2", 0),
   1.887 +        89 : ("dup", 0),
   1.888 +        90 : ("dup_x1", 0),
   1.889 +        91 : ("dup_x2", 0),
   1.890 +        92 : ("dup2", 0),
   1.891 +        93 : ("dup2_x1", 0),
   1.892 +        94 : ("dup2_x2", 0),
   1.893 +        95 : ("swap", 0),
   1.894 +        96 : ("iadd", 0),
   1.895 +        97 : ("ladd", 0),
   1.896 +        98 : ("fadd", 0),
   1.897 +        99 : ("dadd", 0),
   1.898 +        100 : ("isub", 0),
   1.899 +        101 : ("lsub", 0),
   1.900 +        102 : ("fsub", 0),
   1.901 +        103 : ("dsub", 0),
   1.902 +        104 : ("imul", 0),
   1.903 +        105 : ("lmul", 0),
   1.904 +        106 : ("fmul", 0),
   1.905 +        107 : ("dmul", 0),
   1.906 +        108 : ("idiv", 0),
   1.907 +        109 : ("ldiv", 0),
   1.908 +        110 : ("fdiv", 0),
   1.909 +        111 : ("ddiv", 0),
   1.910 +        112 : ("irem", 0),
   1.911 +        113 : ("lrem", 0),
   1.912 +        114 : ("frem", 0),
   1.913 +        115 : ("drem", 0),
   1.914 +        116 : ("ineg", 0),
   1.915 +        117 : ("lneg", 0),
   1.916 +        118 : ("fneg", 0),
   1.917 +        119 : ("dneg", 0),
   1.918 +        120 : ("ishl", 0),
   1.919 +        121 : ("lshl", 0),
   1.920 +        122 : ("ishr", 0),
   1.921 +        123 : ("lshr", 0),
   1.922 +        124 : ("iushr", 0),
   1.923 +        125 : ("lushr", 0),
   1.924 +        126 : ("iand", 0),
   1.925 +        127 : ("land", 0),
   1.926 +        128 : ("ior", 0),
   1.927 +        129 : ("lor", 0),
   1.928 +        130 : ("ixor", 0),
   1.929 +        131 : ("lxor", 0),
   1.930 +        132 : ("iinc", 2),
   1.931 +        133 : ("i2l", 0),
   1.932 +        134 : ("i2f", 0),
   1.933 +        135 : ("i2d", 0),
   1.934 +        136 : ("l2i", 0),
   1.935 +        137 : ("l2f", 0),
   1.936 +        138 : ("l2d", 0),
   1.937 +        139 : ("f2i", 0),
   1.938 +        140 : ("f2l", 0),
   1.939 +        141 : ("f2d", 0),
   1.940 +        142 : ("d2i", 0),
   1.941 +        143 : ("d2l", 0),
   1.942 +        144 : ("d2f", 0),
   1.943 +        145 : ("i2b", 0),
   1.944 +        146 : ("i2c", 0),
   1.945 +        147 : ("i2s", 0),
   1.946 +        148 : ("lcmp", 0),
   1.947 +        149 : ("fcmpl", 0),
   1.948 +        150 : ("fcmpg", 0),
   1.949 +        151 : ("dcmpl", 0),
   1.950 +        152 : ("dcmpg", 0),
   1.951 +        153 : ("ifeq", 2),
   1.952 +        154 : ("ifne", 2),
   1.953 +        155 : ("iflt", 2),
   1.954 +        156 : ("ifge", 2),
   1.955 +        157 : ("ifgt", 2),
   1.956 +        158 : ("ifle", 2),
   1.957 +        159 : ("if_icmpeq", 2),
   1.958 +        160 : ("if_icmpne", 2),
   1.959 +        161 : ("if_icmplt", 2),
   1.960 +        162 : ("if_icmpge", 2),
   1.961 +        163 : ("if_icmpgt", 2),
   1.962 +        164 : ("if_icmple", 2),
   1.963 +        165 : ("if_acmpeq", 2),
   1.964 +        166 : ("if_acmpne", 2),
   1.965 +        167 : ("goto", 2),
   1.966 +        168 : ("jsr", 2),
   1.967 +        169 : ("ret", 1),
   1.968 +        170 : ("tableswitch", None), # variable number of arguments
   1.969 +        171 : ("lookupswitch", None), # variable number of arguments
   1.970 +        172 : ("ireturn", 0),
   1.971 +        173 : ("lreturn", 0),
   1.972 +        174 : ("freturn", 0),
   1.973 +        175 : ("dreturn", 0),
   1.974 +        176 : ("areturn", 0),
   1.975 +        177 : ("return", 0),
   1.976 +        178 : ("getstatic", 2),
   1.977 +        179 : ("putstatic", 2),
   1.978 +        180 : ("getfield", 2),
   1.979 +        181 : ("putfield", 2),
   1.980 +        182 : ("invokevirtual", 2),
   1.981 +        183 : ("invokespecial", 2),
   1.982 +        184 : ("invokestatic", 2),
   1.983 +        185 : ("invokeinterface", 4),
   1.984 +        187 : ("new", 2),
   1.985 +        188 : ("newarray", 1),
   1.986 +        189 : ("anewarray", 2),
   1.987 +        190 : ("arraylength", 0),
   1.988 +        191 : ("athrow", 0),
   1.989 +        192 : ("checkcast", 2),
   1.990 +        193 : ("instanceof", 2),
   1.991 +        194 : ("monitorenter", 0),
   1.992 +        195 : ("monitorexit", 0),
   1.993 +        196 : ("wide", None), # 3 or 5 arguments, stack changes according to modified element
   1.994 +        197 : ("multianewarray", 3),
   1.995 +        198 : ("ifnull", 2),
   1.996 +        199 : ("ifnonnull", 2),
   1.997 +        200 : ("goto_w", 4),
   1.998 +        201 : ("jsr_w", 4),
   1.999 +        }
  1.1000 +
  1.1001 +if __name__ == "__main__":
  1.1002 +    import sys
  1.1003 +    from classfile import ClassFile
  1.1004 +    f = open(sys.argv[1])
  1.1005 +    c = ClassFile(f.read())
  1.1006  
  1.1007  # vim: tabstop=4 expandtab shiftwidth=4