blob: 13bbd370d07b795e7e473c763adcf781d1e5f9d0 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @author Intel, George A. Timoshenko
*
*/
#include <stdio.h>
#include "JavaByteCodeParser.h"
#include "Log.h"
namespace Jitrino {
static const char *opcode_names[256] = {
"NOP", "ACONST_NULL", "ICONST_M1", "ICONST_0", "ICONST_1", "ICONST_2",
"ICONST_3", "ICONST_4", "ICONST_5", "LCONST_0", "LCONST_1", "FCONST_0",
"FCONST_1", "FCONST_2", "DCONST_0", "DCONST_1", "BIPUSH", "SIPUSH",
"LDC", "LDC_W", "LDC2_W", "ILOAD", "LLOAD", "FLOAD", "DLOAD", "ALOAD",
"ILOAD_0", "ILOAD_1", "ILOAD_2", "ILOAD_3", "LLOAD_0", "LLOAD_1",
"LLOAD_2",
"LLOAD_3", "FLOAD_0", "FLOAD_1", "FLOAD_2", "FLOAD_3", "DLOAD_0",
"DLOAD_1",
"DLOAD_2", "DLOAD_3", "ALOAD_0", "ALOAD_1", "ALOAD_2", "ALOAD_3",
"IALOAD",
"LALOAD", "FALOAD", "DALOAD", "AALOAD", "BALOAD", "CALOAD", "SALOAD",
"ISTORE", "LSTORE", "FSTORE", "DSTORE", "ASTORE", "ISTORE_0", "ISTORE_1",
"ISTORE_2", "ISTORE_3", "LSTORE_0", "LSTORE_1", "LSTORE_2", "LSTORE_3",
"FSTORE_0", "FSTORE_1", "FSTORE_2", "FSTORE_3", "DSTORE_0", "DSTORE_1",
"DSTORE_2", "DSTORE_3", "ASTORE_0", "ASTORE_1", "ASTORE_2", "ASTORE_3",
"IASTORE", "LASTORE", "FASTORE", "DASTORE", "AASTORE", "BASTORE",
"CASTORE",
"SASTORE", "POP", "POP2", "DUP", "DUP_X1", "DUP_X2", "DUP2", "DUP2_X1",
"DUP2_X2", "SWAP", "IADD", "LADD", "FADD", "DADD", "ISUB", "LSUB", "FSUB",
"DSUB", "IMUL", "LMUL", "FMUL", "DMUL", "IDIV", "LDIV", "FDIV", "DDIV",
"IREM", "LREM", "FREM", "DREM", "INEG", "LNEG", "FNEG", "DNEG", "ISHL",
"LSHL", "ISHR", "LSHR", "IUSHR", "LUSHR", "IAND", "LAND", "IOR", "LOR",
"IXOR", "LXOR", "IINC", "I2L", "I2F", "I2D", "L2I", "L2F", "L2D", "F2I",
"F2L", "F2D", "D2I", "D2L", "D2F", "I2B", "I2C", "I2S", "LCMP", "FCMPL",
"FCMPG", "DCMPL", "DCMPG", "IFEQ", "IFNE", "IFLT", "IFGE", "IFGT", "IFLE",
"IF_ICMPEQ", "IF_ICMPNE", "IF_ICMPLT", "IF_ICMPGE", "IF_ICMPGT",
"IF_ICMPLE", "IF_ACMPEQ", "IF_ACMPNE", "GOTO", "JSR", "RET",
"TABLESWITCH",
"LOOKUPSWITCH", "IRETURN", "LRETURN", "FRETURN", "DRETURN", "ARETURN",
"RETURN", "GETSTATIC", "PUTSTATIC", "GETFIELD", "PUTFIELD",
"INVOKEVIRTUAL",
"INVOKESPECIAL", "INVOKESTATIC", "INVOKEINTERFACE", "_OPCODE_UNDEFINED",
"NEW", "NEWARRAY", "ANEWARRAY", "ARRAYLENGTH", "ATHROW", "CHECKCAST",
"INSTANCEOF", "MONITORENTER", "MONITOREXIT", "WIDE", "MULTIANEWARRAY",
"IFNULL", "IFNONNULL", "GOTO_W", "JSR_W",
};
static char bytecodelength[] = {
1, // 0x00: nop
1, // 0x01: aconst_null
1, // 0x02: iconst(-1)
1, // 0x03: iconst(0)
1, // 0x04: iconst(1)
1, // 0x05: iconst(2)
1, // 0x06: iconst(3)
1, // 0x07: iconst(4)
1, // 0x08: iconst(5)
1, // 0x09: lconst(0)
1, // 0x0a: lconst(1)
1, // 0x0b: fconst(0.0)
1, // 0x0c: fconst(1.0)
1, // 0x0d: fconst(2.0)
1, // 0x0e: dconst(0.0)
1, // 0x0f: dconst(1.0)
// 0x1[0-f]
2, // 0x10: bipush
3, // 0x11: sipush
2, // 0x12: ldc
3, // 0x13: ldc
3, // 0x14: ldc2
2, // 0x15: iload
2, // 0x16: lload
2, // 0x17: fload
2, // 0x18: dload
2, // 0x19: aload
1, // 0x1a: iload(0)
1, // 0x1b: iload(1)
1, // 0x1c: iload(2)
1, // 0x1d: iload(3)
1, // 0x1e: lload(0)
1, // 0x1f: lload(1)
// 0x2[0-f] unused: 0x24
1, // 0x20: lload(2)
1, // 0x21: lload(3)
1, // 0x22: fload(0)
1, // 0x23: fload(1)
1, // 0x24: fload(2)
1, // 0x25: fload(3)
1, // 0x26: dload(0)
1, // 0x27: dload(1)
1, // 0x28: dload(2)
1, // 0x29: dload(3)
1, // 0x2a: aload(0)
1, // 0x2b: aload(1)
1, // 0x2c: aload(2)
1, // 0x2d: aload(3)
1, // 0x2e: iaload
1, // 0x2f: laload
// 0x3[0-f]
1, // 0x30: faload
1, // 0x31: daload
1, // 0x32: aaload
1, // 0x33: baload
1, // 0x34: caload
1, // 0x35: saload
2, // 0x36: istore
2, // 0x37: lstore
2, // 0x38: fstore
2, // 0x39: dstore
2, // 0x3a: astore
1, // 0x3b: istore(0)
1, // 0x3c: istore(1)
1, // 0x3d: istore(2)
1, // 0x3e: istore(3)
1, // 0x3f: lstore(0)
// 0x4[0-f]
1, // 0x40: lstore(1)
1, // 0x41: lstore(2)
1, // 0x42: lstore(3)
1, // 0x43: fstore(0)
1, // 0x44: fstore(1)
1, // 0x45: fstore(2)
1, // 0x46: fstore(3)
1, // 0x47: dstore(0)
1, // 0x48: dstore(1)
1, // 0x49: dstore(2)
1, // 0x4a: dstore(3)
1, // 0x4b: astore(0)
1, // 0x4c: astore(1)
1, // 0x4d: astore(2)
1, // 0x4e: astore(3)
1, // 0x4f: iastore
// 0x5[0-f]
1, // 0x50: lastore
1, // 0x51: fastore
1, // 0x52: dastore
1, // 0x53: aastore
1, // 0x54: bastore
1, // 0x55: castore
1, // 0x56: sastore
1, // 0x57: pop
1, // 0x58: pop2
1, // 0x59: dup
1, // 0x5a: dup_x1
1, // 0x5b: dup_x2
1, // 0x5c: dup2
1, // 0x5d: dup2_x1
1, // 0x5e: dup2_x2
1, // 0x5f: swap
// 0x6[0-f]
1, // 0x60: iadd
1, // 0x61: ladd
1, // 0x62: fadd
1, // 0x63: dadd
1, // 0x64: isub
1, // 0x65: lsub
1, // 0x66: fsub
1, // 0x67: dsub
1, // 0x68: imul
1, // 0x69: lmul
1, // 0x6a: fmul
1, // 0x6b: dmul
1, // 0x6c: idiv
1, // 0x6d: ldiv
1, // 0x6e: fdiv
1, // 0x6f: ddiv
// 0x7[0-f]
1, // 0x70: irem
1, // 0x71: lrem
1, // 0x72: frem
1, // 0x73: drem
1, // 0x74: ineg
1, // 0x75: lneg
1, // 0x76: fneg
1, // 0x77: dneg
1, // 0x78: ishl
1, // 0x79: lshl
1, // 0x7a: ishr
1, // 0x7b: lshr
1, // 0x7c: iushr
1, // 0x7d: lushr
1, // 0x7e: iand
1, // 0x7f: land
// 0x8[0-f]
1, // 0x80: ior
1, // 0x81: lor
1, // 0x82: ixor
1, // 0x83: lxor
3, // 0x84: iinc
1, // 0x85: i2l
1, // 0x86: i2f
1, // 0x87: i2d
1, // 0x88: l2i
1, // 0x89: l2f
1, // 0x8a: l2d
1, // 0x8b: f2i
1, // 0x8c: f2l
1, // 0x8d: f2d
1, // 0x8e: d2i
1, // 0x8f: d2l
// 0x9
1, // 0x90: d2f
1, // 0x91: i2b
1, // 0x92: i2c
1, // 0x93: i2s
1, // 0x94: lcmp
1, // 0x95: fcmpl
1, // 0x96: fcmpg
1, // 0x97: dcmpl
1, // 0x98: dcmpg
3, // 0x99: ifeq
3, // 0x9a: ifne
3, // 0x9b: iflt
3, // 0x9c: ifge
3, // 0x9d: ifgt
3, // 0x9e: ifle
3, // 0x9f: if_icmpeq
3, // 0xa0: if_ifcmpne
3, // 0xa1: if_icmplt
3, // 0xa2: if_icmpge
3, // 0xa3: if_icmpgt
3, // 0xa4: if_icmple
3, // 0xa5: if_acmpeq
3, // 0xa6: if_acmpne
3, // 0xa7: goto
3, // 0xa8: jsr
2, // 0xa9: ret
0, // 0xaa: switch
0, // 0xab: lookup
1, // 0xac: ireturn
1, // 0xad: lreturn
1, // 0xae: freturn
1, // 0xaf: dreturn
// 0xb[0-f] unused: 0xba
1, // 0xb0: areturn
1, // 0xb1: return_
3, // 0xb2: getstatic
3, // 0xb3: putstatic
3, // 0xb4: getfield
3, // 0xb5: putfield
3, // 0xb6: invokevirtual
3, // 0xb7: invokespecial
3, // 0xb8: invokestatic
5, // 0xb9: invokeinterface
0, // 0xba; unused
3, // 0xbb: new_
2, // 0xbc: newarray
3, // 0xbd: anewarray
1, // 0xbe: arraylength
1, // 0xbf: athrow
// 0xc[0-f] unused: 0xc[a-f]
3, // 0xc0: checkcast
3, // 0xc1: instanceof
1, // 0xc2: monitorenter
1, // 0xc3: monitorexit
0, // 0xc4: wide
4, // 0xc5: multianewarray
3, // 0xc6: ifnull
3, // 0xc7: ifnonnull
5, // 0xc8: gotolong
5, // 0xc9: jsrlong
};
//
// big-endian ordering
//
int16 si16(const U_8* bcp) {
return (((int16)(bcp)[0] << 8) | bcp[1]);
}
uint16 su16(const U_8* bcp) {
return (((uint16)(bcp)[0] << 8)| bcp[1]);
}
I_32 si32(const U_8* bcp) {
return (((U_32)(bcp)[0] << 24) |
((U_32)(bcp)[1] << 16) |
((U_32)(bcp)[2] << 8) |
bcp[3]);
}
uint64 si64(const U_8* bcp) {
return (((uint64)bcp[0] << 56) |
((uint64)bcp[1] << 48) |
((uint64)bcp[2] << 40) |
((uint64)bcp[3] << 32) |
((uint64)bcp[4] << 24) |
((uint64)bcp[5] << 16) |
((uint64)bcp[6] << 8) |
((uint64)bcp[7])
);
} //si64
//
//
bool
JavaByteCodeParserCallback::parseByteCode(const U_8* byteCodes,U_32 off) {
bool linearPassEnd = false;
currentOffset = off;
const U_8* bcp = byteCodes + off;
// find length of the byte code instruction
U_32 len = 0;
const U_8 opcode = *bcp;
assert (opcode <= 0xc9);
if (Log::isEnabled()) {
Log::out()<<"---------------------PARSING BYTECODE: "<<opcode_names[opcode]<<" bc-offset="<<off<<std::endl;
}
len = bytecodelength[opcode];
if (len == 0) { // variable length cases
switch (opcode) {
case 0xaa: {
JavaSwitchTargetsIter switchIter(bcp,off);
len = switchIter.getLength();
break;
}
case 0xab: {
JavaLookupSwitchTargetsIter switchIter(bcp,off);
len = switchIter.getLength();
break;
}
case 0xc4: // wide
if ((su8(bcp+1)) == 0x84) // iinc
len = 6;
else
len = 4;
break;
default:
assert(0);
}
}
offset(off);
if (isLinearPass) {
if (prepassVisited && ! prepassVisited->getBit(off)) {
nextOffset = currentOffset + len;
return true;
}
}
switch (opcode) {
// 0x0[0-f]
case 0x00: nop(); break;
case 0x01: aconst_null(); break;
case 0x02: iconst(-1); break;
case 0x03: iconst(0); break;
case 0x04: iconst(1); break;
case 0x05: iconst(2); break;
case 0x06: iconst(3); break;
case 0x07: iconst(4); break;
case 0x08: iconst(5); break;
case 0x09: lconst(0); break;
case 0x0a: lconst(1); break;
case 0x0b: fconst(0.0); break;
case 0x0c: fconst(1.0); break;
case 0x0d: fconst(2.0); break;
case 0x0e: dconst(0.0); break;
case 0x0f: dconst(1.0); break;
// 0x1[0-f]
case 0x10: bipush(si8(bcp+1)); break;
case 0x11: sipush(si16(bcp+1)); break;
case 0x12: ldc(su8(bcp+1)); break;
case 0x13: ldc(su16(bcp+1)); break;
case 0x14: ldc2(su16(bcp+1)); break;
case 0x15: iload(su8(bcp+1)); break;
case 0x16: lload(su8(bcp+1)); break;
case 0x17: fload(su8(bcp+1)); break;
case 0x18: dload(su8(bcp+1)); break;
case 0x19: aload(su8(bcp+1)); break;
case 0x1a: iload(0); break;
case 0x1b: iload(1); break;
case 0x1c: iload(2); break;
case 0x1d: iload(3); break;
case 0x1e: lload(0); break;
case 0x1f: lload(1); break;
// 0x2[0-f] unused: 0x24
case 0x20: lload(2); break;
case 0x21: lload(3); break;
case 0x22: fload(0); break;
case 0x23: fload(1); break;
case 0x24: fload(2); break;
case 0x25: fload(3); break;
case 0x26: dload(0); break;
case 0x27: dload(1); break;
case 0x28: dload(2); break;
case 0x29: dload(3); break;
case 0x2a: aload(0); break;
case 0x2b: aload(1); break;
case 0x2c: aload(2); break;
case 0x2d: aload(3); break;
case 0x2e: iaload(); break;
case 0x2f: laload(); break;
// 0x3[0-f]
case 0x30: faload(); break;
case 0x31: daload(); break;
case 0x32: aaload(); break;
case 0x33: baload(); break;
case 0x34: caload(); break;
case 0x35: saload(); break;
case 0x36: istore(su8(bcp+1),off); break;
case 0x37: lstore(su8(bcp+1),off); break;
case 0x38: fstore(su8(bcp+1),off); break;
case 0x39: dstore(su8(bcp+1),off); break;
case 0x3a: astore(su8(bcp+1),off); break;
case 0x3b: istore(0,off); break;
case 0x3c: istore(1,off); break;
case 0x3d: istore(2,off); break;
case 0x3e: istore(3,off); break;
case 0x3f: lstore(0,off); break;
// 0x4[0-f]
case 0x40: lstore(1,off); break;
case 0x41: lstore(2,off); break;
case 0x42: lstore(3,off); break;
case 0x43: fstore(0,off); break;
case 0x44: fstore(1,off); break;
case 0x45: fstore(2,off); break;
case 0x46: fstore(3,off); break;
case 0x47: dstore(0,off); break;
case 0x48: dstore(1,off); break;
case 0x49: dstore(2,off); break;
case 0x4a: dstore(3,off); break;
case 0x4b: astore(0,off); break;
case 0x4c: astore(1,off); break;
case 0x4d: astore(2,off); break;
case 0x4e: astore(3,off); break;
case 0x4f: iastore(); break;
// 0x5[0-f]
case 0x50: lastore(); break;
case 0x51: fastore(); break;
case 0x52: dastore(); break;
case 0x53: aastore(); break;
case 0x54: bastore(); break;
case 0x55: castore(); break;
case 0x56: sastore(); break;
case 0x57: pop(); break;
case 0x58: pop2(); break;
case 0x59: dup(); break;
case 0x5a: dup_x1(); break;
case 0x5b: dup_x2(); break;
case 0x5c: dup2(); break;
case 0x5d: dup2_x1(); break;
case 0x5e: dup2_x2(); break;
case 0x5f: swap(); break;
// 0x6[0-f]
case 0x60: iadd(); break;
case 0x61: ladd(); break;
case 0x62: fadd(); break;
case 0x63: dadd(); break;
case 0x64: isub(); break;
case 0x65: lsub(); break;
case 0x66: fsub(); break;
case 0x67: dsub(); break;
case 0x68: imul(); break;
case 0x69: lmul(); break;
case 0x6a: fmul(); break;
case 0x6b: dmul(); break;
case 0x6c: idiv(); break;
case 0x6d: ldiv(); break;
case 0x6e: fdiv(); break;
case 0x6f: ddiv(); break;
// 0x7[0-f]
case 0x70: irem(); break;
case 0x71: lrem(); break;
case 0x72: frem(); break;
case 0x73: drem(); break;
case 0x74: ineg(); break;
case 0x75: lneg(); break;
case 0x76: fneg(); break;
case 0x77: dneg(); break;
case 0x78: ishl(); break;
case 0x79: lshl(); break;
case 0x7a: ishr(); break;
case 0x7b: lshr(); break;
case 0x7c: iushr(); break;
case 0x7d: lushr(); break;
case 0x7e: iand(); break;
case 0x7f: land(); break;
// 0x8[0-f]
case 0x80: ior(); break;
case 0x81: lor(); break;
case 0x82: ixor(); break;
case 0x83: lxor(); break;
case 0x84: iinc(su8(bcp+1),si8(bcp+2)); break;
case 0x85: i2l(); break;
case 0x86: i2f(); break;
case 0x87: i2d(); break;
case 0x88: l2i(); break;
case 0x89: l2f(); break;
case 0x8a: l2d(); break;
case 0x8b: f2i(); break;
case 0x8c: f2l(); break;
case 0x8d: f2d(); break;
case 0x8e: d2i(); break;
case 0x8f: d2l(); break;
case 0x90: d2f(); break;
case 0x91: i2b(); break;
case 0x92: i2c(); break;
case 0x93: i2s(); break;
case 0x94: lcmp(); break;
case 0x95: fcmpl(); break;
case 0x96: fcmpg(); break;
case 0x97: dcmpl(); break;
case 0x98: dcmpg(); break;
case 0x99:
ifeq(off+si16(bcp+1),off+3);
if (labelStack != NULL)
labelStack->push((U_8*)byteCodes + off+si16(bcp+1));
break;
case 0x9a:
ifne(off+si16(bcp+1),off+3);
if (labelStack != NULL)
labelStack->push((U_8*)byteCodes + off+si16(bcp+1));
break;
case 0x9b:
iflt(off+si16(bcp+1),off+3);
if (labelStack != NULL)
labelStack->push((U_8*)byteCodes + off+si16(bcp+1));
break;
case 0x9c:
ifge(off+si16(bcp+1),off+3);
if (labelStack != NULL)
labelStack->push((U_8*)byteCodes + off+si16(bcp+1));
break;
case 0x9d:
ifgt(off+si16(bcp+1),off+3);
if (labelStack != NULL)
labelStack->push((U_8*)byteCodes + off+si16(bcp+1));
break;
case 0x9e:
ifle(off+si16(bcp+1),off+3);
if (labelStack != NULL)
labelStack->push((U_8*)byteCodes + off+si16(bcp+1));
break;
case 0x9f:
if_icmpeq(off+si16(bcp+1),off+3);
if (labelStack != NULL)
labelStack->push((U_8*)byteCodes + off+si16(bcp+1));
break;
// 0xa[0-f]
case 0xa0:
if_icmpne(off+si16(bcp+1),off+3);
if (labelStack != NULL)
labelStack->push((U_8*)byteCodes + off+si16(bcp+1));
break;
case 0xa1:
if_icmplt(off+si16(bcp+1),off+3);
if (labelStack != NULL)
labelStack->push((U_8*)byteCodes + off+si16(bcp+1));
break;
case 0xa2:
if_icmpge(off+si16(bcp+1),off+3);
if (labelStack != NULL)
labelStack->push((U_8*)byteCodes + off+si16(bcp+1));
break;
case 0xa3:
if_icmpgt(off+si16(bcp+1),off+3);
if (labelStack != NULL)
labelStack->push((U_8*)byteCodes + off+si16(bcp+1));
break;
case 0xa4:
if_icmple(off+si16(bcp+1),off+3);
if (labelStack != NULL)
labelStack->push((U_8*)byteCodes + off+si16(bcp+1));
break;
case 0xa5:
if_acmpeq(off+si16(bcp+1),off+3);
if (labelStack != NULL)
labelStack->push((U_8*)byteCodes + off+si16(bcp+1));
break;
case 0xa6:
if_acmpne(off+si16(bcp+1),off+3);
if (labelStack != NULL)
labelStack->push((U_8*)byteCodes + off+si16(bcp+1));
break;
case 0xa7:
goto_(off+si16(bcp+1),off+3);
linearPassEnd = true;
if (labelStack != NULL)
labelStack->push((U_8*)byteCodes + off+si16(bcp+1));
break;
case 0xa8:
jsr(off+si16(bcp+1),off+3);
linearPassEnd = true;
if (labelStack != NULL) {
// If labelStack is stack then the order of pushes should be reverted.
// For now it is line. (labelStack is a Queue)
labelStack->push((U_8*)byteCodes + off+si16(bcp+1));
labelStack->push((U_8*)byteCodes + off+3);
}
break;
case 0xa9:
ret(su8(bcp+1), byteCodes);
linearPassEnd = true;
break;
case 0xaa:
{
JavaSwitchTargetsIter switchIter(bcp,off);
tableswitch(&switchIter);
linearPassEnd = true;
if (labelStack != NULL) {
JavaSwitchTargetsIter switchIter2(bcp,off);
while (switchIter2.hasNext()) {
labelStack->push((U_8*)byteCodes + switchIter2.getNextTarget());
}
labelStack->push((U_8*)byteCodes + switchIter2.getDefaultTarget());
}
break;
}
case 0xab:
{
JavaLookupSwitchTargetsIter switchIter(bcp,off);
lookupswitch(&switchIter);
linearPassEnd = true;
if (labelStack != NULL) {
JavaLookupSwitchTargetsIter switchIter2(bcp,off);
while (switchIter2.hasNext()) {
U_32 key;
labelStack->push((U_8*)byteCodes + switchIter2.getNextTarget(&key));
}
labelStack->push((U_8*)byteCodes + switchIter2.getDefaultTarget());
}
break;
}
case 0xac: ireturn(off); linearPassEnd = true; break;
case 0xad: lreturn(off); linearPassEnd = true; break;
case 0xae: freturn(off); linearPassEnd = true; break;
case 0xaf: dreturn(off); linearPassEnd = true; break;
// 0xb[0-f] unused: 0xba
case 0xb0: areturn(off); linearPassEnd = true; break;
case 0xb1: return_(off); linearPassEnd = true; break;
case 0xb2: getstatic(su16(bcp+1)); break;
case 0xb3: putstatic(su16(bcp+1)); break;
case 0xb4: getfield(su16(bcp+1)); break;
case 0xb5: putfield(su16(bcp+1)); break;
case 0xb6: invokevirtual(su16(bcp+1)); break;
case 0xb7: invokespecial(su16(bcp+1)); break;
case 0xb8: invokestatic(su16(bcp+1)); break;
case 0xb9: invokeinterface(su16(bcp+1),su8(bcp+3)); break;
case 0xbb: new_(su16(bcp+1)); break;
case 0xbc: newarray(su8(bcp+1)); break;
case 0xbd: anewarray(su16(bcp+1)); break;
case 0xbe: arraylength(); break;
case 0xbf: athrow(); linearPassEnd = true; break;
// 0xc[0-f] unused: 0xc[a-f]
case 0xc0: checkcast(su16(bcp+1)); break;
case 0xc1: len = instanceof(bcp,su16(bcp+1),off); break;
case 0xc2: monitorenter(); break;
case 0xc3: monitorexit(); break;
case 0xc4:
{
// wide
switch (su8(bcp+1)) {
case 0x15: iload(su16(bcp+2)); break;
case 0x16: lload(su16(bcp+2)); break;
case 0x17: fload(su16(bcp+2)); break;
case 0x18: dload(su16(bcp+2)); break;
case 0x19: aload(su16(bcp+2)); break;
case 0x36: istore(su16(bcp+2),off); break;
case 0x37: lstore(su16(bcp+2),off); break;
case 0x38: fstore(su16(bcp+2),off); break;
case 0x39: dstore(su16(bcp+2),off); break;
case 0x3a: astore(su16(bcp+2),off); break;
case 0xa9: ret(su16(bcp+2), byteCodes); linearPassEnd = true; break;
case 0x84: iinc(su16(bcp+2),si16(bcp+4)); break;
default:
assert(0);
return false;
}
}
break;
case 0xc5: multianewarray(su16(bcp+1),su8(bcp+3)); break;
case 0xc6:
ifnull(off+si16(bcp+1),off+3);
if (labelStack != NULL)
labelStack->push((U_8*)byteCodes + off+si16(bcp+1));
break;
case 0xc7:
ifnonnull(off+si16(bcp+1),off+3);
if (labelStack != NULL)
labelStack->push((U_8*)byteCodes + off+si16(bcp+1));
break;
case 0xc8:
goto_(off+si32(bcp+1),off+5);
linearPassEnd = true;
if (labelStack != NULL)
labelStack->push((U_8*)byteCodes + off+si32(bcp+1));
break;
case 0xc9:
jsr(off+si32(bcp+1),off+5);
linearPassEnd = true;
if (labelStack != NULL) {
// If labelStack is stack then the order of pushes should be reverted.
// For now it is line. (labelStack is a Queue)
labelStack->push((U_8*)byteCodes + off+si32(bcp+1));
labelStack->push((U_8*)byteCodes + off+5);
}
break;
default:
assert(0);
return false;
}
offset_done(off);
if (isLinearPass == true) {
nextOffset = currentOffset + len;
return true;
}
linearPassDone = linearPassEnd;
if (linearPassEnd == false) {
// continue with next instruction,
// but only if it has not been visited
nextOffset = currentOffset + len;
return true;
}
// get next label by popping label stack
while (!labelStack->isEmpty()) {
nextOffset = (U_32) (labelStack->pop() - byteCodes);
if (!visited->getBit(nextOffset)) {
return true;
}
}
return false;
}
} //namespace Jitrino