From 132d8363bf8cb043d910836672192ec8c36649b6 Mon Sep 17 00:00:00 2001 From: Nicolas Geoffray Date: Wed, 16 Nov 2016 09:19:42 +0000 Subject: Revert "Revert "Revert "Revert "JIT root tables."""" Test: 626-set-resolved-string, test-art-host, test-art-target Test: run-libcore-tests.sh Test: phone boots and runs This reverts commit 3395fbc20bcd20948bec8958db91b304c17cacd8. Change-Id: I104b73d093e3eb6a271d564cfdb9ab09c1c8cf24 --- compiler/optimizing/code_generator.cc | 29 ++++++++++++++++ compiler/optimizing/code_generator.h | 45 ++++++++++++++++++++++++ compiler/optimizing/code_generator_arm.cc | 44 ++++++++++++++++++++---- compiler/optimizing/code_generator_arm.h | 15 +++++--- compiler/optimizing/code_generator_arm64.cc | 51 +++++++++++++++++++++++----- compiler/optimizing/code_generator_arm64.h | 15 +++++--- compiler/optimizing/code_generator_mips.cc | 5 +++ compiler/optimizing/code_generator_x86.cc | 42 +++++++++++++++++++---- compiler/optimizing/code_generator_x86.h | 6 ++++ compiler/optimizing/code_generator_x86_64.cc | 43 +++++++++++++++++++---- compiler/optimizing/code_generator_x86_64.h | 6 ++++ compiler/optimizing/nodes.h | 11 ++++-- compiler/optimizing/optimizing_compiler.cc | 30 +++++++++++++--- compiler/optimizing/sharpening.cc | 16 ++++++--- 14 files changed, 309 insertions(+), 49 deletions(-) (limited to 'compiler/optimizing') diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc index 8b450e11dc..9f6b78a82c 100644 --- a/compiler/optimizing/code_generator.cc +++ b/compiler/optimizing/code_generator.cc @@ -1375,4 +1375,33 @@ uint32_t CodeGenerator::GetReferenceDisableFlagOffset() const { return klass->GetDisableIntrinsicFlagOffset().Uint32Value(); } +void CodeGenerator::EmitJitRoots(uint8_t* code, + Handle> roots, + const uint8_t* roots_data, + Handle outer_dex_cache) { + DCHECK_EQ(static_cast(roots->GetLength()), GetNumberOfJitRoots()); + StackHandleScope<1> hs(Thread::Current()); + MutableHandle h_dex_cache(hs.NewHandle(nullptr)); + ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); + size_t index = 0; + for (auto& entry : jit_string_roots_) { + const DexFile& entry_dex_file = *entry.first.dex_file; + // Avoid the expensive FindDexCache call by checking if the string is + // in the compiled method's dex file. + h_dex_cache.Assign(IsSameDexFile(*outer_dex_cache->GetDexFile(), entry_dex_file) + ? outer_dex_cache.Get() + : class_linker->FindDexCache(hs.Self(), entry_dex_file)); + mirror::String* string = class_linker->LookupString( + entry_dex_file, entry.first.string_index, h_dex_cache); + DCHECK(string != nullptr) << "JIT roots require strings to have been loaded"; + // Ensure the string is strongly interned. This is a requirement on how the JIT + // handles strings. b/32995596 + class_linker->GetInternTable()->InternStrong(string); + roots->Set(index, string); + entry.second = index; + ++index; + } + EmitJitRootPatches(code, roots_data); +} + } // namespace art diff --git a/compiler/optimizing/code_generator.h b/compiler/optimizing/code_generator.h index bf246ad309..a5d19abe92 100644 --- a/compiler/optimizing/code_generator.h +++ b/compiler/optimizing/code_generator.h @@ -32,6 +32,7 @@ #include "optimizing_compiler_stats.h" #include "read_barrier_option.h" #include "stack_map_stream.h" +#include "string_reference.h" #include "utils/label.h" namespace art { @@ -335,6 +336,17 @@ class CodeGenerator : public DeletableArenaObject { void BuildStackMaps(MemoryRegion region, const DexFile::CodeItem& code_item); size_t ComputeStackMapsSize(); + size_t GetNumberOfJitRoots() const { + return jit_string_roots_.size(); + } + + // Fills the `literals` array with literals collected during code generation. + // Also emits literal patches. + void EmitJitRoots(uint8_t* code, + Handle> roots, + const uint8_t* roots_data, + Handle outer_dex_cache) + REQUIRES_SHARED(Locks::mutator_lock_); bool IsLeafMethod() const { return is_leaf_; @@ -515,6 +527,26 @@ class CodeGenerator : public DeletableArenaObject { virtual HLoadClass::LoadKind GetSupportedLoadClassKind( HLoadClass::LoadKind desired_class_load_kind) = 0; + static LocationSummary::CallKind GetLoadStringCallKind(HLoadString* load) { + switch (load->GetLoadKind()) { + case HLoadString::LoadKind::kBssEntry: + DCHECK(load->NeedsEnvironment()); + return LocationSummary::kCallOnSlowPath; + case HLoadString::LoadKind::kDexCacheViaMethod: + DCHECK(load->NeedsEnvironment()); + return LocationSummary::kCallOnMainOnly; + case HLoadString::LoadKind::kJitTableAddress: + DCHECK(!load->NeedsEnvironment()); + return kEmitCompilerReadBarrier + ? LocationSummary::kCallOnSlowPath + : LocationSummary::kNoCall; + break; + default: + DCHECK(!load->NeedsEnvironment()); + return LocationSummary::kNoCall; + } + } + // Check if the desired_dispatch_info is supported. If it is, return it, // otherwise return a fall-back info that should be used instead. virtual HInvokeStaticOrDirect::DispatchInfo GetSupportedInvokeStaticOrDirectDispatch( @@ -571,6 +603,8 @@ class CodeGenerator : public DeletableArenaObject { fpu_callee_save_mask_(fpu_callee_save_mask), stack_map_stream_(graph->GetArena()), block_order_(nullptr), + jit_string_roots_(StringReferenceValueComparator(), + graph->GetArena()->Adapter(kArenaAllocCodeGenerator)), disasm_info_(nullptr), stats_(stats), graph_(graph), @@ -637,6 +671,12 @@ class CodeGenerator : public DeletableArenaObject { return current_slow_path_; } + // Emit the patches assocatied with JIT roots. Only applies to JIT compiled code. + virtual void EmitJitRootPatches(uint8_t* code ATTRIBUTE_UNUSED, + const uint8_t* roots_data ATTRIBUTE_UNUSED) { + DCHECK_EQ(jit_string_roots_.size(), 0u); + } + // Frame size required for this method. uint32_t frame_size_; uint32_t core_spill_mask_; @@ -662,6 +702,11 @@ class CodeGenerator : public DeletableArenaObject { // The order to use for code generation. const ArenaVector* block_order_; + // Maps a StringReference (dex_file, string_index) to the index in the literal table. + // Entries are intially added with a 0 index, and `EmitJitRoots` will compute all the + // indices. + ArenaSafeMap jit_string_roots_; + DisassemblyInformation* disasm_info_; private: diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc index c6363d1708..9725a166f1 100644 --- a/compiler/optimizing/code_generator_arm.cc +++ b/compiler/optimizing/code_generator_arm.cc @@ -1214,7 +1214,9 @@ CodeGeneratorARM::CodeGeneratorARM(HGraph* graph, graph->GetArena()->Adapter(kArenaAllocCodeGenerator)), pc_relative_type_patches_(graph->GetArena()->Adapter(kArenaAllocCodeGenerator)), boot_image_address_patches_(std::less(), - graph->GetArena()->Adapter(kArenaAllocCodeGenerator)) { + graph->GetArena()->Adapter(kArenaAllocCodeGenerator)), + jit_string_patches_(StringReferenceValueComparator(), + graph->GetArena()->Adapter(kArenaAllocCodeGenerator)) { // Always save the LR register to mimic Quick. AddAllocatedRegister(Location::RegisterLocation(LR)); } @@ -5893,6 +5895,9 @@ HLoadString::LoadKind CodeGeneratorARM::GetSupportedLoadStringKind( case HLoadString::LoadKind::kBssEntry: DCHECK(!Runtime::Current()->UseJitCompilation()); break; + case HLoadString::LoadKind::kJitTableAddress: + DCHECK(Runtime::Current()->UseJitCompilation()); + break; case HLoadString::LoadKind::kDexCacheViaMethod: break; } @@ -5900,13 +5905,8 @@ HLoadString::LoadKind CodeGeneratorARM::GetSupportedLoadStringKind( } void LocationsBuilderARM::VisitLoadString(HLoadString* load) { - LocationSummary::CallKind call_kind = load->NeedsEnvironment() - ? ((load->GetLoadKind() == HLoadString::LoadKind::kDexCacheViaMethod) - ? LocationSummary::kCallOnMainOnly - : LocationSummary::kCallOnSlowPath) - : LocationSummary::kNoCall; + LocationSummary::CallKind call_kind = CodeGenerator::GetLoadStringCallKind(load); LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(load, call_kind); - HLoadString::LoadKind load_kind = load->GetLoadKind(); if (load_kind == HLoadString::LoadKind::kDexCacheViaMethod) { locations->SetOut(Location::RegisterLocation(R0)); @@ -5979,6 +5979,13 @@ void InstructionCodeGeneratorARM::VisitLoadString(HLoadString* load) { __ Bind(slow_path->GetExitLabel()); return; } + case HLoadString::LoadKind::kJitTableAddress: { + __ LoadLiteral(out, codegen_->DeduplicateJitStringLiteral(load->GetDexFile(), + load->GetStringIndex())); + // /* GcRoot */ out = *out + GenerateGcRootFieldLoad(load, out_loc, out, /* offset */ 0, kCompilerReadBarrierOption); + return; + } default: break; } @@ -7359,6 +7366,14 @@ Literal* CodeGeneratorARM::DeduplicateDexCacheAddressLiteral(uint32_t address) { return DeduplicateUint32Literal(address, &uint32_literals_); } +Literal* CodeGeneratorARM::DeduplicateJitStringLiteral(const DexFile& dex_file, + uint32_t string_index) { + jit_string_roots_.Overwrite(StringReference(&dex_file, string_index), /* placeholder */ 0u); + return jit_string_patches_.GetOrCreate( + StringReference(&dex_file, string_index), + [this]() { return __ NewLiteral(/* placeholder */ 0u); }); +} + template inline void CodeGeneratorARM::EmitPcRelativeLinkerPatches( const ArenaDeque& infos, @@ -7675,6 +7690,21 @@ void InstructionCodeGeneratorARM::VisitClassTableGet(HClassTableGet* instruction } } +void CodeGeneratorARM::EmitJitRootPatches(uint8_t* code, const uint8_t* roots_data) { + for (const auto& entry : jit_string_patches_) { + const auto& it = jit_string_roots_.find(entry.first); + DCHECK(it != jit_string_roots_.end()); + size_t index_in_table = it->second; + Literal* literal = entry.second; + DCHECK(literal->GetLabel()->IsBound()); + uint32_t literal_offset = literal->GetLabel()->Position(); + uintptr_t address = + reinterpret_cast(roots_data) + index_in_table * sizeof(GcRoot); + uint8_t* data = code + literal_offset; + reinterpret_cast(data)[0] = dchecked_integral_cast(address); + } +} + #undef __ #undef QUICK_ENTRY_POINT diff --git a/compiler/optimizing/code_generator_arm.h b/compiler/optimizing/code_generator_arm.h index f95dd573cb..8ace3dac08 100644 --- a/compiler/optimizing/code_generator_arm.h +++ b/compiler/optimizing/code_generator_arm.h @@ -488,9 +488,12 @@ class CodeGeneratorARM : public CodeGenerator { Literal* DeduplicateBootImageTypeLiteral(const DexFile& dex_file, uint32_t type_index); Literal* DeduplicateBootImageAddressLiteral(uint32_t address); Literal* DeduplicateDexCacheAddressLiteral(uint32_t address); + Literal* DeduplicateJitStringLiteral(const DexFile& dex_file, uint32_t string_index); void EmitLinkerPatches(ArenaVector* linker_patches) OVERRIDE; + void EmitJitRootPatches(uint8_t* code, const uint8_t* roots_data) OVERRIDE; + // Fast path implementation of ReadBarrier::Barrier for a heap // reference field load when Baker's read barriers are used. void GenerateFieldLoadWithBakerReadBarrier(HInstruction* instruction, @@ -591,9 +594,9 @@ class CodeGeneratorARM : public CodeGenerator { using Uint32ToLiteralMap = ArenaSafeMap; using MethodToLiteralMap = ArenaSafeMap; - using BootStringToLiteralMap = ArenaSafeMap; + using StringToLiteralMap = ArenaSafeMap; using BootTypeToLiteralMap = ArenaSafeMap; @@ -605,7 +608,6 @@ class CodeGeneratorARM : public CodeGenerator { PcRelativePatchInfo* NewPcRelativePatch(const DexFile& dex_file, uint32_t offset_or_index, ArenaDeque* patches); - template static void EmitPcRelativeLinkerPatches(const ArenaDeque& infos, ArenaVector* linker_patches); @@ -630,7 +632,7 @@ class CodeGeneratorARM : public CodeGenerator { // PC-relative patch info for each HArmDexCacheArraysBase. ArenaDeque pc_relative_dex_cache_patches_; // Deduplication map for boot string literals for kBootImageLinkTimeAddress. - BootStringToLiteralMap boot_image_string_patches_; + StringToLiteralMap boot_image_string_patches_; // PC-relative String patch info; type depends on configuration (app .bss or boot image PIC). ArenaDeque pc_relative_string_patches_; // Deduplication map for boot type literals for kBootImageLinkTimeAddress. @@ -640,6 +642,9 @@ class CodeGeneratorARM : public CodeGenerator { // Deduplication map for patchable boot image addresses. Uint32ToLiteralMap boot_image_address_patches_; + // Patches for string literals in JIT compiled code. + StringToLiteralMap jit_string_patches_; + DISALLOW_COPY_AND_ASSIGN(CodeGeneratorARM); }; diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc index 4ab6065819..2b575f76c5 100644 --- a/compiler/optimizing/code_generator_arm64.cc +++ b/compiler/optimizing/code_generator_arm64.cc @@ -1158,7 +1158,9 @@ CodeGeneratorARM64::CodeGeneratorARM64(HGraph* graph, graph->GetArena()->Adapter(kArenaAllocCodeGenerator)), pc_relative_type_patches_(graph->GetArena()->Adapter(kArenaAllocCodeGenerator)), boot_image_address_patches_(std::less(), - graph->GetArena()->Adapter(kArenaAllocCodeGenerator)) { + graph->GetArena()->Adapter(kArenaAllocCodeGenerator)), + jit_string_patches_(StringReferenceValueComparator(), + graph->GetArena()->Adapter(kArenaAllocCodeGenerator)) { // Save the link register (containing the return address) to mimic Quick. AddAllocatedRegister(LocationFrom(lr)); } @@ -4155,6 +4157,14 @@ vixl::aarch64::Literal* CodeGeneratorARM64::DeduplicateDexCacheAddress return DeduplicateUint64Literal(address); } +vixl::aarch64::Literal* CodeGeneratorARM64::DeduplicateJitStringLiteral( + const DexFile& dex_file, uint32_t string_index) { + jit_string_roots_.Overwrite(StringReference(&dex_file, string_index), /* placeholder */ 0u); + return jit_string_patches_.GetOrCreate( + StringReference(&dex_file, string_index), + [this]() { return __ CreateLiteralDestroyedWithPool(/* placeholder */ 0u); }); +} + void CodeGeneratorARM64::EmitAdrpPlaceholder(vixl::aarch64::Label* fixup_label, vixl::aarch64::Register reg) { DCHECK(reg.IsX()); @@ -4540,16 +4550,15 @@ HLoadString::LoadKind CodeGeneratorARM64::GetSupportedLoadStringKind( break; case HLoadString::LoadKind::kDexCacheViaMethod: break; + case HLoadString::LoadKind::kJitTableAddress: + DCHECK(Runtime::Current()->UseJitCompilation()); + break; } return desired_string_load_kind; } void LocationsBuilderARM64::VisitLoadString(HLoadString* load) { - LocationSummary::CallKind call_kind = load->NeedsEnvironment() - ? ((load->GetLoadKind() == HLoadString::LoadKind::kDexCacheViaMethod) - ? LocationSummary::kCallOnMainOnly - : LocationSummary::kCallOnSlowPath) - : LocationSummary::kNoCall; + LocationSummary::CallKind call_kind = CodeGenerator::GetLoadStringCallKind(load); LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(load, call_kind); if (load->GetLoadKind() == HLoadString::LoadKind::kDexCacheViaMethod) { InvokeRuntimeCallingConvention calling_convention; @@ -4575,6 +4584,7 @@ void LocationsBuilderARM64::VisitLoadString(HLoadString* load) { void InstructionCodeGeneratorARM64::VisitLoadString(HLoadString* load) { Register out = OutputRegister(load); + Location out_loc = load->GetLocations()->Out(); switch (load->GetLoadKind()) { case HLoadString::LoadKind::kBootImageLinkTimeAddress: @@ -4611,9 +4621,9 @@ void InstructionCodeGeneratorARM64::VisitLoadString(HLoadString* load) { // Add LDR with its PC-relative String patch. vixl::aarch64::Label* ldr_label = codegen_->NewPcRelativeStringPatch(dex_file, string_index, adrp_label); - // /* GcRoot */ out = *(base_address + offset) /* PC-relative */ + // /* GcRoot */ out = *(base_address + offset) /* PC-relative */ GenerateGcRootFieldLoad(load, - load->GetLocations()->Out(), + out_loc, temp, /* offset placeholder */ 0u, ldr_label, @@ -4625,6 +4635,17 @@ void InstructionCodeGeneratorARM64::VisitLoadString(HLoadString* load) { __ Bind(slow_path->GetExitLabel()); return; } + case HLoadString::LoadKind::kJitTableAddress: { + __ Ldr(out, codegen_->DeduplicateJitStringLiteral(load->GetDexFile(), + load->GetStringIndex())); + GenerateGcRootFieldLoad(load, + out_loc, + out.X(), + /* offset */ 0, + /* fixup_label */ nullptr, + kCompilerReadBarrierOption); + return; + } default: break; } @@ -5744,7 +5765,19 @@ void InstructionCodeGeneratorARM64::VisitClassTableGet(HClassTableGet* instructi } } - +void CodeGeneratorARM64::EmitJitRootPatches(uint8_t* code, const uint8_t* roots_data) { + for (const auto& entry : jit_string_patches_) { + const auto& it = jit_string_roots_.find(entry.first); + DCHECK(it != jit_string_roots_.end()); + size_t index_in_table = it->second; + vixl::aarch64::Literal* literal = entry.second; + uint32_t literal_offset = literal->GetOffset(); + uintptr_t address = + reinterpret_cast(roots_data) + index_in_table * sizeof(GcRoot); + uint8_t* data = code + literal_offset; + reinterpret_cast(data)[0] = dchecked_integral_cast(address); + } +} #undef __ #undef QUICK_ENTRY_POINT diff --git a/compiler/optimizing/code_generator_arm64.h b/compiler/optimizing/code_generator_arm64.h index 0e8d4fd549..a2ab60709f 100644 --- a/compiler/optimizing/code_generator_arm64.h +++ b/compiler/optimizing/code_generator_arm64.h @@ -565,6 +565,8 @@ class CodeGeneratorARM64 : public CodeGenerator { uint32_t type_index); vixl::aarch64::Literal* DeduplicateBootImageAddressLiteral(uint64_t address); vixl::aarch64::Literal* DeduplicateDexCacheAddressLiteral(uint64_t address); + vixl::aarch64::Literal* DeduplicateJitStringLiteral(const DexFile& dex_file, + uint32_t string_index); void EmitAdrpPlaceholder(vixl::aarch64::Label* fixup_label, vixl::aarch64::Register reg); void EmitAddPlaceholder(vixl::aarch64::Label* fixup_label, @@ -576,6 +578,8 @@ class CodeGeneratorARM64 : public CodeGenerator { void EmitLinkerPatches(ArenaVector* linker_patches) OVERRIDE; + void EmitJitRootPatches(uint8_t* code, const uint8_t* roots_data) OVERRIDE; + // Fast path implementation of ReadBarrier::Barrier for a heap // reference field load when Baker's read barriers are used. void GenerateFieldLoadWithBakerReadBarrier(HInstruction* instruction, @@ -673,9 +677,9 @@ class CodeGeneratorARM64 : public CodeGenerator { using MethodToLiteralMap = ArenaSafeMap*, MethodReferenceComparator>; - using BootStringToLiteralMap = ArenaSafeMap*, - StringReferenceValueComparator>; + using StringToLiteralMap = ArenaSafeMap*, + StringReferenceValueComparator>; using BootTypeToLiteralMap = ArenaSafeMap*, TypeReferenceValueComparator>; @@ -739,7 +743,7 @@ class CodeGeneratorARM64 : public CodeGenerator { // PC-relative DexCache access info. ArenaDeque pc_relative_dex_cache_patches_; // Deduplication map for boot string literals for kBootImageLinkTimeAddress. - BootStringToLiteralMap boot_image_string_patches_; + StringToLiteralMap boot_image_string_patches_; // PC-relative String patch info; type depends on configuration (app .bss or boot image PIC). ArenaDeque pc_relative_string_patches_; // Deduplication map for boot type literals for kBootImageLinkTimeAddress. @@ -749,6 +753,9 @@ class CodeGeneratorARM64 : public CodeGenerator { // Deduplication map for patchable boot image addresses. Uint32ToLiteralMap boot_image_address_patches_; + // Patches for string literals in JIT compiled code. + StringToLiteralMap jit_string_patches_; + DISALLOW_COPY_AND_ASSIGN(CodeGeneratorARM64); }; diff --git a/compiler/optimizing/code_generator_mips.cc b/compiler/optimizing/code_generator_mips.cc index 573bb507f2..fcbb8f03ad 100644 --- a/compiler/optimizing/code_generator_mips.cc +++ b/compiler/optimizing/code_generator_mips.cc @@ -5207,6 +5207,11 @@ HLoadString::LoadKind CodeGeneratorMIPS::GetSupportedLoadStringKind( case HLoadString::LoadKind::kDexCacheViaMethod: fallback_load = false; break; + case HLoadString::LoadKind::kJitTableAddress: + DCHECK(Runtime::Current()->UseJitCompilation()); + // TODO: implement. + fallback_load = true; + break; } if (fallback_load) { desired_string_load_kind = HLoadString::LoadKind::kDexCacheViaMethod; diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc index 2451b8d247..5997b42156 100644 --- a/compiler/optimizing/code_generator_x86.cc +++ b/compiler/optimizing/code_generator_x86.cc @@ -1012,6 +1012,7 @@ CodeGeneratorX86::CodeGeneratorX86(HGraph* graph, simple_patches_(graph->GetArena()->Adapter(kArenaAllocCodeGenerator)), string_patches_(graph->GetArena()->Adapter(kArenaAllocCodeGenerator)), type_patches_(graph->GetArena()->Adapter(kArenaAllocCodeGenerator)), + jit_string_patches_(graph->GetArena()->Adapter(kArenaAllocCodeGenerator)), constant_area_start_(-1), fixups_to_jump_tables_(graph->GetArena()->Adapter(kArenaAllocCodeGenerator)), method_address_offset_(-1) { @@ -6218,16 +6219,15 @@ HLoadString::LoadKind CodeGeneratorX86::GetSupportedLoadStringKind( break; case HLoadString::LoadKind::kDexCacheViaMethod: break; + case HLoadString::LoadKind::kJitTableAddress: + DCHECK(Runtime::Current()->UseJitCompilation()); + break; } return desired_string_load_kind; } void LocationsBuilderX86::VisitLoadString(HLoadString* load) { - LocationSummary::CallKind call_kind = (load->NeedsEnvironment() || kEmitCompilerReadBarrier) - ? ((load->GetLoadKind() == HLoadString::LoadKind::kDexCacheViaMethod) - ? LocationSummary::kCallOnMainOnly - : LocationSummary::kCallOnSlowPath) - : LocationSummary::kNoCall; + LocationSummary::CallKind call_kind = CodeGenerator::GetLoadStringCallKind(load); LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(load, call_kind); HLoadString::LoadKind load_kind = load->GetLoadKind(); if (load_kind == HLoadString::LoadKind::kBootImageLinkTimePcRelative || @@ -6252,6 +6252,14 @@ void LocationsBuilderX86::VisitLoadString(HLoadString* load) { } } +Label* CodeGeneratorX86::NewJitRootStringPatch(const DexFile& dex_file, uint32_t dex_index) { + jit_string_roots_.Overwrite(StringReference(&dex_file, dex_index), /* placeholder */ 0u); + // Add a patch entry and return the label. + jit_string_patches_.emplace_back(dex_file, dex_index); + PatchInfo