diff options
author | Ben Cheng <bccheng@android.com> | 2011-01-14 11:36:46 -0800 |
---|---|---|
committer | Ben Cheng <bccheng@android.com> | 2011-01-26 12:51:49 -0800 |
commit | cfdeca37fcaa27c37bad5077223e4d1e87f1182e (patch) | |
tree | aa556c91c315994df440244de024ebb15f0e9757 /vm/compiler/InlineTransformation.c | |
parent | 73bfc612a47588c2e657acac44c23bd5668dadf4 (diff) | |
download | android_dalvik-cfdeca37fcaa27c37bad5077223e4d1e87f1182e.tar.gz android_dalvik-cfdeca37fcaa27c37bad5077223e4d1e87f1182e.tar.bz2 android_dalvik-cfdeca37fcaa27c37bad5077223e4d1e87f1182e.zip |
Add runtime support for method based compilation.
Enhanced code cache management to accommodate both trace and method
compilations. Also implemented a hacky dispatch routine for virtual
leaf methods.
Microbenchmark showed 3x speedup in leaf method invocation.
Change-Id: I79d95b7300ba993667b3aa221c1df9c7b0583521
Diffstat (limited to 'vm/compiler/InlineTransformation.c')
-rw-r--r-- | vm/compiler/InlineTransformation.c | 103 |
1 files changed, 75 insertions, 28 deletions
diff --git a/vm/compiler/InlineTransformation.c b/vm/compiler/InlineTransformation.c index cab790cac..6cf2d43be 100644 --- a/vm/compiler/InlineTransformation.c +++ b/vm/compiler/InlineTransformation.c @@ -34,7 +34,7 @@ static inline u4 convertRegId(const DecodedInstruction *invoke, } } -static void inlineGetter(CompilationUnit *cUnit, +static bool inlineGetter(CompilationUnit *cUnit, const Method *calleeMethod, MIR *invokeMIR, BasicBlock *invokeBB, @@ -49,7 +49,7 @@ static void inlineGetter(CompilationUnit *cUnit, dexDecodeInstruction(calleeMethod->insns, &getterInsn); if (!dvmCompilerCanIncludeThisInstruction(calleeMethod, &getterInsn)) - return; + return false; /* * Some getters (especially invoked through interface) are not followed @@ -59,7 +59,7 @@ static void inlineGetter(CompilationUnit *cUnit, (moveResultMIR->dalvikInsn.opcode != OP_MOVE_RESULT && moveResultMIR->dalvikInsn.opcode != OP_MOVE_RESULT_OBJECT && moveResultMIR->dalvikInsn.opcode != OP_MOVE_RESULT_WIDE)) { - return; + return false; } int dfFlags = dvmCompilerDataFlowAttributes[getterInsn.opcode]; @@ -124,10 +124,10 @@ static void inlineGetter(CompilationUnit *cUnit, #endif } - return; + return true; } -static void inlineSetter(CompilationUnit *cUnit, +static bool inlineSetter(CompilationUnit *cUnit, const Method *calleeMethod, MIR *invokeMIR, BasicBlock *invokeBB, @@ -140,7 +140,7 @@ static void inlineSetter(CompilationUnit *cUnit, dexDecodeInstruction(calleeMethod->insns, &setterInsn); if (!dvmCompilerCanIncludeThisInstruction(calleeMethod, &setterInsn)) - return; + return false; int dfFlags = dvmCompilerDataFlowAttributes[setterInsn.opcode]; @@ -205,17 +205,17 @@ static void inlineSetter(CompilationUnit *cUnit, #endif } - return; + return true; } -static void tryInlineSingletonCallsite(CompilationUnit *cUnit, +static bool tryInlineSingletonCallsite(CompilationUnit *cUnit, const Method *calleeMethod, MIR *invokeMIR, BasicBlock *invokeBB, bool isRange) { /* Not a Java method */ - if (dvmIsNativeMethod(calleeMethod)) return; + if (dvmIsNativeMethod(calleeMethod)) return false; CompilerMethodStats *methodStats = dvmCompilerAnalyzeMethodBody(calleeMethod, true); @@ -229,19 +229,20 @@ static void tryInlineSingletonCallsite(CompilationUnit *cUnit, * the PC reconstruction or chaining cell). */ invokeBB->needFallThroughBranch = true; - return; + return true; } if (methodStats->attributes & METHOD_IS_GETTER) { - inlineGetter(cUnit, calleeMethod, invokeMIR, invokeBB, false, isRange); - return; + return inlineGetter(cUnit, calleeMethod, invokeMIR, invokeBB, false, + isRange); } else if (methodStats->attributes & METHOD_IS_SETTER) { - inlineSetter(cUnit, calleeMethod, invokeMIR, invokeBB, false, isRange); - return; + return inlineSetter(cUnit, calleeMethod, invokeMIR, invokeBB, false, + isRange); } + return false; } -static void inlineEmptyVirtualCallee(CompilationUnit *cUnit, +static bool inlineEmptyVirtualCallee(CompilationUnit *cUnit, const Method *calleeMethod, MIR *invokeMIR, BasicBlock *invokeBB) @@ -252,37 +253,39 @@ static void inlineEmptyVirtualCallee(CompilationUnit *cUnit, dvmCompilerInsertMIRAfter(invokeBB, invokeMIR, invokeMIRSlow); invokeMIRSlow->OptimizationFlags |= MIR_INLINED_PRED; + return true; } -static void tryInlineVirtualCallsite(CompilationUnit *cUnit, +static bool tryInlineVirtualCallsite(CompilationUnit *cUnit, const Method *calleeMethod, MIR *invokeMIR, BasicBlock *invokeBB, bool isRange) { /* Not a Java method */ - if (dvmIsNativeMethod(calleeMethod)) return; + if (dvmIsNativeMethod(calleeMethod)) return false; CompilerMethodStats *methodStats = dvmCompilerAnalyzeMethodBody(calleeMethod, true); /* Empty callee - do nothing by checking the clazz pointer */ if (methodStats->attributes & METHOD_IS_EMPTY) { - inlineEmptyVirtualCallee(cUnit, calleeMethod, invokeMIR, invokeBB); - return; + return inlineEmptyVirtualCallee(cUnit, calleeMethod, invokeMIR, + invokeBB); } if (methodStats->attributes & METHOD_IS_GETTER) { - inlineGetter(cUnit, calleeMethod, invokeMIR, invokeBB, true, isRange); - return; + return inlineGetter(cUnit, calleeMethod, invokeMIR, invokeBB, true, + isRange); } else if (methodStats->attributes & METHOD_IS_SETTER) { - inlineSetter(cUnit, calleeMethod, invokeMIR, invokeBB, true, isRange); - return; + return inlineSetter(cUnit, calleeMethod, invokeMIR, invokeBB, true, + isRange); } + return false; } -void dvmCompilerInlineMIR(CompilationUnit *cUnit) +void dvmCompilerInlineMIR(CompilationUnit *cUnit, JitTranslationInfo *info) { bool isRange = false; GrowableListIterator iterator; @@ -337,8 +340,30 @@ void dvmCompilerInlineMIR(CompilationUnit *cUnit) } if (calleeMethod) { - tryInlineSingletonCallsite(cUnit, calleeMethod, lastMIRInsn, bb, - isRange); + bool inlined = tryInlineSingletonCallsite(cUnit, calleeMethod, + lastMIRInsn, bb, isRange); + if (!inlined && + !(gDvmJit.disableOpt & (1 << kMethodJit)) && + !dvmIsNativeMethod(calleeMethod)) { + CompilerMethodStats *methodStats = + dvmCompilerAnalyzeMethodBody(calleeMethod, true); + if ((methodStats->attributes & METHOD_IS_LEAF) && + !(methodStats->attributes & METHOD_CANNOT_COMPILE)) { + /* Callee has been previously compiled */ + if (dvmJitGetMethodAddr(calleeMethod->insns)) { + lastMIRInsn->OptimizationFlags |= MIR_INVOKE_METHOD_JIT; + } else { + /* Compile the callee first */ + dvmCompileMethod(calleeMethod, info); + if (dvmJitGetMethodAddr(calleeMethod->insns)) { + lastMIRInsn->OptimizationFlags |= + MIR_INVOKE_METHOD_JIT; + } else { + methodStats->attributes |= METHOD_CANNOT_COMPILE; + } + } + } + } return; } @@ -360,8 +385,30 @@ void dvmCompilerInlineMIR(CompilationUnit *cUnit) } if (calleeMethod) { - tryInlineVirtualCallsite(cUnit, calleeMethod, lastMIRInsn, bb, - isRange); + bool inlined = tryInlineVirtualCallsite(cUnit, calleeMethod, + lastMIRInsn, bb, isRange); + if (!inlined && + !(gDvmJit.disableOpt & (1 << kMethodJit)) && + !dvmIsNativeMethod(calleeMethod)) { + CompilerMethodStats *methodStats = + dvmCompilerAnalyzeMethodBody(calleeMethod, true); + if ((methodStats->attributes & METHOD_IS_LEAF) && + !(methodStats->attributes & METHOD_CANNOT_COMPILE)) { + /* Callee has been previously compiled */ + if (dvmJitGetMethodAddr(calleeMethod->insns)) { + lastMIRInsn->OptimizationFlags |= MIR_INVOKE_METHOD_JIT; + } else { + /* Compile the callee first */ + dvmCompileMethod(calleeMethod, info); + if (dvmJitGetMethodAddr(calleeMethod->insns)) { + lastMIRInsn->OptimizationFlags |= + MIR_INVOKE_METHOD_JIT; + } else { + methodStats->attributes |= METHOD_CANNOT_COMPILE; + } + } + } + } return; } } |