OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/api.h" | 7 #include "src/api.h" |
8 #include "src/ast.h" | 8 #include "src/ast.h" |
9 #include "src/bailout-reason.h" | 9 #include "src/bailout-reason.h" |
10 #include "src/base/platform/platform.h" | 10 #include "src/base/platform/platform.h" |
(...skipping 896 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
907 | 907 |
908 if (produce_cached_parse_data()) { | 908 if (produce_cached_parse_data()) { |
909 log_ = &recorder; | 909 log_ = &recorder; |
910 } else if (consume_cached_parse_data()) { | 910 } else if (consume_cached_parse_data()) { |
911 cached_parse_data_->Initialize(); | 911 cached_parse_data_->Initialize(); |
912 } | 912 } |
913 | 913 |
914 source = String::Flatten(source); | 914 source = String::Flatten(source); |
915 FunctionLiteral* result; | 915 FunctionLiteral* result; |
916 | 916 |
917 Scope* top_scope = NULL; | |
918 Scope* eval_scope = NULL; | |
919 if (source->IsExternalTwoByteString()) { | 917 if (source->IsExternalTwoByteString()) { |
920 // Notice that the stream is destroyed at the end of the branch block. | 918 // Notice that the stream is destroyed at the end of the branch block. |
921 // The last line of the blocks can't be moved outside, even though they're | 919 // The last line of the blocks can't be moved outside, even though they're |
922 // identical calls. | 920 // identical calls. |
923 ExternalTwoByteStringUtf16CharacterStream stream( | 921 ExternalTwoByteStringUtf16CharacterStream stream( |
924 Handle<ExternalTwoByteString>::cast(source), 0, source->length()); | 922 Handle<ExternalTwoByteString>::cast(source), 0, source->length()); |
925 scanner_.Initialize(&stream); | 923 scanner_.Initialize(&stream); |
926 result = DoParseProgram(info, &top_scope, &eval_scope); | 924 result = DoParseProgram(info); |
927 } else { | 925 } else { |
928 GenericStringUtf16CharacterStream stream(source, 0, source->length()); | 926 GenericStringUtf16CharacterStream stream(source, 0, source->length()); |
929 scanner_.Initialize(&stream); | 927 scanner_.Initialize(&stream); |
930 result = DoParseProgram(info, &top_scope, &eval_scope); | 928 result = DoParseProgram(info); |
931 } | 929 } |
932 top_scope->set_end_position(source->length()); | 930 if (result != NULL) { |
933 if (eval_scope != NULL) { | 931 DCHECK_EQ(scanner_.peek_location().beg_pos, source->length()); |
934 eval_scope->set_end_position(source->length()); | |
935 } | 932 } |
936 HandleSourceURLComments(isolate, info->script()); | 933 HandleSourceURLComments(isolate, info->script()); |
937 | 934 |
938 if (FLAG_trace_parse && result != NULL) { | 935 if (FLAG_trace_parse && result != NULL) { |
939 double ms = timer.Elapsed().InMillisecondsF(); | 936 double ms = timer.Elapsed().InMillisecondsF(); |
940 if (info->is_eval()) { | 937 if (info->is_eval()) { |
941 PrintF("[parsing eval"); | 938 PrintF("[parsing eval"); |
942 } else if (info->script()->name()->IsString()) { | 939 } else if (info->script()->name()->IsString()) { |
943 String* name = String::cast(info->script()->name()); | 940 String* name = String::cast(info->script()->name()); |
944 SmartArrayPointer<char> name_chars = name->ToCString(); | 941 SmartArrayPointer<char> name_chars = name->ToCString(); |
945 PrintF("[parsing script: %s", name_chars.get()); | 942 PrintF("[parsing script: %s", name_chars.get()); |
946 } else { | 943 } else { |
947 PrintF("[parsing script"); | 944 PrintF("[parsing script"); |
948 } | 945 } |
949 PrintF(" - took %0.3f ms]\n", ms); | 946 PrintF(" - took %0.3f ms]\n", ms); |
950 } | 947 } |
951 if (produce_cached_parse_data()) { | 948 if (produce_cached_parse_data()) { |
952 if (result != NULL) *info->cached_data() = recorder.GetScriptData(); | 949 if (result != NULL) *info->cached_data() = recorder.GetScriptData(); |
953 log_ = NULL; | 950 log_ = NULL; |
954 } | 951 } |
955 return result; | 952 return result; |
956 } | 953 } |
957 | 954 |
958 | 955 |
959 FunctionLiteral* Parser::DoParseProgram(ParseInfo* info, Scope** scope, | 956 FunctionLiteral* Parser::DoParseProgram(ParseInfo* info) { |
960 Scope** eval_scope) { | |
961 // Note that this function can be called from the main thread or from a | 957 // Note that this function can be called from the main thread or from a |
962 // background thread. We should not access anything Isolate / heap dependent | 958 // background thread. We should not access anything Isolate / heap dependent |
963 // via ParseInfo, and also not pass it forward. | 959 // via ParseInfo, and also not pass it forward. |
964 DCHECK(scope_ == NULL); | 960 DCHECK(scope_ == NULL); |
965 DCHECK(target_stack_ == NULL); | 961 DCHECK(target_stack_ == NULL); |
966 | 962 |
967 FunctionLiteral* result = NULL; | 963 FunctionLiteral* result = NULL; |
968 { | 964 { |
969 *scope = NewScope(scope_, SCRIPT_SCOPE); | 965 Scope* scope = NewScope(scope_, SCRIPT_SCOPE); |
970 info->set_script_scope(*scope); | 966 info->set_script_scope(scope); |
971 if (!info->context().is_null() && !info->context()->IsNativeContext()) { | 967 if (!info->context().is_null() && !info->context()->IsNativeContext()) { |
972 *scope = Scope::DeserializeScopeChain(info->isolate(), zone(), | 968 scope = Scope::DeserializeScopeChain(info->isolate(), zone(), |
973 *info->context(), *scope); | 969 *info->context(), scope); |
974 // The Scope is backed up by ScopeInfo (which is in the V8 heap); this | 970 // The Scope is backed up by ScopeInfo (which is in the V8 heap); this |
975 // means the Parser cannot operate independent of the V8 heap. Tell the | 971 // means the Parser cannot operate independent of the V8 heap. Tell the |
976 // string table to internalize strings and values right after they're | 972 // string table to internalize strings and values right after they're |
977 // created. This kind of parsing can only be done in the main thread. | 973 // created. This kind of parsing can only be done in the main thread. |
978 DCHECK(parsing_on_main_thread_); | 974 DCHECK(parsing_on_main_thread_); |
979 ast_value_factory()->Internalize(info->isolate()); | 975 ast_value_factory()->Internalize(info->isolate()); |
980 } | 976 } |
981 original_scope_ = *scope; | 977 original_scope_ = scope; |
982 if (info->is_eval()) { | 978 if (info->is_eval()) { |
983 if (!(*scope)->is_script_scope() || is_strict(info->language_mode())) { | 979 if (!scope->is_script_scope() || is_strict(info->language_mode())) { |
984 *scope = NewScope(*scope, EVAL_SCOPE); | 980 scope = NewScope(scope, EVAL_SCOPE); |
985 } | 981 } |
986 } else if (info->is_module()) { | 982 } else if (info->is_module()) { |
987 *scope = NewScope(*scope, MODULE_SCOPE); | 983 scope = NewScope(scope, MODULE_SCOPE); |
988 } | 984 } |
989 (*scope)->set_start_position(0); | 985 |
990 // End position will be set by the caller. | 986 scope->set_start_position(0); |
991 | 987 |
992 // Compute the parsing mode. | 988 // Compute the parsing mode. |
993 Mode mode = (FLAG_lazy && allow_lazy()) ? PARSE_LAZILY : PARSE_EAGERLY; | 989 Mode mode = (FLAG_lazy && allow_lazy()) ? PARSE_LAZILY : PARSE_EAGERLY; |
994 if (allow_natives() || extension_ != NULL || | 990 if (allow_natives() || extension_ != NULL || scope->is_eval_scope()) { |
995 (*scope)->is_eval_scope()) { | |
996 mode = PARSE_EAGERLY; | 991 mode = PARSE_EAGERLY; |
997 } | 992 } |
998 ParsingModeScope parsing_mode(this, mode); | 993 ParsingModeScope parsing_mode(this, mode); |
999 | 994 |
1000 // Enters 'scope'. | 995 // Enters 'scope'. |
1001 AstNodeFactory function_factory(ast_value_factory()); | 996 AstNodeFactory function_factory(ast_value_factory()); |
1002 FunctionState function_state(&function_state_, &scope_, *scope, | 997 FunctionState function_state(&function_state_, &scope_, scope, |
1003 kNormalFunction, &function_factory); | 998 kNormalFunction, &function_factory); |
1004 | 999 |
1005 scope_->SetLanguageMode(info->language_mode()); | 1000 scope_->SetLanguageMode(info->language_mode()); |
1006 ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16, zone()); | 1001 ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16, zone()); |
1007 bool ok = true; | 1002 bool ok = true; |
1008 int beg_pos = scanner()->location().beg_pos; | 1003 int beg_pos = scanner()->location().beg_pos; |
1009 if (info->is_module()) { | 1004 if (info->is_module()) { |
1010 DCHECK(allow_harmony_modules()); | 1005 DCHECK(allow_harmony_modules()); |
1011 ParseModuleItemList(body, &ok); | 1006 ParseModuleItemList(body, &ok); |
1012 } else { | 1007 } else { |
1013 ParseStatementList(body, Token::EOS, info->is_eval(), eval_scope, &ok); | 1008 Scope* eval_scope = nullptr; |
| 1009 ParseStatementList(body, Token::EOS, info->is_eval(), &eval_scope, &ok); |
| 1010 if (eval_scope != nullptr) |
| 1011 eval_scope->set_end_position(scanner()->peek_location().beg_pos); |
1014 } | 1012 } |
1015 | 1013 |
| 1014 // The parser will peek but not consume EOS. Our scope logically goes all |
| 1015 // the way to the EOS, though. |
| 1016 scope->set_end_position(scanner()->peek_location().beg_pos); |
| 1017 |
1016 if (ok && is_strict(language_mode())) { | 1018 if (ok && is_strict(language_mode())) { |
1017 CheckStrictOctalLiteral(beg_pos, scanner()->location().end_pos, &ok); | 1019 CheckStrictOctalLiteral(beg_pos, scanner()->location().end_pos, &ok); |
1018 CheckConflictingVarDeclarations(scope_, &ok); | 1020 CheckConflictingVarDeclarations(scope_, &ok); |
1019 } | 1021 } |
1020 | 1022 |
1021 if (ok && info->parse_restriction() == ONLY_SINGLE_FUNCTION_LITERAL) { | 1023 if (ok && info->parse_restriction() == ONLY_SINGLE_FUNCTION_LITERAL) { |
1022 if (body->length() != 1 || | 1024 if (body->length() != 1 || |
1023 !body->at(0)->IsExpressionStatement() || | 1025 !body->at(0)->IsExpressionStatement() || |
1024 !body->at(0)->AsExpressionStatement()-> | 1026 !body->at(0)->AsExpressionStatement()-> |
1025 expression()->IsFunctionLiteral()) { | 1027 expression()->IsFunctionLiteral()) { |
(...skipping 4491 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5517 info->source_stream_encoding()); | 5519 info->source_stream_encoding()); |
5518 scanner_.Initialize(&stream); | 5520 scanner_.Initialize(&stream); |
5519 DCHECK(info->context().is_null() || info->context()->IsNativeContext()); | 5521 DCHECK(info->context().is_null() || info->context()->IsNativeContext()); |
5520 | 5522 |
5521 // When streaming, we don't know the length of the source until we have parsed | 5523 // When streaming, we don't know the length of the source until we have parsed |
5522 // it. The raw data can be UTF-8, so we wouldn't know the source length until | 5524 // it. The raw data can be UTF-8, so we wouldn't know the source length until |
5523 // we have decoded it anyway even if we knew the raw data length (which we | 5525 // we have decoded it anyway even if we knew the raw data length (which we |
5524 // don't). We work around this by storing all the scopes which need their end | 5526 // don't). We work around this by storing all the scopes which need their end |
5525 // position set at the end of the script (the top scope and possible eval | 5527 // position set at the end of the script (the top scope and possible eval |
5526 // scopes) and set their end position after we know the script length. | 5528 // scopes) and set their end position after we know the script length. |
5527 Scope* top_scope = NULL; | 5529 result = DoParseProgram(info); |
5528 Scope* eval_scope = NULL; | |
5529 result = DoParseProgram(info, &top_scope, &eval_scope); | |
5530 | |
5531 top_scope->set_end_position(scanner()->location().end_pos); | |
5532 if (eval_scope != NULL) { | |
5533 eval_scope->set_end_position(scanner()->location().end_pos); | |
5534 } | |
5535 | 5530 |
5536 info->set_literal(result); | 5531 info->set_literal(result); |
5537 | 5532 |
5538 // We cannot internalize on a background thread; a foreground task will take | 5533 // We cannot internalize on a background thread; a foreground task will take |
5539 // care of calling Parser::Internalize just before compilation. | 5534 // care of calling Parser::Internalize just before compilation. |
5540 | 5535 |
5541 if (produce_cached_parse_data()) { | 5536 if (produce_cached_parse_data()) { |
5542 if (result != NULL) *info->cached_data() = recorder.GetScriptData(); | 5537 if (result != NULL) *info->cached_data() = recorder.GetScriptData(); |
5543 log_ = NULL; | 5538 log_ = NULL; |
5544 } | 5539 } |
(...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5773 | 5768 |
5774 Expression* Parser::SpreadCallNew(Expression* function, | 5769 Expression* Parser::SpreadCallNew(Expression* function, |
5775 ZoneList<v8::internal::Expression*>* args, | 5770 ZoneList<v8::internal::Expression*>* args, |
5776 int pos) { | 5771 int pos) { |
5777 args->InsertAt(0, function, zone()); | 5772 args->InsertAt(0, function, zone()); |
5778 | 5773 |
5779 return factory()->NewCallRuntime( | 5774 return factory()->NewCallRuntime( |
5780 ast_value_factory()->reflect_construct_string(), NULL, args, pos); | 5775 ast_value_factory()->reflect_construct_string(), NULL, args, pos); |
5781 } | 5776 } |
5782 } } // namespace v8::internal | 5777 } } // namespace v8::internal |
OLD | NEW |