| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/locations.h" | 5 #include "vm/locations.h" |
| 6 | 6 |
| 7 #include "vm/assembler.h" | 7 #include "vm/assembler.h" |
| 8 #include "vm/il_printer.h" | 8 #include "vm/il_printer.h" |
| 9 #include "vm/log.h" | 9 #include "vm/log.h" |
| 10 #include "vm/stack_frame.h" | 10 #include "vm/stack_frame.h" |
| 11 | 11 |
| 12 namespace dart { | 12 namespace dart { |
| 13 | 13 |
| 14 intptr_t RegisterSet::RegisterCount(intptr_t registers) { | 14 intptr_t RegisterSet::RegisterCount(intptr_t registers) { |
| 15 // Brian Kernighan's algorithm for counting the bits set. | 15 // Brian Kernighan's algorithm for counting the bits set. |
| 16 intptr_t count = 0; | 16 intptr_t count = 0; |
| 17 while (registers != 0) { | 17 while (registers != 0) { |
| 18 ++count; | 18 ++count; |
| 19 registers &= (registers - 1); // Clear the least significant bit set. | 19 registers &= (registers - 1); // Clear the least significant bit set. |
| 20 } | 20 } |
| 21 return count; | 21 return count; |
| 22 } | 22 } |
| 23 | 23 |
| 24 | |
| 25 LocationSummary::LocationSummary(Zone* zone, | 24 LocationSummary::LocationSummary(Zone* zone, |
| 26 intptr_t input_count, | 25 intptr_t input_count, |
| 27 intptr_t temp_count, | 26 intptr_t temp_count, |
| 28 LocationSummary::ContainsCall contains_call) | 27 LocationSummary::ContainsCall contains_call) |
| 29 : num_inputs_(input_count), | 28 : num_inputs_(input_count), |
| 30 num_temps_(temp_count), | 29 num_temps_(temp_count), |
| 31 stack_bitmap_(NULL), | 30 stack_bitmap_(NULL), |
| 32 contains_call_(contains_call), | 31 contains_call_(contains_call), |
| 33 live_registers_() { | 32 live_registers_() { |
| 34 #if defined(DEBUG) | 33 #if defined(DEBUG) |
| 35 writable_inputs_ = 0; | 34 writable_inputs_ = 0; |
| 36 #endif | 35 #endif |
| 37 input_locations_ = zone->Alloc<Location>(num_inputs_); | 36 input_locations_ = zone->Alloc<Location>(num_inputs_); |
| 38 temp_locations_ = zone->Alloc<Location>(num_temps_); | 37 temp_locations_ = zone->Alloc<Location>(num_temps_); |
| 39 } | 38 } |
| 40 | 39 |
| 41 | |
| 42 LocationSummary* LocationSummary::Make( | 40 LocationSummary* LocationSummary::Make( |
| 43 Zone* zone, | 41 Zone* zone, |
| 44 intptr_t input_count, | 42 intptr_t input_count, |
| 45 Location out, | 43 Location out, |
| 46 LocationSummary::ContainsCall contains_call) { | 44 LocationSummary::ContainsCall contains_call) { |
| 47 LocationSummary* summary = | 45 LocationSummary* summary = |
| 48 new (zone) LocationSummary(zone, input_count, 0, contains_call); | 46 new (zone) LocationSummary(zone, input_count, 0, contains_call); |
| 49 for (intptr_t i = 0; i < input_count; i++) { | 47 for (intptr_t i = 0; i < input_count; i++) { |
| 50 summary->set_in(i, Location::RequiresRegister()); | 48 summary->set_in(i, Location::RequiresRegister()); |
| 51 } | 49 } |
| 52 summary->set_out(0, out); | 50 summary->set_out(0, out); |
| 53 return summary; | 51 return summary; |
| 54 } | 52 } |
| 55 | 53 |
| 56 | |
| 57 Location Location::Pair(Location first, Location second) { | 54 Location Location::Pair(Location first, Location second) { |
| 58 PairLocation* pair_location = new PairLocation(); | 55 PairLocation* pair_location = new PairLocation(); |
| 59 ASSERT((reinterpret_cast<intptr_t>(pair_location) & kLocationTagMask) == 0); | 56 ASSERT((reinterpret_cast<intptr_t>(pair_location) & kLocationTagMask) == 0); |
| 60 pair_location->SetAt(0, first); | 57 pair_location->SetAt(0, first); |
| 61 pair_location->SetAt(1, second); | 58 pair_location->SetAt(1, second); |
| 62 Location loc(reinterpret_cast<uword>(pair_location) | kPairLocationTag); | 59 Location loc(reinterpret_cast<uword>(pair_location) | kPairLocationTag); |
| 63 return loc; | 60 return loc; |
| 64 } | 61 } |
| 65 | 62 |
| 66 | |
| 67 PairLocation* Location::AsPairLocation() const { | 63 PairLocation* Location::AsPairLocation() const { |
| 68 ASSERT(IsPairLocation()); | 64 ASSERT(IsPairLocation()); |
| 69 return reinterpret_cast<PairLocation*>(value_ & ~kLocationTagMask); | 65 return reinterpret_cast<PairLocation*>(value_ & ~kLocationTagMask); |
| 70 } | 66 } |
| 71 | 67 |
| 72 | |
| 73 Location Location::RegisterOrConstant(Value* value) { | 68 Location Location::RegisterOrConstant(Value* value) { |
| 74 ConstantInstr* constant = value->definition()->AsConstant(); | 69 ConstantInstr* constant = value->definition()->AsConstant(); |
| 75 return ((constant != NULL) && Assembler::IsSafe(constant->value())) | 70 return ((constant != NULL) && Assembler::IsSafe(constant->value())) |
| 76 ? Location::Constant(constant) | 71 ? Location::Constant(constant) |
| 77 : Location::RequiresRegister(); | 72 : Location::RequiresRegister(); |
| 78 } | 73 } |
| 79 | 74 |
| 80 | |
| 81 Location Location::RegisterOrSmiConstant(Value* value) { | 75 Location Location::RegisterOrSmiConstant(Value* value) { |
| 82 ConstantInstr* constant = value->definition()->AsConstant(); | 76 ConstantInstr* constant = value->definition()->AsConstant(); |
| 83 return ((constant != NULL) && Assembler::IsSafeSmi(constant->value())) | 77 return ((constant != NULL) && Assembler::IsSafeSmi(constant->value())) |
| 84 ? Location::Constant(constant) | 78 ? Location::Constant(constant) |
| 85 : Location::RequiresRegister(); | 79 : Location::RequiresRegister(); |
| 86 } | 80 } |
| 87 | 81 |
| 88 | |
| 89 Location Location::WritableRegisterOrSmiConstant(Value* value) { | 82 Location Location::WritableRegisterOrSmiConstant(Value* value) { |
| 90 ConstantInstr* constant = value->definition()->AsConstant(); | 83 ConstantInstr* constant = value->definition()->AsConstant(); |
| 91 return ((constant != NULL) && Assembler::IsSafeSmi(constant->value())) | 84 return ((constant != NULL) && Assembler::IsSafeSmi(constant->value())) |
| 92 ? Location::Constant(constant) | 85 ? Location::Constant(constant) |
| 93 : Location::WritableRegister(); | 86 : Location::WritableRegister(); |
| 94 } | 87 } |
| 95 | 88 |
| 96 | |
| 97 Location Location::FixedRegisterOrConstant(Value* value, Register reg) { | 89 Location Location::FixedRegisterOrConstant(Value* value, Register reg) { |
| 98 ConstantInstr* constant = value->definition()->AsConstant(); | 90 ConstantInstr* constant = value->definition()->AsConstant(); |
| 99 return ((constant != NULL) && Assembler::IsSafe(constant->value())) | 91 return ((constant != NULL) && Assembler::IsSafe(constant->value())) |
| 100 ? Location::Constant(constant) | 92 ? Location::Constant(constant) |
| 101 : Location::RegisterLocation(reg); | 93 : Location::RegisterLocation(reg); |
| 102 } | 94 } |
| 103 | 95 |
| 104 | |
| 105 Location Location::FixedRegisterOrSmiConstant(Value* value, Register reg) { | 96 Location Location::FixedRegisterOrSmiConstant(Value* value, Register reg) { |
| 106 ConstantInstr* constant = value->definition()->AsConstant(); | 97 ConstantInstr* constant = value->definition()->AsConstant(); |
| 107 return ((constant != NULL) && Assembler::IsSafeSmi(constant->value())) | 98 return ((constant != NULL) && Assembler::IsSafeSmi(constant->value())) |
| 108 ? Location::Constant(constant) | 99 ? Location::Constant(constant) |
| 109 : Location::RegisterLocation(reg); | 100 : Location::RegisterLocation(reg); |
| 110 } | 101 } |
| 111 | 102 |
| 112 | |
| 113 Location Location::AnyOrConstant(Value* value) { | 103 Location Location::AnyOrConstant(Value* value) { |
| 114 ConstantInstr* constant = value->definition()->AsConstant(); | 104 ConstantInstr* constant = value->definition()->AsConstant(); |
| 115 return ((constant != NULL) && Assembler::IsSafe(constant->value())) | 105 return ((constant != NULL) && Assembler::IsSafe(constant->value())) |
| 116 ? Location::Constant(constant) | 106 ? Location::Constant(constant) |
| 117 : Location::Any(); | 107 : Location::Any(); |
| 118 } | 108 } |
| 119 | 109 |
| 120 | |
| 121 // DBC does not have an notion of 'address' in its instruction set. | 110 // DBC does not have an notion of 'address' in its instruction set. |
| 122 #if !defined(TARGET_ARCH_DBC) | 111 #if !defined(TARGET_ARCH_DBC) |
| 123 Address Location::ToStackSlotAddress() const { | 112 Address Location::ToStackSlotAddress() const { |
| 124 const intptr_t index = stack_index(); | 113 const intptr_t index = stack_index(); |
| 125 const Register base = base_reg(); | 114 const Register base = base_reg(); |
| 126 if (base == FPREG) { | 115 if (base == FPREG) { |
| 127 if (index < 0) { | 116 if (index < 0) { |
| 128 const intptr_t offset = (kParamEndSlotFromFp - index) * kWordSize; | 117 const intptr_t offset = (kParamEndSlotFromFp - index) * kWordSize; |
| 129 return Address(base, offset); | 118 return Address(base, offset); |
| 130 } else { | 119 } else { |
| (...skipping 16 matching lines...) Expand all Loading... |
| 147 } else { | 136 } else { |
| 148 const intptr_t offset = (kFirstLocalSlotFromFp - index) * kWordSize; | 137 const intptr_t offset = (kFirstLocalSlotFromFp - index) * kWordSize; |
| 149 return offset; | 138 return offset; |
| 150 } | 139 } |
| 151 } else { | 140 } else { |
| 152 ASSERT(base_reg() == SPREG); | 141 ASSERT(base_reg() == SPREG); |
| 153 return index * kWordSize; | 142 return index * kWordSize; |
| 154 } | 143 } |
| 155 } | 144 } |
| 156 | 145 |
| 157 | |
| 158 const Object& Location::constant() const { | 146 const Object& Location::constant() const { |
| 159 return constant_instruction()->value(); | 147 return constant_instruction()->value(); |
| 160 } | 148 } |
| 161 | 149 |
| 162 | |
| 163 const char* Location::Name() const { | 150 const char* Location::Name() const { |
| 164 switch (kind()) { | 151 switch (kind()) { |
| 165 case kInvalid: | 152 case kInvalid: |
| 166 return "?"; | 153 return "?"; |
| 167 case kRegister: | 154 case kRegister: |
| 168 return Assembler::RegisterName(reg()); | 155 return Assembler::RegisterName(reg()); |
| 169 case kFpuRegister: | 156 case kFpuRegister: |
| 170 return Assembler::FpuRegisterName(fpu_reg()); | 157 return Assembler::FpuRegisterName(fpu_reg()); |
| 171 case kStackSlot: | 158 case kStackSlot: |
| 172 return "S"; | 159 return "S"; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 194 if (IsConstant()) { | 181 if (IsConstant()) { |
| 195 return "C"; | 182 return "C"; |
| 196 } else { | 183 } else { |
| 197 ASSERT(IsPairLocation()); | 184 ASSERT(IsPairLocation()); |
| 198 return "2P"; | 185 return "2P"; |
| 199 } | 186 } |
| 200 } | 187 } |
| 201 return "?"; | 188 return "?"; |
| 202 } | 189 } |
| 203 | 190 |
| 204 | |
| 205 void Location::PrintTo(BufferFormatter* f) const { | 191 void Location::PrintTo(BufferFormatter* f) const { |
| 206 if (!FLAG_support_il_printer) { | 192 if (!FLAG_support_il_printer) { |
| 207 return; | 193 return; |
| 208 } | 194 } |
| 209 if (kind() == kStackSlot) { | 195 if (kind() == kStackSlot) { |
| 210 f->Print("S%+" Pd "", stack_index()); | 196 f->Print("S%+" Pd "", stack_index()); |
| 211 } else if (kind() == kDoubleStackSlot) { | 197 } else if (kind() == kDoubleStackSlot) { |
| 212 f->Print("DS%+" Pd "", stack_index()); | 198 f->Print("DS%+" Pd "", stack_index()); |
| 213 } else if (kind() == kQuadStackSlot) { | 199 } else if (kind() == kQuadStackSlot) { |
| 214 f->Print("QS%+" Pd "", stack_index()); | 200 f->Print("QS%+" Pd "", stack_index()); |
| 215 } else if (IsPairLocation()) { | 201 } else if (IsPairLocation()) { |
| 216 f->Print("("); | 202 f->Print("("); |
| 217 AsPairLocation()->At(0).PrintTo(f); | 203 AsPairLocation()->At(0).PrintTo(f); |
| 218 f->Print(", "); | 204 f->Print(", "); |
| 219 AsPairLocation()->At(1).PrintTo(f); | 205 AsPairLocation()->At(1).PrintTo(f); |
| 220 f->Print(")"); | 206 f->Print(")"); |
| 221 } else { | 207 } else { |
| 222 f->Print("%s", Name()); | 208 f->Print("%s", Name()); |
| 223 } | 209 } |
| 224 } | 210 } |
| 225 | 211 |
| 226 | |
| 227 const char* Location::ToCString() const { | 212 const char* Location::ToCString() const { |
| 228 char buffer[1024]; | 213 char buffer[1024]; |
| 229 BufferFormatter bf(buffer, 1024); | 214 BufferFormatter bf(buffer, 1024); |
| 230 PrintTo(&bf); | 215 PrintTo(&bf); |
| 231 return Thread::Current()->zone()->MakeCopyOfString(buffer); | 216 return Thread::Current()->zone()->MakeCopyOfString(buffer); |
| 232 } | 217 } |
| 233 | 218 |
| 234 | |
| 235 void Location::Print() const { | 219 void Location::Print() const { |
| 236 if (kind() == kStackSlot) { | 220 if (kind() == kStackSlot) { |
| 237 THR_Print("S%+" Pd "", stack_index()); | 221 THR_Print("S%+" Pd "", stack_index()); |
| 238 } else { | 222 } else { |
| 239 THR_Print("%s", Name()); | 223 THR_Print("%s", Name()); |
| 240 } | 224 } |
| 241 } | 225 } |
| 242 | 226 |
| 243 | |
| 244 Location Location::Copy() const { | 227 Location Location::Copy() const { |
| 245 if (IsPairLocation()) { | 228 if (IsPairLocation()) { |
| 246 PairLocation* pair = AsPairLocation(); | 229 PairLocation* pair = AsPairLocation(); |
| 247 ASSERT(!pair->At(0).IsPairLocation()); | 230 ASSERT(!pair->At(0).IsPairLocation()); |
| 248 ASSERT(!pair->At(1).IsPairLocation()); | 231 ASSERT(!pair->At(1).IsPairLocation()); |
| 249 return Location::Pair(pair->At(0).Copy(), pair->At(1).Copy()); | 232 return Location::Pair(pair->At(0).Copy(), pair->At(1).Copy()); |
| 250 } else { | 233 } else { |
| 251 // Copy by value. | 234 // Copy by value. |
| 252 return *this; | 235 return *this; |
| 253 } | 236 } |
| 254 } | 237 } |
| 255 | 238 |
| 256 | |
| 257 Location Location::RemapForSlowPath(Definition* def, | 239 Location Location::RemapForSlowPath(Definition* def, |
| 258 intptr_t* cpu_reg_slots, | 240 intptr_t* cpu_reg_slots, |
| 259 intptr_t* fpu_reg_slots) const { | 241 intptr_t* fpu_reg_slots) const { |
| 260 if (IsRegister()) { | 242 if (IsRegister()) { |
| 261 intptr_t index = cpu_reg_slots[reg()]; | 243 intptr_t index = cpu_reg_slots[reg()]; |
| 262 ASSERT(index >= 0); | 244 ASSERT(index >= 0); |
| 263 return Location::StackSlot(index); | 245 return Location::StackSlot(index); |
| 264 } else if (IsFpuRegister()) { | 246 } else if (IsFpuRegister()) { |
| 265 intptr_t index = fpu_reg_slots[fpu_reg()]; | 247 intptr_t index = fpu_reg_slots[fpu_reg()]; |
| 266 ASSERT(index >= 0); | 248 ASSERT(index >= 0); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 299 return Location::Pair(Location::StackSlot(index_lo), | 281 return Location::Pair(Location::StackSlot(index_lo), |
| 300 Location::StackSlot(index_hi)); | 282 Location::StackSlot(index_hi)); |
| 301 } else if (IsInvalid() && def->IsMaterializeObject()) { | 283 } else if (IsInvalid() && def->IsMaterializeObject()) { |
| 302 def->AsMaterializeObject()->RemapRegisters(cpu_reg_slots, fpu_reg_slots); | 284 def->AsMaterializeObject()->RemapRegisters(cpu_reg_slots, fpu_reg_slots); |
| 303 return *this; | 285 return *this; |
| 304 } | 286 } |
| 305 | 287 |
| 306 return *this; | 288 return *this; |
| 307 } | 289 } |
| 308 | 290 |
| 309 | |
| 310 void LocationSummary::PrintTo(BufferFormatter* f) const { | 291 void LocationSummary::PrintTo(BufferFormatter* f) const { |
| 311 if (!FLAG_support_il_printer) { | 292 if (!FLAG_support_il_printer) { |
| 312 return; | 293 return; |
| 313 } | 294 } |
| 314 if (input_count() > 0) { | 295 if (input_count() > 0) { |
| 315 f->Print(" ("); | 296 f->Print(" ("); |
| 316 for (intptr_t i = 0; i < input_count(); i++) { | 297 for (intptr_t i = 0; i < input_count(); i++) { |
| 317 if (i != 0) f->Print(", "); | 298 if (i != 0) f->Print(", "); |
| 318 in(i).PrintTo(f); | 299 in(i).PrintTo(f); |
| 319 } | 300 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 330 } | 311 } |
| 331 | 312 |
| 332 if (!out(0).IsInvalid()) { | 313 if (!out(0).IsInvalid()) { |
| 333 f->Print(" => "); | 314 f->Print(" => "); |
| 334 out(0).PrintTo(f); | 315 out(0).PrintTo(f); |
| 335 } | 316 } |
| 336 | 317 |
| 337 if (always_calls()) f->Print(" C"); | 318 if (always_calls()) f->Print(" C"); |
| 338 } | 319 } |
| 339 | 320 |
| 340 | |
| 341 #if defined(DEBUG) | 321 #if defined(DEBUG) |
| 342 void LocationSummary::DiscoverWritableInputs() { | 322 void LocationSummary::DiscoverWritableInputs() { |
| 343 if (!HasCallOnSlowPath()) { | 323 if (!HasCallOnSlowPath()) { |
| 344 return; | 324 return; |
| 345 } | 325 } |
| 346 | 326 |
| 347 for (intptr_t i = 0; i < input_count(); i++) { | 327 for (intptr_t i = 0; i < input_count(); i++) { |
| 348 if (in(i).IsUnallocated() && | 328 if (in(i).IsUnallocated() && |
| 349 (in(i).policy() == Location::kWritableRegister)) { | 329 (in(i).policy() == Location::kWritableRegister)) { |
| 350 writable_inputs_ |= 1 << i; | 330 writable_inputs_ |= 1 << i; |
| 351 } | 331 } |
| 352 } | 332 } |
| 353 } | 333 } |
| 354 | 334 |
| 355 | |
| 356 void LocationSummary::CheckWritableInputs() { | 335 void LocationSummary::CheckWritableInputs() { |
| 357 ASSERT(HasCallOnSlowPath()); | 336 ASSERT(HasCallOnSlowPath()); |
| 358 for (intptr_t i = 0; i < input_count(); i++) { | 337 for (intptr_t i = 0; i < input_count(); i++) { |
| 359 if ((writable_inputs_ & (1 << i)) != 0) { | 338 if ((writable_inputs_ & (1 << i)) != 0) { |
| 360 // Writable registers have to be manually preserved because | 339 // Writable registers have to be manually preserved because |
| 361 // with the right representation because register allocator does not know | 340 // with the right representation because register allocator does not know |
| 362 // how they are used within the instruction template. | 341 // how they are used within the instruction template. |
| 363 ASSERT(in(i).IsMachineRegister()); | 342 ASSERT(in(i).IsMachineRegister()); |
| 364 ASSERT(live_registers()->Contains(in(i))); | 343 ASSERT(live_registers()->Contains(in(i))); |
| 365 } | 344 } |
| 366 } | 345 } |
| 367 } | 346 } |
| 368 #endif | 347 #endif |
| 369 | 348 |
| 370 } // namespace dart | 349 } // namespace dart |
| OLD | NEW |