diff options
author | 2012-09-28 07:19:44 -0700 | |
---|---|---|
committer | 2012-09-28 15:41:57 -0700 | |
commit | a5b3024aed77a8204d5fb48ba7f763fb8c60fa76 (patch) | |
tree | d9b046896b73519302c8b54a97a3abfa8ecfdf4c | |
parent | a75a01313e801c53145df00bad1842d9f643c0a1 (diff) |
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
-rw-r--r-- | src/compiler/CompilerIR.h | 13 | ||||
-rw-r--r-- | src/compiler/Frontend.cc | 5 | ||||
-rw-r--r-- | src/compiler/codegen/CodegenUtil.cc | 73 | ||||
-rw-r--r-- | src/compiler/codegen/MethodBitcode.cc | 2 | ||||
-rw-r--r-- | src/compiler/codegen/MethodCodegenDriver.cc | 4 | ||||
-rw-r--r-- | src/compiler/codegen/arm/ArmLIR.h | 1 | ||||
-rw-r--r-- | src/compiler/codegen/mips/MipsLIR.h | 1 | ||||
-rw-r--r-- | src/compiler/codegen/x86/X86LIR.h | 1 | ||||
-rw-r--r-- | src/exception_test.cc | 8 | ||||
-rw-r--r-- | src/oatdump.cc | 7 | ||||
-rw-r--r-- | src/object.cc | 34 | ||||
-rw-r--r-- | src/object.h | 34 | ||||
-rw-r--r-- | test/ReferenceMap/stack_walk_refmap_jni.cc | 36 |
13 files changed, 157 insertions, 62 deletions
diff --git a/src/compiler/CompilerIR.h b/src/compiler/CompilerIR.h index 56ae4867c3..434320d2e7 100644 --- a/src/compiler/CompilerIR.h +++ b/src/compiler/CompilerIR.h @@ -426,7 +426,18 @@ struct CompilationUnit { 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 31d8aa50a9..09bc054e5e 100644 --- a/src/compiler/Frontend.cc +++ b/src/compiler/Frontend.cc @@ -1216,9 +1216,8 @@ CompiledMethod* compileMethod(Compiler& compiler, } 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 4e39ffcdf8..22aacc2497 100644 --- a/src/compiler/codegen/CodegenUtil.cc +++ b/src/compiler/codegen/CodegenUtil.cc @@ -341,6 +341,9 @@ void oatDumpLIRInsn(CompilationUnit* cUnit, LIR* arg, unsigned char* baseAddr) 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 @@ void oatDumpPromotionMap(CompilationUnit *cUnit) } } +/* 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 @@ void oatCodegenDump(CompilationUnit* cUnit) 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 @@ LIR* rawLIR(CompilationUnit* cUnit, int dalvikOffset, int opcode, int op0, 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 @@ int assignLiteralOffsetCommon(LIR* lir, int offset) 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 @@ class NativePcToReferenceMapBuilder { }; 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 @@ static void createNativeGcMap(CompilationUnit* cUnit) { 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 @@ void oatAssembleLIR(CompilationUnit* cUnit) 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 682de7ad6a..cff4ee5112 100644 --- a/src/compiler/codegen/MethodBitcode.cc +++ b/src/compiler/codegen/MethodBitcode.cc @@ -2891,7 +2891,7 @@ bool methodBitcodeBlockCodeGen(CompilationUnit* cUnit, llvm::BasicBlock* bb) 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 7227487db9..3a80d1063c 100644 --- a/src/compiler/codegen/MethodCodegenDriver.cc +++ b/src/compiler/codegen/MethodCodegenDriver.cc @@ -870,9 +870,9 @@ bool methodBlockCodeGen(CompilationUnit* cUnit, BasicBlock* bb) 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 36a11f22f9..a40df20b8e 100644 --- a/src/compiler/codegen/arm/ArmLIR.h +++ b/src/compiler/codegen/arm/ArmLIR.h @@ -291,6 +291,7 @@ enum ArmConditionCode { * 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 c78cd8dc1c..0f6226f963 100644 --- a/src/compiler/codegen/mips/MipsLIR.h +++ b/src/compiler/codegen/mips/MipsLIR.h @@ -333,6 +333,7 @@ enum MipsShiftEncodings { * 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 43fc63c48f..d3e3da8d6d 100644 --- a/src/compiler/codegen/x86/X86LIR.h +++ b/src/compiler/codegen/x86/X86LIR.h @@ -297,6 +297,7 @@ enum X86ConditionCode { * Assemble.cc. */ enum X86OpCode { + kPseudoExportedPC = -18, kPseudoSafepointPC = -17, kPseudoIntrinsicRetry = -16, kPseudoSuspendTarget = -15, diff --git a/src/exception_test.cc b/src/exception_test.cc index 7303ac6615..b82f8f785c 100644 --- a/src/exception_test.cc +++ b/src/exception_test.cc @@ -47,7 +47,13 @@ class ExceptionTest : public CommonTest { fake_code_.push_back(0x70 | i); } - fake_mapping_data_.push_back(2); // first element is count of remaining elements + fake_mapping_data_.push_back(4); // first element is count + fake_mapping_data_.push_back(4); // total (non-length) elements + fake_mapping_data_.push_back(2); // count of pc to dex elements + // --- pc to dex table + fake_mapping_data_.push_back(3); // offset 3 + fake_mapping_data_.push_back(3); // maps to dex offset 3 + // --- dex to pc table fake_mapping_data_.push_back(3); // offset 3 fake_mapping_data_.push_back(3); // maps to dex offset 3 diff --git a/src/oatdump.cc b/src/oatdump.cc index f08a4984fd..c35d233069 100644 --- a/src/oatdump.cc +++ b/src/oatdump.cc @@ -423,13 +423,18 @@ class OatDumper { uint32_t length = *raw_table; ++raw_table; + uint32_t pc_to_dex_entries = *raw_table; + ++raw_table; os << "\t\t{"; for (size_t i = 0; i < length; i += 2) { const uint8_t* native_pc = reinterpret_cast<const uint8_t*>(code) + raw_table[i]; uint32_t dex_pc = raw_table[i + 1]; os << StringPrintf("%p -> 0x%04x", native_pc, dex_pc); - if (i + 2 < length) { + if (i + 2 == pc_to_dex_entries) { + // Separate the pc -> dex from dex -> pc sections + os << "}\n\t\t{"; + } else if (i + 2 < length) { os << ", "; } } diff --git a/src/object.cc b/src/object.cc index 284f221720..90342ffd3f 100644 --- a/src/object.cc +++ b/src/object.cc @@ -514,14 +514,37 @@ uintptr_t AbstractMethod::NativePcOffset(const uintptr_t pc) const { return pc - reinterpret_cast<uintptr_t>(GetOatCode(this)); } +// Find the lowest-address native safepoint pc for a given dex pc +uint32_t AbstractMethod::ToFirstNativeSafepointPc(const uintptr_t dex_pc) const { +#if !defined(ART_USE_LLVM_COMPILER) + const uint32_t* mapping_table = GetPcToDexMappingTable(); + if (mapping_table == NULL) { + DCHECK(IsNative() || IsCalleeSaveMethod() || IsProxyMethod()) << PrettyMethod(this); + return DexFile::kDexNoIndex; // Special no mapping case + } + size_t mapping_table_length = GetPcToDexMappingTableLength(); + for (size_t i = 0; i < mapping_table_length; i += 2) { + if (mapping_table[i + 1] == dex_pc) { + return mapping_table[i] + reinterpret_cast<uintptr_t>(GetOatCode(this)); + } + } + LOG(FATAL) << "Failed to find native offset for dex pc 0x" << std::hex << dex_pc + << " in " << PrettyMethod(this); + return 0; +#else + // Compiler LLVM doesn't use the machine pc, we just use dex pc instead. + return static_cast<uint32_t>(dex_pc); +#endif +} + uint32_t AbstractMethod::ToDexPc(const uintptr_t pc) const { #if !defined(ART_USE_LLVM_COMPILER) - const uint32_t* mapping_table = GetMappingTable(); + const uint32_t* mapping_table = GetPcToDexMappingTable(); if (mapping_table == NULL) { DCHECK(IsNative() || IsCalleeSaveMethod() || IsProxyMethod()) << PrettyMethod(this); return DexFile::kDexNoIndex; // Special no mapping case } - size_t mapping_table_length = GetMappingTableLength(); + size_t mapping_table_length = GetPcToDexMappingTableLength(); uint32_t sought_offset = pc - reinterpret_cast<uintptr_t>(GetOatCode(this)); for (size_t i = 0; i < mapping_table_length; i += 2) { if (mapping_table[i] == sought_offset) { @@ -538,12 +561,12 @@ uint32_t AbstractMethod::ToDexPc(const uintptr_t pc) const { } uintptr_t AbstractMethod::ToNativePc(const uint32_t dex_pc) const { - const uint32_t* mapping_table = GetMappingTable(); + const uint32_t* mapping_table = GetDexToPcMappingTable(); if (mapping_table == NULL) { DCHECK_EQ(dex_pc, 0U); return 0; // Special no mapping/pc == 0 case } - size_t mapping_table_length = GetMappingTableLength(); + size_t mapping_table_length = GetDexToPcMappingTableLength(); for (size_t i = 0; i < mapping_table_length; i += 2) { uint32_t map_offset = mapping_table[i]; uint32_t map_dex_offset = mapping_table[i + 1]; @@ -551,7 +574,8 @@ uintptr_t AbstractMethod::ToNativePc(const uint32_t dex_pc) const { return reinterpret_cast<uintptr_t>(GetOatCode(this)) + map_offset; } } - LOG(FATAL) << "Looking up Dex PC not contained in method"; + LOG(FATAL) << "Looking up Dex PC not contained in method, 0x" << std::hex << dex_pc + << " in " << PrettyMethod(this); return 0; } diff --git a/src/object.h b/src/object.h index 947b77d35b..5fccb04079 100644 --- a/src/object.h +++ b/src/object.h @@ -729,14 +729,40 @@ class MANAGED AbstractMethod : public Object { return map + 1; } - uint32_t GetMappingTableLength() const { + uint32_t GetPcToDexMappingTableLength() const { const uint32_t* map = GetMappingTableRaw(); if (map == NULL) { return 0; } - return *map; + return map[2]; } + const uint32_t* GetPcToDexMappingTable() const { + const uint32_t* map = GetMappingTableRaw(); + if (map == NULL) { + return map; + } + return map + 3; + } + + + uint32_t GetDexToPcMappingTableLength() const { + const uint32_t* map = GetMappingTableRaw(); + if (map == NULL) { + return 0; + } + return map[1] - map[2]; + } + + const uint32_t* GetDexToPcMappingTable() const { + const uint32_t* map = GetMappingTableRaw(); + if (map == NULL) { + return map; + } + return map + 3 + map[2]; + } + + const uint32_t* GetMappingTableRaw() const { return GetFieldPtr<const uint32_t*>(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, mapping_table_), false); } @@ -922,6 +948,10 @@ class MANAGED AbstractMethod : public Object { // Converts a dex PC to a native PC. uintptr_t ToNativePc(const uint32_t dex_pc) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + // Converts a dex PC to the first corresponding safepoint PC. + uintptr_t ToFirstNativeSafepointPc(const uint32_t dex_pc) + const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + // Find the catch block for the given exception type and dex_pc uint32_t FindCatchBlock(Class* exception_type, uint32_t dex_pc) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); diff --git a/test/ReferenceMap/stack_walk_refmap_jni.cc b/test/ReferenceMap/stack_walk_refmap_jni.cc index 0b6cd7ebc2..a9dfbac9e2 100644 --- a/test/ReferenceMap/stack_walk_refmap_jni.cc +++ b/test/ReferenceMap/stack_walk_refmap_jni.cc @@ -75,31 +75,31 @@ struct ReferenceMap2Visitor : public StackVisitor { // we know the Dex registers with live reference values. Assert that what we // find is what is expected. if (m_name.compare("f") == 0) { - ref_bitmap = map.FindBitMap(m->NativePcOffset(m->ToNativePc(0x03U))); + ref_bitmap = map.FindBitMap(m->NativePcOffset(m->ToFirstNativeSafepointPc(0x03U))); CHECK(ref_bitmap); CHECK_REGS_CONTAIN_REFS(8); // v8: this - ref_bitmap = map.FindBitMap(m->NativePcOffset(m->ToNativePc(0x06U))); + ref_bitmap = map.FindBitMap(m->NativePcOffset(m->ToFirstNativeSafepointPc(0x06U))); CHECK(ref_bitmap); CHECK_REGS_CONTAIN_REFS(8, 1); // v8: this, v1: x - ref_bitmap = map.FindBitMap(m->NativePcOffset(m->ToNativePc(0x08U))); + ref_bitmap = map.FindBitMap(m->NativePcOffset(m->ToFirstNativeSafepointPc(0x08U))); CHECK(ref_bitmap); CHECK_REGS_CONTAIN_REFS(8, 3, 1); // v8: this, v3: y, v1: x - ref_bitmap = map.FindBitMap(m->NativePcOffset(m->ToNativePc(0x0cU))); + ref_bitmap = map.FindBitMap(m->NativePcOffset(m->ToFirstNativeSafepointPc(0x0cU))); CHECK(ref_bitmap); CHECK_REGS_CONTAIN_REFS(8, 3, 1); // v8: this, v3: y, v1: x - ref_bitmap = map.FindBitMap(m->NativePcOffset(m->ToNativePc(0x0eU))); + ref_bitmap = map.FindBitMap(m->NativePcOffset(m->ToFirstNativeSafepointPc(0x0eU))); CHECK(ref_bitmap); CHECK_REGS_CONTAIN_REFS(8, 3, 1); // v8: this, v3: y, v1: x - ref_bitmap = map.FindBitMap(m->NativePcOffset(m->ToNativePc(0x10U))); + ref_bitmap = map.FindBitMap(m->NativePcOffset(m->ToFirstNativeSafepointPc(0x10U))); CHECK(ref_bitmap); CHECK_REGS_CONTAIN_REFS(8, 3, 1); // v8: this, v3: y, v1: x - ref_bitmap = map.FindBitMap(m->NativePcOffset(m->ToNativePc(0x13U))); + ref_bitmap = map.FindBitMap(m->NativePcOffset(m->ToFirstNativeSafepointPc(0x13U))); CHECK(ref_bitmap); // v2 is added because of the instruction at DexPC 0024. Object merges with 0 is Object. See: // 0024: move-object v3, v2 @@ -107,49 +107,49 @@ struct ReferenceMap2Visitor : public StackVisitor { // Detaled dex instructions for ReferenceMap.java are at the end of this function. CHECK_REGS_CONTAIN_REFS(8, 3, 2, 1); // v8: this, v3: y, v2: y, v1: x - ref_bitmap = map.FindBitMap(m->NativePcOffset(m->ToNativePc(0x18U))); + ref_bitmap = map.FindBitMap(m->NativePcOffset(m->ToFirstNativeSafepointPc(0x18U))); CHECK(ref_bitmap); CHECK_REGS_CONTAIN_REFS(8, 2, 1, 0); // v8: this, v2: y, v1: x, v0: ex - ref_bitmap = map.FindBitMap(m->NativePcOffset(m->ToNativePc(0x1aU))); + ref_bitmap = map.FindBitMap(m->NativePcOffset(m->ToFirstNativeSafepointPc(0x1aU))); CHECK(ref_bitmap); CHECK_REGS_CONTAIN_REFS(8, 5, 2, 1, 0); // v8: this, v5: x[1], v2: y, v1: x, v0: ex - ref_bitmap = map.FindBitMap(m->NativePcOffset(m->ToNativePc(0x1dU))); + ref_bitmap = map.FindBitMap(m->NativePcOffset(m->ToFirstNativeSafepointPc(0x1dU))); CHECK(ref_bitmap); CHECK_REGS_CONTAIN_REFS(8, 5, 2, 1, 0); // v8: this, v5: x[1], v2: y, v1: x, v0: ex - ref_bitmap = map.FindBitMap(m->NativePcOffset(m->ToNativePc(0x1fU))); + ref_bitmap = map.FindBitMap(m->NativePcOffset(m->ToFirstNativeSafepointPc(0x1fU))); CHECK(ref_bitmap); // v5 is removed from the root set because there is a "merge" operation. // See 0015: if-nez v2, 001f. CHECK_REGS_CONTAIN_REFS(8, 2, 1, 0); // v8: this, v2: y, v1: x, v0: ex - ref_bitmap = map.FindBitMap(m->NativePcOffset(m->ToNativePc(0x21U))); + ref_bitmap = map.FindBitMap(m->NativePcOffset(m->ToFirstNativeSafepointPc(0x21U))); CHECK(ref_bitmap); CHECK_REGS_CONTAIN_REFS(8, 2, 1, 0); // v8: this, v2: y, v1: x, v0: ex - ref_bitmap = map.FindBitMap(m->NativePcOffset(m->ToNativePc(0x25U))); + ref_bitmap = map.FindBitMap(m->NativePcOffset(m->ToFirstNativeSafepointPc(0x25U))); CHECK(ref_bitmap); CHECK_REGS_CONTAIN_REFS(8, 3, 2, 1, 0); // v8: this, v3: y, v2: y, v1: x, v0: ex - ref_bitmap = map.FindBitMap(m->NativePcOffset(m->ToNativePc(0x27U))); + ref_bitmap = map.FindBitMap(m->NativePcOffset(m->ToFirstNativeSafepointPc(0x27U))); CHECK(ref_bitmap); CHECK_REGS_CONTAIN_REFS(8, 4, 2, 1); // v8: this, v4: ex, v2: y, v1: x - ref_bitmap = map.FindBitMap(m->NativePcOffset(m->ToNativePc(0x29U))); + ref_bitmap = map.FindBitMap(m->NativePcOffset(m->ToFirstNativeSafepointPc(0x29U))); CHECK(ref_bitmap); CHECK_REGS_CONTAIN_REFS(8, 4, 2, 1); // v8: this, v4: ex, v2: y, v1: x - ref_bitmap = map.FindBitMap(m->NativePcOffset(m->ToNativePc(0x2cU))); + ref_bitmap = map.FindBitMap(m->NativePcOffset(m->ToFirstNativeSafepointPc(0x2cU))); CHECK(ref_bitmap); CHECK_REGS_CONTAIN_REFS(8, 4, 2, 1); // v8: this, v4: ex, v2: y, v1: x - ref_bitmap = map.FindBitMap(m->NativePcOffset(m->ToNativePc(0x2fU))); + ref_bitmap = map.FindBitMap(m->NativePcOffset(m->ToFirstNativeSafepointPc(0x2fU))); CHECK(ref_bitmap); CHECK_REGS_CONTAIN_REFS(8, 4, 3, 2, 1); // v8: this, v4: ex, v3: y, v2: y, v1: x - ref_bitmap = map.FindBitMap(m->NativePcOffset(m->ToNativePc(0x32U))); + ref_bitmap = map.FindBitMap(m->NativePcOffset(m->ToFirstNativeSafepointPc(0x32U))); CHECK(ref_bitmap); CHECK_REGS_CONTAIN_REFS(8, 3, 2, 1, 0); // v8: this, v3: y, v2: y, v1: x, v0: ex } |