Bug 1274618 - Generate labels for branch statements. r?sunfish draft
authorYury Delendik <ydelendik@mozilla.com>
Mon, 23 May 2016 15:02:53 -0500
changeset 369821 ff49731c7d5e4918fd66bf54658c6addea02b5c1
parent 369820 34a1313b8fad7a5e0fe893f96e4d4c7fb9714726
child 369822 09f02ca064b1ad57a0a18448dee4b37dddf4c102
child 369848 3ab46f9dcce6671fe69f2b0bc7ace6f4b359895e
push id18925
push userydelendik@mozilla.com
push dateMon, 23 May 2016 20:33:26 +0000
reviewerssunfish
bugs1274618
milestone49.0a1
Bug 1274618 - Generate labels for branch statements. r?sunfish MozReview-Commit-ID: Eco3yLdAcG6
js/src/asmjs/WasmBinaryToAST.cpp
js/src/asmjs/WasmBinaryToText.cpp
--- a/js/src/asmjs/WasmBinaryToAST.cpp
+++ b/js/src/asmjs/WasmBinaryToAST.cpp
@@ -73,46 +73,56 @@ class AstDecodeContext
     Maybe<uint32_t> initialSizePages;
     Maybe<uint32_t> maxSizePages;
 
   private:
     AstModule& module_;
     AstIndexVector funcSigs_;
     AstDecodeExprIter *iter_;
     const ValTypeVector* locals_;
+    AstNameVector blockLabels_;
+    uint32_t currentLabelIndex_;
 
   public:
     AstDecodeContext(JSContext* cx, LifoAlloc& lifo, Decoder& d, AstModule& module, bool generateNames)
      : cx(cx),
        lifo(lifo),
        d(d),
        generateNames(generateNames),
        numTableElems(0),
        initialSizePages(),
        maxSizePages(),
        module_(module),
        funcSigs_(lifo),
        iter_(nullptr),
-       locals_(nullptr)
+       locals_(nullptr),
+       blockLabels_(lifo)
     {}
 
     AstModule& module() { return module_; }
     AstIndexVector& funcSigs() { return funcSigs_; }
     AstDecodeExprIter& iter() { return *iter_; }
     const ValTypeVector& locals() { return *locals_; }
+    AstNameVector& blockLabels() { return blockLabels_; }
 
     void startFunction(AstDecodeExprIter *iter, const ValTypeVector* locals)
     {
         iter_ = iter;
         locals_ = locals;
+        currentLabelIndex_ = 0;
     }
     void endFunction()
     {
         iter_ = nullptr;
         locals_ = nullptr;
+        MOZ_ASSERT(blockLabels_.length() == 0);
+    }
+    uint32_t nextLabelIndex()
+    {
+        return currentLabelIndex_++;
     }
 };
 
 static bool
 AstDecodeFail(AstDecodeContext& c, const char* str)
 {
     uint32_t offset = c.d.currentOffset();
     char offsetStr[sizeof "4294967295"];
@@ -307,16 +317,35 @@ AstDecodeCallImport(AstDecodeContext& c)
     if (!call)
         return false;
 
     c.iter().setResult(AstDecodeStackItem(call, argsLength));
     return true;
 }
 
 static bool
+AstDecodeGetBlockRef(AstDecodeContext& c, uint32_t depth, AstRef* ref)
+{
+    if (!c.generateNames || depth >= c.blockLabels().length()) {
+        // Also ignoring if it's a function body label.
+        *ref = AstRef(AstName(), depth);
+        return true;
+    }
+
+    uint32_t index = c.blockLabels().length() - depth - 1;
+    if (c.blockLabels()[index].empty()) {
+        if (!AstDecodeGenerateName(c, AstName(MOZ_UTF16("$label$"), 7), c.nextLabelIndex(), &c.blockLabels()[index]))
+            return false;
+    }
+    *ref = AstRef(c.blockLabels()[index], AstNoIndex);
+    ref->setIndex(depth);
+    return true;
+}
+
+static bool
 AstDecodeBrTable(AstDecodeContext& c)
 {
     uint32_t tableLength;
     ExprType type;
     AstDecodeStackItem index;
     AstDecodeStackItem value;
     if (!c.iter().readBrTable(&tableLength, &type, &value, &index))
         return false;
@@ -324,41 +353,49 @@ AstDecodeBrTable(AstDecodeContext& c)
     AstRefVector table(c.lifo);
     if (!table.resize(tableLength))
         return false;
 
     uint32_t depth;
     for (size_t i = 0, e = tableLength; i < e; ++i) {
         if (!c.iter().readBrTableEntry(type, &depth))
             return false;
-        table[i] = AstRef(AstName(), depth);
+        if (!AstDecodeGetBlockRef(c, depth, &table[i]))
+            return false;
     }
 
     // Read the default label.
     if (!c.iter().readBrTableEntry(type, &depth))
         return false;
 
-    AstRef def(AstName(), depth);
+    AstRef def;
+    if (!AstDecodeGetBlockRef(c, depth, &def))
+        return false;
+
     AstBranchTable* branchTable = new(c.lifo) AstBranchTable(*index.expr, def, Move(table), value.expr);
     if (!branchTable)
         return false;
 
     c.iter().setResult(AstDecodeStackItem(branchTable, value.expr ? 2 : 1));
     return true;
 }
 
 static bool
 AstDecodeBlock(AstDecodeContext& c, Expr expr)
 {
     MOZ_ASSERT(expr == Expr::Block || expr == Expr::Loop);
 
     if (expr == Expr::Loop) {
+      if (!c.blockLabels().append(AstName()) || !c.blockLabels().append(AstName()))
+          return false;
       if (!c.iter().readLoop())
           return false;
     } else {
+      if (!c.blockLabels().append(AstName()))
+          return false;
       if (!c.iter().readBlock())
           return false;
     }
 
     AstExprVector exprs(c.lifo);
     while (true) {
         if (!AstDecodeExpr(c))
             return false;
@@ -367,66 +404,77 @@ AstDecodeBlock(AstDecodeContext& c, Expr
         if (!item.expr) // Expr::End was found
             break;
 
         exprs.shrinkBy(item.popped);
         if (!exprs.append(item.expr))
             return false;
     }
 
-    AstBlock* block = new(c.lifo) AstBlock(expr, AstName(), AstName(), Move(exprs));
+    AstName continueName;
+    if (expr == Expr::Loop)
+        continueName = c.blockLabels().popCopy();
+    AstName breakName = c.blockLabels().popCopy();
+    AstBlock* block = new(c.lifo) AstBlock(expr, breakName, continueName, Move(exprs));
     if (!block)
         return false;
 
     c.iter().setResult(AstDecodeStackItem(block));
     return true;
 }
 
 static bool
 AstDecodeIf(AstDecodeContext& c)
 {
     AstDecodeStackItem cond;
     if (!c.iter().readIf(&cond))
         return false;
 
     bool hasElse = false;
 
+    if (!c.blockLabels().append(AstName()))
+        return false;
     AstExprVector thenExprs(c.lifo);
     while (true) {
         if (!AstDecodeExpr(c))
             return false;
 
         AstDecodeStackItem item = c.iter().getResult();
         if (!item.expr) {
             hasElse = item.terminationKind == AstDecodeTerminationKind::Else;
             break;
         }
 
         thenExprs.shrinkBy(item.popped);
         if (!thenExprs.append(item.expr))
             return false;
     }
+    AstName thenName = c.blockLabels().popCopy();
 
+    AstName elseName;
     AstExprVector elseExprs(c.lifo);
     if (hasElse) {
+        if (!c.blockLabels().append(AstName()))
+            return false;
         while (true) {
             if (!AstDecodeExpr(c))
                 return false;
 
             AstDecodeStackItem item = c.iter().getResult();
             if (!item.expr) // Expr::End was found
                 break;
 
             elseExprs.shrinkBy(item.popped);
             if (!elseExprs.append(item.expr))
                 return false;
         }
+        elseName = c.blockLabels().popCopy();
     }
 
-    AstIf* if_ = new(c.lifo) AstIf(cond.expr, AstName(), Move(thenExprs), AstName(), Move(elseExprs));
+    AstIf* if_ = new(c.lifo) AstIf(cond.expr, thenName, Move(thenExprs), elseName, Move(elseExprs));
     if (!if_)
         return false;
 
     c.iter().setResult(AstDecodeStackItem(if_, 1));
     return true;
 }
 
 static bool
@@ -588,17 +636,20 @@ AstDecodeBranch(AstDecodeContext& c, Exp
             return false;
         popped = value.expr ? 1 : 0;
     } else {
         if (!c.iter().readBrIf(&depth, &type, &value, &cond))
             return false;
         popped = value.expr ? 2 : 1;
     }
 
-    AstRef depthRef(AstName(), depth);
+    AstRef depthRef;
+    if (!AstDecodeGetBlockRef(c, depth, &depthRef))
+        return false;
+
     AstBranch* branch = new(c.lifo) AstBranch(expr, cond.expr, depthRef, value.expr);
     if (!branch)
         return false;
 
     c.iter().setResult(AstDecodeStackItem(branch, popped));
     return true;
 }
 
@@ -1302,16 +1353,20 @@ AstDecodeFunctionBody(AstDecodeContext &
     if (!locals.appendAll(sig->args()))
         return false;
 
     if (!DecodeLocalEntries(c.d, &locals))
         return AstDecodeFail(c, "failed decoding local entries");
 
     c.startFunction(&iter, &locals);
 
+    AstName funcName;
+    if (!AstDecodeGenerateName(c, AstName(MOZ_UTF16("$func$"), 6), funcIndex, &funcName))
+        return false;
+
     uint32_t numParams = sig->args().length();
     uint32_t numLocals = locals.length();
     for (uint32_t i = numParams; i < numLocals; i++) {
         if (!vars.append(locals[i]))
             return false;
     }
     for (uint32_t i = 0; i < numLocals; i++) {
         AstName varName;
@@ -1337,20 +1392,16 @@ AstDecodeFunctionBody(AstDecodeContext &
     if (!c.iter().readFunctionEnd(sig->ret(), &tmp))
         return false;
 
     c.endFunction();
 
     if (c.d.currentPosition() != bodyEnd)
         return AstDecodeFail(c, "function body length mismatch");
 
-    AstName funcName;
-    if (!AstDecodeGenerateName(c, AstName(MOZ_UTF16("$func$"), 6), funcIndex, &funcName))
-        return false;
-
     AstRef sigRef;
     if (!AstDecodeGenerateRef(c, AstName(MOZ_UTF16("$type$"), 6), sigIndex, &sigRef))
         return false;
 
     *func = new(c.lifo) AstFunc(funcName, sigRef, Move(vars), Move(localsNames), Move(body));
     if (!*func)
         return false;
 
--- a/js/src/asmjs/WasmBinaryToText.cpp
+++ b/js/src/asmjs/WasmBinaryToText.cpp
@@ -376,19 +376,35 @@ RenderExprList(WasmRenderContext& c, con
 }
 
 static bool
 RenderBlock(WasmRenderContext& c, AstBlock& block)
 {
     if (block.expr() == Expr::Block) {
         if (!c.buffer.append("(block "))
             return false;
+        if (!RenderName(c, block.breakName()))
+            return false;
     } else if (block.expr() == Expr::Loop) {
         if (!c.buffer.append("(loop "))
             return false;
+        if (block.breakName().empty() && !block.continueName().empty()) {
+            // Giving auto label if continue label is present.
+            if (!c.buffer.append("$exit$"))
+                return false;
+        } else {
+            if (!RenderName(c, block.breakName()))
+                return false;
+        }
+        if (!block.continueName().empty()) {
+          if (!c.buffer.append(" "))
+              return false;
+          if (!RenderName(c, block.continueName()))
+              return false;
+        }
     } else
         return false;
 
     c.indent++;
     if (!RenderExprList(c, block.exprs()))
         return false;
     c.indent--;
 
@@ -646,25 +662,31 @@ RenderIf(WasmRenderContext& c, AstIf& if
     if (!c.buffer.append("(if "))
         return false;
     if (!RenderExpr(c, if_.cond()))
         return false;
 
     if (!c.buffer.append(" (then "))
         return false;
 
+    if (!RenderName(c, if_.thenName()))
+        return false;
+
     c.indent++;
     if (!RenderExprList(c, if_.thenExprs()))
         return false;
     c.indent--;
 
     if (if_.hasElse()) {
         if (!c.buffer.append(") (else "))
             return false;
 
+        if (!RenderName(c, if_.elseName()))
+            return false;
+
         c.indent++;
         if (!RenderExprList(c, if_.elseExprs()))
             return false;
         c.indent--;
     }
 
     return c.buffer.append("))");
 }