Commit 1e4681c3 authored by bradnelson's avatar bradnelson Committed by Commit bot

Preserve information about dots in numbers across parser rewriting.

Fix several operations in the parser that rewrite constant expressions
to preserve knowledge regarding whether a value originally contained a ".".
This information is required to accurately validate Asm.js typing.

Making the assumption that if either side of a binary operation contains
a dot, that the rewritten expression should be treated as a double for
Asm.js purposes. This is a slight deviation from the spec (which
would forbid mix type operations).

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

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

Cr-Commit-Position: refs/heads/master@{#32581}
parent 46a93665
...@@ -551,49 +551,52 @@ bool ParserTraits::ShortcutNumericLiteralBinaryExpression( ...@@ -551,49 +551,52 @@ bool ParserTraits::ShortcutNumericLiteralBinaryExpression(
y->AsLiteral() && y->AsLiteral()->raw_value()->IsNumber()) { y->AsLiteral() && y->AsLiteral()->raw_value()->IsNumber()) {
double x_val = (*x)->AsLiteral()->raw_value()->AsNumber(); double x_val = (*x)->AsLiteral()->raw_value()->AsNumber();
double y_val = y->AsLiteral()->raw_value()->AsNumber(); double y_val = y->AsLiteral()->raw_value()->AsNumber();
bool x_has_dot = (*x)->AsLiteral()->raw_value()->ContainsDot();
bool y_has_dot = y->AsLiteral()->raw_value()->ContainsDot();
bool has_dot = x_has_dot || y_has_dot;
switch (op) { switch (op) {
case Token::ADD: case Token::ADD:
*x = factory->NewNumberLiteral(x_val + y_val, pos); *x = factory->NewNumberLiteral(x_val + y_val, pos, has_dot);
return true; return true;
case Token::SUB: case Token::SUB:
*x = factory->NewNumberLiteral(x_val - y_val, pos); *x = factory->NewNumberLiteral(x_val - y_val, pos, has_dot);
return true; return true;
case Token::MUL: case Token::MUL:
*x = factory->NewNumberLiteral(x_val * y_val, pos); *x = factory->NewNumberLiteral(x_val * y_val, pos, has_dot);
return true; return true;
case Token::DIV: case Token::DIV:
*x = factory->NewNumberLiteral(x_val / y_val, pos); *x = factory->NewNumberLiteral(x_val / y_val, pos, has_dot);
return true; return true;
case Token::BIT_OR: { case Token::BIT_OR: {
int value = DoubleToInt32(x_val) | DoubleToInt32(y_val); int value = DoubleToInt32(x_val) | DoubleToInt32(y_val);
*x = factory->NewNumberLiteral(value, pos); *x = factory->NewNumberLiteral(value, pos, has_dot);
return true; return true;
} }
case Token::BIT_AND: { case Token::BIT_AND: {
int value = DoubleToInt32(x_val) & DoubleToInt32(y_val); int value = DoubleToInt32(x_val) & DoubleToInt32(y_val);
*x = factory->NewNumberLiteral(value, pos); *x = factory->NewNumberLiteral(value, pos, has_dot);
return true; return true;
} }
case Token::BIT_XOR: { case Token::BIT_XOR: {
int value = DoubleToInt32(x_val) ^ DoubleToInt32(y_val); int value = DoubleToInt32(x_val) ^ DoubleToInt32(y_val);
*x = factory->NewNumberLiteral(value, pos); *x = factory->NewNumberLiteral(value, pos, has_dot);
return true; return true;
} }
case Token::SHL: { case Token::SHL: {
int value = DoubleToInt32(x_val) << (DoubleToInt32(y_val) & 0x1f); int value = DoubleToInt32(x_val) << (DoubleToInt32(y_val) & 0x1f);
*x = factory->NewNumberLiteral(value, pos); *x = factory->NewNumberLiteral(value, pos, has_dot);
return true; return true;
} }
case Token::SHR: { case Token::SHR: {
uint32_t shift = DoubleToInt32(y_val) & 0x1f; uint32_t shift = DoubleToInt32(y_val) & 0x1f;
uint32_t value = DoubleToUint32(x_val) >> shift; uint32_t value = DoubleToUint32(x_val) >> shift;
*x = factory->NewNumberLiteral(value, pos); *x = factory->NewNumberLiteral(value, pos, has_dot);
return true; return true;
} }
case Token::SAR: { case Token::SAR: {
uint32_t shift = DoubleToInt32(y_val) & 0x1f; uint32_t shift = DoubleToInt32(y_val) & 0x1f;
int value = ArithmeticShiftRight(DoubleToInt32(x_val), shift); int value = ArithmeticShiftRight(DoubleToInt32(x_val), shift);
*x = factory->NewNumberLiteral(value, pos); *x = factory->NewNumberLiteral(value, pos, has_dot);
return true; return true;
} }
default: default:
...@@ -617,13 +620,14 @@ Expression* ParserTraits::BuildUnaryExpression(Expression* expression, ...@@ -617,13 +620,14 @@ Expression* ParserTraits::BuildUnaryExpression(Expression* expression,
} else if (literal->IsNumber()) { } else if (literal->IsNumber()) {
// Compute some expressions involving only number literals. // Compute some expressions involving only number literals.
double value = literal->AsNumber(); double value = literal->AsNumber();
bool has_dot = literal->ContainsDot();
switch (op) { switch (op) {
case Token::ADD: case Token::ADD:
return expression; return expression;
case Token::SUB: case Token::SUB:
return factory->NewNumberLiteral(-value, pos); return factory->NewNumberLiteral(-value, pos, has_dot);
case Token::BIT_NOT: case Token::BIT_NOT:
return factory->NewNumberLiteral(~DoubleToInt32(value), pos); return factory->NewNumberLiteral(~DoubleToInt32(value), pos, has_dot);
default: default:
break; break;
} }
......
...@@ -1785,6 +1785,38 @@ TEST(NestedAssignmentInHeap) { ...@@ -1785,6 +1785,38 @@ TEST(NestedAssignmentInHeap) {
} }
TEST(NegativeDouble) {
CHECK_FUNC_TYPES_BEGIN(
"function bar() { var x = -123.2; }\n"
"function foo() { bar(); }") {
CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) {
CHECK_EXPR(Assignment, Bounds(cache.kAsmDouble)) {
CHECK_VAR(x, Bounds(cache.kAsmDouble));
CHECK_EXPR(Literal, Bounds(cache.kAsmDouble));
}
}
CHECK_SKIP();
}
CHECK_FUNC_TYPES_END
}
TEST(NegativeInteger) {
CHECK_FUNC_TYPES_BEGIN(
"function bar() { var x = -123; }\n"
"function foo() { bar(); }") {
CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) {
CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) {
CHECK_VAR(x, Bounds(cache.kAsmInt));
CHECK_EXPR(Literal, Bounds(cache.kAsmSigned));
}
}
CHECK_SKIP();
}
CHECK_FUNC_TYPES_END
}
TEST(TypeConsistency) { TEST(TypeConsistency) {
v8::V8::Initialize(); v8::V8::Initialize();
TypeCache cache; TypeCache cache;
......
...@@ -1151,12 +1151,23 @@ static void CheckParsesToNumber(const char* source, bool with_dot) { ...@@ -1151,12 +1151,23 @@ static void CheckParsesToNumber(const char* source, bool with_dot) {
TEST(ParseNumbers) { TEST(ParseNumbers) {
CheckParsesToNumber("1.", true);
CheckParsesToNumber("1.34", true); CheckParsesToNumber("1.34", true);
CheckParsesToNumber("134", false); CheckParsesToNumber("134", false);
CheckParsesToNumber("134e44", false); CheckParsesToNumber("134e44", false);
CheckParsesToNumber("134.e44", true); CheckParsesToNumber("134.e44", true);
CheckParsesToNumber("134.44e44", true); CheckParsesToNumber("134.44e44", true);
CheckParsesToNumber(".44", true); CheckParsesToNumber(".44", true);
CheckParsesToNumber("-1.", true);
CheckParsesToNumber("-1.0", true);
CheckParsesToNumber("-1.34", true);
CheckParsesToNumber("-134", false);
CheckParsesToNumber("-134e44", false);
CheckParsesToNumber("-134.e44", true);
CheckParsesToNumber("-134.44e44", true);
CheckParsesToNumber("-.44", true);
CheckParsesToNumber("+x", true); CheckParsesToNumber("+x", true);
} }
......
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