[asm.js] Fix and test assignment to function imports.

This tests and fixes validation failures caused by assignments to
variables holding functions references (which are all considered
immutable). Such references can come from "stdlib" or "foreign".

R=clemensh@chromium.org
TEST=mjsunit/asm/global-imports
BUG=chromium:719382

Change-Id: Ic02be765e0773a6cc74a54e11a09d42ffb683cb8
Reviewed-on: https://chromium-review.googlesource.com/500188
Reviewed-by: Clemens Hammacher <clemensh@chromium.org>
Commit-Queue: Michael Starzinger <mstarzinger@chromium.org>
Cr-Commit-Position: refs/heads/master@{#45189}
This commit is contained in:
Michael Starzinger 2017-05-09 11:52:34 +02:00 committed by Commit Bot
parent dfddbd2d2a
commit 17d1530d21
2 changed files with 12 additions and 3 deletions

View File

@ -546,6 +546,7 @@ void AsmJsParser::ValidateModuleVarImport(VarInfo* info,
info->kind = VarKind::kImportedFunction;
info->import = new (zone()->New(sizeof(FunctionImportInfo)))
FunctionImportInfo({name, WasmModuleBuilder::SignatureMap(zone())});
info->mutable_variable = false;
}
}
}
@ -1484,6 +1485,9 @@ AsmType* AsmJsParser::AssignmentExpression() {
if (info->kind == VarKind::kUnused) {
FAILn("Undeclared assignment target");
}
if (!info->mutable_variable) {
FAILn("Expected mutable variable in assignment");
}
DCHECK(is_local ? info->kind == VarKind::kLocal
: info->kind == VarKind::kGlobal);
AsmType* value;
@ -1494,9 +1498,6 @@ AsmType* AsmJsParser::AssignmentExpression() {
if (info->kind == VarKind::kLocal) {
current_function_builder_->EmitTeeLocal(info->index);
} else if (info->kind == VarKind::kGlobal) {
if (!info->mutable_variable) {
FAILn("Expected mutable variable in assignment");
}
current_function_builder_->EmitWithU32V(kExprSetGlobal, VarIndex(info));
current_function_builder_->EmitWithU32V(kExprGetGlobal, VarIndex(info));
} else {

View File

@ -21,6 +21,7 @@ var throws = {};
var test_count = 0;
const stdlib = this;
const buffer = new ArrayBuffer(1024);
function p(x) { return x * x; }
function assertThrowsOrEquals(result, fun) {
if (result === throws) {
@ -52,6 +53,7 @@ function Run(imp, exp, imports, result, valid) {
RunAsmJsTest(src, imports, result, valid);
}
// Imports of values from foreign.
Run("var x = foreign.x | 0", "(x + int) | 0", {x:12}, 13, true);
Run("var x = foreign.x | 0", "(x = int) | 0", {x:12}, 1, true);
Run("var x = foreign.x | 0", "+(x + dbl)", {x:12}, 16.2, false);
@ -64,3 +66,9 @@ Run("const x = foreign.x | 0", "+(x + dbl)", {x:12}, 16.2, false);
Run("const x = +foreign.x", "+(x + dbl)", {x:1.2}, 5.4, true);
Run("const x = +foreign.x", "+(x = dbl)", {x:1.2}, throws, false);
Run("const x = +foreign.x", "(x + int) | 0", {x:1.2}, 2, false);
// Imports of functions and values from stdlib and foreign.
Run("var x = foreign.x", "x(dbl) | 0", { x:p }, 17, true);
Run("var x = foreign.x", "(x = fround, x(dbl)) | 0", { x:p }, 4, false);
Run("var x = stdlib.Math.E", "(x = 3.1415, 1) | 0", {}, 1, false);
Run("var x = stdlib.Math.imul", "(x = fround, 1) | 0", {}, 1, false);