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() { ...@@ -1164,18 +1164,18 @@ void AsmJsParser::DoStatement() {
RECURSE(ValidateStatement()); RECURSE(ValidateStatement());
EXPECT_TOKEN(TOK(while)); EXPECT_TOKEN(TOK(while));
End(); End();
// } // } // end c
EXPECT_TOKEN('('); EXPECT_TOKEN('(');
RECURSE(Expression(AsmType::Int())); RECURSE(Expression(AsmType::Int()));
// if (CONDITION) break a; // if (!CONDITION) break a;
current_function_builder_->Emit(kExprI32Eqz); current_function_builder_->Emit(kExprI32Eqz);
current_function_builder_->EmitWithU8(kExprBrIf, 1); current_function_builder_->EmitWithU8(kExprBrIf, 1);
// continue b; // continue b;
current_function_builder_->EmitWithU8(kExprBr, 0); current_function_builder_->EmitWithU8(kExprBr, 0);
EXPECT_TOKEN(')'); EXPECT_TOKEN(')');
// } // } // end b
End(); End();
// } // } // end a
End(); End();
SkipSemicolon(); SkipSemicolon();
} }
...@@ -1195,13 +1195,16 @@ void AsmJsParser::ForStatement() { ...@@ -1195,13 +1195,16 @@ void AsmJsParser::ForStatement() {
// a: block { // a: block {
Begin(pending_label_); Begin(pending_label_);
// b: loop { // 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; pending_label_ = 0;
if (!Peek(';')) { if (!Peek(';')) {
// if (CONDITION) break a; // if (!CONDITION) break a;
RECURSE(Expression(AsmType::Int())); RECURSE(Expression(AsmType::Int()));
current_function_builder_->Emit(kExprI32Eqz); current_function_builder_->Emit(kExprI32Eqz);
current_function_builder_->EmitWithU8(kExprBrIf, 1); current_function_builder_->EmitWithU8(kExprBrIf, 2);
} }
EXPECT_TOKEN(';'); EXPECT_TOKEN(';');
// Race past INCREMENT // Race past INCREMENT
...@@ -1210,18 +1213,21 @@ void AsmJsParser::ForStatement() { ...@@ -1210,18 +1213,21 @@ void AsmJsParser::ForStatement() {
EXPECT_TOKEN(')'); EXPECT_TOKEN(')');
// BODY // BODY
RECURSE(ValidateStatement()); RECURSE(ValidateStatement());
// INCREMENT // } // end c
End();
// INCREMENT
size_t end_position = scanner_.Position(); size_t end_position = scanner_.Position();
scanner_.Seek(increment_position); scanner_.Seek(increment_position);
if (!Peek(')')) { if (!Peek(')')) {
RECURSE(Expression(nullptr)); RECURSE(Expression(nullptr));
// NOTE: No explicit drop because below break is an implicit drop. // NOTE: No explicit drop because below break is an implicit drop.
} }
// continue b;
current_function_builder_->EmitWithU8(kExprBr, 0); current_function_builder_->EmitWithU8(kExprBr, 0);
scanner_.Seek(end_position); scanner_.Seek(end_position);
// } // } // end b
End(); End();
// } // } // end a
End(); End();
} }
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
var stdlib = this; var stdlib = this;
function assertValidAsm(func) { function assertValidAsm(func) {
assertTrue(%IsAsmWasmCode(func)); assertTrue(%IsAsmWasmCode(func), "must be valid asm code");
} }
function assertWasm(expected, func, ffi) { function assertWasm(expected, func, ffi) {
...@@ -426,6 +426,23 @@ function TestContinueInDoWhileFalse() { ...@@ -426,6 +426,23 @@ function TestContinueInDoWhileFalse() {
assertWasm(47, 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() { function TestNot() {
"use asm"; "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