Bug 951528. r=jandem
authorKannan Vijayan <kvijayan@mozilla.com>
Fri, 20 Dec 2013 18:11:21 -0500
changeset 171869 9f2a7e76e2e2ecd3969c29ba9ce2f58bd62545c9
parent 171867 ee7541e01eb121e6c3eb574af4f7f8c544794d8f
child 171870 fc7cd53d9dd179a739c4a68656c915bcacc2fcff
push id5166
push userlsblakk@mozilla.com
push dateTue, 04 Feb 2014 01:47:54 +0000
treeherdermozilla-aurora@977eb2548b2d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem
bugs951528
milestone29.0a1
Bug 951528. r=jandem
js/src/jit/IonBuilder.cpp
js/src/jit/LinearScan.cpp
js/src/jit/MIRGenerator.h
js/src/jit/MIRGraph.cpp
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -9230,16 +9230,17 @@ IonBuilder::jsop_setarg(uint32_t arg)
     // If no arguments[...] GETELEM expressions are in the script, and an argsobj is not
     // required, then it means that any aliased argument set can never be observed, and
     // the frame does not actually need to be updated with the new arg value.
     if (info().argumentsAliasesFormals()) {
         // JSOP_SETARG with magic arguments within inline frames is not yet supported.
         JS_ASSERT(script()->uninlineable() && !isInlineBuilder());
 
         MSetFrameArgument *store = MSetFrameArgument::New(alloc(), arg, val);
+        modifiesFrameArguments_ = true;
         current->add(store);
         current->setArg(arg);
         return true;
     }
 
     // If this assignment is at the start of the function and is coercing
     // the original value for the argument which was passed in, loosen
     // the type information for that original argument if it is currently
--- a/js/src/jit/LinearScan.cpp
+++ b/js/src/jit/LinearScan.cpp
@@ -762,17 +762,23 @@ LinearScanAllocator::assign(LAllocation 
             // at the end (zero-length intervals are invalid).
             splitPos = splitPos.previous();
             JS_ASSERT (splitPos < current->end());
             if (!splitInterval(current, splitPos))
                 return false;
         }
     }
 
-    if (reg && allocation.isMemory()) {
+    bool useAsCanonicalSpillSlot = allocation.isMemory();
+    // Only canonically spill argument values when frame arguments are not
+    // modified in the body.
+    if (mir->modifiesFrameArguments())
+        useAsCanonicalSpillSlot = allocation.isStackSlot();
+
+    if (reg && useAsCanonicalSpillSlot) {
         if (reg->canonicalSpill()) {
             JS_ASSERT(allocation == *reg->canonicalSpill());
 
             // This interval is spilled more than once, so just always spill
             // it at its definition.
             reg->setSpillAtDefinition(outputOf(reg->ins()));
         } else {
             reg->setCanonicalSpill(current->getAllocation());
--- a/js/src/jit/MIRGenerator.h
+++ b/js/src/jit/MIRGenerator.h
@@ -122,16 +122,20 @@ class MIRGenerator
     }
     bool noteGlobalAccess(unsigned offset, unsigned globalDataOffset) {
         return asmJSGlobalAccesses_.append(AsmJSGlobalAccess(offset, globalDataOffset));
     }
     const Vector<AsmJSGlobalAccess, 0, IonAllocPolicy> &globalAccesses() const {
         return asmJSGlobalAccesses_;
     }
 
+    bool modifiesFrameArguments() const {
+        return modifiesFrameArguments_;
+    }
+
   public:
     CompileCompartment *compartment;
 
   protected:
     CompileInfo *info_;
     const OptimizationInfo *optimizationInfo_;
     TempAllocator *alloc_;
     JSFunction *fun_;
@@ -141,16 +145,21 @@ class MIRGenerator
     size_t cancelBuild_;
 
     uint32_t maxAsmJSStackArgBytes_;
     bool performsAsmJSCall_;
     AsmJSHeapAccessVector asmJSHeapAccesses_;
     AsmJSGlobalAccessVector asmJSGlobalAccesses_;
     uint32_t minAsmJSHeapLength_;
 
+    // Keep track of whether frame arguments are modified during execution.
+    // RegAlloc needs to know this as spilling values back to their register
+    // slots is not compatible with that.
+    bool modifiesFrameArguments_;
+
 #if defined(JS_ION_PERF)
     AsmJSPerfSpewer asmJSPerfSpewer_;
 
   public:
     AsmJSPerfSpewer &perfSpewer() { return asmJSPerfSpewer_; }
 #endif
 };
 
--- a/js/src/jit/MIRGraph.cpp
+++ b/js/src/jit/MIRGraph.cpp
@@ -25,17 +25,18 @@ MIRGenerator::MIRGenerator(CompileCompar
     alloc_(alloc),
     graph_(graph),
     error_(false),
     cancelBuild_(0),
     maxAsmJSStackArgBytes_(0),
     performsAsmJSCall_(false),
     asmJSHeapAccesses_(*alloc),
     asmJSGlobalAccesses_(*alloc),
-    minAsmJSHeapLength_(AsmJSAllocationGranularity)
+    minAsmJSHeapLength_(AsmJSAllocationGranularity),
+    modifiesFrameArguments_(false)
 { }
 
 bool
 MIRGenerator::abortFmt(const char *message, va_list ap)
 {
     IonSpewVA(IonSpew_Abort, message, ap);
     error_ = true;
     return false;