Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(80)

Side by Side Diff: src/lithium-allocator.h

Issue 6529032: Merge 6168:6800 from bleeding_edge to experimental/gc branch. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/gc/
Patch Set: Created 9 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/lithium.cc ('k') | src/lithium-allocator.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 13 matching lines...) Expand all
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 #ifndef V8_LITHIUM_ALLOCATOR_H_ 28 #ifndef V8_LITHIUM_ALLOCATOR_H_
29 #define V8_LITHIUM_ALLOCATOR_H_ 29 #define V8_LITHIUM_ALLOCATOR_H_
30 30
31 #include "v8.h" 31 #include "v8.h"
32 32
33 #include "data-flow.h" 33 #include "data-flow.h"
34 #include "lithium.h"
34 #include "zone.h" 35 #include "zone.h"
35 36
36 namespace v8 { 37 namespace v8 {
37 namespace internal { 38 namespace internal {
38 39
39 // Forward declarations. 40 // Forward declarations.
40 class HBasicBlock; 41 class HBasicBlock;
41 class HGraph; 42 class HGraph;
42 class HInstruction; 43 class HInstruction;
43 class HPhi; 44 class HPhi;
44 class HTracer; 45 class HTracer;
45 class HValue; 46 class HValue;
46 class BitVector; 47 class BitVector;
47 class StringStream; 48 class StringStream;
48 49
49 class LArgument; 50 class LArgument;
50 class LChunk; 51 class LChunk;
52 class LOperand;
53 class LUnallocated;
51 class LConstantOperand; 54 class LConstantOperand;
52 class LGap; 55 class LGap;
53 class LInstruction;
54 class LParallelMove; 56 class LParallelMove;
55 class LPointerMap; 57 class LPointerMap;
56 class LStackSlot; 58 class LStackSlot;
57 class LRegister; 59 class LRegister;
58 60
59 61
60 // This class represents a single point of a LOperand's lifetime. 62 // This class represents a single point of a LOperand's lifetime.
61 // For each lithium instruction there are exactly two lifetime positions: 63 // For each lithium instruction there are exactly two lifetime positions:
62 // the beginning and the end of the instruction. Lifetime positions for 64 // the beginning and the end of the instruction. Lifetime positions for
63 // different lithium instructions are disjoint. 65 // different lithium instructions are disjoint.
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
143 }; 145 };
144 146
145 147
146 enum RegisterKind { 148 enum RegisterKind {
147 NONE, 149 NONE,
148 GENERAL_REGISTERS, 150 GENERAL_REGISTERS,
149 DOUBLE_REGISTERS 151 DOUBLE_REGISTERS
150 }; 152 };
151 153
152 154
153 class LOperand: public ZoneObject {
154 public:
155 enum Kind {
156 INVALID,
157 UNALLOCATED,
158 CONSTANT_OPERAND,
159 STACK_SLOT,
160 DOUBLE_STACK_SLOT,
161 REGISTER,
162 DOUBLE_REGISTER,
163 ARGUMENT
164 };
165
166 LOperand() : value_(KindField::encode(INVALID)) { }
167
168 Kind kind() const { return KindField::decode(value_); }
169 int index() const { return static_cast<int>(value_) >> kKindFieldWidth; }
170 bool IsConstantOperand() const { return kind() == CONSTANT_OPERAND; }
171 bool IsStackSlot() const { return kind() == STACK_SLOT; }
172 bool IsDoubleStackSlot() const { return kind() == DOUBLE_STACK_SLOT; }
173 bool IsRegister() const { return kind() == REGISTER; }
174 bool IsDoubleRegister() const { return kind() == DOUBLE_REGISTER; }
175 bool IsArgument() const { return kind() == ARGUMENT; }
176 bool IsUnallocated() const { return kind() == UNALLOCATED; }
177 bool Equals(LOperand* other) const { return value_ == other->value_; }
178 int VirtualRegister();
179
180 void PrintTo(StringStream* stream);
181 void ConvertTo(Kind kind, int index) {
182 value_ = KindField::encode(kind);
183 value_ |= index << kKindFieldWidth;
184 ASSERT(this->index() == index);
185 }
186
187 protected:
188 static const int kKindFieldWidth = 3;
189 class KindField : public BitField<Kind, 0, kKindFieldWidth> { };
190
191 LOperand(Kind kind, int index) { ConvertTo(kind, index); }
192
193 unsigned value_;
194 };
195
196
197 class LUnallocated: public LOperand {
198 public:
199 enum Policy {
200 NONE,
201 ANY,
202 FIXED_REGISTER,
203 FIXED_DOUBLE_REGISTER,
204 FIXED_SLOT,
205 MUST_HAVE_REGISTER,
206 WRITABLE_REGISTER,
207 SAME_AS_FIRST_INPUT,
208 IGNORE
209 };
210
211 // Lifetime of operand inside the instruction.
212 enum Lifetime {
213 // USED_AT_START operand is guaranteed to be live only at
214 // instruction start. Register allocator is free to assign the same register
215 // to some other operand used inside instruction (i.e. temporary or
216 // output).
217 USED_AT_START,
218
219 // USED_AT_END operand is treated as live until the end of
220 // instruction. This means that register allocator will not reuse it's
221 // register for any other operand inside instruction.
222 USED_AT_END
223 };
224
225 explicit LUnallocated(Policy policy) : LOperand(UNALLOCATED, 0) {
226 Initialize(policy, 0, USED_AT_END);
227 }
228
229 LUnallocated(Policy policy, int fixed_index) : LOperand(UNALLOCATED, 0) {
230 Initialize(policy, fixed_index, USED_AT_END);
231 }
232
233 LUnallocated(Policy policy, Lifetime lifetime) : LOperand(UNALLOCATED, 0) {
234 Initialize(policy, 0, lifetime);
235 }
236
237 // The superclass has a KindField. Some policies have a signed fixed
238 // index in the upper bits.
239 static const int kPolicyWidth = 4;
240 static const int kLifetimeWidth = 1;
241 static const int kVirtualRegisterWidth = 17;
242
243 static const int kPolicyShift = kKindFieldWidth;
244 static const int kLifetimeShift = kPolicyShift + kPolicyWidth;
245 static const int kVirtualRegisterShift = kLifetimeShift + kLifetimeWidth;
246 static const int kFixedIndexShift =
247 kVirtualRegisterShift + kVirtualRegisterWidth;
248
249 class PolicyField : public BitField<Policy, kPolicyShift, kPolicyWidth> { };
250
251 class LifetimeField
252 : public BitField<Lifetime, kLifetimeShift, kLifetimeWidth> {
253 };
254
255 class VirtualRegisterField
256 : public BitField<unsigned,
257 kVirtualRegisterShift,
258 kVirtualRegisterWidth> {
259 };
260
261 static const int kMaxVirtualRegisters = 1 << (kVirtualRegisterWidth + 1);
262 static const int kMaxFixedIndices = 128;
263
264 bool HasIgnorePolicy() const { return policy() == IGNORE; }
265 bool HasNoPolicy() const { return policy() == NONE; }
266 bool HasAnyPolicy() const {
267 return policy() == ANY;
268 }
269 bool HasFixedPolicy() const {
270 return policy() == FIXED_REGISTER ||
271 policy() == FIXED_DOUBLE_REGISTER ||
272 policy() == FIXED_SLOT;
273 }
274 bool HasRegisterPolicy() const {
275 return policy() == WRITABLE_REGISTER || policy() == MUST_HAVE_REGISTER;
276 }
277 bool HasSameAsInputPolicy() const {
278 return policy() == SAME_AS_FIRST_INPUT;
279 }
280 Policy policy() const { return PolicyField::decode(value_); }
281 void set_policy(Policy policy) {
282 value_ &= ~PolicyField::mask();
283 value_ |= PolicyField::encode(policy);
284 }
285 int fixed_index() const {
286 return static_cast<int>(value_) >> kFixedIndexShift;
287 }
288
289 unsigned virtual_register() const {
290 return VirtualRegisterField::decode(value_);
291 }
292
293 void set_virtual_register(unsigned id) {
294 value_ &= ~VirtualRegisterField::mask();
295 value_ |= VirtualRegisterField::encode(id);
296 }
297
298 LUnallocated* CopyUnconstrained() {
299 LUnallocated* result = new LUnallocated(ANY);
300 result->set_virtual_register(virtual_register());
301 return result;
302 }
303
304 static LUnallocated* cast(LOperand* op) {
305 ASSERT(op->IsUnallocated());
306 return reinterpret_cast<LUnallocated*>(op);
307 }
308
309 bool IsUsedAtStart() {
310 return LifetimeField::decode(value_) == USED_AT_START;
311 }
312
313 private:
314 void Initialize(Policy policy, int fixed_index, Lifetime lifetime) {
315 value_ |= PolicyField::encode(policy);
316 value_ |= LifetimeField::encode(lifetime);
317 value_ |= fixed_index << kFixedIndexShift;
318 ASSERT(this->fixed_index() == fixed_index);
319 }
320 };
321
322
323 class LMoveOperands BASE_EMBEDDED {
324 public:
325 LMoveOperands(LOperand* from, LOperand* to) : from_(from), to_(to) { }
326
327 LOperand* from() const { return from_; }
328 LOperand* to() const { return to_; }
329 bool IsRedundant() const {
330 return IsEliminated() || from_->Equals(to_) || IsIgnored();
331 }
332 bool IsEliminated() const { return from_ == NULL; }
333 bool IsIgnored() const {
334 if (to_ != NULL && to_->IsUnallocated() &&
335 LUnallocated::cast(to_)->HasIgnorePolicy()) {
336 return true;
337 }
338 return false;
339 }
340
341 void Eliminate() { from_ = to_ = NULL; }
342
343 private:
344 LOperand* from_;
345 LOperand* to_;
346 };
347
348
349 class LConstantOperand: public LOperand {
350 public:
351 static LConstantOperand* Create(int index) {
352 ASSERT(index >= 0);
353 if (index < kNumCachedOperands) return &cache[index];
354 return new LConstantOperand(index);
355 }
356
357 static LConstantOperand* cast(LOperand* op) {
358 ASSERT(op->IsConstantOperand());
359 return reinterpret_cast<LConstantOperand*>(op);
360 }
361
362 static void SetupCache();
363
364 private:
365 static const int kNumCachedOperands = 128;
366 static LConstantOperand cache[];
367
368 LConstantOperand() : LOperand() { }
369 explicit LConstantOperand(int index) : LOperand(CONSTANT_OPERAND, index) { }
370 };
371
372
373 class LArgument: public LOperand {
374 public:
375 explicit LArgument(int index) : LOperand(ARGUMENT, index) { }
376
377 static LArgument* cast(LOperand* op) {
378 ASSERT(op->IsArgument());
379 return reinterpret_cast<LArgument*>(op);
380 }
381 };
382
383
384 class LStackSlot: public LOperand {
385 public:
386 static LStackSlot* Create(int index) {
387 ASSERT(index >= 0);
388 if (index < kNumCachedOperands) return &cache[index];
389 return new LStackSlot(index);
390 }
391
392 static LStackSlot* cast(LOperand* op) {
393 ASSERT(op->IsStackSlot());
394 return reinterpret_cast<LStackSlot*>(op);
395 }
396
397 static void SetupCache();
398
399 private:
400 static const int kNumCachedOperands = 128;
401 static LStackSlot cache[];
402
403 LStackSlot() : LOperand() { }
404 explicit LStackSlot(int index) : LOperand(STACK_SLOT, index) { }
405 };
406
407
408 class LDoubleStackSlot: public LOperand {
409 public:
410 static LDoubleStackSlot* Create(int index) {
411 ASSERT(index >= 0);
412 if (index < kNumCachedOperands) return &cache[index];
413 return new LDoubleStackSlot(index);
414 }
415
416 static LDoubleStackSlot* cast(LOperand* op) {
417 ASSERT(op->IsStackSlot());
418 return reinterpret_cast<LDoubleStackSlot*>(op);
419 }
420
421 static void SetupCache();
422
423 private:
424 static const int kNumCachedOperands = 128;
425 static LDoubleStackSlot cache[];
426
427 LDoubleStackSlot() : LOperand() { }
428 explicit LDoubleStackSlot(int index) : LOperand(DOUBLE_STACK_SLOT, index) { }
429 };
430
431
432 class LRegister: public LOperand {
433 public:
434 static LRegister* Create(int index) {
435 ASSERT(index >= 0);
436 if (index < kNumCachedOperands) return &cache[index];
437 return new LRegister(index);
438 }
439
440 static LRegister* cast(LOperand* op) {
441 ASSERT(op->IsRegister());
442 return reinterpret_cast<LRegister*>(op);
443 }
444
445 static void SetupCache();
446
447 private:
448 static const int kNumCachedOperands = 16;
449 static LRegister cache[];
450
451 LRegister() : LOperand() { }
452 explicit LRegister(int index) : LOperand(REGISTER, index) { }
453 };
454
455
456 class LDoubleRegister: public LOperand {
457 public:
458 static LDoubleRegister* Create(int index) {
459 ASSERT(index >= 0);
460 if (index < kNumCachedOperands) return &cache[index];
461 return new LDoubleRegister(index);
462 }
463
464 static LDoubleRegister* cast(LOperand* op) {
465 ASSERT(op->IsDoubleRegister());
466 return reinterpret_cast<LDoubleRegister*>(op);
467 }
468
469 static void SetupCache();
470
471 private:
472 static const int kNumCachedOperands = 16;
473 static LDoubleRegister cache[];
474
475 LDoubleRegister() : LOperand() { }
476 explicit LDoubleRegister(int index) : LOperand(DOUBLE_REGISTER, index) { }
477 };
478
479
480 // A register-allocator view of a Lithium instruction. It contains the id of 155 // A register-allocator view of a Lithium instruction. It contains the id of
481 // the output operand and a list of input operand uses. 156 // the output operand and a list of input operand uses.
482 class InstructionSummary: public ZoneObject { 157
158 class LInstruction;
159 class LEnvironment;
160
161 // Iterator for non-null temp operands.
162 class TempIterator BASE_EMBEDDED {
483 public: 163 public:
484 InstructionSummary() 164 inline explicit TempIterator(LInstruction* instr);
485 : output_operand_(NULL), input_count_(0), operands_(4), is_call_(false) {} 165 inline bool HasNext();
486 166 inline LOperand* Next();
487 // Output operands. 167 inline void Advance();
488 LOperand* Output() const { return output_operand_; }
489 void SetOutput(LOperand* output) {
490 ASSERT(output_operand_ == NULL);
491 output_operand_ = output;
492 }
493
494 // Input operands.
495 int InputCount() const { return input_count_; }
496 LOperand* InputAt(int i) const {
497 ASSERT(i < input_count_);
498 return operands_[i];
499 }
500 void AddInput(LOperand* input) {
501 operands_.InsertAt(input_count_, input);
502 input_count_++;
503 }
504
505 // Temporary operands.
506 int TempCount() const { return operands_.length() - input_count_; }
507 LOperand* TempAt(int i) const { return operands_[i + input_count_]; }
508 void AddTemp(LOperand* temp) { operands_.Add(temp); }
509
510 void MarkAsCall() { is_call_ = true; }
511 bool IsCall() const { return is_call_; }
512 168
513 private: 169 private:
514 LOperand* output_operand_; 170 inline int AdvanceToNext(int start);
515 int input_count_; 171 LInstruction* instr_;
516 ZoneList<LOperand*> operands_; 172 int limit_;
517 bool is_call_; 173 int current_;
518 }; 174 };
519 175
176
177 // Iterator for non-constant input operands.
178 class InputIterator BASE_EMBEDDED {
179 public:
180 inline explicit InputIterator(LInstruction* instr);
181 inline bool HasNext();
182 inline LOperand* Next();
183 inline void Advance();
184
185 private:
186 inline int AdvanceToNext(int start);
187 LInstruction* instr_;
188 int limit_;
189 int current_;
190 };
191
192
193 class UseIterator BASE_EMBEDDED {
194 public:
195 inline explicit UseIterator(LInstruction* instr);
196 inline bool HasNext();
197 inline LOperand* Next();
198 inline void Advance();
199
200 private:
201 InputIterator input_iterator_;
202 DeepIterator env_iterator_;
203 };
204
205
520 // Representation of the non-empty interval [start,end[. 206 // Representation of the non-empty interval [start,end[.
521 class UseInterval: public ZoneObject { 207 class UseInterval: public ZoneObject {
522 public: 208 public:
523 UseInterval(LifetimePosition start, LifetimePosition end) 209 UseInterval(LifetimePosition start, LifetimePosition end)
524 : start_(start), end_(end), next_(NULL) { 210 : start_(start), end_(end), next_(NULL) {
525 ASSERT(start.Value() < end.Value()); 211 ASSERT(start.Value() < end.Value());
526 } 212 }
527 213
528 LifetimePosition start() const { return start_; } 214 LifetimePosition start() const { return start_; }
529 LifetimePosition end() const { return end_; } 215 LifetimePosition end() const { return end_; }
(...skipping 22 matching lines...) Expand all
552 LifetimePosition start_; 238 LifetimePosition start_;
553 LifetimePosition end_; 239 LifetimePosition end_;
554 UseInterval* next_; 240 UseInterval* next_;
555 241
556 friend class LiveRange; // Assigns to start_. 242 friend class LiveRange; // Assigns to start_.
557 }; 243 };
558 244
559 // Representation of a use position. 245 // Representation of a use position.
560 class UsePosition: public ZoneObject { 246 class UsePosition: public ZoneObject {
561 public: 247 public:
562 UsePosition(LifetimePosition pos, LOperand* operand) 248 UsePosition(LifetimePosition pos, LOperand* operand);
563 : operand_(operand),
564 hint_(NULL),
565 pos_(pos),
566 next_(NULL),
567 requires_reg_(false),
568 register_beneficial_(true) {
569 if (operand_ != NULL && operand_->IsUnallocated()) {
570 LUnallocated* unalloc = LUnallocated::cast(operand_);
571 requires_reg_ = unalloc->HasRegisterPolicy();
572 register_beneficial_ = !unalloc->HasAnyPolicy();
573 }
574 ASSERT(pos_.IsValid());
575 }
576 249
577 LOperand* operand() const { return operand_; } 250 LOperand* operand() const { return operand_; }
578 bool HasOperand() const { return operand_ != NULL; } 251 bool HasOperand() const { return operand_ != NULL; }
579 252
580 LOperand* hint() const { return hint_; } 253 LOperand* hint() const { return hint_; }
581 void set_hint(LOperand* hint) { hint_ = hint; } 254 void set_hint(LOperand* hint) { hint_ = hint; }
582 bool HasHint() const { return hint_ != NULL && !hint_->IsUnallocated(); } 255 bool HasHint() const;
583 bool RequiresRegister() const; 256 bool RequiresRegister() const;
584 bool RegisterIsBeneficial() const; 257 bool RegisterIsBeneficial() const;
585 258
586 LifetimePosition pos() const { return pos_; } 259 LifetimePosition pos() const { return pos_; }
587 UsePosition* next() const { return next_; } 260 UsePosition* next() const { return next_; }
588 261
589 private: 262 private:
590 void set_next(UsePosition* next) { next_ = next; } 263 void set_next(UsePosition* next) { next_ = next; }
591 264
592 LOperand* operand_; 265 LOperand* operand_;
593 LOperand* hint_; 266 LOperand* hint_;
594 LifetimePosition pos_; 267 LifetimePosition pos_;
595 UsePosition* next_; 268 UsePosition* next_;
596 bool requires_reg_; 269 bool requires_reg_;
597 bool register_beneficial_; 270 bool register_beneficial_;
598 271
599 friend class LiveRange; 272 friend class LiveRange;
600 }; 273 };
601 274
602 // Representation of SSA values' live ranges as a collection of (continuous) 275 // Representation of SSA values' live ranges as a collection of (continuous)
603 // intervals over the instruction ordering. 276 // intervals over the instruction ordering.
604 class LiveRange: public ZoneObject { 277 class LiveRange: public ZoneObject {
605 public: 278 public:
606 static const int kInvalidAssignment = 0x7fffffff; 279 static const int kInvalidAssignment = 0x7fffffff;
607 280
608 explicit LiveRange(int id) 281 explicit LiveRange(int id);
609 : id_(id),
610 spilled_(false),
611 assigned_register_(kInvalidAssignment),
612 assigned_register_kind_(NONE),
613 last_interval_(NULL),
614 first_interval_(NULL),
615 first_pos_(NULL),
616 parent_(NULL),
617 next_(NULL),
618 current_interval_(NULL),
619 last_processed_use_(NULL),
620 spill_start_index_(kMaxInt) {
621 spill_operand_ = new LUnallocated(LUnallocated::IGNORE);
622 }
623 282
624 UseInterval* first_interval() const { return first_interval_; } 283 UseInterval* first_interval() const { return first_interval_; }
625 UsePosition* first_pos() const { return first_pos_; } 284 UsePosition* first_pos() const { return first_pos_; }
626 LiveRange* parent() const { return parent_; } 285 LiveRange* parent() const { return parent_; }
627 LiveRange* TopLevel() { return (parent_ == NULL) ? this : parent_; } 286 LiveRange* TopLevel() { return (parent_ == NULL) ? this : parent_; }
628 LiveRange* next() const { return next_; } 287 LiveRange* next() const { return next_; }
629 bool IsChild() const { return parent() != NULL; } 288 bool IsChild() const { return parent() != NULL; }
630 bool IsParent() const { return parent() == NULL; } 289 bool IsParent() const { return parent() == NULL; }
631 int id() const { return id_; } 290 int id() const { return id_; }
632 bool IsFixed() const { return id_ < 0; } 291 bool IsFixed() const { return id_ < 0; }
633 bool IsEmpty() const { return first_interval() == NULL; } 292 bool IsEmpty() const { return first_interval() == NULL; }
634 LOperand* CreateAssignedOperand(); 293 LOperand* CreateAssignedOperand();
635 int assigned_register() const { return assigned_register_; } 294 int assigned_register() const { return assigned_register_; }
636 int spill_start_index() const { return spill_start_index_; } 295 int spill_start_index() const { return spill_start_index_; }
637 void set_assigned_register(int reg, RegisterKind register_kind) { 296 void set_assigned_register(int reg, RegisterKind register_kind);
638 ASSERT(!HasRegisterAssigned() && !IsSpilled()); 297 void MakeSpilled();
639 assigned_register_ = reg;
640 assigned_register_kind_ = register_kind;
641 ConvertOperands();
642 }
643 void MakeSpilled() {
644 ASSERT(!IsSpilled());
645 ASSERT(TopLevel()->HasAllocatedSpillOperand());
646 spilled_ = true;
647 assigned_register_ = kInvalidAssignment;
648 ConvertOperands();
649 }
650 298
651 // Returns use position in this live range that follows both start 299 // Returns use position in this live range that follows both start
652 // and last processed use position. 300 // and last processed use position.
653 // Modifies internal state of live range! 301 // Modifies internal state of live range!
654 UsePosition* NextUsePosition(LifetimePosition start); 302 UsePosition* NextUsePosition(LifetimePosition start);
655 303
656 // Returns use position for which register is required in this live 304 // Returns use position for which register is required in this live
657 // range and which follows both start and last processed use position 305 // range and which follows both start and last processed use position
658 // Modifies internal state of live range! 306 // Modifies internal state of live range!
659 UsePosition* NextRegisterPosition(LifetimePosition start); 307 UsePosition* NextRegisterPosition(LifetimePosition start);
(...skipping 28 matching lines...) Expand all
688 LifetimePosition Start() const { 336 LifetimePosition Start() const {
689 ASSERT(!IsEmpty()); 337 ASSERT(!IsEmpty());
690 return first_interval()->start(); 338 return first_interval()->start();
691 } 339 }
692 340
693 LifetimePosition End() const { 341 LifetimePosition End() const {
694 ASSERT(!IsEmpty()); 342 ASSERT(!IsEmpty());
695 return last_interval_->end(); 343 return last_interval_->end();
696 } 344 }
697 345
698 bool HasAllocatedSpillOperand() const { 346 bool HasAllocatedSpillOperand() const;
699 return spill_operand_ != NULL && !spill_operand_->IsUnallocated();
700 }
701 LOperand* GetSpillOperand() const { return spill_operand_; } 347 LOperand* GetSpillOperand() const { return spill_operand_; }
702 void SetSpillOperand(LOperand* operand) { 348 void SetSpillOperand(LOperand* operand);
703 ASSERT(!operand->IsUnallocated());
704 ASSERT(spill_operand_ != NULL);
705 ASSERT(spill_operand_->IsUnallocated());
706 spill_operand_->ConvertTo(operand->kind(), operand->index());
707 }
708 349
709 void SetSpillStartIndex(int start) { 350 void SetSpillStartIndex(int start) {
710 spill_start_index_ = Min(start, spill_start_index_); 351 spill_start_index_ = Min(start, spill_start_index_);
711 } 352 }
712 353
713 bool ShouldBeAllocatedBefore(const LiveRange* other) const; 354 bool ShouldBeAllocatedBefore(const LiveRange* other) const;
714 bool CanCover(LifetimePosition position) const; 355 bool CanCover(LifetimePosition position) const;
715 bool Covers(LifetimePosition position); 356 bool Covers(LifetimePosition position);
716 LifetimePosition FirstIntersection(LiveRange* other); 357 LifetimePosition FirstIntersection(LiveRange* other);
717 358
718
719 // Add a new interval or a new use position to this live range. 359 // Add a new interval or a new use position to this live range.
720 void EnsureInterval(LifetimePosition start, LifetimePosition end); 360 void EnsureInterval(LifetimePosition start, LifetimePosition end);
721 void AddUseInterval(LifetimePosition start, LifetimePosition end); 361 void AddUseInterval(LifetimePosition start, LifetimePosition end);
722 UsePosition* AddUsePosition(LifetimePosition pos, LOperand* operand); 362 UsePosition* AddUsePosition(LifetimePosition pos, LOperand* operand);
723 UsePosition* AddUsePosition(LifetimePosition pos); 363 UsePosition* AddUsePosition(LifetimePosition pos);
724 364
725 // Shorten the most recently added interval by setting a new start. 365 // Shorten the most recently added interval by setting a new start.
726 void ShortenTo(LifetimePosition start); 366 void ShortenTo(LifetimePosition start);
727 367
728 #ifdef DEBUG 368 #ifdef DEBUG
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
785 } 425 }
786 426
787 BitVector* bits_; 427 BitVector* bits_;
788 }; 428 };
789 429
790 430
791 class LAllocator BASE_EMBEDDED { 431 class LAllocator BASE_EMBEDDED {
792 public: 432 public:
793 explicit LAllocator(int first_virtual_register, HGraph* graph) 433 explicit LAllocator(int first_virtual_register, HGraph* graph)
794 : chunk_(NULL), 434 : chunk_(NULL),
795 summaries_(0),
796 next_summary_(NULL),
797 summary_stack_(2),
798 live_in_sets_(0), 435 live_in_sets_(0),
799 live_ranges_(16), 436 live_ranges_(16),
800 fixed_live_ranges_(8), 437 fixed_live_ranges_(8),
801 fixed_double_live_ranges_(8), 438 fixed_double_live_ranges_(8),
802 unhandled_live_ranges_(8), 439 unhandled_live_ranges_(8),
803 active_live_ranges_(8), 440 active_live_ranges_(8),
804 inactive_live_ranges_(8), 441 inactive_live_ranges_(8),
805 reusable_slots_(8), 442 reusable_slots_(8),
806 next_virtual_register_(first_virtual_register), 443 next_virtual_register_(first_virtual_register),
807 first_artificial_register_(first_virtual_register), 444 first_artificial_register_(first_virtual_register),
808 mode_(NONE), 445 mode_(NONE),
809 num_registers_(-1), 446 num_registers_(-1),
810 graph_(graph), 447 graph_(graph),
811 has_osr_entry_(false) {} 448 has_osr_entry_(false) {}
812 449
813 static void Setup(); 450 static void Setup();
814 static void TraceAlloc(const char* msg, ...); 451 static void TraceAlloc(const char* msg, ...);
815 452
816 // Lithium translation support. 453 // Lithium translation support.
817 // Record a use of an input operand in the current instruction. 454 // Record a use of an input operand in the current instruction.
818 void RecordUse(HValue* value, LUnallocated* operand); 455 void RecordUse(HValue* value, LUnallocated* operand);
819 // Record the definition of the output operand. 456 // Record the definition of the output operand.
820 void RecordDefinition(HInstruction* instr, LUnallocated* operand); 457 void RecordDefinition(HInstruction* instr, LUnallocated* operand);
821 // Record a temporary operand. 458 // Record a temporary operand.
822 void RecordTemporary(LUnallocated* operand); 459 void RecordTemporary(LUnallocated* operand);
823 460
824 // Marks the current instruction as a call.
825 void MarkAsCall();
826
827 // Checks whether the value of a given virtual register is tagged. 461 // Checks whether the value of a given virtual register is tagged.
828 bool HasTaggedValue(int virtual_register) const; 462 bool HasTaggedValue(int virtual_register) const;
829 463
830 // Returns the register kind required by the given virtual register. 464 // Returns the register kind required by the given virtual register.
831 RegisterKind RequiredRegisterKind(int virtual_register) const; 465 RegisterKind RequiredRegisterKind(int virtual_register) const;
832 466
833 // Begin a new instruction.
834 void BeginInstruction();
835
836 // Summarize the current instruction.
837 void SummarizeInstruction(int index);
838
839 // Summarize the current instruction.
840 void OmitInstruction();
841
842 // Control max function size. 467 // Control max function size.
843 static int max_initial_value_ids(); 468 static int max_initial_value_ids();
844 469
845 void Allocate(LChunk* chunk); 470 void Allocate(LChunk* chunk);
846 471
847 const ZoneList<LiveRange*>* live_ranges() const { return &live_ranges_; } 472 const ZoneList<LiveRange*>* live_ranges() const { return &live_ranges_; }
848 const ZoneList<LiveRange*>* fixed_live_ranges() const { 473 const ZoneList<LiveRange*>* fixed_live_ranges() const {
849 return &fixed_live_ranges_; 474 return &fixed_live_ranges_;
850 } 475 }
851 const ZoneList<LiveRange*>* fixed_double_live_ranges() const { 476 const ZoneList<LiveRange*>* fixed_double_live_ranges() const {
(...skipping 27 matching lines...) Expand all
879 void AllocateRegisters(); 504 void AllocateRegisters();
880 bool CanEagerlyResolveControlFlow(HBasicBlock* block) const; 505 bool CanEagerlyResolveControlFlow(HBasicBlock* block) const;
881 inline bool SafePointsAreInOrder() const; 506 inline bool SafePointsAreInOrder() const;
882 507
883 // Liveness analysis support. 508 // Liveness analysis support.
884 void InitializeLivenessAnalysis(); 509 void InitializeLivenessAnalysis();
885 BitVector* ComputeLiveOut(HBasicBlock* block); 510 BitVector* ComputeLiveOut(HBasicBlock* block);
886 void AddInitialIntervals(HBasicBlock* block, BitVector* live_out); 511 void AddInitialIntervals(HBasicBlock* block, BitVector* live_out);
887 void ProcessInstructions(HBasicBlock* block, BitVector* live); 512 void ProcessInstructions(HBasicBlock* block, BitVector* live);
888 void MeetRegisterConstraints(HBasicBlock* block); 513 void MeetRegisterConstraints(HBasicBlock* block);
889 void MeetConstraintsBetween(InstructionSummary* first, 514 void MeetConstraintsBetween(LInstruction* first,
890 InstructionSummary* second, 515 LInstruction* second,
891 int gap_index); 516 int gap_index);
892 void ResolvePhis(HBasicBlock* block); 517 void ResolvePhis(HBasicBlock* block);
893 518
894 // Helper methods for building intervals. 519 // Helper methods for building intervals.
895 LOperand* AllocateFixed(LUnallocated* operand, int pos, bool is_tagged); 520 LOperand* AllocateFixed(LUnallocated* operand, int pos, bool is_tagged);
896 LiveRange* LiveRangeFor(LOperand* operand); 521 LiveRange* LiveRangeFor(LOperand* operand);
897 void Define(LifetimePosition position, LOperand* operand, LOperand* hint); 522 void Define(LifetimePosition position, LOperand* operand, LOperand* hint);
898 void Use(LifetimePosition block_start, 523 void Use(LifetimePosition block_start,
899 LifetimePosition position, 524 LifetimePosition position,
900 LOperand* operand, 525 LOperand* operand,
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
945 570
946 // Spill the given life range after position start and up to position end. 571 // Spill the given life range after position start and up to position end.
947 void SpillBetween(LiveRange* range, 572 void SpillBetween(LiveRange* range,
948 LifetimePosition start, 573 LifetimePosition start,
949 LifetimePosition end); 574 LifetimePosition end);
950 575
951 void SplitAndSpillIntersecting(LiveRange* range); 576 void SplitAndSpillIntersecting(LiveRange* range);
952 577
953 void Spill(LiveRange* range); 578 void Spill(LiveRange* range);
954 bool IsBlockBoundary(LifetimePosition pos); 579 bool IsBlockBoundary(LifetimePosition pos);
955 void AddGapMove(int pos, LiveRange* prev, LiveRange* next);
956 580
957 // Helper methods for resolving control flow. 581 // Helper methods for resolving control flow.
958 void ResolveControlFlow(LiveRange* range, 582 void ResolveControlFlow(LiveRange* range,
959 HBasicBlock* block, 583 HBasicBlock* block,
960 HBasicBlock* pred); 584 HBasicBlock* pred);
961 585
962 // Return parallel move that should be used to connect ranges split at the 586 // Return parallel move that should be used to connect ranges split at the
963 // given position. 587 // given position.
964 LParallelMove* GetConnectingParallelMove(LifetimePosition pos); 588 LParallelMove* GetConnectingParallelMove(LifetimePosition pos);
965 589
966 // Return the block which contains give lifetime position. 590 // Return the block which contains give lifetime position.
967 HBasicBlock* GetBlock(LifetimePosition pos); 591 HBasicBlock* GetBlock(LifetimePosition pos);
968 592
969 // Current active summary.
970 InstructionSummary* current_summary() const { return summary_stack_.last(); }
971
972 // Get summary for given instruction index.
973 InstructionSummary* GetSummary(int index) const { return summaries_[index]; }
974
975 // Helper methods for the fixed registers. 593 // Helper methods for the fixed registers.
976 int RegisterCount() const; 594 int RegisterCount() const;
977 static int FixedLiveRangeID(int index) { return -index - 1; } 595 static int FixedLiveRangeID(int index) { return -index - 1; }
978 static int FixedDoubleLiveRangeID(int index); 596 static int FixedDoubleLiveRangeID(int index);
979 LiveRange* FixedLiveRangeFor(int index); 597 LiveRange* FixedLiveRangeFor(int index);
980 LiveRange* FixedDoubleLiveRangeFor(int index); 598 LiveRange* FixedDoubleLiveRangeFor(int index);
981 LiveRange* LiveRangeFor(int index); 599 LiveRange* LiveRangeFor(int index);
982 HPhi* LookupPhi(LOperand* operand) const; 600 HPhi* LookupPhi(LOperand* operand) const;
983 LGap* GetLastGap(HBasicBlock* block) const; 601 LGap* GetLastGap(HBasicBlock* block);
984 602
985 const char* RegisterName(int allocation_index); 603 const char* RegisterName(int allocation_index);
986 604
605 inline bool IsGapAt(int index);
606
607 inline LInstruction* InstructionAt(int index);
608
609 inline LGap* GapAt(int index);
610
987 LChunk* chunk_; 611 LChunk* chunk_;
988 ZoneList<InstructionSummary*> summaries_;
989 InstructionSummary* next_summary_;
990
991 ZoneList<InstructionSummary*> summary_stack_;
992 612
993 // During liveness analysis keep a mapping from block id to live_in sets 613 // During liveness analysis keep a mapping from block id to live_in sets
994 // for blocks already analyzed. 614 // for blocks already analyzed.
995 ZoneList<BitVector*> live_in_sets_; 615 ZoneList<BitVector*> live_in_sets_;
996 616
997 // Liveness analysis results. 617 // Liveness analysis results.
998 ZoneList<LiveRange*> live_ranges_; 618 ZoneList<LiveRange*> live_ranges_;
999 619
1000 // Lists of live ranges 620 // Lists of live ranges
1001 ZoneList<LiveRange*> fixed_live_ranges_; 621 ZoneList<LiveRange*> fixed_live_ranges_;
(...skipping 15 matching lines...) Expand all
1017 637
1018 bool has_osr_entry_; 638 bool has_osr_entry_;
1019 639
1020 DISALLOW_COPY_AND_ASSIGN(LAllocator); 640 DISALLOW_COPY_AND_ASSIGN(LAllocator);
1021 }; 641 };
1022 642
1023 643
1024 } } // namespace v8::internal 644 } } // namespace v8::internal
1025 645
1026 #endif // V8_LITHIUM_ALLOCATOR_H_ 646 #endif // V8_LITHIUM_ALLOCATOR_H_
OLDNEW
« no previous file with comments | « src/lithium.cc ('k') | src/lithium-allocator.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698