JIT: Reworked the assembler to be smarter about short instruction forms
Previously, the JIT wasn't generating short-form compare and branch on
zero/not zero instructions for Thumb2. The reason was that these only
allow a 1-byte displacement, and when they didn't reach the assembler would
abort the trace, split it in half and try again. This change re-enables
cbz, cbnz generation and introduces a relatively lightweight retry
mechanism.
Also includes changes for Thumb2 to always generate large displacement
literal loads and conditional branches to minimize the number of retry
attempts.
Change-Id: Icf066836fad203f5c0fcbbb2ae8e1aa73d1cf816
diff --git a/vm/compiler/Frontend.c b/vm/compiler/Frontend.c
index a828886..8e5a5e2 100644
--- a/vm/compiler/Frontend.c
+++ b/vm/compiler/Frontend.c
@@ -918,15 +918,17 @@
/* Convert MIR to LIR, etc. */
dvmCompilerMIR2LIR(&cUnit);
- /* Convert LIR into machine code. */
- dvmCompilerAssembleLIR(&cUnit, info);
+ /* Convert LIR into machine code. Loop for recoverable retries */
+ do {
+ dvmCompilerAssembleLIR(&cUnit, info);
+ cUnit.assemblerRetries++;
+ if (cUnit.printMe && cUnit.assemblerStatus != kSuccess)
+ LOGD("Assembler abort #%d on %d",cUnit.assemblerRetries,
+ cUnit.assemblerStatus);
+ } while (cUnit.assemblerStatus == kRetryAll);
if (cUnit.printMe) {
- if (cUnit.halveInstCount) {
- LOGD("Assembler aborted");
- } else {
- dvmCompilerCodegenDump(&cUnit);
- }
+ dvmCompilerCodegenDump(&cUnit);
LOGD("End %s%s, %d Dalvik instructions",
desc->method->clazz->descriptor, desc->method->name,
cUnit.numInsts);
@@ -935,18 +937,17 @@
/* Reset the compiler resource pool */
dvmCompilerArenaReset();
- /* Success */
- if (!cUnit.halveInstCount) {
-#if defined(WITH_JIT_TUNING)
- methodStats->nativeSize += cUnit.totalSize;
-#endif
- return info->codeAddress != NULL;
-
- /* Halve the instruction count and retry again */
- } else {
+ if (cUnit.assemblerStatus == kRetryHalve) {
+ /* Halve the instruction count and start from the top */
return dvmCompileTrace(desc, cUnit.numInsts / 2, info, bailPtr,
optHints);
}
+
+ assert(cUnit.assemblerStatus == kSuccess);
+#if defined(WITH_JIT_TUNING)
+ methodStats->nativeSize += cUnit.totalSize;
+#endif
+ return info->codeAddress != NULL;
}
/*
@@ -1290,7 +1291,7 @@
/* Convert LIR into machine code. */
dvmCompilerAssembleLIR(cUnit, info);
- if (cUnit->halveInstCount) {
+ if (cUnit->assemblerStatus != kSuccess) {
return false;
}