Reviewers: rossberg, titzer,
Message:
Two questions:
* Should I plumb through the dot detection deeper into StringToDouble. I'm
unsure how much to lean on the compiler to do good things?
* Is there a more compact pattern to test this with?
Description:
Allow numeric literals to be checked for a decimal point.
The asm.js spec decides the type of numeric literals in several places
based on if they contain a ".".
http://asmjs.org/spec/latest/
Adding methods so that AST Literals can be checked for containg a dot.
Adding a cctest that this information is available.
LOG=N
BUG= https://code.google.com/p/v8/issues/detail?id=4203
TEST=test-parsing
[email protected],[email protected]
Please review this at https://codereview.chromium.org/1201783003/
Base URL: https://chromium.googlesource.com/v8/v8.git@master
Affected files (+87, -8 lines):
M src/ast.h
M src/ast-value-factory.h
M src/ast-value-factory.cc
M src/parser.cc
M src/scanner.h
M src/scanner.cc
M test/cctest/test-parsing.cc
Index: src/ast-value-factory.cc
diff --git a/src/ast-value-factory.cc b/src/ast-value-factory.cc
index
a819483eccbc417ea76e5e687dc59a3f304461d9..1634a54451118087d9d36396b9eb0de97002696b
100644
--- a/src/ast-value-factory.cc
+++ b/src/ast-value-factory.cc
@@ -140,6 +140,7 @@ bool AstValue::BooleanValue() const {
case SYMBOL:
UNREACHABLE();
break;
+ case NUMBER_WITH_DOT:
case NUMBER:
return DoubleToBoolean(number_);
case SMI:
@@ -175,6 +176,7 @@ void AstValue::Internalize(Isolate* isolate) {
value_ = isolate->factory()->home_object_symbol();
}
break;
+ case NUMBER_WITH_DOT:
case NUMBER:
value_ = isolate->factory()->NewNumber(number_, TENURED);
break;
@@ -290,8 +292,11 @@ const AstValue* AstValueFactory::NewSymbol(const char*
name) {
}
-const AstValue* AstValueFactory::NewNumber(double number) {
+const AstValue* AstValueFactory::NewNumber(double number, bool with_dot) {
AstValue* value = new (zone_) AstValue(number);
+ if (with_dot) {
+ value->MarkWithDot();
+ }
if (isolate_) {
value->Internalize(isolate_);
}
Index: src/ast-value-factory.h
diff --git a/src/ast-value-factory.h b/src/ast-value-factory.h
index
dd575e26abe337585351d96cbfddced2961cb23b..1b435f33eb57b12c446876c23b51582467d5ccc5
100644
--- a/src/ast-value-factory.h
+++ b/src/ast-value-factory.h
@@ -142,9 +142,11 @@ class AstValue : public ZoneObject {
}
bool IsNumber() const {
- return type_ == NUMBER || type_ == SMI;
+ return type_ == NUMBER || type_ == NUMBER_WITH_DOT || type_ == SMI;
}
+ bool ContainsDot() const { return type_ == NUMBER_WITH_DOT; }
+
const AstRawString* AsString() const {
if (type_ == STRING)
return string_;
@@ -153,8 +155,7 @@ class AstValue : public ZoneObject {
}
double AsNumber() const {
- if (type_ == NUMBER)
- return number_;
+ if (type_ == NUMBER || type_ == NUMBER_WITH_DOT) return number_;
if (type_ == SMI)
return smi_;
UNREACHABLE();
@@ -189,6 +190,7 @@ class AstValue : public ZoneObject {
STRING,
SYMBOL,
NUMBER,
+ NUMBER_WITH_DOT,
SMI,
BOOLEAN,
NULL_TYPE,
@@ -213,6 +215,11 @@ class AstValue : public ZoneObject {
DCHECK(t == NULL_TYPE || t == UNDEFINED || t == THE_HOLE);
}
+ void MarkWithDot() {
+ DCHECK(type_ == NUMBER);
+ type_ = NUMBER_WITH_DOT;
+ }
+
Type type_;
// Uninternalized value.
@@ -334,7 +341,7 @@ class AstValueFactory {
const AstValue* NewString(const AstRawString* string);
// A JavaScript symbol (ECMA-262 edition 6).
const AstValue* NewSymbol(const char* name);
- const AstValue* NewNumber(double number);
+ const AstValue* NewNumber(double number, bool with_dot = false);
const AstValue* NewSmi(int number);
const AstValue* NewBoolean(bool b);
const AstValue* NewStringList(ZoneList<const AstRawString*>* strings);
Index: src/ast.h
diff --git a/src/ast.h b/src/ast.h
index
3a3d896262b14ddb04b0f7664d895691ff94aff0..3f848aeaa43bb5cce5cf466a54aefb5b73bb75e8
100644
--- a/src/ast.h
+++ b/src/ast.h
@@ -3372,9 +3372,9 @@ class AstNodeFactory final BASE_EMBEDDED {
return new (zone_) Literal(zone_, ast_value_factory_->NewSymbol(name),
pos);
}
- Literal* NewNumberLiteral(double number, int pos) {
+ Literal* NewNumberLiteral(double number, int pos, bool with_dot = false)
{
return new (zone_)
- Literal(zone_, ast_value_factory_->NewNumber(number), pos);
+ Literal(zone_, ast_value_factory_->NewNumber(number, with_dot),
pos);
}
Literal* NewSmiLiteral(int number, int pos) {
Index: src/parser.cc
diff --git a/src/parser.cc b/src/parser.cc
index
7e0d9366116f3b8bd7619a78ceb39e6a6901cd1e..cbe1da86ec1865fb0be078ffa915e402d3f67fbc
100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -816,8 +816,9 @@ Literal*
ParserTraits::ExpressionFromLiteral(Token::Value token, int pos,
return factory->NewSmiLiteral(value, pos);
}
case Token::NUMBER: {
+ bool has_dot = scanner->ContainsDot();
double value = scanner->DoubleValue();
- return factory->NewNumberLiteral(value, pos);
+ return factory->NewNumberLiteral(value, pos, has_dot);
}
default:
DCHECK(false);
Index: src/scanner.cc
diff --git a/src/scanner.cc b/src/scanner.cc
index
a2ca30a9be5df0b08eede51835eb506ff78752a1..55a3ab181ad01eb12a8c697d4da24d1bcd90444a
100644
--- a/src/scanner.cc
+++ b/src/scanner.cc
@@ -1433,6 +1433,17 @@ double Scanner::DoubleValue() {
}
+bool Scanner::ContainsDot() {
+ DCHECK(is_literal_one_byte());
+ Vector<const uint8_t> literal_string = literal_one_byte_string();
+ bool with_dot = false;
+ for (int i = 0; !with_dot && i < literal_string.length(); ++i) {
+ with_dot |= (literal_string[i] == '.');
+ }
+ return with_dot;
+}
+
+
int Scanner::FindSymbol(DuplicateFinder* finder, int value) {
if (is_literal_one_byte()) {
return finder->AddOneByteSymbol(literal_one_byte_string(), value);
Index: src/scanner.h
diff --git a/src/scanner.h b/src/scanner.h
index
f387d84133f984ff5183b6b802d65cf5cb3293bb..bfb548313c946e21714e054509ec260160ade932
100644
--- a/src/scanner.h
+++ b/src/scanner.h
@@ -435,6 +435,7 @@ class Scanner {
const AstRawString* CurrentRawSymbol(AstValueFactory* ast_value_factory);
double DoubleValue();
+ bool ContainsDot();
bool LiteralMatches(const char* data, int length, bool allow_escapes =
true) {
if (is_literal_one_byte() &&
literal_length() == length &&
Index: test/cctest/test-parsing.cc
diff --git a/test/cctest/test-parsing.cc b/test/cctest/test-parsing.cc
index
675b48797952dbaf3e0afd23b933c61651ea1998..ff4d529d523740d34e742b6338c157eebb192a54
100644
--- a/test/cctest/test-parsing.cc
+++ b/test/cctest/test-parsing.cc
@@ -1101,6 +1101,60 @@ TEST(ScopeUsesArgumentsSuperThis) {
}
+static void CheckParsesToNumber(const char* source, bool with_dot) {
+ v8::V8::Initialize();
+ HandleAndZoneScope handles;
+
+ i::Isolate* isolate = CcTest::i_isolate();
+ i::Factory* factory = isolate->factory();
+
+ std::string full_source = "function f() { return ";
+ full_source += source;
+ full_source += "; }";
+
+ i::Handle<i::String> source_code =
+ factory->NewStringFromUtf8(i::CStrVector(full_source.c_str()))
+ .ToHandleChecked();
+
+ i::Handle<i::Script> script = factory->NewScript(source_code);
+
+ i::ParseInfo info(handles.main_zone(), script);
+ i::Parser parser(&info);
+ parser.set_allow_harmony_classes(true);
+ parser.set_allow_harmony_object_literals(true);
+ parser.set_allow_harmony_arrow_functions(true);
+ parser.set_allow_harmony_sloppy(true);
+ info.set_global();
+ info.set_lazy(false);
+ info.set_allow_lazy_parsing(false);
+ info.set_toplevel(true);
+
+ i::CompilationInfo compilation_info(&info);
+ CHECK(i::Compiler::ParseAndAnalyze(&info));
+
+ CHECK(info.scope()->declarations()->length() == 1);
+ i::FunctionLiteral* fun =
+ info.scope()->declarations()->at(0)->AsFunctionDeclaration()->fun();
+ CHECK(fun->body()->length() == 1);
+ CHECK(fun->body()->at(0)->IsReturnStatement());
+ i::ReturnStatement* ret = fun->body()->at(0)->AsReturnStatement();
+ CHECK(ret->expression()->IsLiteral());
+ i::Literal* lit = ret->expression()->AsLiteral();
+ const i::AstValue* val = lit->raw_value();
+ CHECK(with_dot == val->ContainsDot());
+}
+
+
+TEST(ParseNumbers) {
+ CheckParsesToNumber("1.34", true);
+ CheckParsesToNumber("134", false);
+ CheckParsesToNumber("134e44", false);
+ CheckParsesToNumber("134.e44", true);
+ CheckParsesToNumber("134.44e44", true);
+ CheckParsesToNumber(".44", true);
+}
+
+
TEST(ScopePositions) {
// Test the parser for correctly setting the start and end positions
// of a scope. We check the scope positions of exactly one scope
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.