[wasm] asm.js: Work around parser converting !0 and !1 to boolean.

!0 -> true and !1 -> false etc in the parser.
This clashes with some of the typing logic in asm.js,
and can show up in some real programs in the wild (at least in past asm.js
versions).

BUG= https://bugs.chromium.org/p/v8/issues/detail?id=4203
R=aseemgarg@chromium.org,jpp@chromium.org

Review-Url: https://codereview.chromium.org/2372823004
Cr-Commit-Position: refs/heads/master@{#39798}
This commit is contained in:
bradnelson 2016-09-27 16:19:59 -07:00 committed by Commit bot
parent 7beb149f47
commit 53b228239e
3 changed files with 53 additions and 1 deletions

View File

@ -1664,6 +1664,12 @@ AsmType* AsmTyper::ValidateNumericLiteral(Literal* literal) {
return AsmType::Double();
}
// The parser collapses expressions like !0 and !123 to true/false.
// We therefore need to permit these as alternate versions of 0 / 1.
if (literal->raw_value()->IsTrue() || literal->raw_value()->IsFalse()) {
return AsmType::Int();
}
uint32_t value;
if (!literal->value()->ToUint32(&value)) {
int32_t value;

View File

@ -589,7 +589,9 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
void VisitLiteral(Literal* expr) {
Handle<Object> value = expr->value();
if (!value->IsNumber() || (scope_ != kFuncScope && scope_ != kInitScope)) {
if (!(value->IsNumber() || expr->raw_value()->IsTrue() ||
expr->raw_value()->IsFalse()) ||
(scope_ != kFuncScope && scope_ != kInitScope)) {
return;
}
AsmType* type = typer_->TypeOf(expr);
@ -610,6 +612,18 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
int32_t i = static_cast<int32_t>(u);
byte code[] = {WASM_I32V(i)};
current_function_builder_->EmitCode(code, sizeof(code));
} else if (type->IsA(AsmType::Int())) {
// The parser can collapse !0, !1 etc to true / false.
// Allow these as int literals.
if (expr->raw_value()->IsTrue()) {
byte code[] = {WASM_I32V(1)};
current_function_builder_->EmitCode(code, sizeof(code));
} else if (expr->raw_value()->IsFalse()) {
byte code[] = {WASM_I32V(0)};
current_function_builder_->EmitCode(code, sizeof(code));
} else {
UNREACHABLE();
}
} else if (type->IsA(AsmType::Double())) {
double val = expr->raw_value()->AsNumber();
byte code[] = {WASM_F64(val)};

View File

@ -1596,3 +1596,35 @@ function TestSingleFunctionModule() {
}
assertEquals(7, TestSingleFunctionModule()(3, 4));
function TestNotZero() {
"use asm";
function caller() {
if (!0) {
return 44;
} else {
return 55;
}
return 0;
}
return {caller: caller};
}
assertWasm(44, TestNotZero);
function TestNotOne() {
"use asm";
function caller() {
if (!1) {
return 44;
} else {
return 55;
}
return 0;
}
return {caller: caller};
}
assertWasm(55, TestNotOne);