Rewrite Class init entrypoint to take a Class arg.
Fixes invalid type index being passed to the entrypoint for
class init check across dex files when the target type does
not have a TypeId in the compilation unit's DexFile.
The size of the aosp_taimen-userdebug prebuilts:
- before:
arm/boot*.oat: 16782748
arm64/boot*.oat: 19764400
oat/arm64/services.odex: 20162432
- after:
arm/boot*.oat: 16811692 (+28.3KiB, +0.17%)
arm64/boot*.oat: 19801032 (+35.8KiB, +0.19%)
oat/arm64/services.odex: 20232208 (+68.1KiB, +0.35%)
This increase comes from doing two runtime calls instead of
one for HLoadClass/kBssEntry that MustGenerateClinitCheck().
Test: Additional test in 476-clinit-inline-static-invoke
Test: m test-art-host-gtest
Test: testrunner.py --host --optimizing --jit
Test: Pixel 2 XL boots.
Test: testrunner.py --target --optimizing --jit
Test: testrunner.py --jvm
Bug: 111433619
Change-Id: I2fccd6944480ab4dac514f60d38e72c1014ae7b2
diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc
index b0a05da..f6a104b 100644
--- a/compiler/optimizing/code_generator.cc
+++ b/compiler/optimizing/code_generator.cc
@@ -737,14 +737,12 @@
void CodeGenerator::GenerateLoadClassRuntimeCall(HLoadClass* cls) {
DCHECK_EQ(cls->GetLoadKind(), HLoadClass::LoadKind::kRuntimeCall);
+ DCHECK(!cls->MustGenerateClinitCheck());
LocationSummary* locations = cls->GetLocations();
MoveConstant(locations->GetTemp(0), cls->GetTypeIndex().index_);
if (cls->NeedsAccessCheck()) {
CheckEntrypointTypes<kQuickInitializeTypeAndVerifyAccess, void*, uint32_t>();
InvokeRuntime(kQuickInitializeTypeAndVerifyAccess, cls, cls->GetDexPc());
- } else if (cls->MustGenerateClinitCheck()) {
- CheckEntrypointTypes<kQuickInitializeStaticStorage, void*, uint32_t>();
- InvokeRuntime(kQuickInitializeStaticStorage, cls, cls->GetDexPc());
} else {
CheckEntrypointTypes<kQuickInitializeType, void*, uint32_t>();
InvokeRuntime(kQuickInitializeType, cls, cls->GetDexPc());
diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc
index 8a5cbca..5659ebf 100644
--- a/compiler/optimizing/code_generator_arm64.cc
+++ b/compiler/optimizing/code_generator_arm64.cc
@@ -307,35 +307,41 @@
class LoadClassSlowPathARM64 : public SlowPathCodeARM64 {
public:
- LoadClassSlowPathARM64(HLoadClass* cls,
- HInstruction* at,
- uint32_t dex_pc,
- bool do_clinit)
- : SlowPathCodeARM64(at),
- cls_(cls),
- dex_pc_(dex_pc),
- do_clinit_(do_clinit) {
+ LoadClassSlowPathARM64(HLoadClass* cls, HInstruction* at)
+ : SlowPathCodeARM64(at), cls_(cls) {
DCHECK(at->IsLoadClass() || at->IsClinitCheck());
+ DCHECK_EQ(instruction_->IsLoadClass(), cls_ == instruction_);
}
void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
LocationSummary* locations = instruction_->GetLocations();
Location out = locations->Out();
- CodeGeneratorARM64* arm64_codegen = down_cast<CodeGeneratorARM64*>(codegen);
+ const uint32_t dex_pc = instruction_->GetDexPc();
+ bool must_resolve_type = instruction_->IsLoadClass() && cls_->MustResolveTypeOnSlowPath();
+ bool must_do_clinit = instruction_->IsClinitCheck() || cls_->MustGenerateClinitCheck();
+ CodeGeneratorARM64* arm64_codegen = down_cast<CodeGeneratorARM64*>(codegen);
__ Bind(GetEntryLabel());
SaveLiveRegisters(codegen, locations);
InvokeRuntimeCallingConvention calling_convention;
- dex::TypeIndex type_index = cls_->GetTypeIndex();
- __ Mov(calling_convention.GetRegisterAt(0).W(), type_index.index_);
- QuickEntrypointEnum entrypoint = do_clinit_ ? kQuickInitializeStaticStorage
- : kQuickInitializeType;
- arm64_codegen->InvokeRuntime(entrypoint, instruction_, dex_pc_, this);
- if (do_clinit_) {
- CheckEntrypointTypes<kQuickInitializeStaticStorage, void*, uint32_t>();
- } else {
+ if (must_resolve_type) {
+ DCHECK(IsSameDexFile(cls_->GetDexFile(), arm64_codegen->GetGraph()->GetDexFile()));
+ dex::TypeIndex type_index = cls_->GetTypeIndex();
+ __ Mov(calling_convention.GetRegisterAt(0).W(), type_index.index_);
+ arm64_codegen->InvokeRuntime(kQuickInitializeType, instruction_, dex_pc, this);
CheckEntrypointTypes<kQuickInitializeType, void*, uint32_t>();
+ // If we also must_do_clinit, the resolved type is now in the correct register.
+ } else {
+ DCHECK(must_do_clinit);
+ Location source = instruction_->IsLoadClass() ? out : locations->InAt(0);
+ arm64_codegen->MoveLocation(LocationFrom(calling_convention.GetRegisterAt(0)),
+ source,
+ cls_->GetType());
+ }
+ if (must_do_clinit) {
+ arm64_codegen->InvokeRuntime(kQuickInitializeStaticStorage, instruction_, dex_pc, this);
+ CheckEntrypointTypes<kQuickInitializeStaticStorage, void*, mirror::Class*>();
}
// Move the class to the desired location.
@@ -354,12 +360,6 @@
// The class this slow path will load.
HLoadClass* const cls_;
- // The dex PC of `at_`.
- const uint32_t dex_pc_;
-
- // Whether to initialize the class.
- const bool do_clinit_;
-
DISALLOW_COPY_AND_ASSIGN(LoadClassSlowPathARM64);
};
@@ -3194,8 +3194,8 @@
void InstructionCodeGeneratorARM64::VisitClinitCheck(HClinitCheck* check) {
// We assume the class is not null.
- SlowPathCodeARM64* slow_path = new (codegen_->GetScopedAllocator()) LoadClassSlowPathARM64(
- check->GetLoadClass(), check, check->GetDexPc(), true);
+ SlowPathCodeARM64* slow_path =
+ new (codegen_->GetScopedAllocator()) LoadClassSlowPathARM64(check->GetLoadClass(), check);
codegen_->AddSlowPath(slow_path);
GenerateClassInitializationCheck(slow_path, InputRegisterAt(check, 0));
}
@@ -5192,8 +5192,8 @@
bool do_clinit = cls->MustGenerateClinitCheck();
if (generate_null_check || do_clinit) {
DCHECK(cls->CanCallRuntime());
- SlowPathCodeARM64* slow_path = new (codegen_->GetScopedAllocator()) LoadClassSlowPathARM64(
- cls, cls, cls->GetDexPc(), do_clinit);
+ SlowPathCodeARM64* slow_path =
+ new (codegen_->GetScopedAllocator()) LoadClassSlowPathARM64(cls, cls);
codegen_->AddSlowPath(slow_path);
if (generate_null_check) {
__ Cbz(out, slow_path->GetEntryLabel());
diff --git a/compiler/optimizing/code_generator_arm_vixl.cc b/compiler/optimizing/code_generator_arm_vixl.cc
index 836a989..c274dfc 100644
--- a/compiler/optimizing/code_generator_arm_vixl.cc
+++ b/compiler/optimizing/code_generator_arm_vixl.cc
@@ -501,29 +501,39 @@
class LoadClassSlowPathARMVIXL : public SlowPathCodeARMVIXL {
public:
- LoadClassSlowPathARMVIXL(HLoadClass* cls, HInstruction* at, uint32_t dex_pc, bool do_clinit)
- : SlowPathCodeARMVIXL(at), cls_(cls), dex_pc_(dex_pc), do_clinit_(do_clinit) {
+ LoadClassSlowPathARMVIXL(HLoadClass* cls, HInstruction* at)
+ : SlowPathCodeARMVIXL(at), cls_(cls) {
DCHECK(at->IsLoadClass() || at->IsClinitCheck());
+ DCHECK_EQ(instruction_->IsLoadClass(), cls_ == instruction_);
}
void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
LocationSummary* locations = instruction_->GetLocations();
Location out = locations->Out();
+ const uint32_t dex_pc = instruction_->GetDexPc();
+ bool must_resolve_type = instruction_->IsLoadClass() && cls_->MustResolveTypeOnSlowPath();
+ bool must_do_clinit = instruction_->IsClinitCheck() || cls_->MustGenerateClinitCheck();
CodeGeneratorARMVIXL* arm_codegen = down_cast<CodeGeneratorARMVIXL*>(codegen);
__ Bind(GetEntryLabel());
SaveLiveRegisters(codegen, locations);
InvokeRuntimeCallingConventionARMVIXL calling_convention;
- dex::TypeIndex type_index = cls_->GetTypeIndex();
- __ Mov(calling_convention.GetRegisterAt(0), type_index.index_);
- QuickEntrypointEnum entrypoint = do_clinit_ ? kQuickInitializeStaticStorage
- : kQuickInitializeType;
- arm_codegen->InvokeRuntime(entrypoint, instruction_, dex_pc_, this);
- if (do_clinit_) {
- CheckEntrypointTypes<kQuickInitializeStaticStorage, void*, uint32_t>();
- } else {
+ if (must_resolve_type) {
+ DCHECK(IsSameDexFile(cls_->GetDexFile(), arm_codegen->GetGraph()->GetDexFile()));
+ dex::TypeIndex type_index = cls_->GetTypeIndex();
+ __ Mov(calling_convention.GetRegisterAt(0), type_index.index_);
+ arm_codegen->InvokeRuntime(kQuickInitializeType, instruction_, dex_pc, this);
CheckEntrypointTypes<kQuickInitializeType, void*, uint32_t>();
+ // If we also must_do_clinit, the resolved type is now in the correct register.
+ } else {
+ DCHECK(must_do_clinit);
+ Location source = instruction_->IsLoadClass() ? out : locations->InAt(0);
+ arm_codegen->Move32(LocationFrom(calling_convention.GetRegisterAt(0)), source);
+ }
+ if (must_do_clinit) {
+ arm_codegen->InvokeRuntime(kQuickInitializeStaticStorage, instruction_, dex_pc, this);
+ CheckEntrypointTypes<kQuickInitializeStaticStorage, void*, mirror::Class*>();
}
// Move the class to the desired location.
@@ -541,12 +551,6 @@
// The class this slow path will load.
HLoadClass* const cls_;
- // The dex PC of `at_`.
- const uint32_t dex_pc_;
-
- // Whether to initialize the class.
- const bool do_clinit_;
-
DISALLOW_COPY_AND_ASSIGN(LoadClassSlowPathARMVIXL);
};
@@ -7508,8 +7512,7 @@
if (generate_null_check || cls->MustGenerateClinitCheck()) {
DCHECK(cls->CanCallRuntime());
LoadClassSlowPathARMVIXL* slow_path =
- new (codegen_->GetScopedAllocator()) LoadClassSlowPathARMVIXL(
- cls, cls, cls->GetDexPc(), cls->MustGenerateClinitCheck());
+ new (codegen_->GetScopedAllocator()) LoadClassSlowPathARMVIXL(cls, cls);
codegen_->AddSlowPath(slow_path);
if (generate_null_check) {
__ CompareAndBranchIfZero(out, slow_path->GetEntryLabel());
@@ -7555,10 +7558,7 @@
void InstructionCodeGeneratorARMVIXL::VisitClinitCheck(HClinitCheck* check) {
// We assume the class is not null.
LoadClassSlowPathARMVIXL* slow_path =
- new (codegen_->GetScopedAllocator()) LoadClassSlowPathARMVIXL(check->GetLoadClass(),
- check,
- check->GetDexPc(),
- /* do_clinit */ true);
+ new (codegen_->GetScopedAllocator()) LoadClassSlowPathARMVIXL(check->GetLoadClass(), check);
codegen_->AddSlowPath(slow_path);
GenerateClassInitializationCheck(slow_path, InputRegisterAt(check, 0));
}
diff --git a/compiler/optimizing/code_generator_mips.cc b/compiler/optimizing/code_generator_mips.cc
index 4aed2c0..60bbf4c 100644
--- a/compiler/optimizing/code_generator_mips.cc
+++ b/compiler/optimizing/code_generator_mips.cc
@@ -222,35 +222,41 @@
class LoadClassSlowPathMIPS : public SlowPathCodeMIPS {
public:
- LoadClassSlowPathMIPS(HLoadClass* cls,
- HInstruction* at,
- uint32_t dex_pc,
- bool do_clinit)
- : SlowPathCodeMIPS(at),
- cls_(cls),
- dex_pc_(dex_pc),
- do_clinit_(do_clinit) {
+ LoadClassSlowPathMIPS(HLoadClass* cls, HInstruction* at)
+ : SlowPathCodeMIPS(at), cls_(cls) {
DCHECK(at->IsLoadClass() || at->IsClinitCheck());
+ DCHECK_EQ(instruction_->IsLoadClass(), cls_ == instruction_);
}
void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
LocationSummary* locations = instruction_->GetLocations();
Location out = locations->Out();
+ const uint32_t dex_pc = instruction_->GetDexPc();
+ bool must_resolve_type = instruction_->IsLoadClass() && cls_->MustResolveTypeOnSlowPath();
+ bool must_do_clinit = instruction_->IsClinitCheck() || cls_->MustGenerateClinitCheck();
+
CodeGeneratorMIPS* mips_codegen = down_cast<CodeGeneratorMIPS*>(codegen);
- InvokeRuntimeCallingConvention calling_convention;
- DCHECK_EQ(instruction_->IsLoadClass(), cls_ == instruction_);
__ Bind(GetEntryLabel());
SaveLiveRegisters(codegen, locations);
- dex::TypeIndex type_index = cls_->GetTypeIndex();
- __ LoadConst32(calling_convention.GetRegisterAt(0), type_index.index_);
- QuickEntrypointEnum entrypoint = do_clinit_ ? kQuickInitializeStaticStorage
- : kQuickInitializeType;
- mips_codegen->InvokeRuntime(entrypoint, instruction_, dex_pc_, this);
- if (do_clinit_) {
- CheckEntrypointTypes<kQuickInitializeStaticStorage, void*, uint32_t>();
- } else {
+ InvokeRuntimeCallingConvention calling_convention;
+ if (must_resolve_type) {
+ DCHECK(IsSameDexFile(cls_->GetDexFile(), mips_codegen->GetGraph()->GetDexFile()));
+ dex::TypeIndex type_index = cls_->GetTypeIndex();
+ __ LoadConst32(calling_convention.GetRegisterAt(0), type_index.index_);
+ mips_codegen->InvokeRuntime(kQuickInitializeType, instruction_, dex_pc, this);
CheckEntrypointTypes<kQuickInitializeType, void*, uint32_t>();
+ // If we also must_do_clinit, the resolved type is now in the correct register.
+ } else {
+ DCHECK(must_do_clinit);
+ Location source = instruction_->IsLoadClass() ? out : locations->InAt(0);
+ mips_codegen->MoveLocation(Location::RegisterLocation(calling_convention.GetRegisterAt(0)),
+ source,
+ cls_->GetType());
+ }
+ if (must_do_clinit) {
+ mips_codegen->InvokeRuntime(kQuickInitializeStaticStorage, instruction_, dex_pc, this);
+ CheckEntrypointTypes<kQuickInitializeStaticStorage, void*, mirror::Class*>();
}
// Move the class to the desired location.
@@ -272,12 +278,6 @@
// The class this slow path will load.
HLoadClass* const cls_;
- // The dex PC of `at_`.
- const uint32_t dex_pc_;
-
- // Whether to initialize the class.
- const bool do_clinit_;
-
DISALLOW_COPY_AND_ASSIGN(LoadClassSlowPathMIPS);
};
@@ -3598,11 +3598,8 @@
void InstructionCodeGeneratorMIPS::VisitClinitCheck(HClinitCheck* check) {
// We assume the class is not null.
- SlowPathCodeMIPS* slow_path = new (codegen_->GetScopedAllocator()) LoadClassSlowPathMIPS(
- check->GetLoadClass(),
- check,
- check->GetDexPc(),
- true);
+ SlowPathCodeMIPS* slow_path =
+ new (codegen_->GetScopedAllocator()) LoadClassSlowPathMIPS(check->GetLoadClass(), check);
codegen_->AddSlowPath(slow_path);
GenerateClassInitializationCheck(slow_path,
check->GetLocations()->InAt(0).AsRegister<Register>());
@@ -8277,8 +8274,8 @@
if (generate_null_check || cls->MustGenerateClinitCheck()) {
DCHECK(cls->CanCallRuntime());
- SlowPathCodeMIPS* slow_path = new (codegen_->GetScopedAllocator()) LoadClassSlowPathMIPS(
- cls, cls, cls->GetDexPc(), cls->MustGenerateClinitCheck());
+ SlowPathCodeMIPS* slow_path =
+ new (codegen_->GetScopedAllocator()) LoadClassSlowPathMIPS(cls, cls);
codegen_->AddSlowPath(slow_path);
if (generate_null_check) {
__ Beqz(out, slow_path->GetEntryLabel());
diff --git a/compiler/optimizing/code_generator_mips64.cc b/compiler/optimizing/code_generator_mips64.cc
index 7516913..81d86a9 100644
--- a/compiler/optimizing/code_generator_mips64.cc
+++ b/compiler/optimizing/code_generator_mips64.cc
@@ -175,35 +175,41 @@
class LoadClassSlowPathMIPS64 : public SlowPathCodeMIPS64 {
public:
- LoadClassSlowPathMIPS64(HLoadClass* cls,
- HInstruction* at,
- uint32_t dex_pc,
- bool do_clinit)
- : SlowPathCodeMIPS64(at),
- cls_(cls),
- dex_pc_(dex_pc),
- do_clinit_(do_clinit) {
+ LoadClassSlowPathMIPS64(HLoadClass* cls, HInstruction* at)
+ : SlowPathCodeMIPS64(at), cls_(cls) {
DCHECK(at->IsLoadClass() || at->IsClinitCheck());
+ DCHECK_EQ(instruction_->IsLoadClass(), cls_ == instruction_);
}
void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
LocationSummary* locations = instruction_->GetLocations();
Location out = locations->Out();
+ const uint32_t dex_pc = instruction_->GetDexPc();
+ bool must_resolve_type = instruction_->IsLoadClass() && cls_->MustResolveTypeOnSlowPath();
+ bool must_do_clinit = instruction_->IsClinitCheck() || cls_->MustGenerateClinitCheck();
+
CodeGeneratorMIPS64* mips64_codegen = down_cast<CodeGeneratorMIPS64*>(codegen);
- InvokeRuntimeCallingConvention calling_convention;
- DCHECK_EQ(instruction_->IsLoadClass(), cls_ == instruction_);
__ Bind(GetEntryLabel());
SaveLiveRegisters(codegen, locations);
- dex::TypeIndex type_index = cls_->GetTypeIndex();
- __ LoadConst32(calling_convention.GetRegisterAt(0), type_index.index_);
- QuickEntrypointEnum entrypoint = do_clinit_ ? kQuickInitializeStaticStorage
- : kQuickInitializeType;
- mips64_codegen->InvokeRuntime(entrypoint, instruction_, dex_pc_, this);
- if (do_clinit_) {
- CheckEntrypointTypes<kQuickInitializeStaticStorage, void*, uint32_t>();
- } else {
+ InvokeRuntimeCallingConvention calling_convention;
+ if (must_resolve_type) {
+ DCHECK(IsSameDexFile(cls_->GetDexFile(), mips64_codegen->GetGraph()->GetDexFile()));
+ dex::TypeIndex type_index = cls_->GetTypeIndex();
+ __ LoadConst32(calling_convention.GetRegisterAt(0), type_index.index_);
+ mips64_codegen->InvokeRuntime(kQuickInitializeType, instruction_, dex_pc, this);
CheckEntrypointTypes<kQuickInitializeType, void*, uint32_t>();
+ // If we also must_do_clinit, the resolved type is now in the correct register.
+ } else {
+ DCHECK(must_do_clinit);
+ Location source = instruction_->IsLoadClass() ? out : locations->InAt(0);
+ mips64_codegen->MoveLocation(Location::RegisterLocation(calling_convention.GetRegisterAt(0)),
+ source,
+ cls_->GetType());
+ }
+ if (must_do_clinit) {
+ mips64_codegen->InvokeRuntime(kQuickInitializeStaticStorage, instruction_, dex_pc, this);
+ CheckEntrypointTypes<kQuickInitializeStaticStorage, void*, mirror::Class*>();
}
// Move the class to the desired location.
@@ -225,12 +231,6 @@
// The class this slow path will load.
HLoadClass* const cls_;
- // The dex PC of `at_`.
- const uint32_t dex_pc_;
-
- // Whether to initialize the class.
- const bool do_clinit_;
-
DISALLOW_COPY_AND_ASSIGN(LoadClassSlowPathMIPS64);
};
@@ -3153,11 +3153,8 @@
void InstructionCodeGeneratorMIPS64::VisitClinitCheck(HClinitCheck* check) {
// We assume the class is not null.
- SlowPathCodeMIPS64* slow_path = new (codegen_->GetScopedAllocator()) LoadClassSlowPathMIPS64(
- check->GetLoadClass(),
- check,
- check->GetDexPc(),
- true);
+ SlowPathCodeMIPS64* slow_path =
+ new (codegen_->GetScopedAllocator()) LoadClassSlowPathMIPS64(check->GetLoadClass(), check);
codegen_->AddSlowPath(slow_path);
GenerateClassInitializationCheck(slow_path,
check->GetLocations()->InAt(0).AsRegister<GpuRegister>());
@@ -6315,8 +6312,8 @@
if (generate_null_check || cls->MustGenerateClinitCheck()) {
DCHECK(cls->CanCallRuntime());
- SlowPathCodeMIPS64* slow_path = new (codegen_->GetScopedAllocator()) LoadClassSlowPathMIPS64(
- cls, cls, cls->GetDexPc(), cls->MustGenerateClinitCheck());
+ SlowPathCodeMIPS64* slow_path =
+ new (codegen_->GetScopedAllocator()) LoadClassSlowPathMIPS64(cls, cls);
codegen_->AddSlowPath(slow_path);
if (generate_null_check) {
__ Beqzc(out, slow_path->GetEntryLabel());
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index 30436ee..83ce734 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -255,36 +255,42 @@
class LoadClassSlowPathX86 : public SlowPathCode {
public:
- LoadClassSlowPathX86(HLoadClass* cls,
- HInstruction* at,
- uint32_t dex_pc,
- bool do_clinit)
- : SlowPathCode(at), cls_(cls), dex_pc_(dex_pc), do_clinit_(do_clinit) {
+ LoadClassSlowPathX86(HLoadClass* cls, HInstruction* at)
+ : SlowPathCode(at), cls_(cls) {
DCHECK(at->IsLoadClass() || at->IsClinitCheck());
+ DCHECK_EQ(instruction_->IsLoadClass(), cls_ == instruction_);
}
void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
LocationSummary* locations = instruction_->GetLocations();
+ Location out = locations->Out();
+ const uint32_t dex_pc = instruction_->GetDexPc();
+ bool must_resolve_type = instruction_->IsLoadClass() && cls_->MustResolveTypeOnSlowPath();
+ bool must_do_clinit = instruction_->IsClinitCheck() || cls_->MustGenerateClinitCheck();
+
CodeGeneratorX86* x86_codegen = down_cast<CodeGeneratorX86*>(codegen);
__ Bind(GetEntryLabel());
SaveLiveRegisters(codegen, locations);
InvokeRuntimeCallingConvention calling_convention;
- dex::TypeIndex type_index = cls_->GetTypeIndex();
- __ movl(calling_convention.GetRegisterAt(0), Immediate(type_index.index_));
- x86_codegen->InvokeRuntime(do_clinit_ ? kQuickInitializeStaticStorage
- : kQuickInitializeType,
- instruction_,
- dex_pc_,
- this);
- if (do_clinit_) {
- CheckEntrypointTypes<kQuickInitializeStaticStorage, void*, uint32_t>();
- } else {
+ if (must_resolve_type) {
+ DCHECK(IsSameDexFile(cls_->GetDexFile(), x86_codegen->GetGraph()->GetDexFile()));
+ dex::TypeIndex type_index = cls_->GetTypeIndex();
+ __ movl(calling_convention.GetRegisterAt(0), Immediate(type_index.index_));
+ x86_codegen->InvokeRuntime(kQuickInitializeType, instruction_, dex_pc, this);
CheckEntrypointTypes<kQuickInitializeType, void*, uint32_t>();
+ // If we also must_do_clinit, the resolved type is now in the correct register.
+ } else {
+ DCHECK(must_do_clinit);
+ Location source = instruction_->IsLoadClass() ? out : locations->InAt(0);
+ x86_codegen->Move32(Location::RegisterLocation(calling_convention.GetRegisterAt(0)), source);
+ }
+ if (must_do_clinit) {
+ x86_codegen->InvokeRuntime(kQuickInitializeStaticStorage, instruction_, dex_pc, this);
+ CheckEntrypointTypes<kQuickInitializeStaticStorage, void*, mirror::Class*>();
}
// Move the class to the desired location.
- Location out = locations->Out();
if (out.IsValid()) {
DCHECK(out.IsRegister() && !locations->GetLiveRegisters()->ContainsCoreRegister(out.reg()));
x86_codegen->Move32(out, Location::RegisterLocation(EAX));
@@ -299,12 +305,6 @@
// The class this slow path will load.
HLoadClass* const cls_;
- // The dex PC of `at_`.
- const uint32_t dex_pc_;
-
- // Whether to initialize the class.
- const bool do_clinit_;
-
DISALLOW_COPY_AND_ASSIGN(LoadClassSlowPathX86);
};
@@ -6588,8 +6588,7 @@
if (generate_null_check || cls->MustGenerateClinitCheck()) {
DCHECK(cls->CanCallRuntime());
- SlowPathCode* slow_path = new (codegen_->GetScopedAllocator()) LoadClassSlowPathX86(
- cls, cls, cls->GetDexPc(), cls->MustGenerateClinitCheck());
+ SlowPathCode* slow_path = new (codegen_->GetScopedAllocator()) LoadClassSlowPathX86(cls, cls);
codegen_->AddSlowPath(slow_path);
if (generate_null_check) {
@@ -6636,8 +6635,8 @@
void InstructionCodeGeneratorX86::VisitClinitCheck(HClinitCheck* check) {
// We assume the class to not be null.
- SlowPathCode* slow_path = new (codegen_->GetScopedAllocator()) LoadClassSlowPathX86(
- check->GetLoadClass(), check, check->GetDexPc(), true);
+ SlowPathCode* slow_path =
+ new (codegen_->GetScopedAllocator()) LoadClassSlowPathX86(check->GetLoadClass(), check);
codegen_->AddSlowPath(slow_path);
GenerateClassInitializationCheck(slow_path,
check->GetLocations()->InAt(0).AsRegister<Register>());
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index 0d7837e..aabf2e0 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -239,34 +239,41 @@
class LoadClassSlowPathX86_64 : public SlowPathCode {
public:
- LoadClassSlowPathX86_64(HLoadClass* cls,
- HInstruction* at,
- uint32_t dex_pc,
- bool do_clinit)
- : SlowPathCode(at), cls_(cls), dex_pc_(dex_pc), do_clinit_(do_clinit) {
+ LoadClassSlowPathX86_64(HLoadClass* cls, HInstruction* at)
+ : SlowPathCode(at), cls_(cls) {
DCHECK(at->IsLoadClass() || at->IsClinitCheck());
+ DCHECK_EQ(instruction_->IsLoadClass(), cls_ == instruction_);
}
void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
LocationSummary* locations = instruction_->GetLocations();
+ Location out = locations->Out();
+ const uint32_t dex_pc = instruction_->GetDexPc();
+ bool must_resolve_type = instruction_->IsLoadClass() && cls_->MustResolveTypeOnSlowPath();
+ bool must_do_clinit = instruction_->IsClinitCheck() || cls_->MustGenerateClinitCheck();
+
CodeGeneratorX86_64* x86_64_codegen = down_cast<CodeGeneratorX86_64*>(codegen);
__ Bind(GetEntryLabel());
-
SaveLiveRegisters(codegen, locations);
// Custom calling convention: RAX serves as both input and output.
- __ movl(CpuRegister(RAX), Immediate(cls_->GetTypeIndex().index_));
- x86_64_codegen->InvokeRuntime(do_clinit_ ? kQuickInitializeStaticStorage : kQuickInitializeType,
- instruction_,
- dex_pc_,
- this);
- if (do_clinit_) {
- CheckEntrypointTypes<kQuickInitializeStaticStorage, void*, uint32_t>();
- } else {
+ if (must_resolve_type) {
+ DCHECK(IsSameDexFile(cls_->GetDexFile(), x86_64_codegen->GetGraph()->GetDexFile()));
+ dex::TypeIndex type_index = cls_->GetTypeIndex();
+ __ movl(CpuRegister(RAX), Immediate(type_index.index_));
+ x86_64_codegen->InvokeRuntime(kQuickInitializeType, instruction_, dex_pc, this);
CheckEntrypointTypes<kQuickInitializeType, void*, uint32_t>();
+ // If we also must_do_clinit, the resolved type is now in the correct register.
+ } else {
+ DCHECK(must_do_clinit);
+ Location source = instruction_->IsLoadClass() ? out : locations->InAt(0);
+ x86_64_codegen->Move(Location::RegisterLocation(RAX), source);
+ }
+ if (must_do_clinit) {
+ x86_64_codegen->InvokeRuntime(kQuickInitializeStaticStorage, instruction_, dex_pc, this);
+ CheckEntrypointTypes<kQuickInitializeStaticStorage, void*, mirror::Class*>();
}
- Location out = locations->Out();
// Move the class to the desired location.
if (out.IsValid()) {
DCHECK(out.IsRegister() && !locations->GetLiveRegisters()->ContainsCoreRegister(out.reg()));
@@ -283,12 +290,6 @@
// The class this slow path will load.
HLoadClass* const cls_;
- // The dex PC of `at_`.
- const uint32_t dex_pc_;
-
- // Whether to initialize the class.
- const bool do_clinit_;
-
DISALLOW_COPY_AND_ASSIGN(LoadClassSlowPathX86_64);
};
@@ -5927,8 +5928,8 @@
if (generate_null_check || cls->MustGenerateClinitCheck()) {
DCHECK(cls->CanCallRuntime());
- SlowPathCode* slow_path = new (codegen_->GetScopedAllocator()) LoadClassSlowPathX86_64(
- cls, cls, cls->GetDexPc(), cls->MustGenerateClinitCheck());
+ SlowPathCode* slow_path =
+ new (codegen_->GetScopedAllocator()) LoadClassSlowPathX86_64(cls, cls);
codegen_->AddSlowPath(slow_path);
if (generate_null_check) {
__ testl(out, out);
@@ -5973,8 +5974,8 @@
void InstructionCodeGeneratorX86_64::VisitClinitCheck(HClinitCheck* check) {
// We assume the class to not be null.
- SlowPathCode* slow_path = new (codegen_->GetScopedAllocator()) LoadClassSlowPathX86_64(
- check->GetLoadClass(), check, check->GetDexPc(), true);
+ SlowPathCode* slow_path =
+ new (codegen_->GetScopedAllocator()) LoadClassSlowPathX86_64(check->GetLoadClass(), check);
codegen_->AddSlowPath(slow_path);
GenerateClassInitializationCheck(slow_path,
check->GetLocations()->InAt(0).AsRegister<CpuRegister>());
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 16a7417..8b9e1da 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -6284,6 +6284,13 @@
bool IsInBootImage() const { return GetPackedFlag<kFlagIsInBootImage>(); }
bool MustGenerateClinitCheck() const { return GetPackedFlag<kFlagGenerateClInitCheck>(); }
+ bool MustResolveTypeOnSlowPath() const {
+ // Check that this instruction has a slow path.
+ DCHECK(GetLoadKind() != LoadKind::kRuntimeCall); // kRuntimeCall calls on main path.
+ DCHECK(GetLoadKind() == LoadKind::kBssEntry || MustGenerateClinitCheck());
+ return GetLoadKind() == LoadKind::kBssEntry;
+ }
+
void MarkInBootImage() {
SetPackedFlag<kFlagIsInBootImage>(true);
}
diff --git a/compiler/optimizing/prepare_for_register_allocation.cc b/compiler/optimizing/prepare_for_register_allocation.cc
index 831bccc..060613d 100644
--- a/compiler/optimizing/prepare_for_register_allocation.cc
+++ b/compiler/optimizing/prepare_for_register_allocation.cc
@@ -150,7 +150,9 @@
if (can_merge_with_load_class && !load_class->HasUses()) {
load_class->GetBlock()->RemoveInstruction(load_class);
}
- } else if (can_merge_with_load_class && !load_class->NeedsAccessCheck()) {
+ } else if (can_merge_with_load_class &&
+ load_class->GetLoadKind() != HLoadClass::LoadKind::kRuntimeCall) {
+ DCHECK(!load_class->NeedsAccessCheck());
// Pass the initialization duty to the `HLoadClass` instruction,
// and remove the instruction from the graph.
DCHECK(load_class->HasEnvironment());