[vmkit-commits] [vmkit] r140004 - in /vmkit/trunk/lib/J3/Compiler: JavaAOTCompiler.cpp JavaJIT.cpp JavaJIT.h JavaJITOpcodes.cpp
Nicolas Geoffray
nicolas.geoffray at lip6.fr
Sun Sep 18 12:11:13 PDT 2011
Author: geoffray
Date: Sun Sep 18 14:11:13 2011
New Revision: 140004
URL: http://llvm.org/viewvc/llvm-project?rev=140004&view=rev
Log:
Add an inlining framework. Currently inlines simple methods that don't go into runtime and don't call non-inlineable Java methods.
Modified:
vmkit/trunk/lib/J3/Compiler/JavaAOTCompiler.cpp
vmkit/trunk/lib/J3/Compiler/JavaJIT.cpp
vmkit/trunk/lib/J3/Compiler/JavaJIT.h
vmkit/trunk/lib/J3/Compiler/JavaJITOpcodes.cpp
Modified: vmkit/trunk/lib/J3/Compiler/JavaAOTCompiler.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/J3/Compiler/JavaAOTCompiler.cpp?rev=140004&r1=140003&r2=140004&view=diff
==============================================================================
--- vmkit/trunk/lib/J3/Compiler/JavaAOTCompiler.cpp (original)
+++ vmkit/trunk/lib/J3/Compiler/JavaAOTCompiler.cpp Sun Sep 18 14:11:13 2011
@@ -2178,6 +2178,8 @@
Function* F = M->getMethod(&cl->virtualMethods[i]);
M->setMethod(F, ptr, F->getName().data());
cl->virtualMethods[i].compiledPtr();
+ // Set native so that we don't try to inline it.
+ cl->virtualMethods[i].setNative();
}
}
@@ -2186,6 +2188,8 @@
Function* F = M->getMethod(&cl->staticMethods[i]);
M->setMethod(F, ptr, F->getName().data());
cl->staticMethods[i].compiledPtr();
+ // Set native so that we don't try to inline it.
+ cl->staticMethods[i].setNative();
}
}
}
@@ -2372,7 +2376,7 @@
gv->setInitializer(CreateConstantFromVT(VT));
}
- // Finally add used stubs to the image.
+ // Add used stubs to the image.
for (SignMap::iterator i = loader->javaSignatures->map.begin(),
e = loader->javaSignatures->map.end(); i != e; i++) {
Signdef* signature = i->second;
@@ -2400,7 +2404,7 @@
}
}
- // Finally emit the stub for the main signature.
+ // Emit the stub for the main signature.
Signdef* mainSignature =
loader->constructSign(loader->asciizConstructUTF8("([Ljava/lang/String;)V"));
getSignatureInfo(mainSignature)->getStaticBuf();
@@ -2410,6 +2414,13 @@
// Emit the UTF8 map.
CreateConstantFromUTF8Map(loader->hashUTF8->map);
+
+ // Check that we have compiled everything.
+ for (Module::iterator I = TheModule->begin(), E = TheModule->end();
+ I != E;
+ I++) {
+ assert(!I->hasExternalWeakLinkage());
+ }
}
void JavaAOTCompiler::generateClassBytes(JnjvmBootstrapLoader* loader) {
Modified: vmkit/trunk/lib/J3/Compiler/JavaJIT.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/J3/Compiler/JavaJIT.cpp?rev=140004&r1=140003&r2=140004&view=diff
==============================================================================
--- vmkit/trunk/lib/J3/Compiler/JavaJIT.cpp (original)
+++ vmkit/trunk/lib/J3/Compiler/JavaJIT.cpp Sun Sep 18 14:11:13 2011
@@ -44,7 +44,7 @@
using namespace j3;
using namespace llvm;
-static bool needsInitialisationCheck(Class* cl, Class* compilingClass) {
+bool JavaJIT::needsInitialisationCheck(Class* cl) {
if (cl->isReadyForCompilation() ||
(!cl->isInterface() && compilingClass->isAssignableFrom(cl))) {
return false;
@@ -61,11 +61,29 @@
}
bool JavaJIT::canBeInlined(JavaMethod* meth) {
- JnjvmClassLoader* loader = meth->classDef->classLoader;
- return (meth->canBeInlined &&
- meth != compilingMethod && inlineMethods[meth] == 0 &&
- (loader == compilingClass->classLoader ||
- loader == compilingClass->classLoader->bootstrapLoader));
+ if (inlineMethods[meth]) return false;
+ if (isSynchro(meth->access)) return false;
+ if (isNative(meth->access)) return false;
+
+ Attribut* codeAtt = meth->lookupAttribut(Attribut::codeAttribut);
+ if (codeAtt == NULL) return false;
+
+ Reader reader(codeAtt, meth->classDef->bytes);
+ /* uint16 maxStack = */ reader.readU2();
+ /* uint16 maxLocals = */ reader.readU2();
+ uint32 codeLen = reader.readU4();
+ uint32 start = reader.cursor;
+ reader.seek(codeLen, Reader::SeekCur);
+ uint16 nbHandlers = reader.readU2();
+ if (nbHandlers != 0) return false;
+ reader.cursor = start;
+
+ JavaJIT jit(TheCompiler, meth, llvmFunction);
+ jit.inlineMethods = inlineMethods;
+ jit.inlineMethods[meth] = true;
+ if (!jit.analyzeForInlining(reader, codeLen)) return false;
+ jit.inlineMethods[meth] = false;
+ return true;
}
void JavaJIT::invokeVirtual(uint16 index) {
@@ -119,7 +137,11 @@
llvm::Type* retType = virtualType->getReturnType();
bool needsInit = false;
- if (canBeDirect && meth && !TheCompiler->needsCallback(meth, &needsInit)) {
+ if (canBeDirect && canBeInlined(meth)) {
+ makeArgs(it, index, args, signature->nbArguments + 1);
+ JITVerifyNull(args[0]);
+ val = invokeInline(meth, args);
+ } else if (canBeDirect && !TheCompiler->needsCallback(meth, &needsInit)) {
makeArgs(it, index, args, signature->nbArguments + 1);
JITVerifyNull(args[0]);
val = invoke(TheCompiler->getMethod(meth), args, "", currentBlock);
@@ -707,35 +729,18 @@
Instruction* JavaJIT::inlineCompile(BasicBlock*& curBB,
BasicBlock* endExBlock,
std::vector<Value*>& args) {
- DbgSubprogram = TheCompiler->GetDbgSubprogram(compilingMethod);
-
- PRINT_DEBUG(JNJVM_COMPILE, 1, COLOR_NORMAL, "inline compile %s.%s\n",
- UTF8Buffer(compilingClass->name).cString(),
- UTF8Buffer(compilingMethod->name).cString());
-
Attribut* codeAtt = compilingMethod->lookupAttribut(Attribut::codeAttribut);
-
- if (!codeAtt) {
- fprintf(stderr, "I haven't verified your class file and it's malformed:"
- " no code attribut found for %s.%s!\n",
- UTF8Buffer(compilingClass->name).cString(),
- UTF8Buffer(compilingMethod->name).cString());
- abort();
- }
-
Reader reader(codeAtt, compilingClass->bytes);
uint16 maxStack = reader.readU2();
uint16 maxLocals = reader.readU2();
uint32 codeLen = reader.readU4();
- uint32 start = reader.cursor;
-
+ uint32 start = reader.cursor;
reader.seek(codeLen, Reader::SeekCur);
- LLVMMethodInfo* LMI = TheCompiler->getMethodInfo(compilingMethod);
- assert(LMI);
- Function* func = LMI->getMethod();
+ LLVMAssessorInfo& LAI = TheCompiler->getTypedefInfo(
+ compilingMethod->getSignature()->getReturnType());
+ Type* returnType = LAI.llvmType;
- Type* returnType = func->getReturnType();
endBlock = createBasicBlock("end");
currentBlock = curBB;
@@ -888,7 +893,6 @@
delete[] opcodeInfos;
return endNode;
-
}
llvm::Function* JavaJIT::javaCompile() {
@@ -1157,11 +1161,7 @@
PRINT_DEBUG(JNJVM_COMPILE, 1, COLOR_NORMAL, "--> end compiling %s.%s\n",
UTF8Buffer(compilingClass->name).cString(),
UTF8Buffer(compilingMethod->name).cString());
-
- if (codeLen < 5 && !callsStackWalker && !TheCompiler->isStaticCompiling()) {
- compilingMethod->canBeInlined = false;
- }
-
+
Attribut* annotationsAtt =
compilingMethod->lookupAttribut(Attribut::annotationsAttribut);
@@ -1486,6 +1486,17 @@
jit.inlineMethods = inlineMethods;
jit.inlineMethods[meth] = true;
jit.inlining = true;
+ jit.DbgSubprogram = DbgSubprogram;
+#if DEBUG
+ static int inlineNb = 0;
+ fprintf(stderr, "inline compile %d %s.%s%s from %s.%s\n", inlineNb++,
+ UTF8Buffer(meth->classDef->name).cString(),
+ UTF8Buffer(meth->name).cString(),
+ UTF8Buffer(meth->getSignature()->keyName).cString(),
+ UTF8Buffer(compilingClass->name).cString(),
+ UTF8Buffer(compilingMethod->name).cString());
+#endif
+
Instruction* ret = jit.inlineCompile(currentBlock,
currentExceptionBlock, args);
inlineMethods[meth] = false;
@@ -1577,7 +1588,7 @@
uint32 clIndex = ctpInfo->getClassIndexFromMethod(index);
UserClass* cl = 0;
Value* Cl = getResolvedClass(clIndex, true, true, &cl);
- if (!meth || (cl && needsInitialisationCheck(cl, compilingClass))) {
+ if (!meth || (cl && needsInitialisationCheck(cl))) {
CallInst::Create(intrinsics->ForceInitialisationCheckFunction, Cl, "",
currentBlock);
}
@@ -1701,7 +1712,7 @@
if (cl && cl->isResolved()) {
if (alreadyResolved) (*alreadyResolved) = cl;
node = TheCompiler->getNativeClass(cl);
- needsInit = needsInitialisationCheck(cl, compilingClass);
+ needsInit = needsInitialisationCheck(cl);
} else {
node = getConstantPoolAt(index, intrinsics->ClassLookupFunction,
intrinsics->JavaClassType, 0, doThrow);
@@ -1732,7 +1743,7 @@
LLVMClassInfo* LCI = TheCompiler->getClassInfo(cl);
Size = LCI->getVirtualSize();
- bool needsCheck = needsInitialisationCheck(cl, compilingClass);
+ bool needsCheck = needsInitialisationCheck(cl);
if (needsCheck) {
Cl = invoke(intrinsics->ForceInitialisationCheckFunction, Cl, "",
currentBlock);
@@ -1773,8 +1784,7 @@
if (stat) {
type = LCI->getStaticType();
Value* Cl = TheCompiler->getNativeClass(field->classDef);
- bool needsCheck = needsInitialisationCheck(field->classDef,
- compilingClass);
+ bool needsCheck = needsInitialisationCheck(field->classDef);
if (needsCheck) {
Cl = invoke(intrinsics->InitialisationCheckFunction, Cl, "",
currentBlock);
@@ -2434,6 +2444,7 @@
Instruction* JavaJIT::invoke(Value *F, std::vector<llvm::Value*>& args,
const char* Name,
BasicBlock *InsertAtEnd) {
+ assert(!inlining);
Instruction* res = CallInst::Create(F, args, Name, InsertAtEnd);
DebugLoc DL = CreateLocation();
@@ -2487,6 +2498,7 @@
Instruction* JavaJIT::invoke(Value *F, Value* arg1, const char* Name,
BasicBlock *InsertAtEnd) {
+ assert(!inlining);
Instruction* res = CallInst::Create(F, arg1, Name, InsertAtEnd);
DebugLoc DL = CreateLocation();
@@ -2532,6 +2544,7 @@
Instruction* JavaJIT::invoke(Value *F, Value* arg1, Value* arg2,
const char* Name, BasicBlock *InsertAtEnd) {
+ assert(!inlining);
Value* args[2] = { arg1, arg2 };
@@ -2579,6 +2592,7 @@
Instruction* JavaJIT::invoke(Value *F, const char* Name,
BasicBlock *InsertAtEnd) {
+ assert(!inlining);
Instruction* res = llvm::CallInst::Create(F, Name, InsertAtEnd);
DebugLoc DL = CreateLocation();
res->setDebugLoc(DL);
Modified: vmkit/trunk/lib/J3/Compiler/JavaJIT.h
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/J3/Compiler/JavaJIT.h?rev=140004&r1=140003&r2=140004&view=diff
==============================================================================
--- vmkit/trunk/lib/J3/Compiler/JavaJIT.h (original)
+++ vmkit/trunk/lib/J3/Compiler/JavaJIT.h Sun Sep 18 14:11:13 2011
@@ -157,7 +157,8 @@
/// getJavaExceptionPtr - Emit code to get a pointer to the Java pending exception
llvm::Value* getJavaExceptionPtr(llvm::Value* javaThreadPtr);
-
+
+ bool needsInitialisationCheck(Class* cl);
//===------------------------- Debugging support --------------------------===//
@@ -193,7 +194,9 @@
/// then this method can not be inlined.
bool callsStackWalker;
-
+ bool analyzeForInlining(Reader& reader, uint32_t codeLength);
+ bool canInlineLoadConstant(uint16 index);
+
//===------------------------- Bytecode parsing ---------------------------===//
/// compileOpcodes - Parse the bytecode and create LLVM instructions.
Modified: vmkit/trunk/lib/J3/Compiler/JavaJITOpcodes.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/J3/Compiler/JavaJITOpcodes.cpp?rev=140004&r1=140003&r2=140004&view=diff
==============================================================================
--- vmkit/trunk/lib/J3/Compiler/JavaJITOpcodes.cpp (original)
+++ vmkit/trunk/lib/J3/Compiler/JavaJITOpcodes.cpp Sun Sep 18 14:11:13 2011
@@ -36,9 +36,7 @@
#include "j3/J3Intrinsics.h"
-#if DEBUG > 0 && (JNJVM_COMPILE > 0 || JNJVM_EXECUTE > 0)
#include "j3/OpcodeNames.def"
-#endif
using namespace j3;
using namespace llvm;
@@ -2728,3 +2726,679 @@
}
}
}
+
+bool JavaJIT::canInlineLoadConstant(uint16 index) {
+ JavaConstantPool* ctpInfo = compilingClass->ctpInfo;
+ uint8 type = ctpInfo->typeAt(index);
+ if (type == JavaConstantPool::ConstantString
+ || type == JavaConstantPool::ConstantClass) {
+ return false;
+ } else {
+ return true;
+ }
+}
+
+static uint8 getReceiver(const std::vector<uint8>& stack, Signdef* signature) {
+ uint32_t index = stack.size() - 1;
+ Typedef* const* arguments = signature->getArgumentsType();
+ for (uint32 i = 0; i < signature->nbArguments; i++) {
+ index--;
+ if (arguments[i]->isDouble() || arguments[i]->isLong()) {
+ index--;
+ }
+ }
+ return stack[index];
+}
+
+static void updateStack(std::vector<uint8>& stack, Signdef* signature, uint8 bytecode) {
+ Typedef* const* arguments = signature->getArgumentsType();
+ if (bytecode != INVOKESTATIC) {
+ stack.pop_back();
+ }
+ for (uint32 i = 0; i < signature->nbArguments; i++) {
+ stack.pop_back();
+ if (arguments[i]->isDouble() || arguments[i]->isLong()) {
+ stack.pop_back();
+ }
+ }
+ if (!signature->getReturnType()->isVoid()) {
+ stack.push_back(bytecode);
+ if (signature->getReturnType()->isLong()
+ || signature->getReturnType()->isDouble()) {
+ stack.push_back(bytecode);
+ }
+ }
+}
+
+bool JavaJIT::analyzeForInlining(Reader& reader, uint32 codeLength) {
+ JavaConstantPool* ctpInfo = compilingClass->ctpInfo;
+ bool wide = false;
+ uint32 start = reader.cursor;
+ std::vector<uint8_t> stack;
+ for(uint32 i = 0; i < codeLength; ++i) {
+ reader.cursor = start + i;
+ uint8 bytecode = reader.readU1();
+
+ switch (bytecode) {
+ case NOP :
+ break;
+
+ 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 FCONST_0 :
+ case FCONST_1 :
+ case FCONST_2 :
+ stack.push_back(bytecode);
+ break;
+
+ case LCONST_0 :
+ case LCONST_1 :
+ case DCONST_0 :
+ case DCONST_1 :
+ stack.push_back(bytecode);
+ stack.push_back(bytecode);
+ break;
+
+ case BIPUSH :
+ ++i;
+ stack.push_back(bytecode);
+ break;
+
+ case SIPUSH :
+ i += 2;
+ stack.push_back(bytecode);
+ break;
+
+ case LDC :
+ i++;
+ stack.push_back(bytecode);
+ if (!canInlineLoadConstant(reader.readU1())) return false;
+ break;
+
+ case LDC_W :
+ i += 2;
+ stack.push_back(bytecode);
+ if (!canInlineLoadConstant(reader.readS2())) return false;
+ break;
+
+
+ case LDC2_W :
+ i += 2;
+ stack.push_back(bytecode);
+ stack.push_back(bytecode);
+ if (!canInlineLoadConstant(reader.readS2())) return false;
+ break;
+
+ case ILOAD :
+ case FLOAD :
+ case ALOAD :
+ i += WCALC(1, wide);
+ stack.push_back(bytecode);
+ break;
+
+ case LLOAD :
+ case DLOAD :
+ i += WCALC(1, wide);
+ stack.push_back(bytecode);
+ stack.push_back(bytecode);
+ break;
+
+ case ILOAD_0 :
+ case ILOAD_1 :
+ case ILOAD_2 :
+ case ILOAD_3 :
+ case FLOAD_0 :
+ case FLOAD_1 :
+ case FLOAD_2 :
+ case FLOAD_3 :
+ case ALOAD_0 :
+ case ALOAD_1 :
+ case ALOAD_2 :
+ case ALOAD_3 :
+ stack.push_back(bytecode);
+ break;
+
+ case LLOAD_0 :
+ case LLOAD_1 :
+ case LLOAD_2 :
+ case LLOAD_3 :
+ case DLOAD_0 :
+ case DLOAD_1 :
+ case DLOAD_2 :
+ case DLOAD_3 :
+ stack.push_back(bytecode);
+ stack.push_back(bytecode);
+ break;
+
+ case IALOAD :
+ case FALOAD :
+ case AALOAD :
+ case BALOAD :
+ case CALOAD :
+ case SALOAD :
+ stack.pop_back();
+ stack.pop_back();
+ stack.push_back(bytecode);
+ return false;
+
+ case LALOAD :
+ case DALOAD :
+ stack.pop_back();
+ stack.pop_back();
+ stack.push_back(bytecode);
+ stack.push_back(bytecode);
+ return false;
+
+ case ISTORE :
+ case FSTORE :
+ case ASTORE :
+ stack.pop_back();
+ i += WCALC(1, wide);
+ break;
+
+ case LSTORE :
+ case DSTORE :
+ stack.pop_back();
+ stack.pop_back();
+ i += WCALC(1, wide);
+ break;
+
+ case ISTORE_0 :
+ case ISTORE_1 :
+ case ISTORE_2 :
+ case ISTORE_3 :
+ case FSTORE_0 :
+ case FSTORE_1 :
+ case FSTORE_2 :
+ case FSTORE_3 :
+ case ASTORE_0 :
+ case ASTORE_1 :
+ case ASTORE_2 :
+ case ASTORE_3 :
+ stack.pop_back();
+ break;
+
+ case DSTORE_0 :
+ case DSTORE_1 :
+ case DSTORE_2 :
+ case DSTORE_3 :
+ case LSTORE_0 :
+ case LSTORE_1 :
+ case LSTORE_2 :
+ case LSTORE_3 :
+ stack.pop_back();
+ stack.pop_back();
+ break;
+
+ case IASTORE :
+ case FASTORE :
+ case AASTORE :
+ case BASTORE :
+ case CASTORE :
+ case SASTORE :
+ stack.pop_back();
+ stack.pop_back();
+ stack.pop_back();
+ return false;
+
+ case LASTORE :
+ case DASTORE :
+ stack.pop_back();
+ stack.pop_back();
+ stack.pop_back();
+ stack.pop_back();
+ return false;
+
+ case POP :
+ stack.pop_back();
+ break;
+
+ case POP2 :
+ stack.pop_back();
+ stack.pop_back();
+ break;
+
+ case DUP :
+ stack.push_back(stack.back());
+ break;
+
+ case DUP_X1 : {
+ uint8 one = stack.back(); stack.pop_back();
+ uint8 two = stack.back(); stack.pop_back();
+
+ stack.push_back(one);
+ stack.push_back(two);
+ stack.push_back(one);
+ break;
+ }
+
+ case DUP_X2 : {
+ uint8 one = stack.back(); stack.pop_back();
+ uint8 two = stack.back(); stack.pop_back();
+ uint8 three = stack.back(); stack.pop_back();
+
+ stack.push_back(one);
+ stack.push_back(three);
+ stack.push_back(two);
+ stack.push_back(one);
+ break;
+ }
+
+ case DUP2 : {
+ uint8 one = stack.back(); stack.pop_back();
+ uint8 two = stack.back(); stack.pop_back();
+
+ stack.push_back(two);
+ stack.push_back(one);
+ stack.push_back(two);
+ stack.push_back(one);
+ break;
+ }
+
+ case DUP2_X1 : {
+ uint8 one = stack.back(); stack.pop_back();
+ uint8 two = stack.back(); stack.pop_back();
+ uint8 three = stack.back(); stack.pop_back();
+
+ stack.push_back(two);
+ stack.push_back(one);
+ stack.push_back(three);
+ stack.push_back(two);
+ stack.push_back(one);
+
+ break;
+ }
+
+ case DUP2_X2 : {
+ uint8 one = stack.back(); stack.pop_back();
+ uint8 two = stack.back(); stack.pop_back();
+ uint8 three = stack.back(); stack.pop_back();
+ uint8 four = stack.back(); stack.pop_back();
+
+ stack.push_back(two);
+ stack.push_back(one);
+ stack.push_back(four);
+ stack.push_back(three);
+ stack.push_back(two);
+ stack.push_back(one);
+
+ break;
+ }
+
+ case SWAP : {
+ uint8 one = stack.back(); stack.pop_back();
+ uint8 two = stack.back(); stack.pop_back();
+ stack.push_back(one);
+ stack.push_back(two);
+ break;
+ }
+
+ case IADD :
+ case FADD :
+ case ISUB :
+ case FSUB :
+ case IMUL :
+ case FMUL :
+ case FDIV :
+ case FREM :
+ case ISHL :
+ case ISHR :
+ case IUSHR :
+ case IAND :
+ case IOR :
+ case IXOR :
+ stack.pop_back();
+ stack.pop_back();
+ stack.push_back(bytecode);
+ break;
+
+ case LADD :
+ case DADD :
+ case DDIV :
+ case LMUL :
+ case DMUL :
+ case DREM :
+ case LSUB :
+ case DSUB :
+ stack.pop_back();
+ stack.pop_back();
+ stack.push_back(bytecode);
+ stack.push_back(bytecode);
+ break;
+
+ case IREM :
+ case IDIV :
+ case LREM :
+ case LDIV :
+ return false;
+
+ case INEG :
+ case FNEG :
+ stack.pop_back();
+ stack.push_back(bytecode);
+ break;
+
+ case LNEG :
+ case DNEG :
+ stack.pop_back();
+ stack.pop_back();
+ stack.push_back(bytecode);
+ stack.push_back(bytecode);
+ break;
+
+ case LSHL :
+ case LSHR :
+ case LUSHR :
+ case LAND :
+ case LOR :
+ case LXOR :
+ stack.pop_back();
+ stack.pop_back();
+ stack.pop_back();
+ stack.push_back(bytecode);
+ stack.push_back(bytecode);
+ break;
+
+ case IINC :
+ i += WCALC(2, wide);
+ break;
+
+ case I2L :
+ case I2D :
+ case F2L :
+ case F2D :
+ stack.pop_back();
+ stack.push_back(bytecode);
+ stack.push_back(bytecode);
+ break;
+
+ case I2F :
+ case F2I :
+ case I2B :
+ case I2C :
+ case I2S :
+ stack.pop_back();
+ stack.push_back(bytecode);
+ break;
+
+ case L2I :
+ case L2F :
+ case D2I :
+ case D2F :
+ stack.pop_back();
+ stack.pop_back();
+ stack.push_back(bytecode);
+ break;
+
+ case L2D :
+ case D2L :
+ stack.pop_back();
+ stack.pop_back();
+ stack.push_back(bytecode);
+ stack.push_back(bytecode);
+ break;
+
+ case FCMPL :
+ case FCMPG :
+ stack.pop_back();
+ stack.pop_back();
+ stack.push_back(bytecode);
+ break;
+
+ case LCMP :
+ case DCMPL :
+ case DCMPG :
+ stack.pop_back();
+ stack.pop_back();
+ stack.pop_back();
+ stack.pop_back();
+ stack.push_back(bytecode);
+ break;
+
+ case IFEQ :
+ case IFNE :
+ case IFLT :
+ case IFGE :
+ case IFGT :
+ case IFLE : {
+ i += 2;
+ stack.pop_back();
+ if (stack.size() > 0) return false;
+ break;
+ }
+
+ case IF_ICMPEQ :
+ case IF_ICMPNE :
+ case IF_ICMPLT :
+ case IF_ICMPGE :
+ case IF_ICMPGT :
+ case IF_ICMPLE :
+ case IF_ACMPEQ :
+ case IF_ACMPNE : {
+ i += 2;
+ stack.pop_back();
+ stack.pop_back();
+ if (stack.size() > 0) return false;
+ break;
+ }
+ case GOTO : {
+ i += 2;
+ if (stack.size() > 0) return false;
+ break;
+ }
+
+ case JSR : {
+ i += 2;
+ return false;
+ }
+
+ case RET : {
+ ++i;
+ return false;
+ }
+
+ case TABLESWITCH : {
+ stack.pop_back();
+ if (stack.size() > 0) return false;
+ uint32 tmp = i;
+ uint32 reste = (i + 1) & 3;
+ uint32 filled = reste ? (4 - reste) : 0;
+ i += filled;
+ reader.cursor += filled;
+ reader.readU4();
+ i += 4;
+
+ sint32 low = reader.readS4();
+ i += 4;
+ sint32 high = reader.readS4() + 1;
+ i += 4;
+ for (sint32 cur = low; cur < high; ++cur) {
+ reader.readU4();
+ i += 4;
+ }
+
+ i = tmp + 12 + filled + ((high - low) << 2);
+ break;
+ }
+
+ case LOOKUPSWITCH : {
+ stack.pop_back();
+ if (stack.size() > 0) return false;
+ uint32 tmp = i;
+ uint32 filled = (3 - i) & 3;
+ i += filled;
+ reader.cursor += filled;
+ reader.readU4();
+ i += 4;
+ uint32 nbs = reader.readU4();
+ i += 4;
+ for (uint32 cur = 0; cur < nbs; ++cur) {
+ i += 4;
+ reader.cursor += 4;
+ reader.readU4();
+ i += 4;
+ }
+
+ i = tmp + 8 + filled + (nbs << 3);
+ break;
+ }
+
+ case IRETURN :
+ case FRETURN :
+ case ARETURN :
+ stack.pop_back();
+ break;
+
+ case RETURN :
+ break;
+
+ case LRETURN :
+ case DRETURN :
+ stack.pop_back();
+ stack.pop_back();
+ break;
+
+ case GETSTATIC :
+ case PUTSTATIC : {
+ uint16 index = reader.readU2();
+ Typedef* sign = ctpInfo->infoOfField(index);
+ JavaField* field = ctpInfo->lookupField(index, true);
+ if (field == NULL) return false;
+ if (needsInitialisationCheck(field->classDef)) return false;
+ if (bytecode == GETSTATIC) {
+ stack.push_back(bytecode);
+ if (sign->isDouble() || sign->isLong()) {
+ stack.push_back(bytecode);
+ }
+ } else {
+ stack.pop_back();
+ if (sign->isDouble() || sign->isLong()) {
+ stack.pop_back();
+ }
+ }
+ i += 2;
+ break;
+ }
+
+ case PUTFIELD : {
+ if (isStatic(compilingMethod->access)) return false;
+ i += 2;
+ stack.pop_back(); // value
+ uint16 index = reader.readU2();
+ Typedef* sign = ctpInfo->infoOfField(index);
+ if (sign->isDouble() || sign->isLong()) {
+ stack.pop_back(); // value
+ }
+ if (stack.back() != ALOAD_0) return false;
+ stack.pop_back(); // object
+ break;
+ }
+
+ case GETFIELD : {
+ if (isStatic(compilingMethod->access)) return false;
+ if (stack.back() != ALOAD_0) return false;
+ i += 2;
+ stack.pop_back(); // object
+ uint16 index = reader.readU2();
+ Typedef* sign = ctpInfo->infoOfField(index);
+ stack.push_back(bytecode);
+ if (sign->isDouble() || sign->isLong()) {
+ stack.push_back(bytecode);
+ }
+ break;
+ }
+
+ case INVOKEVIRTUAL :
+ i += 2;
+ return false;
+
+ case INVOKESPECIAL : {
+ if (isStatic(compilingMethod->access)) return false;
+ uint16 index = reader.readU2();
+ CommonClass* cl = NULL;
+ JavaMethod* meth = NULL;
+ ctpInfo->infoOfMethod(index, ACC_VIRTUAL, cl, meth);
+ i += 2;
+ if (meth == NULL) return false;
+ if (getReceiver(stack, meth->getSignature()) != ALOAD_0) return false;
+ if (!canBeInlined(meth)) return false;
+ updateStack(stack, meth->getSignature(), bytecode);
+ break;
+ }
+
+ case INVOKESTATIC : {
+ uint16 index = reader.readU2();
+ CommonClass* cl = NULL;
+ JavaMethod* meth = NULL;
+ ctpInfo->infoOfMethod(index, ACC_STATIC, cl, meth);
+ i += 2;
+ if (meth == NULL) return false;
+ if (!canBeInlined(meth)) return false;
+ if (needsInitialisationCheck(cl->asClass())) return false;
+ updateStack(stack, meth->getSignature(), bytecode);
+ break;
+ }
+
+ case INVOKEINTERFACE :
+ i += 4;
+ return false;
+
+ case NEW :
+ i += 2;
+ return false;
+
+ case NEWARRAY :
+ ++i;
+ return false;
+
+ case ANEWARRAY :
+ i += 2;
+ return false;
+
+ case ARRAYLENGTH :
+ stack.pop_back();
+ stack.push_back(bytecode);
+ break;
+
+ case ATHROW :
+ return false;
+
+ case CHECKCAST :
+ i += 2;
+ return false;
+
+ case INSTANCEOF :
+ i += 2;
+ return false;
+
+ case MONITORENTER :
+ case MONITOREXIT :
+ return false;
+
+ case MULTIANEWARRAY :
+ i += 3;
+ return false;
+
+ case WIDE :
+ wide = true;
+ break;
+
+ case IFNULL :
+ case IFNONNULL :
+ stack.pop_back();
+ i += 2;
+ if (stack.size() > 0) return false;
+ break;
+
+ default :
+ return false;
+ }
+ }
+ return true;
+}
More information about the vmkit-commits
mailing list