--- 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("))");
}