Backed out changeset b8a962a66a80 (bug 1044578) for ARM simulator orange.
authorRyan VanderMeulen <ryanvm@gmail.com>
Tue, 26 Aug 2014 09:56:43 -0400
changeset 223294 123d4bd5a50bf17aabcea469b0eb70be5ad04fe5
parent 223293 912de3bb85ce46bfbdf0a8df90a6d8b96fd7670c
child 223295 165df837579e1d6b321732349721279ee49c725f
push id3979
push userraliiev@mozilla.com
push dateMon, 13 Oct 2014 16:35:44 +0000
treeherdermozilla-beta@30f2cc610691 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1044578
milestone34.0a1
backs outb8a962a66a800854213c81bdeb180a351ac54004
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out changeset b8a962a66a80 (bug 1044578) for ARM simulator orange.
js/src/jit/BacktrackingAllocator.cpp
js/src/jit/BacktrackingAllocator.h
js/src/jit/arm/Architecture-arm.h
js/src/jit/x64/Architecture-x64.h
js/src/jit/x86/Architecture-x86.h
--- a/js/src/jit/BacktrackingAllocator.cpp
+++ b/js/src/jit/BacktrackingAllocator.cpp
@@ -537,48 +537,44 @@ BacktrackingAllocator::processInterval(L
     // In general, we want to minimize the amount of interval splitting
     // (which generally necessitates spills), so allocate longer lived, lower
     // weight intervals first and evict and split them later if they prevent
     // allocation for higher weight intervals.
 
     bool canAllocate = setIntervalRequirement(interval);
 
     bool fixed;
-    LiveInterval *conflict[MaxAliasedRegisters] = {nullptr};
+    LiveInterval *conflict = nullptr;
     for (size_t attempt = 0;; attempt++) {
         if (canAllocate) {
             bool success = false;
             fixed = false;
-            for (uint32_t i = 0; i < MaxAliasedRegisters; i++)
-                conflict[i] = nullptr;
+            conflict = nullptr;
 
             // Ok, let's try allocating for this interval.
             if (interval->requirement()->kind() == Requirement::FIXED) {
-                if (!tryAllocateFixed(interval, &success, &fixed, conflict))
+                if (!tryAllocateFixed(interval, &success, &fixed, &conflict))
                     return false;
             } else {
-                if (!tryAllocateNonFixed(interval, &success, &fixed, conflict))
+                if (!tryAllocateNonFixed(interval, &success, &fixed, &conflict))
                     return false;
             }
 
             // If that worked, we're done!
             if (success)
                 return true;
 
             // If that didn't work, but we have a non-fixed LiveInterval known
             // to be conflicting, maybe we can evict it and try again.
-            // The conflict array is filled up starting from 0, and they were
-            // initialized to nullptr, so just checking the 0th element is
-            // sufficient.
             if (attempt < MAX_ATTEMPTS &&
                 !fixed &&
-                conflict[0] &&
-                computeSpillsWeight(conflict) < computeSpillWeight(interval))
+                conflict &&
+                computeSpillWeight(conflict) < computeSpillWeight(interval))
             {
-                if (!evictIntervals(conflict))
+                if (!evictInterval(conflict))
                     return false;
                 continue;
             }
         }
 
         // A minimal interval cannot be split any further. If we try to split
         // it at this point we will just end up with the same interval and will
         // enter an infinite loop. Weights and the initial live intervals must
@@ -770,65 +766,44 @@ BacktrackingAllocator::tryAllocateRegist
         return true;
 
     BacktrackingVirtualRegister *reg = &vregs[interval->vreg()];
     if (!reg->isCompatibleReg(r.reg))
         return true;
 
     JS_ASSERT_IF(interval->requirement()->kind() == Requirement::FIXED,
                  interval->requirement()->allocation() == LAllocation(r.reg));
-    size_t aliasCount = 0;
-    LiveInterval *localConflicts[MaxAliasedRegisters] = {nullptr};
+
     for (size_t i = 0; i < interval->numRanges(); i++) {
         AllocatedRange range(interval, interval->getRange(i)), existing;
-        bool shortCircuit = false;
         for (size_t a = 0; a < r.reg.numAliased(); a++) {
             PhysicalRegister &rAlias = registers[r.reg.aliased(a).code()];
             if (!rAlias.allocations.contains(range, &existing))
                 continue;
             if (existing.interval->hasVreg()) {
                 if (IonSpewEnabled(IonSpew_RegAlloc)) {
                     IonSpew(IonSpew_RegAlloc, "  %s collides with v%u[%u] %s [weight %lu]",
                             rAlias.reg.name(), existing.interval->vreg(),
                             existing.interval->index(),
                             existing.range->toString(),
                             computeSpillWeight(existing.interval));
                 }
-                JS_ASSERT(aliasCount < MaxAliasedRegisters);
-                localConflicts[aliasCount++] = existing.interval;
-                // Abstraction Violaiton, and not-perfect optimization!
-                // if the registers are an exact fit, then no other intervals
-                // need to be checked. They are an exact fit if a = 0 (by
-                // convention). this is non-perfect because this optimization
-                // also applies if the register-to-be-evicted is strictly
-                // larger than r. There is currently no api to give this
-                // information, so check a directly for now.
-                if (a == 0) {
-                    shortCircuit = true;
-                    break;
-                }
+                if (!*pconflicting || computeSpillWeight(existing.interval) < computeSpillWeight(*pconflicting))
+                    *pconflicting = existing.interval;
             } else {
                 if (IonSpewEnabled(IonSpew_RegAlloc)) {
                     IonSpew(IonSpew_RegAlloc, "  %s collides with fixed use %s",
                             rAlias.reg.name(), existing.range->toString());
                 }
                 *pfixed = true;
             }
             return true;
         }
-        if (shortCircuit)
-            break;
     }
-    if (aliasCount != 0) {
-        if (!pconflicting[0] || computeSpillsWeight(localConflicts) < computeSpillsWeight(pconflicting)) {
-            for (size_t i = 0; i < MaxAliasedRegisters; i++)
-                pconflicting[i] = localConflicts[i];
-        }
-        return true;
-    }
+
     IonSpew(IonSpew_RegAlloc, "  allocated to %s", r.reg.name());
 
     for (size_t i = 0; i < interval->numRanges(); i++) {
         AllocatedRange range(interval, interval->getRange(i));
         if (!r.allocations.insert(range))
             return false;
     }
 
@@ -1908,55 +1883,30 @@ BacktrackingAllocator::splitAcrossCalls(
                 return false;
         }
     }
     IonSpewFin(IonSpew_RegAlloc);
 
     return splitAt(interval, callPositions);
 }
 
-static LiveInterval *
-maxEnd(LiveInterval **conflicts)
-{
-    LiveInterval *ret = nullptr;
-    for (uint32_t i = 0; i < MaxAliasedRegisters; i++) {
-        if (conflicts[i] == nullptr)
-            continue;
-        if (ret == nullptr || conflicts[i]->end() > ret->end())
-            ret = conflicts[i];
-    }
-    return ret;
-}
-static LiveInterval *
-minStart(LiveInterval **conflicts)
-{
-    LiveInterval *ret = nullptr;
-    for (uint32_t i = 0; i < MaxAliasedRegisters; i++) {
-        if (conflicts[i] == nullptr)
-            continue;
-        if (ret == nullptr || conflicts[i]->start() < ret->start())
-            ret = conflicts[i];
-    }
-    return ret;
-}
-
 bool
-BacktrackingAllocator::chooseIntervalSplit(LiveInterval *interval, LiveInterval **conflict)
+BacktrackingAllocator::chooseIntervalSplit(LiveInterval *interval, LiveInterval *conflict)
 {
     bool success = false;
 
     if (!trySplitAcrossHotcode(interval, &success))
         return false;
     if (success)
         return true;
 
-    if (!trySplitBeforeFirstRegisterUse(interval, maxEnd(conflict), &success))
+    if (!trySplitBeforeFirstRegisterUse(interval, conflict, &success))
         return false;
     if (success)
         return true;
 
-    if (!trySplitAfterLastRegisterUse(interval, minStart(conflict), &success))
+    if (!trySplitAfterLastRegisterUse(interval, conflict, &success))
         return false;
     if (success)
         return true;
 
     return splitAtAllRegisterUses(interval);
 }
--- a/js/src/jit/BacktrackingAllocator.h
+++ b/js/src/jit/BacktrackingAllocator.h
@@ -220,25 +220,16 @@ class BacktrackingAllocator
     bool processInterval(LiveInterval *interval);
     bool processGroup(VirtualRegisterGroup *group);
     bool setIntervalRequirement(LiveInterval *interval);
     bool tryAllocateRegister(PhysicalRegister &r, LiveInterval *interval,
                              bool *success, bool *pfixed, LiveInterval **pconflicting);
     bool tryAllocateGroupRegister(PhysicalRegister &r, VirtualRegisterGroup *group,
                                   bool *psuccess, bool *pfixed, LiveInterval **pconflicting);
     bool evictInterval(LiveInterval *interval);
-    bool evictIntervals(LiveInterval **intervals) {
-        for (size_t i = 0; i < MaxAliasedRegisters; i++) {
-            if (intervals[i] == nullptr)
-                continue;
-            if (!evictInterval(intervals[i]))
-                return false;
-        }
-        return true;
-    }
     void distributeUses(LiveInterval *interval, const LiveIntervalVector &newIntervals);
     bool split(LiveInterval *interval, const LiveIntervalVector &newIntervals);
     bool requeueIntervals(const LiveIntervalVector &newIntervals);
     void spill(LiveInterval *interval);
 
     bool isReusedInput(LUse *use, LInstruction *ins, bool considerCopy);
     bool isRegisterUse(LUse *use, LInstruction *ins, bool considerCopy = false);
     bool isRegisterDefinition(LiveInterval *interval);
@@ -259,30 +250,21 @@ class BacktrackingAllocator
     bool minimalDef(const LiveInterval *interval, LInstruction *ins);
     bool minimalUse(const LiveInterval *interval, LInstruction *ins);
     bool minimalInterval(const LiveInterval *interval, bool *pfixed = nullptr);
 
     // Heuristic methods.
 
     size_t computePriority(const LiveInterval *interval);
     size_t computeSpillWeight(const LiveInterval *interval);
-    size_t computeSpillsWeight(LiveInterval **intervals) {
-        size_t ret = 0;
-        for (size_t i = 0; i < MaxAliasedRegisters; i++) {
-            if (intervals[i] == nullptr)
-                continue;
-            ret += computeSpillWeight(intervals[i]);
-        }
-        return ret;
-    }
 
     size_t computePriority(const VirtualRegisterGroup *group);
     size_t computeSpillWeight(const VirtualRegisterGroup *group);
 
-    bool chooseIntervalSplit(LiveInterval *interval, LiveInterval **conflict);
+    bool chooseIntervalSplit(LiveInterval *interval, LiveInterval *conflict);
 
     bool splitAt(LiveInterval *interval, const SplitPositions &splitPositions);
     bool trySplitAcrossHotcode(LiveInterval *interval, bool *success);
     bool trySplitAfterLastRegisterUse(LiveInterval *interval, LiveInterval *conflict, bool *success);
     bool trySplitBeforeFirstRegisterUse(LiveInterval *interval, LiveInterval *conflict, bool *success);
     bool splitAtAllRegisterUses(LiveInterval *interval);
     bool splitAcrossCalls(LiveInterval *interval);
 };
--- a/js/src/jit/arm/Architecture-arm.h
+++ b/js/src/jit/arm/Architecture-arm.h
@@ -30,23 +30,16 @@ namespace jit {
 static const uint32_t ION_FRAME_SLACK_SIZE   = 20;
 
 // These offsets are specific to nunboxing, and capture offsets into the
 // components of a js::Value.
 static const int32_t NUNBOX32_TYPE_OFFSET    = 4;
 static const int32_t NUNBOX32_PAYLOAD_OFFSET = 0;
 
 static const uint32_t ShadowStackSpace = 0;
-
-// MaxAliasedRegisters is the maximum number of names that can be allocated to
-// any register. For example since S0, S1 and D0 cannot be in use
-// at the same time, the largest number of aliased registers is 2 (S0, S1).
-// This is for the register allocators. It is so the allocator can keep track
-// of all intervals that alias a given register.
-static const uint32_t MaxAliasedRegisters = 2;
 ////
 // These offsets are related to bailouts.
 ////
 
 // Size of each bailout table entry. On arm, this is presently a single call
 // (which is wrong!). The call clobbers lr.
 // For now, I've dealt with this by ensuring that we never allocate to lr. It
 // should probably be 8 bytes, a mov of an immediate into r12 (not allocated
--- a/js/src/jit/x64/Architecture-x64.h
+++ b/js/src/jit/x64/Architecture-x64.h
@@ -19,23 +19,16 @@ namespace jit {
 static const uint32_t ION_FRAME_SLACK_SIZE     = 24;
 
 #ifdef _WIN64
 static const uint32_t ShadowStackSpace = 32;
 #else
 static const uint32_t ShadowStackSpace = 0;
 #endif
 
-// MaxAliasedRegisters is the largest number of registers that be simultaneously
-// allocated, and alais a single register. If al and ah could be allocated
-// independently, this would be two, but since there is no aliasing on x86/x64
-// this is 1.
-// This is so the register allocator knows the largest number of intervals
-// it may have to evict at once
-static const uint32_t MaxAliasedRegisters = 1;
 class Registers {
   public:
     typedef X86Registers::RegisterID Code;
     typedef uint32_t SetType;
     static uint32_t SetSize(SetType x) {
         static_assert(sizeof(SetType) == 4, "SetType must be 32 bits");
         return mozilla::CountPopulation32(x);
     }
--- a/js/src/jit/x86/Architecture-x86.h
+++ b/js/src/jit/x86/Architecture-x86.h
@@ -21,23 +21,16 @@ static const uint32_t ION_FRAME_SLACK_SI
 // Only Win64 requires shadow stack space.
 static const uint32_t ShadowStackSpace = 0;
 
 // These offsets are specific to nunboxing, and capture offsets into the
 // components of a js::Value.
 static const int32_t NUNBOX32_TYPE_OFFSET         = 4;
 static const int32_t NUNBOX32_PAYLOAD_OFFSET      = 0;
 
-// MaxAliasedRegisters is the largest number of registers that be simultaneously
-// allocated, and alais a single register. If al and ah could be allocated
-// independently, this would be two, but since there is no aliasing on x86/x64
-// this is 1.
-// This is so the register allocator knows the largest number of intervals
-// it may have to evict at once
-static const uint32_t MaxAliasedRegisters = 1;
 ////
 // These offsets are related to bailouts.
 ////
 
 // Size of each bailout table entry. On x86 this is a 5-byte relative call.
 static const uint32_t BAILOUT_TABLE_ENTRY_SIZE    = 5;
 
 class Registers {