Bug 1316814 - Split wasm iterator's readEnd and popEnd. p=sunfish, r=luke
authorLars T Hansen <lhansen@mozilla.com>
Wed, 18 Jan 2017 19:55:10 +0100
changeset 358127 1571ba44e85026e0e5ded9ebf4df5f31371cff68
parent 358126 2164277367ccce620b9105aa9e8c2ea21fb3e22f
child 358128 9042d15381359dc12bbce404f157cdde53e359eb
push id10621
push userjlund@mozilla.com
push dateMon, 23 Jan 2017 16:02:43 +0000
treeherdermozilla-aurora@dca7b42e6c67 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersluke
bugs1316814
milestone53.0a1
Bug 1316814 - Split wasm iterator's readEnd and popEnd. p=sunfish, r=luke
js/src/wasm/WasmBaselineCompile.cpp
js/src/wasm/WasmBinaryIterator.h
js/src/wasm/WasmBinaryToAST.cpp
js/src/wasm/WasmIonCompile.cpp
js/src/wasm/WasmValidate.cpp
--- a/js/src/wasm/WasmBaselineCompile.cpp
+++ b/js/src/wasm/WasmBaselineCompile.cpp
@@ -5687,18 +5687,20 @@ BaseCompiler::endIfThenElse(ExprType typ
 }
 
 bool
 BaseCompiler::emitEnd()
 {
     LabelKind kind;
     ExprType type;
     Nothing unused_value;
+
     if (!iter_.readEnd(&kind, &type, &unused_value))
         return false;
+    iter_.popEnd();
 
     switch (kind) {
       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;
     }
--- a/js/src/wasm/WasmBinaryIterator.h
+++ b/js/src/wasm/WasmBinaryIterator.h
@@ -146,17 +146,16 @@ class ControlStackEntry
     ControlItem& controlItem() { return controlItem_; }
 
     void setReachable() { reachable_ = true; }
 
     void switchToElse(bool reachable) {
         MOZ_ASSERT(kind_ == LabelKind::Then || kind_ == LabelKind::UnreachableThen);
         reachable_ = reachable;
         kind_ = LabelKind::Else;
-        controlItem_ = ControlItem();
     }
 };
 
 // Specialization for when there is no additional data needed.
 template <>
 class ControlStackEntry<Nothing>
 {
     LabelKind kind_;
@@ -378,18 +377,18 @@ class MOZ_STACK_CLASS OpIter : private P
     MOZ_MUST_USE bool readLinearMemoryAddress(uint32_t byteSize, LinearMemoryAddress<Value>* addr);
     MOZ_MUST_USE bool readBlockType(ExprType* expr);
 
     MOZ_MUST_USE bool typeMismatch(ExprType actual, ExprType expected) MOZ_COLD;
     MOZ_MUST_USE bool checkType(ValType actual, ValType expected);
     MOZ_MUST_USE bool checkType(ExprType actual, ExprType expected);
 
     MOZ_MUST_USE bool pushControl(LabelKind kind, ExprType type, bool reachable);
-    MOZ_MUST_USE bool mergeControl(LabelKind* kind, ExprType* type, Value* value);
-    MOZ_MUST_USE bool popControl(LabelKind* kind, ExprType* type, Value* value);
+    MOZ_MUST_USE bool checkControlAtEndOfBlock(LabelKind* kind, ExprType* type, Value* value);
+    MOZ_MUST_USE bool finishControl(LabelKind* kind, ExprType* type, Value* value);
 
     MOZ_MUST_USE bool push(ValType t) {
         if (MOZ_UNLIKELY(!reachable_))
             return true;
         return valueStack_.emplaceBack(t);
     }
     MOZ_MUST_USE bool push(TypeAndValue<Value> tv) {
         if (MOZ_UNLIKELY(!reachable_))
@@ -545,16 +544,17 @@ class MOZ_STACK_CLASS OpIter : private P
     MOZ_MUST_USE bool readFunctionStart(ExprType ret);
     MOZ_MUST_USE bool readFunctionEnd();
     MOZ_MUST_USE bool readReturn(Value* value);
     MOZ_MUST_USE bool readBlock();
     MOZ_MUST_USE bool readLoop();
     MOZ_MUST_USE bool readIf(Value* condition);
     MOZ_MUST_USE bool readElse(ExprType* thenType, Value* thenValue);
     MOZ_MUST_USE bool readEnd(LabelKind* kind, ExprType* type, Value* value);
+    void popEnd();
     MOZ_MUST_USE bool readBr(uint32_t* relativeDepth, ExprType* type, Value* value);
     MOZ_MUST_USE bool readBrIf(uint32_t* relativeDepth, ExprType* type,
                                Value* value, Value* condition);
     MOZ_MUST_USE bool readBrTable(uint32_t* tableLength, ExprType* type,
                                   Value* value, Value* index);
     MOZ_MUST_USE bool readBrTableEntry(ExprType* type, Value* value, uint32_t* depth);
     MOZ_MUST_USE bool readBrTableDefault(ExprType* type, Value* value, uint32_t* depth);
     MOZ_MUST_USE bool readUnreachable();
@@ -656,16 +656,26 @@ class MOZ_STACK_CLASS OpIter : private P
         return valueStack_.back().value();
     }
 
     // Return a reference to the top of the control stack.
     ControlItem& controlItem() {
         return controlStack_.back().controlItem();
     }
 
+    // Return a reference to an element in the control stack.
+    ControlItem& controlItem(uint32_t relativeDepth) {
+        return controlStack_[controlStack_.length() - 1 - relativeDepth].controlItem();
+    }
+
+    // Return a reference to the outermost element on the control stack.
+    ControlItem& controlOutermost() {
+        return controlStack_[0].controlItem();
+    }
+
     // Return the signature of the top of the control stack.
     ExprType controlType() {
         return controlStack_.back().type();
     }
 
     // Test whether the control-stack is empty, meaning we've consumed the final
     // end of the function body.
     bool controlStackEmpty() const {
@@ -745,17 +755,17 @@ template <typename Policy>
 inline bool
 OpIter<Policy>::pushControl(LabelKind kind, ExprType type, bool reachable)
 {
     return controlStack_.emplaceBack(kind, type, reachable, valueStack_.length());
 }
 
 template <typename Policy>
 inline bool
-OpIter<Policy>::mergeControl(LabelKind* kind, ExprType* type, Value* value)
+OpIter<Policy>::checkControlAtEndOfBlock(LabelKind* kind, ExprType* type, Value* value)
 {
     MOZ_ASSERT(!controlStack_.empty());
 
     ControlStackEntry<ControlItem>& controlItem = controlStack_.back();
     *kind = controlItem.kind();
 
     if (reachable_) {
         // Unlike branching, exiting a scope via fallthrough does not implicitly
@@ -793,35 +803,30 @@ OpIter<Policy>::mergeControl(LabelKind* 
             *value = Value();
     }
 
     return true;
 }
 
 template <typename Policy>
 inline bool
-OpIter<Policy>::popControl(LabelKind* kind, ExprType* type, Value* value)
+OpIter<Policy>::finishControl(LabelKind* kind, ExprType* type, Value* value)
 {
-    if (!mergeControl(kind, type, value))
+    if (!checkControlAtEndOfBlock(kind, type, value))
         return false;
 
     if (*kind == LabelKind::Then) {
         // A reachable If without an Else. Forbid a result value.
         if (reachable_) {
             if (Validate && !IsVoid(*type))
                 return fail("if without else with a result value");
         }
         reachable_ = true;
     }
 
-    controlStack_.popBack();
-
-    if (!reachable_ && !controlStack_.empty())
-        valueStack_.shrinkTo(controlStack_.back().valueStackStart());
-
     return true;
 }
 
 template <typename Policy>
 inline bool
 OpIter<Policy>::readBlockType(ExprType* type)
 {
     uint8_t unchecked;
@@ -988,17 +993,17 @@ template <typename Policy>
 inline bool
 OpIter<Policy>::readElse(ExprType* thenType, Value* thenValue)
 {
     MOZ_ASSERT(Classify(op_) == OpKind::Else);
 
     // Finish up the then arm.
     ExprType type = ExprType::Limit;
     LabelKind kind;
-    if (!mergeControl(&kind, &type, thenValue))
+    if (!checkControlAtEndOfBlock(&kind, &type, thenValue))
         return false;
 
     if (Output)
         *thenType = type;
 
     // Pop the old then value from the stack.
     if (!IsVoid(type))
         valueStack_.popBack();
@@ -1019,28 +1024,40 @@ OpIter<Policy>::readElse(ExprType* thenT
 template <typename Policy>
 inline bool
 OpIter<Policy>::readEnd(LabelKind* kind, ExprType* type, Value* value)
 {
     MOZ_ASSERT(Classify(op_) == OpKind::End);
 
     LabelKind validateKind = static_cast<LabelKind>(-1);
     ExprType validateType = ExprType::Limit;
-    if (!popControl(&validateKind, &validateType, value))
+    if (!finishControl(&validateKind, &validateType, value))
         return false;
 
     if (Output) {
         *kind = validateKind;
         *type = validateType;
     }
 
     return true;
 }
 
 template <typename Policy>
+inline void
+OpIter<Policy>::popEnd()
+{
+    MOZ_ASSERT(Classify(op_) == OpKind::End);
+
+    controlStack_.popBack();
+
+    if (!reachable_ && !controlStack_.empty())
+        valueStack_.shrinkTo(controlStack_.back().valueStackStart());
+}
+
+template <typename Policy>
 inline bool
 OpIter<Policy>::checkBrValue(uint32_t relativeDepth, ExprType* type, Value* value)
 {
     if (MOZ_LIKELY(reachable_)) {
         ControlStackEntry<ControlItem>* controlItem = nullptr;
         if (!getControl(relativeDepth, &controlItem))
             return false;
 
--- a/js/src/wasm/WasmBinaryToAST.cpp
+++ b/js/src/wasm/WasmBinaryToAST.cpp
@@ -594,16 +594,18 @@ AstDecodeIf(AstDecodeContext& c)
 static bool
 AstDecodeEnd(AstDecodeContext& c)
 {
     LabelKind kind;
     ExprType type;
     if (!c.iter().readEnd(&kind, &type, nullptr))
         return false;
 
+    c.iter().popEnd();
+
     if (!c.push(AstDecodeStackItem(AstDecodeTerminationKind::End, type)))
         return false;
 
     return true;
 }
 
 static bool
 AstDecodeElse(AstDecodeContext& c)
--- a/js/src/wasm/WasmIonCompile.cpp
+++ b/js/src/wasm/WasmIonCompile.cpp
@@ -1657,43 +1657,43 @@ EmitIf(FunctionCompiler& f)
 
     f.iter().controlItem() = elseBlock;
     return true;
 }
 
 static bool
 EmitElse(FunctionCompiler& f)
 {
-    MBasicBlock* block = f.iter().controlItem();
-
     ExprType thenType;
     MDefinition* thenValue;
     if (!f.iter().readElse(&thenType, &thenValue))
         return false;
 
     if (!IsVoid(thenType))
         f.pushDef(thenValue);
 
-    if (!f.switchToElse(block, &f.iter().controlItem()))
+    if (!f.switchToElse(f.iter().controlItem(), &f.iter().controlItem()))
         return false;
 
     return true;
 }
 
 static bool
 EmitEnd(FunctionCompiler& f)
 {
-    MBasicBlock* block = f.iter().controlItem();
-
     LabelKind kind;
     ExprType type;
     MDefinition* value;
     if (!f.iter().readEnd(&kind, &type, &value))
         return false;
 
+    MBasicBlock* block = f.iter().controlItem();
+
+    f.iter().popEnd();
+
     if (!IsVoid(type))
         f.pushDef(value);
 
     MDefinition* def = nullptr;
     switch (kind) {
       case LabelKind::Block:
         if (!f.finishBlock(&def))
             return false;
--- a/js/src/wasm/WasmValidate.cpp
+++ b/js/src/wasm/WasmValidate.cpp
@@ -419,16 +419,17 @@ DecodeFunctionBodyExprs(FunctionDecoder&
         uint16_t op;
         if (!f.iter().readOp(&op))
             return false;
 
         switch (op) {
           case uint16_t(Op::End):
             if (!f.iter().readEnd(nullptr, nullptr, nullptr))
                 return false;
+            f.iter().popEnd();
             if (f.iter().controlStackEmpty())
                 return true;
             break;
           case uint16_t(Op::Nop):
             CHECK(f.iter().readNop());
           case uint16_t(Op::Drop):
             CHECK(f.iter().readDrop());
           case uint16_t(Op::Call):