Commit f2b9c500 authored by Michael Starzinger's avatar Michael Starzinger Committed by Commit Bot

[asm.js] Fix evaluation of first for-statement expression.

This makes sure that the evaluation result of the first expression in
for-statements is properly dropped, to leave the stack in a balanced
state after the statement. It also makes sure validation failures in
said expression are handled correctly.

R=clemensh@chromium.org
TEST=mjsunit/regress/regress-crbug-721835
BUG=chromium:721835

Change-Id: I7e6cff4cea0bbf5aad6a3459e27a08ea814dbdbe
Reviewed-on: https://chromium-review.googlesource.com/506148
Commit-Queue: Michael Starzinger <mstarzinger@chromium.org>
Reviewed-by: 's avatarClemens Hammacher <clemensh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#45299}
parent 96b09289
...@@ -988,7 +988,7 @@ void AsmJsParser::ValidateFunctionLocals( ...@@ -988,7 +988,7 @@ void AsmJsParser::ValidateFunctionLocals(
} }
} }
// ValidateStatement // 6.5 ValidateStatement
void AsmJsParser::ValidateStatement() { void AsmJsParser::ValidateStatement() {
call_coercion_ = nullptr; call_coercion_ = nullptr;
if (Peek('{')) { if (Peek('{')) {
...@@ -1172,7 +1172,11 @@ void AsmJsParser::ForStatement() { ...@@ -1172,7 +1172,11 @@ void AsmJsParser::ForStatement() {
EXPECT_TOKEN(TOK(for)); EXPECT_TOKEN(TOK(for));
EXPECT_TOKEN('('); EXPECT_TOKEN('(');
if (!Peek(';')) { if (!Peek(';')) {
Expression(nullptr); AsmType* ret;
RECURSE(ret = Expression(nullptr));
if (!ret->IsA(AsmType::Void())) {
current_function_builder_->Emit(kExprDrop);
}
} }
EXPECT_TOKEN(';'); EXPECT_TOKEN(';');
// a: block { // a: block {
...@@ -1198,6 +1202,7 @@ void AsmJsParser::ForStatement() { ...@@ -1198,6 +1202,7 @@ void AsmJsParser::ForStatement() {
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.
} }
current_function_builder_->EmitWithU8(kExprBr, 0); current_function_builder_->EmitWithU8(kExprBr, 0);
scanner_.Seek(end_position); scanner_.Seek(end_position);
......
...@@ -271,10 +271,9 @@ class AsmJsParser { ...@@ -271,10 +271,9 @@ class AsmJsParser {
FunctionSig* ConvertSignature(AsmType* return_type, FunctionSig* ConvertSignature(AsmType* return_type,
const std::vector<AsmType*>& params); const std::vector<AsmType*>& params);
// 6.1 ValidateModule void ValidateModule(); // 6.1 ValidateModule
void ValidateModule(); void ValidateModuleParameters(); // 6.1 ValidateModule - parameters
void ValidateModuleParameters(); void ValidateModuleVars(); // 6.1 ValidateModule - variables
void ValidateModuleVars();
void ValidateModuleVar(bool mutable_variable); void ValidateModuleVar(bool mutable_variable);
void ValidateModuleVarImport(VarInfo* info, bool mutable_variable); void ValidateModuleVarImport(VarInfo* info, bool mutable_variable);
void ValidateModuleVarStdlib(VarInfo* info); void ValidateModuleVarStdlib(VarInfo* info);
...@@ -287,7 +286,7 @@ class AsmJsParser { ...@@ -287,7 +286,7 @@ class AsmJsParser {
void ValidateFunctionParams(std::vector<AsmType*>* params); void ValidateFunctionParams(std::vector<AsmType*>* params);
void ValidateFunctionLocals(size_t param_count, void ValidateFunctionLocals(size_t param_count,
std::vector<ValueType>* locals); std::vector<ValueType>* locals);
void ValidateStatement(); // ValidateStatement void ValidateStatement(); // 6.5 ValidateStatement
void Block(); // 6.5.1 Block void Block(); // 6.5.1 Block
void ExpressionStatement(); // 6.5.2 ExpressionStatement void ExpressionStatement(); // 6.5.2 ExpressionStatement
void EmptyStatement(); // 6.5.3 EmptyStatement void EmptyStatement(); // 6.5.3 EmptyStatement
......
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --validate-asm --allow-natives-syntax
(function TestValidationFailureInForStatement() {
function Module() {
"use asm"
function f() {
var a = 0;
for (a = b; 0; 0) {};
return 0;
}
return { f:f };
}
assertThrows(() => Module().f(), ReferenceError);
assertFalse(%IsAsmWasmCode(Module));
})();
(function TestForStatementInVoidFunction() {
function Module() {
"use asm"
function f() {
for (1; 0; 0) {};
}
return { f:f };
}
assertDoesNotThrow(() => Module().f());
assertTrue(%IsAsmWasmCode(Module));
})();
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