Revert "Revert "Store resolved Strings for AOT code in .bss.""
Fixed oat_test to keep dex files alive. Fixed mips build.
Rewritten the .bss GC root visiting and added write barrier
to the artResolveStringFromCode().
Test: build aosp_mips-eng
Test: m ART_DEFAULT_GC_TYPE=SS test-art-target-host-gtest-oat_test
Test: Run ART test suite on host and Nexus 9.
Bug: 20323084
Bug: 30627598
This reverts commit 5f926055cb88089d8ca27243f35a9dfd89d981f0.
Change-Id: I07fa2278d82b8eb64964c9a4b66cb93726ccda6b
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index b243ee0..28638d7 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -287,6 +287,44 @@
DISALLOW_COPY_AND_ASSIGN(LoadClassSlowPathX86_64);
};
+class LoadStringSlowPathX86_64 : public SlowPathCode {
+ public:
+ explicit LoadStringSlowPathX86_64(HLoadString* instruction) : SlowPathCode(instruction) {}
+
+ void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
+ LocationSummary* locations = instruction_->GetLocations();
+ DCHECK(!locations->GetLiveRegisters()->ContainsCoreRegister(locations->Out().reg()));
+
+ CodeGeneratorX86_64* x86_64_codegen = down_cast<CodeGeneratorX86_64*>(codegen);
+ __ Bind(GetEntryLabel());
+ SaveLiveRegisters(codegen, locations);
+
+ InvokeRuntimeCallingConvention calling_convention;
+ const uint32_t string_index = instruction_->AsLoadString()->GetStringIndex();
+ __ movl(CpuRegister(calling_convention.GetRegisterAt(0)), Immediate(string_index));
+ x86_64_codegen->InvokeRuntime(kQuickResolveString,
+ instruction_,
+ instruction_->GetDexPc(),
+ this);
+ CheckEntrypointTypes<kQuickResolveString, void*, uint32_t>();
+ x86_64_codegen->Move(locations->Out(), Location::RegisterLocation(RAX));
+ RestoreLiveRegisters(codegen, locations);
+
+ // Store the resolved String to the BSS entry.
+ __ movl(Address::Absolute(CodeGeneratorX86_64::kDummy32BitOffset, /* no_rip */ false),
+ locations->Out().AsRegister<CpuRegister>());
+ Label* fixup_label = x86_64_codegen->NewStringBssEntryPatch(instruction_->AsLoadString());
+ __ Bind(fixup_label);
+
+ __ jmp(GetExitLabel());
+ }
+
+ const char* GetDescription() const OVERRIDE { return "LoadStringSlowPathX86_64"; }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(LoadStringSlowPathX86_64);
+};
+
class TypeCheckSlowPathX86_64 : public SlowPathCode {
public:
TypeCheckSlowPathX86_64(HInstruction* instruction, bool is_fatal)
@@ -772,7 +810,8 @@
break;
case HInvokeStaticOrDirect::MethodLoadKind::kDirectAddressWithFixup:
__ movl(temp.AsRegister<CpuRegister>(), Immediate(0)); // Placeholder.
- method_patches_.emplace_back(invoke->GetTargetMethod());
+ method_patches_.emplace_back(*invoke->GetTargetMethod().dex_file,
+ invoke->GetTargetMethod().dex_method_index);
__ Bind(&method_patches_.back().label); // Bind the label at the end of the "movl" insn.
break;
case HInvokeStaticOrDirect::MethodLoadKind::kDexCachePcRelative: {
@@ -819,7 +858,8 @@
__ call(&frame_entry_label_);
break;
case HInvokeStaticOrDirect::CodePtrLocation::kCallPCRelative: {
- relative_call_patches_.emplace_back(invoke->GetTargetMethod());
+ relative_call_patches_.emplace_back(*invoke->GetTargetMethod().dex_file,
+ invoke->GetTargetMethod().dex_method_index);
Label* label = &relative_call_patches_.back().label;
__ call(label); // Bind to the patch label, override at link time.
__ Bind(label); // Bind the label at the end of the "call" insn.
@@ -879,7 +919,8 @@
}
}
-void CodeGeneratorX86_64::RecordStringPatch(HLoadString* load_string) {
+void CodeGeneratorX86_64::RecordBootStringPatch(HLoadString* load_string) {
+ DCHECK(GetCompilerOptions().IsBootImage());
string_patches_.emplace_back(load_string->GetDexFile(), load_string->GetStringIndex());
__ Bind(&string_patches_.back().label);
}
@@ -889,6 +930,12 @@
__ Bind(&type_patches_.back().label);
}
+Label* CodeGeneratorX86_64::NewStringBssEntryPatch(HLoadString* load_string) {
+ DCHECK(!GetCompilerOptions().IsBootImage());
+ string_patches_.emplace_back(load_string->GetDexFile(), load_string->GetStringIndex());
+ return &string_patches_.back().label;
+}
+
Label* CodeGeneratorX86_64::NewPcRelativeDexCacheArrayPatch(const DexFile& dex_file,
uint32_t element_offset) {
// Add a patch entry and return the label.
@@ -896,6 +943,21 @@
return &pc_relative_dex_cache_patches_.back().label;
}
+// The label points to the end of the "movl" or another instruction but the literal offset
+// for method patch needs to point to the embedded constant which occupies the last 4 bytes.
+constexpr uint32_t kLabelPositionToLiteralOffsetAdjustment = 4u;
+
+template <LinkerPatch (*Factory)(size_t, const DexFile*, uint32_t, uint32_t)>
+inline void CodeGeneratorX86_64::EmitPcRelativeLinkerPatches(
+ const ArenaDeque<PatchInfo<Label>>& infos,
+ ArenaVector<LinkerPatch>* linker_patches) {
+ for (const PatchInfo<Label>& info : infos) {
+ uint32_t literal_offset = info.label.Position() - kLabelPositionToLiteralOffsetAdjustment;
+ linker_patches->push_back(
+ Factory(literal_offset, &info.dex_file, info.label.Position(), info.index));
+ }
+}
+
void CodeGeneratorX86_64::EmitLinkerPatches(ArenaVector<LinkerPatch>* linker_patches) {
DCHECK(linker_patches->empty());
size_t size =
@@ -906,48 +968,29 @@
string_patches_.size() +
type_patches_.size();
linker_patches->reserve(size);
- // The label points to the end of the "movl" insn but the literal offset for method
- // patch needs to point to the embedded constant which occupies the last 4 bytes.
- constexpr uint32_t kLabelPositionToLiteralOffsetAdjustment = 4u;
- for (const MethodPatchInfo<Label>& info : method_patches_) {
+ for (const PatchInfo<Label>& info : method_patches_) {
uint32_t literal_offset = info.label.Position() - kLabelPositionToLiteralOffsetAdjustment;
- linker_patches->push_back(LinkerPatch::MethodPatch(literal_offset,
- info.target_method.dex_file,
- info.target_method.dex_method_index));
+ linker_patches->push_back(LinkerPatch::MethodPatch(literal_offset, &info.dex_file, info.index));
}
- for (const MethodPatchInfo<Label>& info : relative_call_patches_) {
+ for (const PatchInfo<Label>& info : relative_call_patches_) {
uint32_t literal_offset = info.label.Position() - kLabelPositionToLiteralOffsetAdjustment;
- linker_patches->push_back(LinkerPatch::RelativeCodePatch(literal_offset,
- info.target_method.dex_file,
- info.target_method.dex_method_index));
+ linker_patches->push_back(
+ LinkerPatch::RelativeCodePatch(literal_offset, &info.dex_file, info.index));
}
- for (const PcRelativeDexCacheAccessInfo& info : pc_relative_dex_cache_patches_) {
- uint32_t literal_offset = info.label.Position() - kLabelPositionToLiteralOffsetAdjustment;
- linker_patches->push_back(LinkerPatch::DexCacheArrayPatch(literal_offset,
- &info.target_dex_file,
- info.label.Position(),
- info.element_offset));
- }
+ EmitPcRelativeLinkerPatches<LinkerPatch::DexCacheArrayPatch>(pc_relative_dex_cache_patches_,
+ linker_patches);
for (const Label& label : simple_patches_) {
uint32_t literal_offset = label.Position() - kLabelPositionToLiteralOffsetAdjustment;
linker_patches->push_back(LinkerPatch::RecordPosition(literal_offset));
}
- for (const StringPatchInfo<Label>& info : string_patches_) {
+ if (!GetCompilerOptions().IsBootImage()) {
+ EmitPcRelativeLinkerPatches<LinkerPatch::StringBssEntryPatch>(string_patches_, linker_patches);
+ } else {
// These are always PC-relative, see GetSupportedLoadStringKind().
- uint32_t literal_offset = info.label.Position() - kLabelPositionToLiteralOffsetAdjustment;
- linker_patches->push_back(LinkerPatch::RelativeStringPatch(literal_offset,
- &info.dex_file,
- info.label.Position(),
- info.string_index));
+ EmitPcRelativeLinkerPatches<LinkerPatch::RelativeStringPatch>(string_patches_, linker_patches);
}
- for (const TypePatchInfo<Label>& info : type_patches_) {
- // These are always PC-relative, see GetSupportedLoadClassKind().
- uint32_t literal_offset = info.label.Position() - kLabelPositionToLiteralOffsetAdjustment;
- linker_patches->push_back(LinkerPatch::RelativeTypePatch(literal_offset,
- &info.dex_file,
- info.label.Position(),
- info.type_index));
- }
+ // These are always PC-relative, see GetSupportedLoadClassKind().
+ EmitPcRelativeLinkerPatches<LinkerPatch::RelativeTypePatch>(type_patches_, linker_patches);
}
void CodeGeneratorX86_64::DumpCoreRegister(std::ostream& stream, int reg) const {
@@ -5390,7 +5433,7 @@
case HLoadString::LoadKind::kDexCacheAddress:
DCHECK(Runtime::Current()->UseJitCompilation());
break;
- case HLoadString::LoadKind::kDexCachePcRelative:
+ case HLoadString::LoadKind::kBssEntry:
DCHECK(!Runtime::Current()->UseJitCompilation());
break;
case HLoadString::LoadKind::kDexCacheViaMethod:
@@ -5401,7 +5444,9 @@
void LocationsBuilderX86_64::VisitLoadString(HLoadString* load) {
LocationSummary::CallKind call_kind = load->NeedsEnvironment()
- ? LocationSummary::kCallOnMainOnly
+ ? ((load->GetLoadKind() == HLoadString::LoadKind::kDexCacheViaMethod)
+ ? LocationSummary::kCallOnMainOnly
+ : LocationSummary::kCallOnSlowPath)
: LocationSummary::kNoCall;
LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(load, call_kind);
if (load->GetLoadKind() == HLoadString::LoadKind::kDexCacheViaMethod) {
@@ -5420,7 +5465,7 @@
switch (load->GetLoadKind()) {
case HLoadString::LoadKind::kBootImageLinkTimePcRelative: {
__ leal(out, Address::Absolute(CodeGeneratorX86_64::kDummy32BitOffset, /* no_rip */ false));
- codegen_->RecordStringPatch(load);
+ codegen_->RecordBootStringPatch(load);
return; // No dex cache slow path.
}
case HLoadString::LoadKind::kBootImageAddress: {
@@ -5430,6 +5475,19 @@
codegen_->RecordSimplePatch();
return; // No dex cache slow path.
}
+ case HLoadString::LoadKind::kBssEntry: {
+ Address address = Address::Absolute(CodeGeneratorX86_64::kDummy32BitOffset,
+ /* no_rip */ false);
+ Label* fixup_label = codegen_->NewStringBssEntryPatch(load);
+ // /* GcRoot<mirror::Class> */ out = *address /* PC-relative */
+ GenerateGcRootFieldLoad(load, out_loc, address, fixup_label);
+ SlowPathCode* slow_path = new (GetGraph()->GetArena()) LoadStringSlowPathX86_64(load);
+ codegen_->AddSlowPath(slow_path);
+ __ testl(out, out);
+ __ j(kEqual, slow_path->GetEntryLabel());
+ __ Bind(slow_path->GetExitLabel());
+ return;
+ }
default:
break;
}