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 |