| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 209 : start_(start), end_(end), next_(NULL) { | 209 : start_(start), end_(end), next_(NULL) { |
| 210 ASSERT(start.Value() < end.Value()); | 210 ASSERT(start.Value() < end.Value()); |
| 211 } | 211 } |
| 212 | 212 |
| 213 LifetimePosition start() const { return start_; } | 213 LifetimePosition start() const { return start_; } |
| 214 LifetimePosition end() const { return end_; } | 214 LifetimePosition end() const { return end_; } |
| 215 UseInterval* next() const { return next_; } | 215 UseInterval* next() const { return next_; } |
| 216 | 216 |
| 217 // Split this interval at the given position without effecting the | 217 // Split this interval at the given position without effecting the |
| 218 // live range that owns it. The interval must contain the position. | 218 // live range that owns it. The interval must contain the position. |
| 219 void SplitAt(LifetimePosition pos); | 219 void SplitAt(LifetimePosition pos, Zone* zone); |
| 220 | 220 |
| 221 // If this interval intersects with other return smallest position | 221 // If this interval intersects with other return smallest position |
| 222 // that belongs to both of them. | 222 // that belongs to both of them. |
| 223 LifetimePosition Intersect(const UseInterval* other) const { | 223 LifetimePosition Intersect(const UseInterval* other) const { |
| 224 if (other->start().Value() < start_.Value()) return other->Intersect(this); | 224 if (other->start().Value() < start_.Value()) return other->Intersect(this); |
| 225 if (other->start().Value() < end_.Value()) return other->start(); | 225 if (other->start().Value() < end_.Value()) return other->start(); |
| 226 return LifetimePosition::Invalid(); | 226 return LifetimePosition::Invalid(); |
| 227 } | 227 } |
| 228 | 228 |
| 229 bool Contains(LifetimePosition point) const { | 229 bool Contains(LifetimePosition point) const { |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 270 | 270 |
| 271 friend class LiveRange; | 271 friend class LiveRange; |
| 272 }; | 272 }; |
| 273 | 273 |
| 274 // Representation of SSA values' live ranges as a collection of (continuous) | 274 // Representation of SSA values' live ranges as a collection of (continuous) |
| 275 // intervals over the instruction ordering. | 275 // intervals over the instruction ordering. |
| 276 class LiveRange: public ZoneObject { | 276 class LiveRange: public ZoneObject { |
| 277 public: | 277 public: |
| 278 static const int kInvalidAssignment = 0x7fffffff; | 278 static const int kInvalidAssignment = 0x7fffffff; |
| 279 | 279 |
| 280 explicit LiveRange(int id); | 280 LiveRange(int id, Zone* zone); |
| 281 | 281 |
| 282 UseInterval* first_interval() const { return first_interval_; } | 282 UseInterval* first_interval() const { return first_interval_; } |
| 283 UsePosition* first_pos() const { return first_pos_; } | 283 UsePosition* first_pos() const { return first_pos_; } |
| 284 LiveRange* parent() const { return parent_; } | 284 LiveRange* parent() const { return parent_; } |
| 285 LiveRange* TopLevel() { return (parent_ == NULL) ? this : parent_; } | 285 LiveRange* TopLevel() { return (parent_ == NULL) ? this : parent_; } |
| 286 LiveRange* next() const { return next_; } | 286 LiveRange* next() const { return next_; } |
| 287 bool IsChild() const { return parent() != NULL; } | 287 bool IsChild() const { return parent() != NULL; } |
| 288 int id() const { return id_; } | 288 int id() const { return id_; } |
| 289 bool IsFixed() const { return id_ < 0; } | 289 bool IsFixed() const { return id_ < 0; } |
| 290 bool IsEmpty() const { return first_interval() == NULL; } | 290 bool IsEmpty() const { return first_interval() == NULL; } |
| 291 LOperand* CreateAssignedOperand(); | 291 LOperand* CreateAssignedOperand(Zone* zone); |
| 292 int assigned_register() const { return assigned_register_; } | 292 int assigned_register() const { return assigned_register_; } |
| 293 int spill_start_index() const { return spill_start_index_; } | 293 int spill_start_index() const { return spill_start_index_; } |
| 294 void set_assigned_register(int reg, RegisterKind register_kind); | 294 void set_assigned_register(int reg, |
| 295 void MakeSpilled(); | 295 RegisterKind register_kind, |
| 296 Zone* zone); |
| 297 void MakeSpilled(Zone* zone); |
| 296 | 298 |
| 297 // Returns use position in this live range that follows both start | 299 // Returns use position in this live range that follows both start |
| 298 // and last processed use position. | 300 // and last processed use position. |
| 299 // Modifies internal state of live range! | 301 // Modifies internal state of live range! |
| 300 UsePosition* NextUsePosition(LifetimePosition start); | 302 UsePosition* NextUsePosition(LifetimePosition start); |
| 301 | 303 |
| 302 // Returns use position for which register is required in this live | 304 // Returns use position for which register is required in this live |
| 303 // range and which follows both start and last processed use position | 305 // range and which follows both start and last processed use position |
| 304 // Modifies internal state of live range! | 306 // Modifies internal state of live range! |
| 305 UsePosition* NextRegisterPosition(LifetimePosition start); | 307 UsePosition* NextRegisterPosition(LifetimePosition start); |
| 306 | 308 |
| 307 // Returns use position for which register is beneficial in this live | 309 // Returns use position for which register is beneficial in this live |
| 308 // range and which follows both start and last processed use position | 310 // range and which follows both start and last processed use position |
| 309 // Modifies internal state of live range! | 311 // Modifies internal state of live range! |
| 310 UsePosition* NextUsePositionRegisterIsBeneficial(LifetimePosition start); | 312 UsePosition* NextUsePositionRegisterIsBeneficial(LifetimePosition start); |
| 311 | 313 |
| 312 // Can this live range be spilled at this position. | 314 // Can this live range be spilled at this position. |
| 313 bool CanBeSpilled(LifetimePosition pos); | 315 bool CanBeSpilled(LifetimePosition pos); |
| 314 | 316 |
| 315 // Split this live range at the given position which must follow the start of | 317 // Split this live range at the given position which must follow the start of |
| 316 // the range. | 318 // the range. |
| 317 // All uses following the given position will be moved from this | 319 // All uses following the given position will be moved from this |
| 318 // live range to the result live range. | 320 // live range to the result live range. |
| 319 void SplitAt(LifetimePosition position, LiveRange* result); | 321 void SplitAt(LifetimePosition position, LiveRange* result, Zone* zone); |
| 320 | 322 |
| 321 bool IsDouble() const { return is_double_; } | 323 bool IsDouble() const { return is_double_; } |
| 322 bool HasRegisterAssigned() const { | 324 bool HasRegisterAssigned() const { |
| 323 return assigned_register_ != kInvalidAssignment; | 325 return assigned_register_ != kInvalidAssignment; |
| 324 } | 326 } |
| 325 bool IsSpilled() const { return spilled_; } | 327 bool IsSpilled() const { return spilled_; } |
| 326 UsePosition* FirstPosWithHint() const; | 328 UsePosition* FirstPosWithHint() const; |
| 327 | 329 |
| 328 LOperand* FirstHint() const { | 330 LOperand* FirstHint() const { |
| 329 UsePosition* pos = FirstPosWithHint(); | 331 UsePosition* pos = FirstPosWithHint(); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 348 void SetSpillStartIndex(int start) { | 350 void SetSpillStartIndex(int start) { |
| 349 spill_start_index_ = Min(start, spill_start_index_); | 351 spill_start_index_ = Min(start, spill_start_index_); |
| 350 } | 352 } |
| 351 | 353 |
| 352 bool ShouldBeAllocatedBefore(const LiveRange* other) const; | 354 bool ShouldBeAllocatedBefore(const LiveRange* other) const; |
| 353 bool CanCover(LifetimePosition position) const; | 355 bool CanCover(LifetimePosition position) const; |
| 354 bool Covers(LifetimePosition position); | 356 bool Covers(LifetimePosition position); |
| 355 LifetimePosition FirstIntersection(LiveRange* other); | 357 LifetimePosition FirstIntersection(LiveRange* other); |
| 356 | 358 |
| 357 // 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. |
| 358 void EnsureInterval(LifetimePosition start, LifetimePosition end); | 360 void EnsureInterval(LifetimePosition start, |
| 359 void AddUseInterval(LifetimePosition start, LifetimePosition end); | 361 LifetimePosition end, |
| 360 UsePosition* AddUsePosition(LifetimePosition pos, LOperand* operand); | 362 Zone* zone); |
| 363 void AddUseInterval(LifetimePosition start, |
| 364 LifetimePosition end, |
| 365 Zone* zone); |
| 366 UsePosition* AddUsePosition(LifetimePosition pos, |
| 367 LOperand* operand, |
| 368 Zone* zone); |
| 361 | 369 |
| 362 // Shorten the most recently added interval by setting a new start. | 370 // Shorten the most recently added interval by setting a new start. |
| 363 void ShortenTo(LifetimePosition start); | 371 void ShortenTo(LifetimePosition start); |
| 364 | 372 |
| 365 #ifdef DEBUG | 373 #ifdef DEBUG |
| 366 // True if target overlaps an existing interval. | 374 // True if target overlaps an existing interval. |
| 367 bool HasOverlap(UseInterval* target) const; | 375 bool HasOverlap(UseInterval* target) const; |
| 368 void Verify() const; | 376 void Verify() const; |
| 369 #endif | 377 #endif |
| 370 | 378 |
| 371 private: | 379 private: |
| 372 void ConvertOperands(); | 380 void ConvertOperands(Zone* zone); |
| 373 UseInterval* FirstSearchIntervalForPosition(LifetimePosition position) const; | 381 UseInterval* FirstSearchIntervalForPosition(LifetimePosition position) const; |
| 374 void AdvanceLastProcessedMarker(UseInterval* to_start_of, | 382 void AdvanceLastProcessedMarker(UseInterval* to_start_of, |
| 375 LifetimePosition but_not_past) const; | 383 LifetimePosition but_not_past) const; |
| 376 | 384 |
| 377 int id_; | 385 int id_; |
| 378 bool spilled_; | 386 bool spilled_; |
| 379 bool is_double_; | 387 bool is_double_; |
| 380 int assigned_register_; | 388 int assigned_register_; |
| 381 UseInterval* last_interval_; | 389 UseInterval* last_interval_; |
| 382 UseInterval* first_interval_; | 390 UseInterval* first_interval_; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 393 | 401 |
| 394 class GrowableBitVector BASE_EMBEDDED { | 402 class GrowableBitVector BASE_EMBEDDED { |
| 395 public: | 403 public: |
| 396 GrowableBitVector() : bits_(NULL) { } | 404 GrowableBitVector() : bits_(NULL) { } |
| 397 | 405 |
| 398 bool Contains(int value) const { | 406 bool Contains(int value) const { |
| 399 if (!InBitsRange(value)) return false; | 407 if (!InBitsRange(value)) return false; |
| 400 return bits_->Contains(value); | 408 return bits_->Contains(value); |
| 401 } | 409 } |
| 402 | 410 |
| 403 void Add(int value) { | 411 void Add(int value, Zone* zone) { |
| 404 EnsureCapacity(value); | 412 EnsureCapacity(value, zone); |
| 405 bits_->Add(value); | 413 bits_->Add(value); |
| 406 } | 414 } |
| 407 | 415 |
| 408 private: | 416 private: |
| 409 static const int kInitialLength = 1024; | 417 static const int kInitialLength = 1024; |
| 410 | 418 |
| 411 bool InBitsRange(int value) const { | 419 bool InBitsRange(int value) const { |
| 412 return bits_ != NULL && bits_->length() > value; | 420 return bits_ != NULL && bits_->length() > value; |
| 413 } | 421 } |
| 414 | 422 |
| 415 void EnsureCapacity(int value) { | 423 void EnsureCapacity(int value, Zone* zone) { |
| 416 if (InBitsRange(value)) return; | 424 if (InBitsRange(value)) return; |
| 417 int new_length = bits_ == NULL ? kInitialLength : bits_->length(); | 425 int new_length = bits_ == NULL ? kInitialLength : bits_->length(); |
| 418 while (new_length <= value) new_length *= 2; | 426 while (new_length <= value) new_length *= 2; |
| 419 BitVector* new_bits = new BitVector(new_length); | 427 BitVector* new_bits = new(zone) BitVector(new_length); |
| 420 if (bits_ != NULL) new_bits->CopyFrom(*bits_); | 428 if (bits_ != NULL) new_bits->CopyFrom(*bits_); |
| 421 bits_ = new_bits; | 429 bits_ = new_bits; |
| 422 } | 430 } |
| 423 | 431 |
| 424 BitVector* bits_; | 432 BitVector* bits_; |
| 425 }; | 433 }; |
| 426 | 434 |
| 427 | 435 |
| 428 class LAllocator BASE_EMBEDDED { | 436 class LAllocator BASE_EMBEDDED { |
| 429 public: | 437 public: |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 580 LGap* GetLastGap(HBasicBlock* block); | 588 LGap* GetLastGap(HBasicBlock* block); |
| 581 | 589 |
| 582 const char* RegisterName(int allocation_index); | 590 const char* RegisterName(int allocation_index); |
| 583 | 591 |
| 584 inline bool IsGapAt(int index); | 592 inline bool IsGapAt(int index); |
| 585 | 593 |
| 586 inline LInstruction* InstructionAt(int index); | 594 inline LInstruction* InstructionAt(int index); |
| 587 | 595 |
| 588 inline LGap* GapAt(int index); | 596 inline LGap* GapAt(int index); |
| 589 | 597 |
| 598 Zone* zone_; |
| 599 |
| 590 LChunk* chunk_; | 600 LChunk* chunk_; |
| 591 | 601 |
| 592 // Indicates success or failure during register allocation. | |
| 593 bool allocation_ok_; | |
| 594 | |
| 595 // During liveness analysis keep a mapping from block id to live_in sets | 602 // During liveness analysis keep a mapping from block id to live_in sets |
| 596 // for blocks already analyzed. | 603 // for blocks already analyzed. |
| 597 ZoneList<BitVector*> live_in_sets_; | 604 ZoneList<BitVector*> live_in_sets_; |
| 598 | 605 |
| 599 // Liveness analysis results. | 606 // Liveness analysis results. |
| 600 ZoneList<LiveRange*> live_ranges_; | 607 ZoneList<LiveRange*> live_ranges_; |
| 601 | 608 |
| 602 // Lists of live ranges | 609 // Lists of live ranges |
| 603 EmbeddedVector<LiveRange*, Register::kNumAllocatableRegisters> | 610 EmbeddedVector<LiveRange*, Register::kNumAllocatableRegisters> |
| 604 fixed_live_ranges_; | 611 fixed_live_ranges_; |
| 605 EmbeddedVector<LiveRange*, DoubleRegister::kNumAllocatableRegisters> | 612 EmbeddedVector<LiveRange*, DoubleRegister::kNumAllocatableRegisters> |
| 606 fixed_double_live_ranges_; | 613 fixed_double_live_ranges_; |
| 607 ZoneList<LiveRange*> unhandled_live_ranges_; | 614 ZoneList<LiveRange*> unhandled_live_ranges_; |
| 608 ZoneList<LiveRange*> active_live_ranges_; | 615 ZoneList<LiveRange*> active_live_ranges_; |
| 609 ZoneList<LiveRange*> inactive_live_ranges_; | 616 ZoneList<LiveRange*> inactive_live_ranges_; |
| 610 ZoneList<LiveRange*> reusable_slots_; | 617 ZoneList<LiveRange*> reusable_slots_; |
| 611 | 618 |
| 612 // Next virtual register number to be assigned to temporaries. | 619 // Next virtual register number to be assigned to temporaries. |
| 613 int next_virtual_register_; | 620 int next_virtual_register_; |
| 614 int first_artificial_register_; | 621 int first_artificial_register_; |
| 615 GrowableBitVector double_artificial_registers_; | 622 GrowableBitVector double_artificial_registers_; |
| 616 | 623 |
| 617 RegisterKind mode_; | 624 RegisterKind mode_; |
| 618 int num_registers_; | 625 int num_registers_; |
| 619 | 626 |
| 620 HGraph* graph_; | 627 HGraph* graph_; |
| 621 | 628 |
| 622 bool has_osr_entry_; | 629 bool has_osr_entry_; |
| 623 | 630 |
| 631 // Indicates success or failure during register allocation. |
| 632 bool allocation_ok_; |
| 633 |
| 624 DISALLOW_COPY_AND_ASSIGN(LAllocator); | 634 DISALLOW_COPY_AND_ASSIGN(LAllocator); |
| 625 }; | 635 }; |
| 626 | 636 |
| 627 | 637 |
| 628 } } // namespace v8::internal | 638 } } // namespace v8::internal |
| 629 | 639 |
| 630 #endif // V8_LITHIUM_ALLOCATOR_H_ | 640 #endif // V8_LITHIUM_ALLOCATOR_H_ |
| OLD | NEW |