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 375103 1571ba44e85026e0e5ded9ebf4df5f31371cff68
parent 375102 2164277367ccce620b9105aa9e8c2ea21fb3e22f
child 375104 9042d15381359dc12bbce404f157cdde53e359eb
push id6996
push userjlorenzo@mozilla.com
push dateMon, 06 Mar 2017 20:48:21 +0000
treeherdermozilla-beta@d89512dab048 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersluke
bugs1316814
milestone53.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
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):