Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * Created on 11 nov 2009
- */
- package interpreter.internals.runtime;
- import interpreter.api.InterpreterHeap;
- import interpreter.api.ExecutionFrame;
- import interpreter.api.ExecutionThread;
- import interpreter.api.InterpreterContext;
- import interpreter.api.util.InterpreterTypeUtil;
- import org.objectweb.asm.Opcodes;
- public class BytecodeStream
- {
- private final int[] stream;
- private final String[] instructions;
- private final int[] iConst;
- private final long[] lConst;
- private final float[] fConst;
- private final double[] dConst;
- private final int[] sConst;
- public BytecodeStream(int[] stream, String[] instructions, int[] iConst, long[] lConst, float[] fConst, double[] dConst, int[] sConst)
- {
- this.stream = stream;
- this.instructions = instructions;
- this.iConst = iConst;
- this.lConst = lConst;
- this.fConst = fConst;
- this.dConst = dConst;
- this.sConst = sConst;
- }
- public boolean step(ExecutionFrame frame) throws Throwable
- {
- InterpreterHeap heap = frame.thread.process.heap;
- int i1, i2, ref;
- long l1, l2;
- float f1, f2;
- double d1, d2;
- int ip = frame.instructionPointer;
- frame.instructionPointer++;
- int ip3 = ip * 3;
- int[] s = this.stream;
- ExecutionThread stack = frame.thread;
- String instruction = this.instructions[ip];
- if (InterpreterContext.feedback().isLoggingExecution())
- {
- InterpreterContext.feedback().executing(instruction);
- }
- switch (s[ip3])
- {
- case Opcodes.ICONST_0:
- frame.pushInt(0);
- break;
- case Opcodes.ICONST_1:
- frame.pushInt(1);
- break;
- case Opcodes.ICONST_2:
- frame.pushInt(2);
- break;
- case Opcodes.ICONST_3:
- frame.pushInt(3);
- break;
- case Opcodes.ICONST_4:
- frame.pushInt(4);
- break;
- case Opcodes.ICONST_5:
- frame.pushInt(5);
- break;
- case Opcodes.ICONST_M1:
- frame.pushInt(-1);
- break;
- case Opcodes.ACONST_NULL:
- frame.pushInt(0);
- break;
- case Opcodes.IINC:
- i1 = frame.loadInt(s[ip3 + 1]);
- frame.storeInt(s[ip3 + 1], i1 + s[ip3 + 2]);
- break;
- case Opcodes.BIPUSH:
- frame.pushInt(s[ip3 + 1]);
- break;
- case Opcodes.SIPUSH:
- frame.pushInt(s[ip3 + 1]);
- break;
- case Opcodes.LDC:
- switch (s[ip3 + 1])
- {
- case 0:
- frame.pushInt(this.iConst[s[ip3 + 2]]);
- break;
- case 1:
- frame.pushLong(this.lConst[s[ip3 + 2]]);
- break;
- case 2:
- frame.pushFloat(this.fConst[s[ip3 + 2]]);
- break;
- case 3:
- frame.pushDouble(this.dConst[s[ip3 + 2]]);
- break;
- case 4:
- frame.pushReference(this.sConst[s[ip3 + 2]]);
- break;
- }
- break;
- // load
- case Opcodes.ILOAD:
- frame.pushInt(frame.loadInt(s[ip3 + 1]));
- break;
- case Opcodes.LLOAD:
- frame.pushLong(frame.loadLong(s[ip3 + 1]));
- break;
- case Opcodes.FLOAD:
- frame.pushFloat(frame.loadFloat(s[ip3 + 1]));
- break;
- case Opcodes.DLOAD:
- frame.pushDouble(frame.loadDouble(s[ip3 + 1]));
- break;
- case Opcodes.ALOAD:
- frame.pushReference(frame.loadReference(s[ip3 + 1]));
- break;
- case Opcodes.BALOAD:
- i1 = frame.popInt();
- ref = frame.popReference();
- i1 = heap.getArrayByte(ref, i1);
- frame.pushInt(i1);
- break;
- case Opcodes.SALOAD:
- i1 = frame.popInt();
- ref = frame.popReference();
- i1 = heap.getArrayShort(ref, i1);
- frame.pushInt(i1);
- break;
- case Opcodes.CALOAD:
- i1 = frame.popInt();
- ref = frame.popReference();
- i1 = heap.getArrayChar(ref, i1);
- frame.pushInt(i1);
- break;
- case Opcodes.IALOAD:
- i1 = frame.popInt();
- ref = frame.popReference();
- i1 = heap.getArrayInt(ref, i1);
- frame.pushInt(i1);
- break;
- case Opcodes.LALOAD:
- i1 = frame.popInt();
- ref = frame.popReference();
- l1 = heap.getArrayLong(ref, i1);
- frame.pushLong(l1);
- break;
- case Opcodes.FALOAD:
- i1 = frame.popInt();
- ref = frame.popReference();
- f1 = heap.getArrayFloat(ref, i1);
- frame.pushFloat(f1);
- break;
- case Opcodes.DALOAD:
- i1 = frame.popInt();
- ref = frame.popReference();
- d1 = heap.getArrayDouble(ref, i1);
- frame.pushDouble(d1);
- break;
- case Opcodes.AALOAD:
- i1 = frame.popInt();
- ref = frame.popReference();
- i1 = heap.getArrayInt(ref, i1);
- frame.pushInt(i1);
- break;
- // store
- case Opcodes.ISTORE:
- frame.storeInt(s[ip3 + 1], frame.popInt());
- break;
- case Opcodes.LSTORE:
- frame.storeLong(s[ip3 + 1], frame.popLong());
- break;
- case Opcodes.FSTORE:
- frame.storeFloat(s[ip3 + 1], frame.popFloat());
- break;
- case Opcodes.DSTORE:
- frame.storeDouble(s[ip3 + 1], frame.popDouble());
- break;
- case Opcodes.ASTORE:
- frame.storeReference(s[ip3 + 1], frame.popReference());
- break;
- case Opcodes.BASTORE:
- i1 = frame.popInt();
- i2 = frame.popInt();
- ref = frame.popReference();
- heap.putArrayByte(ref, i2, (byte) i1);
- break;
- case Opcodes.SASTORE:
- i1 = frame.popInt();
- i2 = frame.popInt();
- ref = frame.popReference();
- heap.putArrayShort(ref, i2, (short) i1);
- break;
- case Opcodes.CASTORE:
- i1 = frame.popInt();
- i2 = frame.popInt();
- ref = frame.popReference();
- heap.putArrayChar(ref, i2, (char) i1);
- break;
- case Opcodes.IASTORE:
- i1 = frame.popInt();
- i2 = frame.popInt();
- ref = frame.popReference();
- heap.putArrayInt(ref, i2, i1);
- break;
- case Opcodes.LASTORE:
- l1 = frame.popLong();
- i2 = frame.popInt();
- ref = frame.popReference();
- heap.putArrayLong(ref, i2, l1);
- break;
- case Opcodes.FASTORE:
- f1 = frame.popFloat();
- i2 = frame.popInt();
- ref = frame.popReference();
- heap.putArrayFloat(ref, i2, f1);
- break;
- case Opcodes.DASTORE:
- d1 = frame.popDouble();
- i2 = frame.popInt();
- ref = frame.popReference();
- heap.putArrayDouble(ref, i2, d1);
- break;
- case Opcodes.AASTORE:
- i1 = frame.popInt();
- i2 = frame.popInt();
- ref = frame.popReference();
- heap.putArrayInt(ref, i2, i1);
- break;
- //
- case Opcodes.I2B:
- frame.pushInt((byte) frame.popInt());
- break;
- case Opcodes.I2S:
- frame.pushInt((short) frame.popInt());
- break;
- case Opcodes.I2C:
- frame.pushInt((char) frame.popInt());
- break;
- case Opcodes.I2L:
- frame.pushLong(frame.popInt());
- break;
- case Opcodes.I2F:
- frame.pushFloat(frame.popInt());
- break;
- case Opcodes.I2D:
- frame.pushDouble(frame.popInt());
- break;
- case Opcodes.L2I:
- frame.pushInt((int) frame.popLong());
- break;
- case Opcodes.L2F:
- frame.pushFloat(frame.popLong());
- break;
- case Opcodes.L2D:
- frame.pushDouble(frame.popLong());
- break;
- case Opcodes.F2I:
- frame.pushInt((int) frame.popFloat());
- break;
- case Opcodes.F2L:
- frame.pushLong((long) frame.popFloat());
- break;
- case Opcodes.F2D:
- frame.pushDouble(frame.popFloat());
- break;
- case Opcodes.D2I:
- frame.pushInt((int) frame.popDouble());
- break;
- case Opcodes.D2L:
- frame.pushLong((long) frame.popDouble());
- break;
- case Opcodes.D2F:
- frame.pushFloat((float) frame.popDouble());
- break;
- // fancy
- case Opcodes.ARRAYLENGTH:
- ref = frame.popReference();
- int len = heap.getArrayLength(ref);
- frame.pushInt(len);
- break;
- case Opcodes.NEWARRAY:
- int alen = frame.popInt();
- switch (s[ip3 + 1])
- {
- case 0:
- frame.pushReference(heap.mallocBooleanArray(alen));
- break;
- case 1:
- frame.pushReference(heap.mallocByteArray(alen));
- break;
- case 2:
- frame.pushReference(heap.mallocShortArray(alen));
- break;
- case 3:
- frame.pushReference(heap.mallocCharArray(alen));
- break;
- case 4:
- frame.pushReference(heap.mallocIntArray(alen));
- break;
- case 5:
- frame.pushReference(heap.mallocLongArray(alen));
- break;
- case 6:
- frame.pushReference(heap.mallocFloatArray(alen));
- break;
- case 7:
- frame.pushReference(heap.mallocDoubleArray(alen));
- break;
- default:
- throw new IllegalStateException();
- }
- break;
- case Opcodes.ANEWARRAY:
- int aalen = frame.popInt();
- String classname = heap.lookupString(sConst[s[ip3 + 1]]);
- if (classname.equals("java/lang/String"))
- {
- frame.pushReference(heap.mallocReferenceArray(aalen));
- }
- else
- {
- throw new UnsupportedOperationException("new " + classname + "[" + aalen + "]");
- }
- break;
- case Opcodes.INVOKESTATIC:
- stack.process.invokeStaticLookup.getAt(s[ip3 + 1]).execute(frame);
- break;
- case Opcodes.INVOKEVIRTUAL:
- stack.process.invokeVirtualLookup.getAt(s[ip3 + 1]).execute(frame);
- break;
- case Opcodes.INVOKESPECIAL:
- stack.process.invokeSpecialLookup.getAt(s[ip3 + 1]).execute(frame);
- break;
- case Opcodes.INVOKEINTERFACE:
- stack.process.invokeInterfaceLookup.getAt(s[ip3 + 1]).execute(frame);
- break;
- case Opcodes.GETFIELD:
- stack.process.getFieldLookup.getAt(s[ip3 + 1]).execute(frame);
- break;
- case Opcodes.PUTFIELD:
- stack.process.putFieldLookup.getAt(s[ip3 + 1]).execute(frame);
- break;
- case Opcodes.GETSTATIC:
- stack.process.getStaticLookup.getAt(s[ip3 + 1]).execute(frame);
- break;
- case Opcodes.PUTSTATIC:
- stack.process.putStaticLookup.getAt(s[ip3 + 1]).execute(frame);
- break;
- case Opcodes.NEW:
- stack.process.newLookup.getAt(s[ip3 + 1]).execute(frame);
- break;
- case Opcodes.ATHROW:
- throw (Throwable) InterpreterTypeUtil.popValueFromStack(frame, Throwable.class);
- // stack
- case Opcodes.NOP:
- break;
- case Opcodes.POP:
- frame.popInt();
- break;
- case Opcodes.DUP:
- {
- int a = frame.popInt();
- frame.pushInt(a);
- frame.pushInt(a);
- }
- break;
- case Opcodes.DUP_X1:
- {
- int a = frame.popInt();
- int b = frame.popInt();
- frame.pushInt(a);
- frame.pushInt(b);
- frame.pushInt(a);
- }
- break;
- case Opcodes.DUP_X2:
- {
- int a = frame.popInt();
- int b = frame.popInt();
- int c = frame.popInt();
- frame.pushInt(a);
- frame.pushInt(c);
- frame.pushInt(b);
- frame.pushInt(a);
- }
- break;
- case Opcodes.DUP2:
- {
- int a = frame.popInt();
- int b = frame.popInt();
- frame.pushInt(b);
- frame.pushInt(a);
- frame.pushInt(b);
- frame.pushInt(a);
- }
- break;
- case Opcodes.DUP2_X1:
- {
- int a = frame.popInt();
- int b = frame.popInt();
- int c = frame.popInt();
- frame.pushInt(b);
- frame.pushInt(a);
- frame.pushInt(c);
- frame.pushInt(b);
- frame.pushInt(a);
- }
- break;
- case Opcodes.DUP2_X2:
- {
- int a = frame.popInt();
- int b = frame.popInt();
- int c = frame.popInt();
- int d = frame.popInt();
- frame.pushInt(b);
- frame.pushInt(a);
- frame.pushInt(d);
- frame.pushInt(c);
- frame.pushInt(b);
- frame.pushInt(a);
- }
- break;
- case Opcodes.SWAP:
- {
- int a = frame.popInt();
- int b = frame.popInt();
- frame.pushInt(b);
- frame.pushInt(a);
- }
- break;
- // jumps
- case Opcodes.GOTO:
- frame.$goto(s[ip3 + 1]);
- break;
- case Opcodes.IFNULL:
- if (frame.popReference() == 0)
- frame.$goto(s[ip3 + 1]);
- break;
- case Opcodes.IFNONNULL:
- if (frame.popReference() != 0)
- frame.$goto(s[ip3 + 1]);
- break;
- case Opcodes.IFEQ:
- if (frame.popInt() == 0)
- frame.$goto(s[ip3 + 1]);
- break;
- case Opcodes.IFNE:
- if (frame.popInt() != 0)
- frame.$goto(s[ip3 + 1]);
- break;
- case Opcodes.IFLT:
- if (frame.popInt() < 0)
- frame.$goto(s[ip3 + 1]);
- break;
- case Opcodes.IFLE:
- if (frame.popInt() <= 0)
- frame.$goto(s[ip3 + 1]);
- break;
- case Opcodes.IFGE:
- if (frame.popInt() >= 0)
- frame.$goto(s[ip3 + 1]);
- break;
- case Opcodes.IFGT:
- if (frame.popInt() > 0)
- frame.$goto(s[ip3 + 1]);
- break;
- case Opcodes.IF_ICMPEQ:
- i1 = frame.popInt();
- i2 = frame.popInt();
- if (i2 == i1)
- frame.$goto(s[ip3 + 1]);
- break;
- case Opcodes.IF_ICMPNE:
- i1 = frame.popInt();
- i2 = frame.popInt();
- if (i2 != i1)
- frame.$goto(s[ip3 + 1]);
- break;
- case Opcodes.IF_ICMPLT:
- i1 = frame.popInt();
- i2 = frame.popInt();
- if (i2 < i1)
- frame.$goto(s[ip3 + 1]);
- break;
- case Opcodes.IF_ICMPLE:
- i1 = frame.popInt();
- i2 = frame.popInt();
- if (i2 <= i1)
- frame.$goto(s[ip3 + 1]);
- break;
- case Opcodes.IF_ICMPGE:
- i1 = frame.popInt();
- i2 = frame.popInt();
- if (i2 >= i1)
- frame.$goto(s[ip3 + 1]);
- break;
- case Opcodes.IF_ICMPGT:
- i1 = frame.popInt();
- i2 = frame.popInt();
- if (i2 > i1)
- frame.$goto(s[ip3 + 1]);
- break;
- case Opcodes.LCMP:
- l1 = frame.popLong();
- l2 = frame.popLong();
- frame.pushInt((l2 == l1) ? 0 : (l2 < l1 ? -1 : +1));
- break;
- case Opcodes.FCMPG: // TODO: NaN
- case Opcodes.FCMPL:
- f1 = frame.popFloat();
- f2 = frame.popFloat();
- frame.pushInt((f2 == f1) ? 0 : (f2 < f1 ? -1 : +1));
- break;
- case Opcodes.DCMPG: // TODO: NaN
- case Opcodes.DCMPL:
- d1 = frame.popDouble();
- d2 = frame.popDouble();
- frame.pushInt((d2 == d1) ? 0 : (d2 < d1 ? -1 : +1));
- break;
- //
- case Opcodes.RETURN:
- frame.thread.vreturn();
- return false;
- case Opcodes.IRETURN:
- frame.thread.ireturn();
- return false;
- case Opcodes.LRETURN:
- frame.thread.lreturn();
- return false;
- case Opcodes.FRETURN:
- frame.thread.freturn();
- return false;
- case Opcodes.DRETURN:
- frame.thread.dreturn();
- return false;
- case Opcodes.ARETURN:
- frame.thread.areturn();
- return false;
- //
- case Opcodes.INEG:
- frame.pushInt(-frame.popInt());
- break;
- case Opcodes.LNEG:
- frame.pushLong(-frame.popLong());
- break;
- case Opcodes.FNEG:
- frame.pushFloat(-frame.popFloat());
- break;
- case Opcodes.DNEG:
- frame.pushDouble(-frame.popDouble());
- break;
- // int:pop,pop,push
- case Opcodes.IOR:
- i1 = frame.popInt();
- i2 = frame.popInt();
- frame.pushInt(i2 | i1);
- break;
- case Opcodes.IAND:
- i1 = frame.popInt();
- i2 = frame.popInt();
- frame.pushInt(i2 & i1);
- break;
- case Opcodes.IXOR:
- i1 = frame.popInt();
- i2 = frame.popInt();
- frame.pushInt(i2 ^ i1);
- break;
- case Opcodes.IADD:
- i1 = frame.popInt();
- i2 = frame.popInt();
- frame.pushInt(i2 + i1);
- break;
- case Opcodes.ISUB:
- i1 = frame.popInt();
- i2 = frame.popInt();
- frame.pushInt(i2 - i1);
- break;
- case Opcodes.IMUL:
- i1 = frame.popInt();
- i2 = frame.popInt();
- frame.pushInt(i2 * i1);
- break;
- case Opcodes.IDIV:
- i1 = frame.popInt();
- i2 = frame.popInt();
- frame.pushInt(i2 / i1);
- break;
- case Opcodes.IREM:
- i1 = frame.popInt();
- i2 = frame.popInt();
- frame.pushInt(i2 % i1);
- break;
- case Opcodes.ISHL:
- i1 = frame.popInt();
- i2 = frame.popInt();
- frame.pushInt(i2 << i1);
- break;
- case Opcodes.ISHR:
- i1 = frame.popInt();
- i2 = frame.popInt();
- frame.pushInt(i2 >> i1);
- break;
- case Opcodes.IUSHR:
- i1 = frame.popInt();
- i2 = frame.popInt();
- frame.pushInt(i2 >>> i1);
- break;
- // long:pop,pop,push
- case Opcodes.LOR:
- l1 = frame.popLong();
- l2 = frame.popLong();
- frame.pushLong(l2 | l1);
- break;
- case Opcodes.LAND:
- l1 = frame.popLong();
- l2 = frame.popLong();
- frame.pushLong(l2 & l1);
- break;
- case Opcodes.LXOR:
- l1 = frame.popLong();
- l2 = frame.popLong();
- frame.pushLong(l2 ^ l1);
- break;
- case Opcodes.LADD:
- l1 = frame.popLong();
- l2 = frame.popLong();
- frame.pushLong(l2 + l1);
- break;
- case Opcodes.LSUB:
- l1 = frame.popLong();
- l2 = frame.popLong();
- frame.pushLong(l2 - l1);
- break;
- case Opcodes.LMUL:
- l1 = frame.popLong();
- l2 = frame.popLong();
- frame.pushLong(l2 * l1);
- break;
- case Opcodes.LDIV:
- l1 = frame.popLong();
- l2 = frame.popLong();
- frame.pushLong(l2 / l1);
- break;
- case Opcodes.LREM:
- l1 = frame.popLong();
- l2 = frame.popLong();
- frame.pushLong(l2 % l1);
- break;
- case Opcodes.LSHL:
- l1 = frame.popLong();
- l2 = frame.popLong();
- frame.pushLong(l2 << l1);
- break;
- case Opcodes.LSHR:
- l1 = frame.popLong();
- l2 = frame.popLong();
- frame.pushLong(l2 >> l1);
- break;
- case Opcodes.LUSHR:
- l1 = frame.popLong();
- l2 = frame.popLong();
- frame.pushLong(l2 >>> l1);
- break;
- // float:pop,pop,push
- case Opcodes.FADD:
- f1 = frame.popFloat();
- f2 = frame.popFloat();
- frame.pushFloat(f2 + f1);
- break;
- case Opcodes.FSUB:
- f1 = frame.popFloat();
- f2 = frame.popFloat();
- frame.pushFloat(f2 - f1);
- break;
- case Opcodes.FMUL:
- f1 = frame.popFloat();
- f2 = frame.popFloat();
- frame.pushFloat(f2 * f1);
- break;
- case Opcodes.FDIV:
- f1 = frame.popFloat();
- f2 = frame.popFloat();
- frame.pushFloat(f2 / f1);
- break;
- case Opcodes.FREM:
- f1 = frame.popFloat();
- f2 = frame.popFloat();
- frame.pushFloat(f2 % f1);
- break;
- // double,pop,pop,push
- case Opcodes.DADD:
- d1 = frame.popDouble();
- d2 = frame.popDouble();
- frame.pushDouble(d2 + d1);
- break;
- case Opcodes.DSUB:
- d1 = frame.popDouble();
- d2 = frame.popDouble();
- frame.pushDouble(d2 - d1);
- break;
- case Opcodes.DMUL:
- d1 = frame.popDouble();
- d2 = frame.popDouble();
- frame.pushDouble(d2 * d1);
- break;
- case Opcodes.DDIV:
- d1 = frame.popDouble();
- d2 = frame.popDouble();
- frame.pushDouble(d2 / d1);
- break;
- case Opcodes.DREM:
- d1 = frame.popDouble();
- d2 = frame.popDouble();
- frame.pushDouble(d2 % d1);
- break;
- default:
- throw new UnsupportedOperationException("bytecode=" + s[ip3]);
- }
- return true;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement