Allow constant multiply both ways.

asm.js permits both:
int * constant
constant * int

It does not, however, allow intishes in multiplies.

BUG= https://code.google.com/p/v8/issues/detail?id=4203
TEST=mjsunit/asm-wasm,test-asm-validator
R=aseemgarg@chromium.org,titzer@chromium.org
LOG=N

Review URL: https://codereview.chromium.org/1718083004

Cr-Commit-Position: refs/heads/master@{#34222}
This commit is contained in:
bradnelson 2016-02-23 11:03:50 -08:00 committed by Commit bot
parent 943650784a
commit 0dd24015fb
4 changed files with 59 additions and 18 deletions

View File

@ -690,7 +690,7 @@ void AsmTyper::VisitAssignment(Assignment* expr) {
expected_type_ = target_type;
VisitVariableProxy(expr->target()->AsVariableProxy(), true);
} else if (expr->target()->IsProperty()) {
int value_intish = intish_;
int32_t value_intish = intish_;
Property* property = expr->target()->AsProperty();
RECURSE(VisitWithExpectation(property->obj(), Type::Any(),
"bad propety object"));
@ -1083,7 +1083,7 @@ void AsmTyper::VisitIntegerBitwiseOperator(BinaryOperation* expr,
Type* result_type, bool conversion) {
RECURSE(VisitWithExpectation(expr->left(), Type::Number(),
"left bitwise operand expected to be a number"));
int left_intish = intish_;
int32_t left_intish = intish_;
Type* left_type = computed_type_;
if (!left_type->Is(left_expected)) {
FAIL(expr->left(), "left bitwise operand expected to be an integer");
@ -1095,7 +1095,7 @@ void AsmTyper::VisitIntegerBitwiseOperator(BinaryOperation* expr,
RECURSE(
VisitWithExpectation(expr->right(), Type::Number(),
"right bitwise operand expected to be a number"));
int right_intish = intish_;
int32_t right_intish = intish_;
Type* right_type = computed_type_;
if (!right_type->Is(right_expected)) {
FAIL(expr->right(), "right bitwise operand expected to be an integer");
@ -1204,28 +1204,33 @@ void AsmTyper::VisitBinaryOperation(BinaryOperation* expr) {
expr->left(), Type::Number(),
"left arithmetic operand expected to be number"));
Type* left_type = computed_type_;
int left_intish = intish_;
int32_t left_intish = intish_;
RECURSE(VisitWithExpectation(
expr->right(), Type::Number(),
"right arithmetic operand expected to be number"));
Type* right_type = computed_type_;
int right_intish = intish_;
int32_t right_intish = intish_;
Type* type = Type::Union(left_type, right_type, zone());
if (type->Is(cache_.kAsmInt)) {
if (expr->op() == Token::MUL) {
Literal* right = expr->right()->AsLiteral();
if (!right) {
FAIL(expr, "direct integer multiply forbidden");
}
if (!right->value()->IsNumber()) {
FAIL(expr, "multiply must be by an integer");
}
int32_t i;
if (!right->value()->ToInt32(&i)) {
FAIL(expr, "multiply must be a signed integer");
Literal* left = expr->left()->AsLiteral();
Literal* right = expr->right()->AsLiteral();
if (left != nullptr && left->value()->IsNumber() &&
left->value()->ToInt32(&i)) {
if (right_intish != 0) {
FAIL(expr, "intish not allowed in multiply");
}
} else if (right != nullptr && right->value()->IsNumber() &&
right->value()->ToInt32(&i)) {
if (left_intish != 0) {
FAIL(expr, "intish not allowed in multiply");
}
} else {
FAIL(expr, "multiply must be by an integer literal");
}
i = abs(i);
if (i >= 1 << 20) {
if (i >= (1 << 20)) {
FAIL(expr, "multiply must be by value in -2^20 < n < 2^20");
}
intish_ = i;

View File

@ -92,7 +92,7 @@ class AsmTyper : public AstVisitor {
Type* expected_type_;
Type* computed_type_;
VariableInfo* property_info_;
int intish_; // How many ops we've gone without a x|0.
int32_t intish_; // How many ops we've gone without a x|0.
Type* return_type_; // Return type of last function.
size_t array_size_; // Array size of last ArrayLiteral.

View File

@ -1171,6 +1171,12 @@ TEST(TernaryBadCondition) {
"asm: line 39: condition must be of type int\n");
}
TEST(BadIntishMultiply) {
CHECK_FUNC_ERROR(
"function bar() { var x = 1; return ((x + x) * 4) | 0; }\n"
"function foo() { bar(); }",
"asm: line 39: intish not allowed in multiply\n");
}
TEST(FroundFloat32) {
CHECK_FUNC_TYPES_BEGIN(
@ -1229,7 +1235,7 @@ TEST(Multiplication2) {
CHECK_FUNC_ERROR(
"function bar() { var x = 1; var y = 2; return (x*y)|0; }\n"
"function foo() { bar(); }",
"asm: line 39: direct integer multiply forbidden\n");
"asm: line 39: multiply must be by an integer literal\n");
}

View File

@ -1441,4 +1441,34 @@ TestForeignVariables();
var m = _WASMEXP_.instantiateModuleFromAsm(Module.toString());
assertEquals(3, m.func());
}) // TODO(bradnelson): Enable when Math.fround implementation lands.
}); // TODO(bradnelson): Enable when Math.fround implementation lands.
(function TestIntegerMultiplyBothWays() {
function Module(stdlib, foreign, heap) {
"use asm";
function func() {
var a = 1;
return ((a * 3) + (4 * a)) | 0;
}
return {func: func};
}
var m = _WASMEXP_.instantiateModuleFromAsm(Module.toString());
assertEquals(7, m.func());
})();
(function TestBadMultiplyIntish() {
function Module(stdlib, foreign, heap) {
"use asm";
function func() {
var a = 1;
return ((a + a) * 4) | 0;
}
return {func: func};
}
assertThrows(function() {
_WASMEXP_.instantiateModuleFromAsm(Module.toString());
});
})();