summaryrefslogtreecommitdiff
path: root/compiler/optimizing
diff options
context:
space:
mode:
author Nicolas Geoffray <ngeoffray@google.com> 2014-09-02 15:17:15 +0100
committer Nicolas Geoffray <ngeoffray@google.com> 2014-09-08 12:15:07 +0100
commit3946844c34ad965515f677084b07d663d70ad1b8 (patch)
tree0d85bfba2ff69c34a2897351d1e50a1464509305 /compiler/optimizing
parente2c23739c6395a83b30ece38f8a2e9e1bf7cf3ce (diff)
Runtime support for the new stack maps for the opt compiler.
Now most of the methods supported by the compiler can be optimized, instead of using the baseline. Change-Id: I80ab36a34913fa4e7dd576c7bf55af63594dc1fa
Diffstat (limited to 'compiler/optimizing')
-rw-r--r--compiler/optimizing/builder.cc11
-rw-r--r--compiler/optimizing/code_generator.cc104
-rw-r--r--compiler/optimizing/code_generator.h16
-rw-r--r--compiler/optimizing/code_generator_arm.cc129
-rw-r--r--compiler/optimizing/code_generator_x86.cc120
-rw-r--r--compiler/optimizing/code_generator_x86_64.cc128
-rw-r--r--compiler/optimizing/locations.cc22
-rw-r--r--compiler/optimizing/locations.h55
-rw-r--r--compiler/optimizing/nodes.cc4
-rw-r--r--compiler/optimizing/nodes.h33
-rw-r--r--compiler/optimizing/optimizing_compiler.cc63
-rw-r--r--compiler/optimizing/register_allocator.cc309
-rw-r--r--compiler/optimizing/register_allocator.h32
-rw-r--r--compiler/optimizing/register_allocator_test.cc22
-rw-r--r--compiler/optimizing/ssa_liveness_analysis.h49
-rw-r--r--compiler/optimizing/ssa_phi_elimination.cc4
-rw-r--r--compiler/optimizing/stack_map_stream.h31
-rw-r--r--compiler/optimizing/stack_map_test.cc24
18 files changed, 761 insertions, 395 deletions
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc
index 43e6b830e9..ecd6802ca4 100644
--- a/compiler/optimizing/builder.cc
+++ b/compiler/optimizing/builder.cc
@@ -413,6 +413,7 @@ bool HGraphBuilder::BuildFieldAccess(const Instruction& instruction,
current_block_->AddInstruction(new (arena_) HInstanceFieldSet(
null_check,
value,
+ field_type,
resolved_field->GetOffset()));
} else {
current_block_->AddInstruction(new (arena_) HInstanceFieldGet(
@@ -453,7 +454,8 @@ void HGraphBuilder::BuildArrayAccess(const Instruction& instruction,
if (is_put) {
HInstruction* value = LoadLocal(source_or_dest_reg, anticipated_type);
// TODO: Insert a type check node if the type is Object.
- current_block_->AddInstruction(new (arena_) HArraySet(object, index, value, dex_offset));
+ current_block_->AddInstruction(new (arena_) HArraySet(
+ object, index, value, anticipated_type, dex_offset));
} else {
current_block_->AddInstruction(new (arena_) HArrayGet(object, index, anticipated_type));
UpdateLocal(source_or_dest_reg, current_block_->GetLastInstruction());
@@ -750,6 +752,13 @@ bool HGraphBuilder::AnalyzeDexInstruction(const Instruction& instruction, int32_
ARRAY_XX(_CHAR, Primitive::kPrimChar);
ARRAY_XX(_SHORT, Primitive::kPrimShort);
+ case Instruction::ARRAY_LENGTH: {
+ HInstruction* object = LoadLocal(instruction.VRegB_12x(), Primitive::kPrimNot);
+ current_block_->AddInstruction(new (arena_) HArrayLength(object));
+ UpdateLocal(instruction.VRegA_12x(), current_block_->GetLastInstruction());
+ break;
+ }
+
default:
return false;
}
diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc
index 7269fff62c..7731e6e982 100644
--- a/compiler/optimizing/code_generator.cc
+++ b/compiler/optimizing/code_generator.cc
@@ -41,10 +41,11 @@ void CodeGenerator::CompileBaseline(CodeAllocator* allocator, bool is_leaf) {
if (!is_leaf) {
MarkNotLeaf();
}
- ComputeFrameSize(GetGraph()->GetMaximumNumberOfOutVRegs()
- + GetGraph()->GetNumberOfLocalVRegs()
- + GetGraph()->GetNumberOfTemporaries()
- + 1 /* filler */);
+ ComputeFrameSize(GetGraph()->GetNumberOfLocalVRegs()
+ + GetGraph()->GetNumberOfTemporaries()
+ + 1 /* filler */,
+ GetGraph()->GetMaximumNumberOfOutVRegs()
+ + 1 /* current method */);
GenerateFrameEntry();
for (size_t i = 0, e = blocks.Size(); i < e; ++i) {
@@ -110,10 +111,10 @@ size_t CodeGenerator::AllocateFreeRegisterInternal(
return -1;
}
-void CodeGenerator::ComputeFrameSize(size_t number_of_spill_slots) {
+void CodeGenerator::ComputeFrameSize(size_t number_of_spill_slots, size_t number_of_out_slots) {
SetFrameSize(RoundUp(
number_of_spill_slots * kVRegSize
- + kVRegSize // Art method
+ + number_of_out_slots * kVRegSize
+ FrameEntrySpillSize(),
kStackAlignment));
}
@@ -376,4 +377,95 @@ void CodeGenerator::BuildVMapTable(std::vector<uint8_t>* data) const {
*data = vmap_encoder.GetData();
}
+void CodeGenerator::BuildStackMaps(std::vector<uint8_t>* data) {
+ uint32_t size = stack_map_stream_.ComputeNeededSize();
+ data->resize(size);
+ MemoryRegion region(data->data(), size);
+ stack_map_stream_.FillIn(region);
+}
+
+void CodeGenerator::RecordPcInfo(HInstruction* instruction, uint32_t dex_pc) {
+ // Collect PC infos for the mapping table.
+ struct PcInfo pc_info;
+ pc_info.dex_pc = dex_pc;
+ pc_info.native_pc = GetAssembler()->CodeSize();
+ pc_infos_.Add(pc_info);
+
+ // Populate stack map information.
+
+ if (instruction == nullptr) {
+ // For stack overflow checks.
+ stack_map_stream_.AddStackMapEntry(dex_pc, pc_info.native_pc, 0, 0, 0, 0);
+ return;
+ }
+
+ LocationSummary* locations = instruction->GetLocations();
+ HEnvironment* environment = instruction->GetEnvironment();
+
+ size_t environment_size = instruction->EnvironmentSize();
+
+ size_t register_mask = 0;
+ size_t inlining_depth = 0;
+ stack_map_stream_.AddStackMapEntry(
+ dex_pc, pc_info.native_pc, register_mask,
+ locations->GetStackMask(), environment_size, inlining_depth);
+
+ // Walk over the environment, and record the location of dex registers.
+ for (size_t i = 0; i < environment_size; ++i) {
+ HInstruction* current = environment->GetInstructionAt(i);
+ if (current == nullptr) {
+ stack_map_stream_.AddDexRegisterEntry(DexRegisterMap::kNone, 0);
+ continue;
+ }
+
+ Location location = locations->GetEnvironmentAt(i);
+ switch (location.GetKind()) {
+ case Location::kConstant: {
+ DCHECK(current == location.GetConstant());
+ if (current->IsLongConstant()) {
+ int64_t value = current->AsLongConstant()->GetValue();
+ stack_map_stream_.AddDexRegisterEntry(DexRegisterMap::kConstant, Low32Bits(value));
+ stack_map_stream_.AddDexRegisterEntry(DexRegisterMap::kConstant, High32Bits(value));
+ ++i;
+ DCHECK_LT(i, environment_size);
+ } else {
+ DCHECK(current->IsIntConstant());
+ int32_t value = current->AsIntConstant()->GetValue();
+ stack_map_stream_.AddDexRegisterEntry(DexRegisterMap::kConstant, value);
+ }
+ break;
+ }
+
+ case Location::kStackSlot: {
+ stack_map_stream_.AddDexRegisterEntry(DexRegisterMap::kInStack, location.GetStackIndex());
+ break;
+ }
+
+ case Location::kDoubleStackSlot: {
+ stack_map_stream_.AddDexRegisterEntry(DexRegisterMap::kInStack, location.GetStackIndex());
+ stack_map_stream_.AddDexRegisterEntry(DexRegisterMap::kInStack,
+ location.GetHighStackIndex(kVRegSize));
+ ++i;
+ DCHECK_LT(i, environment_size);
+ break;
+ }
+
+ case Location::kRegister : {
+ int id = location.reg().RegId();
+ stack_map_stream_.AddDexRegisterEntry(DexRegisterMap::kInRegister, id);
+ if (current->GetType() == Primitive::kPrimDouble
+ || current->GetType() == Primitive::kPrimLong) {
+ stack_map_stream_.AddDexRegisterEntry(DexRegisterMap::kInRegister, id);
+ ++i;
+ DCHECK_LT(i, environment_size);
+ }
+ break;
+ }
+
+ default:
+ LOG(FATAL) << "Unexpected kind " << location.GetKind();
+ }
+ }
+}
+
} // namespace art
diff --git a/compiler/optimizing/code_generator.h b/compiler/optimizing/code_generator.h
index 12337c93de..a83d7032e3 100644
--- a/compiler/optimizing/code_generator.h
+++ b/compiler/optimizing/code_generator.h
@@ -23,6 +23,7 @@
#include "locations.h"
#include "memory_region.h"
#include "nodes.h"
+#include "stack_map_stream.h"
#include "utils/assembler.h"
namespace art {
@@ -97,7 +98,7 @@ class CodeGenerator : public ArenaObject {
virtual HGraphVisitor* GetInstructionVisitor() = 0;
virtual Assembler* GetAssembler() = 0;
virtual size_t GetWordSize() const = 0;
- void ComputeFrameSize(size_t number_of_spill_slots);
+ void ComputeFrameSize(size_t number_of_spill_slots, size_t number_of_out_slots);
virtual size_t FrameEntrySpillSize() const = 0;
int32_t GetStackSlot(HLocal* local) const;
Location GetTemporaryLocation(HTemporary* temp) const;
@@ -114,12 +115,7 @@ class CodeGenerator : public ArenaObject {
virtual void DumpFloatingPointRegister(std::ostream& stream, int reg) const = 0;
virtual InstructionSet GetInstructionSet() const = 0;
- void RecordPcInfo(uint32_t dex_pc) {
- struct PcInfo pc_info;
- pc_info.dex_pc = dex_pc;
- pc_info.native_pc = GetAssembler()->CodeSize();
- pc_infos_.Add(pc_info);
- }
+ void RecordPcInfo(HInstruction* instruction, uint32_t dex_pc);
void AddSlowPath(SlowPathCode* slow_path) {
slow_paths_.Add(slow_path);
@@ -131,6 +127,7 @@ class CodeGenerator : public ArenaObject {
void BuildVMapTable(std::vector<uint8_t>* vector) const;
void BuildNativeGCMap(
std::vector<uint8_t>* vector, const DexCompilationUnit& dex_compilation_unit) const;
+ void BuildStackMaps(std::vector<uint8_t>* vector);
bool IsLeafMethod() const {
return is_leaf_;
@@ -149,7 +146,8 @@ class CodeGenerator : public ArenaObject {
pc_infos_(graph->GetArena(), 32),
slow_paths_(graph->GetArena(), 8),
blocked_registers_(graph->GetArena()->AllocArray<bool>(number_of_registers)),
- is_leaf_(true) {}
+ is_leaf_(true),
+ stack_map_stream_(graph->GetArena()) {}
~CodeGenerator() {}
// Register allocation logic.
@@ -184,6 +182,8 @@ class CodeGenerator : public ArenaObject {
bool is_leaf_;
+ StackMapStream stack_map_stream_;
+
DISALLOW_COPY_AND_ASSIGN(CodeGenerator);
};
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc
index 2c954a0502..e72e39ba71 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -61,18 +61,18 @@ class InvokeRuntimeCallingConvention : public CallingConvention<Register> {
class NullCheckSlowPathARM : public SlowPathCode {
public:
- explicit NullCheckSlowPathARM(uint32_t dex_pc) : dex_pc_(dex_pc) {}
+ explicit NullCheckSlowPathARM(HNullCheck* instruction) : instruction_(instruction) {}
virtual void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
__ Bind(GetEntryLabel());
int32_t offset = QUICK_ENTRYPOINT_OFFSET(kArmWordSize, pThrowNullPointer).Int32Value();
__ ldr(LR, Address(TR, offset));
__ blx(LR);
- codegen->RecordPcInfo(dex_pc_);
+ codegen->RecordPcInfo(instruction_, instruction_->GetDexPc());
}
private:
- const uint32_t dex_pc_;
+ HNullCheck* const instruction_;
DISALLOW_COPY_AND_ASSIGN(NullCheckSlowPathARM);
};
@@ -92,10 +92,12 @@ class StackOverflowCheckSlowPathARM : public SlowPathCode {
class BoundsCheckSlowPathARM : public SlowPathCode {
public:
- explicit BoundsCheckSlowPathARM(uint32_t dex_pc,
+ explicit BoundsCheckSlowPathARM(HBoundsCheck* instruction,
Location index_location,
Location length_location)
- : dex_pc_(dex_pc), index_location_(index_location), length_location_(length_location) {}
+ : instruction_(instruction),
+ index_location_(index_location),
+ length_location_(length_location) {}
virtual void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
CodeGeneratorARM* arm_codegen = reinterpret_cast<CodeGeneratorARM*>(codegen);
@@ -106,11 +108,11 @@ class BoundsCheckSlowPathARM : public SlowPathCode {
int32_t offset = QUICK_ENTRYPOINT_OFFSET(kArmWordSize, pThrowArrayBounds).Int32Value();
__ ldr(LR, Address(TR, offset));
__ blx(LR);
- codegen->RecordPcInfo(dex_pc_);
+ codegen->RecordPcInfo(instruction_, instruction_->GetDexPc());
}
private:
- const uint32_t dex_pc_;
+ HBoundsCheck* const instruction_;
const Location index_location_;
const Location length_location_;
@@ -277,7 +279,7 @@ void CodeGeneratorARM::GenerateFrameEntry() {
} else {
__ AddConstant(IP, SP, -static_cast<int32_t>(GetStackOverflowReservedBytes(kArm)));
__ ldr(IP, Address(IP, 0));
- RecordPcInfo(0);
+ RecordPcInfo(nullptr, 0);
}
}
@@ -545,14 +547,14 @@ void InstructionCodeGeneratorARM::VisitExit(HExit* exit) {
}
void LocationsBuilderARM::VisitIf(HIf* if_instr) {
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(if_instr);
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(if_instr, LocationSummary::kNoCall);
HInstruction* cond = if_instr->InputAt(0);
DCHECK(cond->IsCondition());
HCondition* condition = cond->AsCondition();
if (condition->NeedsMaterialization()) {
locations->SetInAt(0, Location::Any());
}
- if_instr->SetLocations(locations);
}
void InstructionCodeGeneratorARM::VisitIf(HIf* if_instr) {
@@ -595,13 +597,13 @@ void InstructionCodeGeneratorARM::VisitIf(HIf* if_instr) {
void LocationsBuilderARM::VisitCondition(HCondition* comp) {
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(comp);
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(comp, LocationSummary::kNoCall);
locations->SetInAt(0, Location::RequiresRegister());
locations->SetInAt(1, Location::RegisterOrConstant(comp->InputAt(1)));
if (comp->NeedsMaterialization()) {
locations->SetOut(Location::RequiresRegister());
}
- comp->SetLocations(locations);
}
void InstructionCodeGeneratorARM::VisitCondition(HCondition* comp) {
@@ -695,7 +697,8 @@ void InstructionCodeGeneratorARM::VisitLoadLocal(HLoadLocal* load) {
}
void LocationsBuilderARM::VisitStoreLocal(HStoreLocal* store) {
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(store);
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(store, LocationSummary::kNoCall);
switch (store->InputAt(1)->GetType()) {
case Primitive::kPrimBoolean:
case Primitive::kPrimByte:
@@ -713,25 +716,24 @@ void LocationsBuilderARM::VisitStoreLocal(HStoreLocal* store) {
default:
LOG(FATAL) << "Unimplemented local type " << store->InputAt(1)->GetType();
}
- store->SetLocations(locations);
}
void InstructionCodeGeneratorARM::VisitStoreLocal(HStoreLocal* store) {
}
void LocationsBuilderARM::VisitIntConstant(HIntConstant* constant) {
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(constant);
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(constant, LocationSummary::kNoCall);
locations->SetOut(Location::ConstantLocation(constant));
- constant->SetLocations(locations);
}
void InstructionCodeGeneratorARM::VisitIntConstant(HIntConstant* constant) {
}
void LocationsBuilderARM::VisitLongConstant(HLongConstant* constant) {
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(constant);
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(constant, LocationSummary::kNoCall);
locations->SetOut(Location::ConstantLocation(constant));
- constant->SetLocations(locations);
}
void InstructionCodeGeneratorARM::VisitLongConstant(HLongConstant* constant) {
@@ -747,7 +749,8 @@ void InstructionCodeGeneratorARM::VisitReturnVoid(HReturnVoid* ret) {
}
void LocationsBuilderARM::VisitReturn(HReturn* ret) {
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(ret);
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(ret, LocationSummary::kNoCall);
switch (ret->InputAt(0)->GetType()) {
case Primitive::kPrimBoolean:
case Primitive::kPrimByte:
@@ -766,8 +769,6 @@ void LocationsBuilderARM::VisitReturn(HReturn* ret) {
default:
LOG(FATAL) << "Unimplemented return type " << ret->InputAt(0)->GetType();
}
-
- ret->SetLocations(locations);
}
void InstructionCodeGeneratorARM::VisitReturn(HReturn* ret) {
@@ -794,8 +795,8 @@ void InstructionCodeGeneratorARM::VisitReturn(HReturn* ret) {
}
void LocationsBuilderARM::VisitInvokeStatic(HInvokeStatic* invoke) {
- codegen_->MarkNotLeaf();
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(invoke);
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(invoke, LocationSummary::kCall);
locations->AddTemp(ArmCoreLocation(R0));
InvokeDexCallingConventionVisitor calling_convention_visitor;
@@ -826,8 +827,6 @@ void LocationsBuilderARM::VisitInvokeStatic(HInvokeStatic* invoke) {
LOG(FATAL) << "Unimplemented return type " << invoke->GetType();
break;
}
-
- invoke->SetLocations(locations);
}
void InstructionCodeGeneratorARM::LoadCurrentMethod(Register reg) {
@@ -859,12 +858,13 @@ void InstructionCodeGeneratorARM::VisitInvokeStatic(HInvokeStatic* invoke) {
// LR()
__ blx(LR);
- codegen_->RecordPcInfo(invoke->GetDexPc());
+ codegen_->RecordPcInfo(invoke, invoke->GetDexPc());
DCHECK(!codegen_->IsLeafMethod());
}
void LocationsBuilderARM::VisitAdd(HAdd* add) {
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(add);
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(add, LocationSummary::kNoCall);
switch (add->GetResultType()) {
case Primitive::kPrimInt:
case Primitive::kPrimLong: {
@@ -884,7 +884,6 @@ void LocationsBuilderARM::VisitAdd(HAdd* add) {
default:
LOG(FATAL) << "Unimplemented add type " << add->GetResultType();
}
- add->SetLocations(locations);
}
void InstructionCodeGeneratorARM::VisitAdd(HAdd* add) {
@@ -924,7 +923,8 @@ void InstructionCodeGeneratorARM::VisitAdd(HAdd* add) {
}
void LocationsBuilderARM::VisitSub(HSub* sub) {
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(sub);
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(sub, LocationSummary::kNoCall);
switch (sub->GetResultType()) {
case Primitive::kPrimInt:
case Primitive::kPrimLong: {
@@ -944,7 +944,6 @@ void LocationsBuilderARM::VisitSub(HSub* sub) {
default:
LOG(FATAL) << "Unimplemented sub type " << sub->GetResultType();
}
- sub->SetLocations(locations);
}
void InstructionCodeGeneratorARM::VisitSub(HSub* sub) {
@@ -985,13 +984,12 @@ void InstructionCodeGeneratorARM::VisitSub(HSub* sub) {
}
void LocationsBuilderARM::VisitNewInstance(HNewInstance* instruction) {
- codegen_->MarkNotLeaf();
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCall);
InvokeRuntimeCallingConvention calling_convention;
locations->AddTemp(ArmCoreLocation(calling_convention.GetRegisterAt(0)));
locations->AddTemp(ArmCoreLocation(calling_convention.GetRegisterAt(1)));
locations->SetOut(ArmCoreLocation(R0));
- instruction->SetLocations(locations);
}
void InstructionCodeGeneratorARM::VisitNewInstance(HNewInstance* instruction) {
@@ -1003,12 +1001,13 @@ void InstructionCodeGeneratorARM::VisitNewInstance(HNewInstance* instruction) {
__ ldr(LR, Address(TR, offset));
__ blx(LR);
- codegen_->RecordPcInfo(instruction->GetDexPc());
+ codegen_->RecordPcInfo(instruction, instruction->GetDexPc());
DCHECK(!codegen_->IsLeafMethod());
}
void LocationsBuilderARM::VisitParameterValue(HParameterValue* instruction) {
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
Location location = parameter_visitor_.GetNextLocation(instruction->GetType());
if (location.IsStackSlot()) {
location = Location::StackSlot(location.GetStackIndex() + codegen_->GetFrameSize());
@@ -1016,7 +1015,6 @@ void LocationsBuilderARM::VisitParameterValue(HParameterValue* instruction) {
location = Location::DoubleStackSlot(location.GetStackIndex() + codegen_->GetFrameSize());
}
locations->SetOut(location);
- instruction->SetLocations(locations);
}
void InstructionCodeGeneratorARM::VisitParameterValue(HParameterValue* instruction) {
@@ -1024,10 +1022,10 @@ void InstructionCodeGeneratorARM::VisitParameterValue(HParameterValue* instructi
}
void LocationsBuilderARM::VisitNot(HNot* instruction) {
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
locations->SetInAt(0, Location::RequiresRegister());
locations->SetOut(Location::RequiresRegister());
- instruction->SetLocations(locations);
}
void InstructionCodeGeneratorARM::VisitNot(HNot* instruction) {
@@ -1037,11 +1035,11 @@ void InstructionCodeGeneratorARM::VisitNot(HNot* instruction) {
}
void LocationsBuilderARM::VisitCompare(HCompare* compare) {
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(compare);
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(compare, LocationSummary::kNoCall);
locations->SetInAt(0, Location::RequiresRegister());
locations->SetInAt(1, Location::RequiresRegister());
locations->SetOut(Location::RequiresRegister());
- compare->SetLocations(locations);
}
void InstructionCodeGeneratorARM::VisitCompare(HCompare* compare) {
@@ -1081,12 +1079,12 @@ void InstructionCodeGeneratorARM::VisitCompare(HCompare* compare) {
}
void LocationsBuilderARM::VisitPhi(HPhi* instruction) {
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
for (size_t i = 0, e = instruction->InputCount(); i < e; ++i) {
locations->SetInAt(i, Location::Any());
}
locations->SetOut(Location::Any());
- instruction->SetLocations(locations);
}
void InstructionCodeGeneratorARM::VisitPhi(HPhi* instruction) {
@@ -1094,22 +1092,22 @@ void InstructionCodeGeneratorARM::VisitPhi(HPhi* instruction) {
}
void LocationsBuilderARM::VisitInstanceFieldSet(HInstanceFieldSet* instruction) {
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
locations->SetInAt(0, Location::RequiresRegister());
locations->SetInAt(1, Location::RequiresRegister());
// Temporary registers for the write barrier.
- if (instruction->InputAt(1)->GetType() == Primitive::kPrimNot) {
+ if (instruction->GetFieldType() == Primitive::kPrimNot) {
locations->AddTemp(Location::RequiresRegister());
locations->AddTemp(Location::RequiresRegister());
}
- instruction->SetLocations(locations);
}
void InstructionCodeGeneratorARM::VisitInstanceFieldSet(HInstanceFieldSet* instruction) {
LocationSummary* locations = instruction->GetLocations();
Register obj = locations->InAt(0).AsArm().AsCoreRegister();
uint32_t offset = instruction->GetFieldOffset().Uint32Value();
- Primitive::Type field_type = instruction->InputAt(1)->GetType();
+ Primitive::Type field_type = instruction->GetFieldType();
switch (field_type) {
case Primitive::kPrimBoolean:
@@ -1154,10 +1152,10 @@ void InstructionCodeGeneratorARM::VisitInstanceFieldSet(HInstanceFieldSet* instr
}
void LocationsBuilderARM::VisitInstanceFieldGet(HInstanceFieldGet* instruction) {
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
locations->SetInAt(0, Location::RequiresRegister());
locations->SetOut(Location::RequiresRegister());
- instruction->SetLocations(locations);
}
void InstructionCodeGeneratorARM::VisitInstanceFieldGet(HInstanceFieldGet* instruction) {
@@ -1214,16 +1212,15 @@ void InstructionCodeGeneratorARM::VisitInstanceFieldGet(HInstanceFieldGet* instr
}
void LocationsBuilderARM::VisitNullCheck(HNullCheck* instruction) {
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
locations->SetInAt(0, Location::RequiresRegister());
// TODO: Have a normalization phase that makes this instruction never used.
locations->SetOut(Location::SameAsFirstInput());
- instruction->SetLocations(locations);
}
void InstructionCodeGeneratorARM::VisitNullCheck(HNullCheck* instruction) {
- SlowPathCode* slow_path =
- new (GetGraph()->GetArena()) NullCheckSlowPathARM(instruction->GetDexPc());
+ SlowPathCode* slow_path = new (GetGraph()->GetArena()) NullCheckSlowPathARM(instruction);
codegen_->AddSlowPath(slow_path);
LocationSummary* locations = instruction->GetLocations();
@@ -1237,11 +1234,11 @@ void InstructionCodeGeneratorARM::VisitNullCheck(HNullCheck* instruction) {
}
void LocationsBuilderARM::VisitArrayGet(HArrayGet* instruction) {
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
locations->SetInAt(0, Location::RequiresRegister());
locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1)));
locations->SetOut(Location::RequiresRegister());
- instruction->SetLocations(locations);
}
void InstructionCodeGeneratorARM::VisitArrayGet(HArrayGet* instruction) {
@@ -1340,27 +1337,27 @@ void InstructionCodeGeneratorARM::VisitArrayGet(HArrayGet* instruction) {
}
void LocationsBuilderARM::VisitArraySet(HArraySet* instruction) {
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
- Primitive::Type value_type = instruction->InputAt(2)->GetType();
- if (value_type == Primitive::kPrimNot) {
+ Primitive::Type value_type = instruction->GetComponentType();
+ bool is_object = value_type == Primitive::kPrimNot;
+ LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(
+ instruction, is_object ? LocationSummary::kCall : LocationSummary::kNoCall);
+ if (is_object) {
InvokeRuntimeCallingConvention calling_convention;
locations->SetInAt(0, ArmCoreLocation(calling_convention.GetRegisterAt(0)));
locations->SetInAt(1, ArmCoreLocation(calling_convention.GetRegisterAt(1)));
locations->SetInAt(2, ArmCoreLocation(calling_convention.GetRegisterAt(2)));
- codegen_->MarkNotLeaf();
} else {
locations->SetInAt(0, Location::RequiresRegister());
locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1)));
locations->SetInAt(2, Location::RequiresRegister());
}
- instruction->SetLocations(locations);
}
void InstructionCodeGeneratorARM::VisitArraySet(HArraySet* instruction) {
LocationSummary* locations = instruction->GetLocations();
Register obj = locations->InAt(0).AsArm().AsCoreRegister();
Location index = locations->InAt(1);
- Primitive::Type value_type = instruction->InputAt(2)->GetType();
+ Primitive::Type value_type = instruction->GetComponentType();
switch (value_type) {
case Primitive::kPrimBoolean:
@@ -1408,7 +1405,7 @@ void InstructionCodeGeneratorARM::VisitArraySet(HArraySet* instruction) {
int32_t offset = QUICK_ENTRYPOINT_OFFSET(kArmWordSize, pAputObject).Int32Value();
__ ldr(LR, Address(TR, offset));
__ blx(LR);
- codegen_->RecordPcInfo(instruction->GetDexPc());
+ codegen_->RecordPcInfo(instruction, instruction->GetDexPc());
DCHECK(!codegen_->IsLeafMethod());
break;
}
@@ -1436,10 +1433,10 @@ void InstructionCodeGeneratorARM::VisitArraySet(HArraySet* instruction) {
}
void LocationsBuilderARM::VisitArrayLength(HArrayLength* instruction) {
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
locations->SetInAt(0, Location::RequiresRegister());
locations->SetOut(Location::RequiresRegister());
- instruction->SetLocations(locations);
}
void InstructionCodeGeneratorARM::VisitArrayLength(HArrayLength* instruction) {
@@ -1451,18 +1448,18 @@ void InstructionCodeGeneratorARM::VisitArrayLength(HArrayLength* instruction) {
}
void LocationsBuilderARM::VisitBoundsCheck(HBoundsCheck* instruction) {
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
locations->SetInAt(0, Location::RequiresRegister());
locations->SetInAt(1, Location::RequiresRegister());
// TODO: Have a normalization phase that makes this instruction never used.
locations->SetOut(Location::SameAsFirstInput());
- instruction->SetLocations(locations);
}
void InstructionCodeGeneratorARM::VisitBoundsCheck(HBoundsCheck* instruction) {
LocationSummary* locations = instruction->GetLocations();
SlowPathCode* slow_path = new (GetGraph()->GetArena()) BoundsCheckSlowPathARM(
- instruction->GetDexPc(), locations->InAt(0), locations->InAt(1));
+ instruction, locations->InAt(0), locations->InAt(1));
codegen_->AddSlowPath(slow_path);
Register index = locations->InAt(0).AsArm().AsCoreRegister();
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index 35b811628b..6602d3fb45 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -61,16 +61,16 @@ class InvokeRuntimeCallingConvention : public CallingConvention<Register> {
class NullCheckSlowPathX86 : public SlowPathCode {
public:
- explicit NullCheckSlowPathX86(uint32_t dex_pc) : dex_pc_(dex_pc) {}
+ explicit NullCheckSlowPathX86(HNullCheck* instruction) : instruction_(instruction) {}
virtual void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
__ Bind(GetEntryLabel());
__ fs()->call(Address::Absolute(QUICK_ENTRYPOINT_OFFSET(kX86WordSize, pThrowNullPointer)));
- codegen->RecordPcInfo(dex_pc_);
+ codegen->RecordPcInfo(instruction_, instruction_->GetDexPc());
}
private:
- const uint32_t dex_pc_;
+ HNullCheck* const instruction_;
DISALLOW_COPY_AND_ASSIGN(NullCheckSlowPathX86);
};
@@ -91,10 +91,10 @@ class StackOverflowCheckSlowPathX86 : public SlowPathCode {
class BoundsCheckSlowPathX86 : public SlowPathCode {
public:
- explicit BoundsCheckSlowPathX86(uint32_t dex_pc,
+ explicit BoundsCheckSlowPathX86(HBoundsCheck* instruction,
Location index_location,
Location length_location)
- : dex_pc_(dex_pc), index_location_(index_location), length_location_(length_location) {}
+ : instruction_(instruction), index_location_(index_location), length_location_(length_location) {}
virtual void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
CodeGeneratorX86* x86_codegen = reinterpret_cast<CodeGeneratorX86*>(codegen);
@@ -103,11 +103,11 @@ class BoundsCheckSlowPathX86 : public SlowPathCode {
x86_codegen->Move32(X86CpuLocation(calling_convention.GetRegisterAt(0)), index_location_);
x86_codegen->Move32(X86CpuLocation(calling_convention.GetRegisterAt(1)), length_location_);
__ fs()->call(Address::Absolute(QUICK_ENTRYPOINT_OFFSET(kX86WordSize, pThrowArrayBounds)));
- codegen->RecordPcInfo(dex_pc_);
+ codegen->RecordPcInfo(instruction_, instruction_->GetDexPc());
}
private:
- const uint32_t dex_pc_;
+ HBoundsCheck* const instruction_;
const Location index_location_;
const Location length_location_;
@@ -244,7 +244,7 @@ void CodeGeneratorX86::GenerateFrameEntry() {
bool skip_overflow_check = IsLeafMethod() && !FrameNeedsStackCheck(GetFrameSize(), InstructionSet::kX86);
if (!skip_overflow_check && !kExplicitStackOverflowCheck) {
__ testl(EAX, Address(ESP, -static_cast<int32_t>(GetStackOverflowReservedBytes(kX86))));
- RecordPcInfo(0);
+ RecordPcInfo(nullptr, 0);
}
// The return PC has already been pushed on the stack.
@@ -398,6 +398,7 @@ void CodeGeneratorX86::Move64(Location destination, Location source) {
__ popl(Address(ESP, calling_convention.GetStackOffsetOf(argument_index + 1)));
}
} else {
+ DCHECK(destination.IsDoubleStackSlot());
if (source.IsRegister()) {
__ movl(Address(ESP, destination.GetStackIndex()), source.AsX86().AsRegisterPairLow());
__ movl(Address(ESP, destination.GetHighStackIndex(kX86WordSize)),
@@ -503,14 +504,14 @@ void InstructionCodeGeneratorX86::VisitExit(HExit* exit) {
}
void LocationsBuilderX86::VisitIf(HIf* if_instr) {
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(if_instr);
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(if_instr, LocationSummary::kNoCall);
HInstruction* cond = if_instr->InputAt(0);
DCHECK(cond->IsCondition());
HCondition* condition = cond->AsCondition();
if (condition->NeedsMaterialization()) {
locations->SetInAt(0, Location::Any());
}
- if_instr->SetLocations(locations);
}
void InstructionCodeGeneratorX86::VisitIf(HIf* if_instr) {
@@ -564,7 +565,8 @@ void InstructionCodeGeneratorX86::VisitLoadLocal(HLoadLocal* load) {
}
void LocationsBuilderX86::VisitStoreLocal(HStoreLocal* store) {
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(store);
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(store, LocationSummary::kNoCall);
switch (store->InputAt(1)->GetType()) {
case Primitive::kPrimBoolean:
case Primitive::kPrimByte:
@@ -589,13 +591,13 @@ void InstructionCodeGeneratorX86::VisitStoreLocal(HStoreLocal* store) {
}
void LocationsBuilderX86::VisitCondition(HCondition* comp) {
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(comp);
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(comp, LocationSummary::kNoCall);
locations->SetInAt(0, Location::RequiresRegister());
locations->SetInAt(1, Location::Any());
if (comp->NeedsMaterialization()) {
locations->SetOut(Location::RequiresRegister());
}
- comp->SetLocations(locations);
}
void InstructionCodeGeneratorX86::VisitCondition(HCondition* comp) {
@@ -665,18 +667,18 @@ void InstructionCodeGeneratorX86::VisitGreaterThanOrEqual(HGreaterThanOrEqual* c
}
void LocationsBuilderX86::VisitIntConstant(HIntConstant* constant) {
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(constant);
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(constant, LocationSummary::kNoCall);
locations->SetOut(Location::ConstantLocation(constant));
- constant->SetLocations(locations);
}
void InstructionCodeGeneratorX86::VisitIntConstant(HIntConstant* constant) {
}
void LocationsBuilderX86::VisitLongConstant(HLongConstant* constant) {
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(constant);
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(constant, LocationSummary::kNoCall);
locations->SetOut(Location::ConstantLocation(constant));
- constant->SetLocations(locations);
}
void InstructionCodeGeneratorX86::VisitLongConstant(HLongConstant* constant) {
@@ -693,7 +695,8 @@ void InstructionCodeGeneratorX86::VisitReturnVoid(HReturnVoid* ret) {
}
void LocationsBuilderX86::VisitReturn(HReturn* ret) {
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(ret);
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(ret, LocationSummary::kNoCall);
switch (ret->InputAt(0)->GetType()) {
case Primitive::kPrimBoolean:
case Primitive::kPrimByte:
@@ -712,7 +715,6 @@ void LocationsBuilderX86::VisitReturn(HReturn* ret) {
default:
LOG(FATAL) << "Unimplemented return type " << ret->InputAt(0)->GetType();
}
- ret->SetLocations(locations);
}
void InstructionCodeGeneratorX86::VisitReturn(HReturn* ret) {
@@ -740,8 +742,8 @@ void InstructionCodeGeneratorX86::VisitReturn(HReturn* ret) {
}
void LocationsBuilderX86::VisitInvokeStatic(HInvokeStatic* invoke) {
- codegen_->MarkNotLeaf();
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(invoke);
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(invoke, LocationSummary::kCall);
locations->AddTemp(X86CpuLocation(EAX));
InvokeDexCallingConventionVisitor calling_convention_visitor;
@@ -799,11 +801,12 @@ void InstructionCodeGeneratorX86::VisitInvokeStatic(HInvokeStatic* invoke) {
__ call(Address(temp, mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset().Int32Value()));
DCHECK(!codegen_->IsLeafMethod());
- codegen_->RecordPcInfo(invoke->GetDexPc());
+ codegen_->RecordPcInfo(invoke, invoke->GetDexPc());
}
void LocationsBuilderX86::VisitAdd(HAdd* add) {
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(add);
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(add, LocationSummary::kNoCall);
switch (add->GetResultType()) {
case Primitive::kPrimInt:
case Primitive::kPrimLong: {
@@ -823,7 +826,6 @@ void LocationsBuilderX86::VisitAdd(HAdd* add) {
default:
LOG(FATAL) << "Unimplemented add type " << add->GetResultType();
}
- add->SetLocations(locations);
}
void InstructionCodeGeneratorX86::VisitAdd(HAdd* add) {
@@ -876,7 +878,8 @@ void InstructionCodeGeneratorX86::VisitAdd(HAdd* add) {
}
void LocationsBuilderX86::VisitSub(HSub* sub) {
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(sub);
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(sub, LocationSummary::kNoCall);
switch (sub->GetResultType()) {
case Primitive::kPrimInt:
case Primitive::kPrimLong: {
@@ -896,7 +899,6 @@ void LocationsBuilderX86::VisitSub(HSub* sub) {
default:
LOG(FATAL) << "Unimplemented sub type " << sub->GetResultType();
}
- sub->SetLocations(locations);
}
void InstructionCodeGeneratorX86::VisitSub(HSub* sub) {
@@ -949,13 +951,12 @@ void InstructionCodeGeneratorX86::VisitSub(HSub* sub) {
}
void LocationsBuilderX86::VisitNewInstance(HNewInstance* instruction) {
- codegen_->MarkNotLeaf();
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCall);
locations->SetOut(X86CpuLocation(EAX));
InvokeRuntimeCallingConvention calling_convention;
locations->AddTemp(X86CpuLocation(calling_convention.GetRegisterAt(0)));
locations->AddTemp(X86CpuLocation(calling_convention.GetRegisterAt(1)));
- instruction->SetLocations(locations);
}
void InstructionCodeGeneratorX86::VisitNewInstance(HNewInstance* instruction) {
@@ -966,12 +967,13 @@ void InstructionCodeGeneratorX86::VisitNewInstance(HNewInstance* instruction) {
__ fs()->call(
Address::Absolute(QUICK_ENTRYPOINT_OFFSET(kX86WordSize, pAllocObjectWithAccessCheck)));
- codegen_->RecordPcInfo(instruction->GetDexPc());
+ codegen_->RecordPcInfo(instruction, instruction->GetDexPc());
DCHECK(!codegen_->IsLeafMethod());
}
void LocationsBuilderX86::VisitParameterValue(HParameterValue* instruction) {
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
Location location = parameter_visitor_.GetNextLocation(instruction->GetType());
if (location.IsStackSlot()) {
location = Location::StackSlot(location.GetStackIndex() + codegen_->GetFrameSize());
@@ -979,17 +981,16 @@ void LocationsBuilderX86::VisitParameterValue(HParameterValue* instruction) {
location = Location::DoubleStackSlot(location.GetStackIndex() + codegen_->GetFrameSize());
}
locations->SetOut(location);
- instruction->SetLocations(locations);
}
void InstructionCodeGeneratorX86::VisitParameterValue(HParameterValue* instruction) {
}
void LocationsBuilderX86::VisitNot(HNot* instruction) {
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
locations->SetInAt(0, Location::RequiresRegister());
locations->SetOut(Location::SameAsFirstInput());
- instruction->SetLocations(locations);
}
void InstructionCodeGeneratorX86::VisitNot(HNot* instruction) {
@@ -1000,11 +1001,11 @@ void InstructionCodeGeneratorX86::VisitNot(HNot* instruction) {
}
void LocationsBuilderX86::VisitCompare(HCompare* compare) {
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(compare);
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(compare, LocationSummary::kNoCall);
locations->SetInAt(0, Location::RequiresRegister());
locations->SetInAt(1, Location::Any());
locations->SetOut(Location::RequiresRegister());
- compare->SetLocations(locations);
}
void InstructionCodeGeneratorX86::VisitCompare(HCompare* compare) {
@@ -1050,12 +1051,12 @@ void InstructionCodeGeneratorX86::VisitCompare(HCompare* compare) {
}
void LocationsBuilderX86::VisitPhi(HPhi* instruction) {
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
for (size_t i = 0, e = instruction->InputCount(); i < e; ++i) {
locations->SetInAt(i, Location::Any());
}
locations->SetOut(Location::Any());
- instruction->SetLocations(locations);
}
void InstructionCodeGeneratorX86::VisitPhi(HPhi* instruction) {
@@ -1063,9 +1064,10 @@ void InstructionCodeGeneratorX86::VisitPhi(HPhi* instruction) {
}
void LocationsBuilderX86::VisitInstanceFieldSet(HInstanceFieldSet* instruction) {
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
locations->SetInAt(0, Location::RequiresRegister());
- Primitive::Type field_type = instruction->InputAt(1)->GetType();
+ Primitive::Type field_type = instruction->GetFieldType();
if (field_type == Primitive::kPrimBoolean || field_type == Primitive::kPrimByte) {
// Ensure the value is in a byte register.
locations->SetInAt(1, X86CpuLocation(EAX));
@@ -1078,14 +1080,13 @@ void LocationsBuilderX86::VisitInstanceFieldSet(HInstanceFieldSet* instruction)
// Ensure the card is in a byte register.
locations->AddTemp(X86CpuLocation(ECX));
}
- instruction->SetLocations(locations);
}
void InstructionCodeGeneratorX86::VisitInstanceFieldSet(HInstanceFieldSet* instruction) {
LocationSummary* locations = instruction->GetLocations();
Register obj = locations->InAt(0).AsX86().AsCpuRegister();
uint32_t offset = instruction->GetFieldOffset().Uint32Value();
- Primitive::Type field_type = instruction->InputAt(1)->GetType();
+ Primitive::Type field_type = instruction->GetFieldType();
switch (field_type) {
case Primitive::kPrimBoolean:
@@ -1144,10 +1145,10 @@ void CodeGeneratorX86::MarkGCCard(Register temp, Register card, Register object,
}
void LocationsBuilderX86::VisitInstanceFieldGet(HInstanceFieldGet* instruction) {
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
locations->SetInAt(0, Location::RequiresRegister());
locations->SetOut(Location::RequiresRegister());
- instruction->SetLocations(locations);
}
void InstructionCodeGeneratorX86::VisitInstanceFieldGet(HInstanceFieldGet* instruction) {
@@ -1205,16 +1206,15 @@ void InstructionCodeGeneratorX86::VisitInstanceFieldGet(HInstanceFieldGet* instr
}
void LocationsBuilderX86::VisitNullCheck(HNullCheck* instruction) {
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
locations->SetInAt(0, Location::Any());
// TODO: Have a normalization phase that makes this instruction never used.
locations->SetOut(Location::SameAsFirstInput());
- instruction->SetLocations(locations);
}
void InstructionCodeGeneratorX86::VisitNullCheck(HNullCheck* instruction) {
- SlowPathCode* slow_path =
- new (GetGraph()->GetArena()) NullCheckSlowPathX86(instruction->GetDexPc());
+ SlowPathCode* slow_path = new (GetGraph()->GetArena()) NullCheckSlowPathX86(instruction);
codegen_->AddSlowPath(slow_path);
LocationSummary* locations = instruction->GetLocations();
@@ -1231,11 +1231,11 @@ void InstructionCodeGeneratorX86::VisitNullCheck(HNullCheck* instruction) {
}
void LocationsBuilderX86::VisitArrayGet(HArrayGet* instruction) {
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
locations->SetInAt(0, Location::RequiresRegister());
locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1)));
locations->SetOut(Location::RequiresRegister());
- instruction->SetLocations(locations);
}
void InstructionCodeGeneratorX86::VisitArrayGet(HArrayGet* instruction) {
@@ -1331,14 +1331,16 @@ void InstructionCodeGeneratorX86::VisitArrayGet(HArrayGet* instruction) {
}
void LocationsBuilderX86::VisitArraySet(HArraySet* instruction) {
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
- Primitive::Type value_type = instruction->InputAt(2)->GetType();
+ Primitive::Type value_type = instruction->GetComponentType();
+ LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(
+ instruction,
+ value_type == Primitive::kPrimNot ? LocationSummary::kCall : LocationSummary::kNoCall);
+
if (value_type == Primitive::kPrimNot) {
InvokeRuntimeCallingConvention calling_convention;
locations->SetInAt(0, X86CpuLocation(calling_convention.GetRegisterAt(0)));
locations->SetInAt(1, X86CpuLocation(calling_convention.GetRegisterAt(1)));
locations->SetInAt(2, X86CpuLocation(calling_convention.GetRegisterAt(2)));
- codegen_->MarkNotLeaf();
} else {
locations->SetInAt(0, Location::RequiresRegister());
locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1)));
@@ -1349,15 +1351,13 @@ void LocationsBuilderX86::VisitArraySet(HArraySet* instruction) {
locations->SetInAt(2, Location::RequiresRegister());
}
}
-
- instruction->SetLocations(locations);
}
void InstructionCodeGeneratorX86::VisitArraySet(HArraySet* instruction) {
LocationSummary* locations = instruction->GetLocations();
Register obj = locations->InAt(0).AsX86().AsCpuRegister();
Location index = locations->InAt(1);
- Primitive::Type value_type = instruction->InputAt(2)->GetType();
+ Primitive::Type value_type = instruction->GetComponentType();
switch (value_type) {
case Primitive::kPrimBoolean:
@@ -1401,7 +1401,7 @@ void InstructionCodeGeneratorX86::VisitArraySet(HArraySet* instruction) {
case Primitive::kPrimNot: {
DCHECK(!codegen_->IsLeafMethod());
__ fs()->call(Address::Absolute(QUICK_ENTRYPOINT_OFFSET(kX86WordSize, pAputObject)));
- codegen_->RecordPcInfo(instruction->GetDexPc());
+ codegen_->RecordPcInfo(instruction, instruction->GetDexPc());
break;
}
@@ -1446,18 +1446,18 @@ void InstructionCodeGeneratorX86::VisitArrayLength(HArrayLength* instruction) {
}
void LocationsBuilderX86::VisitBoundsCheck(HBoundsCheck* instruction) {
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
locations->SetInAt(0, Location::RequiresRegister());
locations->SetInAt(1, Location::RequiresRegister());
// TODO: Have a normalization phase that makes this instruction never used.
locations->SetOut(Location::SameAsFirstInput());
- instruction->SetLocations(locations);
}
void InstructionCodeGeneratorX86::VisitBoundsCheck(HBoundsCheck* instruction) {
LocationSummary* locations = instruction->GetLocations();
SlowPathCode* slow_path = new (GetGraph()->GetArena()) BoundsCheckSlowPathX86(
- instruction->GetDexPc(), locations->InAt(0), locations->InAt(1));
+ instruction, locations->InAt(0), locations->InAt(1));
codegen_->AddSlowPath(slow_path);
Register index = locations->InAt(0).AsX86().AsCpuRegister();
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index c4571caf27..b2d81e35dd 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -65,17 +65,17 @@ class InvokeRuntimeCallingConvention : public CallingConvention<Register> {
class NullCheckSlowPathX86_64 : public SlowPathCode {
public:
- explicit NullCheckSlowPathX86_64(uint32_t dex_pc) : dex_pc_(dex_pc) {}
+ explicit NullCheckSlowPathX86_64(HNullCheck* instruction) : instruction_(instruction) {}
virtual void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
__ Bind(GetEntryLabel());
__ gs()->call(
Address::Absolute(QUICK_ENTRYPOINT_OFFSET(kX86_64WordSize, pThrowNullPointer), true));
- codegen->RecordPcInfo(dex_pc_);
+ codegen->RecordPcInfo(instruction_, instruction_->GetDexPc());
}
private:
- const uint32_t dex_pc_;
+ HNullCheck* const instruction_;
DISALLOW_COPY_AND_ASSIGN(NullCheckSlowPathX86_64);
};
@@ -97,10 +97,12 @@ class StackOverflowCheckSlowPathX86_64 : public SlowPathCode {
class BoundsCheckSlowPathX86_64 : public SlowPathCode {
public:
- explicit BoundsCheckSlowPathX86_64(uint32_t dex_pc,
+ explicit BoundsCheckSlowPathX86_64(HBoundsCheck* instruction,
Location index_location,
Location length_location)
- : dex_pc_(dex_pc), index_location_(index_location), length_location_(length_location) {}
+ : instruction_(instruction),
+ index_location_(index_location),
+ length_location_(length_location) {}
virtual void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
CodeGeneratorX86_64* x64_codegen = reinterpret_cast<CodeGeneratorX86_64*>(codegen);
@@ -110,11 +112,11 @@ class BoundsCheckSlowPathX86_64 : public SlowPathCode {
x64_codegen->Move(X86_64CpuLocation(calling_convention.GetRegisterAt(1)), length_location_);
__ gs()->call(Address::Absolute(
QUICK_ENTRYPOINT_OFFSET(kX86_64WordSize, pThrowArrayBounds), true));
- codegen->RecordPcInfo(dex_pc_);
+ codegen->RecordPcInfo(instruction_, instruction_->GetDexPc());
}
private:
- const uint32_t dex_pc_;
+ HBoundsCheck* const instruction_;
const Location index_location_;
const Location length_location_;
@@ -214,7 +216,7 @@ void CodeGeneratorX86_64::GenerateFrameEntry() {
if (!skip_overflow_check && !kExplicitStackOverflowCheck) {
__ testq(CpuRegister(RAX), Address(
CpuRegister(RSP), -static_cast<int32_t>(GetStackOverflowReservedBytes(kX86_64))));
- RecordPcInfo(0);
+ RecordPcInfo(nullptr, 0);
}
// The return PC has already been pushed on the stack.
@@ -385,14 +387,14 @@ void InstructionCodeGeneratorX86_64::VisitExit(HExit* exit) {
}
void LocationsBuilderX86_64::VisitIf(HIf* if_instr) {
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(if_instr);
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(if_instr, LocationSummary::kNoCall);
HInstruction* cond = if_instr->InputAt(0);
DCHECK(cond->IsCondition());
HCondition* condition = cond->AsCondition();
if (condition->NeedsMaterialization()) {
locations->SetInAt(0, Location::Any());
}
- if_instr->SetLocations(locations);
}
void InstructionCodeGeneratorX86_64::VisitIf(HIf* if_instr) {
@@ -444,7 +446,8 @@ void InstructionCodeGeneratorX86_64::VisitLoadLocal(HLoadLocal* load) {
}
void LocationsBuilderX86_64::VisitStoreLocal(HStoreLocal* store) {
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(store);
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(store, LocationSummary::kNoCall);
switch (store->InputAt(1)->GetType()) {
case Primitive::kPrimBoolean:
case Primitive::kPrimByte:
@@ -462,20 +465,19 @@ void LocationsBuilderX86_64::VisitStoreLocal(HStoreLocal* store) {
default:
LOG(FATAL) << "Unimplemented local type " << store->InputAt(1)->GetType();
}
- store->SetLocations(locations);
}
void InstructionCodeGeneratorX86_64::VisitStoreLocal(HStoreLocal* store) {
}
void LocationsBuilderX86_64::VisitCondition(HCondition* comp) {
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(comp);
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(comp, LocationSummary::kNoCall);
locations->SetInAt(0, Location::RequiresRegister());
locations->SetInAt(1, Location::Any());
if (comp->NeedsMaterialization()) {
locations->SetOut(Location::RequiresRegister());
}
- comp->SetLocations(locations);
}
void InstructionCodeGeneratorX86_64::VisitCondition(HCondition* comp) {
@@ -545,11 +547,11 @@ void InstructionCodeGeneratorX86_64::VisitGreaterThanOrEqual(HGreaterThanOrEqual
}
void LocationsBuilderX86_64::VisitCompare(HCompare* compare) {
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(compare);
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(compare, LocationSummary::kNoCall);
locations->SetInAt(0, Location::RequiresRegister());
locations->SetInAt(1, Location::RequiresRegister());
locations->SetOut(Location::RequiresRegister());
- compare->SetLocations(locations);
}
void InstructionCodeGeneratorX86_64::VisitCompare(HCompare* compare) {
@@ -578,18 +580,18 @@ void InstructionCodeGeneratorX86_64::VisitCompare(HCompare* compare) {
}
void LocationsBuilderX86_64::VisitIntConstant(HIntConstant* constant) {
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(constant);
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(constant, LocationSummary::kNoCall);
locations->SetOut(Location::ConstantLocation(constant));
- constant->SetLocations(locations);
}
void InstructionCodeGeneratorX86_64::VisitIntConstant(HIntConstant* constant) {
}
void LocationsBuilderX86_64::VisitLongConstant(HLongConstant* constant) {
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(constant);
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(constant, LocationSummary::kNoCall);
locations->SetOut(Location::ConstantLocation(constant));
- constant->SetLocations(locations);
}
void InstructionCodeGeneratorX86_64::VisitLongConstant(HLongConstant* constant) {
@@ -605,7 +607,8 @@ void InstructionCodeGeneratorX86_64::VisitReturnVoid(HReturnVoid* ret) {
}
void LocationsBuilderX86_64::VisitReturn(HReturn* ret) {
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(ret);
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(ret, LocationSummary::kNoCall);
switch (ret->InputAt(0)->GetType()) {
case Primitive::kPrimBoolean:
case Primitive::kPrimByte:
@@ -620,7 +623,6 @@ void LocationsBuilderX86_64::VisitReturn(HReturn* ret) {
default:
LOG(FATAL) << "Unimplemented return type " << ret->InputAt(0)->GetType();
}
- ret->SetLocations(locations);
}
void InstructionCodeGeneratorX86_64::VisitReturn(HReturn* ret) {
@@ -686,8 +688,8 @@ Location InvokeDexCallingConventionVisitor::GetNextLocation(Primitive::Type type
}
void LocationsBuilderX86_64::VisitInvokeStatic(HInvokeStatic* invoke) {
- codegen_->MarkNotLeaf();
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(invoke);
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(invoke, LocationSummary::kCall);
locations->AddTemp(X86_64CpuLocation(RDI));
InvokeDexCallingConventionVisitor calling_convention_visitor;
@@ -715,8 +717,6 @@ void LocationsBuilderX86_64::VisitInvokeStatic(HInvokeStatic* invoke) {
LOG(FATAL) << "Unimplemented return type " << invoke->GetType();
break;
}
-
- invoke->SetLocations(locations);
}
void InstructionCodeGeneratorX86_64::VisitInvokeStatic(HInvokeStatic* invoke) {
@@ -742,11 +742,12 @@ void InstructionCodeGeneratorX86_64::VisitInvokeStatic(HInvokeStatic* invoke) {
__ call(Address(temp, mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset().SizeValue()));
DCHECK(!codegen_->IsLeafMethod());
- codegen_->RecordPcInfo(invoke->GetDexPc());
+ codegen_->RecordPcInfo(invoke, invoke->GetDexPc());
}
void LocationsBuilderX86_64::VisitAdd(HAdd* add) {
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(add);
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(add, LocationSummary::kNoCall);
switch (add->GetResultType()) {
case Primitive::kPrimInt: {
locations->SetInAt(0, Location::RequiresRegister());
@@ -771,7 +772,6 @@ void LocationsBuilderX86_64::VisitAdd(HAdd* add) {
default:
LOG(FATAL) << "Unimplemented add type " << add->GetResultType();
}
- add->SetLocations(locations);
}
void InstructionCodeGeneratorX86_64::VisitAdd(HAdd* add) {
@@ -812,7 +812,8 @@ void InstructionCodeGeneratorX86_64::VisitAdd(HAdd* add) {
}
void LocationsBuilderX86_64::VisitSub(HSub* sub) {
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(sub);
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(sub, LocationSummary::kNoCall);
switch (sub->GetResultType()) {
case Primitive::kPrimInt: {
locations->SetInAt(0, Location::RequiresRegister());
@@ -837,7 +838,6 @@ void LocationsBuilderX86_64::VisitSub(HSub* sub) {
default:
LOG(FATAL) << "Unimplemented sub type " << sub->GetResultType();
}
- sub->SetLocations(locations);
}
void InstructionCodeGeneratorX86_64::VisitSub(HSub* sub) {
@@ -878,10 +878,9 @@ void InstructionCodeGeneratorX86_64::VisitSub(HSub* sub) {
}
void LocationsBuilderX86_64::VisitNewInstance(HNewInstance* instruction) {
- codegen_->MarkNotLeaf();
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCall);
locations->SetOut(X86_64CpuLocation(RAX));
- instruction->SetLocations(locations);
}
void InstructionCodeGeneratorX86_64::VisitNewInstance(HNewInstance* instruction) {
@@ -893,11 +892,12 @@ void InstructionCodeGeneratorX86_64::VisitNewInstance(HNewInstance* instruction)
QUICK_ENTRYPOINT_OFFSET(kX86_64WordSize, pAllocObjectWithAccessCheck), true));
DCHECK(!codegen_->IsLeafMethod());
- codegen_->RecordPcInfo(instruction->GetDexPc());
+ codegen_->RecordPcInfo(instruction, instruction->GetDexPc());
}
void LocationsBuilderX86_64::VisitParameterValue(HParameterValue* instruction) {
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
Location location = parameter_visitor_.GetNextLocation(instruction->GetType());
if (location.IsStackSlot()) {
location = Location::StackSlot(location.GetStackIndex() + codegen_->GetFrameSize());
@@ -905,7 +905,6 @@ void LocationsBuilderX86_64::VisitParameterValue(HParameterValue* instruction) {
location = Location::DoubleStackSlot(location.GetStackIndex() + codegen_->GetFrameSize());
}
locations->SetOut(location);
- instruction->SetLocations(locations);
}
void InstructionCodeGeneratorX86_64::VisitParameterValue(HParameterValue* instruction) {
@@ -913,10 +912,10 @@ void InstructionCodeGeneratorX86_64::VisitParameterValue(HParameterValue* instru
}
void LocationsBuilderX86_64::VisitNot(HNot* instruction) {
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
locations->SetInAt(0, Location::RequiresRegister());
locations->SetOut(Location::SameAsFirstInput());
- instruction->SetLocations(locations);
}
void InstructionCodeGeneratorX86_64::VisitNot(HNot* instruction) {
@@ -927,12 +926,12 @@ void InstructionCodeGeneratorX86_64::VisitNot(HNot* instruction) {
}
void LocationsBuilderX86_64::VisitPhi(HPhi* instruction) {
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
for (size_t i = 0, e = instruction->InputCount(); i < e; ++i) {
locations->SetInAt(i, Location::Any());
}
locations->SetOut(Location::Any());
- instruction->SetLocations(locations);
}
void InstructionCodeGeneratorX86_64::VisitPhi(HPhi* instruction) {
@@ -940,15 +939,15 @@ void InstructionCodeGeneratorX86_64::VisitPhi(HPhi* instruction) {
}
void LocationsBuilderX86_64::VisitInstanceFieldSet(HInstanceFieldSet* instruction) {
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
locations->SetInAt(0, Location::RequiresRegister());
locations->SetInAt(1, Location::RequiresRegister());
// Temporary registers for the write barrier.
- if (instruction->InputAt(1)->GetType() == Primitive::kPrimNot) {
+ if (instruction->GetFieldType() == Primitive::kPrimNot) {
locations->AddTemp(Location::RequiresRegister());
locations->AddTemp(Location::RequiresRegister());
}
- instruction->SetLocations(locations);
}
void InstructionCodeGeneratorX86_64::VisitInstanceFieldSet(HInstanceFieldSet* instruction) {
@@ -956,7 +955,7 @@ void InstructionCodeGeneratorX86_64::VisitInstanceFieldSet(HInstanceFieldSet* in
CpuRegister obj = locations->InAt(0).AsX86_64().AsCpuRegister();
CpuRegister value = locations->InAt(1).AsX86_64().AsCpuRegister();
size_t offset = instruction->GetFieldOffset().SizeValue();
- Primitive::Type field_type = instruction->InputAt(1)->GetType();
+ Primitive::Type field_type = instruction->GetFieldType();
switch (field_type) {
case Primitive::kPrimBoolean:
@@ -997,10 +996,10 @@ void InstructionCodeGeneratorX86_64::VisitInstanceFieldSet(HInstanceFieldSet* in
}
void LocationsBuilderX86_64::VisitInstanceFieldGet(HInstanceFieldGet* instruction) {
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
locations->SetInAt(0, Location::RequiresRegister());
locations->SetOut(Location::RequiresRegister());
- instruction->SetLocations(locations);
}
void InstructionCodeGeneratorX86_64::VisitInstanceFieldGet(HInstanceFieldGet* instruction) {
@@ -1051,16 +1050,15 @@ void InstructionCodeGeneratorX86_64::VisitInstanceFieldGet(HInstanceFieldGet* in
}
void LocationsBuilderX86_64::VisitNullCheck(HNullCheck* instruction) {
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
locations->SetInAt(0, Location::Any());
// TODO: Have a normalization phase that makes this instruction never used.
locations->SetOut(Location::SameAsFirstInput());
- instruction->SetLocations(locations);
}
void InstructionCodeGeneratorX86_64::VisitNullCheck(HNullCheck* instruction) {
- SlowPathCode* slow_path =
- new (GetGraph()->GetArena()) NullCheckSlowPathX86_64(instruction->GetDexPc());
+ SlowPathCode* slow_path = new (GetGraph()->GetArena()) NullCheckSlowPathX86_64(instruction);
codegen_->AddSlowPath(slow_path);
LocationSummary* locations = instruction->GetLocations();
@@ -1077,11 +1075,11 @@ void InstructionCodeGeneratorX86_64::VisitNullCheck(HNullCheck* instruction) {
}
void LocationsBuilderX86_64::VisitArrayGet(HArrayGet* instruction) {
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
locations->SetInAt(0, Location::RequiresRegister());
locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1)));
locations->SetOut(Location::RequiresRegister());
- instruction->SetLocations(locations);
}
void InstructionCodeGeneratorX86_64::VisitArrayGet(HArrayGet* instruction) {
@@ -1174,27 +1172,27 @@ void InstructionCodeGeneratorX86_64::VisitArrayGet(HArrayGet* instruction) {
}
void LocationsBuilderX86_64::VisitArraySet(HArraySet* instruction) {
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
- Primitive::Type value_type = instruction->InputAt(2)->GetType();
- if (value_type == Primitive::kPrimNot) {
+ Primitive::Type value_type = instruction->GetComponentType();
+ bool is_object = value_type == Primitive::kPrimNot;
+ LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(
+ instruction, is_object ? LocationSummary::kCall : LocationSummary::kNoCall);
+ if (is_object) {
InvokeRuntimeCallingConvention calling_convention;
locations->SetInAt(0, X86_64CpuLocation(calling_convention.GetRegisterAt(0)));
locations->SetInAt(1, X86_64CpuLocation(calling_convention.GetRegisterAt(1)));
locations->SetInAt(2, X86_64CpuLocation(calling_convention.GetRegisterAt(2)));
- codegen_->MarkNotLeaf();
} else {
locations->SetInAt(0, Location::RequiresRegister());
locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1)));
locations->SetInAt(2, Location::RequiresRegister());
}
- instruction->SetLocations(locations);
}
void InstructionCodeGeneratorX86_64::VisitArraySet(HArraySet* instruction) {
LocationSummary* locations = instruction->GetLocations();
CpuRegister obj = locations->InAt(0).AsX86_64().AsCpuRegister();
Location index = locations->InAt(1);
- Primitive::Type value_type = instruction->InputAt(2)->GetType();
+ Primitive::Type value_type = instruction->GetComponentType();
switch (value_type) {
case Primitive::kPrimBoolean:
@@ -1238,7 +1236,7 @@ void InstructionCodeGeneratorX86_64::VisitArraySet(HArraySet* instruction) {
case Primitive::kPrimNot: {
__ gs()->call(Address::Absolute(QUICK_ENTRYPOINT_OFFSET(kX86_64WordSize, pAputObject), true));
DCHECK(!codegen_->IsLeafMethod());
- codegen_->RecordPcInfo(instruction->GetDexPc());
+ codegen_->RecordPcInfo(instruction, instruction->GetDexPc());
break;
}
@@ -1264,10 +1262,10 @@ void InstructionCodeGeneratorX86_64::VisitArraySet(HArraySet* instruction) {
}
void LocationsBuilderX86_64::VisitArrayLength(HArrayLength* instruction) {
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
locations->SetInAt(0, Location::RequiresRegister());
locations->SetOut(Location::RequiresRegister());
- instruction->SetLocations(locations);
}
void InstructionCodeGeneratorX86_64::VisitArrayLength(HArrayLength* instruction) {
@@ -1279,18 +1277,18 @@ void InstructionCodeGeneratorX86_64::VisitArrayLength(HArrayLength* instruction)
}
void LocationsBuilderX86_64::VisitBoundsCheck(HBoundsCheck* instruction) {
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
locations->SetInAt(0, Location::RequiresRegister());
locations->SetInAt(1, Location::RequiresRegister());
// TODO: Have a normalization phase that makes this instruction never used.
locations->SetOut(Location::SameAsFirstInput());
- instruction->SetLocations(locations);
}
void InstructionCodeGeneratorX86_64::VisitBoundsCheck(HBoundsCheck* instruction) {
LocationSummary* locations = instruction->GetLocations();
SlowPathCode* slow_path = new (GetGraph()->GetArena()) BoundsCheckSlowPathX86_64(
- instruction->GetDexPc(), locations->InAt(0), locations->InAt(1));
+ instruction, locations->InAt(0), locations->InAt(1));
codegen_->AddSlowPath(slow_path);
CpuRegister index = locations->InAt(0).AsX86_64().AsCpuRegister();
diff --git a/compiler/optimizing/locations.cc b/compiler/optimizing/locations.cc
index 468cfb7923..fce97bd5db 100644
--- a/compiler/optimizing/locations.cc
+++ b/compiler/optimizing/locations.cc
@@ -20,13 +20,29 @@
namespace art {
-LocationSummary::LocationSummary(HInstruction* instruction)
+LocationSummary::LocationSummary(HInstruction* instruction, CallKind call_kind)
: inputs_(instruction->GetBlock()->GetGraph()->GetArena(), instruction->InputCount()),
- temps_(instruction->GetBlock()->GetGraph()->GetArena(), 0) {
+ temps_(instruction->GetBlock()->GetGraph()->GetArena(), 0),
+ environment_(instruction->GetBlock()->GetGraph()->GetArena(),
+ instruction->EnvironmentSize()),
+ call_kind_(call_kind),
+ stack_mask_(nullptr),
+ register_mask_(0),
+ live_registers_(0) {
inputs_.SetSize(instruction->InputCount());
- for (size_t i = 0; i < instruction->InputCount(); i++) {
+ for (size_t i = 0; i < instruction->InputCount(); ++i) {
inputs_.Put(i, Location());
}
+ environment_.SetSize(instruction->EnvironmentSize());
+ for (size_t i = 0; i < instruction->EnvironmentSize(); ++i) {
+ environment_.Put(i, Location());
+ }
+ instruction->SetLocations(this);
+
+ if (NeedsSafepoint()) {
+ ArenaAllocator* arena = instruction->GetBlock()->GetGraph()->GetArena();
+ stack_mask_ = new (arena) ArenaBitVector(arena, 0, true);
+ }
}
diff --git a/compiler/optimizing/locations.h b/compiler/optimizing/locations.h
index aaddb099a6..041e85b846 100644
--- a/compiler/optimizing/locations.h
+++ b/compiler/optimizing/locations.h
@@ -18,6 +18,7 @@
#define ART_COMPILER_OPTIMIZING_LOCATIONS_H_
#include "base/bit_field.h"
+#include "base/bit_vector.h"
#include "utils/allocation.h"
#include "utils/growable_array.h"
#include "utils/managed_register.h"
@@ -43,13 +44,13 @@ class Location : public ValueObject {
// low bits are in the last parameter register, and the high
// bits are in a stack slot. The kQuickParameter kind is for
// handling this special case.
- kQuickParameter = 5,
+ kQuickParameter = 6,
// Unallocated location represents a location that is not fixed and can be
// allocated by a register allocator. Each unallocated location has
// a policy that specifies what kind of location is suitable. Payload
// contains register allocation policy.
- kUnallocated = 6,
+ kUnallocated = 7,
};
Location() : value_(kInvalid) {
@@ -59,8 +60,8 @@ class Location : public ValueObject {
COMPILE_ASSERT((kStackSlot & kLocationTagMask) != kConstant, TagError);
COMPILE_ASSERT((kDoubleStackSlot & kLocationTagMask) != kConstant, TagError);
COMPILE_ASSERT((kRegister & kLocationTagMask) != kConstant, TagError);
+ COMPILE_ASSERT((kQuickParameter & kLocationTagMask) != kConstant, TagError);
COMPILE_ASSERT((kConstant & kLocationTagMask) == kConstant, TagError);
- COMPILE_ASSERT((kQuickParameter & kLocationTagMask) == kConstant, TagError);
DCHECK(!IsValid());
}
@@ -173,7 +174,7 @@ class Location : public ValueObject {
x86_64::X86_64ManagedRegister AsX86_64() const;
Kind GetKind() const {
- return KindField::Decode(value_);
+ return IsConstant() ? kConstant : KindField::Decode(value_);
}
bool Equals(Location other) const {
@@ -275,7 +276,13 @@ class Location : public ValueObject {
*/
class LocationSummary : public ArenaObject {
public:
- explicit LocationSummary(HInstruction* instruction);
+ enum CallKind {
+ kNoCall,
+ kCallOnSlowPath,
+ kCall
+ };
+
+ explicit LocationSummary(HInstruction* instruction, CallKind call_kind = kNoCall);
void SetInAt(uint32_t at, Location location) {
inputs_.Put(at, location);
@@ -309,12 +316,50 @@ class LocationSummary : public ArenaObject {
return temps_.Size();
}
+ void SetEnvironmentAt(uint32_t at, Location location) {
+ environment_.Put(at, location);
+ }
+
+ Location GetEnvironmentAt(uint32_t at) const {
+ return environment_.Get(at);
+ }
+
Location Out() const { return output_; }
+ bool CanCall() const { return call_kind_ != kNoCall; }
+ bool NeedsSafepoint() const { return CanCall(); }
+
+ void SetStackBit(uint32_t index) {
+ stack_mask_->SetBit(index);
+ }
+
+ void SetRegisterBit(uint32_t reg_id) {
+ register_mask_ |= (1 << reg_id);
+ }
+
+ void SetLiveRegister(uint32_t reg_id) {
+ live_registers_ |= (1 << reg_id);
+ }
+
+ BitVector* GetStackMask() const {
+ return stack_mask_;
+ }
+
private:
GrowableArray<Location> inputs_;
GrowableArray<Location> temps_;
+ GrowableArray<Location> environment_;
Location output_;
+ const CallKind call_kind_;
+
+ // Mask of objects that live in the stack.
+ BitVector* stack_mask_;
+
+ // Mask of objects that live in register.
+ uint32_t register_mask_;
+
+ // Registers that are in use at this position.
+ uint32_t live_registers_;
DISALLOW_COPY_AND_ASSIGN(LocationSummary);
};
diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc
index 490d345826..f07029d6c2 100644
--- a/compiler/optimizing/nodes.cc
+++ b/compiler/optimizing/nodes.cc
@@ -414,6 +414,10 @@ void HInstruction::ReplaceWith(HInstruction* other) {
env_uses_ = nullptr;
}
+size_t HInstruction::EnvironmentSize() const {
+ return HasEnvironment() ? environment_->Size() : 0;
+}
+
void HPhi::AddInput(HInstruction* input) {
DCHECK(input->GetBlock() != nullptr);
inputs_.Add(input);
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index bb699e47c3..ea0cacc4ea 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -554,6 +554,10 @@ class HInstruction : public ArenaObject {
HEnvironment* GetEnvironment() const { return environment_; }
void SetEnvironment(HEnvironment* environment) { environment_ = environment; }
+ // Returns the number of entries in the environment. Typically, that is the
+ // number of dex registers in a method. It could be more in case of inlining.
+ size_t EnvironmentSize() const;
+
LocationSummary* GetLocations() const { return locations_; }
void SetLocations(LocationSummary* locations) { locations_ = locations; }
@@ -583,7 +587,7 @@ class HInstruction : public ArenaObject {
// An instruction gets an id when it is added to the graph.
// It reflects creation order. A negative id means the instruction
- // has not beed added to the graph.
+ // has not been added to the graph.
int id_;
// When doing liveness analysis, instructions that have uses get an SSA index.
@@ -595,6 +599,8 @@ class HInstruction : public ArenaObject {
// List of environments that contain this instruction.
HUseListNode<HEnvironment>* env_uses_;
+ // The environment associated with this instruction. Not null if the instruction
+ // might jump out of the method.
HEnvironment* environment_;
// Set by the code generator.
@@ -660,10 +666,16 @@ class HEnvironment : public ArenaObject {
vregs_.Put(index, instruction);
}
+ HInstruction* GetInstructionAt(size_t index) const {
+ return vregs_.Get(index);
+ }
+
GrowableArray<HInstruction*>* GetVRegs() {
return &vregs_;
}
+ size_t Size() const { return vregs_.Size(); }
+
private:
GrowableArray<HInstruction*> vregs_;
@@ -1324,13 +1336,15 @@ class HNullCheck : public HExpression<1> {
class FieldInfo : public ValueObject {
public:
- explicit FieldInfo(MemberOffset field_offset)
- : field_offset_(field_offset) {}
+ explicit FieldInfo(MemberOffset field_offset, Primitive::Type field_type)
+ : field_offset_(field_offset), field_type_(field_type) {}
MemberOffset GetFieldOffset() const { return field_offset_; }
+ Primitive::Type GetFieldType() const { return field_type_; }
private:
const MemberOffset field_offset_;
+ const Primitive::Type field_type_;
};
class HInstanceFieldGet : public HExpression<1> {
@@ -1338,11 +1352,12 @@ class HInstanceFieldGet : public HExpression<1> {
HInstanceFieldGet(HInstruction* value,
Primitive::Type field_type,
MemberOffset field_offset)
- : HExpression(field_type), field_info_(field_offset) {
+ : HExpression(field_type), field_info_(field_offset, field_type) {
SetRawInputAt(0, value);
}
MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); }
+ Primitive::Type GetFieldType() const { return field_info_.GetFieldType(); }
DECLARE_INSTRUCTION(InstanceFieldGet);
@@ -1356,13 +1371,15 @@ class HInstanceFieldSet : public HTemplateInstruction<2> {
public:
HInstanceFieldSet(HInstruction* object,
HInstruction* value,
+ Primitive::Type field_type,
MemberOffset field_offset)
- : field_info_(field_offset) {
+ : field_info_(field_offset, field_type) {
SetRawInputAt(0, object);
SetRawInputAt(1, value);
}
MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); }
+ Primitive::Type GetFieldType() const { return field_info_.GetFieldType(); }
DECLARE_INSTRUCTION(InstanceFieldSet);
@@ -1391,7 +1408,8 @@ class HArraySet : public HTemplateInstruction<3> {
HArraySet(HInstruction* array,
HInstruction* index,
HInstruction* value,
- uint32_t dex_pc) : dex_pc_(dex_pc) {
+ Primitive::Type component_type,
+ uint32_t dex_pc) : dex_pc_(dex_pc), component_type_(component_type) {
SetRawInputAt(0, array);
SetRawInputAt(1, index);
SetRawInputAt(2, value);
@@ -1405,10 +1423,13 @@ class HArraySet : public HTemplateInstruction<3> {
uint32_t GetDexPc() const { return dex_pc_; }
+ Primitive::Type GetComponentType() const { return component_type_; }
+
DECLARE_INSTRUCTION(ArraySet);
private:
const uint32_t dex_pc_;
+ const Primitive::Type component_type_;
DISALLOW_COPY_AND_ASSIGN(HArraySet);
};
diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc
index 34612766d6..75f41557e2 100644
--- a/compiler/optimizing/optimizing_compiler.cc
+++ b/compiler/optimizing/optimizing_compiler.cc
@@ -240,8 +240,27 @@ CompiledMethod* OptimizingCompiler::TryCompile(const DexFile::CodeItem* code_ite
visualizer.DumpGraph(kRegisterAllocatorPassName);
codegen->CompileOptimized(&allocator);
+
+ std::vector<uint8_t> mapping_table;
+ SrcMap src_mapping_table;
+ codegen->BuildMappingTable(&mapping_table,
+ GetCompilerDriver()->GetCompilerOptions().GetIncludeDebugSymbols() ?
+ &src_mapping_table : nullptr);
+
+ std::vector<uint8_t> stack_map;
+ codegen->BuildStackMaps(&stack_map);
+
+ return new CompiledMethod(GetCompilerDriver(),
+ instruction_set,
+ allocator.GetMemory(),
+ codegen->GetFrameSize(),
+ codegen->GetCoreSpillMask(),
+ 0, /* FPR spill mask, unused */
+ mapping_table,
+ stack_map);
} else if (shouldOptimize && RegisterAllocator::Supports(instruction_set)) {
LOG(FATAL) << "Could not allocate registers in optimizing compiler";
+ return nullptr;
} else {
codegen->CompileBaseline(&allocator);
@@ -253,29 +272,29 @@ CompiledMethod* OptimizingCompiler::TryCompile(const DexFile::CodeItem* code_ite
SsaLivenessAnalysis liveness(*graph, codegen);
liveness.Analyze();
visualizer.DumpGraph(kLivenessPassName);
- }
- std::vector<uint8_t> mapping_table;
- SrcMap src_mapping_table;
- codegen->BuildMappingTable(&mapping_table,
- GetCompilerDriver()->GetCompilerOptions().GetIncludeDebugSymbols() ?
- &src_mapping_table : nullptr);
- std::vector<uint8_t> vmap_table;
- codegen->BuildVMapTable(&vmap_table);
- std::vector<uint8_t> gc_map;
- codegen->BuildNativeGCMap(&gc_map, dex_compilation_unit);
-
- return new CompiledMethod(GetCompilerDriver(),
- instruction_set,
- allocator.GetMemory(),
- codegen->GetFrameSize(),
- codegen->GetCoreSpillMask(),
- 0, /* FPR spill mask, unused */
- &src_mapping_table,
- mapping_table,
- vmap_table,
- gc_map,
- nullptr);
+ std::vector<uint8_t> mapping_table;
+ SrcMap src_mapping_table;
+ codegen->BuildMappingTable(&mapping_table,
+ GetCompilerDriver()->GetCompilerOptions().GetIncludeDebugSymbols() ?
+ &src_mapping_table : nullptr);
+ std::vector<uint8_t> vmap_table;
+ codegen->BuildVMapTable(&vmap_table);
+ std::vector<uint8_t> gc_map;
+ codegen->BuildNativeGCMap(&gc_map, dex_compilation_unit);
+
+ return new CompiledMethod(GetCompilerDriver(),
+ instruction_set,
+ allocator.GetMemory(),
+ codegen->GetFrameSize(),
+ codegen->GetCoreSpillMask(),
+ 0, /* FPR spill mask, unused */
+ &src_mapping_table,
+ mapping_table,
+ vmap_table,
+ gc_map,
+ nullptr);
+ }
}
CompiledMethod* OptimizingCompiler::Compile(const DexFile::CodeItem* code_item,
diff --git a/compiler/optimizing/register_allocator.cc b/compiler/optimizing/register_allocator.cc
index da13b1ec55..54888ba7d8 100644
--- a/compiler/optimizing/register_allocator.cc
+++ b/compiler/optimizing/register_allocator.cc
@@ -31,18 +31,26 @@ RegisterAllocator::RegisterAllocator(ArenaAllocator* allocator,
: allocator_(allocator),
codegen_(codegen),
liveness_(liveness),
- unhandled_(allocator, 0),
+ unhandled_core_intervals_(allocator, 0),
+ unhandled_fp_intervals_(allocator, 0),
+ unhandled_(nullptr),
handled_(allocator, 0),
active_(allocator, 0),
inactive_(allocator, 0),
physical_register_intervals_(allocator, codegen->GetNumberOfRegisters()),
+ temp_intervals_(allocator, 4),
spill_slots_(allocator, kDefaultNumberOfSpillSlots),
+ safepoints_(allocator, 0),
processing_core_registers_(false),
number_of_registers_(-1),
registers_array_(nullptr),
- blocked_registers_(allocator->AllocArray<bool>(codegen->GetNumberOfRegisters())) {
+ blocked_registers_(allocator->AllocArray<bool>(codegen->GetNumberOfRegisters())),
+ reserved_out_slots_(0) {
codegen->SetupBlockedRegisters(blocked_registers_);
physical_register_intervals_.SetSize(codegen->GetNumberOfRegisters());
+ // Always reserve for the current method and the graph's max out registers.
+ // TODO: compute it instead.
+ reserved_out_slots_ = 1 + codegen->GetGraph()->GetMaximumNumberOfOutVRegs();
}
bool RegisterAllocator::CanAllocateRegistersFor(const HGraph& graph,
@@ -55,7 +63,6 @@ bool RegisterAllocator::CanAllocateRegistersFor(const HGraph& graph,
!it.Done();
it.Advance()) {
HInstruction* current = it.Current();
- if (current->NeedsEnvironment()) return false;
if (current->GetType() == Primitive::kPrimLong && instruction_set != kX86_64) return false;
if (current->GetType() == Primitive::kPrimFloat) return false;
if (current->GetType() == Primitive::kPrimDouble) return false;
@@ -65,17 +72,14 @@ bool RegisterAllocator::CanAllocateRegistersFor(const HGraph& graph,
}
static bool ShouldProcess(bool processing_core_registers, LiveInterval* interval) {
+ if (interval == nullptr) return false;
bool is_core_register = (interval->GetType() != Primitive::kPrimDouble)
&& (interval->GetType() != Primitive::kPrimFloat);
return processing_core_registers == is_core_register;
}
void RegisterAllocator::AllocateRegisters() {
- processing_core_registers_ = true;
- AllocateRegistersInternal();
- processing_core_registers_ = false;
AllocateRegistersInternal();
-
Resolve();
if (kIsDebugBuild) {
@@ -101,78 +105,120 @@ void RegisterAllocator::BlockRegister(Location location,
interval->AddRange(start, end);
}
-// TODO: make the register allocator understand instructions like HCondition
-// that may not need to be materialized. It doesn't need to allocate any
-// registers for it.
void RegisterAllocator::AllocateRegistersInternal() {
- number_of_registers_ = processing_core_registers_
- ? codegen_->GetNumberOfCoreRegisters()
- : codegen_->GetNumberOfFloatingPointRegisters();
+ // Iterate post-order, to ensure the list is sorted, and the last added interval
+ // is the one with the lowest start position.
+ for (HLinearPostOrderIterator it(liveness_); !it.Done(); it.Advance()) {
+ HBasicBlock* block = it.Current();
+ for (HBackwardInstructionIterator it(block->GetInstructions()); !it.Done(); it.Advance()) {
+ ProcessInstruction(it.Current());
+ }
+ for (HInstructionIterator it(block->GetPhis()); !it.Done(); it.Advance()) {
+ ProcessInstruction(it.Current());
+ }
+ }
+ number_of_registers_ = codegen_->GetNumberOfCoreRegisters();
registers_array_ = allocator_->AllocArray<size_t>(number_of_registers_);
+ processing_core_registers_ = true;
+ unhandled_ = &unhandled_core_intervals_;
+ LinearScan();
- // Iterate post-order, to ensure the list is sorted, and the last added interval
- // is the one with the lowest start position.
- for (size_t i = liveness_.GetNumberOfSsaValues(); i > 0; --i) {
- HInstruction* instruction = liveness_.GetInstructionFromSsaIndex(i - 1);
- LiveInterval* current = instruction->GetLiveInterval();
- if (ShouldProcess(processing_core_registers_, current)) {
- DCHECK(unhandled_.IsEmpty() || current->StartsBefore(unhandled_.Peek()));
-
- LocationSummary* locations = instruction->GetLocations();
- if (locations->GetTempCount() != 0) {
- // Note that we already filtered out instructions requiring temporaries in
- // RegisterAllocator::CanAllocateRegistersFor.
- LOG(FATAL) << "Unimplemented";
- }
+ inactive_.Reset();
+ active_.Reset();
+ handled_.Reset();
- // Some instructions define their output in fixed register/stack slot. We need
- // to ensure we know these locations before doing register allocation. For a
- // given register, we create an interval that covers these locations. The register
- // will be unavailable at these locations when trying to allocate one for an
- // interval.
- //
- // The backwards walking ensures the ranges are ordered on increasing start positions.
- Location output = locations->Out();
- size_t position = instruction->GetLifetimePosition();
- if (output.IsRegister()) {
- // Shift the interval's start by one to account for the blocked register.
- current->SetFrom(position + 1);
- current->SetRegister(output.reg().RegId());
- BlockRegister(output, position, position + 1, instruction->GetType());
- } else if (output.IsStackSlot() || output.IsDoubleStackSlot()) {
- current->SetSpillSlot(output.GetStackIndex());
- }
- for (size_t i = 0; i < instruction->InputCount(); ++i) {
- Location input = locations->InAt(i);
- if (input.IsRegister()) {
- BlockRegister(input, position, position + 1, instruction->InputAt(i)->GetType());
- }
- }
+ number_of_registers_ = codegen_->GetNumberOfFloatingPointRegisters();
+ registers_array_ = allocator_->AllocArray<size_t>(number_of_registers_);
+ processing_core_registers_ = false;
+ unhandled_ = &unhandled_fp_intervals_;
+ // TODO: Enable FP register allocation.
+ DCHECK(unhandled_->IsEmpty());
+ LinearScan();
+}
- // Add the interval to the correct list.
- if (current->HasRegister()) {
- DCHECK(instruction->IsParameterValue());
- inactive_.Add(current);
- } else if (current->HasSpillSlot() || instruction->IsConstant()) {
- // Split before first register use.
- size_t first_register_use = current->FirstRegisterUse();
- if (first_register_use != kNoLifetime) {
- LiveInterval* split = Split(current, first_register_use - 1);
- // Don't add direclty to `unhandled_`, it needs to be sorted and the start
- // of this new interval might be after intervals already in the list.
- AddToUnhandled(split);
- } else {
- // Nothing to do, we won't allocate a register for this value.
- }
- } else {
- DCHECK(unhandled_.IsEmpty() || current->StartsBefore(unhandled_.Peek()));
- unhandled_.Add(current);
- }
+void RegisterAllocator::ProcessInstruction(HInstruction* instruction) {
+ LocationSummary* locations = instruction->GetLocations();
+ size_t position = instruction->GetLifetimePosition();
+
+ if (locations == nullptr) return;
+
+ // Create synthesized intervals for temporaries.
+ for (size_t i = 0; i < locations->GetTempCount(); ++i) {
+ Location temp = locations->GetTemp(i);
+ if (temp.IsRegister()) {
+ BlockRegister(temp, position, position + 1, Primitive::kPrimInt);
+ } else {
+ LiveInterval* interval =
+ LiveInterval::MakeTempInterval(allocator_, instruction, Primitive::kPrimInt);
+ temp_intervals_.Add(interval);
+ interval->AddRange(position, position + 1);
+ unhandled_core_intervals_.Add(interval);
}
}
- LinearScan();
+ if (locations->CanCall()) {
+ codegen_->MarkNotLeaf();
+ safepoints_.Add(instruction);
+ // Block all registers.
+ for (size_t i = 0; i < codegen_->GetNumberOfCoreRegisters(); ++i) {
+ BlockRegister(Location::RegisterLocation(ManagedRegister(i)),
+ position,
+ position + 1,
+ Primitive::kPrimInt);
+ }
+ }
+
+ for (size_t i = 0; i < instruction->InputCount(); ++i) {
+ Location input = locations->InAt(i);
+ if (input.IsRegister()) {
+ BlockRegister(input, position, position + 1, instruction->InputAt(i)->GetType());
+ }
+ }
+
+ bool core_register = (instruction->GetType() != Primitive::kPrimDouble)
+ && (instruction->GetType() != Primitive::kPrimFloat);
+ GrowableArray<LiveInterval*>& unhandled = core_register
+ ? unhandled_core_intervals_
+ : unhandled_fp_intervals_;
+
+ LiveInterval* current = instruction->GetLiveInterval();
+ if (current == nullptr) return;
+
+ DCHECK(unhandled.IsEmpty() || current->StartsBefore(unhandled.Peek()));
+ // Some instructions define their output in fixed register/stack slot. We need
+ // to ensure we know these locations before doing register allocation. For a
+ // given register, we create an interval that covers these locations. The register
+ // will be unavailable at these locations when trying to allocate one for an
+ // interval.
+ //
+ // The backwards walking ensures the ranges are ordered on increasing start positions.
+ Location output = locations->Out();
+ if (output.IsRegister()) {
+ // Shift the interval's start by one to account for the blocked register.
+ current->SetFrom(position + 1);
+ current->SetRegister(output.reg().RegId());
+ BlockRegister(output, position, position + 1, instruction->GetType());
+ } else if (output.IsStackSlot() || output.IsDoubleStackSlot()) {
+ current->SetSpillSlot(output.GetStackIndex());
+ }
+
+ // If needed, add interval to the list of unhandled intervals.
+ if (current->HasSpillSlot() || instruction->IsConstant()) {
+ // Split before first register use.
+ size_t first_register_use = current->FirstRegisterUse();
+ if (first_register_use != kNoLifetime) {
+ LiveInterval* split = Split(current, first_register_use - 1);
+ // Don't add direclty to `unhandled`, it needs to be sorted and the start
+ // of this new interval might be after intervals already in the list.
+ AddSorted(&unhandled, split);
+ } else {
+ // Nothing to do, we won't allocate a register for this value.
+ }
+ } else {
+ DCHECK(unhandled.IsEmpty() || current->StartsBefore(unhandled.Peek()));
+ unhandled.Add(current);
+ }
}
class AllRangesIterator : public ValueObject {
@@ -220,12 +266,20 @@ bool RegisterAllocator::ValidateInternal(bool log_fatal_on_failure) const {
}
}
- return ValidateIntervals(intervals, spill_slots_.Size(), *codegen_, allocator_,
- processing_core_registers_, log_fatal_on_failure);
+ for (size_t i = 0, e = temp_intervals_.Size(); i < e; ++i) {
+ LiveInterval* temp = temp_intervals_.Get(i);
+ if (ShouldProcess(processing_core_registers_, temp)) {
+ intervals.Add(temp);
+ }
+ }
+
+ return ValidateIntervals(intervals, spill_slots_.Size(), reserved_out_slots_, *codegen_,
+ allocator_, processing_core_registers_, log_fatal_on_failure);
}
bool RegisterAllocator::ValidateIntervals(const GrowableArray<LiveInterval*>& intervals,
size_t number_of_spill_slots,
+ size_t number_of_out_slots,
const CodeGenerator& codegen,
ArenaAllocator* allocator,
bool processing_core_registers,
@@ -249,8 +303,9 @@ bool RegisterAllocator::ValidateIntervals(const GrowableArray<LiveInterval*>& in
if (current->GetParent()->HasSpillSlot()
// Parameters have their own stack slot.
&& !(defined_by != nullptr && defined_by->IsParameterValue())) {
- BitVector* liveness_of_spill_slot = liveness_of_values.Get(
- number_of_registers + current->GetParent()->GetSpillSlot() / kVRegSize);
+ BitVector* liveness_of_spill_slot = liveness_of_values.Get(number_of_registers
+ + current->GetParent()->GetSpillSlot() / kVRegSize
+ - number_of_out_slots);
for (size_t j = it.CurrentRange()->GetStart(); j < it.CurrentRange()->GetEnd(); ++j) {
if (liveness_of_spill_slot->IsBitSet(j)) {
if (log_fatal_on_failure) {
@@ -272,7 +327,11 @@ bool RegisterAllocator::ValidateIntervals(const GrowableArray<LiveInterval*>& in
if (liveness_of_register->IsBitSet(j)) {
if (log_fatal_on_failure) {
std::ostringstream message;
- message << "Register conflict at " << j << " for ";
+ message << "Register conflict at " << j << " ";
+ if (defined_by != nullptr) {
+ message << "(" << defined_by->DebugName() << ")";
+ }
+ message << "for ";
if (processing_core_registers) {
codegen.DumpCoreRegister(message, current->GetRegister());
} else {
@@ -309,10 +368,10 @@ void RegisterAllocator::DumpInterval(std::ostream& stream, LiveInterval* interva
// By the book implementation of a linear scan register allocator.
void RegisterAllocator::LinearScan() {
- while (!unhandled_.IsEmpty()) {
+ while (!unhandled_->IsEmpty()) {
// (1) Remove interval with the lowest start position from unhandled.
- LiveInterval* current = unhandled_.Pop();
- DCHECK(!current->IsFixed() && !current->HasRegister() && !current->HasSpillSlot());
+ LiveInterval* current = unhandled_->Pop();
+ DCHECK(!current->IsFixed() && !current->HasSpillSlot());
size_t position = current->GetStart();
// (2) Remove currently active intervals that are dead at this position.
@@ -392,13 +451,19 @@ bool RegisterAllocator::TryAllocateFreeReg(LiveInterval* current) {
free_until[interval->GetRegister()] = 0;
}
- // Pick the register that is free the longest.
int reg = -1;
- for (size_t i = 0; i < number_of_registers_; ++i) {
- if (IsBlocked(i)) continue;
- if (reg == -1 || free_until[i] > free_until[reg]) {
- reg = i;
- if (free_until[i] == kMaxLifetimePosition) break;
+ if (current->HasRegister()) {
+ // Some instructions have a fixed register output.
+ reg = current->GetRegister();
+ DCHECK_NE(free_until[reg], 0u);
+ } else {
+ // Pick the register that is free the longest.
+ for (size_t i = 0; i < number_of_registers_; ++i) {
+ if (IsBlocked(i)) continue;
+ if (reg == -1 || free_until[i] > free_until[reg]) {
+ reg = i;
+ if (free_until[i] == kMaxLifetimePosition) break;
+ }
}
}
@@ -414,7 +479,7 @@ bool RegisterAllocator::TryAllocateFreeReg(LiveInterval* current) {
// the register is not available anymore.
LiveInterval* split = Split(current, free_until[reg]);
DCHECK(split != nullptr);
- AddToUnhandled(split);
+ AddSorted(unhandled_, split);
}
return true;
}
@@ -493,7 +558,7 @@ bool RegisterAllocator::AllocateBlockedReg(LiveInterval* current) {
// register, we split this interval just before its first register use.
AllocateSpillSlotFor(current);
LiveInterval* split = Split(current, first_register_use - 1);
- AddToUnhandled(split);
+ AddSorted(unhandled_, split);
return false;
} else {
// Use this register and spill the active and inactives interval that
@@ -507,7 +572,7 @@ bool RegisterAllocator::AllocateBlockedReg(LiveInterval* current) {
LiveInterval* split = Split(active, current->GetStart());
active_.DeleteAt(i);
handled_.Add(active);
- AddToUnhandled(split);
+ AddSorted(unhandled_, split);
break;
}
}
@@ -519,12 +584,12 @@ bool RegisterAllocator::AllocateBlockedReg(LiveInterval* current) {
if (next_intersection != kNoLifetime) {
if (inactive->IsFixed()) {
LiveInterval* split = Split(current, next_intersection);
- AddToUnhandled(split);
+ AddSorted(unhandled_, split);
} else {
LiveInterval* split = Split(inactive, current->GetStart());
inactive_.DeleteAt(i);
handled_.Add(inactive);
- AddToUnhandled(split);
+ AddSorted(unhandled_, split);
--i;
}
}
@@ -535,16 +600,16 @@ bool RegisterAllocator::AllocateBlockedReg(LiveInterval* current) {
}
}
-void RegisterAllocator::AddToUnhandled(LiveInterval* interval) {
+void RegisterAllocator::AddSorted(GrowableArray<LiveInterval*>* array, LiveInterval* interval) {
size_t insert_at = 0;
- for (size_t i = unhandled_.Size(); i > 0; --i) {
- LiveInterval* current = unhandled_.Get(i - 1);
+ for (size_t i = array->Size(); i > 0; --i) {
+ LiveInterval* current = array->Get(i - 1);
if (current->StartsAfter(interval)) {
insert_at = i;
break;
}
}
- unhandled_.InsertAt(insert_at, interval);
+ array->InsertAt(insert_at, interval);
}
LiveInterval* RegisterAllocator::Split(LiveInterval* interval, size_t position) {
@@ -624,7 +689,7 @@ void RegisterAllocator::AllocateTwoSpillSlots(LiveInterval* parent, size_t end)
spill_slots_.Put(slot + 1, end);
}
- parent->SetSpillSlot(slot * kVRegSize);
+ parent->SetSpillSlot((slot + reserved_out_slots_) * kVRegSize);
}
void RegisterAllocator::AllocateOneSpillSlot(LiveInterval* parent, size_t end) {
@@ -643,7 +708,7 @@ void RegisterAllocator::AllocateOneSpillSlot(LiveInterval* parent, size_t end) {
spill_slots_.Put(slot, end);
}
- parent->SetSpillSlot(slot * kVRegSize);
+ parent->SetSpillSlot((slot + reserved_out_slots_) * kVRegSize);
}
static Location ConvertToLocation(LiveInterval* interval) {
@@ -820,8 +885,10 @@ void RegisterAllocator::ConnectSiblings(LiveInterval* interval) {
// Walk over all uses covered by this interval, and update the location
// information.
while (use != nullptr && use->GetPosition() <= current->GetEnd()) {
- if (!use->GetIsEnvironment()) {
- LocationSummary* locations = use->GetUser()->GetLocations();
+ LocationSummary* locations = use->GetUser()->GetLocations();
+ if (use->GetIsEnvironment()) {
+ locations->SetEnvironmentAt(use->GetInputIndex(), source);
+ } else {
Location expected_location = locations->InAt(use->GetInputIndex());
if (expected_location.IsUnallocated()) {
locations->SetInAt(use->GetInputIndex(), source);
@@ -841,6 +908,38 @@ void RegisterAllocator::ConnectSiblings(LiveInterval* interval) {
Location destination = ConvertToLocation(next_sibling);
InsertParallelMoveAt(current->GetEnd(), source, destination);
}
+
+ // At each safepoint, we record stack and register information.
+ for (size_t i = 0, e = safepoints_.Size(); i < e; ++i) {
+ HInstruction* safepoint = safepoints_.Get(i);
+ size_t position = safepoint->GetLifetimePosition();
+ LocationSummary* locations = safepoint->GetLocations();
+ if (!current->Covers(position)) continue;
+
+ if (current->GetType() == Primitive::kPrimNot) {
+ DCHECK(current->GetParent()->HasSpillSlot());
+ locations->SetStackBit(current->GetParent()->GetSpillSlot() / kVRegSize);
+ }
+
+ switch (source.GetKind()) {
+ case Location::kRegister: {
+ locations->SetLiveRegister(source.reg().RegId());
+ if (current->GetType() == Primitive::kPrimNot) {
+ locations->SetRegisterBit(source.reg().RegId());
+ }
+ break;
+ }
+ case Location::kStackSlot: // Fall-through
+ case Location::kDoubleStackSlot: // Fall-through
+ case Location::kConstant: {
+ // Nothing to do.
+ break;
+ }
+ default: {
+ LOG(FATAL) << "Unexpected location for object";
+ }
+ }
+ }
current = next_sibling;
} while (current != nullptr);
DCHECK(use == nullptr);
@@ -907,7 +1006,7 @@ static Location FindLocationAt(LiveInterval* interval, size_t position) {
}
void RegisterAllocator::Resolve() {
- codegen_->ComputeFrameSize(spill_slots_.Size());
+ codegen_->ComputeFrameSize(spill_slots_.Size(), reserved_out_slots_);
// Adjust the Out Location of instructions.
// TODO: Use pointers of Location inside LiveInterval to avoid doing another iteration.
@@ -978,6 +1077,20 @@ void RegisterAllocator::Resolve() {
}
}
}
+
+ // Assign temp locations.
+ HInstruction* current = nullptr;
+ size_t temp_index = 0;
+ for (size_t i = 0; i < temp_intervals_.Size(); ++i) {
+ LiveInterval* temp = temp_intervals_.Get(i);
+ if (temp->GetDefinedBy() != current) {
+ temp_index = 0;
+ current = temp->GetDefinedBy();
+ }
+ LocationSummary* locations = current->GetLocations();
+ locations->SetTempAt(
+ temp_index++, Location::RegisterLocation(ManagedRegister(temp->GetRegister())));
+ }
}
} // namespace art
diff --git a/compiler/optimizing/register_allocator.h b/compiler/optimizing/register_allocator.h
index be1c7ec7c6..f737491026 100644
--- a/compiler/optimizing/register_allocator.h
+++ b/compiler/optimizing/register_allocator.h
@@ -59,6 +59,7 @@ class RegisterAllocator {
// Helper method for validation. Used by unit testing.
static bool ValidateIntervals(const GrowableArray<LiveInterval*>& intervals,
size_t number_of_spill_slots,
+ size_t number_of_out_slots,
const CodeGenerator& codegen,
ArenaAllocator* allocator,
bool processing_core_registers,
@@ -83,8 +84,8 @@ class RegisterAllocator {
bool AllocateBlockedReg(LiveInterval* interval);
void Resolve();
- // Add `interval` in the sorted list of unhandled intervals.
- void AddToUnhandled(LiveInterval* interval);
+ // Add `interval` in the given sorted list.
+ static void AddSorted(GrowableArray<LiveInterval*>* array, LiveInterval* interval);
// Split `interval` at the position `at`. The new interval starts at `at`.
LiveInterval* Split(LiveInterval* interval, size_t at);
@@ -115,6 +116,7 @@ class RegisterAllocator {
// Helper methods.
void AllocateRegistersInternal();
+ void ProcessInstruction(HInstruction* instruction);
bool ValidateInternal(bool log_fatal_on_failure) const;
void DumpInterval(std::ostream& stream, LiveInterval* interval) const;
@@ -122,9 +124,17 @@ class RegisterAllocator {
CodeGenerator* const codegen_;
const SsaLivenessAnalysis& liveness_;
- // List of intervals that must be processed, ordered by start position. Last entry
- // is the interval that has the lowest start position.
- GrowableArray<LiveInterval*> unhandled_;
+ // List of intervals for core registers that must be processed, ordered by start
+ // position. Last entry is the interval that has the lowest start position.
+ // This list is initially populated before doing the linear scan.
+ GrowableArray<LiveInterval*> unhandled_core_intervals_;
+
+ // List of intervals for floating-point registers. Same comments as above.
+ GrowableArray<LiveInterval*> unhandled_fp_intervals_;
+
+ // Currently processed list of unhandled intervals. Either `unhandled_core_intervals_`
+ // or `unhandled_fp_intervals_`.
+ GrowableArray<LiveInterval*>* unhandled_;
// List of intervals that have been processed.
GrowableArray<LiveInterval*> handled_;
@@ -137,13 +147,20 @@ class RegisterAllocator {
// That is, they have a lifetime hole that spans the start of the new interval.
GrowableArray<LiveInterval*> inactive_;
- // Fixed intervals for physical registers. Such an interval covers the positions
+ // Fixed intervals for physical registers. Such intervals cover the positions
// where an instruction requires a specific register.
GrowableArray<LiveInterval*> physical_register_intervals_;
+ // Intervals for temporaries. Such intervals cover the positions
+ // where an instruction requires a temporary.
+ GrowableArray<LiveInterval*> temp_intervals_;
+
// The spill slots allocated for live intervals.
GrowableArray<size_t> spill_slots_;
+ // Instructions that need a safepoint.
+ GrowableArray<HInstruction*> safepoints_;
+
// True if processing core registers. False if processing floating
// point registers.
bool processing_core_registers_;
@@ -157,6 +174,9 @@ class RegisterAllocator {
// Blocked registers, as decided by the code generator.
bool* const blocked_registers_;
+ // Slots reserved for out arguments.
+ size_t reserved_out_slots_;
+
DISALLOW_COPY_AND_ASSIGN(RegisterAllocator);
};
diff --git a/compiler/optimizing/register_allocator_test.cc b/compiler/optimizing/register_allocator_test.cc
index bafe577f90..7539d44d1a 100644
--- a/compiler/optimizing/register_allocator_test.cc
+++ b/compiler/optimizing/register_allocator_test.cc
@@ -66,11 +66,11 @@ TEST(RegisterAllocatorTest, ValidateIntervals) {
intervals.Add(BuildInterval(ranges, arraysize(ranges), &allocator, 0));
intervals.Add(BuildInterval(ranges, arraysize(ranges), &allocator, 1));
ASSERT_TRUE(RegisterAllocator::ValidateIntervals(
- intervals, 0, *codegen, &allocator, true, false));
+ intervals, 0, 0, *codegen, &allocator, true, false));
intervals.Get(1)->SetRegister(0);
ASSERT_FALSE(RegisterAllocator::ValidateIntervals(
- intervals, 0, *codegen, &allocator, true, false));
+ intervals, 0, 0, *codegen, &allocator, true, false));
intervals.Reset();
}
@@ -81,11 +81,11 @@ TEST(RegisterAllocatorTest, ValidateIntervals) {
static constexpr size_t ranges2[][2] = {{42, 43}};
intervals.Add(BuildInterval(ranges2, arraysize(ranges2), &allocator, 1));
ASSERT_TRUE(RegisterAllocator::ValidateIntervals(
- intervals, 0, *codegen, &allocator, true, false));
+ intervals, 0, 0, *codegen, &allocator, true, false));
intervals.Get(1)->SetRegister(0);
ASSERT_TRUE(RegisterAllocator::ValidateIntervals(
- intervals, 0, *codegen, &allocator, true, false));
+ intervals, 0, 0, *codegen, &allocator, true, false));
intervals.Reset();
}
@@ -96,11 +96,11 @@ TEST(RegisterAllocatorTest, ValidateIntervals) {
static constexpr size_t ranges2[][2] = {{42, 43}};
intervals.Add(BuildInterval(ranges2, arraysize(ranges2), &allocator, 1));
ASSERT_TRUE(RegisterAllocator::ValidateIntervals(
- intervals, 0, *codegen, &allocator, true, false));
+ intervals, 0, 0, *codegen, &allocator, true, false));
intervals.Get(1)->SetRegister(0);
ASSERT_TRUE(RegisterAllocator::ValidateIntervals(
- intervals, 0, *codegen, &allocator, true, false));
+ intervals, 0, 0, *codegen, &allocator, true, false));
intervals.Reset();
}
@@ -111,11 +111,11 @@ TEST(RegisterAllocatorTest, ValidateIntervals) {
static constexpr size_t ranges2[][2] = {{42, 47}};
intervals.Add(BuildInterval(ranges2, arraysize(ranges2), &allocator, 1));
ASSERT_TRUE(RegisterAllocator::ValidateIntervals(
- intervals, 0, *codegen, &allocator, true, false));
+ intervals, 0, 0, *codegen, &allocator, true, false));
intervals.Get(1)->SetRegister(0);
ASSERT_FALSE(RegisterAllocator::ValidateIntervals(
- intervals, 0, *codegen, &allocator, true, false));
+ intervals, 0, 0, *codegen, &allocator, true, false));
intervals.Reset();
}
@@ -127,16 +127,16 @@ TEST(RegisterAllocatorTest, ValidateIntervals) {
static constexpr size_t ranges2[][2] = {{42, 47}};
intervals.Add(BuildInterval(ranges2, arraysize(ranges2), &allocator, 1));
ASSERT_TRUE(RegisterAllocator::ValidateIntervals(
- intervals, 0, *codegen, &allocator, true, false));
+ intervals, 0, 0, *codegen, &allocator, true, false));
intervals.Get(1)->SetRegister(0);
// Sibling of the first interval has no register allocated to it.
ASSERT_TRUE(RegisterAllocator::ValidateIntervals(
- intervals, 0, *codegen, &allocator, true, false));
+ intervals, 0, 0, *codegen, &allocator, true, false));
intervals.Get(0)->GetNextSibling()->SetRegister(0);
ASSERT_FALSE(RegisterAllocator::ValidateIntervals(
- intervals, 0, *codegen, &allocator, true, false));
+ intervals, 0, 0, *codegen, &allocator, true, false));
}
}
diff --git a/compiler/optimizing/ssa_liveness_analysis.h b/compiler/optimizing/ssa_liveness_analysis.h
index 83035b52f6..33b1f1fc9a 100644
--- a/compiler/optimizing/ssa_liveness_analysis.h
+++ b/compiler/optimizing/ssa_liveness_analysis.h
@@ -47,7 +47,7 @@ class BlockInfo : public ArenaObject {
};
/**
- * A live range contains the start and end of a range where an instruction
+ * A live range contains the start and end of a range where an instruction or a temporary
* is live.
*/
class LiveRange : public ArenaObject {
@@ -76,7 +76,7 @@ class LiveRange : public ArenaObject {
private:
size_t start_;
- size_t end_;
+ const size_t end_;
LiveRange* next_;
friend class LiveInterval;
@@ -133,7 +133,12 @@ class UsePosition : public ArenaObject {
*/
class LiveInterval : public ArenaObject {
public:
- LiveInterval(ArenaAllocator* allocator, Primitive::Type type, HInstruction* defined_by = nullptr)
+ LiveInterval(ArenaAllocator* allocator,
+ Primitive::Type type,
+ HInstruction* defined_by = nullptr,
+ bool is_fixed = false,
+ int reg = kNoRegister,
+ bool is_temp = false)
: allocator_(allocator),
first_range_(nullptr),
last_range_(nullptr),
@@ -141,16 +146,20 @@ class LiveInterval : public ArenaObject {
type_(type),
next_sibling_(nullptr),
parent_(this),
- register_(kNoRegister),
+ register_(reg),
spill_slot_(kNoSpillSlot),
- is_fixed_(false),
+ is_fixed_(is_fixed),
+ is_temp_(is_temp),
defined_by_(defined_by) {}
static LiveInterval* MakeFixedInterval(ArenaAllocator* allocator, int reg, Primitive::Type type) {
- LiveInterval* interval = new (allocator) LiveInterval(allocator, type);
- interval->SetRegister(reg);
- interval->is_fixed_ = true;
- return interval;
+ return new (allocator) LiveInterval(allocator, type, nullptr, true, reg, false);
+ }
+
+ static LiveInterval* MakeTempInterval(ArenaAllocator* allocator,
+ HInstruction* defined_by,
+ Primitive::Type type) {
+ return new (allocator) LiveInterval(allocator, type, defined_by, false, kNoRegister, true);
}
bool IsFixed() const { return is_fixed_; }
@@ -192,8 +201,10 @@ class LiveInterval : public ArenaObject {
} else if (first_range_->GetStart() == end) {
// There is a use in the following block.
first_range_->start_ = start;
+ } else if (first_range_->GetStart() == start && first_range_->GetEnd() == end) {
+ DCHECK(is_fixed_);
} else {
- DCHECK(first_range_->GetStart() > end);
+ DCHECK_GT(first_range_->GetStart(), end);
// There is a hole in the interval. Create a new range.
first_range_ = new (allocator_) LiveRange(start, end, first_range_);
}
@@ -215,7 +226,11 @@ class LiveInterval : public ArenaObject {
}
bool HasSpillSlot() const { return spill_slot_ != kNoSpillSlot; }
- void SetSpillSlot(int slot) { spill_slot_ = slot; }
+ void SetSpillSlot(int slot) {
+ DCHECK(!is_fixed_);
+ DCHECK(!is_temp_);
+ spill_slot_ = slot;
+ }
int GetSpillSlot() const { return spill_slot_; }
void SetFrom(size_t from) {
@@ -243,6 +258,9 @@ class LiveInterval : public ArenaObject {
}
bool Covers(size_t position) const {
+ if (IsDeadAt(position)) {
+ return false;
+ }
LiveRange* current = first_range_;
while (current != nullptr) {
if (position >= current->GetStart() && position < current->GetEnd()) {
@@ -288,6 +306,9 @@ class LiveInterval : public ArenaObject {
}
size_t FirstRegisterUseAfter(size_t position) const {
+ if (is_temp_) {
+ return position == GetStart() ? position : kNoLifetime;
+ }
if (position == GetStart() && defined_by_ != nullptr) {
LocationSummary* locations = defined_by_->GetLocations();
Location location = locations->Out();
@@ -342,6 +363,7 @@ class LiveInterval : public ArenaObject {
* [position ... end)
*/
LiveInterval* SplitAt(size_t position) {
+ DCHECK(!is_temp_);
DCHECK(!is_fixed_);
DCHECK_GT(position, GetStart());
@@ -453,7 +475,10 @@ class LiveInterval : public ArenaObject {
int spill_slot_;
// Whether the interval is for a fixed register.
- bool is_fixed_;
+ const bool is_fixed_;
+
+ // Whether the interval is for a temporary.
+ const bool is_temp_;
// The instruction represented by this interval.
HInstruction* const defined_by_;
diff --git a/compiler/optimizing/ssa_phi_elimination.cc b/compiler/optimizing/ssa_phi_elimination.cc
index a079954166..65675dc273 100644
--- a/compiler/optimizing/ssa_phi_elimination.cc
+++ b/compiler/optimizing/ssa_phi_elimination.cc
@@ -26,6 +26,8 @@ void SsaDeadPhiElimination::Run() {
HPhi* phi = it.Current()->AsPhi();
if (phi->HasEnvironmentUses()) {
// TODO: Do we want to keep that phi alive?
+ worklist_.Add(phi);
+ phi->SetLive();
continue;
}
for (HUseIterator<HInstruction> it(phi->GetUses()); !it.Done(); it.Advance()) {
@@ -105,7 +107,7 @@ void SsaRedundantPhiElimination::Run() {
for (size_t i = 1; i < phi->InputCount(); ++i) {
HInstruction* input = phi->InputAt(i);
- // For a loop phi, If the input is the phi, the phi is still candidate for
+ // For a loop phi, if the input is the phi, the phi is still candidate for
// elimination.
if (input != candidate && input != phi) {
candidate = nullptr;
diff --git a/compiler/optimizing/stack_map_stream.h b/compiler/optimizing/stack_map_stream.h
index 5e1329e63c..0ea11ad04b 100644
--- a/compiler/optimizing/stack_map_stream.h
+++ b/compiler/optimizing/stack_map_stream.h
@@ -26,9 +26,9 @@
namespace art {
/**
- * Collects and builds a CodeInfo for a method.
+ * Collects and builds stack maps for a method. All the stack maps
+ * for a method are placed in a CodeInfo object.
*/
-template<typename T>
class StackMapStream : public ValueObject {
public:
explicit StackMapStream(ArenaAllocator* allocator)
@@ -47,7 +47,7 @@ class StackMapStream : public ValueObject {
// See runtime/stack_map.h to know what these fields contain.
struct StackMapEntry {
uint32_t dex_pc;
- T native_pc;
+ uint32_t native_pc_offset;
uint32_t register_mask;
BitVector* sp_mask;
uint32_t num_dex_registers;
@@ -66,14 +66,14 @@ class StackMapStream : public ValueObject {
};
void AddStackMapEntry(uint32_t dex_pc,
- T native_pc,
+ uint32_t native_pc_offset,
uint32_t register_mask,
BitVector* sp_mask,
uint32_t num_dex_registers,
uint8_t inlining_depth) {
StackMapEntry entry;
entry.dex_pc = dex_pc;
- entry.native_pc = native_pc;
+ entry.native_pc_offset = native_pc_offset;
entry.register_mask = register_mask;
entry.sp_mask = sp_mask;
entry.num_dex_registers = num_dex_registers;
@@ -82,7 +82,9 @@ class StackMapStream : public ValueObject {
entry.inline_infos_start_index = inline_infos_.Size();
stack_maps_.Add(entry);
- stack_mask_max_ = std::max(stack_mask_max_, sp_mask->GetHighestBitSet());
+ if (sp_mask != nullptr) {
+ stack_mask_max_ = std::max(stack_mask_max_, sp_mask->GetHighestBitSet());
+ }
if (inlining_depth > 0) {
number_of_stack_maps_with_inline_info_++;
}
@@ -102,14 +104,14 @@ class StackMapStream : public ValueObject {
}
size_t ComputeNeededSize() const {
- return CodeInfo<T>::kFixedSize
+ return CodeInfo::kFixedSize
+ ComputeStackMapSize()
+ ComputeDexRegisterMapSize()
+ ComputeInlineInfoSize();
}
size_t ComputeStackMapSize() const {
- return stack_maps_.Size() * (StackMap<T>::kFixedSize + StackMaskEncodingSize(stack_mask_max_));
+ return stack_maps_.Size() * (StackMap::kFixedSize + StackMaskEncodingSize(stack_mask_max_));
}
size_t ComputeDexRegisterMapSize() const {
@@ -130,11 +132,12 @@ class StackMapStream : public ValueObject {
}
size_t ComputeDexRegisterMapStart() const {
- return CodeInfo<T>::kFixedSize + ComputeStackMapSize();
+ return CodeInfo::kFixedSize + ComputeStackMapSize();
}
void FillIn(MemoryRegion region) {
- CodeInfo<T> code_info(region);
+ CodeInfo code_info(region);
+ code_info.SetOverallSize(region.size());
size_t stack_mask_size = StackMaskEncodingSize(stack_mask_max_);
uint8_t* memory_start = region.start();
@@ -153,13 +156,15 @@ class StackMapStream : public ValueObject {
uintptr_t next_dex_register_map_offset = 0;
uintptr_t next_inline_info_offset = 0;
for (size_t i = 0, e = stack_maps_.Size(); i < e; ++i) {
- StackMap<T> stack_map = code_info.GetStackMapAt(i);
+ StackMap stack_map = code_info.GetStackMapAt(i);
StackMapEntry entry = stack_maps_.Get(i);
stack_map.SetDexPc(entry.dex_pc);
- stack_map.SetNativePc(entry.native_pc);
+ stack_map.SetNativePcOffset(entry.native_pc_offset);
stack_map.SetRegisterMask(entry.register_mask);
- stack_map.SetStackMask(*entry.sp_mask);
+ if (entry.sp_mask != nullptr) {
+ stack_map.SetStackMask(*entry.sp_mask);
+ }
// Set the register map.
MemoryRegion region = dex_register_maps_region.Subregion(
diff --git a/compiler/optimizing/stack_map_test.cc b/compiler/optimizing/stack_map_test.cc
index a70259e7b9..5ee6ae049c 100644
--- a/compiler/optimizing/stack_map_test.cc
+++ b/compiler/optimizing/stack_map_test.cc
@@ -34,7 +34,7 @@ bool SameBits(MemoryRegion region, const BitVector& bit_vector) {
TEST(StackMapTest, Test1) {
ArenaPool pool;
ArenaAllocator arena(&pool);
- StackMapStream<size_t> stream(&arena);
+ StackMapStream stream(&arena);
ArenaBitVector sp_mask(&arena, 0, false);
stream.AddStackMapEntry(0, 64, 0x3, &sp_mask, 2, 0);
@@ -46,15 +46,15 @@ TEST(StackMapTest, Test1) {
MemoryRegion region(memory, size);
stream.FillIn(region);
- CodeInfo<size_t> code_info(region);
+ CodeInfo code_info(region);
ASSERT_EQ(0u, code_info.GetStackMaskSize());
ASSERT_EQ(1u, code_info.GetNumberOfStackMaps());
- StackMap<size_t> stack_map = code_info.GetStackMapAt(0);
+ StackMap stack_map = code_info.GetStackMapAt(0);
ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(0)));
- ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePc(64)));
+ ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(64)));
ASSERT_EQ(0u, stack_map.GetDexPc());
- ASSERT_EQ(64u, stack_map.GetNativePc());
+ ASSERT_EQ(64u, stack_map.GetNativePcOffset());
ASSERT_EQ(0x3u, stack_map.GetRegisterMask());
ASSERT_FALSE(stack_map.HasInlineInfo());
@@ -71,7 +71,7 @@ TEST(StackMapTest, Test1) {
TEST(StackMapTest, Test2) {
ArenaPool pool;
ArenaAllocator arena(&pool);
- StackMapStream<size_t> stream(&arena);
+ StackMapStream stream(&arena);
ArenaBitVector sp_mask1(&arena, 0, true);
sp_mask1.SetBit(2);
@@ -93,15 +93,15 @@ TEST(StackMapTest, Test2) {
MemoryRegion region(memory, size);
stream.FillIn(region);
- CodeInfo<size_t> code_info(region);
+ CodeInfo code_info(region);
ASSERT_EQ(1u, code_info.GetStackMaskSize());
ASSERT_EQ(2u, code_info.GetNumberOfStackMaps());
- StackMap<size_t> stack_map = code_info.GetStackMapAt(0);
+ StackMap stack_map = code_info.GetStackMapAt(0);
ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(0)));
- ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePc(64)));
+ ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(64)));
ASSERT_EQ(0u, stack_map.GetDexPc());
- ASSERT_EQ(64u, stack_map.GetNativePc());
+ ASSERT_EQ(64u, stack_map.GetNativePcOffset());
ASSERT_EQ(0x3u, stack_map.GetRegisterMask());
MemoryRegion stack_mask = stack_map.GetStackMask();
@@ -120,9 +120,9 @@ TEST(StackMapTest, Test2) {
stack_map = code_info.GetStackMapAt(1);
ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(1u)));
- ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePc(128u)));
+ ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(128u)));
ASSERT_EQ(1u, stack_map.GetDexPc());
- ASSERT_EQ(128u, stack_map.GetNativePc());
+ ASSERT_EQ(128u, stack_map.GetNativePcOffset());
ASSERT_EQ(0xFFu, stack_map.GetRegisterMask());
stack_mask = stack_map.GetStackMask();