| Index: src/compiler/coalesced-live-ranges.h
|
| diff --git a/src/compiler/coalesced-live-ranges.h b/src/compiler/coalesced-live-ranges.h
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..f12517203f844e4a71a68e77eaff21eb16f67eff
|
| --- /dev/null
|
| +++ b/src/compiler/coalesced-live-ranges.h
|
| @@ -0,0 +1,109 @@
|
| +// Copyright 2015 the V8 project authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#ifndef V8_COALESCED_LIVE_RANGES_H_
|
| +#define V8_COALESCED_LIVE_RANGES_H_
|
| +
|
| +#include "src/compiler/register-allocator.h"
|
| +#include "src/zone-containers.h"
|
| +
|
| +namespace v8 {
|
| +namespace internal {
|
| +namespace compiler {
|
| +
|
| +
|
| +class AllocationScheduler;
|
| +
|
| +
|
| +// Collection of live ranges allocated to the same register.
|
| +// It supports efficiently finding all conflicts for a given, non-allocated
|
| +// range. See AllocatedInterval.
|
| +// Allocated live ranges do not intersect. At most, individual use intervals
|
| +// touch. We store, for a live range, an AllocatedInterval corresponding to each
|
| +// of that range's UseIntervals. We keep the list of AllocatedIntervals sorted
|
| +// by starts. Then, given the non-intersecting property, we know that
|
| +// consecutive AllocatedIntervals have the property that the "smaller"'s end is
|
| +// less or equal to the "larger"'s start.
|
| +// This allows for quick (logarithmic complexity) identification of the first
|
| +// AllocatedInterval to conflict with a given LiveRange, and then for efficient
|
| +// traversal of conflicts.
|
| +class CoalescedLiveRanges : public ZoneObject {
|
| + public:
|
| + explicit CoalescedLiveRanges(Zone* zone) : storage_(zone) {}
|
| + void clear() { storage_.clear(); }
|
| +
|
| + bool empty() const { return storage_.empty(); }
|
| +
|
| + // Returns kInvalidWeight if there are no conflicts, or the largest weight of
|
| + // a range conflicting with the given range.
|
| + float GetMaximumConflictingWeight(const LiveRange* range) const;
|
| +
|
| + // Evicts all conflicts of the given range, and reschedules them with the
|
| + // provided scheduler.
|
| + void EvictAndRescheduleConflicts(LiveRange* range,
|
| + AllocationScheduler* scheduler);
|
| +
|
| + // Allocates a range with a pre-calculated candidate weight.
|
| + void AllocateRange(LiveRange* range);
|
| +
|
| + // TODO(mtrofin): remove this in favor of comprehensive unit tests.
|
| + bool VerifyAllocationsAreValid() const;
|
| +
|
| + private:
|
| + static const float kAllocatedRangeMultiplier;
|
| + // Storage detail for CoalescedLiveRanges.
|
| + struct AllocatedInterval {
|
| + LifetimePosition start;
|
| + LifetimePosition end;
|
| + LiveRange* range;
|
| + bool operator<(const AllocatedInterval& other) const {
|
| + return start < other.start;
|
| + }
|
| + bool operator>(const AllocatedInterval& other) const {
|
| + return start > other.start;
|
| + }
|
| + };
|
| + typedef ZoneSet<AllocatedInterval> IntervalStore;
|
| + typedef IntervalStore::const_iterator interval_iterator;
|
| +
|
| + IntervalStore& storage() { return storage_; }
|
| + const IntervalStore& storage() const { return storage_; }
|
| +
|
| + // Augment the weight of a range that is about to be allocated.
|
| + static void UpdateWeightAtAllocation(LiveRange* range);
|
| +
|
| + // Reduce the weight of a range that has lost allocation.
|
| + static void UpdateWeightAtEviction(LiveRange* range);
|
| +
|
| + // Intersection utilities.
|
| + static bool Intersects(LifetimePosition a_start, LifetimePosition a_end,
|
| + LifetimePosition b_start, LifetimePosition b_end) {
|
| + return a_start < b_end && b_start < a_end;
|
| + }
|
| + static AllocatedInterval AsAllocatedInterval(LifetimePosition pos) {
|
| + return {pos, LifetimePosition::Invalid(), nullptr};
|
| + }
|
| +
|
| + bool QueryIntersectsAllocatedInterval(const UseInterval* query,
|
| + interval_iterator& pos) const {
|
| + DCHECK(query != nullptr);
|
| + return pos != storage().end() &&
|
| + Intersects(query->start(), query->end(), pos->start, pos->end);
|
| + }
|
| +
|
| + void Remove(LiveRange* range);
|
| +
|
| + // Get the first interval intersecting query. Since the intervals are sorted,
|
| + // subsequent intervals intersecting query follow.
|
| + interval_iterator GetFirstConflict(const UseInterval* query) const;
|
| +
|
| + IntervalStore storage_;
|
| + DISALLOW_COPY_AND_ASSIGN(CoalescedLiveRanges);
|
| +};
|
| +
|
| +
|
| +} // namespace compiler
|
| +} // namespace internal
|
| +} // namespace v8
|
| +#endif // V8_COALESCED_LIVE_RANGES_H_
|
|
|