| 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/base/platform/platform.h" | 9 #include "src/base/platform/platform.h" |
| 10 #include "src/bootstrapper.h" | 10 #include "src/bootstrapper.h" |
| (...skipping 732 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 743 original_scope_(NULL), | 743 original_scope_(NULL), |
| 744 target_stack_(NULL), | 744 target_stack_(NULL), |
| 745 cached_parse_data_(NULL), | 745 cached_parse_data_(NULL), |
| 746 info_(info), | 746 info_(info), |
| 747 has_pending_error_(false), | 747 has_pending_error_(false), |
| 748 pending_error_message_(NULL), | 748 pending_error_message_(NULL), |
| 749 pending_error_arg_(NULL), | 749 pending_error_arg_(NULL), |
| 750 pending_error_char_arg_(NULL), | 750 pending_error_char_arg_(NULL), |
| 751 total_preparse_skipped_(0), | 751 total_preparse_skipped_(0), |
| 752 pre_parse_timer_(NULL) { | 752 pre_parse_timer_(NULL) { |
| 753 DCHECK(!script().is_null() || info->source_stream() != NULL); | 753 DCHECK(!script().is_null()); |
| 754 set_allow_harmony_scoping(!info->is_native() && FLAG_harmony_scoping); | 754 set_allow_harmony_scoping(!info->is_native() && FLAG_harmony_scoping); |
| 755 set_allow_modules(!info->is_native() && FLAG_harmony_modules); | 755 set_allow_modules(!info->is_native() && FLAG_harmony_modules); |
| 756 set_allow_natives_syntax(FLAG_allow_natives_syntax || info->is_native()); | 756 set_allow_natives_syntax(FLAG_allow_natives_syntax || info->is_native()); |
| 757 set_allow_lazy(false); // Must be explicitly enabled. | 757 set_allow_lazy(false); // Must be explicitly enabled. |
| 758 set_allow_generators(FLAG_harmony_generators); | 758 set_allow_generators(FLAG_harmony_generators); |
| 759 set_allow_arrow_functions(FLAG_harmony_arrow_functions); | 759 set_allow_arrow_functions(FLAG_harmony_arrow_functions); |
| 760 set_allow_harmony_numeric_literals(FLAG_harmony_numeric_literals); | 760 set_allow_harmony_numeric_literals(FLAG_harmony_numeric_literals); |
| 761 set_allow_classes(FLAG_harmony_classes); | 761 set_allow_classes(FLAG_harmony_classes); |
| 762 set_allow_harmony_object_literals(FLAG_harmony_object_literals); | 762 set_allow_harmony_object_literals(FLAG_harmony_object_literals); |
| 763 for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount; | 763 for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount; |
| (...skipping 27 matching lines...) Expand all Loading... |
| 791 CompleteParserRecorder recorder; | 791 CompleteParserRecorder recorder; |
| 792 | 792 |
| 793 if (compile_options() == ScriptCompiler::kProduceParserCache) { | 793 if (compile_options() == ScriptCompiler::kProduceParserCache) { |
| 794 log_ = &recorder; | 794 log_ = &recorder; |
| 795 } else if (compile_options() == ScriptCompiler::kConsumeParserCache) { | 795 } else if (compile_options() == ScriptCompiler::kConsumeParserCache) { |
| 796 cached_parse_data_->Initialize(); | 796 cached_parse_data_->Initialize(); |
| 797 } | 797 } |
| 798 | 798 |
| 799 source = String::Flatten(source); | 799 source = String::Flatten(source); |
| 800 FunctionLiteral* result; | 800 FunctionLiteral* result; |
| 801 | |
| 802 Scope* top_scope = NULL; | |
| 803 Scope* eval_scope = NULL; | |
| 804 if (source->IsExternalTwoByteString()) { | 801 if (source->IsExternalTwoByteString()) { |
| 805 // Notice that the stream is destroyed at the end of the branch block. | 802 // Notice that the stream is destroyed at the end of the branch block. |
| 806 // The last line of the blocks can't be moved outside, even though they're | 803 // The last line of the blocks can't be moved outside, even though they're |
| 807 // identical calls. | 804 // identical calls. |
| 808 ExternalTwoByteStringUtf16CharacterStream stream( | 805 ExternalTwoByteStringUtf16CharacterStream stream( |
| 809 Handle<ExternalTwoByteString>::cast(source), 0, source->length()); | 806 Handle<ExternalTwoByteString>::cast(source), 0, source->length()); |
| 810 scanner_.Initialize(&stream); | 807 scanner_.Initialize(&stream); |
| 811 result = DoParseProgram(info(), &top_scope, &eval_scope); | 808 result = DoParseProgram(info(), source); |
| 812 } else { | 809 } else { |
| 813 GenericStringUtf16CharacterStream stream(source, 0, source->length()); | 810 GenericStringUtf16CharacterStream stream(source, 0, source->length()); |
| 814 scanner_.Initialize(&stream); | 811 scanner_.Initialize(&stream); |
| 815 result = DoParseProgram(info(), &top_scope, &eval_scope); | 812 result = DoParseProgram(info(), source); |
| 816 } | |
| 817 top_scope->set_end_position(source->length()); | |
| 818 if (eval_scope != NULL) { | |
| 819 eval_scope->set_end_position(source->length()); | |
| 820 } | 813 } |
| 821 HandleSourceURLComments(); | 814 HandleSourceURLComments(); |
| 822 | 815 |
| 823 if (FLAG_trace_parse && result != NULL) { | 816 if (FLAG_trace_parse && result != NULL) { |
| 824 double ms = timer.Elapsed().InMillisecondsF(); | 817 double ms = timer.Elapsed().InMillisecondsF(); |
| 825 if (info()->is_eval()) { | 818 if (info()->is_eval()) { |
| 826 PrintF("[parsing eval"); | 819 PrintF("[parsing eval"); |
| 827 } else if (info()->script()->name()->IsString()) { | 820 } else if (info()->script()->name()->IsString()) { |
| 828 String* name = String::cast(info()->script()->name()); | 821 String* name = String::cast(info()->script()->name()); |
| 829 SmartArrayPointer<char> name_chars = name->ToCString(); | 822 SmartArrayPointer<char> name_chars = name->ToCString(); |
| 830 PrintF("[parsing script: %s", name_chars.get()); | 823 PrintF("[parsing script: %s", name_chars.get()); |
| 831 } else { | 824 } else { |
| 832 PrintF("[parsing script"); | 825 PrintF("[parsing script"); |
| 833 } | 826 } |
| 834 PrintF(" - took %0.3f ms]\n", ms); | 827 PrintF(" - took %0.3f ms]\n", ms); |
| 835 } | 828 } |
| 836 if (compile_options() == ScriptCompiler::kProduceParserCache) { | 829 if (compile_options() == ScriptCompiler::kProduceParserCache) { |
| 837 if (result != NULL) *info_->cached_data() = recorder.GetScriptData(); | 830 if (result != NULL) *info_->cached_data() = recorder.GetScriptData(); |
| 838 log_ = NULL; | 831 log_ = NULL; |
| 839 } | 832 } |
| 840 return result; | 833 return result; |
| 841 } | 834 } |
| 842 | 835 |
| 843 | 836 |
| 844 FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info, Scope** scope, | 837 FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info, |
| 845 Scope** eval_scope) { | 838 Handle<String> source) { |
| 846 DCHECK(scope_ == NULL); | 839 DCHECK(scope_ == NULL); |
| 847 DCHECK(target_stack_ == NULL); | 840 DCHECK(target_stack_ == NULL); |
| 848 | 841 |
| 849 FunctionLiteral* result = NULL; | 842 FunctionLiteral* result = NULL; |
| 850 { | 843 { Scope* scope = NewScope(scope_, GLOBAL_SCOPE); |
| 851 *scope = NewScope(scope_, GLOBAL_SCOPE); | 844 info->SetGlobalScope(scope); |
| 852 info->SetGlobalScope(*scope); | |
| 853 if (!info->context().is_null() && !info->context()->IsNativeContext()) { | 845 if (!info->context().is_null() && !info->context()->IsNativeContext()) { |
| 854 *scope = Scope::DeserializeScopeChain(*info->context(), *scope, zone()); | 846 scope = Scope::DeserializeScopeChain(*info->context(), scope, zone()); |
| 855 // The Scope is backed up by ScopeInfo (which is in the V8 heap); this | 847 // The Scope is backed up by ScopeInfo (which is in the V8 heap); this |
| 856 // means the Parser cannot operate independent of the V8 heap. Tell the | 848 // means the Parser cannot operate independent of the V8 heap. Tell the |
| 857 // string table to internalize strings and values right after they're | 849 // string table to internalize strings and values right after they're |
| 858 // created. | 850 // created. |
| 859 ast_value_factory()->Internalize(isolate()); | 851 ast_value_factory()->Internalize(isolate()); |
| 860 } | 852 } |
| 861 original_scope_ = *scope; | 853 original_scope_ = scope; |
| 862 if (info->is_eval()) { | 854 if (info->is_eval()) { |
| 863 if (!(*scope)->is_global_scope() || info->strict_mode() == STRICT) { | 855 if (!scope->is_global_scope() || info->strict_mode() == STRICT) { |
| 864 *scope = NewScope(*scope, EVAL_SCOPE); | 856 scope = NewScope(scope, EVAL_SCOPE); |
| 865 } | 857 } |
| 866 } else if (info->is_global()) { | 858 } else if (info->is_global()) { |
| 867 *scope = NewScope(*scope, GLOBAL_SCOPE); | 859 scope = NewScope(scope, GLOBAL_SCOPE); |
| 868 } | 860 } |
| 869 (*scope)->set_start_position(0); | 861 scope->set_start_position(0); |
| 870 // End position will be set by the caller. | 862 scope->set_end_position(source->length()); |
| 871 | 863 |
| 872 // Compute the parsing mode. | 864 // Compute the parsing mode. |
| 873 Mode mode = (FLAG_lazy && allow_lazy()) ? PARSE_LAZILY : PARSE_EAGERLY; | 865 Mode mode = (FLAG_lazy && allow_lazy()) ? PARSE_LAZILY : PARSE_EAGERLY; |
| 874 if (allow_natives_syntax() || extension_ != NULL || | 866 if (allow_natives_syntax() || |
| 875 (*scope)->is_eval_scope()) { | 867 extension_ != NULL || |
| 868 scope->is_eval_scope()) { |
| 876 mode = PARSE_EAGERLY; | 869 mode = PARSE_EAGERLY; |
| 877 } | 870 } |
| 878 ParsingModeScope parsing_mode(this, mode); | 871 ParsingModeScope parsing_mode(this, mode); |
| 879 | 872 |
| 880 // Enters 'scope'. | 873 // Enters 'scope'. |
| 881 FunctionState function_state(&function_state_, &scope_, *scope, zone(), | 874 FunctionState function_state(&function_state_, &scope_, scope, zone(), |
| 882 ast_value_factory(), info->ast_node_id_gen()); | 875 ast_value_factory(), info->ast_node_id_gen()); |
| 883 | 876 |
| 884 scope_->SetStrictMode(info->strict_mode()); | 877 scope_->SetStrictMode(info->strict_mode()); |
| 885 ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16, zone()); | 878 ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16, zone()); |
| 886 bool ok = true; | 879 bool ok = true; |
| 887 int beg_pos = scanner()->location().beg_pos; | 880 int beg_pos = scanner()->location().beg_pos; |
| 888 ParseSourceElements(body, Token::EOS, info->is_eval(), true, eval_scope, | 881 ParseSourceElements(body, Token::EOS, info->is_eval(), true, &ok); |
| 889 &ok); | |
| 890 | 882 |
| 891 if (ok && strict_mode() == STRICT) { | 883 if (ok && strict_mode() == STRICT) { |
| 892 CheckOctalLiteral(beg_pos, scanner()->location().end_pos, &ok); | 884 CheckOctalLiteral(beg_pos, scanner()->location().end_pos, &ok); |
| 893 } | 885 } |
| 894 | 886 |
| 895 if (ok && allow_harmony_scoping() && strict_mode() == STRICT) { | 887 if (ok && allow_harmony_scoping() && strict_mode() == STRICT) { |
| 896 CheckConflictingVarDeclarations(scope_, &ok); | 888 CheckConflictingVarDeclarations(scope_, &ok); |
| 897 } | 889 } |
| 898 | 890 |
| 899 if (ok && info->parse_restriction() == ONLY_SINGLE_FUNCTION_LITERAL) { | 891 if (ok && info->parse_restriction() == ONLY_SINGLE_FUNCTION_LITERAL) { |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1024 | 1016 |
| 1025 if (result != NULL) { | 1017 if (result != NULL) { |
| 1026 Handle<String> inferred_name(shared_info->inferred_name()); | 1018 Handle<String> inferred_name(shared_info->inferred_name()); |
| 1027 result->set_inferred_name(inferred_name); | 1019 result->set_inferred_name(inferred_name); |
| 1028 } | 1020 } |
| 1029 return result; | 1021 return result; |
| 1030 } | 1022 } |
| 1031 | 1023 |
| 1032 | 1024 |
| 1033 void* Parser::ParseSourceElements(ZoneList<Statement*>* processor, | 1025 void* Parser::ParseSourceElements(ZoneList<Statement*>* processor, |
| 1034 int end_token, bool is_eval, bool is_global, | 1026 int end_token, |
| 1035 Scope** eval_scope, bool* ok) { | 1027 bool is_eval, |
| 1028 bool is_global, |
| 1029 bool* ok) { |
| 1036 // SourceElements :: | 1030 // SourceElements :: |
| 1037 // (ModuleElement)* <end_token> | 1031 // (ModuleElement)* <end_token> |
| 1038 | 1032 |
| 1039 // Allocate a target stack to use for this set of source | 1033 // Allocate a target stack to use for this set of source |
| 1040 // elements. This way, all scripts and functions get their own | 1034 // elements. This way, all scripts and functions get their own |
| 1041 // target stack thus avoiding illegal breaks and continues across | 1035 // target stack thus avoiding illegal breaks and continues across |
| 1042 // functions. | 1036 // functions. |
| 1043 TargetScope scope(&this->target_stack_); | 1037 TargetScope scope(&this->target_stack_); |
| 1044 | 1038 |
| 1045 DCHECK(processor != NULL); | 1039 DCHECK(processor != NULL); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1081 // as specified in ES5 10.4.2(3). The correct fix would be to always | 1075 // as specified in ES5 10.4.2(3). The correct fix would be to always |
| 1082 // add this scope in DoParseProgram(), but that requires adaptations | 1076 // add this scope in DoParseProgram(), but that requires adaptations |
| 1083 // all over the code base, so we go with a quick-fix for now. | 1077 // all over the code base, so we go with a quick-fix for now. |
| 1084 // In the same manner, we have to patch the parsing mode. | 1078 // In the same manner, we have to patch the parsing mode. |
| 1085 if (is_eval && !scope_->is_eval_scope()) { | 1079 if (is_eval && !scope_->is_eval_scope()) { |
| 1086 DCHECK(scope_->is_global_scope()); | 1080 DCHECK(scope_->is_global_scope()); |
| 1087 Scope* scope = NewScope(scope_, EVAL_SCOPE); | 1081 Scope* scope = NewScope(scope_, EVAL_SCOPE); |
| 1088 scope->set_start_position(scope_->start_position()); | 1082 scope->set_start_position(scope_->start_position()); |
| 1089 scope->set_end_position(scope_->end_position()); | 1083 scope->set_end_position(scope_->end_position()); |
| 1090 scope_ = scope; | 1084 scope_ = scope; |
| 1091 if (eval_scope != NULL) { | |
| 1092 // Caller will correct the positions of the ad hoc eval scope. | |
| 1093 *eval_scope = scope; | |
| 1094 } | |
| 1095 mode_ = PARSE_EAGERLY; | 1085 mode_ = PARSE_EAGERLY; |
| 1096 } | 1086 } |
| 1097 scope_->SetStrictMode(STRICT); | 1087 scope_->SetStrictMode(STRICT); |
| 1098 // "use strict" is the only directive for now. | 1088 // "use strict" is the only directive for now. |
| 1099 directive_prologue = false; | 1089 directive_prologue = false; |
| 1100 } else if (literal->raw_value()->AsString() == | 1090 } else if (literal->raw_value()->AsString() == |
| 1101 ast_value_factory()->use_asm_string() && | 1091 ast_value_factory()->use_asm_string() && |
| 1102 token_loc.end_pos - token_loc.beg_pos == | 1092 token_loc.end_pos - token_loc.beg_pos == |
| 1103 ast_value_factory()->use_asm_string()->length() + 2) { | 1093 ast_value_factory()->use_asm_string()->length() + 2) { |
| 1104 // Store the usage count; The actual use counter on the isolate is | 1094 // Store the usage count; The actual use counter on the isolate is |
| (...skipping 2620 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3725 Assignment* assignment = factory()->NewAssignment( | 3715 Assignment* assignment = factory()->NewAssignment( |
| 3726 Token::INIT_VAR, init_proxy, allocation, RelocInfo::kNoPosition); | 3716 Token::INIT_VAR, init_proxy, allocation, RelocInfo::kNoPosition); |
| 3727 VariableProxy* get_proxy = factory()->NewVariableProxy( | 3717 VariableProxy* get_proxy = factory()->NewVariableProxy( |
| 3728 function_state_->generator_object_variable()); | 3718 function_state_->generator_object_variable()); |
| 3729 Yield* yield = factory()->NewYield( | 3719 Yield* yield = factory()->NewYield( |
| 3730 get_proxy, assignment, Yield::kInitial, RelocInfo::kNoPosition); | 3720 get_proxy, assignment, Yield::kInitial, RelocInfo::kNoPosition); |
| 3731 body->Add(factory()->NewExpressionStatement( | 3721 body->Add(factory()->NewExpressionStatement( |
| 3732 yield, RelocInfo::kNoPosition), zone()); | 3722 yield, RelocInfo::kNoPosition), zone()); |
| 3733 } | 3723 } |
| 3734 | 3724 |
| 3735 ParseSourceElements(body, Token::RBRACE, false, false, NULL, CHECK_OK); | 3725 ParseSourceElements(body, Token::RBRACE, false, false, CHECK_OK); |
| 3736 | 3726 |
| 3737 if (is_generator) { | 3727 if (is_generator) { |
| 3738 VariableProxy* get_proxy = factory()->NewVariableProxy( | 3728 VariableProxy* get_proxy = factory()->NewVariableProxy( |
| 3739 function_state_->generator_object_variable()); | 3729 function_state_->generator_object_variable()); |
| 3740 Expression* undefined = | 3730 Expression* undefined = |
| 3741 factory()->NewUndefinedLiteral(RelocInfo::kNoPosition); | 3731 factory()->NewUndefinedLiteral(RelocInfo::kNoPosition); |
| 3742 Yield* yield = factory()->NewYield(get_proxy, undefined, Yield::kFinal, | 3732 Yield* yield = factory()->NewYield(get_proxy, undefined, Yield::kFinal, |
| 3743 RelocInfo::kNoPosition); | 3733 RelocInfo::kNoPosition); |
| 3744 body->Add(factory()->NewExpressionStatement( | 3734 body->Add(factory()->NewExpressionStatement( |
| 3745 yield, RelocInfo::kNoPosition), zone()); | 3735 yield, RelocInfo::kNoPosition), zone()); |
| (...skipping 1096 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4842 SetCachedData(); | 4832 SetCachedData(); |
| 4843 result = ParseProgram(); | 4833 result = ParseProgram(); |
| 4844 } | 4834 } |
| 4845 info()->SetFunction(result); | 4835 info()->SetFunction(result); |
| 4846 | 4836 |
| 4847 Internalize(); | 4837 Internalize(); |
| 4848 DCHECK(ast_value_factory()->IsInternalized()); | 4838 DCHECK(ast_value_factory()->IsInternalized()); |
| 4849 return (result != NULL); | 4839 return (result != NULL); |
| 4850 } | 4840 } |
| 4851 | 4841 |
| 4852 | |
| 4853 void Parser::ParseOnBackground() { | |
| 4854 DCHECK(info()->function() == NULL); | |
| 4855 FunctionLiteral* result = NULL; | |
| 4856 fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone()); | |
| 4857 | |
| 4858 CompleteParserRecorder recorder; | |
| 4859 if (compile_options() == ScriptCompiler::kProduceParserCache) { | |
| 4860 log_ = &recorder; | |
| 4861 } | |
| 4862 | |
| 4863 DCHECK(info()->source_stream() != NULL); | |
| 4864 ExternalStreamingStream stream(info()->source_stream(), | |
| 4865 info()->source_stream_encoding()); | |
| 4866 scanner_.Initialize(&stream); | |
| 4867 DCHECK(info()->context().is_null() || info()->context()->IsNativeContext()); | |
| 4868 | |
| 4869 // When streaming, we don't know the length of the source until we have parsed | |
| 4870 // it. The raw data can be UTF-8, so we wouldn't know the source length until | |
| 4871 // we have decoded it anyway even if we knew the raw data length (which we | |
| 4872 // don't). We work around this by storing all the scopes which need their end | |
| 4873 // position set at the end of the script (the top scope and possible eval | |
| 4874 // scopes) and set their end position after we know the script length. | |
| 4875 Scope* top_scope = NULL; | |
| 4876 Scope* eval_scope = NULL; | |
| 4877 result = DoParseProgram(info(), &top_scope, &eval_scope); | |
| 4878 | |
| 4879 top_scope->set_end_position(scanner()->location().end_pos); | |
| 4880 if (eval_scope != NULL) { | |
| 4881 eval_scope->set_end_position(scanner()->location().end_pos); | |
| 4882 } | |
| 4883 | |
| 4884 info()->SetFunction(result); | |
| 4885 | |
| 4886 // We cannot internalize on a background thread; a foreground task will take | |
| 4887 // care of calling Parser::Internalize just before compilation. | |
| 4888 | |
| 4889 if (compile_options() == ScriptCompiler::kProduceParserCache) { | |
| 4890 if (result != NULL) *info_->cached_data() = recorder.GetScriptData(); | |
| 4891 log_ = NULL; | |
| 4892 } | |
| 4893 } | |
| 4894 } } // namespace v8::internal | 4842 } } // namespace v8::internal |
| OLD | NEW |