Flutter Engine
The Flutter Engine
Public Member Functions | List of all members
dart::LiveRange Class Reference

#include <linearscan.h>

Inheritance diagram for dart::LiveRange:
dart::ZoneAllocated

Public Member Functions

 LiveRange (intptr_t vreg, Representation rep)
 
intptr_t vreg () const
 
Representation representation () const
 
LiveRangenext_sibling () const
 
UsePositionfirst_use () const
 
void set_first_use (UsePosition *use)
 
UseIntervalfirst_use_interval () const
 
UseIntervallast_use_interval () const
 
Location assigned_location () const
 
Locationassigned_location_slot ()
 
intptr_t Start () const
 
intptr_t End () const
 
SafepointPositionfirst_safepoint () const
 
AllocationFingerfinger ()
 
void set_assigned_location (Location location)
 
void set_spill_slot (Location spill_slot)
 
void DefineAt (intptr_t pos)
 
void AddSafepoint (intptr_t pos, LocationSummary *locs)
 
UsePositionAddUse (intptr_t pos, Location *location_slot)
 
void AddHintedUse (intptr_t pos, Location *location_slot, Location *hint)
 
void AddUseInterval (intptr_t start, intptr_t end)
 
void Print ()
 
LiveRangeSplitAt (intptr_t pos)
 
bool CanCover (intptr_t pos) const
 
bool Contains (intptr_t pos) const
 
Location spill_slot () const
 
bool HasOnlyUnconstrainedUsesInLoop (intptr_t loop_id) const
 
void MarkHasOnlyUnconstrainedUsesInLoop (intptr_t loop_id)
 
bool is_loop_phi () const
 
void mark_loop_phi ()
 
void mark_has_uses_which_require_stack ()
 
bool has_uses_which_require_stack () const
 
- Public Member Functions inherited from dart::ZoneAllocated
 ZoneAllocated ()
 
void * operator new (size_t size)
 
void * operator new (size_t size, Zone *zone)
 
void operator delete (void *pointer)
 

Detailed Description

Definition at line 512 of file linearscan.h.

Constructor & Destructor Documentation

◆ LiveRange()

dart::LiveRange::LiveRange ( intptr_t  vreg,
Representation  rep 
)
inlineexplicit

Definition at line 514 of file linearscan.h.

515 : vreg_(vreg),
516 representation_(rep),
517 assigned_location_(),
518 spill_slot_(),
519 uses_(nullptr),
520 first_use_interval_(nullptr),
521 last_use_interval_(nullptr),
522 first_safepoint_(nullptr),
523 last_safepoint_(nullptr),
524 next_sibling_(nullptr),
525 has_only_any_uses_in_loops_(0),
526 is_loop_phi_(false),
527 finger_() {}
intptr_t vreg() const
Definition: linearscan.h:529

Member Function Documentation

◆ AddHintedUse()

void dart::LiveRange::AddHintedUse ( intptr_t  pos,
Location location_slot,
Location hint 
)

Definition at line 368 of file linearscan.cc.

370 {
371 ASSERT(hint != nullptr);
372 AddUse(pos, location_slot)->set_hint(hint);
373}
SkPoint pos
UsePosition * AddUse(intptr_t pos, Location *location_slot)
Definition: linearscan.cc:305
void set_hint(Location *hint)
Definition: linearscan.h:406
#define ASSERT(E)

◆ AddSafepoint()

void dart::LiveRange::AddSafepoint ( intptr_t  pos,
LocationSummary locs 
)

Definition at line 340 of file linearscan.cc.

340 {
341 if (spill_slot().IsConstant() &&
342 (locs->always_calls() && !locs->callee_safe_call())) {
343 // Constants have pseudo spill slot assigned to them from
344 // the very beginning. This means that we don't need to associate
345 // "always_calls" safepoints with these ranges, because they will never
346 // be spilled. We still need to associate slow-path safepoints because
347 // a value might be allocated to a register across a slow-path call.
348 return;
349 }
350
352 SafepointPosition* safepoint =
353 new SafepointPosition(ToInstructionEnd(pos), locs);
354
355 if (first_safepoint_ == nullptr) {
356 ASSERT(last_safepoint_ == nullptr);
357 first_safepoint_ = last_safepoint_ = safepoint;
358 } else {
359 ASSERT(last_safepoint_ != nullptr);
360 // We assume that safepoints list is sorted by position and that
361 // safepoints are added in this order.
362 ASSERT(last_safepoint_->pos() < pos);
363 last_safepoint_->set_next(safepoint);
364 last_safepoint_ = safepoint;
365 }
366}
Location spill_slot() const
Definition: linearscan.h:574
void set_next(SafepointPosition *next)
Definition: linearscan.h:497
intptr_t pos() const
Definition: linearscan.h:500
static intptr_t ToInstructionEnd(intptr_t pos)
Definition: linearscan.cc:54
static bool IsInstructionStartPosition(intptr_t pos)
Definition: linearscan.cc:42
static bool IsConstant(Definition *def, int64_t *val)
Definition: loops.cc:123

◆ AddUse()

UsePosition * dart::LiveRange::AddUse ( intptr_t  pos,
Location location_slot 
)

Definition at line 305 of file linearscan.cc.

305 {
306 ASSERT(location_slot != nullptr);
307 ASSERT((first_use_interval_->start_ <= pos) &&
308 (pos <= first_use_interval_->end_));
309 if (uses_ != nullptr) {
310 if ((uses_->pos() == pos) && (uses_->location_slot() == location_slot)) {
311 return uses_;
312 } else if (uses_->pos() < pos) {
313 // If an instruction at position P is using the same value both as
314 // a fixed register input and a non-fixed input (in this order) we will
315 // add uses both at position P-1 and *then* P which will make
316 // uses_ unsorted unless we account for it here.
317 UsePosition* insert_after = uses_;
318 while ((insert_after->next() != nullptr) &&
319 (insert_after->next()->pos() < pos)) {
320 insert_after = insert_after->next();
321 }
322
323 UsePosition* insert_before = insert_after->next();
324 while (insert_before != nullptr && (insert_before->pos() == pos)) {
325 if (insert_before->location_slot() == location_slot) {
326 return insert_before;
327 }
328 insert_before = insert_before->next();
329 }
330
331 insert_after->set_next(
332 new UsePosition(pos, insert_after->next(), location_slot));
333 return insert_after->next();
334 }
335 }
336 uses_ = new UsePosition(pos, uses_, location_slot);
337 return uses_;
338}
void set_next(UsePosition *next)
Definition: linearscan.h:410
Location * location_slot() const
Definition: linearscan.h:396
intptr_t pos() const
Definition: linearscan.h:413
UsePosition * next() const
Definition: linearscan.h:411

◆ AddUseInterval()

void dart::LiveRange::AddUseInterval ( intptr_t  start,
intptr_t  end 
)

Definition at line 375 of file linearscan.cc.

375 {
376 ASSERT(start < end);
377
378 // Live ranges are being build by visiting instructions in post-order.
379 // This implies that use intervals will be prepended in a monotonically
380 // decreasing order.
381 if (first_use_interval() != nullptr) {
382 // If the first use interval and the use interval we are adding
383 // touch then we can just extend the first interval to cover their
384 // union.
385 if (start > first_use_interval()->start()) {
386 // The only case when we can add intervals with start greater than
387 // start of an already created interval is BlockLocation.
389 ASSERT(end <= first_use_interval()->end());
390 return;
391 } else if (start == first_use_interval()->start()) {
392 // Grow first interval if necessary.
393 if (end <= first_use_interval()->end()) return;
394 first_use_interval_->end_ = end;
395 return;
396 } else if (end == first_use_interval()->start()) {
397 first_use_interval()->start_ = start;
398 return;
399 }
400
401 ASSERT(end < first_use_interval()->start());
402 }
403
404 first_use_interval_ = new UseInterval(start, end, first_use_interval_);
405 if (last_use_interval_ == nullptr) {
406 ASSERT(first_use_interval_->next() == nullptr);
407 last_use_interval_ = first_use_interval_;
408 }
409}
UseInterval * first_use_interval() const
Definition: linearscan.h:534
UseInterval * next() const
Definition: linearscan.h:440
glong glong end
static constexpr intptr_t kNoVirtualRegister
Definition: linearscan.cc:33

◆ assigned_location()

Location dart::LiveRange::assigned_location ( ) const
inline

Definition at line 536 of file linearscan.h.

536{ return assigned_location_; }

◆ assigned_location_slot()

Location * dart::LiveRange::assigned_location_slot ( )
inline

Definition at line 537 of file linearscan.h.

537{ return &assigned_location_; }

◆ CanCover()

bool dart::LiveRange::CanCover ( intptr_t  pos) const
inline

Definition at line 567 of file linearscan.h.

567 {
568 return (Start() <= pos) && (pos < End());
569 }
intptr_t End() const
Definition: linearscan.h:539
intptr_t Start() const
Definition: linearscan.h:538

◆ Contains()

bool dart::LiveRange::Contains ( intptr_t  pos) const

Definition at line 2777 of file linearscan.cc.

2777 {
2778 if (!CanCover(pos)) return false;
2779
2780 for (UseInterval* interval = first_use_interval_; interval != nullptr;
2781 interval = interval->next()) {
2782 if (interval->Contains(pos)) {
2783 return true;
2784 }
2785 }
2786
2787 return false;
2788}
bool CanCover(intptr_t pos) const
Definition: linearscan.h:567

◆ DefineAt()

void dart::LiveRange::DefineAt ( intptr_t  pos)

Definition at line 411 of file linearscan.cc.

411 {
412 // Live ranges are being build by visiting instructions in post-order.
413 // This implies that use intervals will be prepended in a monotonically
414 // decreasing order.
415 // When we encounter a use of a value inside a block we optimistically
416 // expand the first use interval to cover the block from the start
417 // to the last use in the block and then we shrink it if we encounter
418 // definition of the value inside the same block.
419 if (first_use_interval_ == nullptr) {
420 // Definition without a use.
421 first_use_interval_ = new UseInterval(pos, pos + 1, nullptr);
422 last_use_interval_ = first_use_interval_;
423 } else {
424 // Shrink the first use interval. It was optimistically expanded to
425 // cover the block from the start to the last use in the block.
426 ASSERT(first_use_interval_->start_ <= pos);
427 first_use_interval_->start_ = pos;
428 }
429}

◆ End()

intptr_t dart::LiveRange::End ( ) const
inline

Definition at line 539 of file linearscan.h.

539{ return last_use_interval()->end(); }
UseInterval * last_use_interval() const
Definition: linearscan.h:535
intptr_t end() const
Definition: linearscan.h:439

◆ finger()

AllocationFinger * dart::LiveRange::finger ( )
inline

Definition at line 543 of file linearscan.h.

543{ return &finger_; }

◆ first_safepoint()

SafepointPosition * dart::LiveRange::first_safepoint ( ) const
inline

Definition at line 541 of file linearscan.h.

541{ return first_safepoint_; }

◆ first_use()

UsePosition * dart::LiveRange::first_use ( ) const
inline

Definition at line 532 of file linearscan.h.

532{ return uses_; }

◆ first_use_interval()

UseInterval * dart::LiveRange::first_use_interval ( ) const
inline

Definition at line 534 of file linearscan.h.

534{ return first_use_interval_; }

◆ has_uses_which_require_stack()

bool dart::LiveRange::has_uses_which_require_stack ( ) const
inline

Definition at line 596 of file linearscan.h.

596 {
597 return has_uses_which_require_stack_;
598 }

◆ HasOnlyUnconstrainedUsesInLoop()

bool dart::LiveRange::HasOnlyUnconstrainedUsesInLoop ( intptr_t  loop_id) const
inline

Definition at line 576 of file linearscan.h.

576 {
577 if (loop_id < kMaxLoops) {
578 const uint64_t mask = static_cast<uint64_t>(1) << loop_id;
579 return (has_only_any_uses_in_loops_ & mask) != 0;
580 }
581 return false;
582 }

◆ is_loop_phi()

bool dart::LiveRange::is_loop_phi ( ) const
inline

Definition at line 590 of file linearscan.h.

590{ return is_loop_phi_; }

◆ last_use_interval()

UseInterval * dart::LiveRange::last_use_interval ( ) const
inline

Definition at line 535 of file linearscan.h.

535{ return last_use_interval_; }

◆ mark_has_uses_which_require_stack()

void dart::LiveRange::mark_has_uses_which_require_stack ( )
inline

Definition at line 593 of file linearscan.h.

593 {
594 has_uses_which_require_stack_ = true;
595 }

◆ mark_loop_phi()

void dart::LiveRange::mark_loop_phi ( )
inline

Definition at line 591 of file linearscan.h.

591{ is_loop_phi_ = true; }

◆ MarkHasOnlyUnconstrainedUsesInLoop()

void dart::LiveRange::MarkHasOnlyUnconstrainedUsesInLoop ( intptr_t  loop_id)
inline

Definition at line 584 of file linearscan.h.

584 {
585 if (loop_id < kMaxLoops) {
586 has_only_any_uses_in_loops_ |= static_cast<uint64_t>(1) << loop_id;
587 }
588 }

◆ next_sibling()

LiveRange * dart::LiveRange::next_sibling ( ) const
inline

Definition at line 531 of file linearscan.h.

531{ return next_sibling_; }

◆ Print()

void dart::LiveRange::Print ( )

Definition at line 507 of file linearscan.cc.

507 {
508 if (first_use_interval() == nullptr) {
509 return;
510 }
511
512 THR_Print(" live range v%" Pd " [%" Pd ", %" Pd ") in ", vreg(), Start(),
513 End());
516 THR_Print(" %s", assigned_location().constant().ToCString());
517 }
518 if (!spill_slot_.IsInvalid() && !spill_slot_.IsConstant()) {
519 THR_Print(" assigned spill slot: %s", spill_slot_.ToCString());
520 }
521 THR_Print("\n");
522
523 SafepointPosition* safepoint = first_safepoint();
524 while (safepoint != nullptr) {
525 THR_Print(" Safepoint [%" Pd "]: ", safepoint->pos());
526 safepoint->locs()->stack_bitmap().Print();
527 THR_Print("\n");
528 safepoint = safepoint->next();
529 }
530
531 UsePosition* use_pos = uses_;
532 for (UseInterval* interval = first_use_interval_; interval != nullptr;
533 interval = interval->next()) {
534 THR_Print(" use interval [%" Pd ", %" Pd ")\n", interval->start(),
535 interval->end());
536 while ((use_pos != nullptr) && (use_pos->pos() <= interval->end())) {
537 THR_Print(" use at %" Pd "", use_pos->pos());
538 if (use_pos->location_slot() != nullptr) {
539 THR_Print(" as ");
540 use_pos->location_slot()->Print();
541 }
542 THR_Print("\n");
543 use_pos = use_pos->next();
544 }
545 }
546
547 if (next_sibling() != nullptr) {
548 next_sibling()->Print();
549 }
550}
Location assigned_location() const
Definition: linearscan.h:536
LiveRange * next_sibling() const
Definition: linearscan.h:531
SafepointPosition * first_safepoint() const
Definition: linearscan.h:541
bool IsInvalid() const
Definition: locations.h:289
void Print() const
Definition: locations.cc:452
const char * ToCString() const
Definition: locations.cc:445
bool IsConstant() const
Definition: locations.h:292
#define THR_Print(format,...)
Definition: log.h:20
#define Pd
Definition: globals.h:408

◆ representation()

Representation dart::LiveRange::representation ( ) const
inline

Definition at line 530 of file linearscan.h.

530{ return representation_; }

◆ set_assigned_location()

void dart::LiveRange::set_assigned_location ( Location  location)
inline

Definition at line 545 of file linearscan.h.

545 {
546 assigned_location_ = location;
547 }

◆ set_first_use()

void dart::LiveRange::set_first_use ( UsePosition use)
inline

Definition at line 533 of file linearscan.h.

533{ uses_ = use; }

◆ set_spill_slot()

void dart::LiveRange::set_spill_slot ( Location  spill_slot)
inline

Definition at line 549 of file linearscan.h.

549{ spill_slot_ = spill_slot; }

◆ spill_slot()

Location dart::LiveRange::spill_slot ( ) const
inline

Definition at line 574 of file linearscan.h.

574{ return spill_slot_; }

◆ SplitAt()

LiveRange * dart::LiveRange::SplitAt ( intptr_t  pos)

Definition at line 1895 of file linearscan.cc.

1895 {
1896 if (Start() == split_pos) return this;
1897
1898 UseInterval* interval = finger_.first_pending_use_interval();
1899 if (interval == nullptr) {
1900 finger_.Initialize(this);
1901 interval = finger_.first_pending_use_interval();
1902 }
1903
1904 ASSERT(split_pos < End());
1905
1906 // Corner case. Split position can be inside the a lifetime hole or at its
1907 // end. We need to start over to find the previous interval.
1908 if (split_pos <= interval->start()) interval = first_use_interval_;
1909
1910 UseInterval* last_before_split = nullptr;
1911 while (interval->end() <= split_pos) {
1912 last_before_split = interval;
1913 interval = interval->next();
1914 }
1915
1916 const bool split_at_start = (interval->start() == split_pos);
1917
1918 UseInterval* first_after_split = interval;
1919 if (!split_at_start && interval->Contains(split_pos)) {
1920 first_after_split =
1921 new UseInterval(split_pos, interval->end(), interval->next());
1922 interval->end_ = split_pos;
1923 interval->next_ = first_after_split;
1924 last_before_split = interval;
1925 }
1926
1927 ASSERT(last_before_split != nullptr);
1928 ASSERT(last_before_split->next() == first_after_split);
1929 ASSERT(last_before_split->end() <= split_pos);
1930 ASSERT(split_pos <= first_after_split->start());
1931
1932 UsePosition* first_use_after_split =
1933 SplitListOfPositions(&uses_, split_pos, split_at_start);
1934
1935 SafepointPosition* first_safepoint_after_split =
1936 SplitListOfPositions(&first_safepoint_, split_pos, split_at_start);
1937
1938 UseInterval* last_use_interval = (last_before_split == last_use_interval_)
1939 ? first_after_split
1940 : last_use_interval_;
1941 next_sibling_ = new LiveRange(vreg(), representation(), first_use_after_split,
1942 first_after_split, last_use_interval,
1943 first_safepoint_after_split, next_sibling_);
1944
1945 TRACE_ALLOC(THR_Print(" split sibling [%" Pd ", %" Pd ")\n",
1946 next_sibling_->Start(), next_sibling_->End()));
1947
1948 last_use_interval_ = last_before_split;
1949 last_use_interval_->next_ = nullptr;
1950
1951 if (first_use_after_split != nullptr) {
1952 finger_.UpdateAfterSplit(first_use_after_split->pos());
1953 }
1954
1955 return next_sibling_;
1956}
void Initialize(LiveRange *range)
Definition: linearscan.cc:1764
void UpdateAfterSplit(intptr_t first_use_after_split_pos)
Definition: linearscan.cc:1832
UseInterval * first_pending_use_interval() const
Definition: linearscan.h:474
Representation representation() const
Definition: linearscan.h:530
LiveRange(intptr_t vreg, Representation rep)
Definition: linearscan.h:514
#define TRACE_ALLOC(statement)
Definition: linearscan.cc:25
PositionType * SplitListOfPositions(PositionType **head, intptr_t split_pos, bool split_at_start)
Definition: linearscan.cc:1869

◆ Start()

intptr_t dart::LiveRange::Start ( ) const
inline

Definition at line 538 of file linearscan.h.

538{ return first_use_interval()->start(); }
intptr_t start() const
Definition: linearscan.h:438

◆ vreg()

intptr_t dart::LiveRange::vreg ( ) const
inline

Definition at line 529 of file linearscan.h.

529{ return vreg_; }

The documentation for this class was generated from the following files: