| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 317 parent_(*variable) { | 317 parent_(*variable) { |
| 318 *variable = this; | 318 *variable = this; |
| 319 } | 319 } |
| 320 | 320 |
| 321 | 321 |
| 322 TemporaryScope::~TemporaryScope() { | 322 TemporaryScope::~TemporaryScope() { |
| 323 *variable_ = parent_; | 323 *variable_ = parent_; |
| 324 } | 324 } |
| 325 | 325 |
| 326 | 326 |
| 327 Handle<String> Parser::LookupSymbol(int symbol_id, | 327 Handle<String> Parser::LookupSymbol(int symbol_id) { |
| 328 Vector<const char> string) { | |
| 329 // Length of symbol cache is the number of identified symbols. | 328 // Length of symbol cache is the number of identified symbols. |
| 330 // If we are larger than that, or negative, it's not a cached symbol. | 329 // If we are larger than that, or negative, it's not a cached symbol. |
| 331 // This might also happen if there is no preparser symbol data, even | 330 // This might also happen if there is no preparser symbol data, even |
| 332 // if there is some preparser data. | 331 // if there is some preparser data. |
| 333 if (static_cast<unsigned>(symbol_id) | 332 if (static_cast<unsigned>(symbol_id) |
| 334 >= static_cast<unsigned>(symbol_cache_.length())) { | 333 >= static_cast<unsigned>(symbol_cache_.length())) { |
| 335 return isolate()->factory()->LookupSymbol(string); | 334 if (scanner().is_literal_ascii()) { |
| 335 return isolate()->factory()->LookupAsciiSymbol( |
| 336 scanner().literal_ascii_string()); |
| 337 } else { |
| 338 return isolate()->factory()->LookupTwoByteSymbol( |
| 339 scanner().literal_uc16_string()); |
| 340 } |
| 336 } | 341 } |
| 337 return LookupCachedSymbol(symbol_id, string); | 342 return LookupCachedSymbol(symbol_id); |
| 338 } | 343 } |
| 339 | 344 |
| 340 | 345 |
| 341 Handle<String> Parser::LookupCachedSymbol(int symbol_id, | 346 Handle<String> Parser::LookupCachedSymbol(int symbol_id) { |
| 342 Vector<const char> string) { | |
| 343 // Make sure the cache is large enough to hold the symbol identifier. | 347 // Make sure the cache is large enough to hold the symbol identifier. |
| 344 if (symbol_cache_.length() <= symbol_id) { | 348 if (symbol_cache_.length() <= symbol_id) { |
| 345 // Increase length to index + 1. | 349 // Increase length to index + 1. |
| 346 symbol_cache_.AddBlock(Handle<String>::null(), | 350 symbol_cache_.AddBlock(Handle<String>::null(), |
| 347 symbol_id + 1 - symbol_cache_.length()); | 351 symbol_id + 1 - symbol_cache_.length()); |
| 348 } | 352 } |
| 349 Handle<String> result = symbol_cache_.at(symbol_id); | 353 Handle<String> result = symbol_cache_.at(symbol_id); |
| 350 if (result.is_null()) { | 354 if (result.is_null()) { |
| 351 result = isolate()->factory()->LookupSymbol(string); | 355 if (scanner().is_literal_ascii()) { |
| 356 result = isolate()->factory()->LookupAsciiSymbol( |
| 357 scanner().literal_ascii_string()); |
| 358 } else { |
| 359 result = isolate()->factory()->LookupTwoByteSymbol( |
| 360 scanner().literal_uc16_string()); |
| 361 } |
| 352 symbol_cache_.at(symbol_id) = result; | 362 symbol_cache_.at(symbol_id) = result; |
| 353 return result; | 363 return result; |
| 354 } | 364 } |
| 355 COUNTERS->total_preparse_symbols_skipped()->Increment(); | 365 COUNTERS->total_preparse_symbols_skipped()->Increment(); |
| 356 return result; | 366 return result; |
| 357 } | 367 } |
| 358 | 368 |
| 359 | 369 |
| 360 FunctionEntry ScriptDataImpl::GetFunctionEntry(int start) { | 370 FunctionEntry ScriptDataImpl::GetFunctionEntry(int start) { |
| 361 // The current pre-data entry must be a FunctionEntry with the given | 371 // The current pre-data entry must be a FunctionEntry with the given |
| (...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 610 fni_ = new FuncNameInferrer(); | 620 fni_ = new FuncNameInferrer(); |
| 611 | 621 |
| 612 // Initialize parser state. | 622 // Initialize parser state. |
| 613 source->TryFlatten(); | 623 source->TryFlatten(); |
| 614 if (source->IsExternalTwoByteString()) { | 624 if (source->IsExternalTwoByteString()) { |
| 615 // Notice that the stream is destroyed at the end of the branch block. | 625 // Notice that the stream is destroyed at the end of the branch block. |
| 616 // The last line of the blocks can't be moved outside, even though they're | 626 // The last line of the blocks can't be moved outside, even though they're |
| 617 // identical calls. | 627 // identical calls. |
| 618 ExternalTwoByteStringUC16CharacterStream stream( | 628 ExternalTwoByteStringUC16CharacterStream stream( |
| 619 Handle<ExternalTwoByteString>::cast(source), 0, source->length()); | 629 Handle<ExternalTwoByteString>::cast(source), 0, source->length()); |
| 620 scanner_.Initialize(&stream, JavaScriptScanner::kAllLiterals); | 630 scanner_.Initialize(&stream); |
| 621 return DoParseProgram(source, in_global_context, &zone_scope); | 631 return DoParseProgram(source, in_global_context, &zone_scope); |
| 622 } else { | 632 } else { |
| 623 GenericStringUC16CharacterStream stream(source, 0, source->length()); | 633 GenericStringUC16CharacterStream stream(source, 0, source->length()); |
| 624 scanner_.Initialize(&stream, JavaScriptScanner::kAllLiterals); | 634 scanner_.Initialize(&stream); |
| 625 return DoParseProgram(source, in_global_context, &zone_scope); | 635 return DoParseProgram(source, in_global_context, &zone_scope); |
| 626 } | 636 } |
| 627 } | 637 } |
| 628 | 638 |
| 629 | 639 |
| 630 FunctionLiteral* Parser::DoParseProgram(Handle<String> source, | 640 FunctionLiteral* Parser::DoParseProgram(Handle<String> source, |
| 631 bool in_global_context, | 641 bool in_global_context, |
| 632 ZoneScope* zone_scope) { | 642 ZoneScope* zone_scope) { |
| 633 ASSERT(target_stack_ == NULL); | 643 ASSERT(target_stack_ == NULL); |
| 634 if (pre_data_ != NULL) pre_data_->Initialize(); | 644 if (pre_data_ != NULL) pre_data_->Initialize(); |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 700 info->end_position()); | 710 info->end_position()); |
| 701 FunctionLiteral* result = ParseLazy(info, &stream, &zone_scope); | 711 FunctionLiteral* result = ParseLazy(info, &stream, &zone_scope); |
| 702 return result; | 712 return result; |
| 703 } | 713 } |
| 704 } | 714 } |
| 705 | 715 |
| 706 | 716 |
| 707 FunctionLiteral* Parser::ParseLazy(Handle<SharedFunctionInfo> info, | 717 FunctionLiteral* Parser::ParseLazy(Handle<SharedFunctionInfo> info, |
| 708 UC16CharacterStream* source, | 718 UC16CharacterStream* source, |
| 709 ZoneScope* zone_scope) { | 719 ZoneScope* zone_scope) { |
| 710 scanner_.Initialize(source, JavaScriptScanner::kAllLiterals); | 720 scanner_.Initialize(source); |
| 711 ASSERT(target_stack_ == NULL); | 721 ASSERT(target_stack_ == NULL); |
| 712 | 722 |
| 713 Handle<String> name(String::cast(info->name())); | 723 Handle<String> name(String::cast(info->name())); |
| 714 fni_ = new FuncNameInferrer(); | 724 fni_ = new FuncNameInferrer(); |
| 715 fni_->PushEnclosingName(name); | 725 fni_->PushEnclosingName(name); |
| 716 | 726 |
| 717 mode_ = PARSE_EAGERLY; | 727 mode_ = PARSE_EAGERLY; |
| 718 | 728 |
| 719 // Place holder for the result. | 729 // Place holder for the result. |
| 720 FunctionLiteral* result = NULL; | 730 FunctionLiteral* result = NULL; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 752 } | 762 } |
| 753 return result; | 763 return result; |
| 754 } | 764 } |
| 755 | 765 |
| 756 | 766 |
| 757 Handle<String> Parser::GetSymbol(bool* ok) { | 767 Handle<String> Parser::GetSymbol(bool* ok) { |
| 758 int symbol_id = -1; | 768 int symbol_id = -1; |
| 759 if (pre_data() != NULL) { | 769 if (pre_data() != NULL) { |
| 760 symbol_id = pre_data()->GetSymbolIdentifier(); | 770 symbol_id = pre_data()->GetSymbolIdentifier(); |
| 761 } | 771 } |
| 762 return LookupSymbol(symbol_id, scanner().literal()); | 772 return LookupSymbol(symbol_id); |
| 763 } | 773 } |
| 764 | 774 |
| 765 | 775 |
| 766 void Parser::ReportMessage(const char* type, Vector<const char*> args) { | 776 void Parser::ReportMessage(const char* type, Vector<const char*> args) { |
| 767 Scanner::Location source_location = scanner().location(); | 777 Scanner::Location source_location = scanner().location(); |
| 768 ReportMessageAt(source_location, type, args); | 778 ReportMessageAt(source_location, type, args); |
| 769 } | 779 } |
| 770 | 780 |
| 771 | 781 |
| 772 void Parser::ReportMessageAt(Scanner::Location source_location, | 782 void Parser::ReportMessageAt(Scanner::Location source_location, |
| (...skipping 1547 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2320 uint32_t shift = DoubleToInt32(y_val) & 0x1f; | 2330 uint32_t shift = DoubleToInt32(y_val) & 0x1f; |
| 2321 int value = ArithmeticShiftRight(DoubleToInt32(x_val), shift); | 2331 int value = ArithmeticShiftRight(DoubleToInt32(x_val), shift); |
| 2322 x = NewNumberLiteral(value); | 2332 x = NewNumberLiteral(value); |
| 2323 continue; | 2333 continue; |
| 2324 } | 2334 } |
| 2325 default: | 2335 default: |
| 2326 break; | 2336 break; |
| 2327 } | 2337 } |
| 2328 } | 2338 } |
| 2329 | 2339 |
| 2330 // Convert constant divisions to multiplications for speed. | |
| 2331 if (op == Token::DIV && | |
| 2332 y && y->AsLiteral() && y->AsLiteral()->handle()->IsNumber()) { | |
| 2333 double y_val = y->AsLiteral()->handle()->Number(); | |
| 2334 int64_t y_int = static_cast<int64_t>(y_val); | |
| 2335 // There are rounding issues with this optimization, but they don't | |
| 2336 // apply if the number to be divided with has a reciprocal that can be | |
| 2337 // precisely represented as a floating point number. This is the case | |
| 2338 // if the number is an integer power of 2. Negative integer powers of | |
| 2339 // 2 work too, but for -2, -1, 1 and 2 we don't do the strength | |
| 2340 // reduction because the inlined optimistic idiv has a reasonable | |
| 2341 // chance of succeeding by producing a Smi answer with no remainder. | |
| 2342 if (static_cast<double>(y_int) == y_val && | |
| 2343 (IsPowerOf2(y_int) || IsPowerOf2(-y_int)) && | |
| 2344 (y_int > 2 || y_int < -2)) { | |
| 2345 y = NewNumberLiteral(1 / y_val); | |
| 2346 op = Token::MUL; | |
| 2347 } | |
| 2348 } | |
| 2349 | |
| 2350 // For now we distinguish between comparisons and other binary | 2340 // For now we distinguish between comparisons and other binary |
| 2351 // operations. (We could combine the two and get rid of this | 2341 // operations. (We could combine the two and get rid of this |
| 2352 // code and AST node eventually.) | 2342 // code and AST node eventually.) |
| 2353 if (Token::IsCompareOp(op)) { | 2343 if (Token::IsCompareOp(op)) { |
| 2354 // We have a comparison. | 2344 // We have a comparison. |
| 2355 Token::Value cmp = op; | 2345 Token::Value cmp = op; |
| 2356 switch (op) { | 2346 switch (op) { |
| 2357 case Token::NE: cmp = Token::EQ; break; | 2347 case Token::NE: cmp = Token::EQ; break; |
| 2358 case Token::NE_STRICT: cmp = Token::EQ_STRICT; break; | 2348 case Token::NE_STRICT: cmp = Token::EQ_STRICT; break; |
| 2359 default: break; | 2349 default: break; |
| (...skipping 361 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2721 | 2711 |
| 2722 case Token::IDENTIFIER: { | 2712 case Token::IDENTIFIER: { |
| 2723 Handle<String> name = ParseIdentifier(CHECK_OK); | 2713 Handle<String> name = ParseIdentifier(CHECK_OK); |
| 2724 if (fni_ != NULL) fni_->PushVariableName(name); | 2714 if (fni_ != NULL) fni_->PushVariableName(name); |
| 2725 result = top_scope_->NewUnresolved(name, inside_with()); | 2715 result = top_scope_->NewUnresolved(name, inside_with()); |
| 2726 break; | 2716 break; |
| 2727 } | 2717 } |
| 2728 | 2718 |
| 2729 case Token::NUMBER: { | 2719 case Token::NUMBER: { |
| 2730 Consume(Token::NUMBER); | 2720 Consume(Token::NUMBER); |
| 2731 double value = | 2721 ASSERT(scanner().is_literal_ascii()); |
| 2732 StringToDouble(scanner().literal(), ALLOW_HEX | ALLOW_OCTALS); | 2722 double value = StringToDouble(scanner().literal_ascii_string(), |
| 2723 ALLOW_HEX | ALLOW_OCTALS); |
| 2733 result = NewNumberLiteral(value); | 2724 result = NewNumberLiteral(value); |
| 2734 break; | 2725 break; |
| 2735 } | 2726 } |
| 2736 | 2727 |
| 2737 case Token::STRING: { | 2728 case Token::STRING: { |
| 2738 Consume(Token::STRING); | 2729 Consume(Token::STRING); |
| 2739 Handle<String> symbol = GetSymbol(CHECK_OK); | 2730 Handle<String> symbol = GetSymbol(CHECK_OK); |
| 2740 result = new Literal(symbol); | 2731 result = new Literal(symbol); |
| 2741 if (fni_ != NULL) fni_->PushLiteralName(symbol); | 2732 if (fni_ != NULL) fni_->PushLiteralName(symbol); |
| 2742 break; | 2733 break; |
| (...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2994 *depth = depth_acc; | 2985 *depth = depth_acc; |
| 2995 } | 2986 } |
| 2996 | 2987 |
| 2997 | 2988 |
| 2998 ObjectLiteral::Property* Parser::ParseObjectLiteralGetSet(bool is_getter, | 2989 ObjectLiteral::Property* Parser::ParseObjectLiteralGetSet(bool is_getter, |
| 2999 bool* ok) { | 2990 bool* ok) { |
| 3000 // Special handling of getter and setter syntax: | 2991 // Special handling of getter and setter syntax: |
| 3001 // { ... , get foo() { ... }, ... , set foo(v) { ... v ... } , ... } | 2992 // { ... , get foo() { ... }, ... , set foo(v) { ... v ... } , ... } |
| 3002 // We have already read the "get" or "set" keyword. | 2993 // We have already read the "get" or "set" keyword. |
| 3003 Token::Value next = Next(); | 2994 Token::Value next = Next(); |
| 3004 // TODO(820): Allow NUMBER and STRING as well (and handle array indices). | 2995 bool is_keyword = Token::IsKeyword(next); |
| 3005 if (next == Token::IDENTIFIER || Token::IsKeyword(next)) { | 2996 if (next == Token::IDENTIFIER || next == Token::NUMBER || |
| 3006 Handle<String> name = GetSymbol(CHECK_OK); | 2997 next == Token::STRING || is_keyword) { |
| 2998 Handle<String> name; |
| 2999 if (is_keyword) { |
| 3000 name = isolate_->factory()->LookupAsciiSymbol(Token::String(next)); |
| 3001 } else { |
| 3002 name = GetSymbol(CHECK_OK); |
| 3003 } |
| 3007 FunctionLiteral* value = | 3004 FunctionLiteral* value = |
| 3008 ParseFunctionLiteral(name, | 3005 ParseFunctionLiteral(name, |
| 3009 RelocInfo::kNoPosition, | 3006 RelocInfo::kNoPosition, |
| 3010 DECLARATION, | 3007 DECLARATION, |
| 3011 CHECK_OK); | 3008 CHECK_OK); |
| 3009 // Allow any number of parameters for compatiabilty with JSC. |
| 3010 // Specification only allows zero parameters for get and one for set. |
| 3012 ObjectLiteral::Property* property = | 3011 ObjectLiteral::Property* property = |
| 3013 new ObjectLiteral::Property(is_getter, value); | 3012 new ObjectLiteral::Property(is_getter, value); |
| 3014 return property; | 3013 return property; |
| 3015 } else { | 3014 } else { |
| 3016 ReportUnexpectedToken(next); | 3015 ReportUnexpectedToken(next); |
| 3017 *ok = false; | 3016 *ok = false; |
| 3018 return NULL; | 3017 return NULL; |
| 3019 } | 3018 } |
| 3020 } | 3019 } |
| 3021 | 3020 |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3072 uint32_t index; | 3071 uint32_t index; |
| 3073 if (!string.is_null() && string->AsArrayIndex(&index)) { | 3072 if (!string.is_null() && string->AsArrayIndex(&index)) { |
| 3074 key = NewNumberLiteral(index); | 3073 key = NewNumberLiteral(index); |
| 3075 break; | 3074 break; |
| 3076 } | 3075 } |
| 3077 key = new Literal(string); | 3076 key = new Literal(string); |
| 3078 break; | 3077 break; |
| 3079 } | 3078 } |
| 3080 case Token::NUMBER: { | 3079 case Token::NUMBER: { |
| 3081 Consume(Token::NUMBER); | 3080 Consume(Token::NUMBER); |
| 3082 double value = | 3081 ASSERT(scanner().is_literal_ascii()); |
| 3083 StringToDouble(scanner().literal(), ALLOW_HEX | ALLOW_OCTALS); | 3082 double value = StringToDouble(scanner().literal_ascii_string(), |
| 3083 ALLOW_HEX | ALLOW_OCTALS); |
| 3084 key = NewNumberLiteral(value); | 3084 key = NewNumberLiteral(value); |
| 3085 break; | 3085 break; |
| 3086 } | 3086 } |
| 3087 default: | 3087 default: |
| 3088 if (Token::IsKeyword(next)) { | 3088 if (Token::IsKeyword(next)) { |
| 3089 Consume(next); | 3089 Consume(next); |
| 3090 Handle<String> string = GetSymbol(CHECK_OK); | 3090 Handle<String> string = GetSymbol(CHECK_OK); |
| 3091 key = new Literal(string); | 3091 key = new Literal(string); |
| 3092 } else { | 3092 } else { |
| 3093 // Unexpected token. | 3093 // Unexpected token. |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3143 Expression* Parser::ParseRegExpLiteral(bool seen_equal, bool* ok) { | 3143 Expression* Parser::ParseRegExpLiteral(bool seen_equal, bool* ok) { |
| 3144 if (!scanner().ScanRegExpPattern(seen_equal)) { | 3144 if (!scanner().ScanRegExpPattern(seen_equal)) { |
| 3145 Next(); | 3145 Next(); |
| 3146 ReportMessage("unterminated_regexp", Vector<const char*>::empty()); | 3146 ReportMessage("unterminated_regexp", Vector<const char*>::empty()); |
| 3147 *ok = false; | 3147 *ok = false; |
| 3148 return NULL; | 3148 return NULL; |
| 3149 } | 3149 } |
| 3150 | 3150 |
| 3151 int literal_index = temp_scope_->NextMaterializedLiteralIndex(); | 3151 int literal_index = temp_scope_->NextMaterializedLiteralIndex(); |
| 3152 | 3152 |
| 3153 Handle<String> js_pattern = | 3153 Handle<String> js_pattern = NextLiteralString(TENURED); |
| 3154 isolate_->factory()->NewStringFromUtf8(scanner().next_literal(), TENURED); | |
| 3155 scanner().ScanRegExpFlags(); | 3154 scanner().ScanRegExpFlags(); |
| 3156 Handle<String> js_flags = | 3155 Handle<String> js_flags = NextLiteralString(TENURED); |
| 3157 isolate_->factory()->NewStringFromUtf8(scanner().next_literal(), TENURED); | |
| 3158 Next(); | 3156 Next(); |
| 3159 | 3157 |
| 3160 return new RegExpLiteral(js_pattern, js_flags, literal_index); | 3158 return new RegExpLiteral(js_pattern, js_flags, literal_index); |
| 3161 } | 3159 } |
| 3162 | 3160 |
| 3163 | 3161 |
| 3164 ZoneList<Expression*>* Parser::ParseArguments(bool* ok) { | 3162 ZoneList<Expression*>* Parser::ParseArguments(bool* ok) { |
| 3165 // Arguments :: | 3163 // Arguments :: |
| 3166 // '(' (AssignmentExpression)*[','] ')' | 3164 // '(' (AssignmentExpression)*[','] ')' |
| 3167 | 3165 |
| (...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3431 | 3429 |
| 3432 // This function reads an identifier and determines whether or not it | 3430 // This function reads an identifier and determines whether or not it |
| 3433 // is 'get' or 'set'. The reason for not using ParseIdentifier and | 3431 // is 'get' or 'set'. The reason for not using ParseIdentifier and |
| 3434 // checking on the output is that this involves heap allocation which | 3432 // checking on the output is that this involves heap allocation which |
| 3435 // we can't do during preparsing. | 3433 // we can't do during preparsing. |
| 3436 Handle<String> Parser::ParseIdentifierOrGetOrSet(bool* is_get, | 3434 Handle<String> Parser::ParseIdentifierOrGetOrSet(bool* is_get, |
| 3437 bool* is_set, | 3435 bool* is_set, |
| 3438 bool* ok) { | 3436 bool* ok) { |
| 3439 Expect(Token::IDENTIFIER, ok); | 3437 Expect(Token::IDENTIFIER, ok); |
| 3440 if (!*ok) return Handle<String>(); | 3438 if (!*ok) return Handle<String>(); |
| 3441 if (scanner().literal_length() == 3) { | 3439 if (scanner().is_literal_ascii() && scanner().literal_length() == 3) { |
| 3442 const char* token = scanner().literal_string(); | 3440 const char* token = scanner().literal_ascii_string().start(); |
| 3443 *is_get = strcmp(token, "get") == 0; | 3441 *is_get = strncmp(token, "get", 3) == 0; |
| 3444 *is_set = !*is_get && strcmp(token, "set") == 0; | 3442 *is_set = !*is_get && strncmp(token, "set", 3) == 0; |
| 3445 } | 3443 } |
| 3446 return GetSymbol(ok); | 3444 return GetSymbol(ok); |
| 3447 } | 3445 } |
| 3448 | 3446 |
| 3449 | 3447 |
| 3450 // ---------------------------------------------------------------------------- | 3448 // ---------------------------------------------------------------------------- |
| 3451 // Parser support | 3449 // Parser support |
| 3452 | 3450 |
| 3453 | 3451 |
| 3454 bool Parser::TargetStackContainsLabel(Handle<String> label) { | 3452 bool Parser::TargetStackContainsLabel(Handle<String> label) { |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3616 } | 3614 } |
| 3617 return result; | 3615 return result; |
| 3618 } | 3616 } |
| 3619 | 3617 |
| 3620 | 3618 |
| 3621 Handle<String> JsonParser::GetString() { | 3619 Handle<String> JsonParser::GetString() { |
| 3622 int literal_length = scanner_.literal_length(); | 3620 int literal_length = scanner_.literal_length(); |
| 3623 if (literal_length == 0) { | 3621 if (literal_length == 0) { |
| 3624 return isolate()->factory()->empty_string(); | 3622 return isolate()->factory()->empty_string(); |
| 3625 } | 3623 } |
| 3626 const char* literal_string = scanner_.literal_string(); | 3624 if (scanner_.is_literal_ascii()) { |
| 3627 Vector<const char> literal(literal_string, literal_length); | 3625 return isolate()->factory()->NewStringFromAscii( |
| 3628 return isolate()->factory()->NewStringFromUtf8(literal); | 3626 scanner_.literal_ascii_string()); |
| 3627 } else { |
| 3628 return isolate()->factory()->NewStringFromTwoByte( |
| 3629 scanner_.literal_uc16_string()); |
| 3630 } |
| 3629 } | 3631 } |
| 3630 | 3632 |
| 3631 | 3633 |
| 3632 // Parse any JSON value. | 3634 // Parse any JSON value. |
| 3633 Handle<Object> JsonParser::ParseJsonValue() { | 3635 Handle<Object> JsonParser::ParseJsonValue() { |
| 3634 Token::Value token = scanner_.Next(); | 3636 Token::Value token = scanner_.Next(); |
| 3635 switch (token) { | 3637 switch (token) { |
| 3636 case Token::STRING: { | 3638 case Token::STRING: { |
| 3637 return GetString(); | 3639 return GetString(); |
| 3638 } | 3640 } |
| 3639 case Token::NUMBER: { | 3641 case Token::NUMBER: { |
| 3640 double value = StringToDouble(scanner_.literal(), | 3642 ASSERT(scanner_.is_literal_ascii()); |
| 3643 double value = StringToDouble(scanner_.literal_ascii_string(), |
| 3641 NO_FLAGS, // Hex, octal or trailing junk. | 3644 NO_FLAGS, // Hex, octal or trailing junk. |
| 3642 OS::nan_value()); | 3645 OS::nan_value()); |
| 3643 return isolate()->factory()->NewNumber(value); | 3646 return isolate()->factory()->NewNumber(value); |
| 3644 } | 3647 } |
| 3645 case Token::FALSE_LITERAL: | 3648 case Token::FALSE_LITERAL: |
| 3646 return isolate()->factory()->false_value(); | 3649 return isolate()->factory()->false_value(); |
| 3647 case Token::TRUE_LITERAL: | 3650 case Token::TRUE_LITERAL: |
| 3648 return isolate()->factory()->true_value(); | 3651 return isolate()->factory()->true_value(); |
| 3649 case Token::NULL_LITERAL: | 3652 case Token::NULL_LITERAL: |
| 3650 return isolate()->factory()->null_value(); | 3653 return isolate()->factory()->null_value(); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 3676 return ReportUnexpectedToken(); | 3679 return ReportUnexpectedToken(); |
| 3677 } | 3680 } |
| 3678 Handle<String> key = GetString(); | 3681 Handle<String> key = GetString(); |
| 3679 if (scanner_.Next() != Token::COLON) { | 3682 if (scanner_.Next() != Token::COLON) { |
| 3680 return ReportUnexpectedToken(); | 3683 return ReportUnexpectedToken(); |
| 3681 } | 3684 } |
| 3682 Handle<Object> value = ParseJsonValue(); | 3685 Handle<Object> value = ParseJsonValue(); |
| 3683 if (value.is_null()) return Handle<Object>::null(); | 3686 if (value.is_null()) return Handle<Object>::null(); |
| 3684 uint32_t index; | 3687 uint32_t index; |
| 3685 if (key->AsArrayIndex(&index)) { | 3688 if (key->AsArrayIndex(&index)) { |
| 3686 SetElement(json_object, index, value); | 3689 SetOwnElement(json_object, index, value); |
| 3687 } else { | 3690 } else { |
| 3688 SetProperty(json_object, key, value, NONE); | 3691 SetLocalPropertyIgnoreAttributes(json_object, key, value, NONE); |
| 3689 } | 3692 } |
| 3690 } while (scanner_.Next() == Token::COMMA); | 3693 } while (scanner_.Next() == Token::COMMA); |
| 3691 if (scanner_.current_token() != Token::RBRACE) { | 3694 if (scanner_.current_token() != Token::RBRACE) { |
| 3692 return ReportUnexpectedToken(); | 3695 return ReportUnexpectedToken(); |
| 3693 } | 3696 } |
| 3694 } | 3697 } |
| 3695 return json_object; | 3698 return json_object; |
| 3696 } | 3699 } |
| 3697 | 3700 |
| 3698 | 3701 |
| (...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4039 break; | 4042 break; |
| 4040 case 't': | 4043 case 't': |
| 4041 Advance(2); | 4044 Advance(2); |
| 4042 builder->AddCharacter('\t'); | 4045 builder->AddCharacter('\t'); |
| 4043 break; | 4046 break; |
| 4044 case 'v': | 4047 case 'v': |
| 4045 Advance(2); | 4048 Advance(2); |
| 4046 builder->AddCharacter('\v'); | 4049 builder->AddCharacter('\v'); |
| 4047 break; | 4050 break; |
| 4048 case 'c': { | 4051 case 'c': { |
| 4049 Advance(2); | 4052 Advance(); |
| 4050 uc32 control = ParseControlLetterEscape(); | 4053 uc32 controlLetter = Next(); |
| 4051 builder->AddCharacter(control); | 4054 // Special case if it is an ASCII letter. |
| 4055 // Convert lower case letters to uppercase. |
| 4056 uc32 letter = controlLetter & ~('a' ^ 'A'); |
| 4057 if (letter < 'A' || 'Z' < letter) { |
| 4058 // controlLetter is not in range 'A'-'Z' or 'a'-'z'. |
| 4059 // This is outside the specification. We match JSC in |
| 4060 // reading the backslash as a literal character instead |
| 4061 // of as starting an escape. |
| 4062 builder->AddCharacter('\\'); |
| 4063 } else { |
| 4064 Advance(2); |
| 4065 builder->AddCharacter(controlLetter & 0x1f); |
| 4066 } |
| 4052 break; | 4067 break; |
| 4053 } | 4068 } |
| 4054 case 'x': { | 4069 case 'x': { |
| 4055 Advance(2); | 4070 Advance(2); |
| 4056 uc32 value; | 4071 uc32 value; |
| 4057 if (ParseHexEscape(2, &value)) { | 4072 if (ParseHexEscape(2, &value)) { |
| 4058 builder->AddCharacter(value); | 4073 builder->AddCharacter(value); |
| 4059 } else { | 4074 } else { |
| 4060 builder->AddCharacter('x'); | 4075 builder->AddCharacter('x'); |
| 4061 } | 4076 } |
| (...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4292 } else { | 4307 } else { |
| 4293 Reset(start); | 4308 Reset(start); |
| 4294 return false; | 4309 return false; |
| 4295 } | 4310 } |
| 4296 *min_out = min; | 4311 *min_out = min; |
| 4297 *max_out = max; | 4312 *max_out = max; |
| 4298 return true; | 4313 return true; |
| 4299 } | 4314 } |
| 4300 | 4315 |
| 4301 | 4316 |
| 4302 // Upper and lower case letters differ by one bit. | |
| 4303 STATIC_CHECK(('a' ^ 'A') == 0x20); | |
| 4304 | |
| 4305 uc32 RegExpParser::ParseControlLetterEscape() { | |
| 4306 if (!has_more()) | |
| 4307 return 'c'; | |
| 4308 uc32 letter = current() & ~(0x20); // Collapse upper and lower case letters. | |
| 4309 if (letter < 'A' || 'Z' < letter) { | |
| 4310 // Non-spec error-correction: "\c" followed by non-control letter is | |
| 4311 // interpreted as an IdentityEscape of 'c'. | |
| 4312 return 'c'; | |
| 4313 } | |
| 4314 Advance(); | |
| 4315 return letter & 0x1f; // Remainder modulo 32, per specification. | |
| 4316 } | |
| 4317 | |
| 4318 | |
| 4319 uc32 RegExpParser::ParseOctalLiteral() { | 4317 uc32 RegExpParser::ParseOctalLiteral() { |
| 4320 ASSERT('0' <= current() && current() <= '7'); | 4318 ASSERT('0' <= current() && current() <= '7'); |
| 4321 // For compatibility with some other browsers (not all), we parse | 4319 // For compatibility with some other browsers (not all), we parse |
| 4322 // up to three octal digits with a value below 256. | 4320 // up to three octal digits with a value below 256. |
| 4323 uc32 value = current() - '0'; | 4321 uc32 value = current() - '0'; |
| 4324 Advance(); | 4322 Advance(); |
| 4325 if ('0' <= current() && current() <= '7') { | 4323 if ('0' <= current() && current() <= '7') { |
| 4326 value = value * 8 + current() - '0'; | 4324 value = value * 8 + current() - '0'; |
| 4327 Advance(); | 4325 Advance(); |
| 4328 if (value < 32 && '0' <= current() && current() <= '7') { | 4326 if (value < 32 && '0' <= current() && current() <= '7') { |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4374 return '\n'; | 4372 return '\n'; |
| 4375 case 'r': | 4373 case 'r': |
| 4376 Advance(); | 4374 Advance(); |
| 4377 return '\r'; | 4375 return '\r'; |
| 4378 case 't': | 4376 case 't': |
| 4379 Advance(); | 4377 Advance(); |
| 4380 return '\t'; | 4378 return '\t'; |
| 4381 case 'v': | 4379 case 'v': |
| 4382 Advance(); | 4380 Advance(); |
| 4383 return '\v'; | 4381 return '\v'; |
| 4384 case 'c': | 4382 case 'c': { |
| 4385 Advance(); | 4383 uc32 controlLetter = Next(); |
| 4386 return ParseControlLetterEscape(); | 4384 uc32 letter = controlLetter & ~('A' ^ 'a'); |
| 4385 // For compatibility with JSC, inside a character class |
| 4386 // we also accept digits and underscore as control characters. |
| 4387 if ((controlLetter >= '0' && controlLetter <= '9') || |
| 4388 controlLetter == '_' || |
| 4389 (letter >= 'A' && letter <= 'Z')) { |
| 4390 Advance(2); |
| 4391 // Control letters mapped to ASCII control characters in the range |
| 4392 // 0x00-0x1f. |
| 4393 return controlLetter & 0x1f; |
| 4394 } |
| 4395 // We match JSC in reading the backslash as a literal |
| 4396 // character instead of as starting an escape. |
| 4397 return '\\'; |
| 4398 } |
| 4387 case '0': case '1': case '2': case '3': case '4': case '5': | 4399 case '0': case '1': case '2': case '3': case '4': case '5': |
| 4388 case '6': case '7': | 4400 case '6': case '7': |
| 4389 // For compatibility, we interpret a decimal escape that isn't | 4401 // For compatibility, we interpret a decimal escape that isn't |
| 4390 // a back reference (and therefore either \0 or not valid according | 4402 // a back reference (and therefore either \0 or not valid according |
| 4391 // to the specification) as a 1..3 digit octal character code. | 4403 // to the specification) as a 1..3 digit octal character code. |
| 4392 return ParseOctalLiteral(); | 4404 return ParseOctalLiteral(); |
| 4393 case 'x': { | 4405 case 'x': { |
| 4394 Advance(); | 4406 Advance(); |
| 4395 uc32 value; | 4407 uc32 value; |
| 4396 if (ParseHexEscape(2, &value)) { | 4408 if (ParseHexEscape(2, &value)) { |
| (...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4587 data++; | 4599 data++; |
| 4588 } | 4600 } |
| 4589 *source = data; | 4601 *source = data; |
| 4590 return result; | 4602 return result; |
| 4591 } | 4603 } |
| 4592 | 4604 |
| 4593 | 4605 |
| 4594 // Create a Scanner for the preparser to use as input, and preparse the source. | 4606 // Create a Scanner for the preparser to use as input, and preparse the source. |
| 4595 static ScriptDataImpl* DoPreParse(UC16CharacterStream* source, | 4607 static ScriptDataImpl* DoPreParse(UC16CharacterStream* source, |
| 4596 bool allow_lazy, | 4608 bool allow_lazy, |
| 4597 ParserRecorder* recorder, | 4609 ParserRecorder* recorder) { |
| 4598 int literal_flags) { | |
| 4599 Isolate* isolate = Isolate::Current(); | 4610 Isolate* isolate = Isolate::Current(); |
| 4600 V8JavaScriptScanner scanner(isolate); | 4611 V8JavaScriptScanner scanner(isolate); |
| 4601 scanner.Initialize(source, literal_flags); | 4612 scanner.Initialize(source); |
| 4602 intptr_t stack_limit = isolate->stack_guard()->real_climit(); | 4613 intptr_t stack_limit = isolate->stack_guard()->real_climit(); |
| 4603 if (!preparser::PreParser::PreParseProgram(&scanner, | 4614 if (!preparser::PreParser::PreParseProgram(&scanner, |
| 4604 recorder, | 4615 recorder, |
| 4605 allow_lazy, | 4616 allow_lazy, |
| 4606 stack_limit)) { | 4617 stack_limit)) { |
| 4607 isolate->StackOverflow(); | 4618 isolate->StackOverflow(); |
| 4608 return NULL; | 4619 return NULL; |
| 4609 } | 4620 } |
| 4610 | 4621 |
| 4611 // Extract the accumulated data from the recorder as a single | 4622 // Extract the accumulated data from the recorder as a single |
| 4612 // contiguous vector that we are responsible for disposing. | 4623 // contiguous vector that we are responsible for disposing. |
| 4613 Vector<unsigned> store = recorder->ExtractData(); | 4624 Vector<unsigned> store = recorder->ExtractData(); |
| 4614 return new ScriptDataImpl(store); | 4625 return new ScriptDataImpl(store); |
| 4615 } | 4626 } |
| 4616 | 4627 |
| 4617 | 4628 |
| 4618 // Preparse, but only collect data that is immediately useful, | 4629 // Preparse, but only collect data that is immediately useful, |
| 4619 // even if the preparser data is only used once. | 4630 // even if the preparser data is only used once. |
| 4620 ScriptDataImpl* ParserApi::PartialPreParse(UC16CharacterStream* source, | 4631 ScriptDataImpl* ParserApi::PartialPreParse(UC16CharacterStream* source, |
| 4621 v8::Extension* extension) { | 4632 v8::Extension* extension) { |
| 4622 bool allow_lazy = FLAG_lazy && (extension == NULL); | 4633 bool allow_lazy = FLAG_lazy && (extension == NULL); |
| 4623 if (!allow_lazy) { | 4634 if (!allow_lazy) { |
| 4624 // Partial preparsing is only about lazily compiled functions. | 4635 // Partial preparsing is only about lazily compiled functions. |
| 4625 // If we don't allow lazy compilation, the log data will be empty. | 4636 // If we don't allow lazy compilation, the log data will be empty. |
| 4626 return NULL; | 4637 return NULL; |
| 4627 } | 4638 } |
| 4628 PartialParserRecorder recorder; | 4639 PartialParserRecorder recorder; |
| 4629 return DoPreParse(source, allow_lazy, &recorder, | 4640 return DoPreParse(source, allow_lazy, &recorder); |
| 4630 JavaScriptScanner::kNoLiterals); | |
| 4631 } | 4641 } |
| 4632 | 4642 |
| 4633 | 4643 |
| 4634 ScriptDataImpl* ParserApi::PreParse(UC16CharacterStream* source, | 4644 ScriptDataImpl* ParserApi::PreParse(UC16CharacterStream* source, |
| 4635 v8::Extension* extension) { | 4645 v8::Extension* extension) { |
| 4636 Handle<Script> no_script; | 4646 Handle<Script> no_script; |
| 4637 bool allow_lazy = FLAG_lazy && (extension == NULL); | 4647 bool allow_lazy = FLAG_lazy && (extension == NULL); |
| 4638 CompleteParserRecorder recorder; | 4648 CompleteParserRecorder recorder; |
| 4639 int kPreParseLiteralsFlags = | 4649 return DoPreParse(source, allow_lazy, &recorder); |
| 4640 JavaScriptScanner::kLiteralString | JavaScriptScanner::kLiteralIdentifier; | |
| 4641 return DoPreParse(source, allow_lazy, &recorder, kPreParseLiteralsFlags); | |
| 4642 } | 4650 } |
| 4643 | 4651 |
| 4644 | 4652 |
| 4645 bool RegExpParser::ParseRegExp(FlatStringReader* input, | 4653 bool RegExpParser::ParseRegExp(FlatStringReader* input, |
| 4646 bool multiline, | 4654 bool multiline, |
| 4647 RegExpCompileData* result) { | 4655 RegExpCompileData* result) { |
| 4648 ASSERT(result != NULL); | 4656 ASSERT(result != NULL); |
| 4649 RegExpParser parser(input, &result->error, multiline); | 4657 RegExpParser parser(input, &result->error, multiline); |
| 4650 RegExpTree* tree = parser.ParsePattern(); | 4658 RegExpTree* tree = parser.ParsePattern(); |
| 4651 if (parser.failed()) { | 4659 if (parser.failed()) { |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4692 Handle<String> source = Handle<String>(String::cast(script->source())); | 4700 Handle<String> source = Handle<String>(String::cast(script->source())); |
| 4693 result = parser.ParseProgram(source, info->is_global()); | 4701 result = parser.ParseProgram(source, info->is_global()); |
| 4694 } | 4702 } |
| 4695 } | 4703 } |
| 4696 | 4704 |
| 4697 info->SetFunction(result); | 4705 info->SetFunction(result); |
| 4698 return (result != NULL); | 4706 return (result != NULL); |
| 4699 } | 4707 } |
| 4700 | 4708 |
| 4701 } } // namespace v8::internal | 4709 } } // namespace v8::internal |
| OLD | NEW |