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(
y->AsLiteral() && y->AsLiteral()->raw_value()->IsNumber()) {
double x_val = (*x)->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) {
case Token::ADD:
*x = factory->NewNumberLiteral(x_val + y_val, pos);
*x = factory->NewNumberLiteral(x_val + y_val, pos, has_dot);
return true;
case Token::SUB:
*x = factory->NewNumberLiteral(x_val - y_val, pos);
*x = factory->NewNumberLiteral(x_val - y_val, pos, has_dot);
return true;
case Token::MUL:
*x = factory->NewNumberLiteral(x_val * y_val, pos);
*x = factory->NewNumberLiteral(x_val * y_val, pos, has_dot);
return true;
case Token::DIV:
*x = factory->NewNumberLiteral(x_val / y_val, pos);
*x = factory->NewNumberLiteral(x_val / y_val, pos, has_dot);
return true;
case Token::BIT_OR: {
int value = DoubleToInt32(x_val) | DoubleToInt32(y_val);
*x = factory->NewNumberLiteral(value, pos);
*x = factory->NewNumberLiteral(value, pos, has_dot);
return true;
}
case Token::BIT_AND: {
int value = DoubleToInt32(x_val) & DoubleToInt32(y_val);
*x = factory->NewNumberLiteral(value, pos);
*x = factory->NewNumberLiteral(value, pos, has_dot);
return true;
}
case Token::BIT_XOR: {
int value = DoubleToInt32(x_val) ^ DoubleToInt32(y_val);
*x = factory->NewNumberLiteral(value, pos);
*x = factory->NewNumberLiteral(value, pos, has_dot);
return true;
}
case Token::SHL: {
int value = DoubleToInt32(x_val) << (DoubleToInt32(y_val) & 0x1f);
*x = factory->NewNumberLiteral(value, pos);
*x = factory->NewNumberLiteral(value, pos, has_dot);
return true;
}
case Token::SHR: {
uint32_t shift = DoubleToInt32(y_val) & 0x1f;
uint32_t value = DoubleToUint32(x_val) >> shift;
*x = factory->NewNumberLiteral(value, pos);
*x = factory->NewNumberLiteral(value, pos, has_dot);
return true;
}
case Token::SAR: {
uint32_t shift = DoubleToInt32(y_val) & 0x1f;
int value = ArithmeticShiftRight(DoubleToInt32(x_val), shift);
*x = factory->NewNumberLiteral(value, pos);
*x = factory->NewNumberLiteral(value, pos, has_dot);
return true;
}
default:
......@@ -617,13 +620,14 @@ Expression* ParserTraits::BuildUnaryExpression(Expression* expression,
} else if (literal->IsNumber()) {
// Compute some expressions involving only number literals.
double value = literal->AsNumber();
bool has_dot = literal->ContainsDot();
switch (op) {
case Token::ADD:
return expression;
case Token::SUB:
return factory->NewNumberLiteral(-value, pos);
return factory->NewNumberLiteral(-value, pos, has_dot);
case Token::BIT_NOT:
return factory->NewNumberLiteral(~DoubleToInt32(value), pos);
return factory->NewNumberLiteral(~DoubleToInt32(value), pos, has_dot);
default:
break;
}
......
......@@ -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) {
v8::V8::Initialize();
TypeCache cache;
......
......@@ -1151,12 +1151,23 @@ static void CheckParsesToNumber(const char* source, bool with_dot) {
TEST(ParseNumbers) {
CheckParsesToNumber("1.", true);
CheckParsesToNumber("1.34", true);
CheckParsesToNumber("134", false);
CheckParsesToNumber("134e44", false);
CheckParsesToNumber("134.e44", true);
CheckParsesToNumber("134.44e44", 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);
}
......
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