Bug 1322093 part 5 - Factor out restoreInputState from emitFailurePath. r=h4writer
authorJan de Mooij <jdemooij@mozilla.com>
Wed, 21 Dec 2016 17:37:44 +0100
changeset 452480 2cb264cab3a12716b995c17915706da6665dc2ca
parent 452479 664ed8d2eaffe16894095bbe294dcb80a3774953
child 452481 cc3b8d218cc7e8515312919a291fac97cc59ff01
push id39415
push usermozilla@noorenberghe.ca
push dateWed, 21 Dec 2016 20:49:14 +0000
reviewersh4writer
bugs1322093
milestone53.0a1
Bug 1322093 part 5 - Factor out restoreInputState from emitFailurePath. r=h4writer
js/src/jit/CacheIRCompiler.cpp
js/src/jit/CacheIRCompiler.h
--- a/js/src/jit/CacheIRCompiler.cpp
+++ b/js/src/jit/CacheIRCompiler.cpp
@@ -334,16 +334,101 @@ CacheRegisterAllocator::knownType(ValOpe
 
       case OperandLocation::Uninitialized:
         break;
     }
 
     MOZ_CRASH("Invalid kind");
 }
 
+void
+CacheRegisterAllocator::restoreInputState(MacroAssembler& masm)
+{
+    size_t numInputOperands = origInputLocations_.length();
+    MOZ_ASSERT(writer_.numInputOperands() == numInputOperands);
+
+    for (size_t j = 0; j < numInputOperands; j++) {
+        OperandLocation orig = origInputLocation(j);
+        OperandLocation cur = operandLocation(j);
+
+        MOZ_ASSERT(orig.kind() == OperandLocation::ValueReg);
+
+        // We have a cycle if a destination register will be used later
+        // as source register. If that happens, just push the current value
+        // on the stack and later get it from there.
+        for (size_t k = j + 1; k < numInputOperands; k++) {
+            OperandLocation laterSource = operandLocation(k);
+            switch (laterSource.kind()) {
+              case OperandLocation::ValueReg:
+                if (orig.aliasesReg(laterSource.valueReg())) {
+                    stackPushed_ += sizeof(js::Value);
+                    masm.pushValue(laterSource.valueReg());
+                    laterSource.setValueStack(stackPushed_);
+                }
+                continue;
+              case OperandLocation::PayloadReg:
+                if (orig.aliasesReg(laterSource.payloadReg())) {
+                    stackPushed_ += sizeof(uintptr_t);
+                    masm.push(laterSource.payloadReg());
+                    laterSource.setPayloadStack(stackPushed_, laterSource.payloadType());
+                }
+                continue;
+              case OperandLocation::PayloadStack:
+              case OperandLocation::ValueStack:
+              case OperandLocation::Constant:
+                continue;
+              case OperandLocation::Uninitialized:
+                break;
+            }
+            MOZ_CRASH("Invalid kind");
+        }
+
+        switch (cur.kind()) {
+          case OperandLocation::ValueReg:
+            masm.moveValue(cur.valueReg(), orig.valueReg());
+            continue;
+          case OperandLocation::PayloadReg:
+            masm.tagValue(cur.payloadType(), cur.payloadReg(), orig.valueReg());
+            continue;
+          case OperandLocation::PayloadStack: {
+            MOZ_ASSERT(stackPushed_ >= sizeof(uintptr_t));
+            Register scratch = orig.valueReg().scratchReg();
+            if (cur.payloadStack() == stackPushed_) {
+                masm.pop(scratch);
+                stackPushed_ -= sizeof(uintptr_t);
+            } else {
+                MOZ_ASSERT(cur.payloadStack() < stackPushed_);
+                masm.loadPtr(Address(masm.getStackPointer(), stackPushed_ - cur.payloadStack()),
+                             scratch);
+            }
+            masm.tagValue(cur.payloadType(), scratch, orig.valueReg());
+            continue;
+          }
+          case OperandLocation::ValueStack:
+            MOZ_ASSERT(stackPushed_ >= sizeof(js::Value));
+            if (cur.valueStack() == stackPushed_) {
+                masm.popValue(orig.valueReg());
+                stackPushed_ -= sizeof(js::Value);
+            } else {
+                MOZ_ASSERT(cur.valueStack() < stackPushed_);
+                masm.loadValue(Address(masm.getStackPointer(), stackPushed_ - cur.valueStack()),
+                               orig.valueReg());
+            }
+            continue;
+          case OperandLocation::Constant:
+            continue;
+          case OperandLocation::Uninitialized:
+            break;
+        }
+        MOZ_CRASH("Invalid kind");
+    }
+
+    discardStack(masm);
+}
+
 size_t
 CacheIRStubInfo::stubDataSize() const
 {
     size_t field = 0;
     size_t size = 0;
     while (true) {
         StubField::Type type = fieldType(field++);
         if (type == StubField::Type::Limit)
@@ -613,102 +698,27 @@ CacheIRCompiler::addFailurePath(FailureP
     if (!failurePaths.append(Move(newFailure)))
         return false;
 
     *failure = &failurePaths.back();
     return true;
 }
 
 void
-CacheIRCompiler::emitFailurePath(size_t i)
+CacheIRCompiler::emitFailurePath(size_t index)
 {
-    FailurePath& failure = failurePaths[i];
+    FailurePath& failure = failurePaths[index];
+
+    allocator.setStackPushed(failure.stackPushed());
+
+    for (size_t i = 0; i < writer_.numInputOperands(); i++)
+        allocator.setOperandLocation(i, failure.input(i));
 
     masm.bind(failure.label());
-
-    uint32_t stackPushed = failure.stackPushed();
-    size_t numInputOperands = writer_.numInputOperands();
-
-    for (size_t j = 0; j < numInputOperands; j++) {
-        OperandLocation orig = allocator.origInputLocation(j);
-        OperandLocation cur = failure.input(j);
-
-        MOZ_ASSERT(orig.kind() == OperandLocation::ValueReg);
-
-        // We have a cycle if a destination register will be used later
-        // as source register. If that happens, just push the current value
-        // on the stack and later get it from there.
-        for (size_t k = j + 1; k < numInputOperands; k++) {
-            OperandLocation laterSource = failure.input(k);
-            switch (laterSource.kind()) {
-              case OperandLocation::ValueReg:
-                if (orig.aliasesReg(laterSource.valueReg())) {
-                    stackPushed += sizeof(js::Value);
-                    masm.pushValue(laterSource.valueReg());
-                    laterSource.setValueStack(stackPushed);
-                }
-                continue;
-              case OperandLocation::PayloadReg:
-                if (orig.aliasesReg(laterSource.payloadReg())) {
-                    stackPushed += sizeof(uintptr_t);
-                    masm.push(laterSource.payloadReg());
-                    laterSource.setPayloadStack(stackPushed, laterSource.payloadType());
-                }
-                continue;
-              case OperandLocation::PayloadStack:
-              case OperandLocation::ValueStack:
-              case OperandLocation::Constant:
-                continue;
-              case OperandLocation::Uninitialized:
-                break;
-            }
-            MOZ_CRASH("Invalid kind");
-        }
-
-        switch (cur.kind()) {
-          case OperandLocation::ValueReg:
-            masm.moveValue(cur.valueReg(), orig.valueReg());
-            continue;
-          case OperandLocation::PayloadReg:
-            masm.tagValue(cur.payloadType(), cur.payloadReg(), orig.valueReg());
-            continue;
-          case OperandLocation::PayloadStack: {
-            MOZ_ASSERT(stackPushed >= sizeof(uintptr_t));
-            Register scratch = orig.valueReg().scratchReg();
-            if (cur.payloadStack() == stackPushed) {
-                masm.pop(scratch);
-                stackPushed -= sizeof(uintptr_t);
-            } else {
-                MOZ_ASSERT(cur.payloadStack() < stackPushed);
-                masm.loadPtr(Address(masm.getStackPointer(), stackPushed - cur.payloadStack()),
-                             scratch);
-            }
-            masm.tagValue(cur.payloadType(), scratch, orig.valueReg());
-            continue;
-          }
-          case OperandLocation::ValueStack:
-            MOZ_ASSERT(stackPushed >= sizeof(js::Value));
-            if (cur.valueStack() == stackPushed) {
-                masm.popValue(orig.valueReg());
-                stackPushed -= sizeof(js::Value);
-            } else {
-                MOZ_ASSERT(cur.valueStack() < stackPushed);
-                masm.loadValue(Address(masm.getStackPointer(), stackPushed - cur.valueStack()),
-                               orig.valueReg());
-            }
-            continue;
-          case OperandLocation::Constant:
-            continue;
-          case OperandLocation::Uninitialized:
-            break;
-        }
-        MOZ_CRASH("Invalid kind");
-    }
-
-    allocator.discardStack(masm);
+    allocator.restoreInputState(masm);
 }
 
 bool
 CacheIRCompiler::emitGuardIsObject()
 {
     ValOperandId inputId = reader.valOperandId();
     if (allocator.knownType(inputId) == JSVAL_TYPE_OBJECT)
         return true;
--- a/js/src/jit/CacheIRCompiler.h
+++ b/js/src/jit/CacheIRCompiler.h
@@ -174,32 +174,39 @@ class MOZ_RAII CacheRegisterAllocator
         writer_(writer)
     {}
 
     MOZ_MUST_USE bool init(const AllocatableGeneralRegisterSet& available);
 
     OperandLocation operandLocation(size_t i) const {
         return operandLocations_[i];
     }
+    void setOperandLocation(size_t i, const OperandLocation& loc) {
+        operandLocations_[i] = loc;
+    }
+
     OperandLocation origInputLocation(size_t i) const {
         return origInputLocations_[i];
     }
     void initInputLocation(size_t i, ValueOperand reg) {
         origInputLocations_[i].setValueReg(reg);
         operandLocations_[i] = origInputLocations_[i];
     }
 
     void nextOp() {
         currentOpRegs_.clear();
         currentInstruction_++;
     }
 
     uint32_t stackPushed() const {
         return stackPushed_;
     }
+    void setStackPushed(uint32_t pushed) {
+        stackPushed_ = pushed;
+    }
 
     bool isAllocatable(Register reg) const {
         return allocatableRegs_.has(reg);
     }
 
     // Allocates a new register.
     Register allocateRegister(MacroAssembler& masm);
     ValueOperand allocateValueRegister(MacroAssembler& masm);
@@ -221,16 +228,20 @@ class MOZ_RAII CacheRegisterAllocator
     Register useRegister(MacroAssembler& masm, TypedOperandId typedId);
 
     // Allocates an output register for the given operand.
     Register defineRegister(MacroAssembler& masm, TypedOperandId typedId);
     ValueOperand defineValueRegister(MacroAssembler& masm, ValOperandId val);
 
     // Returns |val|'s JSValueType or JSVAL_TYPE_UNKNOWN.
     JSValueType knownType(ValOperandId val) const;
+
+    // Emits code to restore registers and stack to the state at the start of
+    // the stub.
+    void restoreInputState(MacroAssembler& masm);
 };
 
 // RAII class to allocate a scratch register and release it when we're done
 // with it.
 class MOZ_RAII AutoScratchRegister
 {
     CacheRegisterAllocator& alloc_;
     Register reg_;
@@ -336,17 +347,17 @@ class MOZ_RAII CacheIRCompiler
       : cx_(cx),
         reader(writer),
         writer_(writer),
         allocator(writer_)
     {}
 
     MOZ_MUST_USE bool addFailurePath(FailurePath** failure);
 
-    void emitFailurePath(size_t i);
+    void emitFailurePath(size_t index);
 
 #define DEFINE_SHARED_OP(op) MOZ_MUST_USE bool emit##op();
     CACHE_IR_SHARED_OPS(DEFINE_SHARED_OP)
 #undef DEFINE_SHARED_OP
 };
 
 // See the 'Sharing Baseline stub code' comment in CacheIR.h for a description
 // of this class.