Bug 1316850 - restore old value stack popping regime, with a twist. r=bbouvier
authorLars T Hansen <lhansen@mozilla.com>
Wed, 16 Nov 2016 11:36:30 +0100
changeset 439865 df748be239499d9a8f88df38988d89acab774f7a
parent 439864 0da56750be97361ba349e591b699b66911a0ce9c
child 439866 3cbb93f5768e0e5ac470d3bb29cea58fe2f45df3
push id36113
push userbmo:afarre@mozilla.com
push dateWed, 16 Nov 2016 18:15:04 +0000
reviewersbbouvier
bugs1316850
milestone53.0a1
Bug 1316850 - restore old value stack popping regime, with a twist. r=bbouvier
js/src/wasm/WasmBaselineCompile.cpp
--- a/js/src/wasm/WasmBaselineCompile.cpp
+++ b/js/src/wasm/WasmBaselineCompile.cpp
@@ -151,16 +151,17 @@ struct BaseCompilePolicy : OpIterPolicy
 
 typedef OpIter<BaseCompilePolicy> BaseOpIter;
 
 typedef bool IsUnsigned;
 typedef bool IsSigned;
 typedef bool ZeroOnOverflow;
 typedef bool IsKnownNotZero;
 typedef bool HandleNaNSpecially;
+typedef bool PopStack;
 typedef unsigned ByteSize;
 typedef unsigned BitSize;
 
 // UseABI::Wasm implies that the Tls/Heap/Global registers are nonvolatile,
 // except when InterModule::True is also set, when they are volatile.
 //
 // UseABI::System implies that the Tls/Heap/Global registers are volatile.
 // Additionally, the parameter passing mechanism may be slightly different from
@@ -1929,19 +1930,16 @@ class BaseCompiler
     }
 
     void popControl() {
         Control last = ctl_.popCopy();
         if (last.label)
             freeLabel(last.label);
         if (last.otherLabel)
             freeLabel(last.otherLabel);
-
-        if (deadCode_ && !ctl_.empty())
-            popValueStackTo(ctl_.back().stackSize);
     }
 
     Control& controlItem(uint32_t relativeDepth) {
         return ctl_[ctl_.length() - 1 - relativeDepth];
     }
 
     MOZ_MUST_USE PooledLabel* newLabel() {
         // TODO / INVESTIGATE (Bug 1316819): allocate() is fallible, but we can
@@ -2472,18 +2470,19 @@ class BaseCompiler
         }
 #elif defined(JS_CODEGEN_ARM)
         if (call.usesSystemAbi && !call.hardFP)
             masm.ma_vxfer(r0, r1, rv.reg);
 #endif
         return rv;
     }
 
-    void returnCleanup() {
-        popStackBeforeBranch(ctl_[0].framePushed);
+    void returnCleanup(bool popStack) {
+        if (popStack)
+            popStackBeforeBranch(ctl_[0].framePushed);
         masm.jump(&returnLabel_);
     }
 
     void pop2xI32ForIntMulDiv(RegI32* r0, RegI32* r1) {
 #if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
         // srcDest must be eax, and edx will be clobbered.
         need2xI32(specific_eax, specific_edx);
         *r1 = popI32();
@@ -3641,22 +3640,22 @@ class BaseCompiler
 
     template<bool isSetLocal> MOZ_MUST_USE inline bool emitSetOrTeeLocal(uint32_t slot);
     template<bool isSetGlobal> MOZ_MUST_USE inline bool emitSetOrTeeGlobal(uint32_t id);
     template<bool isStore>
     MOZ_MUST_USE inline bool emitStoreOrTeeStore(ValType resultType,
                                                  Scalar::Type viewType,
                                                  LinearMemoryAddress<Nothing> addr);
 
-    void endBlock(ExprType type, bool isFunctionBody);
+    void endBlock(ExprType type);
     void endLoop(ExprType type);
     void endIfThen();
     void endIfThenElse(ExprType type);
 
-    void doReturn(ExprType returnType);
+    void doReturn(ExprType returnType, bool popStack);
     void pushReturned(const FunctionCall& call, ExprType type);
 
     void emitCompareI32(JSOp compareOp, MCompare::CompareType compareType);
     void emitCompareI64(JSOp compareOp, MCompare::CompareType compareType);
     void emitCompareF32(JSOp compareOp, MCompare::CompareType compareType);
     void emitCompareF64(JSOp compareOp, MCompare::CompareType compareType);
 
     void emitAddI32();
@@ -4824,17 +4823,17 @@ BaseCompiler::emitBlock()
 
     if (!deadCode_)
         sync();                    // Simplifies branching out from block
 
     return pushControl(&blockEnd);
 }
 
 void
-BaseCompiler::endBlock(ExprType type, bool isFunctionBody)
+BaseCompiler::endBlock(ExprType type)
 {
     Control& block = controlItem(0);
 
     // Save the value.
     AnyReg r;
     if (!deadCode_)
         r = popJoinRegUnlessVoid(type);
 
@@ -4846,27 +4845,22 @@ BaseCompiler::endBlock(ExprType type, bo
         masm.bind(block.label);
         // No value was provided by the fallthrough but the branch out will
         // have stored one in joinReg, so capture that.
         if (deadCode_)
             r = captureJoinRegUnlessVoid(type);
         deadCode_ = false;
     }
 
-    MOZ_ASSERT(stk_.length() == block.stackSize);
+    popValueStackTo(block.stackSize);
+    popControl();
 
     // Retain the value stored in joinReg by all paths, if there are any.
-    if (!deadCode_) {
+    if (!deadCode_)
         pushJoinRegUnlessVoid(r);
-
-        if (isFunctionBody)
-            doReturn(func_.sig().ret());
-    }
-
-    popControl();
 }
 
 bool
 BaseCompiler::emitLoop()
 {
     if (!iter_.readLoop())
         return false;
 
@@ -4894,18 +4888,17 @@ BaseCompiler::endLoop(ExprType type)
     Control& block = controlItem(0);
 
     AnyReg r;
     if (!deadCode_)
         r = popJoinRegUnlessVoid(type);
 
     popStackOnBlockExit(block.framePushed);
 
-    MOZ_ASSERT(stk_.length() == block.stackSize);
-
+    popValueStackTo(block.stackSize);
     popControl();
 
     // Retain the value stored in joinReg by all paths.
     if (!deadCode_)
         pushJoinRegUnlessVoid(r);
 }
 
 // The bodies of the "then" and "else" arms can be arbitrary sequences
@@ -4964,18 +4957,17 @@ BaseCompiler::endIfThen()
     if (ifThen.otherLabel->used())
         masm.bind(ifThen.otherLabel);
 
     if (ifThen.label->used())
         masm.bind(ifThen.label);
 
     deadCode_ = ifThen.deadOnArrival;
 
-    MOZ_ASSERT(stk_.length() == ifThen.stackSize);
-
+    popValueStackTo(ifThen.stackSize);
     popControl();
 }
 
 bool
 BaseCompiler::emitElse()
 {
     ExprType thenType;
     Nothing unused_thenValue;
@@ -4999,17 +4991,17 @@ BaseCompiler::emitElse()
     if (!deadCode_)
         masm.jump(ifThenElse.label);
 
     if (ifThenElse.otherLabel->used())
         masm.bind(ifThenElse.otherLabel);
 
     // Reset to the "else" branch.
 
-    MOZ_ASSERT(stk_.length() == ifThenElse.stackSize);
+    popValueStackTo(ifThenElse.stackSize);
 
     if (!deadCode_)
         freeJoinRegUnlessVoid(r);
 
     deadCode_ = ifThenElse.deadOnArrival;
 
     return true;
 }
@@ -5041,35 +5033,34 @@ BaseCompiler::endIfThenElse(ExprType typ
     if (joinLive) {
         // No value was provided by the "then" path but capture the one
         // provided by the "else" path.
         if (deadCode_)
             r = captureJoinRegUnlessVoid(type);
         deadCode_ = false;
     }
 
-    MOZ_ASSERT(stk_.length() == ifThenElse.stackSize);
-
+    popValueStackTo(ifThenElse.stackSize);
     popControl();
 
     if (!deadCode_)
         pushJoinRegUnlessVoid(r);
 }
 
 bool
 BaseCompiler::emitEnd()
 {
     LabelKind kind;
     ExprType type;
     Nothing unused_value;
     if (!iter_.readEnd(&kind, &type, &unused_value))
         return false;
 
     switch (kind) {
-      case LabelKind::Block: endBlock(type, iter_.controlStackEmpty()); break;
+      case LabelKind::Block: endBlock(type); break;
       case LabelKind::Loop:  endLoop(type); break;
       case LabelKind::UnreachableThen:
       case LabelKind::Then:  endIfThen(); break;
       case LabelKind::Else:  endIfThenElse(type); break;
     }
 
     return true;
 }
@@ -5098,18 +5089,16 @@ BaseCompiler::emitBr()
 
     // The register holding the join value is free for the remainder
     // of this block.
 
     freeJoinRegUnlessVoid(r);
 
     deadCode_ = true;
 
-    popValueStackTo(ctl_.back().stackSize);
-
     return true;
 }
 
 bool
 BaseCompiler::emitBrIf()
 {
     uint32_t relativeDepth;
     ExprType type;
@@ -5238,18 +5227,16 @@ BaseCompiler::emitBrTable()
     // Clean up.
 
     freeI32(rc);
     freeJoinRegUnlessVoid(r);
 
     for (uint32_t i = 0; i < tableLength; i++)
         freeLabel(stubs[i]);
 
-    popValueStackTo(ctl_.back().stackSize);
-
     return true;
 }
 
 bool
 BaseCompiler::emitDrop()
 {
     if (!iter_.readDrop())
         return false;
@@ -5258,44 +5245,44 @@ BaseCompiler::emitDrop()
         return true;
 
     popStackIfMemory();
     popValueStackBy(1);
     return true;
 }
 
 void
-BaseCompiler::doReturn(ExprType type)
+BaseCompiler::doReturn(ExprType type, bool popStack)
 {
     switch (type) {
       case ExprType::Void: {
-        returnCleanup();
+        returnCleanup(popStack);
         break;
       }
       case ExprType::I32: {
         RegI32 rv = popI32(RegI32(ReturnReg));
-        returnCleanup();
+        returnCleanup(popStack);
         freeI32(rv);
         break;
       }
       case ExprType::I64: {
         RegI64 rv = popI64(RegI64(ReturnReg64));
-        returnCleanup();
+        returnCleanup(popStack);
         freeI64(rv);
         break;
       }
       case ExprType::F64: {
         RegF64 rv = popF64(RegF64(ReturnDoubleReg));
-        returnCleanup();
+        returnCleanup(popStack);
         freeF64(rv);
         break;
       }
       case ExprType::F32: {
         RegF32 rv = popF32(RegF32(ReturnFloat32Reg));
-        returnCleanup();
+        returnCleanup(popStack);
         freeF32(rv);
         break;
       }
       default: {
         MOZ_CRASH("Function return type");
       }
     }
 }
@@ -5305,21 +5292,19 @@ BaseCompiler::emitReturn()
 {
     Nothing unused_value;
     if (!iter_.readReturn(&unused_value))
         return false;
 
     if (deadCode_)
         return true;
 
-    doReturn(func_.sig().ret());
+    doReturn(func_.sig().ret(), PopStack(true));
     deadCode_ = true;
 
-    popValueStackTo(ctl_.back().stackSize);
-
     return true;
 }
 
 bool
 BaseCompiler::emitCallArgs(const ValTypeVector& args, FunctionCall& baselineCall)
 {
     MOZ_ASSERT(!deadCode_);
 
@@ -6529,17 +6514,16 @@ BaseCompiler::emitBody()
             CHECK_NEXT(emitBrTable());
           case uint16_t(Op::Return):
             CHECK_NEXT(emitReturn());
           case uint16_t(Op::Unreachable):
             CHECK(iter_.readUnreachable());
             if (!deadCode_) {
                 unreachableTrap();
                 deadCode_ = true;
-                popValueStackTo(ctl_.back().stackSize);
             }
             NEXT();
 
           // Calls
           case uint16_t(Op::Call):
             CHECK_NEXT(emitCall());
           case uint16_t(Op::CallIndirect):
             CHECK_NEXT(emitCallIndirect(/* oldStyle = */ false));
@@ -7125,22 +7109,26 @@ BaseCompiler::emitFunction()
         return false;
 
     beginFunction();
 
     UniquePooledLabel functionEnd(newLabel());
     if (!functionEnd)
         return false;
 
+    // For the function's block; it will be popped by endBlock().
     if (!pushControl(&functionEnd))
         return false;
 
     if (!emitBody())
         return false;
 
+    if (!deadCode_)
+        doReturn(sig.ret(), PopStack(false));
+
     if (!iter_.readFunctionEnd())
         return false;
 
     if (!endFunction())
         return false;
 
     return true;
 }