GreedyAllocator support for calls. (Bug 670484, r=dvander)
authorSean Stangl <sstangl@mozilla.com>
Tue, 23 Aug 2011 17:47:26 -0700
changeset 105244 50142bbb735daf200fdf737e54968010b768dd23
parent 105243 090a6a0de93a879fd73c00aee52415327ee92b78
child 105245 1c09becc1638adc59dd965e9f793aff4b706c1e6
push id14706
push usereakhgari@mozilla.com
push dateTue, 11 Sep 2012 20:39:52 +0000
treeherdermozilla-inbound@d50bf1edaabe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdvander
bugs670484
milestone9.0a1
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
GreedyAllocator support for calls. (Bug 670484, r=dvander)
js/src/ion/GreedyAllocator.cpp
js/src/ion/GreedyAllocator.h
--- a/js/src/ion/GreedyAllocator.cpp
+++ b/js/src/ion/GreedyAllocator.cpp
@@ -563,16 +563,28 @@ GreedyAllocator::allocateInputs(LInstruc
         if (!allocateAnyOperand(a, vr))
             return false;
     }
 
     return true;
 }
 
 bool
+GreedyAllocator::spillForCall(LInstruction *ins)
+{
+    GeneralRegisterSet genset(Registers::JSCallClobberMask);
+    FloatRegisterSet floatset(FloatRegisters::JSCallClobberMask);
+    for (AnyRegisterIterator iter(genset, floatset); iter.more(); iter++) {
+        if (!maybeEvict(*iter))
+            return false;
+    }
+    return true;
+}
+
+bool
 GreedyAllocator::informSnapshot(LSnapshot *snapshot)
 {
     for (size_t i = 0; i < snapshot->numEntries(); i++) {
         LAllocation *a = snapshot->getEntry(i);
         if (!a->isUse())
             continue;
 
         LUse *use = a->toUse();
@@ -612,35 +624,39 @@ GreedyAllocator::allocateInstruction(LBl
 {
     if (!gen->ensureBallast())
         return false;
 
     // Reset internal state used for evicting.
     reset();
     assertValidRegisterState();
 
-    // Step 1. Find all fixed writable registers, adding them to the
+    // Step 1. Around a call, save all registers used downstream.
+    if (ins->isCallGeneric() && !spillForCall(ins))
+        return false;
+
+    // Step 2. Find all fixed writable registers, adding them to the
     // disallow set.
     if (!prescanDefinitions(ins))
         return false;
 
-    // Step 2. For each use, add fixed policies to the disallow set and
+    // Step 3. For each use, add fixed policies to the disallow set and
     // already allocated registers to the discouraged set.
     if (!prescanUses(ins))
         return false;
 
-    // Step 3. Allocate registers for each definition.
+    // Step 4. Allocate registers for each definition.
     if (!allocateDefinitions(ins))
         return false;
 
-    // Step 4. Allocate inputs and temporaries.
+    // Step 5. Allocate inputs and temporaries.
     if (!allocateInputs(ins))
         return false;
 
-    // Step 5. Assign fields of a snapshot.
+    // Step 6. Assign fields of a snapshot.
     if (ins->snapshot() && !informSnapshot(ins->snapshot()))
         return false;
 
     if (aligns)
         block->insertBefore(ins, aligns);
 
     return true;
 }
--- a/js/src/ion/GreedyAllocator.h
+++ b/js/src/ion/GreedyAllocator.h
@@ -271,16 +271,17 @@ class GreedyAllocator
     bool allocateRegisterOperand(LAllocation *a, VirtualRegister *vr);
     bool allocateAnyOperand(LAllocation *a, VirtualRegister *vr, bool preferReg = false);
     bool allocateFixedOperand(LAllocation *a, VirtualRegister *vr);
     bool allocateWritableOperand(LAllocation *a, VirtualRegister *vr);
 
     bool prescanDefinition(LDefinition *def);
     bool prescanDefinitions(LInstruction *ins);
     bool prescanUses(LInstruction *ins);
+    bool spillForCall(LInstruction *ins);
     bool informSnapshot(LSnapshot *snapshot);
     bool allocateSameAsInput(LDefinition *def, LAllocation *a, AnyRegister *out);
     bool allocateDefinitions(LInstruction *ins);
     bool allocateTemporaries(LInstruction *ins);
     bool allocateInputs(LInstruction *ins);
 
     bool allocateRegisters();
     bool allocateRegistersInBlock(LBlock *block);