diff options
-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 } |