Patch support for the boot image.
Requires oat and image writer support.
Change-Id: Ic87dd481a4f86d15faa1e830ea1dd0b3d664c220
diff --git a/src/compiler/CompilerIR.h b/src/compiler/CompilerIR.h
index 54d9951..8a3fa09 100644
--- a/src/compiler/CompilerIR.h
+++ b/src/compiler/CompilerIR.h
@@ -298,6 +298,8 @@
LIR* firstLIRInsn;
LIR* lastLIRInsn;
LIR* literalList; // Constants
+ LIR* methodLiteralList; // Method literals requiring patching
+ LIR* codeLiteralList; // Code literals requiring patching
LIR* classPointerList; // Relocatable
int numClassPointers;
LIR* chainCellOffsetLIR;
diff --git a/src/compiler/codegen/CodegenUtil.cc b/src/compiler/codegen/CodegenUtil.cc
index cc31b29..8b324ed 100644
--- a/src/compiler/codegen/CodegenUtil.cc
+++ b/src/compiler/codegen/CodegenUtil.cc
@@ -553,8 +553,7 @@
*/
/* Add a 32-bit constant either in the constant pool */
-LIR* addWordData(CompilationUnit* cUnit, LIR* *constantListP,
- int value)
+LIR* addWordData(CompilationUnit* cUnit, LIR* *constantListP, int value)
{
/* Add the constant to the literal pool */
if (constantListP) {
@@ -595,11 +594,33 @@
void installLiteralPools(CompilationUnit* cUnit)
{
alignBuffer(cUnit->codeBuffer, cUnit->dataOffset);
- LIR* dataLIR = (LIR*) cUnit->literalList;
+ LIR* dataLIR = cUnit->literalList;
while (dataLIR != NULL) {
pushWord(cUnit->codeBuffer, dataLIR->operands[0]);
dataLIR = NEXT_LIR(dataLIR);
}
+ // Push code and method literals, record offsets for the compiler to patch.
+ dataLIR = cUnit->codeLiteralList;
+ if (dataLIR != NULL) {
+ while (dataLIR != NULL) {
+ cUnit->compiler->AddCodePatch(cUnit->dex_cache, cUnit->dex_file,
+ cUnit->method_idx,
+ dataLIR->operands[0],
+ cUnit->codeBuffer.size());
+ pushWord(cUnit->codeBuffer, 0xEBAD9A7C); // value to be patched
+ dataLIR = NEXT_LIR(dataLIR);
+ }
+ dataLIR = cUnit->methodLiteralList;
+ while (dataLIR != NULL) {
+ cUnit->compiler->AddMethodPatch(cUnit->dex_cache, cUnit->dex_file,
+ cUnit->method_idx,
+ dataLIR->operands[0],
+ cUnit->codeBuffer.size());
+ pushWord(cUnit->codeBuffer, 0xEBAD9A7D); // value to be patched
+ dataLIR = NEXT_LIR(dataLIR);
+ }
+ }
+
}
/* Write the switch tables to the output stream */
@@ -702,6 +723,8 @@
int assignLiteralOffset(CompilationUnit* cUnit, int offset)
{
offset = assignLiteralOffsetCommon(cUnit->literalList, offset);
+ offset = assignLiteralOffsetCommon(cUnit->codeLiteralList, offset);
+ offset = assignLiteralOffsetCommon(cUnit->methodLiteralList, offset);
return offset;
}
diff --git a/src/compiler/codegen/GenInvoke.cc b/src/compiler/codegen/GenInvoke.cc
index 2ded800..90e2267 100644
--- a/src/compiler/codegen/GenInvoke.cc
+++ b/src/compiler/codegen/GenInvoke.cc
@@ -94,6 +94,25 @@
}
}
+void scanMethodLiteralPool(CompilationUnit* cUnit, LIR** methodTarget, LIR** codeTarget, const DexFile* dexFile, uint32_t dexMethodIdx)
+{
+ LIR* curTarget = cUnit->methodLiteralList;
+ LIR* nextTarget = curTarget != NULL ? curTarget->next : NULL;
+ while (curTarget != NULL && nextTarget != NULL) {
+ if (curTarget->operands[0] == (int)dexFile &&
+ nextTarget->operands[0] == (int)dexMethodIdx) {
+ *codeTarget = curTarget;
+ *methodTarget = nextTarget;
+ DCHECK((*codeTarget)->next == *methodTarget);
+ DCHECK_EQ((*codeTarget)->operands[0], (int)dexFile);
+ DCHECK_EQ((*methodTarget)->operands[0], (int)dexMethodIdx);
+ break;
+ }
+ curTarget = nextTarget->next;
+ nextTarget = curTarget != NULL ? curTarget->next : NULL;
+ }
+}
+
/*
* Bit of a hack here - in leiu of a real scheduling pass,
* emit the next instruction in static & direct invoke sequences.
@@ -105,8 +124,36 @@
if (directCode != 0 && directMethod != 0) {
switch(state) {
case 0: // Get the current Method* [sets rARG0]
- loadConstant(cUnit, rINVOKE_TGT, directCode);
- loadConstant(cUnit, rARG0, directMethod);
+ if (directCode != (uintptr_t)-1) {
+ loadConstant(cUnit, rINVOKE_TGT, directCode);
+ } else {
+ LIR* dataTarget = scanLiteralPool(cUnit->codeLiteralList, dexIdx, 0);
+ if (dataTarget == NULL) {
+ dataTarget = addWordData(cUnit, &cUnit->codeLiteralList, dexIdx);
+ }
+#if defined(TARGET_ARM)
+ LIR* loadPcRel = rawLIR(cUnit, cUnit->currentDalvikOffset,
+ kThumb2LdrPcRel12, rINVOKE_TGT, 0, 0, 0, 0, dataTarget);
+ oatAppendLIR(cUnit, loadPcRel);
+#else
+ UNIMPLEMENTED(FATAL) << (void*)dataTarget;
+#endif
+ }
+ if (directMethod != (uintptr_t)-1) {
+ loadConstant(cUnit, rARG0, directMethod);
+ } else {
+ LIR* dataTarget = scanLiteralPool(cUnit->methodLiteralList, dexIdx, 0);
+ if (dataTarget == NULL) {
+ dataTarget = addWordData(cUnit, &cUnit->methodLiteralList, dexIdx);
+ }
+#if defined(TARGET_ARM)
+ LIR* loadPcRel = rawLIR(cUnit, cUnit->currentDalvikOffset,
+ kThumb2LdrPcRel12, rARG0, 0, 0, 0, 0, dataTarget);
+ oatAppendLIR(cUnit, loadPcRel);
+#else
+ UNIMPLEMENTED(FATAL) << (void*)dataTarget;
+#endif
+ }
break;
default:
return -1;
@@ -122,7 +169,21 @@
rARG0);
// Set up direct code if known.
if (directCode != 0) {
- loadConstant(cUnit, rINVOKE_TGT, directCode);
+ if (directCode != (uintptr_t)-1) {
+ loadConstant(cUnit, rINVOKE_TGT, directCode);
+ } else {
+ LIR* dataTarget = scanLiteralPool(cUnit->codeLiteralList, dexIdx, 0);
+ if (dataTarget == NULL) {
+ dataTarget = addWordData(cUnit, &cUnit->codeLiteralList, dexIdx);
+ }
+#if defined(TARGET_ARM)
+ LIR* loadPcRel = rawLIR(cUnit, cUnit->currentDalvikOffset,
+ kThumb2LdrPcRel12, rINVOKE_TGT, 0, 0, 0, 0, dataTarget);
+ oatAppendLIR(cUnit, loadPcRel);
+#else
+ UNIMPLEMENTED(FATAL) << (void*)dataTarget;
+#endif
+ }
}
break;
case 2: // Grab target method*