ART: Refactor intrinsics slow-paths
Refactor slow paths so that there is a default implementation for
common cases (only arm64 with vixl is special). Write a generic
intrinsic slow-path that can be reused for the specific architectures.
Move helper functions into CodeGenerator so that they are accessible.
Change-Id: Ibd788dce432601c6a9f7e6f13eab31f28dcb8550
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc
index 6f89293..55c9214 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -59,7 +59,7 @@
#define __ down_cast<ArmAssembler*>(codegen->GetAssembler())->
#define QUICK_ENTRY_POINT(x) QUICK_ENTRYPOINT_OFFSET(kArmWordSize, x).Int32Value()
-class NullCheckSlowPathARM : public SlowPathCodeARM {
+class NullCheckSlowPathARM : public SlowPathCode {
public:
explicit NullCheckSlowPathARM(HNullCheck* instruction) : instruction_(instruction) {}
@@ -83,7 +83,7 @@
DISALLOW_COPY_AND_ASSIGN(NullCheckSlowPathARM);
};
-class DivZeroCheckSlowPathARM : public SlowPathCodeARM {
+class DivZeroCheckSlowPathARM : public SlowPathCode {
public:
explicit DivZeroCheckSlowPathARM(HDivZeroCheck* instruction) : instruction_(instruction) {}
@@ -107,7 +107,7 @@
DISALLOW_COPY_AND_ASSIGN(DivZeroCheckSlowPathARM);
};
-class SuspendCheckSlowPathARM : public SlowPathCodeARM {
+class SuspendCheckSlowPathARM : public SlowPathCode {
public:
SuspendCheckSlowPathARM(HSuspendCheck* instruction, HBasicBlock* successor)
: instruction_(instruction), successor_(successor) {}
@@ -148,7 +148,7 @@
DISALLOW_COPY_AND_ASSIGN(SuspendCheckSlowPathARM);
};
-class BoundsCheckSlowPathARM : public SlowPathCodeARM {
+class BoundsCheckSlowPathARM : public SlowPathCode {
public:
explicit BoundsCheckSlowPathARM(HBoundsCheck* instruction)
: instruction_(instruction) {}
@@ -186,7 +186,7 @@
DISALLOW_COPY_AND_ASSIGN(BoundsCheckSlowPathARM);
};
-class LoadClassSlowPathARM : public SlowPathCodeARM {
+class LoadClassSlowPathARM : public SlowPathCode {
public:
LoadClassSlowPathARM(HLoadClass* cls,
HInstruction* at,
@@ -239,7 +239,7 @@
DISALLOW_COPY_AND_ASSIGN(LoadClassSlowPathARM);
};
-class LoadStringSlowPathARM : public SlowPathCodeARM {
+class LoadStringSlowPathARM : public SlowPathCode {
public:
explicit LoadStringSlowPathARM(HLoadString* instruction) : instruction_(instruction) {}
@@ -269,7 +269,7 @@
DISALLOW_COPY_AND_ASSIGN(LoadStringSlowPathARM);
};
-class TypeCheckSlowPathARM : public SlowPathCodeARM {
+class TypeCheckSlowPathARM : public SlowPathCode {
public:
explicit TypeCheckSlowPathARM(HInstruction* instruction) : instruction_(instruction) {}
@@ -321,7 +321,7 @@
DISALLOW_COPY_AND_ASSIGN(TypeCheckSlowPathARM);
};
-class DeoptimizationSlowPathARM : public SlowPathCodeARM {
+class DeoptimizationSlowPathARM : public SlowPathCode {
public:
explicit DeoptimizationSlowPathARM(HInstruction* instruction)
: instruction_(instruction) {}
@@ -1261,7 +1261,7 @@
}
void InstructionCodeGeneratorARM::VisitDeoptimize(HDeoptimize* deoptimize) {
- SlowPathCodeARM* slow_path = new (GetGraph()->GetArena())
+ SlowPathCode* slow_path = new (GetGraph()->GetArena())
DeoptimizationSlowPathARM(deoptimize);
codegen_->AddSlowPath(slow_path);
Label* slow_path_entry = slow_path->GetEntryLabel();
@@ -2792,7 +2792,7 @@
}
void InstructionCodeGeneratorARM::VisitDivZeroCheck(HDivZeroCheck* instruction) {
- SlowPathCodeARM* slow_path = new (GetGraph()->GetArena()) DivZeroCheckSlowPathARM(instruction);
+ SlowPathCode* slow_path = new (GetGraph()->GetArena()) DivZeroCheckSlowPathARM(instruction);
codegen_->AddSlowPath(slow_path);
LocationSummary* locations = instruction->GetLocations();
@@ -3558,7 +3558,7 @@
}
void InstructionCodeGeneratorARM::GenerateExplicitNullCheck(HNullCheck* instruction) {
- SlowPathCodeARM* slow_path = new (GetGraph()->GetArena()) NullCheckSlowPathARM(instruction);
+ SlowPathCode* slow_path = new (GetGraph()->GetArena()) NullCheckSlowPathARM(instruction);
codegen_->AddSlowPath(slow_path);
LocationSummary* locations = instruction->GetLocations();
@@ -3920,7 +3920,7 @@
void InstructionCodeGeneratorARM::VisitBoundsCheck(HBoundsCheck* instruction) {
LocationSummary* locations = instruction->GetLocations();
- SlowPathCodeARM* slow_path =
+ SlowPathCode* slow_path =
new (GetGraph()->GetArena()) BoundsCheckSlowPathARM(instruction);
codegen_->AddSlowPath(slow_path);
@@ -4256,7 +4256,7 @@
__ LoadFromOffset(kLoadWord, out, out, CodeGenerator::GetCacheOffset(cls->GetTypeIndex()));
// TODO: We will need a read barrier here.
- SlowPathCodeARM* slow_path = new (GetGraph()->GetArena()) LoadClassSlowPathARM(
+ SlowPathCode* slow_path = new (GetGraph()->GetArena()) LoadClassSlowPathARM(
cls, cls, cls->GetDexPc(), cls->MustGenerateClinitCheck());
codegen_->AddSlowPath(slow_path);
__ CompareAndBranchIfZero(out, slow_path->GetEntryLabel());
@@ -4279,7 +4279,7 @@
void InstructionCodeGeneratorARM::VisitClinitCheck(HClinitCheck* check) {
// We assume the class is not null.
- SlowPathCodeARM* slow_path = new (GetGraph()->GetArena()) LoadClassSlowPathARM(
+ SlowPathCode* slow_path = new (GetGraph()->GetArena()) LoadClassSlowPathARM(
check->GetLoadClass(), check, check->GetDexPc(), true);
codegen_->AddSlowPath(slow_path);
GenerateClassInitializationCheck(slow_path,
@@ -4287,7 +4287,7 @@
}
void InstructionCodeGeneratorARM::GenerateClassInitializationCheck(
- SlowPathCodeARM* slow_path, Register class_reg) {
+ SlowPathCode* slow_path, Register class_reg) {
__ LoadFromOffset(kLoadWord, IP, class_reg, mirror::Class::StatusOffset().Int32Value());
__ cmp(IP, ShifterOperand(mirror::Class::kStatusInitialized));
__ b(slow_path->GetEntryLabel(), LT);
@@ -4305,7 +4305,7 @@
}
void InstructionCodeGeneratorARM::VisitLoadString(HLoadString* load) {
- SlowPathCodeARM* slow_path = new (GetGraph()->GetArena()) LoadStringSlowPathARM(load);
+ SlowPathCode* slow_path = new (GetGraph()->GetArena()) LoadStringSlowPathARM(load);
codegen_->AddSlowPath(slow_path);
LocationSummary* locations = load->GetLocations();
@@ -4375,7 +4375,7 @@
Register out = locations->Out().AsRegister<Register>();
uint32_t class_offset = mirror::Object::ClassOffset().Int32Value();
Label done, zero;
- SlowPathCodeARM* slow_path = nullptr;
+ SlowPathCode* slow_path = nullptr;
// Return 0 if `obj` is null.
// avoid null check if we know obj is not null.
@@ -4428,8 +4428,7 @@
Register temp = locations->GetTemp(0).AsRegister<Register>();
uint32_t class_offset = mirror::Object::ClassOffset().Int32Value();
- SlowPathCodeARM* slow_path =
- new (GetGraph()->GetArena()) TypeCheckSlowPathARM(instruction);
+ SlowPathCode* slow_path = new (GetGraph()->GetArena()) TypeCheckSlowPathARM(instruction);
codegen_->AddSlowPath(slow_path);
// avoid null check if we know obj is not null.
@@ -4732,6 +4731,39 @@
// Will be generated at use site.
}
+void CodeGeneratorARM::MoveFromReturnRegister(Location trg, Primitive::Type type) {
+ if (!trg.IsValid()) {
+ DCHECK(type == Primitive::kPrimVoid);
+ return;
+ }
+
+ DCHECK_NE(type, Primitive::kPrimVoid);
+
+ Location return_loc = InvokeDexCallingConventionVisitorARM().GetReturnLocation(type);
+ if (return_loc.Equals(trg)) {
+ return;
+ }
+
+ // TODO: Consider pairs in the parallel move resolver, then this could be nicely merged
+ // with the last branch.
+ if (type == Primitive::kPrimLong) {
+ HParallelMove parallel_move(GetGraph()->GetArena());
+ parallel_move.AddMove(return_loc.ToLow(), trg.ToLow(), Primitive::kPrimInt, nullptr);
+ parallel_move.AddMove(return_loc.ToHigh(), trg.ToHigh(), Primitive::kPrimInt, nullptr);
+ GetMoveResolver()->EmitNativeCode(¶llel_move);
+ } else if (type == Primitive::kPrimDouble) {
+ HParallelMove parallel_move(GetGraph()->GetArena());
+ parallel_move.AddMove(return_loc.ToLow(), trg.ToLow(), Primitive::kPrimFloat, nullptr);
+ parallel_move.AddMove(return_loc.ToHigh(), trg.ToHigh(), Primitive::kPrimFloat, nullptr);
+ GetMoveResolver()->EmitNativeCode(¶llel_move);
+ } else {
+ // Let the parallel move resolver take care of all of this.
+ HParallelMove parallel_move(GetGraph()->GetArena());
+ parallel_move.AddMove(return_loc, trg, type, nullptr);
+ GetMoveResolver()->EmitNativeCode(¶llel_move);
+ }
+}
+
#undef __
#undef QUICK_ENTRY_POINT