| //===---- JavaJITOpcodes.cpp - Reads and compiles opcodes -----------------===// |
| // |
| // JnJVM |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #define DEBUG 0 |
| #define JNJVM_COMPILE 0 |
| #define JNJVM_EXECUTE 0 |
| |
| #include <string.h> |
| |
| #include <llvm/Type.h> |
| #include <llvm/Module.h> |
| #include <llvm/Constants.h> |
| #include <llvm/Type.h> |
| #include <llvm/DerivedTypes.h> |
| #include <llvm/Function.h> |
| #include <llvm/Instructions.h> |
| #include <llvm/ModuleProvider.h> |
| #include <llvm/ExecutionEngine/JIT.h> |
| #include <llvm/ExecutionEngine/GenericValue.h> |
| #include <llvm/PassManager.h> |
| #include <llvm/Analysis/Verifier.h> |
| #include <llvm/Transforms/Scalar.h> |
| #include <llvm/Target/TargetData.h> |
| #include <llvm/Assembly/PrintModulePass.h> |
| #include <llvm/Target/TargetOptions.h> |
| #include <llvm/CodeGen/MachineCodeEmitter.h> |
| #include <llvm/CodeGen/MachineBasicBlock.h> |
| |
| #include <llvm/Transforms/IPO.h> |
| |
| |
| #include "mvm/JIT.h" |
| #include "mvm/Method.h" |
| |
| #include "debug.h" |
| |
| #include "JavaArray.h" |
| #include "JavaClass.h" |
| #include "JavaConstantPool.h" |
| #include "JavaObject.h" |
| #include "JavaJIT.h" |
| #include "JavaThread.h" |
| #include "JavaTypes.h" |
| #include "Jnjvm.h" |
| #include "Reader.h" |
| |
| #include "OpcodeNames.def" |
| |
| #include <iostream> |
| |
| |
| |
| using namespace jnjvm; |
| using namespace llvm; |
| |
| |
| static inline sint8 readS1(uint8* bytecode, uint32& i) { |
| return ((sint8*)bytecode)[++i]; |
| } |
| |
| static inline uint8 readU1(uint8* bytecode, uint32& i) { |
| return bytecode[++i]; |
| } |
| |
| static inline sint16 readS2(uint8* bytecode, uint32& i) { |
| sint16 val = readS1(bytecode, i) << 8; |
| return val | readU1(bytecode, i); |
| } |
| |
| static inline uint16 readU2(uint8* bytecode, uint32& i) { |
| uint16 val = readU1(bytecode, i) << 8; |
| return val | readU1(bytecode, i); |
| } |
| |
| static inline sint32 readS4(uint8* bytecode, uint32& i) { |
| sint32 val = readU2(bytecode, i) << 16; |
| return val | readU2(bytecode, i); |
| } |
| |
| |
| static inline uint32 readU4(uint8* bytecode, uint32& i) { |
| return readS4(bytecode, i); |
| } |
| |
| uint32 JavaJIT::WREAD_U1(uint8* array, bool init, uint32 &i) { |
| if (wide) { |
| wide = init; |
| return readU2(array, i); |
| } else { |
| return readU1(array, i); |
| } |
| } |
| |
| sint32 JavaJIT::WREAD_S1(uint8* array, bool init, uint32 &i) { |
| if (wide) { |
| wide = init; |
| return readS2(array, i); |
| } else { |
| return readS1(array, i); |
| } |
| } |
| |
| uint32 JavaJIT::WCALC(uint32 n) { |
| if (wide) { |
| wide = false; |
| return n << 1; |
| } else { |
| return n; |
| } |
| } |
| |
| void convertValue(Value*& val, const Type* t1, BasicBlock* currentBlock, bool usign) { |
| const Type* t2 = val->getType(); |
| if (t1 != t2) { |
| if (t1->isInteger() && t2->isInteger()) { |
| if (t2->getPrimitiveSizeInBits() < t1->getPrimitiveSizeInBits()) { |
| if (usign) { |
| val = new ZExtInst(val, t1, "", currentBlock); |
| } else { |
| val = new SExtInst(val, t1, "", currentBlock); |
| } |
| } else { |
| val = new TruncInst(val, t1, "", currentBlock); |
| } |
| } else if (t1->isFloatingPoint() && t2->isFloatingPoint()) { |
| if (t2->getPrimitiveSizeInBits() < t1->getPrimitiveSizeInBits()) { |
| val = new FPExtInst(val, t1, "", currentBlock); |
| } else { |
| val = new FPTruncInst(val, t1, "", currentBlock); |
| } |
| } else if (isa<PointerType>(t1) && isa<PointerType>(t2)) { |
| val = new BitCastInst(val, t1, "", currentBlock); |
| } |
| } |
| } |
| |
| void JavaJIT::compileOpcodes(uint8* bytecodes, uint32 codeLength) { |
| uint32 jsrIndex = 0; |
| for(uint32 i = 0; i < codeLength; ++i) { |
| |
| PRINT_DEBUG(JNJVM_COMPILE, 1, COLOR_NORMAL, "\t[at %5d] %-5d ", i, |
| bytecodes[i]); |
| PRINT_DEBUG(JNJVM_COMPILE, 1, LIGHT_BLUE, "compiling "); |
| PRINT_DEBUG(JNJVM_COMPILE, 1, LIGHT_CYAN, OpcodeNames[bytecodes[i]]); |
| PRINT_DEBUG(JNJVM_COMPILE, 1, LIGHT_BLUE, "\n"); |
| |
| Opinfo* opinfo = &(opcodeInfos[i]); |
| if (opinfo->newBlock) { |
| if (currentBlock->getTerminator() == 0) { |
| branch(opinfo->newBlock, currentBlock); |
| } |
| setCurrentBlock(opinfo->newBlock); |
| } |
| currentExceptionBlock = opinfo->exceptionBlock; |
| if (currentBlock->getTerminator() != 0) { // To prevent a gcj bug with useless goto |
| currentBlock = createBasicBlock("gcj bug"); |
| } |
| #if JNJVM_EXECUTE > 1 |
| { |
| std::vector<llvm::Value*> args; |
| mvm::jit::protectConstants();//->lock(); |
| args.push_back(ConstantInt::get(Type::Int32Ty, (int64_t)OpcodeNames[bytecodes[i]])); |
| args.push_back(ConstantInt::get(Type::Int32Ty, (int64_t)i)); |
| args.push_back(ConstantInt::get(Type::Int32Ty, (int64_t)compilingMethod)); |
| mvm::jit::unprotectConstants();//->unlock(); |
| new CallInst(printExecutionLLVM, args.begin(), args.end(), "", currentBlock); |
| } |
| #endif |
| |
| if (opinfo->reqSuppl) { |
| push(new LoadInst(supplLocal, "", currentBlock), AssessorDesc::dRef); |
| } |
| |
| switch (bytecodes[i]) { |
| |
| case ACONST_NULL : |
| push(constantJavaObjectNull, AssessorDesc::dRef); |
| break; |
| |
| case ICONST_M1 : |
| push(mvm::jit::constantMinusOne, AssessorDesc::dInt); |
| break; |
| |
| case ICONST_0 : |
| push(mvm::jit::constantZero, AssessorDesc::dInt); |
| break; |
| |
| case ICONST_1 : |
| push(mvm::jit::constantOne, AssessorDesc::dInt); |
| break; |
| |
| case ICONST_2 : |
| push(mvm::jit::constantTwo, AssessorDesc::dInt); |
| break; |
| |
| case ICONST_3 : |
| push(mvm::jit::constantThree, AssessorDesc::dInt); |
| break; |
| |
| case ICONST_4 : |
| push(mvm::jit::constantFour, AssessorDesc::dInt); |
| break; |
| |
| case ICONST_5 : |
| push(mvm::jit::constantFive, AssessorDesc::dInt); |
| break; |
| |
| case LCONST_0 : |
| push(mvm::jit::constantLongZero, AssessorDesc::dLong); |
| push(mvm::jit::constantZero, AssessorDesc::dInt); |
| break; |
| |
| case LCONST_1 : |
| push(mvm::jit::constantLongOne, AssessorDesc::dLong); |
| push(mvm::jit::constantZero, AssessorDesc::dInt); |
| break; |
| |
| case FCONST_0 : |
| push(mvm::jit::constantFloatZero, AssessorDesc::dFloat); |
| break; |
| |
| case FCONST_1 : |
| push(mvm::jit::constantFloatOne, AssessorDesc::dFloat); |
| break; |
| |
| case FCONST_2 : |
| push(mvm::jit::constantFloatTwo, AssessorDesc::dFloat); |
| break; |
| |
| case DCONST_0 : |
| push(mvm::jit::constantDoubleZero, AssessorDesc::dDouble); |
| push(mvm::jit::constantZero, AssessorDesc::dInt); |
| break; |
| |
| case DCONST_1 : |
| push(mvm::jit::constantDoubleOne, AssessorDesc::dDouble); |
| push(mvm::jit::constantZero, AssessorDesc::dInt); |
| break; |
| |
| case BIPUSH : |
| mvm::jit::protectConstants();//->lock(); |
| push(ConstantExpr::getSExt(ConstantInt::get(Type::Int8Ty, |
| bytecodes[++i]), |
| Type::Int32Ty), AssessorDesc::dInt); |
| mvm::jit::unprotectConstants();//->unlock(); |
| break; |
| |
| case SIPUSH : |
| mvm::jit::protectConstants();//->lock(); |
| push(ConstantExpr::getSExt(ConstantInt::get(Type::Int16Ty, |
| readS2(bytecodes, i)), |
| Type::Int32Ty), AssessorDesc::dInt); |
| mvm::jit::unprotectConstants();//->unlock(); |
| break; |
| |
| case LDC : |
| _ldc(bytecodes[++i]); |
| break; |
| |
| case LDC_W : |
| _ldc(readS2(bytecodes, i)); |
| break; |
| |
| case LDC2_W : |
| _ldc(readS2(bytecodes, i)); |
| push(mvm::jit::constantZero, AssessorDesc::dInt); |
| break; |
| |
| case ILOAD : |
| push(new LoadInst(intLocals[WREAD_U1(bytecodes, false, i)], "", |
| currentBlock), AssessorDesc::dInt); |
| break; |
| |
| case LLOAD : |
| push(new LoadInst(longLocals[WREAD_U1(bytecodes, false, i)], "", |
| currentBlock), AssessorDesc::dLong); |
| push(mvm::jit::constantZero, AssessorDesc::dInt); |
| break; |
| |
| case FLOAD : |
| push(new LoadInst(floatLocals[WREAD_U1(bytecodes, false, i)], "", |
| currentBlock), AssessorDesc::dFloat); |
| break; |
| |
| case DLOAD : |
| push(new LoadInst(doubleLocals[WREAD_U1(bytecodes, false, i)], "", |
| currentBlock), AssessorDesc::dDouble); |
| push(mvm::jit::constantZero, AssessorDesc::dInt); |
| break; |
| |
| case ALOAD : |
| push(new LoadInst(objectLocals[WREAD_U1(bytecodes, false, i)], "", |
| currentBlock), AssessorDesc::dRef); |
| break; |
| |
| case ILOAD_0 : |
| push(new LoadInst(intLocals[0], "", currentBlock), AssessorDesc::dInt); |
| break; |
| |
| case ILOAD_1 : |
| push(new LoadInst(intLocals[1], "", currentBlock), AssessorDesc::dInt); |
| break; |
| |
| case ILOAD_2 : |
| push(new LoadInst(intLocals[2], "", currentBlock), AssessorDesc::dInt); |
| break; |
| |
| case ILOAD_3 : |
| push(new LoadInst(intLocals[3], "", currentBlock), AssessorDesc::dInt); |
| break; |
| |
| case LLOAD_0 : |
| push(new LoadInst(longLocals[0], "", currentBlock), AssessorDesc::dLong); |
| push(mvm::jit::constantZero, AssessorDesc::dInt); |
| break; |
| |
| case LLOAD_1 : |
| push(new LoadInst(longLocals[1], "", currentBlock), AssessorDesc::dLong); |
| push(mvm::jit::constantZero, AssessorDesc::dInt); |
| break; |
| |
| case LLOAD_2 : |
| push(new LoadInst(longLocals[2], "", currentBlock), AssessorDesc::dLong); |
| push(mvm::jit::constantZero, AssessorDesc::dInt); |
| break; |
| |
| case LLOAD_3 : |
| push(new LoadInst(longLocals[3], "", currentBlock), AssessorDesc::dLong); |
| push(mvm::jit::constantZero, AssessorDesc::dInt); |
| break; |
| |
| case FLOAD_0 : |
| push(new LoadInst(floatLocals[0], "", currentBlock), AssessorDesc::dFloat); |
| break; |
| |
| case FLOAD_1 : |
| push(new LoadInst(floatLocals[1], "", currentBlock), AssessorDesc::dFloat); |
| break; |
| |
| case FLOAD_2 : |
| push(new LoadInst(floatLocals[2], "", currentBlock), AssessorDesc::dFloat); |
| break; |
| |
| case FLOAD_3 : |
| push(new LoadInst(floatLocals[3], "", currentBlock), AssessorDesc::dFloat); |
| break; |
| |
| case DLOAD_0 : |
| push(new LoadInst(doubleLocals[0], "", currentBlock), AssessorDesc::dDouble); |
| push(mvm::jit::constantZero, AssessorDesc::dInt); |
| break; |
| |
| case DLOAD_1 : |
| push(new LoadInst(doubleLocals[1], "", currentBlock), AssessorDesc::dDouble); |
| push(mvm::jit::constantZero, AssessorDesc::dInt); |
| break; |
| |
| case DLOAD_2 : |
| push(new LoadInst(doubleLocals[2], "", currentBlock), AssessorDesc::dDouble); |
| push(mvm::jit::constantZero, AssessorDesc::dInt); |
| break; |
| |
| case DLOAD_3 : |
| push(new LoadInst(doubleLocals[3], "", currentBlock), AssessorDesc::dDouble); |
| push(mvm::jit::constantZero, AssessorDesc::dInt); |
| break; |
| |
| case ALOAD_0 : |
| push(new LoadInst(objectLocals[0], "", currentBlock), AssessorDesc::dRef); |
| break; |
| |
| case ALOAD_1 : |
| push(new LoadInst(objectLocals[1], "", currentBlock), AssessorDesc::dRef); |
| break; |
| |
| case ALOAD_2 : |
| push(new LoadInst(objectLocals[2], "", currentBlock), AssessorDesc::dRef); |
| break; |
| |
| case ALOAD_3 : |
| push(new LoadInst(objectLocals[3], "", currentBlock), AssessorDesc::dRef); |
| break; |
| |
| case IALOAD : { |
| Value* index = pop(); |
| Value* obj = pop(); |
| Value* ptr = verifyAndComputePtr(obj, index, ArraySInt32::llvmType); |
| push(new LoadInst(ptr, "", currentBlock), AssessorDesc::dInt); |
| break; |
| } |
| |
| case LALOAD : { |
| Value* index = pop(); |
| Value* obj = pop(); |
| Value* ptr = verifyAndComputePtr(obj, index, ArrayLong::llvmType); |
| push(new LoadInst(ptr, "", currentBlock), AssessorDesc::dLong); |
| push(mvm::jit::constantZero, AssessorDesc::dInt); |
| break; |
| } |
| |
| case FALOAD : { |
| Value* index = pop(); |
| Value* obj = pop(); |
| Value* ptr = verifyAndComputePtr(obj, index, ArrayFloat::llvmType); |
| push(new LoadInst(ptr, "", currentBlock), AssessorDesc::dFloat); |
| break; |
| } |
| |
| case DALOAD : { |
| Value* index = pop(); |
| Value* obj = pop(); |
| Value* ptr = verifyAndComputePtr(obj, index, ArrayDouble::llvmType); |
| push(new LoadInst(ptr, "", currentBlock), AssessorDesc::dDouble); |
| push(mvm::jit::constantZero, AssessorDesc::dInt); |
| break; |
| } |
| |
| case AALOAD : { |
| Value* index = pop(); |
| Value* obj = pop(); |
| Value* ptr = verifyAndComputePtr(obj, index, ArrayObject::llvmType); |
| push(new LoadInst(ptr, "", currentBlock), AssessorDesc::dRef); |
| break; |
| } |
| |
| case BALOAD : { |
| Value* index = pop(); |
| Value* obj = pop(); |
| Value* ptr = verifyAndComputePtr(obj, index, ArraySInt8::llvmType); |
| Value* val = new LoadInst(ptr, "", currentBlock); |
| push(new SExtInst(val, Type::Int32Ty, "", currentBlock), AssessorDesc::dInt); |
| break; |
| } |
| |
| case CALOAD : { |
| Value* index = pop(); |
| Value* obj = pop(); |
| Value* ptr = verifyAndComputePtr(obj, index, ArrayUInt16::llvmType); |
| Value* val = new LoadInst(ptr, "", currentBlock); |
| push(new ZExtInst(val, Type::Int32Ty, "", currentBlock), AssessorDesc::dInt); |
| break; |
| } |
| |
| case SALOAD : { |
| Value* index = pop(); |
| Value* obj = pop(); |
| Value* ptr = verifyAndComputePtr(obj, index, ArraySInt16::llvmType); |
| Value* val = new LoadInst(ptr, "", currentBlock); |
| push(new SExtInst(val, Type::Int32Ty, "", currentBlock), AssessorDesc::dInt); |
| break; |
| } |
| |
| case ISTORE : { |
| Value* val = popAsInt(); |
| new StoreInst(val, intLocals[WREAD_U1(bytecodes, false, i)], false, |
| currentBlock); |
| break; |
| } |
| |
| case LSTORE : |
| pop(); // remove the 0 on the stack |
| new StoreInst(pop(), longLocals[WREAD_U1(bytecodes, false, i)], false, |
| currentBlock); |
| break; |
| |
| case FSTORE : |
| new StoreInst(pop(), floatLocals[WREAD_U1(bytecodes, false, i)], false, |
| currentBlock); |
| break; |
| |
| case DSTORE : |
| pop(); // remove the 0 on the stack |
| new StoreInst(pop(), doubleLocals[WREAD_U1(bytecodes, false, i)], false, |
| currentBlock); |
| break; |
| |
| case ASTORE : |
| new StoreInst(pop(), objectLocals[WREAD_U1(bytecodes, false, i)], false, |
| currentBlock); |
| break; |
| |
| case ISTORE_0 : { |
| Value* val = pop(); |
| if (val->getType() != Type::Int32Ty) // int8 and int16 |
| val = new ZExtInst(val, Type::Int32Ty, "", currentBlock); |
| new StoreInst(val, intLocals[0], false, currentBlock); |
| break; |
| } |
| |
| case ISTORE_1 : { |
| Value* val = pop(); |
| if (val->getType() != Type::Int32Ty) // int8 and int16 |
| val = new ZExtInst(val, Type::Int32Ty, "", currentBlock); |
| new StoreInst(val, intLocals[1], false, currentBlock); |
| break; |
| } |
| |
| case ISTORE_2 : { |
| Value* val = pop(); |
| if (val->getType() != Type::Int32Ty) // int8 and int16 |
| val = new ZExtInst(val, Type::Int32Ty, "", currentBlock); |
| new StoreInst(val, intLocals[2], false, currentBlock); |
| break; |
| } |
| |
| case ISTORE_3 : { |
| Value* val = pop(); |
| if (val->getType() != Type::Int32Ty) // int8 and int16 |
| val = new ZExtInst(val, Type::Int32Ty, "", currentBlock); |
| new StoreInst(val, intLocals[3], false, currentBlock); |
| break; |
| } |
| |
| case LSTORE_0 : |
| pop(); // remove the 0 on the stack |
| new StoreInst(pop(), longLocals[0], false, currentBlock); |
| break; |
| |
| case LSTORE_1 : |
| pop(); // remove the 0 on the stack |
| new StoreInst(pop(), longLocals[1], false, currentBlock); |
| break; |
| |
| case LSTORE_2 : |
| pop(); // remove the 0 on the stack |
| new StoreInst(pop(), longLocals[2], false, currentBlock); |
| break; |
| |
| case LSTORE_3 : |
| pop(); // remove the 0 on the stack |
| new StoreInst(pop(), longLocals[3], false, currentBlock); |
| break; |
| |
| case FSTORE_0 : |
| new StoreInst(pop(), floatLocals[0], false, currentBlock); |
| break; |
| |
| case FSTORE_1 : |
| new StoreInst(pop(), floatLocals[1], false, currentBlock); |
| break; |
| |
| case FSTORE_2 : |
| new StoreInst(pop(), floatLocals[2], false, currentBlock); |
| break; |
| |
| case FSTORE_3 : |
| new StoreInst(pop(), floatLocals[3], false, currentBlock); |
| break; |
| |
| case DSTORE_0 : |
| pop(); // remove the 0 on the stack |
| new StoreInst(pop(), doubleLocals[0], false, currentBlock); |
| break; |
| |
| case DSTORE_1 : |
| pop(); // remove the 0 on the stack |
| new StoreInst(pop(), doubleLocals[1], false, currentBlock); |
| break; |
| |
| case DSTORE_2 : |
| pop(); // remove the 0 on the stack |
| new StoreInst(pop(), doubleLocals[2], false, currentBlock); |
| break; |
| |
| case DSTORE_3 : |
| pop(); // remove the 0 on the stack |
| new StoreInst(pop(), doubleLocals[3], false, currentBlock); |
| break; |
| |
| case ASTORE_0 : |
| new StoreInst(pop(), objectLocals[0], false, currentBlock); |
| break; |
| |
| case ASTORE_1 : |
| new StoreInst(pop(), objectLocals[1], false, currentBlock); |
| break; |
| |
| case ASTORE_2 : |
| new StoreInst(pop(), objectLocals[2], false, currentBlock); |
| break; |
| |
| case ASTORE_3 : |
| new StoreInst(pop(), objectLocals[3], false, currentBlock); |
| break; |
| |
| case IASTORE : { |
| Value* val = popAsInt(); |
| Value* index = popAsInt(); |
| Value* obj = pop(); |
| Value* ptr = verifyAndComputePtr(obj, index, ArraySInt32::llvmType); |
| new StoreInst(val, ptr, false, currentBlock); |
| break; |
| } |
| |
| case LASTORE : { |
| pop(); // remove the 0 on stack |
| Value* val = pop(); |
| Value* index = pop(); |
| Value* obj = pop(); |
| Value* ptr = verifyAndComputePtr(obj, index, ArrayLong::llvmType); |
| new StoreInst(val, ptr, false, currentBlock); |
| break; |
| } |
| |
| case FASTORE : { |
| Value* val = pop(); |
| Value* index = pop(); |
| Value* obj = pop(); |
| Value* ptr = verifyAndComputePtr(obj, index, ArrayFloat::llvmType); |
| new StoreInst(val, ptr, false, currentBlock); |
| break; |
| } |
| |
| case DASTORE : { |
| pop(); // remove the 0 on stack |
| Value* val = pop(); |
| Value* index = pop(); |
| Value* obj = pop(); |
| Value* ptr = verifyAndComputePtr(obj, index, ArrayDouble::llvmType); |
| new StoreInst(val, ptr, false, currentBlock); |
| break; |
| } |
| |
| case AASTORE : { |
| Value* val = pop(); |
| Value* index = pop(); |
| Value* obj = pop(); |
| Value* ptr = verifyAndComputePtr(obj, index, ArrayObject::llvmType); |
| new StoreInst(val, ptr, false, currentBlock); |
| break; |
| } |
| |
| case BASTORE : { |
| Value* val = pop(); |
| if (val->getType() != Type::Int8Ty) { |
| val = new TruncInst(val, Type::Int8Ty, "", currentBlock); |
| } |
| Value* index = pop(); |
| Value* obj = pop(); |
| Value* ptr = verifyAndComputePtr(obj, index, ArraySInt8::llvmType); |
| new StoreInst(val, ptr, false, currentBlock); |
| break; |
| } |
| |
| case CASTORE : { |
| const AssessorDesc* ass = topFunc(); |
| Value* val = pop(); |
| if (ass == AssessorDesc::dInt) { |
| val = new TruncInst(val, Type::Int16Ty, "", currentBlock); |
| } else if (ass == AssessorDesc::dByte || ass == AssessorDesc::dBool) { |
| val = new ZExtInst(val, Type::Int16Ty, "", currentBlock); |
| } |
| Value* index = pop(); |
| Value* obj = pop(); |
| Value* ptr = verifyAndComputePtr(obj, index, ArrayUInt16::llvmType); |
| new StoreInst(val, ptr, false, currentBlock); |
| break; |
| } |
| |
| case SASTORE : { |
| const AssessorDesc* ass = topFunc(); |
| Value* val = pop(); |
| if (ass == AssessorDesc::dInt) { |
| val = new TruncInst(val, Type::Int16Ty, "", currentBlock); |
| } else if (ass == AssessorDesc::dByte || ass == AssessorDesc::dBool) { |
| val = new SExtInst(val, Type::Int16Ty, "", currentBlock); |
| } |
| Value* index = pop(); |
| Value* obj = pop(); |
| Value* ptr = verifyAndComputePtr(obj, index, ArraySInt16::llvmType); |
| new StoreInst(val, ptr, false, currentBlock); |
| break; |
| } |
| |
| case POP : |
| pop(); |
| break; |
| |
| case POP2 : |
| pop(); pop(); |
| break; |
| |
| case DUP : |
| push(top(), topFunc()); |
| break; |
| |
| case DUP_X1 : { |
| std::pair<Value*, const AssessorDesc*> one = popPair(); |
| std::pair<Value*, const AssessorDesc*> two = popPair(); |
| push(one); |
| push(two); |
| push(one); |
| break; |
| } |
| |
| case DUP_X2 : { |
| std::pair<Value*, const AssessorDesc*> one = popPair(); |
| std::pair<Value*, const AssessorDesc*> two = popPair(); |
| std::pair<Value*, const AssessorDesc*> three = popPair(); |
| push(one); |
| push(three); |
| push(two); |
| push(one); |
| break; |
| } |
| |
| case DUP2 : |
| push(stack[stackSize() - 2]); |
| push(stack[stackSize() - 2]); |
| break; |
| |
| case DUP2_X1 : { |
| std::pair<Value*, const AssessorDesc*> one = popPair(); |
| std::pair<Value*, const AssessorDesc*> two = popPair(); |
| std::pair<Value*, const AssessorDesc*> three = popPair(); |
| |
| push(two); |
| push(one); |
| |
| push(three); |
| push(two); |
| push(one); |
| |
| break; |
| } |
| |
| case DUP2_X2 : { |
| std::pair<Value*, const AssessorDesc*> one = popPair(); |
| std::pair<Value*, const AssessorDesc*> two = popPair(); |
| std::pair<Value*, const AssessorDesc*> three = popPair(); |
| std::pair<Value*, const AssessorDesc*> four = popPair(); |
| |
| push(two); |
| push(one); |
| |
| push(four); |
| push(three); |
| push(two); |
| push(one); |
| |
| break; |
| } |
| |
| case SWAP : { |
| std::pair<Value*, const AssessorDesc*> one = popPair(); |
| std::pair<Value*, const AssessorDesc*> two = popPair(); |
| push(one); |
| push(two); |
| break; |
| } |
| |
| case IADD : { |
| Value* val2 = popAsInt(); |
| Value* val1 = popAsInt(); |
| push(BinaryOperator::createAdd(val1, val2, "", currentBlock), AssessorDesc::dInt); |
| break; |
| } |
| |
| case LADD : { |
| pop(); |
| llvm::Value* val2 = pop(); |
| pop(); |
| llvm::Value* val1 = pop(); |
| push(BinaryOperator::createAdd(val1, val2, "", currentBlock), AssessorDesc::dLong); |
| push(mvm::jit::constantZero, AssessorDesc::dInt); |
| break; |
| } |
| |
| case FADD : { |
| Value* val2 = pop(); |
| Value* val1 = pop(); |
| push(BinaryOperator::createAdd(val1, val2, "", currentBlock), AssessorDesc::dFloat); |
| break; |
| } |
| |
| case DADD : { |
| pop(); |
| llvm::Value* val2 = pop(); |
| pop(); |
| llvm::Value* val1 = pop(); |
| push(BinaryOperator::createAdd(val1, val2, "", currentBlock), AssessorDesc::dDouble); |
| push(mvm::jit::constantZero, AssessorDesc::dInt); |
| break; |
| } |
| |
| case ISUB : { |
| Value* val2 = popAsInt(); |
| Value* val1 = popAsInt(); |
| push(BinaryOperator::createSub(val1, val2, "", currentBlock), AssessorDesc::dInt); |
| break; |
| } |
| case LSUB : { |
| pop(); |
| llvm::Value* val2 = pop(); |
| pop(); |
| llvm::Value* val1 = pop(); |
| push(BinaryOperator::createSub(val1, val2, "", currentBlock), AssessorDesc::dLong); |
| push(mvm::jit::constantZero, AssessorDesc::dInt); |
| break; |
| } |
| |
| case FSUB : { |
| Value* val2 = pop(); |
| Value* val1 = pop(); |
| push(BinaryOperator::createSub(val1, val2, "", currentBlock), AssessorDesc::dFloat); |
| break; |
| } |
| |
| case DSUB : { |
| pop(); |
| llvm::Value* val2 = pop(); |
| pop(); |
| llvm::Value* val1 = pop(); |
| push(BinaryOperator::createSub(val1, val2, "", currentBlock), AssessorDesc::dDouble); |
| push(mvm::jit::constantZero, AssessorDesc::dInt); |
| break; |
| } |
| |
| case IMUL : { |
| Value* val2 = popAsInt(); |
| Value* val1 = popAsInt(); |
| push(BinaryOperator::createMul(val1, val2, "", currentBlock), AssessorDesc::dInt); |
| break; |
| } |
| |
| case LMUL : { |
| pop(); |
| llvm::Value* val2 = pop(); |
| pop(); |
| llvm::Value* val1 = pop(); |
| push(BinaryOperator::createMul(val1, val2, "", currentBlock), AssessorDesc::dLong); |
| push(mvm::jit::constantZero, AssessorDesc::dInt); |
| break; |
| } |
| |
| case FMUL : { |
| Value* val2 = pop(); |
| Value* val1 = pop(); |
| push(BinaryOperator::createMul(val1, val2, "", currentBlock), AssessorDesc::dFloat); |
| break; |
| } |
| |
| case DMUL : { |
| pop(); |
| llvm::Value* val2 = pop(); |
| pop(); |
| llvm::Value* val1 = pop(); |
| push(BinaryOperator::createMul(val1, val2, "", currentBlock), AssessorDesc::dDouble); |
| push(mvm::jit::constantZero, AssessorDesc::dInt); |
| break; |
| } |
| |
| case IDIV : { |
| Value* val2 = popAsInt(); |
| Value* val1 = popAsInt(); |
| push(BinaryOperator::createSDiv(val1, val2, "", currentBlock), AssessorDesc::dInt); |
| break; |
| } |
| |
| case LDIV : { |
| pop(); |
| llvm::Value* val2 = pop(); |
| pop(); |
| llvm::Value* val1 = pop(); |
| push(BinaryOperator::createSDiv(val1, val2, "", currentBlock), AssessorDesc::dLong); |
| push(mvm::jit::constantZero, AssessorDesc::dInt); |
| break; |
| } |
| |
| case FDIV : { |
| Value* val2 = pop(); |
| Value* val1 = pop(); |
| push(BinaryOperator::createFDiv(val1, val2, "", currentBlock), AssessorDesc::dFloat); |
| break; |
| } |
| |
| case DDIV : { |
| pop(); |
| llvm::Value* val2 = pop(); |
| pop(); |
| llvm::Value* val1 = pop(); |
| push(BinaryOperator::createFDiv(val1, val2, "", currentBlock), AssessorDesc::dDouble); |
| push(mvm::jit::constantZero, AssessorDesc::dInt); |
| break; |
| } |
| |
| case IREM : { |
| Value* val2 = popAsInt(); |
| Value* val1 = popAsInt(); |
| push(BinaryOperator::createSRem(val1, val2, "", currentBlock), AssessorDesc::dInt); |
| break; |
| } |
| |
| case LREM : { |
| pop(); |
| llvm::Value* val2 = pop(); |
| pop(); |
| llvm::Value* val1 = pop(); |
| push(BinaryOperator::createSRem(val1, val2, "", currentBlock), AssessorDesc::dLong); |
| push(mvm::jit::constantZero, AssessorDesc::dInt); |
| break; |
| } |
| |
| case FREM : { |
| Value* val2 = pop(); |
| Value* val1 = pop(); |
| push(BinaryOperator::createFRem(val1, val2, "", currentBlock), AssessorDesc::dFloat); |
| break; |
| } |
| |
| case DREM : { |
| pop(); |
| llvm::Value* val2 = pop(); |
| pop(); |
| llvm::Value* val1 = pop(); |
| push(BinaryOperator::createFRem(val1, val2, "", currentBlock), AssessorDesc::dDouble); |
| push(mvm::jit::constantZero, AssessorDesc::dInt); |
| break; |
| } |
| |
| case INEG : |
| push(BinaryOperator::createSub( |
| mvm::jit::constantZero, |
| popAsInt(), "", currentBlock), AssessorDesc::dInt); |
| break; |
| |
| case LNEG : { |
| pop(); |
| push(BinaryOperator::createSub( |
| mvm::jit::constantLongZero, |
| pop(), "", currentBlock), AssessorDesc::dLong); |
| push(mvm::jit::constantZero, AssessorDesc::dInt); |
| break; |
| } |
| |
| case FNEG : |
| push(BinaryOperator::createSub( |
| mvm::jit::constantFloatMinusZero, |
| pop(), "", currentBlock), AssessorDesc::dFloat); |
| break; |
| |
| case DNEG : { |
| pop(); |
| push(BinaryOperator::createSub( |
| mvm::jit::constantDoubleMinusZero, |
| pop(), "", currentBlock), AssessorDesc::dDouble); |
| push(mvm::jit::constantZero, AssessorDesc::dInt); |
| break; |
| } |
| |
| case ISHL : { |
| Value* val2 = popAsInt(); |
| Value* val1 = popAsInt(); |
| push(BinaryOperator::createShl(val1, val2, "", currentBlock), AssessorDesc::dInt); |
| break; |
| } |
| |
| case LSHL : { |
| Value* val2 = new ZExtInst(pop(), Type::Int64Ty, "", currentBlock); |
| pop(); // remove the 0 on the stack |
| Value* val1 = pop(); |
| push(BinaryOperator::createShl(val1, val2, "", currentBlock), AssessorDesc::dLong); |
| push(mvm::jit::constantZero, AssessorDesc::dInt); |
| break; |
| } |
| |
| case ISHR : { |
| Value* val2 = popAsInt(); |
| Value* val1 = popAsInt(); |
| push(BinaryOperator::createAShr(val1, val2, "", currentBlock), AssessorDesc::dInt); |
| break; |
| } |
| |
| case LSHR : { |
| Value* val2 = new ZExtInst(pop(), Type::Int64Ty, "", currentBlock); |
| pop(); // remove the 0 on the stack |
| Value* val1 = pop(); |
| push(BinaryOperator::createAShr(val1, val2, "", currentBlock), AssessorDesc::dLong); |
| push(mvm::jit::constantZero, AssessorDesc::dInt); |
| break; |
| } |
| |
| case IUSHR : { |
| Value* val2 = popAsInt(); |
| Value* val1 = popAsInt(); |
| push(BinaryOperator::createLShr(val1, val2, "", currentBlock), AssessorDesc::dInt); |
| break; |
| } |
| |
| case LUSHR : { |
| Value* val2 = new ZExtInst(pop(), Type::Int64Ty, "", currentBlock); |
| pop(); // remove the 0 on the stack |
| Value* val1 = pop(); |
| push(BinaryOperator::createLShr(val1, val2, "", currentBlock), AssessorDesc::dLong); |
| push(mvm::jit::constantZero, AssessorDesc::dInt); |
| break; |
| } |
| |
| case IAND : { |
| Value* val2 = popAsInt(); |
| Value* val1 = popAsInt(); |
| push(BinaryOperator::createAnd(val1, val2, "", currentBlock), AssessorDesc::dInt); |
| break; |
| } |
| |
| case LAND : { |
| pop(); |
| Value* val2 = pop(); |
| pop(); // remove the 0 on the stack |
| Value* val1 = pop(); |
| push(BinaryOperator::createAnd(val1, val2, "", currentBlock), AssessorDesc::dLong); |
| push(mvm::jit::constantZero, AssessorDesc::dInt); |
| break; |
| } |
| |
| case IOR : { |
| Value* val2 = popAsInt(); |
| Value* val1 = popAsInt(); |
| push(BinaryOperator::createOr(val1, val2, "", currentBlock), AssessorDesc::dInt); |
| break; |
| } |
| |
| case LOR : { |
| pop(); |
| Value* val2 = pop(); |
| pop(); // remove the 0 on the stack |
| Value* val1 = pop(); |
| push(BinaryOperator::createOr(val1, val2, "", currentBlock), AssessorDesc::dLong); |
| push(mvm::jit::constantZero, AssessorDesc::dInt); |
| break; |
| } |
| |
| case IXOR : { |
| Value* val2 = popAsInt(); |
| Value* val1 = popAsInt(); |
| push(BinaryOperator::createXor(val1, val2, "", currentBlock), AssessorDesc::dInt); |
| break; |
| } |
| |
| case LXOR : { |
| pop(); |
| Value* val2 = pop(); |
| pop(); // remove the 0 on the stack |
| Value* val1 = pop(); |
| push(BinaryOperator::createXor(val1, val2, "", currentBlock), AssessorDesc::dLong); |
| push(mvm::jit::constantZero, AssessorDesc::dInt); |
| break; |
| } |
| |
| case IINC : { |
| uint16 idx = WREAD_U1(bytecodes, true, i); |
| sint16 val = WREAD_S1(bytecodes, false, i); |
| mvm::jit::protectConstants();//->lock(); |
| llvm::Value* add = BinaryOperator::createAdd( |
| new LoadInst(intLocals[idx], "", currentBlock), |
| ConstantInt::get(Type::Int32Ty, val), "", |
| currentBlock); |
| mvm::jit::unprotectConstants();//->unlock(); |
| new StoreInst(add, intLocals[idx], false, currentBlock); |
| break; |
| } |
| |
| case I2L : |
| push(new SExtInst(pop(), llvm::Type::Int64Ty, "", currentBlock), AssessorDesc::dLong); |
| push(mvm::jit::constantZero, AssessorDesc::dInt); |
| break; |
| |
| case I2F : |
| push(new SIToFPInst(pop(), llvm::Type::FloatTy, "", currentBlock), AssessorDesc::dFloat); |
| break; |
| |
| case I2D : |
| push(new SIToFPInst(pop(), llvm::Type::DoubleTy, "", currentBlock), AssessorDesc::dDouble); |
| push(mvm::jit::constantZero, AssessorDesc::dInt); |
| break; |
| |
| case L2I : |
| pop(); |
| push(new TruncInst(pop(), llvm::Type::Int32Ty, "", currentBlock), AssessorDesc::dInt); |
| break; |
| |
| case L2F : |
| pop(); |
| push(new SIToFPInst(pop(), llvm::Type::FloatTy, "", currentBlock), AssessorDesc::dFloat); |
| break; |
| |
| case L2D : |
| pop(); |
| push(new SIToFPInst(pop(), llvm::Type::DoubleTy, "", currentBlock), AssessorDesc::dDouble); |
| push(mvm::jit::constantZero, AssessorDesc::dInt); |
| break; |
| |
| case F2I : { |
| llvm::Value* val = pop(); |
| llvm::Value* test = new FCmpInst(FCmpInst::FCMP_ONE, val, val, "", |
| currentBlock); |
| |
| BasicBlock* res = createBasicBlock("F2I"); |
| PHINode* node = new PHINode(llvm::Type::Int32Ty, "", res); |
| node->addIncoming(mvm::jit::constantZero, currentBlock); |
| BasicBlock* cont = createBasicBlock("F2I"); |
| |
| new BranchInst(res, cont, test, currentBlock); |
| |
| currentBlock = cont; |
| |
| test = new FCmpInst(FCmpInst::FCMP_OGE, val, |
| mvm::jit::constantMaxIntFloat, |
| "", currentBlock); |
| |
| cont = createBasicBlock("F2I"); |
| |
| new BranchInst(res, cont, test, currentBlock); |
| node->addIncoming(mvm::jit::constantMaxInt, |
| currentBlock); |
| |
| currentBlock = cont; |
| |
| test = new FCmpInst(FCmpInst::FCMP_OLE, val, |
| mvm::jit::constantMinIntFloat, |
| "", currentBlock); |
| |
| cont = createBasicBlock("F2I"); |
| |
| new BranchInst(res, cont, test, currentBlock); |
| node->addIncoming(mvm::jit::constantMinInt, currentBlock); |
| |
| currentBlock = cont; |
| llvm::Value* newVal = new FPToSIInst(val, Type::Int32Ty, "", |
| currentBlock); |
| new BranchInst(res, currentBlock); |
| |
| node->addIncoming(newVal, currentBlock); |
| |
| currentBlock = res; |
| |
| push(node, AssessorDesc::dInt); |
| break; |
| } |
| |
| case F2L : { |
| llvm::Value* val = pop(); |
| llvm::Value* test = new FCmpInst(FCmpInst::FCMP_ONE, val, val, "", |
| currentBlock); |
| |
| BasicBlock* res = createBasicBlock("F2L"); |
| PHINode* node = new PHINode(llvm::Type::Int64Ty, "", res); |
| node->addIncoming(mvm::jit::constantLongZero, currentBlock); |
| BasicBlock* cont = createBasicBlock("F2L"); |
| |
| new BranchInst(res, cont, test, currentBlock); |
| |
| currentBlock = cont; |
| |
| test = new FCmpInst(FCmpInst::FCMP_OGE, val, |
| mvm::jit::constantMaxLongFloat, |
| "", currentBlock); |
| |
| cont = createBasicBlock("F2L"); |
| |
| new BranchInst(res, cont, test, currentBlock); |
| node->addIncoming(mvm::jit::constantMaxLong, currentBlock); |
| |
| currentBlock = cont; |
| |
| test = new FCmpInst(FCmpInst::FCMP_OLE, val, |
| mvm::jit::constantMinLongFloat, "", currentBlock); |
| |
| cont = createBasicBlock("F2L"); |
| |
| new BranchInst(res, cont, test, currentBlock); |
| node->addIncoming(mvm::jit::constantMinLong, currentBlock); |
| |
| currentBlock = cont; |
| llvm::Value* newVal = new FPToSIInst(val, Type::Int64Ty, "", |
| currentBlock); |
| new BranchInst(res, currentBlock); |
| |
| node->addIncoming(newVal, currentBlock); |
| |
| currentBlock = res; |
| |
| push(node, AssessorDesc::dLong); |
| push(mvm::jit::constantZero, AssessorDesc::dInt); |
| break; |
| } |
| |
| case F2D : |
| push(new FPExtInst(pop(), llvm::Type::DoubleTy, "", currentBlock), AssessorDesc::dDouble); |
| push(mvm::jit::constantZero, AssessorDesc::dInt); |
| break; |
| |
| case D2I : { |
| pop(); // remove the 0 on the stack |
| llvm::Value* val = pop(); |
| llvm::Value* test = new FCmpInst(FCmpInst::FCMP_ONE, val, val, "", |
| currentBlock); |
| |
| BasicBlock* res = createBasicBlock("D2I"); |
| PHINode* node = new PHINode(llvm::Type::Int32Ty, "", res); |
| node->addIncoming(mvm::jit::constantZero, currentBlock); |
| BasicBlock* cont = createBasicBlock("D2I"); |
| |
| new BranchInst(res, cont, test, currentBlock); |
| |
| currentBlock = cont; |
| |
| test = new FCmpInst(FCmpInst::FCMP_OGE, val, mvm::jit::constantMaxIntDouble, |
| "", currentBlock); |
| |
| cont = createBasicBlock("D2I"); |
| |
| new BranchInst(res, cont, test, currentBlock); |
| node->addIncoming(mvm::jit::constantMaxInt, currentBlock); |
| |
| currentBlock = cont; |
| |
| test = new FCmpInst(FCmpInst::FCMP_OLE, val, mvm::jit::constantMinIntDouble, |
| "", currentBlock); |
| |
| cont = createBasicBlock("D2I"); |
| |
| new BranchInst(res, cont, test, currentBlock); |
| node->addIncoming(mvm::jit::constantMinInt, currentBlock); |
| |
| currentBlock = cont; |
| llvm::Value* newVal = new FPToSIInst(val, Type::Int32Ty, "", |
| currentBlock); |
| new BranchInst(res, currentBlock); |
| |
| node->addIncoming(newVal, currentBlock); |
| |
| currentBlock = res; |
| |
| push(node, AssessorDesc::dInt); |
| |
| break; |
| } |
| |
| case D2L : { |
| pop(); // remove the 0 on the stack |
| llvm::Value* val = pop(); |
| llvm::Value* test = new FCmpInst(FCmpInst::FCMP_ONE, val, val, "", |
| currentBlock); |
| |
| BasicBlock* res = createBasicBlock("D2L"); |
| PHINode* node = new PHINode(llvm::Type::Int64Ty, "", res); |
| node->addIncoming(mvm::jit::constantLongZero, currentBlock); |
| BasicBlock* cont = createBasicBlock("D2L"); |
| |
| new BranchInst(res, cont, test, currentBlock); |
| |
| currentBlock = cont; |
| |
| test = new FCmpInst(FCmpInst::FCMP_OGE, val, mvm::jit::constantMaxLongDouble, |
| "", currentBlock); |
| |
| cont = createBasicBlock("D2L"); |
| |
| new BranchInst(res, cont, test, currentBlock); |
| node->addIncoming(mvm::jit::constantMaxLong, currentBlock); |
| |
| currentBlock = cont; |
| |
| test = |
| new FCmpInst(FCmpInst::FCMP_OLE, val, mvm::jit::constantMinLongDouble, |
| "", currentBlock); |
| |
| cont = createBasicBlock("D2L"); |
| |
| new BranchInst(res, cont, test, currentBlock); |
| node->addIncoming(mvm::jit::constantMinLong, currentBlock); |
| |
| currentBlock = cont; |
| llvm::Value* newVal = new FPToSIInst(val, Type::Int64Ty, "", |
| currentBlock); |
| new BranchInst(res, currentBlock); |
| |
| node->addIncoming(newVal, currentBlock); |
| |
| currentBlock = res; |
| |
| push(node, AssessorDesc::dLong); |
| push(mvm::jit::constantZero, AssessorDesc::dInt); |
| break; |
| } |
| |
| case D2F : |
| pop(); // remove the 0 on the stack |
| push(new FPTruncInst(pop(), llvm::Type::FloatTy, "", currentBlock), AssessorDesc::dFloat); |
| break; |
| |
| case I2B : { |
| Value* val = pop(); |
| if (val->getType() == Type::Int32Ty) { |
| val = new TruncInst(val, llvm::Type::Int8Ty, "", currentBlock); |
| } |
| push(new SExtInst(val, llvm::Type::Int32Ty, "", currentBlock), AssessorDesc::dInt); |
| break; |
| } |
| |
| case I2C : { |
| Value* val = pop(); |
| if (val->getType() == Type::Int32Ty) { |
| val = new TruncInst(val, llvm::Type::Int16Ty, "", currentBlock); |
| } |
| push(new ZExtInst(val, llvm::Type::Int32Ty, "", currentBlock), AssessorDesc::dInt); |
| break; |
| } |
| |
| case I2S : { |
| Value* val = pop(); |
| if (val->getType() == Type::Int32Ty) { |
| val = new TruncInst(val, llvm::Type::Int16Ty, "", currentBlock); |
| } |
| push(new SExtInst(val, llvm::Type::Int32Ty, "", currentBlock), AssessorDesc::dInt); |
| break; |
| } |
| |
| case LCMP : { |
| pop(); |
| llvm::Value* val2 = pop(); |
| pop(); |
| llvm::Value* val1 = pop(); |
| |
| llvm::Value* test = new ICmpInst(ICmpInst::ICMP_EQ, val1, val2, "", |
| currentBlock); |
| |
| BasicBlock* cont = createBasicBlock("LCMP"); |
| BasicBlock* res = createBasicBlock("LCMP"); |
| PHINode* node = new PHINode(llvm::Type::Int32Ty, "", res); |
| node->addIncoming(mvm::jit::constantZero, currentBlock); |
| |
| new BranchInst(res, cont, test, currentBlock); |
| currentBlock = cont; |
| |
| test = new ICmpInst(ICmpInst::ICMP_SLT, val1, val2, "", currentBlock); |
| node->addIncoming(mvm::jit::constantMinusOne, currentBlock); |
| |
| cont = createBasicBlock("LCMP"); |
| new BranchInst(res, cont, test, currentBlock); |
| currentBlock = cont; |
| node->addIncoming(mvm::jit::constantOne, currentBlock); |
| new BranchInst(res, currentBlock); |
| currentBlock = res; |
| |
| push(node, AssessorDesc::dInt); |
| break; |
| } |
| |
| case FCMPL : { |
| llvm::Value* val2 = pop(); |
| llvm::Value* val1 = pop(); |
| compareFP(val1, val2, Type::FloatTy, false); |
| break; |
| } |
| |
| case FCMPG : { |
| llvm::Value* val2 = pop(); |
| llvm::Value* val1 = pop(); |
| compareFP(val1, val2, Type::FloatTy, true); |
| break; |
| } |
| |
| case DCMPL : { |
| pop(); |
| llvm::Value* val2 = pop(); |
| pop(); |
| llvm::Value* val1 = pop(); |
| |
| compareFP(val1, val2, Type::DoubleTy, false); |
| break; |
| } |
| |
| case DCMPG : { |
| pop(); |
| llvm::Value* val2 = pop(); |
| pop(); |
| llvm::Value* val1 = pop(); |
| |
| compareFP(val1, val2, Type::DoubleTy, false); |
| break; |
| } |
| |
| case IFEQ : { |
| uint32 tmp = i; |
| BasicBlock* ifTrue = opcodeInfos[tmp + readS2(bytecodes, i)].newBlock; |
| const AssessorDesc* ass = topFunc(); |
| llvm::Value* val = ass->llvmNullConstant; |
| Value* op = pop(); |
| llvm::Value* test = new ICmpInst(ICmpInst::ICMP_EQ, op, val, "", |
| currentBlock); |
| BasicBlock* ifFalse = createBasicBlock("false IFEQ"); |
| branch(test, ifTrue, ifFalse, currentBlock); |
| currentBlock = ifFalse; |
| break; |
| } |
| |
| case IFNE : { |
| uint32 tmp = i; |
| BasicBlock* ifTrue = opcodeInfos[tmp + readS2(bytecodes, i)].newBlock; |
| const AssessorDesc* ass = topFunc(); |
| llvm::Value* val = ass->llvmNullConstant; |
| Value* op = pop(); |
| llvm::Value* test = new ICmpInst(ICmpInst::ICMP_NE, op, val, "", |
| currentBlock); |
| BasicBlock* ifFalse = createBasicBlock("false IFNE"); |
| branch(test, ifTrue, ifFalse, currentBlock); |
| currentBlock = ifFalse; |
| break; |
| } |
| |
| case IFLT : { |
| uint32 tmp = i; |
| BasicBlock* ifTrue = opcodeInfos[tmp + readS2(bytecodes, i)].newBlock; |
| const AssessorDesc* ass = topFunc(); |
| llvm::Value* val = ass->llvmNullConstant; |
| Value* op = pop(); |
| llvm::Value* test = new ICmpInst(ICmpInst::ICMP_SLT, op, val, "", |
| currentBlock); |
| BasicBlock* ifFalse = createBasicBlock("false IFLT"); |
| branch(test, ifTrue, ifFalse, currentBlock); |
| currentBlock = ifFalse; |
| break; |
| } |
| |
| case IFGE : { |
| uint32 tmp = i; |
| BasicBlock* ifTrue = opcodeInfos[tmp + readS2(bytecodes, i)].newBlock; |
| const AssessorDesc* ass = topFunc(); |
| llvm::Value* val = ass->llvmNullConstant; |
| Value* op = pop(); |
| llvm::Value* test = new ICmpInst(ICmpInst::ICMP_SGE, op, val, "", |
| currentBlock); |
| BasicBlock* ifFalse = createBasicBlock("false IFGE"); |
| branch(test, ifTrue, ifFalse, currentBlock); |
| currentBlock = ifFalse; |
| break; |
| } |
| |
| case IFGT : { |
| uint32 tmp = i; |
| BasicBlock* ifTrue = opcodeInfos[tmp + readS2(bytecodes, i)].newBlock; |
| const AssessorDesc* ass = topFunc(); |
| llvm::Value* val = ass->llvmNullConstant; |
| Value* op = pop(); |
| llvm::Value* test = new ICmpInst(ICmpInst::ICMP_SGT, op, val, "", |
| currentBlock); |
| BasicBlock* ifFalse = createBasicBlock("false IFGT"); |
| branch(test, ifTrue, ifFalse, currentBlock); |
| currentBlock = ifFalse; |
| break; |
| } |
| |
| case IFLE : { |
| uint32 tmp = i; |
| BasicBlock* ifTrue = opcodeInfos[tmp + readS2(bytecodes, i)].newBlock; |
| const AssessorDesc* ass = topFunc(); |
| llvm::Value* val = ass->llvmNullConstant; |
| Value* op = pop(); |
| llvm::Value* test = new ICmpInst(ICmpInst::ICMP_SLE, op, val, "", |
| currentBlock); |
| BasicBlock* ifFalse = createBasicBlock("false IFLE"); |
| branch(test, ifTrue, ifFalse, currentBlock); |
| currentBlock = ifFalse; |
| break; |
| } |
| |
| case IF_ICMPEQ : { |
| Value *val2 = popAsInt(); |
| Value *val1 = popAsInt(); |
| uint32 tmp = i; |
| BasicBlock* ifTrue = opcodeInfos[tmp + readS2(bytecodes, i)].newBlock; |
| llvm::Value* test = new ICmpInst(ICmpInst::ICMP_EQ, val1, val2, "", |
| currentBlock); |
| BasicBlock* ifFalse = createBasicBlock("false IF_ICMPEQ"); |
| branch(test, ifTrue, ifFalse, currentBlock); |
| currentBlock = ifFalse; |
| break; |
| } |
| |
| case IF_ICMPNE : { |
| Value *val2 = popAsInt(); |
| Value *val1 = popAsInt(); |
| uint32 tmp = i; |
| BasicBlock* ifTrue = opcodeInfos[tmp + readS2(bytecodes, i)].newBlock; |
| llvm::Value* test = new ICmpInst(ICmpInst::ICMP_NE, val1, val2, "", |
| currentBlock); |
| BasicBlock* ifFalse = createBasicBlock("false IF_ICMPNE"); |
| branch(test, ifTrue, ifFalse, currentBlock); |
| currentBlock = ifFalse; |
| break; |
| } |
| |
| case IF_ICMPLT : { |
| Value *val2 = popAsInt(); |
| Value *val1 = popAsInt(); |
| uint32 tmp = i; |
| BasicBlock* ifTrue = opcodeInfos[tmp + readS2(bytecodes, i)].newBlock; |
| llvm::Value* test = new ICmpInst(ICmpInst::ICMP_SLT, val1, val2, "", |
| currentBlock); |
| BasicBlock* ifFalse = createBasicBlock("false IF_IFCMPLT"); |
| branch(test, ifTrue, ifFalse, currentBlock); |
| currentBlock = ifFalse; |
| break; |
| } |
| |
| case IF_ICMPGE : { |
| Value *val2 = popAsInt(); |
| Value *val1 = popAsInt(); |
| uint32 tmp = i; |
| BasicBlock* ifTrue = opcodeInfos[tmp + readS2(bytecodes, i)].newBlock; |
| llvm::Value* test = new ICmpInst(ICmpInst::ICMP_SGE, val1, val2, "", |
| currentBlock); |
| BasicBlock* ifFalse = createBasicBlock("false IF_ICMPGE"); |
| branch(test, ifTrue, ifFalse, currentBlock); |
| currentBlock = ifFalse; |
| break; |
| } |
| |
| case IF_ICMPGT : { |
| Value *val2 = popAsInt(); |
| Value *val1 = popAsInt(); |
| uint32 tmp = i; |
| BasicBlock* ifTrue = opcodeInfos[tmp + readS2(bytecodes, i)].newBlock; |
| llvm::Value* test = new ICmpInst(ICmpInst::ICMP_SGT, val1, val2, "", |
| currentBlock); |
| BasicBlock* ifFalse = createBasicBlock("false IF_ICMPGT"); |
| branch(test, ifTrue, ifFalse, currentBlock); |
| currentBlock = ifFalse; |
| break; |
| } |
| |
| case IF_ICMPLE : { |
| Value *val2 = popAsInt(); |
| Value *val1 = popAsInt(); |
| uint32 tmp = i; |
| BasicBlock* ifTrue = opcodeInfos[tmp + readS2(bytecodes, i)].newBlock; |
| llvm::Value* test = new ICmpInst(ICmpInst::ICMP_SLE, val1, val2, "", |
| currentBlock); |
| BasicBlock* ifFalse = createBasicBlock("false IF_ICMPLE"); |
| branch(test, ifTrue, ifFalse, currentBlock); |
| currentBlock = ifFalse; |
| break; |
| } |
| |
| case IF_ACMPEQ : { |
| Value *val2 = pop(); |
| Value *val1 = pop(); |
| uint32 tmp = i; |
| BasicBlock* ifTrue = opcodeInfos[tmp + readS2(bytecodes, i)].newBlock; |
| llvm::Value* test = new ICmpInst(ICmpInst::ICMP_EQ, val1, val2, "", |
| currentBlock); |
| BasicBlock* ifFalse = createBasicBlock("false IF_ACMPEQ"); |
| branch(test, ifTrue, ifFalse, currentBlock); |
| currentBlock = ifFalse; |
| break; |
| } |
| |
| case IF_ACMPNE : { |
| Value *val2 = pop(); |
| Value *val1 = pop(); |
| uint32 tmp = i; |
| BasicBlock* ifTrue = opcodeInfos[tmp + readS2(bytecodes, i)].newBlock; |
| llvm::Value* test = new ICmpInst(ICmpInst::ICMP_NE, val1, val2, "", |
| currentBlock); |
| BasicBlock* ifFalse = createBasicBlock("false IF_ACMPNE"); |
| branch(test, ifTrue, ifFalse, currentBlock); |
| currentBlock = ifFalse; |
| break; |
| } |
| |
| case GOTO : { |
| uint32 tmp = i; |
| branch(opcodeInfos[tmp + readS2(bytecodes, i)].newBlock, |
| currentBlock); |
| break; |
| } |
| |
| case JSR : { |
| uint32 tmp = i; |
| mvm::jit::protectConstants();//->lock(); |
| Value* expr = ConstantExpr::getIntToPtr( |
| ConstantInt::get(Type::Int64Ty, |
| uint64_t (jsrIndex++)), |
| JavaObject::llvmType); |
| mvm::jit::unprotectConstants();//->unlock(); |
| |
| new StoreInst(expr, supplLocal, false, currentBlock); |
| new BranchInst(opcodeInfos[tmp + readS2(bytecodes, i)].newBlock, |
| currentBlock); |
| break; |
| } |
| |
| case RET : { |
| uint8 local = readU1(bytecodes, i); |
| Value* _val = new LoadInst(objectLocals[local], "", currentBlock); |
| Value* val = new PtrToIntInst(_val, Type::Int32Ty, "", currentBlock); |
| SwitchInst* inst = new SwitchInst(val, jsrs[0], jsrs.size(), |
| currentBlock); |
| |
| uint32 index = 0; |
| mvm::jit::protectConstants();//->lock(); |
| for (std::vector<BasicBlock*>::iterator i = jsrs.begin(), |
| e = jsrs.end(); i!= e; ++i, ++index) { |
| inst->addCase(ConstantInt::get(Type::Int32Ty, index), *i); |
| } |
| mvm::jit::unprotectConstants();//->unlock(); |
| |
| break; |
| } |
| |
| case TABLESWITCH : { |
| uint32 tmp = i; |
| uint32 reste = (i + 1) & 3; |
| uint32 filled = reste ? (4 - reste) : 0; |
| i += filled; |
| BasicBlock* def = opcodeInfos[tmp + readU4(bytecodes, i)].newBlock; |
| |
| uint32 low = readU4(bytecodes, i); |
| uint32 high = readU4(bytecodes, i) + 1; |
| |
| Value* index = pop(); |
| |
| const llvm::Type* type = index->getType(); |
| mvm::jit::protectConstants();//->lock(); |
| for (uint32 cur = low; cur < high; ++cur) { |
| Value* cmp = new ICmpInst(ICmpInst::ICMP_EQ, |
| ConstantInt::get(type, cur), index, |
| "", currentBlock); |
| BasicBlock* falseBlock = createBasicBlock("continue tableswitch"); |
| branch(cmp, opcodeInfos[tmp + readU4(bytecodes, i)].newBlock, falseBlock, currentBlock); |
| currentBlock = falseBlock; |
| } |
| mvm::jit::unprotectConstants();//->unlock(); |
| |
| |
| //Value* cmp = new ICmpInst(ICmpInst::ICMP_SLT, index, |
| // ConstantInt::get(Type::Int32Ty, low), "", |
| // currentBlock); |
| branch(def, currentBlock); |
| i = tmp + 12 + filled + ((high - low) << 2); |
| |
| break; |
| } |
| |
| case LOOKUPSWITCH : { |
| uint32 tmp = i; |
| uint32 filled = (3 - i) & 3; |
| i += filled; |
| BasicBlock* def = opcodeInfos[tmp + readU4(bytecodes, i)].newBlock; |
| uint32 nbs = readU4(bytecodes, i); |
| |
| const AssessorDesc* ass = topFunc(); |
| Value* key = pop(); |
| if (ass == AssessorDesc::dShort || ass == AssessorDesc::dByte) { |
| key = new SExtInst(key, Type::Int32Ty, "", currentBlock); |
| } else if (ass == AssessorDesc::dChar || ass == AssessorDesc::dBool) { |
| key = new ZExtInst(key, Type::Int32Ty, "", currentBlock); |
| } |
| mvm::jit::protectConstants();//->lock(); |
| for (uint32 cur = 0; cur < nbs; ++cur) { |
| Value* val = ConstantInt::get(Type::Int32Ty, readU4(bytecodes, i)); |
| Value* cmp = new ICmpInst(ICmpInst::ICMP_EQ, val, key, "", currentBlock); |
| BasicBlock* falseBlock = createBasicBlock("continue lookupswitch"); |
| branch(cmp, opcodeInfos[tmp + readU4(bytecodes, i)].newBlock, falseBlock, currentBlock); |
| currentBlock = falseBlock; |
| } |
| mvm::jit::unprotectConstants();//->unlock(); |
| branch(def, currentBlock); |
| i = tmp + 8 + filled + (nbs << 3); |
| break; |
| } |
| case IRETURN : { |
| const AssessorDesc* ass = topFunc(); |
| Value* val = pop(); |
| assert(val->getType()->isInteger()); |
| convertValue(val, returnType, currentBlock, |
| ass == AssessorDesc::dChar || ass == AssessorDesc::dBool); |
| endNode->addIncoming(val, currentBlock); |
| new BranchInst(endBlock, currentBlock); |
| break; |
| } |
| case LRETURN : |
| pop(); // remove the 0 on the stack |
| endNode->addIncoming(pop(), currentBlock); |
| new BranchInst(endBlock, currentBlock); |
| break; |
| |
| case FRETURN : |
| endNode->addIncoming(pop(), currentBlock); |
| new BranchInst(endBlock, currentBlock); |
| break; |
| |
| case DRETURN : |
| pop(); // remove the 0 on the stack |
| endNode->addIncoming(pop(), currentBlock); |
| new BranchInst(endBlock, currentBlock); |
| break; |
| |
| case ARETURN : |
| endNode->addIncoming(pop(), currentBlock); |
| new BranchInst(endBlock, currentBlock); |
| break; |
| |
| case RETURN : |
| new BranchInst(endBlock, currentBlock); |
| break; |
| |
| case GETSTATIC : { |
| uint16 index = readU2(bytecodes, i); |
| getStaticField(index); |
| break; |
| } |
| |
| case PUTSTATIC : { |
| uint16 index = readU2(bytecodes, i); |
| setStaticField(index); |
| break; |
| } |
| |
| case GETFIELD : { |
| uint16 index = readU2(bytecodes, i); |
| getVirtualField(index); |
| break; |
| } |
| |
| case PUTFIELD : { |
| uint16 index = readU2(bytecodes, i); |
| setVirtualField(index); |
| break; |
| } |
| |
| case INVOKEVIRTUAL : { |
| uint16 index = readU2(bytecodes, i); |
| JavaCtpInfo* ctpInfo = compilingClass->ctpInfo; |
| CommonClass* cl = 0; |
| JavaMethod* meth = 0; |
| ctpInfo->infoOfMethod(index, ACC_VIRTUAL, cl, meth); |
| if ((cl && isFinal(cl->access)) || (meth && isFinal(meth->access))) |
| invokeSpecial(index); |
| else |
| invokeInterfaceOrVirtual(index); |
| break; |
| } |
| |
| case INVOKESPECIAL : { |
| uint16 index = readU2(bytecodes, i); |
| invokeSpecial(index); |
| break; |
| } |
| |
| case INVOKESTATIC : { |
| uint16 index = readU2(bytecodes, i); |
| invokeStatic(index); |
| break; |
| } |
| |
| case INVOKEINTERFACE : { |
| uint16 index = readU2(bytecodes, i); |
| invokeInterfaceOrVirtual(index); |
| i += 2; |
| break; |
| } |
| |
| case NEW : { |
| uint16 index = readU2(bytecodes, i); |
| invokeNew(index); |
| break; |
| } |
| |
| case NEWARRAY : { |
| |
| Jnjvm* vm = compilingClass->isolate; |
| uint8 id = bytecodes[++i]; |
| ClassArray* cl = 0; |
| AssessorDesc* ass = 0; |
| Function* ctr = 0; |
| AssessorDesc::arrayType(vm, compilingClass->classLoader, id, cl, ass, |
| ctr); |
| |
| llvm::Value* valCl = new LoadInst(cl->llvmVar(vm->module), "", currentBlock); |
| llvm::Value* arg1 = popAsInt(); |
| |
| push(invoke(ctr, arg1, valCl, "", currentBlock), AssessorDesc::dRef); |
| break; |
| } |
| |
| case ANEWARRAY : { |
| |
| Jnjvm* vm = compilingClass->isolate; |
| uint16 index = readU2(bytecodes, i); |
| const UTF8* className = |
| compilingClass->ctpInfo->resolveClassName(index); |
| |
| const UTF8* arrayName = |
| AssessorDesc::constructArrayName(vm, 0, 1, className); |
| |
| ClassArray* dcl = |
| vm->constructArray(arrayName, compilingClass->classLoader); |
| |
| |
| llvm::Value* valCl = new LoadInst(dcl->llvmVar(vm->module), "", currentBlock); |
| llvm::Value* arg1 = popAsInt(); |
| |
| push(invoke(ObjectAconsLLVM, arg1, valCl, "", currentBlock), AssessorDesc::dRef); |
| break; |
| } |
| |
| case ARRAYLENGTH : { |
| Value* val = pop(); |
| JITVerifyNull(val); |
| push(arraySize(val), AssessorDesc::dInt); |
| break; |
| } |
| |
| case ATHROW : { |
| llvm::Value* arg = pop(); |
| std::vector<Value*> args; |
| args.push_back(arg); |
| if (currentExceptionBlock != endExceptionBlock) { |
| new InvokeInst(throwExceptionLLVM, unifiedUnreachable, currentExceptionBlock, args.begin(), args.end(), "", currentBlock); |
| } else { |
| new CallInst(throwExceptionLLVM, args.begin(), args.end(), "", currentBlock); |
| new UnreachableInst(currentBlock); |
| } |
| break; |
| } |
| |
| case CHECKCAST : { |
| uint16 index = readU2(bytecodes, i); |
| CommonClass* dcl = |
| compilingClass->ctpInfo->getMethodClassIfLoaded(index); |
| |
| Value* obj = top(); |
| |
| Value* cmp = new ICmpInst(ICmpInst::ICMP_EQ, obj, |
| constantJavaObjectNull, |
| "", currentBlock); |
| |
| BasicBlock* ifTrue = createBasicBlock("null checkcast"); |
| BasicBlock* ifFalse = createBasicBlock("non null checkcast"); |
| |
| new BranchInst(ifTrue, ifFalse, cmp, currentBlock); |
| currentBlock = ifFalse; |
| Value* clVar = 0; |
| if (dcl && dcl->isReady()) { |
| clVar = new LoadInst(dcl->llvmVar(compilingClass->isolate->module), "", ifFalse); |
| } else { |
| clVar = getInitializedClass(index); |
| } |
| std::vector<Value*> args; |
| args.push_back(obj); |
| args.push_back(clVar); |
| Value* call = new CallInst(instanceOfLLVM, args.begin(), args.end(), |
| "", currentBlock); |
| |
| cmp = new ICmpInst(ICmpInst::ICMP_EQ, call, |
| mvm::jit::constantZero, "", currentBlock); |
| |
| BasicBlock* ex = createBasicBlock("false checkcast"); |
| new BranchInst(ex, ifTrue, cmp, currentBlock); |
| |
| std::vector<Value*> exArgs; |
| exArgs.push_back(obj); |
| exArgs.push_back(clVar); |
| if (currentExceptionBlock != endExceptionBlock) { |
| new InvokeInst(classCastExceptionLLVM, unifiedUnreachable, currentExceptionBlock, exArgs.begin(), exArgs.end(), "", ex); |
| } else { |
| new CallInst(classCastExceptionLLVM, exArgs.begin(), exArgs.end(), "", ex); |
| new UnreachableInst(ex); |
| } |
| |
| currentBlock = ifTrue; |
| break; |
| } |
| |
| case INSTANCEOF : { |
| uint16 index = readU2(bytecodes, i); |
| CommonClass* dcl = |
| compilingClass->ctpInfo->getMethodClassIfLoaded(index); |
| |
| Value* clVar = 0; |
| if (dcl && dcl->isReady()) { |
| clVar = new LoadInst(dcl->llvmVar(compilingClass->isolate->module), "", currentBlock); |
| } else { |
| clVar = getInitializedClass(index); |
| } |
| std::vector<Value*> args; |
| args.push_back(pop()); |
| args.push_back(clVar); |
| push(new CallInst(instanceOfLLVM, args.begin(), args.end(), "", currentBlock), AssessorDesc::dInt); |
| break; |
| } |
| |
| case MONITORENTER : { |
| Value* obj = pop(); |
| invoke(aquireObjectLLVM, obj, "", currentBlock); |
| break; |
| } |
| |
| case MONITOREXIT : { |
| Value* obj = pop(); |
| invoke(releaseObjectLLVM, obj, "", currentBlock); |
| break; |
| } |
| |
| case MULTIANEWARRAY : { |
| Jnjvm* vm = compilingClass->isolate; |
| uint16 index = readU2(bytecodes, i); |
| uint8 dim = readU1(bytecodes, i); |
| |
| const UTF8* className = |
| compilingClass->ctpInfo->resolveClassName(index); |
| |
| ClassArray* dcl = |
| vm->constructArray(className, compilingClass->classLoader); |
| |
| compilingClass->ctpInfo->loadClass(index); |
| |
| Value* valCl = new LoadInst(dcl->llvmVar(vm->module), "", currentBlock); |
| Value* args[dim + 2]; |
| args[0] = valCl; |
| mvm::jit::protectConstants();//->lock(); |
| args[1] = ConstantInt::get(Type::Int32Ty, dim); |
| mvm::jit::unprotectConstants();//->unlock(); |
| |
| for (int cur = dim + 1; cur >= 2; --cur) |
| args[cur] = pop(); |
| |
| std::vector<Value*> Args; |
| for (sint32 v = 0; v < dim + 2; ++v) { |
| Args.push_back(args[v]); |
| } |
| push(invoke(multiCallNewLLVM, Args, "", currentBlock), AssessorDesc::dRef); |
| break; |
| } |
| |
| case WIDE : |
| wide = true; |
| break; |
| |
| case IFNULL : { |
| uint32 tmp = i; |
| const AssessorDesc* ass = topFunc(); |
| llvm::Value* nil = ass->llvmNullConstant; |
| llvm::Value* val = pop(); |
| llvm::Value* test = new ICmpInst(ICmpInst::ICMP_EQ, val, nil, "", |
| currentBlock); |
| BasicBlock* ifFalse = createBasicBlock("true IFNULL"); |
| BasicBlock* ifTrue = opcodeInfos[readS2(bytecodes, i) + tmp].newBlock; |
| branch(test, ifTrue, ifFalse, currentBlock); |
| currentBlock = ifFalse; |
| break; |
| } |
| |
| case IFNONNULL : { |
| uint32 tmp = i; |
| const AssessorDesc* ass = topFunc(); |
| llvm::Value* nil = ass->llvmNullConstant; |
| llvm::Value* val = pop(); |
| llvm::Value* test = new ICmpInst(ICmpInst::ICMP_NE, val, nil, "", |
| currentBlock); |
| BasicBlock* ifFalse = createBasicBlock("false IFNONNULL"); |
| BasicBlock* ifTrue = opcodeInfos[readS2(bytecodes, i) + tmp].newBlock; |
| branch(test, ifTrue, ifFalse, currentBlock); |
| currentBlock = ifFalse; |
| break; |
| } |
| |
| default : |
| JavaThread::get()->isolate->unknownError("unknown bytecode"); |
| |
| } |
| } |
| } |
| |
| void JavaJIT::exploreOpcodes(uint8* bytecodes, uint32 codeLength) { |
| for(uint32 i = 0; i < codeLength; ++i) { |
| |
| PRINT_DEBUG(JNJVM_COMPILE, 1, COLOR_NORMAL, "\t[at %5d] %-5d ", i, |
| bytecodes[i]); |
| PRINT_DEBUG(JNJVM_COMPILE, 1, LIGHT_BLUE, "exploring "); |
| PRINT_DEBUG(JNJVM_COMPILE, 1, LIGHT_CYAN, OpcodeNames[bytecodes[i]]); |
| PRINT_DEBUG(JNJVM_COMPILE, 1, LIGHT_BLUE, "\n"); |
| |
| switch (bytecodes[i]) { |
| |
| case ACONST_NULL : |
| case ICONST_M1 : |
| case ICONST_0 : |
| case ICONST_1 : |
| case ICONST_2 : |
| case ICONST_3 : |
| case ICONST_4 : |
| case ICONST_5 : |
| case LCONST_0 : |
| case LCONST_1 : |
| case FCONST_0 : |
| case FCONST_1 : |
| case FCONST_2 : |
| case DCONST_0 : |
| case DCONST_1 : break; |
| |
| case BIPUSH : ++i; break; |
| |
| case SIPUSH : i += 2; break; |
| |
| case LDC : ++i; break; |
| |
| case LDC_W : |
| case LDC2_W : i += 2; break; |
| |
| case ILOAD : |
| case LLOAD : |
| case FLOAD : |
| case DLOAD : |
| case ALOAD : |
| i += WCALC(1); |
| break; |
| |
| case ILOAD_0 : |
| case ILOAD_1 : |
| case ILOAD_2 : |
| case ILOAD_3 : |
| case LLOAD_0 : |
| case LLOAD_1 : |
| case LLOAD_2 : |
| case LLOAD_3 : |
| case FLOAD_0 : |
| case FLOAD_1 : |
| case FLOAD_2 : |
| case FLOAD_3 : |
| case DLOAD_0 : |
| case DLOAD_1 : |
| case DLOAD_2 : |
| case DLOAD_3 : |
| case ALOAD_0 : |
| case ALOAD_1 : |
| case ALOAD_2 : |
| case ALOAD_3 : |
| case IALOAD : |
| case LALOAD : |
| case FALOAD : |
| case DALOAD : |
| case AALOAD : |
| case BALOAD : |
| case CALOAD : |
| case SALOAD : break; |
| |
| case ISTORE : |
| case LSTORE : |
| case FSTORE : |
| case DSTORE : |
| case ASTORE : |
| i += WCALC(1); |
| break; |
| |
| case ISTORE_0 : |
| case ISTORE_1 : |
| case ISTORE_2 : |
| case ISTORE_3 : |
| case LSTORE_0 : |
| case LSTORE_1 : |
| case LSTORE_2 : |
| case LSTORE_3 : |
| case FSTORE_0 : |
| case FSTORE_1 : |
| case FSTORE_2 : |
| case FSTORE_3 : |
| case DSTORE_0 : |
| case DSTORE_1 : |
| case DSTORE_2 : |
| case DSTORE_3 : |
| case ASTORE_0 : |
| case ASTORE_1 : |
| case ASTORE_2 : |
| case ASTORE_3 : |
| case IASTORE : |
| case LASTORE : |
| case FASTORE : |
| case DASTORE : |
| case AASTORE : |
| case BASTORE : |
| case CASTORE : |
| case SASTORE : |
| case POP : |
| case POP2 : |
| case DUP : |
| case DUP_X1 : |
| case DUP_X2 : |
| case DUP2 : |
| case DUP2_X1 : |
| case DUP2_X2 : |
| case SWAP : |
| case IADD : |
| case LADD : |
| case FADD : |
| case DADD : |
| case ISUB : |
| case LSUB : |
| case FSUB : |
| case DSUB : |
| case IMUL : |
| case LMUL : |
| case FMUL : |
| case DMUL : |
| case IDIV : |
| case LDIV : |
| case FDIV : |
| case DDIV : |
| case IREM : |
| case LREM : |
| case FREM : |
| case DREM : |
| case INEG : |
| case LNEG : |
| case FNEG : |
| case DNEG : |
| case ISHL : |
| case LSHL : |
| case ISHR : |
| case LSHR : |
| case IUSHR : |
| case LUSHR : |
| case IAND : |
| case LAND : |
| case IOR : |
| case LOR : |
| case IXOR : |
| case LXOR : break; |
| |
| case IINC : |
| i += WCALC(2); |
| break; |
| |
| case I2L : |
| case I2F : |
| case I2D : |
| case L2I : |
| case L2F : |
| case L2D : |
| case F2I : |
| case F2L : |
| case F2D : |
| case D2I : |
| case D2L : |
| case D2F : |
| case I2B : |
| case I2C : |
| case I2S : |
| case LCMP : |
| case FCMPL : |
| case FCMPG : |
| case DCMPL : |
| case DCMPG : break; |
| |
| case IFEQ : |
| case IFNE : |
| case IFLT : |
| case IFGE : |
| case IFGT : |
| case IFLE : |
| case IF_ICMPEQ : |
| case IF_ICMPNE : |
| case IF_ICMPLT : |
| case IF_ICMPGE : |
| case IF_ICMPGT : |
| case IF_ICMPLE : |
| case IF_ACMPEQ : |
| case IF_ACMPNE : |
| case GOTO : { |
| uint32 tmp = i; |
| uint16 index = tmp + readU2(bytecodes, i); |
| if (!(opcodeInfos[index].newBlock)) |
| opcodeInfos[index].newBlock = createBasicBlock("GOTO or IF*"); |
| break; |
| } |
| |
| case JSR : { |
| uint32 tmp = i; |
| uint16 index = tmp + readU2(bytecodes, i); |
| if (!(opcodeInfos[index].newBlock)) { |
| BasicBlock* block = createBasicBlock("JSR"); |
| opcodeInfos[index].newBlock = block; |
| } |
| if (!(opcodeInfos[tmp + 3].newBlock)) { |
| BasicBlock* block = createBasicBlock("JSR2"); |
| jsrs.push_back(block); |
| opcodeInfos[tmp + 3].newBlock = block; |
| } else { |
| jsrs.push_back(opcodeInfos[tmp + 3].newBlock); |
| } |
| opcodeInfos[index].reqSuppl = true; |
| break; |
| } |
| |
| case RET : ++i; break; |
| |
| case TABLESWITCH : { |
| uint32 tmp = i; |
| uint32 reste = (i + 1) & 3; |
| uint32 filled = reste ? (4 - reste) : 0; |
| i += filled; |
| uint32 index = tmp + readU4(bytecodes, i); |
| if (!(opcodeInfos[index].newBlock)) { |
| BasicBlock* block = createBasicBlock("tableswitch"); |
| opcodeInfos[index].newBlock = block; |
| } |
| uint32 low = readU4(bytecodes, i); |
| uint32 high = readU4(bytecodes, i) + 1; |
| uint32 depl = high - low; |
| for (uint32 cur = 0; cur < depl; ++cur) { |
| uint32 index2 = tmp + readU4(bytecodes, i); |
| if (!(opcodeInfos[index2].newBlock)) { |
| BasicBlock* block = createBasicBlock("tableswitch"); |
| opcodeInfos[index2].newBlock = block; |
| } |
| } |
| i = tmp + 12 + filled + (depl << 2); |
| break; |
| } |
| |
| case LOOKUPSWITCH : { |
| uint32 tmp = i; |
| uint32 filled = (3 - i) & 3; |
| i += filled; |
| uint32 index = tmp + readU4(bytecodes, i); |
| if (!(opcodeInfos[index].newBlock)) { |
| BasicBlock* block = createBasicBlock("tableswitch"); |
| opcodeInfos[index].newBlock = block; |
| } |
| uint32 nbs = readU4(bytecodes, i); |
| for (uint32 cur = 0; cur < nbs; ++cur) { |
| i += 4; |
| uint32 index2 = tmp + readU4(bytecodes, i); |
| if (!(opcodeInfos[index2].newBlock)) { |
| BasicBlock* block = createBasicBlock("tableswitch"); |
| opcodeInfos[index2].newBlock = block; |
| } |
| } |
| |
| i = tmp + 8 + filled + (nbs << 3); |
| break; |
| } |
| |
| case IRETURN : |
| case LRETURN : |
| case FRETURN : |
| case DRETURN : |
| case ARETURN : |
| case RETURN : break; |
| |
| case GETSTATIC : |
| case PUTSTATIC : |
| case GETFIELD : |
| case PUTFIELD : |
| case INVOKEVIRTUAL : |
| case INVOKESPECIAL : |
| case INVOKESTATIC : |
| i += 2; |
| break; |
| |
| case INVOKEINTERFACE : |
| i += 4; |
| break; |
| |
| case NEW : |
| i += 2; |
| break; |
| |
| case NEWARRAY : |
| ++i; |
| break; |
| |
| case ANEWARRAY : |
| i += 2; |
| break; |
| |
| case ARRAYLENGTH : |
| case ATHROW : break; |
| |
| case CHECKCAST : |
| i += 2; |
| break; |
| |
| case INSTANCEOF : |
| i += 2; |
| break; |
| |
| case MONITORENTER : |
| break; |
| |
| case MONITOREXIT : |
| break; |
| |
| case MULTIANEWARRAY : |
| i += 3; |
| break; |
| |
| case WIDE : |
| wide = true; |
| break; |
| |
| case IFNULL : |
| case IFNONNULL : { |
| uint32 tmp = i; |
| uint16 index = tmp + readU2(bytecodes, i); |
| if (!(opcodeInfos[index].newBlock)) |
| opcodeInfos[index].newBlock = createBasicBlock("true IF*NULL"); |
| break; |
| } |
| |
| |
| default : |
| JavaThread::get()->isolate->unknownError("unknown bytecode"); |
| } |
| } |
| } |