diff options
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 |
commit | 3946844c34ad965515f677084b07d663d70ad1b8 (patch) | |
tree | 0d85bfba2ff69c34a2897351d1e50a1464509305 | |
parent | e2c23739c6395a83b30ece38f8a2e9e1bf7cf3ce (diff) | |
download | art-3946844c34ad965515f677084b07d663d70ad1b8.zip art-3946844c34ad965515f677084b07d663d70ad1b8.tar.gz art-3946844c34ad965515f677084b07d663d70ad1b8.tar.bz2 |
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
28 files changed, 951 insertions, 485 deletions
diff --git a/compiler/compiled_method.cc b/compiler/compiled_method.cc index f9a78be..ba5bd30 100644 --- a/compiler/compiled_method.cc +++ b/compiler/compiled_method.cc @@ -164,6 +164,25 @@ CompiledMethod::CompiledMethod(CompilerDriver* driver, CompiledMethod::CompiledMethod(CompilerDriver* driver, InstructionSet instruction_set, + const std::vector<uint8_t>& quick_code, + const size_t frame_size_in_bytes, + const uint32_t core_spill_mask, + const uint32_t fp_spill_mask, + const std::vector<uint8_t>& mapping_table, + const std::vector<uint8_t>& stack_map) + : CompiledCode(driver, instruction_set, quick_code), + frame_size_in_bytes_(frame_size_in_bytes), + core_spill_mask_(core_spill_mask), + fp_spill_mask_(fp_spill_mask), + src_mapping_table_(driver->DeduplicateSrcMappingTable(SrcMap())), + mapping_table_(driver->DeduplicateMappingTable(mapping_table)), + vmap_table_(driver->DeduplicateVMapTable(stack_map)), + gc_map_(nullptr), + cfi_info_(nullptr) { +} + +CompiledMethod::CompiledMethod(CompilerDriver* driver, + InstructionSet instruction_set, const std::vector<uint8_t>& code, const size_t frame_size_in_bytes, const uint32_t core_spill_mask, diff --git a/compiler/compiled_method.h b/compiler/compiled_method.h index 36f4745..3e34144 100644 --- a/compiler/compiled_method.h +++ b/compiler/compiled_method.h @@ -173,7 +173,7 @@ class SrcMap FINAL : public std::vector<SrcMapElem> { class CompiledMethod FINAL : public CompiledCode { public: - // Constructs a CompiledMethod for the non-LLVM compilers. + // Constructs a CompiledMethod for Quick. CompiledMethod(CompilerDriver* driver, InstructionSet instruction_set, const std::vector<uint8_t>& quick_code, @@ -186,6 +186,16 @@ class CompiledMethod FINAL : public CompiledCode { const std::vector<uint8_t>& native_gc_map, const std::vector<uint8_t>* cfi_info); + // Constructs a CompiledMethod for Optimizing. + CompiledMethod(CompilerDriver* driver, + InstructionSet instruction_set, + const std::vector<uint8_t>& quick_code, + const size_t frame_size_in_bytes, + const uint32_t core_spill_mask, + const uint32_t fp_spill_mask, + const std::vector<uint8_t>& mapping_table, + const std::vector<uint8_t>& vmap_table); + // Constructs a CompiledMethod for the QuickJniCompiler. CompiledMethod(CompilerDriver* driver, InstructionSet instruction_set, @@ -232,9 +242,8 @@ class CompiledMethod FINAL : public CompiledCode { return *vmap_table_; } - const std::vector<uint8_t>& GetGcMap() const { - DCHECK(gc_map_ != nullptr); - return *gc_map_; + std::vector<uint8_t> const* GetGcMap() const { + return gc_map_; } const std::vector<uint8_t>* GetCFIInfo() const { diff --git a/compiler/oat_writer.cc b/compiler/oat_writer.cc index 680ce0a..c5d1478 100644 --- a/compiler/oat_writer.cc +++ b/compiler/oat_writer.cc @@ -140,7 +140,7 @@ OatWriter::~OatWriter() { struct OatWriter::GcMapDataAccess { static const std::vector<uint8_t>* GetData(const CompiledMethod* compiled_method) ALWAYS_INLINE { - return &compiled_method->GetGcMap(); + return compiled_method->GetGcMap(); } static uint32_t GetOffset(OatClass* oat_class, size_t method_offsets_index) ALWAYS_INLINE { @@ -434,13 +434,15 @@ class OatWriter::InitCodeMethodVisitor : public OatDexMethodVisitor { } else { status = mirror::Class::kStatusNotReady; } - const std::vector<uint8_t>& gc_map = compiled_method->GetGcMap(); - size_t gc_map_size = gc_map.size() * sizeof(gc_map[0]); - bool is_native = (it.GetMemberAccessFlags() & kAccNative) != 0; - CHECK(gc_map_size != 0 || is_native || status < mirror::Class::kStatusVerified) - << &gc_map << " " << gc_map_size << " " << (is_native ? "true" : "false") << " " - << (status < mirror::Class::kStatusVerified) << " " << status << " " - << PrettyMethod(it.GetMemberIndex(), *dex_file_); + std::vector<uint8_t> const * gc_map = compiled_method->GetGcMap(); + if (gc_map != nullptr) { + size_t gc_map_size = gc_map->size() * sizeof(gc_map[0]); + bool is_native = (it.GetMemberAccessFlags() & kAccNative) != 0; + CHECK(gc_map_size != 0 || is_native || status < mirror::Class::kStatusVerified) + << gc_map << " " << gc_map_size << " " << (is_native ? "true" : "false") << " " + << (status < mirror::Class::kStatusVerified) << " " << status << " " + << PrettyMethod(it.GetMemberIndex(), *dex_file_); + } } DCHECK_LT(method_offsets_index_, oat_class->method_offsets_.size()); @@ -475,7 +477,7 @@ class OatWriter::InitMapMethodVisitor : public OatDexMethodVisitor { DCHECK_EQ(DataAccess::GetOffset(oat_class, method_offsets_index_), 0u); const std::vector<uint8_t>* map = DataAccess::GetData(compiled_method); - uint32_t map_size = map->size() * sizeof((*map)[0]); + uint32_t map_size = map == nullptr ? 0 : map->size() * sizeof((*map)[0]); if (map_size != 0u) { auto lb = dedupe_map_.lower_bound(map); if (lb != dedupe_map_.end() && !dedupe_map_.key_comp()(map, lb->first)) { @@ -645,7 +647,7 @@ class OatWriter::WriteMapMethodVisitor : public OatDexMethodVisitor { // Write deduplicated map. const std::vector<uint8_t>* map = DataAccess::GetData(compiled_method); - size_t map_size = map->size() * sizeof((*map)[0]); + size_t map_size = map == nullptr ? 0 : map->size() * sizeof((*map)[0]); DCHECK((map_size == 0u && map_offset == 0u) || (map_size != 0u && map_offset != 0u && map_offset <= offset_)) << PrettyMethod(it.GetMemberIndex(), *dex_file_); diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc index 43e6b83..ecd6802 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 7269fff..7731e6e 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 12337c9..a83d703 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 2c954a0..e72e39b 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 35b8116..6602d3f 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 c4571ca..b2d81e3 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 468cfb7..fce97bd 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 aaddb09..041e85b 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 490d345..f07029d 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 bb699e4..ea0cacc 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 3461276..75f4155 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 da13b1e..54888ba 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 be1c7ec..f737491 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 bafe577..7539d44 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 83035b5..33b1f1f 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 a079954..65675dc 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 5e1329e..0ea11ad 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 a70259e..5ee6ae0 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(); diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc index fff42f6..4cdf618 100644 --- a/oatdump/oatdump.cc +++ b/oatdump/oatdump.cc @@ -386,7 +386,7 @@ class OatDumper { GetQuickToInterpreterBridgeOffset); #undef DUMP_OAT_HEADER_OFFSET - os << "IMAGE PATCH DELTA:\n" << oat_header.GetImagePatchDelta(); + os << "IMAGE PATCH DELTA:\n" << oat_header.GetImagePatchDelta() << "\n\n"; os << "IMAGE FILE LOCATION OAT CHECKSUM:\n"; os << StringPrintf("0x%08x\n\n", oat_header.GetImageFileLocationOatChecksum()); @@ -616,7 +616,11 @@ class OatDumper { DumpSpillMask(*indent2_os, oat_method.GetFpSpillMask(), true); *indent2_os << StringPrintf("\nvmap_table: %p (offset=0x%08x)\n", oat_method.GetVmapTable(), oat_method.GetVmapTableOffset()); - DumpVmap(*indent2_os, oat_method); + + if (oat_method.GetNativeGcMap() != nullptr) { + // The native GC map is null for methods compiled with the optimizing compiler. + DumpVmap(*indent2_os, oat_method); + } DumpVregLocations(*indent2_os, oat_method, code_item); *indent2_os << StringPrintf("mapping_table: %p (offset=0x%08x)\n", oat_method.GetMappingTable(), oat_method.GetMappingTableOffset()); diff --git a/runtime/mirror/art_method-inl.h b/runtime/mirror/art_method-inl.h index c50c703..ae17070 100644 --- a/runtime/mirror/art_method-inl.h +++ b/runtime/mirror/art_method-inl.h @@ -271,6 +271,9 @@ inline const uint8_t* ArtMethod::GetVmapTable() { } inline const uint8_t* ArtMethod::GetVmapTable(const void* code_pointer) { + if (IsOptimized()) { + LOG(FATAL) << "Unimplemented vmap table for optimized compiler"; + } DCHECK(code_pointer != nullptr); DCHECK(code_pointer == GetQuickOatCodePointer()); uint32_t offset = @@ -281,6 +284,17 @@ inline const uint8_t* ArtMethod::GetVmapTable(const void* code_pointer) { return reinterpret_cast<const uint8_t*>(code_pointer) - offset; } +inline StackMap ArtMethod::GetStackMap(uint32_t native_pc_offset) { + DCHECK(IsOptimized()); + const void* code_pointer = GetQuickOatCodePointer(); + DCHECK(code_pointer != nullptr); + uint32_t offset = + reinterpret_cast<const OatQuickMethodHeader*>(code_pointer)[-1].vmap_table_offset_; + const void* data = reinterpret_cast<const void*>(reinterpret_cast<const uint8_t*>(code_pointer) - offset); + CodeInfo code_info(data); + return code_info.GetStackMapForNativePcOffset(native_pc_offset); +} + inline void ArtMethod::SetOatNativeGcMapOffset(uint32_t gc_map_offset) { DCHECK(!Runtime::Current()->IsStarted()); SetNativeGcMap(reinterpret_cast<uint8_t*>(gc_map_offset)); diff --git a/runtime/mirror/art_method.h b/runtime/mirror/art_method.h index ebd5bd5..d37aa57 100644 --- a/runtime/mirror/art_method.h +++ b/runtime/mirror/art_method.h @@ -25,6 +25,7 @@ #include "object_callbacks.h" #include "quick/quick_method_frame_info.h" #include "read_barrier_option.h" +#include "stack_map.h" namespace art { @@ -150,6 +151,13 @@ class MANAGED ArtMethod FINAL : public Object { SetAccessFlags(GetAccessFlags() | kAccPreverified); } + bool IsOptimized() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + // Temporary solution for detecting if a method has been optimized: the compiler + // does not create a GC map. Instead, the vmap table contains the stack map + // (as in stack_map.h). + return (GetEntryPointFromQuickCompiledCode() != nullptr) && (GetNativeGcMap() == nullptr); + } + bool IsPortableCompiled() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { return (GetAccessFlags() & kAccPortableCompiled) != 0; } @@ -340,6 +348,8 @@ class MANAGED ArtMethod FINAL : public Object { const uint8_t* GetVmapTable(const void* code_pointer) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + StackMap GetStackMap(uint32_t native_pc_offset) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + const uint8_t* GetNativeGcMap() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { return GetFieldPtr<uint8_t*>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, gc_map_)); } diff --git a/runtime/stack.cc b/runtime/stack.cc index 2d0060e..b8b10d2 100644 --- a/runtime/stack.cc +++ b/runtime/stack.cc @@ -115,18 +115,22 @@ uint32_t StackVisitor::GetDexPc(bool abort_on_failure) const { mirror::Object* StackVisitor::GetThisObject() const { mirror::ArtMethod* m = GetMethod(); if (m->IsStatic()) { - return NULL; + return nullptr; } else if (m->IsNative()) { - if (cur_quick_frame_ != NULL) { + if (cur_quick_frame_ != nullptr) { HandleScope* hs = reinterpret_cast<HandleScope*>( reinterpret_cast<char*>(cur_quick_frame_) + m->GetHandleScopeOffsetInBytes()); return hs->GetReference(0); } else { return cur_shadow_frame_->GetVRegReference(0); } + } else if (m->IsOptimized()) { + // TODO: Implement, currently only used for exceptions when jdwp is enabled. + LOG(WARNING) << "StackVisitor::GetThisObject is unimplemented with the optimizing compiler"; + return nullptr; } else { const DexFile::CodeItem* code_item = m->GetCodeItem(); - if (code_item == NULL) { + if (code_item == nullptr) { UNIMPLEMENTED(ERROR) << "Failed to determine this object of abstract or proxy method: " << PrettyMethod(m); return nullptr; diff --git a/runtime/stack_map.h b/runtime/stack_map.h index 7d3a48f..9b49d31 100644 --- a/runtime/stack_map.h +++ b/runtime/stack_map.h @@ -64,9 +64,9 @@ class InlineInfo { MemoryRegion region_; - template<typename T> friend class CodeInfo; - template<typename T> friend class StackMap; - template<typename T> friend class StackMapStream; + friend class CodeInfo; + friend class StackMap; + friend class StackMapStream; }; /** @@ -77,13 +77,15 @@ class InlineInfo { * The location_kind for a Dex register can either be: * - Constant: register_value holds the constant, * - Stack: register_value holds the stack offset, - * - Register: register_value holds the register number. + * - Register: register_value holds the physical register number. + * - None: the register has no location yet, meaning it has not been set. */ class DexRegisterMap { public: explicit DexRegisterMap(MemoryRegion region) : region_(region) {} enum LocationKind { + kNone, kInStack, kInRegister, kConstant @@ -114,8 +116,8 @@ class DexRegisterMap { MemoryRegion region_; - template <typename T> friend class CodeInfo; - template <typename T> friend class StackMapStream; + friend class CodeInfo; + friend class StackMapStream; }; /** @@ -127,12 +129,11 @@ class DexRegisterMap { * - Knowing the values of dex registers. * * The information is of the form: - * [dex_pc, native_pc, dex_register_map_offset, inlining_info_offset, register_mask, stack_mask]. + * [dex_pc, native_pc_offset, dex_register_map_offset, inlining_info_offset, register_mask, stack_mask]. * * Note that register_mask is fixed size, but stack_mask is variable size, depending on the * stack size of a method. */ -template <typename T> class StackMap { public: explicit StackMap(MemoryRegion region) : region_(region) {} @@ -145,12 +146,12 @@ class StackMap { region_.Store<uint32_t>(kDexPcOffset, dex_pc); } - T GetNativePc() const { - return region_.Load<T>(kNativePcOffset); + uint32_t GetNativePcOffset() const { + return region_.Load<uint32_t>(kNativePcOffsetOffset); } - void SetNativePc(T native_pc) { - return region_.Store<T>(kNativePcOffset, native_pc); + void SetNativePcOffset(uint32_t native_pc_offset) { + return region_.Store<uint32_t>(kNativePcOffsetOffset, native_pc_offset); } uint32_t GetDexRegisterMapOffset() const { @@ -199,8 +200,8 @@ class StackMap { private: static constexpr int kDexPcOffset = 0; - static constexpr int kNativePcOffset = kDexPcOffset + sizeof(uint32_t); - static constexpr int kDexRegisterMapOffsetOffset = kNativePcOffset + sizeof(T); + static constexpr int kNativePcOffsetOffset = kDexPcOffset + sizeof(uint32_t); + static constexpr int kDexRegisterMapOffsetOffset = kNativePcOffsetOffset + sizeof(uint32_t); static constexpr int kInlineDescriptorOffsetOffset = kDexRegisterMapOffsetOffset + sizeof(uint32_t); static constexpr int kRegisterMaskOffset = kInlineDescriptorOffsetOffset + sizeof(uint32_t); @@ -211,24 +212,36 @@ class StackMap { MemoryRegion region_; - template <typename U> friend class CodeInfo; - template <typename U> friend class StackMapStream; + friend class CodeInfo; + friend class StackMapStream; }; /** * Wrapper around all compiler information collected for a method. * The information is of the form: - * [number_of_stack_maps, stack_mask_size, StackMap+, DexRegisterInfo+, InlineInfo*]. + * [overall_size, number_of_stack_maps, stack_mask_size, StackMap+, DexRegisterInfo+, InlineInfo*]. */ -template <typename T> class CodeInfo { public: explicit CodeInfo(MemoryRegion region) : region_(region) {} - StackMap<T> GetStackMapAt(size_t i) const { + explicit CodeInfo(const void* data) { + uint32_t size = reinterpret_cast<const uint32_t*>(data)[0]; + region_ = MemoryRegion(const_cast<void*>(data), size); + } + + StackMap GetStackMapAt(size_t i) const { size_t size = StackMapSize(); - return StackMap<T>(GetStackMaps().Subregion(i * size, size)); + return StackMap(GetStackMaps().Subregion(i * size, size)); + } + + uint32_t GetOverallSize() const { + return region_.Load<uint32_t>(kOverallSizeOffset); + } + + void SetOverallSize(uint32_t size) { + region_.Store<uint32_t>(kOverallSizeOffset, size); } uint32_t GetStackMaskSize() const { @@ -248,47 +261,48 @@ class CodeInfo { } size_t StackMapSize() const { - return StackMap<T>::kFixedSize + GetStackMaskSize(); + return StackMap::kFixedSize + GetStackMaskSize(); } - DexRegisterMap GetDexRegisterMapOf(StackMap<T> stack_map, uint32_t number_of_dex_registers) { + DexRegisterMap GetDexRegisterMapOf(StackMap stack_map, uint32_t number_of_dex_registers) { uint32_t offset = stack_map.GetDexRegisterMapOffset(); return DexRegisterMap(region_.Subregion(offset, DexRegisterMap::kFixedSize + number_of_dex_registers * DexRegisterMap::SingleEntrySize())); } - InlineInfo GetInlineInfoOf(StackMap<T> stack_map) { + InlineInfo GetInlineInfoOf(StackMap stack_map) { uint32_t offset = stack_map.GetInlineDescriptorOffset(); uint8_t depth = region_.Load<uint8_t>(offset); return InlineInfo(region_.Subregion(offset, InlineInfo::kFixedSize + depth * InlineInfo::SingleEntrySize())); } - StackMap<T> GetStackMapForDexPc(uint32_t dex_pc) { + StackMap GetStackMapForDexPc(uint32_t dex_pc) { for (size_t i = 0, e = GetNumberOfStackMaps(); i < e; ++i) { - StackMap<T> stack_map = GetStackMapAt(i); + StackMap stack_map = GetStackMapAt(i); if (stack_map.GetDexPc() == dex_pc) { return stack_map; } } LOG(FATAL) << "Unreachable"; - return StackMap<T>(MemoryRegion()); + return StackMap(MemoryRegion()); } - StackMap<T> GetStackMapForNativePc(T native_pc) { + StackMap GetStackMapForNativePcOffset(uint32_t native_pc_offset) { // TODO: stack maps are sorted by native pc, we can do a binary search. for (size_t i = 0, e = GetNumberOfStackMaps(); i < e; ++i) { - StackMap<T> stack_map = GetStackMapAt(i); - if (stack_map.GetNativePc() == native_pc) { + StackMap stack_map = GetStackMapAt(i); + if (stack_map.GetNativePcOffset() == native_pc_offset) { return stack_map; } } LOG(FATAL) << "Unreachable"; - return StackMap<T>(MemoryRegion()); + return StackMap(MemoryRegion()); } private: - static constexpr int kNumberOfStackMapsOffset = 0; + static constexpr int kOverallSizeOffset = 0; + static constexpr int kNumberOfStackMapsOffset = kOverallSizeOffset + sizeof(uint32_t); static constexpr int kStackMaskSizeOffset = kNumberOfStackMapsOffset + sizeof(uint32_t); static constexpr int kFixedSize = kStackMaskSizeOffset + sizeof(uint32_t); @@ -299,7 +313,7 @@ class CodeInfo { } MemoryRegion region_; - template<typename U> friend class StackMapStream; + friend class StackMapStream; }; } // namespace art diff --git a/runtime/thread.cc b/runtime/thread.cc index e323473..6e3e9c1 100644 --- a/runtime/thread.cc +++ b/runtime/thread.cc @@ -2070,48 +2070,72 @@ class ReferenceMapVisitor : public StackVisitor { // Process register map (which native and runtime methods don't have) if (!m->IsNative() && !m->IsRuntimeMethod() && !m->IsProxyMethod()) { - const uint8_t* native_gc_map = m->GetNativeGcMap(); - CHECK(native_gc_map != nullptr) << PrettyMethod(m); - const DexFile::CodeItem* code_item = m->GetCodeItem(); - DCHECK(code_item != nullptr) << PrettyMethod(m); // Can't be nullptr or how would we compile its instructions? - NativePcOffsetToReferenceMap map(native_gc_map); - size_t num_regs = std::min(map.RegWidth() * 8, - static_cast<size_t>(code_item->registers_size_)); - if (num_regs > 0) { + if (m->IsOptimized()) { Runtime* runtime = Runtime::Current(); const void* entry_point = runtime->GetInstrumentation()->GetQuickCodeFor(m); uintptr_t native_pc_offset = m->NativePcOffset(GetCurrentQuickFramePc(), entry_point); - const uint8_t* reg_bitmap = map.FindBitMap(native_pc_offset); - DCHECK(reg_bitmap != nullptr); - const void* code_pointer = mirror::ArtMethod::EntryPointToCodePointer(entry_point); - const VmapTable vmap_table(m->GetVmapTable(code_pointer)); - QuickMethodFrameInfo frame_info = m->GetQuickFrameInfo(code_pointer); - // For all dex registers in the bitmap - StackReference<mirror::ArtMethod>* cur_quick_frame = GetCurrentQuickFrame(); - DCHECK(cur_quick_frame != nullptr); - for (size_t reg = 0; reg < num_regs; ++reg) { - // Does this register hold a reference? - if (TestBitmap(reg, reg_bitmap)) { - uint32_t vmap_offset; - if (vmap_table.IsInContext(reg, kReferenceVReg, &vmap_offset)) { - int vmap_reg = vmap_table.ComputeRegister(frame_info.CoreSpillMask(), vmap_offset, - kReferenceVReg); - // This is sound as spilled GPRs will be word sized (ie 32 or 64bit). - mirror::Object** ref_addr = reinterpret_cast<mirror::Object**>(GetGPRAddress(vmap_reg)); - if (*ref_addr != nullptr) { - visitor_(ref_addr, reg, this); + StackMap map = m->GetStackMap(native_pc_offset); + MemoryRegion mask = map.GetStackMask(); + for (size_t i = 0; i < mask.size_in_bits(); ++i) { + if (mask.LoadBit(i)) { + StackReference<mirror::Object>* ref_addr = + reinterpret_cast<StackReference<mirror::Object>*>(cur_quick_frame) + i; + mirror::Object* ref = ref_addr->AsMirrorPtr(); + if (ref != nullptr) { + mirror::Object* new_ref = ref; + visitor_(&new_ref, -1, this); + if (ref != new_ref) { + ref_addr->Assign(new_ref); } - } else { - StackReference<mirror::Object>* ref_addr = - reinterpret_cast<StackReference<mirror::Object>*>( - GetVRegAddr(cur_quick_frame, code_item, frame_info.CoreSpillMask(), - frame_info.FpSpillMask(), frame_info.FrameSizeInBytes(), reg)); - mirror::Object* ref = ref_addr->AsMirrorPtr(); - if (ref != nullptr) { - mirror::Object* new_ref = ref; - visitor_(&new_ref, reg, this); - if (ref != new_ref) { - ref_addr->Assign(new_ref); + } + } + } + } else { + const uint8_t* native_gc_map = m->GetNativeGcMap(); + CHECK(native_gc_map != nullptr) << PrettyMethod(m); + const DexFile::CodeItem* code_item = m->GetCodeItem(); + // Can't be nullptr or how would we compile its instructions? + DCHECK(code_item != nullptr) << PrettyMethod(m); + NativePcOffsetToReferenceMap map(native_gc_map); + size_t num_regs = std::min(map.RegWidth() * 8, + static_cast<size_t>(code_item->registers_size_)); + if (num_regs > 0) { + Runtime* runtime = Runtime::Current(); + const void* entry_point = runtime->GetInstrumentation()->GetQuickCodeFor(m); + uintptr_t native_pc_offset = m->NativePcOffset(GetCurrentQuickFramePc(), entry_point); + const uint8_t* reg_bitmap = map.FindBitMap(native_pc_offset); + DCHECK(reg_bitmap != nullptr); + const void* code_pointer = mirror::ArtMethod::EntryPointToCodePointer(entry_point); + const VmapTable vmap_table(m->GetVmapTable(code_pointer)); + QuickMethodFrameInfo frame_info = m->GetQuickFrameInfo(code_pointer); + // For all dex registers in the bitmap + StackReference<mirror::ArtMethod>* cur_quick_frame = GetCurrentQuickFrame(); + DCHECK(cur_quick_frame != nullptr); + for (size_t reg = 0; reg < num_regs; ++reg) { + // Does this register hold a reference? + if (TestBitmap(reg, reg_bitmap)) { + uint32_t vmap_offset; + if (vmap_table.IsInContext(reg, kReferenceVReg, &vmap_offset)) { + int vmap_reg = vmap_table.ComputeRegister(frame_info.CoreSpillMask(), vmap_offset, + kReferenceVReg); + // This is sound as spilled GPRs will be word sized (ie 32 or 64bit). + mirror::Object** ref_addr = + reinterpret_cast<mirror::Object**>(GetGPRAddress(vmap_reg)); + if (*ref_addr != nullptr) { + visitor_(ref_addr, reg, this); + } + } else { + StackReference<mirror::Object>* ref_addr = + reinterpret_cast<StackReference<mirror::Object>*>( + GetVRegAddr(cur_quick_frame, code_item, frame_info.CoreSpillMask(), + frame_info.FpSpillMask(), frame_info.FrameSizeInBytes(), reg)); + mirror::Object* ref = ref_addr->AsMirrorPtr(); + if (ref != nullptr) { + mirror::Object* new_ref = ref; + visitor_(&new_ref, reg, this); + if (ref != new_ref) { + ref_addr->Assign(new_ref); + } } } } diff --git a/test/407-arrays/src/Main.java b/test/407-arrays/src/Main.java index 5d27e6d..b5e95b0 100644 --- a/test/407-arrays/src/Main.java +++ b/test/407-arrays/src/Main.java @@ -57,7 +57,7 @@ public class Main extends TestCase { int[] ints, Object[] objects, long[] longs, int index) { bools[0] = true; assertEquals(true, bools[0]); - bools[1] = true; + bools[index] = true; assertEquals(true, bools[index]); bytes[0] = -4; |