| Index: src/parser.cc
|
| ===================================================================
|
| --- src/parser.cc (revision 6941)
|
| +++ src/parser.cc (working copy)
|
| @@ -324,22 +324,26 @@
|
| }
|
|
|
|
|
| -Handle<String> Parser::LookupSymbol(int symbol_id,
|
| - Vector<const char> string) {
|
| +Handle<String> Parser::LookupSymbol(int symbol_id) {
|
| // Length of symbol cache is the number of identified symbols.
|
| // If we are larger than that, or negative, it's not a cached symbol.
|
| // This might also happen if there is no preparser symbol data, even
|
| // if there is some preparser data.
|
| if (static_cast<unsigned>(symbol_id)
|
| >= static_cast<unsigned>(symbol_cache_.length())) {
|
| - return isolate()->factory()->LookupSymbol(string);
|
| + if (scanner().is_literal_ascii()) {
|
| + return isolate()->factory()->LookupAsciiSymbol(
|
| + scanner().literal_ascii_string());
|
| + } else {
|
| + return isolate()->factory()->LookupTwoByteSymbol(
|
| + scanner().literal_uc16_string());
|
| + }
|
| }
|
| - return LookupCachedSymbol(symbol_id, string);
|
| + return LookupCachedSymbol(symbol_id);
|
| }
|
|
|
|
|
| -Handle<String> Parser::LookupCachedSymbol(int symbol_id,
|
| - Vector<const char> string) {
|
| +Handle<String> Parser::LookupCachedSymbol(int symbol_id) {
|
| // Make sure the cache is large enough to hold the symbol identifier.
|
| if (symbol_cache_.length() <= symbol_id) {
|
| // Increase length to index + 1.
|
| @@ -348,7 +352,13 @@
|
| }
|
| Handle<String> result = symbol_cache_.at(symbol_id);
|
| if (result.is_null()) {
|
| - result = isolate()->factory()->LookupSymbol(string);
|
| + if (scanner().is_literal_ascii()) {
|
| + result = isolate()->factory()->LookupAsciiSymbol(
|
| + scanner().literal_ascii_string());
|
| + } else {
|
| + result = isolate()->factory()->LookupTwoByteSymbol(
|
| + scanner().literal_uc16_string());
|
| + }
|
| symbol_cache_.at(symbol_id) = result;
|
| return result;
|
| }
|
| @@ -617,11 +627,11 @@
|
| // identical calls.
|
| ExternalTwoByteStringUC16CharacterStream stream(
|
| Handle<ExternalTwoByteString>::cast(source), 0, source->length());
|
| - scanner_.Initialize(&stream, JavaScriptScanner::kAllLiterals);
|
| + scanner_.Initialize(&stream);
|
| return DoParseProgram(source, in_global_context, &zone_scope);
|
| } else {
|
| GenericStringUC16CharacterStream stream(source, 0, source->length());
|
| - scanner_.Initialize(&stream, JavaScriptScanner::kAllLiterals);
|
| + scanner_.Initialize(&stream);
|
| return DoParseProgram(source, in_global_context, &zone_scope);
|
| }
|
| }
|
| @@ -707,7 +717,7 @@
|
| FunctionLiteral* Parser::ParseLazy(Handle<SharedFunctionInfo> info,
|
| UC16CharacterStream* source,
|
| ZoneScope* zone_scope) {
|
| - scanner_.Initialize(source, JavaScriptScanner::kAllLiterals);
|
| + scanner_.Initialize(source);
|
| ASSERT(target_stack_ == NULL);
|
|
|
| Handle<String> name(String::cast(info->name()));
|
| @@ -759,7 +769,7 @@
|
| if (pre_data() != NULL) {
|
| symbol_id = pre_data()->GetSymbolIdentifier();
|
| }
|
| - return LookupSymbol(symbol_id, scanner().literal());
|
| + return LookupSymbol(symbol_id);
|
| }
|
|
|
|
|
| @@ -2327,26 +2337,6 @@
|
| }
|
| }
|
|
|
| - // Convert constant divisions to multiplications for speed.
|
| - if (op == Token::DIV &&
|
| - y && y->AsLiteral() && y->AsLiteral()->handle()->IsNumber()) {
|
| - double y_val = y->AsLiteral()->handle()->Number();
|
| - int64_t y_int = static_cast<int64_t>(y_val);
|
| - // There are rounding issues with this optimization, but they don't
|
| - // apply if the number to be divided with has a reciprocal that can be
|
| - // precisely represented as a floating point number. This is the case
|
| - // if the number is an integer power of 2. Negative integer powers of
|
| - // 2 work too, but for -2, -1, 1 and 2 we don't do the strength
|
| - // reduction because the inlined optimistic idiv has a reasonable
|
| - // chance of succeeding by producing a Smi answer with no remainder.
|
| - if (static_cast<double>(y_int) == y_val &&
|
| - (IsPowerOf2(y_int) || IsPowerOf2(-y_int)) &&
|
| - (y_int > 2 || y_int < -2)) {
|
| - y = NewNumberLiteral(1 / y_val);
|
| - op = Token::MUL;
|
| - }
|
| - }
|
| -
|
| // For now we distinguish between comparisons and other binary
|
| // operations. (We could combine the two and get rid of this
|
| // code and AST node eventually.)
|
| @@ -2728,8 +2718,9 @@
|
|
|
| case Token::NUMBER: {
|
| Consume(Token::NUMBER);
|
| - double value =
|
| - StringToDouble(scanner().literal(), ALLOW_HEX | ALLOW_OCTALS);
|
| + ASSERT(scanner().is_literal_ascii());
|
| + double value = StringToDouble(scanner().literal_ascii_string(),
|
| + ALLOW_HEX | ALLOW_OCTALS);
|
| result = NewNumberLiteral(value);
|
| break;
|
| }
|
| @@ -3001,14 +2992,22 @@
|
| // { ... , get foo() { ... }, ... , set foo(v) { ... v ... } , ... }
|
| // We have already read the "get" or "set" keyword.
|
| Token::Value next = Next();
|
| - // TODO(820): Allow NUMBER and STRING as well (and handle array indices).
|
| - if (next == Token::IDENTIFIER || Token::IsKeyword(next)) {
|
| - Handle<String> name = GetSymbol(CHECK_OK);
|
| + bool is_keyword = Token::IsKeyword(next);
|
| + if (next == Token::IDENTIFIER || next == Token::NUMBER ||
|
| + next == Token::STRING || is_keyword) {
|
| + Handle<String> name;
|
| + if (is_keyword) {
|
| + name = isolate_->factory()->LookupAsciiSymbol(Token::String(next));
|
| + } else {
|
| + name = GetSymbol(CHECK_OK);
|
| + }
|
| FunctionLiteral* value =
|
| ParseFunctionLiteral(name,
|
| RelocInfo::kNoPosition,
|
| DECLARATION,
|
| CHECK_OK);
|
| + // Allow any number of parameters for compatiabilty with JSC.
|
| + // Specification only allows zero parameters for get and one for set.
|
| ObjectLiteral::Property* property =
|
| new ObjectLiteral::Property(is_getter, value);
|
| return property;
|
| @@ -3079,8 +3078,9 @@
|
| }
|
| case Token::NUMBER: {
|
| Consume(Token::NUMBER);
|
| - double value =
|
| - StringToDouble(scanner().literal(), ALLOW_HEX | ALLOW_OCTALS);
|
| + ASSERT(scanner().is_literal_ascii());
|
| + double value = StringToDouble(scanner().literal_ascii_string(),
|
| + ALLOW_HEX | ALLOW_OCTALS);
|
| key = NewNumberLiteral(value);
|
| break;
|
| }
|
| @@ -3150,11 +3150,9 @@
|
|
|
| int literal_index = temp_scope_->NextMaterializedLiteralIndex();
|
|
|
| - Handle<String> js_pattern =
|
| - isolate_->factory()->NewStringFromUtf8(scanner().next_literal(), TENURED);
|
| + Handle<String> js_pattern = NextLiteralString(TENURED);
|
| scanner().ScanRegExpFlags();
|
| - Handle<String> js_flags =
|
| - isolate_->factory()->NewStringFromUtf8(scanner().next_literal(), TENURED);
|
| + Handle<String> js_flags = NextLiteralString(TENURED);
|
| Next();
|
|
|
| return new RegExpLiteral(js_pattern, js_flags, literal_index);
|
| @@ -3438,10 +3436,10 @@
|
| bool* ok) {
|
| Expect(Token::IDENTIFIER, ok);
|
| if (!*ok) return Handle<String>();
|
| - if (scanner().literal_length() == 3) {
|
| - const char* token = scanner().literal_string();
|
| - *is_get = strcmp(token, "get") == 0;
|
| - *is_set = !*is_get && strcmp(token, "set") == 0;
|
| + if (scanner().is_literal_ascii() && scanner().literal_length() == 3) {
|
| + const char* token = scanner().literal_ascii_string().start();
|
| + *is_get = strncmp(token, "get", 3) == 0;
|
| + *is_set = !*is_get && strncmp(token, "set", 3) == 0;
|
| }
|
| return GetSymbol(ok);
|
| }
|
| @@ -3623,9 +3621,13 @@
|
| if (literal_length == 0) {
|
| return isolate()->factory()->empty_string();
|
| }
|
| - const char* literal_string = scanner_.literal_string();
|
| - Vector<const char> literal(literal_string, literal_length);
|
| - return isolate()->factory()->NewStringFromUtf8(literal);
|
| + if (scanner_.is_literal_ascii()) {
|
| + return isolate()->factory()->NewStringFromAscii(
|
| + scanner_.literal_ascii_string());
|
| + } else {
|
| + return isolate()->factory()->NewStringFromTwoByte(
|
| + scanner_.literal_uc16_string());
|
| + }
|
| }
|
|
|
|
|
| @@ -3637,7 +3639,8 @@
|
| return GetString();
|
| }
|
| case Token::NUMBER: {
|
| - double value = StringToDouble(scanner_.literal(),
|
| + ASSERT(scanner_.is_literal_ascii());
|
| + double value = StringToDouble(scanner_.literal_ascii_string(),
|
| NO_FLAGS, // Hex, octal or trailing junk.
|
| OS::nan_value());
|
| return isolate()->factory()->NewNumber(value);
|
| @@ -3683,9 +3686,9 @@
|
| if (value.is_null()) return Handle<Object>::null();
|
| uint32_t index;
|
| if (key->AsArrayIndex(&index)) {
|
| - SetElement(json_object, index, value);
|
| + SetOwnElement(json_object, index, value);
|
| } else {
|
| - SetProperty(json_object, key, value, NONE);
|
| + SetLocalPropertyIgnoreAttributes(json_object, key, value, NONE);
|
| }
|
| } while (scanner_.Next() == Token::COMMA);
|
| if (scanner_.current_token() != Token::RBRACE) {
|
| @@ -4046,9 +4049,21 @@
|
| builder->AddCharacter('\v');
|
| break;
|
| case 'c': {
|
| - Advance(2);
|
| - uc32 control = ParseControlLetterEscape();
|
| - builder->AddCharacter(control);
|
| + Advance();
|
| + uc32 controlLetter = Next();
|
| + // Special case if it is an ASCII letter.
|
| + // Convert lower case letters to uppercase.
|
| + uc32 letter = controlLetter & ~('a' ^ 'A');
|
| + if (letter < 'A' || 'Z' < letter) {
|
| + // controlLetter is not in range 'A'-'Z' or 'a'-'z'.
|
| + // This is outside the specification. We match JSC in
|
| + // reading the backslash as a literal character instead
|
| + // of as starting an escape.
|
| + builder->AddCharacter('\\');
|
| + } else {
|
| + Advance(2);
|
| + builder->AddCharacter(controlLetter & 0x1f);
|
| + }
|
| break;
|
| }
|
| case 'x': {
|
| @@ -4299,23 +4314,6 @@
|
| }
|
|
|
|
|
| -// Upper and lower case letters differ by one bit.
|
| -STATIC_CHECK(('a' ^ 'A') == 0x20);
|
| -
|
| -uc32 RegExpParser::ParseControlLetterEscape() {
|
| - if (!has_more())
|
| - return 'c';
|
| - uc32 letter = current() & ~(0x20); // Collapse upper and lower case letters.
|
| - if (letter < 'A' || 'Z' < letter) {
|
| - // Non-spec error-correction: "\c" followed by non-control letter is
|
| - // interpreted as an IdentityEscape of 'c'.
|
| - return 'c';
|
| - }
|
| - Advance();
|
| - return letter & 0x1f; // Remainder modulo 32, per specification.
|
| -}
|
| -
|
| -
|
| uc32 RegExpParser::ParseOctalLiteral() {
|
| ASSERT('0' <= current() && current() <= '7');
|
| // For compatibility with some other browsers (not all), we parse
|
| @@ -4381,9 +4379,23 @@
|
| case 'v':
|
| Advance();
|
| return '\v';
|
| - case 'c':
|
| - Advance();
|
| - return ParseControlLetterEscape();
|
| + case 'c': {
|
| + uc32 controlLetter = Next();
|
| + uc32 letter = controlLetter & ~('A' ^ 'a');
|
| + // For compatibility with JSC, inside a character class
|
| + // we also accept digits and underscore as control characters.
|
| + if ((controlLetter >= '0' && controlLetter <= '9') ||
|
| + controlLetter == '_' ||
|
| + (letter >= 'A' && letter <= 'Z')) {
|
| + Advance(2);
|
| + // Control letters mapped to ASCII control characters in the range
|
| + // 0x00-0x1f.
|
| + return controlLetter & 0x1f;
|
| + }
|
| + // We match JSC in reading the backslash as a literal
|
| + // character instead of as starting an escape.
|
| + return '\\';
|
| + }
|
| case '0': case '1': case '2': case '3': case '4': case '5':
|
| case '6': case '7':
|
| // For compatibility, we interpret a decimal escape that isn't
|
| @@ -4594,11 +4606,10 @@
|
| // Create a Scanner for the preparser to use as input, and preparse the source.
|
| static ScriptDataImpl* DoPreParse(UC16CharacterStream* source,
|
| bool allow_lazy,
|
| - ParserRecorder* recorder,
|
| - int literal_flags) {
|
| + ParserRecorder* recorder) {
|
| Isolate* isolate = Isolate::Current();
|
| V8JavaScriptScanner scanner(isolate);
|
| - scanner.Initialize(source, literal_flags);
|
| + scanner.Initialize(source);
|
| intptr_t stack_limit = isolate->stack_guard()->real_climit();
|
| if (!preparser::PreParser::PreParseProgram(&scanner,
|
| recorder,
|
| @@ -4626,8 +4637,7 @@
|
| return NULL;
|
| }
|
| PartialParserRecorder recorder;
|
| - return DoPreParse(source, allow_lazy, &recorder,
|
| - JavaScriptScanner::kNoLiterals);
|
| + return DoPreParse(source, allow_lazy, &recorder);
|
| }
|
|
|
|
|
| @@ -4636,9 +4646,7 @@
|
| Handle<Script> no_script;
|
| bool allow_lazy = FLAG_lazy && (extension == NULL);
|
| CompleteParserRecorder recorder;
|
| - int kPreParseLiteralsFlags =
|
| - JavaScriptScanner::kLiteralString | JavaScriptScanner::kLiteralIdentifier;
|
| - return DoPreParse(source, allow_lazy, &recorder, kPreParseLiteralsFlags);
|
| + return DoPreParse(source, allow_lazy, &recorder);
|
| }
|
|
|
|
|
|
|