From 5acbb8d34f88eae9b5b50cf5d00f86dc56a7057c Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sat, 5 Mar 2016 22:31:09 -0800 Subject: handle continues in one-time loops --- src/asm2wasm.h | 48 ++++++++++++++++++++++++++++++------------------ 1 file changed, 30 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/asm2wasm.h b/src/asm2wasm.h index 06960a114..c13c847e7 100644 --- a/src/asm2wasm.h +++ b/src/asm2wasm.h @@ -66,6 +66,17 @@ struct AstStackHelper { std::vector AstStackHelper::astStack; +struct BreakSeeker : public WasmWalker { + IString target; // look for this one + size_t found; + + BreakSeeker(IString target) : target(target), found(false) {} + + void visitBreak(Break *curr) { + if (curr->name == target) found++; + } +}; + // // Asm2WasmPreProcessor - does some initial parsing/processing // of asm.js code. @@ -1281,8 +1292,7 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) { return ret; } else if (what == DO) { if (ast[1][0] == NUM && ast[1][1]->getNumber() == 0) { - // one-time loop - auto block = allocator.alloc(); + // one-time loop, unless there is a continue IString stop; if (!parentLabel.isNull()) { stop = getBreakLabelName(parentLabel); @@ -1290,13 +1300,27 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) { } else { stop = getNextId("do-once"); } - block->name = stop; + IString more = getNextId("unlikely-continue"); breakStack.push_back(stop); - continueStack.push_back(IMPOSSIBLE_CONTINUE); - block->list.push_back(process(ast[2])); + continueStack.push_back(more); + auto child = process(ast[2]); continueStack.pop_back(); breakStack.pop_back(); - return block; + // if we never continued, we don't need a loop + BreakSeeker breakSeeker(more); + breakSeeker.walk(child); + if (breakSeeker.found == 0) { + auto block = allocator.alloc(); + block->list.push_back(child); + block->name = stop; + return block; + } else { + auto loop = allocator.alloc(); + loop->body = child; + loop->out = stop; + loop->in = more; + return loop; + } } // general do-while loop auto ret = allocator.alloc(); @@ -1514,18 +1538,6 @@ void Asm2WasmBuilder::optimize() { return; } // we might be broken to, but maybe there isn't a break (and we may have removed it, leading to this) - - struct BreakSeeker : public WasmWalker { - IString target; // look for this one - size_t found; - - BreakSeeker(IString target) : target(target), found(false) {} - - void visitBreak(Break *curr) { - if (curr->name == target) found++; - } - }; - // look for any breaks to this block BreakSeeker breakSeeker(curr->name); Expression *child = curr->list[0]; -- cgit v1.2.3