Split dex_pc<->native_pc mapping table
First of 2 related CLs - this one moves to a split table, a future
CL will compress the table to save image space.
The current MappingTable mixes two flavors of entries: dex->pc and
pc(return address)->dex. The problem is that we can have two
entries with the same native pc address but two different dex pcs.
The reason is that when we go from native pc to dex, the native
pc is actually the return address from the previous call, whereas
when we go from dex to native pc, the mapping refers to the first
native instruction of the sequence.
Previously, the first entry in the mapping table was the number
of subsequent entries. That will remain the same, but now
the second entry will be a count of the number of entries in
the pc->dex section of the table. The difference between the
two counts gives us the number of entries in the following dex->pc
section.
Change-Id: Ibadb96cb50bf1f93e079dff3832130b9f9782723
diff --git a/src/compiler/CompilerIR.h b/src/compiler/CompilerIR.h
index 56ae486..434320d 100644
--- a/src/compiler/CompilerIR.h
+++ b/src/compiler/CompilerIR.h
@@ -426,7 +426,18 @@
AssemblerStatus assemblerStatus; // Success or fix and retry
int assemblerRetries;
std::vector<uint8_t> codeBuffer;
- std::vector<uint32_t> mappingTable;
+ /*
+ * Holds mapping from native PC to dex PC for safepoints where we may deoptimize.
+ * Native PC is on the return address of the safepointed operation. Dex PC is for
+ * the instruction being executed at the safepoint.
+ */
+ std::vector<uint32_t> pc2dexMappingTable;
+ /*
+ * Holds mapping from Dex PC to native PC for catch entry points. Native PC and Dex PC
+ * immediately preceed the instruction.
+ */
+ std::vector<uint32_t> dex2pcMappingTable;
+ std::vector<uint32_t> combinedMappingTable;
std::vector<uint32_t> coreVmapTable;
std::vector<uint32_t> fpVmapTable;
std::vector<uint8_t> nativeGcMap;
diff --git a/src/compiler/Frontend.cc b/src/compiler/Frontend.cc
index 31d8aa5..09bc054 100644
--- a/src/compiler/Frontend.cc
+++ b/src/compiler/Frontend.cc
@@ -1216,9 +1216,8 @@
}
CompiledMethod* result =
new CompiledMethod(cUnit->instructionSet, cUnit->codeBuffer,
- cUnit->frameSize, cUnit->coreSpillMask,
- cUnit->fpSpillMask, cUnit->mappingTable, vmapTable,
- cUnit->nativeGcMap);
+ cUnit->frameSize, cUnit->coreSpillMask, cUnit->fpSpillMask,
+ cUnit->combinedMappingTable, vmapTable, cUnit->nativeGcMap);
VLOG(compiler) << "Compiled " << PrettyMethod(method_idx, dex_file)
<< " (" << (cUnit->codeBuffer.size() * sizeof(cUnit->codeBuffer[0]))
diff --git a/src/compiler/codegen/CodegenUtil.cc b/src/compiler/codegen/CodegenUtil.cc
index 4e39ffc..22aacc2 100644
--- a/src/compiler/codegen/CodegenUtil.cc
+++ b/src/compiler/codegen/CodegenUtil.cc
@@ -341,6 +341,9 @@
case kPseudoSafepointPC:
LOG(INFO) << "LsafepointPC_0x" << std::hex << lir->offset << "_" << lir->dalvikOffset << ":";
break;
+ case kPseudoExportedPC:
+ LOG(INFO) << "LexportedPC_0x" << std::hex << lir->offset << "_" << lir->dalvikOffset << ":";
+ break;
case kPseudoCaseLabel:
LOG(INFO) << "LC" << (void*)lir << ": Case target 0x"
<< std::hex << lir->operands[0] << "|" << std::dec <<
@@ -397,6 +400,23 @@
}
}
+/* Dump a mapping table */
+void dumpMappingTable(const char* table_name, const std::string& descriptor,
+ const std::string& name, const std::string& signature,
+ const std::vector<uint32_t>& v) {
+ if (v.size() > 0) {
+ std::string line(StringPrintf("\n %s %s%s_%s_table[%zu] = {", table_name,
+ descriptor.c_str(), name.c_str(), signature.c_str(), v.size()));
+ std::replace(line.begin(), line.end(), ';', '_');
+ LOG(INFO) << line;
+ for (uint32_t i = 0; i < v.size(); i+=2) {
+ line = StringPrintf(" {0x%05x, 0x%04x},", v[i], v[i+1]);
+ LOG(INFO) << line;
+ }
+ LOG(INFO) <<" };\n\n";
+ }
+}
+
/* Dump instructions and constant pool contents */
void oatCodegenDump(CompilationUnit* cUnit)
{
@@ -434,21 +454,9 @@
std::string name(cUnit->dex_file->GetMethodName(method_id));
std::string descriptor(cUnit->dex_file->GetMethodDeclaringClassDescriptor(method_id));
- // Dump mapping table
- if (cUnit->mappingTable.size() > 0) {
- std::string
- line(StringPrintf("\n MappingTable %s%s_%s_mappingTable[%zu] = {",
- descriptor.c_str(), name.c_str(), signature.c_str(),
- cUnit->mappingTable.size()));
- std::replace(line.begin(), line.end(), ';', '_');
- LOG(INFO) << line;
- for (uint32_t i = 0; i < cUnit->mappingTable.size(); i+=2) {
- line = StringPrintf(" {0x%05x, 0x%04x},",
- cUnit->mappingTable[i], cUnit->mappingTable[i+1]);
- LOG(INFO) << line;
- }
- LOG(INFO) <<" };\n\n";
- }
+ // Dump mapping tables
+ dumpMappingTable("PC2Dex_MappingTable", descriptor, name, signature, cUnit->pc2dexMappingTable);
+ dumpMappingTable("Dex2PC_MappingTable", descriptor, name, signature, cUnit->dex2pcMappingTable);
}
@@ -465,7 +473,8 @@
insn->operands[4] = op4;
insn->target = target;
oatSetupResourceMasks(insn);
- if ((opcode == kPseudoTargetLabel) || (opcode == kPseudoSafepointPC)) {
+ if ((opcode == kPseudoTargetLabel) || (opcode == kPseudoSafepointPC) ||
+ (opcode == kPseudoExportedPC)) {
// Always make labels scheduling barriers
insn->useMask = insn->defMask = ENCODE_ALL;
}
@@ -755,14 +764,27 @@
return offset;
}
-void createMappingTable(CompilationUnit* cUnit)
+void createMappingTables(CompilationUnit* cUnit)
{
for (LIR* tgtLIR = (LIR *) cUnit->firstLIRInsn; tgtLIR != NULL; tgtLIR = NEXT_LIR(tgtLIR)) {
if (!tgtLIR->flags.isNop && (tgtLIR->opcode == kPseudoSafepointPC)) {
- cUnit->mappingTable.push_back(tgtLIR->offset);
- cUnit->mappingTable.push_back(tgtLIR->dalvikOffset);
+ cUnit->pc2dexMappingTable.push_back(tgtLIR->offset);
+ cUnit->pc2dexMappingTable.push_back(tgtLIR->dalvikOffset);
+ }
+ if (!tgtLIR->flags.isNop && (tgtLIR->opcode == kPseudoExportedPC)) {
+ cUnit->dex2pcMappingTable.push_back(tgtLIR->offset);
+ cUnit->dex2pcMappingTable.push_back(tgtLIR->dalvikOffset);
}
}
+ cUnit->combinedMappingTable.push_back(cUnit->pc2dexMappingTable.size() +
+ cUnit->dex2pcMappingTable.size());
+ cUnit->combinedMappingTable.push_back(cUnit->pc2dexMappingTable.size());
+ cUnit->combinedMappingTable.insert(cUnit->combinedMappingTable.end(),
+ cUnit->pc2dexMappingTable.begin(),
+ cUnit->pc2dexMappingTable.end());
+ cUnit->combinedMappingTable.insert(cUnit->combinedMappingTable.end(),
+ cUnit->dex2pcMappingTable.begin(),
+ cUnit->dex2pcMappingTable.end());
}
class NativePcToReferenceMapBuilder {
@@ -844,7 +866,7 @@
};
static void createNativeGcMap(CompilationUnit* cUnit) {
- const std::vector<uint32_t>& mapping_table = cUnit->mappingTable;
+ const std::vector<uint32_t>& mapping_table = cUnit->pc2dexMappingTable;
uint32_t max_native_offset = 0;
for (size_t i = 0; i < mapping_table.size(); i += 2) {
uint32_t native_offset = mapping_table[i + 0];
@@ -864,13 +886,8 @@
uint32_t native_offset = mapping_table[i + 0];
uint32_t dex_pc = mapping_table[i + 1];
const uint8_t* references = dex_gc_map.FindBitMap(dex_pc, false);
- if (references != NULL) {
- native_gc_map_builder.AddEntry(native_offset, references);
- } else {
- // TODO: there is a mapping table entry but no reference bitmap. This happens because of
- // catch block entries. We should check that the dex_pc corresponds with a catch block
- // here.
- }
+ CHECK(references != NULL) << "Missing ref for dex pc 0x" << std::hex << dex_pc;
+ native_gc_map_builder.AddEntry(native_offset, references);
}
}
@@ -981,7 +998,7 @@
installFillArrayData(cUnit);
// Create the mapping table and native offset to reference map.
- createMappingTable(cUnit);
+ createMappingTables(cUnit);
createNativeGcMap(cUnit);
}
diff --git a/src/compiler/codegen/MethodBitcode.cc b/src/compiler/codegen/MethodBitcode.cc
index 682de7a..cff4ee5 100644
--- a/src/compiler/codegen/MethodBitcode.cc
+++ b/src/compiler/codegen/MethodBitcode.cc
@@ -2891,7 +2891,7 @@
LIR* headLIR = NULL;
if (blockType == kCatchBlock) {
- headLIR = newLIR0(cUnit, kPseudoSafepointPC);
+ headLIR = newLIR0(cUnit, kPseudoExportedPC);
}
// Free temp registers and reset redundant store tracking */
diff --git a/src/compiler/codegen/MethodCodegenDriver.cc b/src/compiler/codegen/MethodCodegenDriver.cc
index 7227487..3a80d10 100644
--- a/src/compiler/codegen/MethodCodegenDriver.cc
+++ b/src/compiler/codegen/MethodCodegenDriver.cc
@@ -870,9 +870,9 @@
LIR* headLIR = NULL;
- /* If this is a catch block, mark the beginning as a safepoint */
+ /* If this is a catch block, export the start address */
if (bb->catchEntry) {
- headLIR = newLIR0(cUnit, kPseudoSafepointPC);
+ headLIR = newLIR0(cUnit, kPseudoExportedPC);
}
/* Free temp registers and reset redundant store tracking */
diff --git a/src/compiler/codegen/arm/ArmLIR.h b/src/compiler/codegen/arm/ArmLIR.h
index 36a11f2..a40df20 100644
--- a/src/compiler/codegen/arm/ArmLIR.h
+++ b/src/compiler/codegen/arm/ArmLIR.h
@@ -291,6 +291,7 @@
* Assemble.cc.
*/
enum ArmOpcode {
+ kPseudoExportedPC = -18,
kPseudoSafepointPC = -17,
kPseudoIntrinsicRetry = -16,
kPseudoSuspendTarget = -15,
diff --git a/src/compiler/codegen/mips/MipsLIR.h b/src/compiler/codegen/mips/MipsLIR.h
index c78cd8d..0f6226f 100644
--- a/src/compiler/codegen/mips/MipsLIR.h
+++ b/src/compiler/codegen/mips/MipsLIR.h
@@ -333,6 +333,7 @@
* Assemble.cc.
*/
enum MipsOpCode {
+ kPseudoExportedPC = -18,
kPseudoSafepointPC = -17,
kPseudoIntrinsicRetry = -16,
kPseudoSuspendTarget = -15,
diff --git a/src/compiler/codegen/x86/X86LIR.h b/src/compiler/codegen/x86/X86LIR.h
index 43fc63c..d3e3da8 100644
--- a/src/compiler/codegen/x86/X86LIR.h
+++ b/src/compiler/codegen/x86/X86LIR.h
@@ -297,6 +297,7 @@
* Assemble.cc.
*/
enum X86OpCode {
+ kPseudoExportedPC = -18,
kPseudoSafepointPC = -17,
kPseudoIntrinsicRetry = -16,
kPseudoSuspendTarget = -15,