| // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| #include "vm/locations.h" |
| |
| #include "vm/assembler.h" |
| #include "vm/il_printer.h" |
| #include "vm/intermediate_language.h" |
| #include "vm/flow_graph_compiler.h" |
| #include "vm/stack_frame.h" |
| |
| namespace dart { |
| |
| intptr_t RegisterSet::RegisterCount(intptr_t registers) { |
| // Brian Kernighan's algorithm for counting the bits set. |
| intptr_t count = 0; |
| while (registers != 0) { |
| ++count; |
| registers &= (registers - 1); // Clear the least significant bit set. |
| } |
| return count; |
| } |
| |
| |
| LocationSummary::LocationSummary(Isolate* isolate, |
| intptr_t input_count, |
| intptr_t temp_count, |
| LocationSummary::ContainsCall contains_call) |
| : input_locations_(isolate, input_count), |
| temp_locations_(isolate, temp_count), |
| output_locations_(isolate, 1), |
| stack_bitmap_(NULL), |
| contains_call_(contains_call), |
| live_registers_() { |
| for (intptr_t i = 0; i < input_count; i++) { |
| input_locations_.Add(Location()); |
| } |
| for (intptr_t i = 0; i < temp_count; i++) { |
| temp_locations_.Add(Location()); |
| } |
| output_locations_.Add(Location()); |
| ASSERT(output_locations_.length() == 1); |
| } |
| |
| |
| LocationSummary::LocationSummary(Isolate* isolate, |
| intptr_t input_count, |
| intptr_t temp_count, |
| intptr_t output_count, |
| LocationSummary::ContainsCall contains_call) |
| : input_locations_(isolate, input_count), |
| temp_locations_(isolate, temp_count), |
| output_locations_(isolate, output_count), |
| stack_bitmap_(NULL), |
| contains_call_(contains_call), |
| live_registers_() { |
| for (intptr_t i = 0; i < input_count; i++) { |
| input_locations_.Add(Location()); |
| } |
| for (intptr_t i = 0; i < temp_count; i++) { |
| temp_locations_.Add(Location()); |
| } |
| // TODO(johnmccutchan): Remove this assertion once support for multiple |
| // outputs is complete. |
| ASSERT(output_count == 1); |
| for (intptr_t i = 0; i < output_count; i++) { |
| output_locations_.Add(Location()); |
| } |
| } |
| |
| |
| LocationSummary* LocationSummary::Make( |
| Isolate* isolate, |
| intptr_t input_count, |
| Location out, |
| LocationSummary::ContainsCall contains_call) { |
| LocationSummary* summary = new(isolate) LocationSummary( |
| isolate, input_count, 0, contains_call); |
| for (intptr_t i = 0; i < input_count; i++) { |
| summary->set_in(i, Location::RequiresRegister()); |
| } |
| summary->set_out(0, out); |
| return summary; |
| } |
| |
| |
| Location Location::Pair(Location first, Location second) { |
| PairLocation* pair_location = new PairLocation(); |
| ASSERT((reinterpret_cast<intptr_t>(pair_location) & kLocationTagMask) == 0); |
| pair_location->SetAt(0, first); |
| pair_location->SetAt(1, second); |
| Location loc(reinterpret_cast<uword>(pair_location) | kPairLocationTag); |
| return loc; |
| } |
| |
| |
| PairLocation* Location::AsPairLocation() const { |
| ASSERT(IsPairLocation()); |
| return reinterpret_cast<PairLocation*>(value_ & ~kLocationTagMask); |
| } |
| |
| |
| Location Location::RegisterOrConstant(Value* value) { |
| ConstantInstr* constant = value->definition()->AsConstant(); |
| return ((constant != NULL) && Assembler::IsSafe(constant->value())) |
| ? Location::Constant(constant->value()) |
| : Location::RequiresRegister(); |
| } |
| |
| |
| Location Location::RegisterOrSmiConstant(Value* value) { |
| ConstantInstr* constant = value->definition()->AsConstant(); |
| return ((constant != NULL) && Assembler::IsSafeSmi(constant->value())) |
| ? Location::Constant(constant->value()) |
| : Location::RequiresRegister(); |
| } |
| |
| |
| Location Location::FixedRegisterOrConstant(Value* value, Register reg) { |
| ConstantInstr* constant = value->definition()->AsConstant(); |
| return ((constant != NULL) && Assembler::IsSafe(constant->value())) |
| ? Location::Constant(constant->value()) |
| : Location::RegisterLocation(reg); |
| } |
| |
| |
| Location Location::FixedRegisterOrSmiConstant(Value* value, Register reg) { |
| ConstantInstr* constant = value->definition()->AsConstant(); |
| return ((constant != NULL) && Assembler::IsSafeSmi(constant->value())) |
| ? Location::Constant(constant->value()) |
| : Location::RegisterLocation(reg); |
| } |
| |
| |
| Location Location::AnyOrConstant(Value* value) { |
| ConstantInstr* constant = value->definition()->AsConstant(); |
| return ((constant != NULL) && Assembler::IsSafe(constant->value())) |
| ? Location::Constant(constant->value()) |
| : Location::Any(); |
| } |
| |
| |
| Address Location::ToStackSlotAddress() const { |
| const intptr_t index = stack_index(); |
| if (index < 0) { |
| const intptr_t offset = (kParamEndSlotFromFp - index) * kWordSize; |
| return Address(FPREG, offset); |
| } else { |
| const intptr_t offset = (kFirstLocalSlotFromFp - index) * kWordSize; |
| return Address(FPREG, offset); |
| } |
| } |
| |
| |
| intptr_t Location::ToStackSlotOffset() const { |
| const intptr_t index = stack_index(); |
| if (index < 0) { |
| const intptr_t offset = (kParamEndSlotFromFp - index) * kWordSize; |
| return offset; |
| } else { |
| const intptr_t offset = (kFirstLocalSlotFromFp - index) * kWordSize; |
| return offset; |
| } |
| } |
| |
| |
| const char* Location::Name() const { |
| switch (kind()) { |
| case kInvalid: return "?"; |
| case kRegister: return Assembler::RegisterName(reg()); |
| case kFpuRegister: return Assembler::FpuRegisterName(fpu_reg()); |
| case kStackSlot: return "S"; |
| case kDoubleStackSlot: return "DS"; |
| case kQuadStackSlot: return "QS"; |
| case kUnallocated: |
| switch (policy()) { |
| case kAny: |
| return "A"; |
| case kPrefersRegister: |
| return "P"; |
| case kRequiresRegister: |
| return "R"; |
| case kRequiresFpuRegister: |
| return "DR"; |
| case kWritableRegister: |
| return "WR"; |
| case kSameAsFirstInput: |
| return "0"; |
| } |
| UNREACHABLE(); |
| default: |
| if (IsConstant()) { |
| return "C"; |
| } else { |
| ASSERT(IsPairLocation()); |
| return "2P"; |
| } |
| } |
| return "?"; |
| } |
| |
| |
| void Location::PrintTo(BufferFormatter* f) const { |
| if (kind() == kStackSlot) { |
| f->Print("S%+" Pd "", stack_index()); |
| } else if (kind() == kDoubleStackSlot) { |
| f->Print("DS%+" Pd "", stack_index()); |
| } else if (kind() == kQuadStackSlot) { |
| f->Print("QS%+" Pd "", stack_index()); |
| } else if (IsPairLocation()) { |
| f->Print("("); |
| AsPairLocation()->At(0).PrintTo(f); |
| f->Print(", "); |
| AsPairLocation()->At(1).PrintTo(f); |
| f->Print(")"); |
| } else { |
| f->Print("%s", Name()); |
| } |
| } |
| |
| |
| const char* Location::ToCString() const { |
| char buffer[1024]; |
| BufferFormatter bf(buffer, 1024); |
| PrintTo(&bf); |
| return Isolate::Current()->current_zone()->MakeCopyOfString(buffer); |
| } |
| |
| |
| void Location::Print() const { |
| if (kind() == kStackSlot) { |
| OS::Print("S%+" Pd "", stack_index()); |
| } else { |
| OS::Print("%s", Name()); |
| } |
| } |
| |
| |
| Location Location::Copy() const { |
| if (IsPairLocation()) { |
| PairLocation* pair = AsPairLocation(); |
| ASSERT(!pair->At(0).IsPairLocation()); |
| ASSERT(!pair->At(1).IsPairLocation()); |
| return Location::Pair(pair->At(0).Copy(), pair->At(1).Copy()); |
| } else { |
| // Copy by value. |
| return *this; |
| } |
| } |
| |
| |
| void LocationSummary::PrintTo(BufferFormatter* f) const { |
| if (input_count() > 0) { |
| f->Print(" ("); |
| for (intptr_t i = 0; i < input_count(); i++) { |
| if (i != 0) f->Print(", "); |
| in(i).PrintTo(f); |
| } |
| f->Print(")"); |
| } |
| |
| if (temp_count() > 0) { |
| f->Print(" ["); |
| for (intptr_t i = 0; i < temp_count(); i++) { |
| if (i != 0) f->Print(", "); |
| temp(i).PrintTo(f); |
| } |
| f->Print("]"); |
| } |
| |
| if (!out(0).IsInvalid()) { |
| f->Print(" => "); |
| out(0).PrintTo(f); |
| } |
| |
| if (always_calls()) f->Print(" C"); |
| } |
| |
| } // namespace dart |