OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 30 matching lines...) Expand all Loading... |
41 class HGraph; | 41 class HGraph; |
42 class HInstruction; | 42 class HInstruction; |
43 class HPhi; | 43 class HPhi; |
44 class HTracer; | 44 class HTracer; |
45 class HValue; | 45 class HValue; |
46 class BitVector; | 46 class BitVector; |
47 class StringStream; | 47 class StringStream; |
48 | 48 |
49 class LArgument; | 49 class LArgument; |
50 class LChunk; | 50 class LChunk; |
| 51 class LOperand; |
| 52 class LUnallocated; |
51 class LConstantOperand; | 53 class LConstantOperand; |
52 class LGap; | 54 class LGap; |
53 class LParallelMove; | 55 class LParallelMove; |
54 class LPointerMap; | 56 class LPointerMap; |
55 class LStackSlot; | 57 class LStackSlot; |
56 class LRegister; | 58 class LRegister; |
57 | 59 |
58 | 60 |
59 // This class represents a single point of a LOperand's lifetime. | 61 // This class represents a single point of a LOperand's lifetime. |
60 // For each lithium instruction there are exactly two lifetime positions: | 62 // For each lithium instruction there are exactly two lifetime positions: |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
142 }; | 144 }; |
143 | 145 |
144 | 146 |
145 enum RegisterKind { | 147 enum RegisterKind { |
146 NONE, | 148 NONE, |
147 GENERAL_REGISTERS, | 149 GENERAL_REGISTERS, |
148 DOUBLE_REGISTERS | 150 DOUBLE_REGISTERS |
149 }; | 151 }; |
150 | 152 |
151 | 153 |
152 class LOperand: public ZoneObject { | |
153 public: | |
154 enum Kind { | |
155 INVALID, | |
156 UNALLOCATED, | |
157 CONSTANT_OPERAND, | |
158 STACK_SLOT, | |
159 DOUBLE_STACK_SLOT, | |
160 REGISTER, | |
161 DOUBLE_REGISTER, | |
162 ARGUMENT | |
163 }; | |
164 | |
165 LOperand() : value_(KindField::encode(INVALID)) { } | |
166 | |
167 Kind kind() const { return KindField::decode(value_); } | |
168 int index() const { return static_cast<int>(value_) >> kKindFieldWidth; } | |
169 bool IsConstantOperand() const { return kind() == CONSTANT_OPERAND; } | |
170 bool IsStackSlot() const { return kind() == STACK_SLOT; } | |
171 bool IsDoubleStackSlot() const { return kind() == DOUBLE_STACK_SLOT; } | |
172 bool IsRegister() const { return kind() == REGISTER; } | |
173 bool IsDoubleRegister() const { return kind() == DOUBLE_REGISTER; } | |
174 bool IsArgument() const { return kind() == ARGUMENT; } | |
175 bool IsUnallocated() const { return kind() == UNALLOCATED; } | |
176 bool Equals(LOperand* other) const { return value_ == other->value_; } | |
177 int VirtualRegister(); | |
178 | |
179 void PrintTo(StringStream* stream); | |
180 void ConvertTo(Kind kind, int index) { | |
181 value_ = KindField::encode(kind); | |
182 value_ |= index << kKindFieldWidth; | |
183 ASSERT(this->index() == index); | |
184 } | |
185 | |
186 protected: | |
187 static const int kKindFieldWidth = 3; | |
188 class KindField : public BitField<Kind, 0, kKindFieldWidth> { }; | |
189 | |
190 LOperand(Kind kind, int index) { ConvertTo(kind, index); } | |
191 | |
192 unsigned value_; | |
193 }; | |
194 | |
195 | |
196 class LUnallocated: public LOperand { | |
197 public: | |
198 enum Policy { | |
199 NONE, | |
200 ANY, | |
201 FIXED_REGISTER, | |
202 FIXED_DOUBLE_REGISTER, | |
203 FIXED_SLOT, | |
204 MUST_HAVE_REGISTER, | |
205 WRITABLE_REGISTER, | |
206 SAME_AS_FIRST_INPUT, | |
207 IGNORE | |
208 }; | |
209 | |
210 // Lifetime of operand inside the instruction. | |
211 enum Lifetime { | |
212 // USED_AT_START operand is guaranteed to be live only at | |
213 // instruction start. Register allocator is free to assign the same register | |
214 // to some other operand used inside instruction (i.e. temporary or | |
215 // output). | |
216 USED_AT_START, | |
217 | |
218 // USED_AT_END operand is treated as live until the end of | |
219 // instruction. This means that register allocator will not reuse it's | |
220 // register for any other operand inside instruction. | |
221 USED_AT_END | |
222 }; | |
223 | |
224 explicit LUnallocated(Policy policy) : LOperand(UNALLOCATED, 0) { | |
225 Initialize(policy, 0, USED_AT_END); | |
226 } | |
227 | |
228 LUnallocated(Policy policy, int fixed_index) : LOperand(UNALLOCATED, 0) { | |
229 Initialize(policy, fixed_index, USED_AT_END); | |
230 } | |
231 | |
232 LUnallocated(Policy policy, Lifetime lifetime) : LOperand(UNALLOCATED, 0) { | |
233 Initialize(policy, 0, lifetime); | |
234 } | |
235 | |
236 // The superclass has a KindField. Some policies have a signed fixed | |
237 // index in the upper bits. | |
238 static const int kPolicyWidth = 4; | |
239 static const int kLifetimeWidth = 1; | |
240 static const int kVirtualRegisterWidth = 17; | |
241 | |
242 static const int kPolicyShift = kKindFieldWidth; | |
243 static const int kLifetimeShift = kPolicyShift + kPolicyWidth; | |
244 static const int kVirtualRegisterShift = kLifetimeShift + kLifetimeWidth; | |
245 static const int kFixedIndexShift = | |
246 kVirtualRegisterShift + kVirtualRegisterWidth; | |
247 | |
248 class PolicyField : public BitField<Policy, kPolicyShift, kPolicyWidth> { }; | |
249 | |
250 class LifetimeField | |
251 : public BitField<Lifetime, kLifetimeShift, kLifetimeWidth> { | |
252 }; | |
253 | |
254 class VirtualRegisterField | |
255 : public BitField<unsigned, | |
256 kVirtualRegisterShift, | |
257 kVirtualRegisterWidth> { | |
258 }; | |
259 | |
260 static const int kMaxVirtualRegisters = 1 << (kVirtualRegisterWidth + 1); | |
261 static const int kMaxFixedIndices = 128; | |
262 | |
263 bool HasIgnorePolicy() const { return policy() == IGNORE; } | |
264 bool HasNoPolicy() const { return policy() == NONE; } | |
265 bool HasAnyPolicy() const { | |
266 return policy() == ANY; | |
267 } | |
268 bool HasFixedPolicy() const { | |
269 return policy() == FIXED_REGISTER || | |
270 policy() == FIXED_DOUBLE_REGISTER || | |
271 policy() == FIXED_SLOT; | |
272 } | |
273 bool HasRegisterPolicy() const { | |
274 return policy() == WRITABLE_REGISTER || policy() == MUST_HAVE_REGISTER; | |
275 } | |
276 bool HasSameAsInputPolicy() const { | |
277 return policy() == SAME_AS_FIRST_INPUT; | |
278 } | |
279 Policy policy() const { return PolicyField::decode(value_); } | |
280 void set_policy(Policy policy) { | |
281 value_ &= ~PolicyField::mask(); | |
282 value_ |= PolicyField::encode(policy); | |
283 } | |
284 int fixed_index() const { | |
285 return static_cast<int>(value_) >> kFixedIndexShift; | |
286 } | |
287 | |
288 unsigned virtual_register() const { | |
289 return VirtualRegisterField::decode(value_); | |
290 } | |
291 | |
292 void set_virtual_register(unsigned id) { | |
293 value_ &= ~VirtualRegisterField::mask(); | |
294 value_ |= VirtualRegisterField::encode(id); | |
295 } | |
296 | |
297 LUnallocated* CopyUnconstrained() { | |
298 LUnallocated* result = new LUnallocated(ANY); | |
299 result->set_virtual_register(virtual_register()); | |
300 return result; | |
301 } | |
302 | |
303 static LUnallocated* cast(LOperand* op) { | |
304 ASSERT(op->IsUnallocated()); | |
305 return reinterpret_cast<LUnallocated*>(op); | |
306 } | |
307 | |
308 bool IsUsedAtStart() { | |
309 return LifetimeField::decode(value_) == USED_AT_START; | |
310 } | |
311 | |
312 private: | |
313 void Initialize(Policy policy, int fixed_index, Lifetime lifetime) { | |
314 value_ |= PolicyField::encode(policy); | |
315 value_ |= LifetimeField::encode(lifetime); | |
316 value_ |= fixed_index << kFixedIndexShift; | |
317 ASSERT(this->fixed_index() == fixed_index); | |
318 } | |
319 }; | |
320 | |
321 | |
322 class LMoveOperands BASE_EMBEDDED { | |
323 public: | |
324 LMoveOperands(LOperand* source, LOperand* destination) | |
325 : source_(source), destination_(destination) { | |
326 } | |
327 | |
328 LOperand* source() const { return source_; } | |
329 void set_source(LOperand* operand) { source_ = operand; } | |
330 | |
331 LOperand* destination() const { return destination_; } | |
332 void set_destination(LOperand* operand) { destination_ = operand; } | |
333 | |
334 // The gap resolver marks moves as "in-progress" by clearing the | |
335 // destination (but not the source). | |
336 bool IsPending() const { | |
337 return destination_ == NULL && source_ != NULL; | |
338 } | |
339 | |
340 // True if this move a move into the given destination operand. | |
341 bool Blocks(LOperand* operand) const { | |
342 return !IsEliminated() && source()->Equals(operand); | |
343 } | |
344 | |
345 // A move is redundant if it's been eliminated, if its source and | |
346 // destination are the same, or if its destination is unneeded. | |
347 bool IsRedundant() const { | |
348 return IsEliminated() || source_->Equals(destination_) || IsIgnored(); | |
349 } | |
350 | |
351 bool IsIgnored() const { | |
352 return destination_ != NULL && | |
353 destination_->IsUnallocated() && | |
354 LUnallocated::cast(destination_)->HasIgnorePolicy(); | |
355 } | |
356 | |
357 // We clear both operands to indicate move that's been eliminated. | |
358 void Eliminate() { source_ = destination_ = NULL; } | |
359 bool IsEliminated() const { | |
360 ASSERT(source_ != NULL || destination_ == NULL); | |
361 return source_ == NULL; | |
362 } | |
363 | |
364 private: | |
365 LOperand* source_; | |
366 LOperand* destination_; | |
367 }; | |
368 | |
369 | |
370 class LConstantOperand: public LOperand { | |
371 public: | |
372 static LConstantOperand* Create(int index) { | |
373 ASSERT(index >= 0); | |
374 if (index < kNumCachedOperands) return &cache[index]; | |
375 return new LConstantOperand(index); | |
376 } | |
377 | |
378 static LConstantOperand* cast(LOperand* op) { | |
379 ASSERT(op->IsConstantOperand()); | |
380 return reinterpret_cast<LConstantOperand*>(op); | |
381 } | |
382 | |
383 static void SetupCache(); | |
384 | |
385 private: | |
386 static const int kNumCachedOperands = 128; | |
387 static LConstantOperand cache[]; | |
388 | |
389 LConstantOperand() : LOperand() { } | |
390 explicit LConstantOperand(int index) : LOperand(CONSTANT_OPERAND, index) { } | |
391 }; | |
392 | |
393 | |
394 class LArgument: public LOperand { | |
395 public: | |
396 explicit LArgument(int index) : LOperand(ARGUMENT, index) { } | |
397 | |
398 static LArgument* cast(LOperand* op) { | |
399 ASSERT(op->IsArgument()); | |
400 return reinterpret_cast<LArgument*>(op); | |
401 } | |
402 }; | |
403 | |
404 | |
405 class LStackSlot: public LOperand { | |
406 public: | |
407 static LStackSlot* Create(int index) { | |
408 ASSERT(index >= 0); | |
409 if (index < kNumCachedOperands) return &cache[index]; | |
410 return new LStackSlot(index); | |
411 } | |
412 | |
413 static LStackSlot* cast(LOperand* op) { | |
414 ASSERT(op->IsStackSlot()); | |
415 return reinterpret_cast<LStackSlot*>(op); | |
416 } | |
417 | |
418 static void SetupCache(); | |
419 | |
420 private: | |
421 static const int kNumCachedOperands = 128; | |
422 static LStackSlot cache[]; | |
423 | |
424 LStackSlot() : LOperand() { } | |
425 explicit LStackSlot(int index) : LOperand(STACK_SLOT, index) { } | |
426 }; | |
427 | |
428 | |
429 class LDoubleStackSlot: public LOperand { | |
430 public: | |
431 static LDoubleStackSlot* Create(int index) { | |
432 ASSERT(index >= 0); | |
433 if (index < kNumCachedOperands) return &cache[index]; | |
434 return new LDoubleStackSlot(index); | |
435 } | |
436 | |
437 static LDoubleStackSlot* cast(LOperand* op) { | |
438 ASSERT(op->IsStackSlot()); | |
439 return reinterpret_cast<LDoubleStackSlot*>(op); | |
440 } | |
441 | |
442 static void SetupCache(); | |
443 | |
444 private: | |
445 static const int kNumCachedOperands = 128; | |
446 static LDoubleStackSlot cache[]; | |
447 | |
448 LDoubleStackSlot() : LOperand() { } | |
449 explicit LDoubleStackSlot(int index) : LOperand(DOUBLE_STACK_SLOT, index) { } | |
450 }; | |
451 | |
452 | |
453 class LRegister: public LOperand { | |
454 public: | |
455 static LRegister* Create(int index) { | |
456 ASSERT(index >= 0); | |
457 if (index < kNumCachedOperands) return &cache[index]; | |
458 return new LRegister(index); | |
459 } | |
460 | |
461 static LRegister* cast(LOperand* op) { | |
462 ASSERT(op->IsRegister()); | |
463 return reinterpret_cast<LRegister*>(op); | |
464 } | |
465 | |
466 static void SetupCache(); | |
467 | |
468 private: | |
469 static const int kNumCachedOperands = 16; | |
470 static LRegister cache[]; | |
471 | |
472 LRegister() : LOperand() { } | |
473 explicit LRegister(int index) : LOperand(REGISTER, index) { } | |
474 }; | |
475 | |
476 | |
477 class LDoubleRegister: public LOperand { | |
478 public: | |
479 static LDoubleRegister* Create(int index) { | |
480 ASSERT(index >= 0); | |
481 if (index < kNumCachedOperands) return &cache[index]; | |
482 return new LDoubleRegister(index); | |
483 } | |
484 | |
485 static LDoubleRegister* cast(LOperand* op) { | |
486 ASSERT(op->IsDoubleRegister()); | |
487 return reinterpret_cast<LDoubleRegister*>(op); | |
488 } | |
489 | |
490 static void SetupCache(); | |
491 | |
492 private: | |
493 static const int kNumCachedOperands = 16; | |
494 static LDoubleRegister cache[]; | |
495 | |
496 LDoubleRegister() : LOperand() { } | |
497 explicit LDoubleRegister(int index) : LOperand(DOUBLE_REGISTER, index) { } | |
498 }; | |
499 | |
500 | |
501 // A register-allocator view of a Lithium instruction. It contains the id of | 154 // A register-allocator view of a Lithium instruction. It contains the id of |
502 // the output operand and a list of input operand uses. | 155 // the output operand and a list of input operand uses. |
503 class InstructionSummary: public ZoneObject { | 156 class InstructionSummary: public ZoneObject { |
504 public: | 157 public: |
505 InstructionSummary() | 158 InstructionSummary() |
506 : output_operand_(NULL), | 159 : output_operand_(NULL), |
507 input_count_(0), | 160 input_count_(0), |
508 operands_(4), | 161 operands_(4), |
509 is_call_(false), | 162 is_call_(false), |
510 is_save_doubles_(false) {} | 163 is_save_doubles_(false) {} |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
581 LifetimePosition start_; | 234 LifetimePosition start_; |
582 LifetimePosition end_; | 235 LifetimePosition end_; |
583 UseInterval* next_; | 236 UseInterval* next_; |
584 | 237 |
585 friend class LiveRange; // Assigns to start_. | 238 friend class LiveRange; // Assigns to start_. |
586 }; | 239 }; |
587 | 240 |
588 // Representation of a use position. | 241 // Representation of a use position. |
589 class UsePosition: public ZoneObject { | 242 class UsePosition: public ZoneObject { |
590 public: | 243 public: |
591 UsePosition(LifetimePosition pos, LOperand* operand) | 244 UsePosition(LifetimePosition pos, LOperand* operand); |
592 : operand_(operand), | |
593 hint_(NULL), | |
594 pos_(pos), | |
595 next_(NULL), | |
596 requires_reg_(false), | |
597 register_beneficial_(true) { | |
598 if (operand_ != NULL && operand_->IsUnallocated()) { | |
599 LUnallocated* unalloc = LUnallocated::cast(operand_); | |
600 requires_reg_ = unalloc->HasRegisterPolicy(); | |
601 register_beneficial_ = !unalloc->HasAnyPolicy(); | |
602 } | |
603 ASSERT(pos_.IsValid()); | |
604 } | |
605 | 245 |
606 LOperand* operand() const { return operand_; } | 246 LOperand* operand() const { return operand_; } |
607 bool HasOperand() const { return operand_ != NULL; } | 247 bool HasOperand() const { return operand_ != NULL; } |
608 | 248 |
609 LOperand* hint() const { return hint_; } | 249 LOperand* hint() const { return hint_; } |
610 void set_hint(LOperand* hint) { hint_ = hint; } | 250 void set_hint(LOperand* hint) { hint_ = hint; } |
611 bool HasHint() const { return hint_ != NULL && !hint_->IsUnallocated(); } | 251 bool HasHint() const; |
612 bool RequiresRegister() const; | 252 bool RequiresRegister() const; |
613 bool RegisterIsBeneficial() const; | 253 bool RegisterIsBeneficial() const; |
614 | 254 |
615 LifetimePosition pos() const { return pos_; } | 255 LifetimePosition pos() const { return pos_; } |
616 UsePosition* next() const { return next_; } | 256 UsePosition* next() const { return next_; } |
617 | 257 |
618 private: | 258 private: |
619 void set_next(UsePosition* next) { next_ = next; } | 259 void set_next(UsePosition* next) { next_ = next; } |
620 | 260 |
621 LOperand* operand_; | 261 LOperand* operand_; |
622 LOperand* hint_; | 262 LOperand* hint_; |
623 LifetimePosition pos_; | 263 LifetimePosition pos_; |
624 UsePosition* next_; | 264 UsePosition* next_; |
625 bool requires_reg_; | 265 bool requires_reg_; |
626 bool register_beneficial_; | 266 bool register_beneficial_; |
627 | 267 |
628 friend class LiveRange; | 268 friend class LiveRange; |
629 }; | 269 }; |
630 | 270 |
631 // Representation of SSA values' live ranges as a collection of (continuous) | 271 // Representation of SSA values' live ranges as a collection of (continuous) |
632 // intervals over the instruction ordering. | 272 // intervals over the instruction ordering. |
633 class LiveRange: public ZoneObject { | 273 class LiveRange: public ZoneObject { |
634 public: | 274 public: |
635 static const int kInvalidAssignment = 0x7fffffff; | 275 static const int kInvalidAssignment = 0x7fffffff; |
636 | 276 |
637 explicit LiveRange(int id) | 277 explicit LiveRange(int id); |
638 : id_(id), | |
639 spilled_(false), | |
640 assigned_register_(kInvalidAssignment), | |
641 assigned_register_kind_(NONE), | |
642 last_interval_(NULL), | |
643 first_interval_(NULL), | |
644 first_pos_(NULL), | |
645 parent_(NULL), | |
646 next_(NULL), | |
647 current_interval_(NULL), | |
648 last_processed_use_(NULL), | |
649 spill_start_index_(kMaxInt) { | |
650 spill_operand_ = new LUnallocated(LUnallocated::IGNORE); | |
651 } | |
652 | 278 |
653 UseInterval* first_interval() const { return first_interval_; } | 279 UseInterval* first_interval() const { return first_interval_; } |
654 UsePosition* first_pos() const { return first_pos_; } | 280 UsePosition* first_pos() const { return first_pos_; } |
655 LiveRange* parent() const { return parent_; } | 281 LiveRange* parent() const { return parent_; } |
656 LiveRange* TopLevel() { return (parent_ == NULL) ? this : parent_; } | 282 LiveRange* TopLevel() { return (parent_ == NULL) ? this : parent_; } |
657 LiveRange* next() const { return next_; } | 283 LiveRange* next() const { return next_; } |
658 bool IsChild() const { return parent() != NULL; } | 284 bool IsChild() const { return parent() != NULL; } |
659 bool IsParent() const { return parent() == NULL; } | 285 bool IsParent() const { return parent() == NULL; } |
660 int id() const { return id_; } | 286 int id() const { return id_; } |
661 bool IsFixed() const { return id_ < 0; } | 287 bool IsFixed() const { return id_ < 0; } |
662 bool IsEmpty() const { return first_interval() == NULL; } | 288 bool IsEmpty() const { return first_interval() == NULL; } |
663 LOperand* CreateAssignedOperand(); | 289 LOperand* CreateAssignedOperand(); |
664 int assigned_register() const { return assigned_register_; } | 290 int assigned_register() const { return assigned_register_; } |
665 int spill_start_index() const { return spill_start_index_; } | 291 int spill_start_index() const { return spill_start_index_; } |
666 void set_assigned_register(int reg, RegisterKind register_kind) { | 292 void set_assigned_register(int reg, RegisterKind register_kind); |
667 ASSERT(!HasRegisterAssigned() && !IsSpilled()); | 293 void MakeSpilled(); |
668 assigned_register_ = reg; | |
669 assigned_register_kind_ = register_kind; | |
670 ConvertOperands(); | |
671 } | |
672 void MakeSpilled() { | |
673 ASSERT(!IsSpilled()); | |
674 ASSERT(TopLevel()->HasAllocatedSpillOperand()); | |
675 spilled_ = true; | |
676 assigned_register_ = kInvalidAssignment; | |
677 ConvertOperands(); | |
678 } | |
679 | 294 |
680 // Returns use position in this live range that follows both start | 295 // Returns use position in this live range that follows both start |
681 // and last processed use position. | 296 // and last processed use position. |
682 // Modifies internal state of live range! | 297 // Modifies internal state of live range! |
683 UsePosition* NextUsePosition(LifetimePosition start); | 298 UsePosition* NextUsePosition(LifetimePosition start); |
684 | 299 |
685 // Returns use position for which register is required in this live | 300 // Returns use position for which register is required in this live |
686 // range and which follows both start and last processed use position | 301 // range and which follows both start and last processed use position |
687 // Modifies internal state of live range! | 302 // Modifies internal state of live range! |
688 UsePosition* NextRegisterPosition(LifetimePosition start); | 303 UsePosition* NextRegisterPosition(LifetimePosition start); |
(...skipping 28 matching lines...) Expand all Loading... |
717 LifetimePosition Start() const { | 332 LifetimePosition Start() const { |
718 ASSERT(!IsEmpty()); | 333 ASSERT(!IsEmpty()); |
719 return first_interval()->start(); | 334 return first_interval()->start(); |
720 } | 335 } |
721 | 336 |
722 LifetimePosition End() const { | 337 LifetimePosition End() const { |
723 ASSERT(!IsEmpty()); | 338 ASSERT(!IsEmpty()); |
724 return last_interval_->end(); | 339 return last_interval_->end(); |
725 } | 340 } |
726 | 341 |
727 bool HasAllocatedSpillOperand() const { | 342 bool HasAllocatedSpillOperand() const; |
728 return spill_operand_ != NULL && !spill_operand_->IsUnallocated(); | |
729 } | |
730 | |
731 LOperand* GetSpillOperand() const { return spill_operand_; } | 343 LOperand* GetSpillOperand() const { return spill_operand_; } |
732 void SetSpillOperand(LOperand* operand) { | 344 void SetSpillOperand(LOperand* operand); |
733 ASSERT(!operand->IsUnallocated()); | |
734 ASSERT(spill_operand_ != NULL); | |
735 ASSERT(spill_operand_->IsUnallocated()); | |
736 spill_operand_->ConvertTo(operand->kind(), operand->index()); | |
737 } | |
738 | 345 |
739 void SetSpillStartIndex(int start) { | 346 void SetSpillStartIndex(int start) { |
740 spill_start_index_ = Min(start, spill_start_index_); | 347 spill_start_index_ = Min(start, spill_start_index_); |
741 } | 348 } |
742 | 349 |
743 bool ShouldBeAllocatedBefore(const LiveRange* other) const; | 350 bool ShouldBeAllocatedBefore(const LiveRange* other) const; |
744 bool CanCover(LifetimePosition position) const; | 351 bool CanCover(LifetimePosition position) const; |
745 bool Covers(LifetimePosition position); | 352 bool Covers(LifetimePosition position); |
746 LifetimePosition FirstIntersection(LiveRange* other); | 353 LifetimePosition FirstIntersection(LiveRange* other); |
747 | 354 |
(...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1049 | 656 |
1050 bool has_osr_entry_; | 657 bool has_osr_entry_; |
1051 | 658 |
1052 DISALLOW_COPY_AND_ASSIGN(LAllocator); | 659 DISALLOW_COPY_AND_ASSIGN(LAllocator); |
1053 }; | 660 }; |
1054 | 661 |
1055 | 662 |
1056 } } // namespace v8::internal | 663 } } // namespace v8::internal |
1057 | 664 |
1058 #endif // V8_LITHIUM_ALLOCATOR_H_ | 665 #endif // V8_LITHIUM_ALLOCATOR_H_ |
OLD | NEW |