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