summaryrefslogtreecommitdiffstats
path: root/vm/compiler/codegen
diff options
context:
space:
mode:
Diffstat (limited to 'vm/compiler/codegen')
-rw-r--r--vm/compiler/codegen/CompilerCodegen.h3
-rw-r--r--vm/compiler/codegen/arm/Assemble.c60
-rw-r--r--vm/compiler/codegen/arm/CodegenDriver.c3
3 files changed, 51 insertions, 15 deletions
diff --git a/vm/compiler/codegen/CompilerCodegen.h b/vm/compiler/codegen/CompilerCodegen.h
index 3e9718c6d..ff39cd408 100644
--- a/vm/compiler/codegen/CompilerCodegen.h
+++ b/vm/compiler/codegen/CompilerCodegen.h
@@ -31,6 +31,9 @@ void dvmCompilerMIR2LIR(CompilationUnit *cUnit);
/* Assemble LIR into machine code */
void dvmCompilerAssembleLIR(CompilationUnit *cUnit, JitTranslationInfo *info);
+/* Patch inline cache content for polymorphic callsites */
+bool dvmJitPatchInlineCache(void *cellPtr, void *contentPtr);
+
/* Implemented in the codegen/<target>/ArchUtility.c */
void dvmCompilerCodegenDump(CompilationUnit *cUnit);
diff --git a/vm/compiler/codegen/arm/Assemble.c b/vm/compiler/codegen/arm/Assemble.c
index 26e227fd3..7444b3eba 100644
--- a/vm/compiler/codegen/arm/Assemble.c
+++ b/vm/compiler/codegen/arm/Assemble.c
@@ -1407,35 +1407,65 @@ const Method *dvmJitToPatchPredictedChain(const Method *method,
*/
cell->counter = PREDICTED_CHAIN_COUNTER_AVOID;
- /* Stop the world */
- dvmSuspendAllThreads(SUSPEND_FOR_IC_PATCH);
+ PredictedChainingCell *newCell =
+ (PredictedChainingCell *) malloc(sizeof(PredictedChainingCell));
int baseAddr = (int) cell + 4; // PC is cur_addr + 4
int branchOffset = tgtAddr - baseAddr;
- COMPILER_TRACE_CHAINING(
- LOGD("Jit Runtime: predicted chain %p from %s to %s (%s) patched",
- cell, cell->clazz ? cell->clazz->descriptor : "NULL",
- clazz->descriptor,
- method->name));
+ newCell->branch = assembleChainingBranch(branchOffset, true);
+ newCell->clazz = clazz;
+ newCell->method = method;
- cell->branch = assembleChainingBranch(branchOffset, true);
- cell->clazz = clazz;
- cell->method = method;
/*
* Reset the counter again in case other mutator threads got invoked
* between the previous rest and dvmSuspendAllThreads call.
*/
- cell->counter = PREDICTED_CHAIN_COUNTER_RECHAIN;
+ newCell->counter = PREDICTED_CHAIN_COUNTER_RECHAIN;
- cacheflush((long) cell, (long) (cell+1), 0);
+ /*
+ * Enter the work order to the queue for the compiler thread to patch the
+ * chaining cell.
+ *
+ * No blocking call is added here because the patched result is not
+ * intended to be immediately consumed by the requesting thread. Its
+ * execution is simply resumed by chasing the class pointer to resolve the
+ * callsite.
+ */
+ dvmCompilerWorkEnqueue((const u2 *) cell, kWorkOrderICPatch, newCell);
+#endif
+done:
+ return method;
+}
+
+/*
+ * Patch the inline cache content based on the content passed from the work
+ * order.
+ */
+bool dvmJitPatchInlineCache(void *cellPtr, void *contentPtr)
+{
+ PredictedChainingCell *cellDest = (PredictedChainingCell *) cellPtr;
+ PredictedChainingCell *newContent = (PredictedChainingCell *) contentPtr;
+
+ /* Stop the world */
+ dvmSuspendAllThreads(SUSPEND_FOR_IC_PATCH);
+
+ COMPILER_TRACE_CHAINING(
+ LOGD("Jit Runtime: predicted chain %p from %s to %s (%s) patched",
+ cellDest, cellDest->clazz ? cellDest->clazz->descriptor : "NULL",
+ newContent->clazz->descriptor,
+ newContent->method->name));
+
+ /* Install the new cell content */
+ *cellDest = *newContent;
+
+ /* Then synchronize the I/D$ */
+ cacheflush((long) cellDest, (long) (cellDest+1), 0);
/* All done - resume all other threads */
dvmResumeAllThreads(SUSPEND_FOR_IC_PATCH);
-#endif
-done:
- return method;
+ return true;
}
/*
diff --git a/vm/compiler/codegen/arm/CodegenDriver.c b/vm/compiler/codegen/arm/CodegenDriver.c
index f3648b9bd..010e8ca23 100644
--- a/vm/compiler/codegen/arm/CodegenDriver.c
+++ b/vm/compiler/codegen/arm/CodegenDriver.c
@@ -4117,6 +4117,9 @@ bool dvmCompilerDoWork(CompilerWorkOrder *work)
gDvmJit.printMe = oldPrintMe;;
break;
}
+ case kWorkOrderICPatch:
+ res = dvmJitPatchInlineCache((void *) work->pc, work->info);
+ break;
default:
res = false;
dvmAbort();