Commit 9a241228 authored by Clemens Hammacher's avatar Clemens Hammacher Committed by Commit Bot

[asm.js] Fix continue target in for loops

Make sure that a continue still executed the increment part of a for
loop by adding another nested block for the body, which is the break
target for a continue in the body. The increment code lives outside
this block, in the original loop.

R=bradnelson@chromium.org
CC=mstarzinger@chromium.org

Bug: chromium:788916
Change-Id: I178b874ffac16d9237a0f4da097d2742bd93335a
Reviewed-on: https://chromium-review.googlesource.com/832447
Commit-Queue: Brad Nelson <bradnelson@chromium.org>
Reviewed-by: 's avatarBrad Nelson <bradnelson@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50169}
parent c9d88eed
......@@ -1164,18 +1164,18 @@ void AsmJsParser::DoStatement() {
RECURSE(ValidateStatement());
EXPECT_TOKEN(TOK(while));
End();
// }
// } // end c
EXPECT_TOKEN('(');
RECURSE(Expression(AsmType::Int()));
// if (CONDITION) break a;
// if (!CONDITION) break a;
current_function_builder_->Emit(kExprI32Eqz);
current_function_builder_->EmitWithU8(kExprBrIf, 1);
// continue b;
current_function_builder_->EmitWithU8(kExprBr, 0);
EXPECT_TOKEN(')');
// }
// } // end b
End();
// }
// } // end a
End();
SkipSemicolon();
}
......@@ -1195,13 +1195,16 @@ void AsmJsParser::ForStatement() {
// a: block {
Begin(pending_label_);
// b: loop {
Loop(pending_label_);
Loop();
// c: block { // but treated like loop so continue works
BareBegin(BlockKind::kLoop, pending_label_);
current_function_builder_->EmitWithU8(kExprBlock, kLocalVoid);
pending_label_ = 0;
if (!Peek(';')) {
// if (CONDITION) break a;
// if (!CONDITION) break a;
RECURSE(Expression(AsmType::Int()));
current_function_builder_->Emit(kExprI32Eqz);
current_function_builder_->EmitWithU8(kExprBrIf, 1);
current_function_builder_->EmitWithU8(kExprBrIf, 2);
}
EXPECT_TOKEN(';');
// Race past INCREMENT
......@@ -1210,18 +1213,21 @@ void AsmJsParser::ForStatement() {
EXPECT_TOKEN(')');
// BODY
RECURSE(ValidateStatement());
// INCREMENT
// } // end c
End();
// INCREMENT
size_t end_position = scanner_.Position();
scanner_.Seek(increment_position);
if (!Peek(')')) {
RECURSE(Expression(nullptr));
// NOTE: No explicit drop because below break is an implicit drop.
}
// continue b;
current_function_builder_->EmitWithU8(kExprBr, 0);
scanner_.Seek(end_position);
// }
// } // end b
End();
// }
// } // end a
End();
}
......
......@@ -7,7 +7,7 @@
var stdlib = this;
function assertValidAsm(func) {
assertTrue(%IsAsmWasmCode(func));
assertTrue(%IsAsmWasmCode(func), "must be valid asm code");
}
function assertWasm(expected, func, ffi) {
......@@ -426,6 +426,23 @@ function TestContinueInDoWhileFalse() {
assertWasm(47, TestContinueInDoWhileFalse);
function TestContinueInForLoop() {
"use asm";
function caller() {
var i = 0;
for (; (i|0) < 10; i = (i+1)|0) {
continue;
}
return 4711;
}
return {caller: caller};
}
assertWasm(4711, TestContinueInForLoop);
function TestNot() {
"use asm";
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment