Parsing: Make Parser not know about Isolate during background parsing.
authormarja <marja@chromium.org>
Thu, 12 Feb 2015 13:02:30 +0000 (05:02 -0800)
committerCommit bot <commit-bot@chromium.org>
Thu, 12 Feb 2015 13:02:44 +0000 (13:02 +0000)
Parser must be able to operate independent of Isolate and the V8 heap during
parsing. After the heap-independent phase, there is a heap dependent phase,
during which we internalize strings, handle errors, etc.

This makes Isolate (also via CompilationInfo) unaccessible during parsing, and
thus decreases the probability of accidental code changes which would add
heap-dependent operations into the heap-independent phase.

Since Isolate is also accessible via CompilationInfo, now CompilationInfo is
only passed to the entry points of parsing, and not stored in Parser.

R=rossberg@chromium.org
BUG=

Review URL: https://codereview.chromium.org/908173003

Cr-Commit-Position: refs/heads/master@{#26612}

13 files changed:
src/api.cc
src/background-parsing-task.cc
src/compiler.cc
src/parser.cc
src/parser.h
src/preparser.h
src/runtime/runtime-debug.cc
src/runtime/runtime-internal.cc
test/cctest/compiler/function-tester.h
test/cctest/compiler/test-codegen-deopt.cc
test/cctest/compiler/test-loop-assignment-analysis.cc
test/cctest/test-parsing.cc
tools/parser-shell.cc

index f2fffa2..ec9978e 100644 (file)
@@ -1727,8 +1727,8 @@ Local<Script> ScriptCompiler::Compile(Isolate* v8_isolate,
 
     // Do the parsing tasks which need to be done on the main thread. This will
     // also handle parse errors.
-    source->parser->Internalize();
-    source->parser->HandleSourceURLComments();
+    source->parser->Internalize(source->info.get());
+    source->parser->HandleSourceURLComments(source->info.get());
 
     i::Handle<i::SharedFunctionInfo> result =
         i::Handle<i::SharedFunctionInfo>::null();
index 393a948..cb31cc9 100644 (file)
@@ -54,7 +54,7 @@ void BackgroundParsingTask::Run() {
                                    source_->hash_seed,
                                    &source_->unicode_cache));
   source_->parser->set_allow_lazy(source_->allow_lazy);
-  source_->parser->ParseOnBackground();
+  source_->parser->ParseOnBackground(source_->info.get());
 
   if (script_data != NULL) {
     source_->cached_data.Reset(new ScriptCompiler::CachedData(
index c1e852b..12d7aaf 100644 (file)
@@ -645,7 +645,7 @@ MUST_USE_RESULT static MaybeHandle<Code> GetUnoptimizedCodeCommon(
   PostponeInterruptsScope postpone(info->isolate());
 
   // Parse and update CompilationInfo with the results.
-  if (!Parser::Parse(info)) return MaybeHandle<Code>();
+  if (!Parser::ParseStatic(info)) return MaybeHandle<Code>();
   Handle<SharedFunctionInfo> shared = info->shared_info();
   FunctionLiteral* lit = info->function();
   shared->set_language_mode(lit->language_mode());
@@ -817,7 +817,7 @@ bool Compiler::Analyze(CompilationInfo* info) {
 
 
 bool Compiler::ParseAndAnalyze(CompilationInfo* info) {
-  if (!Parser::Parse(info)) return false;
+  if (!Parser::ParseStatic(info)) return false;
   return Compiler::Analyze(info);
 }
 
@@ -1058,7 +1058,7 @@ void Compiler::CompileForLiveEdit(Handle<Script> script) {
   VMState<COMPILER> state(info.isolate());
 
   info.MarkAsGlobal();
-  if (!Parser::Parse(&info)) return;
+  if (!Parser::ParseStatic(&info)) return;
 
   LiveEditFunctionTracker tracker(info.isolate(), info.function());
   if (!CompileUnoptimizedCode(&info)) return;
@@ -1108,7 +1108,7 @@ static Handle<SharedFunctionInfo> CompileToplevel(CompilationInfo* info) {
         // data while parsing eagerly is not implemented.
         info->SetCachedData(NULL, ScriptCompiler::kNoCompileOptions);
       }
-      if (!Parser::Parse(info, parse_allow_lazy)) {
+      if (!Parser::ParseStatic(info, parse_allow_lazy)) {
         return Handle<SharedFunctionInfo>::null();
       }
     }
index c1e6815..6db2b0d 100644 (file)
@@ -251,13 +251,13 @@ int ParseData::FunctionsSize() {
 }
 
 
-void Parser::SetCachedData() {
-  if (compile_options() == ScriptCompiler::kNoCompileOptions) {
+void Parser::SetCachedData(CompilationInfo* info) {
+  if (compile_options_ == ScriptCompiler::kNoCompileOptions) {
     cached_parse_data_ = NULL;
   } else {
-    DCHECK(info_->cached_data() != NULL);
-    if (compile_options() == ScriptCompiler::kConsumeParserCache) {
-      cached_parse_data_ = ParseData::FromCachedData(*info_->cached_data());
+    DCHECK(info->cached_data() != NULL);
+    if (compile_options_ == ScriptCompiler::kConsumeParserCache) {
+      cached_parse_data_ = ParseData::FromCachedData(*info->cached_data());
     }
   }
 }
@@ -790,23 +790,27 @@ ClassLiteral* ParserTraits::ParseClassLiteral(
 
 Parser::Parser(CompilationInfo* info, uintptr_t stack_limit, uint32_t hash_seed,
                UnicodeCache* unicode_cache)
-    : ParserBase<ParserTraits>(info->isolate(), info->zone(), &scanner_,
-                               stack_limit, info->extension(),
-                               info->ast_value_factory(), NULL, this),
+    : ParserBase<ParserTraits>(info->zone(), &scanner_, stack_limit,
+                               info->extension(), info->ast_value_factory(),
+                               NULL, this),
       scanner_(unicode_cache),
       reusable_preparser_(NULL),
       original_scope_(NULL),
       target_stack_(NULL),
+      compile_options_(info->compile_options()),
       cached_parse_data_(NULL),
-      info_(info),
       parsing_lazy_arrow_parameters_(false),
       has_pending_error_(false),
       pending_error_message_(NULL),
       pending_error_arg_(NULL),
       pending_error_char_arg_(NULL),
       total_preparse_skipped_(0),
-      pre_parse_timer_(NULL) {
-  DCHECK(!script().is_null() || info->source_stream() != NULL);
+      pre_parse_timer_(NULL),
+      parsing_on_main_thread_(true) {
+  // Even though we were passed CompilationInfo, we should not store it in
+  // Parser - this makes sure that Isolate is not accidentally accessed via
+  // CompilationInfo during background parsing.
+  DCHECK(!info->script().is_null() || info->source_stream() != NULL);
   set_allow_lazy(false);  // Must be explicitly enabled.
   set_allow_natives(FLAG_allow_natives_syntax || info->is_native());
   set_allow_harmony_scoping(!info->is_native() && FLAG_harmony_scoping);
@@ -834,15 +838,18 @@ Parser::Parser(CompilationInfo* info, uintptr_t stack_limit, uint32_t hash_seed,
 }
 
 
-FunctionLiteral* Parser::ParseProgram() {
+FunctionLiteral* Parser::ParseProgram(CompilationInfo* info) {
   // TODO(bmeurer): We temporarily need to pass allow_nesting = true here,
   // see comment for HistogramTimerScope class.
 
-  // It's OK to use the counters here, since this function is only called in
-  // the main thread.
-  HistogramTimerScope timer_scope(isolate()->counters()->parse(), true);
-  Handle<String> source(String::cast(script()->source()));
-  isolate()->counters()->total_parse_size()->Increment(source->length());
+  // It's OK to use the Isolate & counters here, since this function is only
+  // called in the main thread.
+  DCHECK(parsing_on_main_thread_);
+
+  Isolate* isolate = info->isolate();
+  HistogramTimerScope timer_scope(isolate->counters()->parse(), true);
+  Handle<String> source(String::cast(info->script()->source()));
+  isolate->counters()->total_parse_size()->Increment(source->length());
   base::ElapsedTimer timer;
   if (FLAG_trace_parse) {
     timer.Start();
@@ -870,24 +877,24 @@ FunctionLiteral* Parser::ParseProgram() {
     ExternalTwoByteStringUtf16CharacterStream stream(
         Handle<ExternalTwoByteString>::cast(source), 0, source->length());
     scanner_.Initialize(&stream);
-    result = DoParseProgram(info(), &top_scope, &eval_scope);
+    result = DoParseProgram(info, &top_scope, &eval_scope);
   } else {
     GenericStringUtf16CharacterStream stream(source, 0, source->length());
     scanner_.Initialize(&stream);
-    result = DoParseProgram(info(), &top_scope, &eval_scope);
+    result = DoParseProgram(info, &top_scope, &eval_scope);
   }
   top_scope->set_end_position(source->length());
   if (eval_scope != NULL) {
     eval_scope->set_end_position(source->length());
   }
-  HandleSourceURLComments();
+  HandleSourceURLComments(info);
 
   if (FLAG_trace_parse && result != NULL) {
     double ms = timer.Elapsed().InMillisecondsF();
-    if (info()->is_eval()) {
+    if (info->is_eval()) {
       PrintF("[parsing eval");
-    } else if (info()->script()->name()->IsString()) {
-      String* name = String::cast(info()->script()->name());
+    } else if (info->script()->name()->IsString()) {
+      String* name = String::cast(info->script()->name());
       SmartArrayPointer<char> name_chars = name->ToCString();
       PrintF("[parsing script: %s", name_chars.get());
     } else {
@@ -896,7 +903,7 @@ FunctionLiteral* Parser::ParseProgram() {
     PrintF(" - took %0.3f ms]\n", ms);
   }
   if (produce_cached_parse_data()) {
-    if (result != NULL) *info_->cached_data() = recorder.GetScriptData();
+    if (result != NULL) *info->cached_data() = recorder.GetScriptData();
     log_ = NULL;
   }
   return result;
@@ -905,6 +912,9 @@ FunctionLiteral* Parser::ParseProgram() {
 
 FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info, Scope** scope,
                                         Scope** eval_scope) {
+  // Note that this function can be called from the main thread or from a
+  // background thread. We should not access anything Isolate / heap dependent
+  // via CompilationInfo, and also not pass it forward.
   DCHECK(scope_ == NULL);
   DCHECK(target_stack_ == NULL);
 
@@ -918,8 +928,9 @@ FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info, Scope** scope,
       // The Scope is backed up by ScopeInfo (which is in the V8 heap); this
       // means the Parser cannot operate independent of the V8 heap. Tell the
       // string table to internalize strings and values right after they're
-      // created.
-      ast_value_factory()->Internalize(isolate());
+      // created. This kind of parsing can only be done in the main thread.
+      DCHECK(parsing_on_main_thread_);
+      ast_value_factory()->Internalize(info->isolate());
     }
     original_scope_ = *scope;
     if (info->is_eval()) {
@@ -996,17 +1007,18 @@ FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info, Scope** scope,
 }
 
 
-FunctionLiteral* Parser::ParseLazy() {
-  // It's OK to use the counters here, since this function is only called in
-  // the main thread.
-  HistogramTimerScope timer_scope(isolate()->counters()->parse_lazy());
-  Handle<String> source(String::cast(script()->source()));
-  isolate()->counters()->total_parse_size()->Increment(source->length());
+FunctionLiteral* Parser::ParseLazy(CompilationInfo* info) {
+  // It's OK to use the Isolate & counters here, since this function is only
+  // called in the main thread.
+  DCHECK(parsing_on_main_thread_);
+  HistogramTimerScope timer_scope(info->isolate()->counters()->parse_lazy());
+  Handle<String> source(String::cast(info->script()->source()));
+  info->isolate()->counters()->total_parse_size()->Increment(source->length());
   base::ElapsedTimer timer;
   if (FLAG_trace_parse) {
     timer.Start();
   }
-  Handle<SharedFunctionInfo> shared_info = info()->shared_info();
+  Handle<SharedFunctionInfo> shared_info = info->shared_info();
 
   // Initialize parser state.
   source = String::Flatten(source);
@@ -1016,12 +1028,12 @@ FunctionLiteral* Parser::ParseLazy() {
         Handle<ExternalTwoByteString>::cast(source),
         shared_info->start_position(),
         shared_info->end_position());
-    result = ParseLazy(&stream);
+    result = ParseLazy(info, &stream);
   } else {
     GenericStringUtf16CharacterStream stream(source,
                                              shared_info->start_position(),
                                              shared_info->end_position());
-    result = ParseLazy(&stream);
+    result = ParseLazy(info, &stream);
   }
 
   if (FLAG_trace_parse && result != NULL) {
@@ -1033,8 +1045,9 @@ FunctionLiteral* Parser::ParseLazy() {
 }
 
 
-FunctionLiteral* Parser::ParseLazy(Utf16CharacterStream* source) {
-  Handle<SharedFunctionInfo> shared_info = info()->shared_info();
+FunctionLiteral* Parser::ParseLazy(CompilationInfo* info,
+                                   Utf16CharacterStream* source) {
+  Handle<SharedFunctionInfo> shared_info = info->shared_info();
   scanner_.Initialize(source);
   DCHECK(scope_ == NULL);
   DCHECK(target_stack_ == NULL);
@@ -1053,18 +1066,21 @@ FunctionLiteral* Parser::ParseLazy(Utf16CharacterStream* source) {
   {
     // Parse the function literal.
     Scope* scope = NewScope(scope_, SCRIPT_SCOPE);
-    info()->SetScriptScope(scope);
-    if (!info()->closure().is_null()) {
-      scope = Scope::DeserializeScopeChain(isolate(), zone(),
-                                           info()->closure()->context(), scope);
+    info->SetScriptScope(scope);
+    if (!info->closure().is_null()) {
+      // Ok to use Isolate here, since lazy function parsing is only done in the
+      // main thread.
+      DCHECK(parsing_on_main_thread_);
+      scope = Scope::DeserializeScopeChain(info->isolate(), zone(),
+                                           info->closure()->context(), scope);
     }
     original_scope_ = scope;
     AstNodeFactory function_factory(ast_value_factory());
     FunctionState function_state(&function_state_, &scope_, scope,
                                  shared_info->kind(), &function_factory);
     DCHECK(is_sloppy(scope->language_mode()) ||
-           is_strict(info()->language_mode()));
-    DCHECK(info()->language_mode() == shared_info->language_mode());
+           is_strict(info->language_mode()));
+    DCHECK(info->language_mode() == shared_info->language_mode());
     scope->SetLanguageMode(shared_info->language_mode());
     FunctionLiteral::FunctionType function_type = shared_info->is_expression()
         ? (shared_info->is_anonymous()
@@ -4009,8 +4025,8 @@ PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser(
   DCHECK_EQ(Token::LBRACE, scanner()->current_token());
 
   if (reusable_preparser_ == NULL) {
-    reusable_preparser_ = new PreParser(
-        isolate(), zone(), &scanner_, ast_value_factory(), NULL, stack_limit_);
+    reusable_preparser_ = new PreParser(zone(), &scanner_, ast_value_factory(),
+                                        NULL, stack_limit_);
     reusable_preparser_->set_allow_lazy(true);
     reusable_preparser_->set_allow_natives(allow_natives());
     reusable_preparser_->set_allow_harmony_scoping(allow_harmony_scoping());
@@ -4250,25 +4266,26 @@ IterationStatement* Parser::LookupContinueTarget(const AstRawString* label,
 }
 
 
-void Parser::HandleSourceURLComments() {
+void Parser::HandleSourceURLComments(CompilationInfo* info) {
   if (scanner_.source_url()->length() > 0) {
-    Handle<String> source_url = scanner_.source_url()->Internalize(isolate());
-    info_->script()->set_source_url(*source_url);
+    Handle<String> source_url =
+        scanner_.source_url()->Internalize(info->isolate());
+    info->script()->set_source_url(*source_url);
   }
   if (scanner_.source_mapping_url()->length() > 0) {
     Handle<String> source_mapping_url =
-        scanner_.source_mapping_url()->Internalize(isolate());
-    info_->script()->set_source_mapping_url(*source_mapping_url);
+        scanner_.source_mapping_url()->Internalize(info->isolate());
+    info->script()->set_source_mapping_url(*source_mapping_url);
   }
 }
 
 
-void Parser::ThrowPendingError() {
+void Parser::ThrowPendingError(Isolate* isolate, Handle<Script> script) {
   DCHECK(ast_value_factory()->IsInternalized());
   if (has_pending_error_) {
-    MessageLocation location(script(), pending_error_location_.beg_pos,
+    MessageLocation location(script, pending_error_location_.beg_pos,
                              pending_error_location_.end_pos);
-    Factory* factory = isolate()->factory();
+    Factory* factory = isolate->factory();
     bool has_arg =
         pending_error_arg_ != NULL || pending_error_char_arg_ != NULL;
     Handle<FixedArray> elements = factory->NewFixedArray(has_arg ? 1 : 0);
@@ -4281,7 +4298,7 @@ void Parser::ThrowPendingError() {
           .ToHandleChecked();
       elements->set(0, *arg_string);
     }
-    isolate()->debug()->OnCompileError(script());
+    isolate->debug()->OnCompileError(script);
 
     Handle<JSArray> array = factory->NewJSArrayWithElements(elements);
     Handle<Object> error;
@@ -4294,35 +4311,34 @@ void Parser::ThrowPendingError() {
       Handle<JSObject> jserror = Handle<JSObject>::cast(error);
 
       Handle<Name> key_start_pos = factory->error_start_pos_symbol();
-      JSObject::SetProperty(
-          jserror, key_start_pos,
-          handle(Smi::FromInt(location.start_pos()), isolate()),
-          SLOPPY).Check();
+      JSObject::SetProperty(jserror, key_start_pos,
+                            handle(Smi::FromInt(location.start_pos()), isolate),
+                            SLOPPY).Check();
 
       Handle<Name> key_end_pos = factory->error_end_pos_symbol();
       JSObject::SetProperty(jserror, key_end_pos,
-                            handle(Smi::FromInt(location.end_pos()), isolate()),
+                            handle(Smi::FromInt(location.end_pos()), isolate),
                             SLOPPY).Check();
 
       Handle<Name> key_script = factory->error_script_symbol();
-      JSObject::SetProperty(jserror, key_script, script(), SLOPPY).Check();
+      JSObject::SetProperty(jserror, key_script, script, SLOPPY).Check();
 
-      isolate()->Throw(*error, &location);
+      isolate->Throw(*error, &location);
     }
   }
 }
 
 
-void Parser::Internalize() {
+void Parser::Internalize(CompilationInfo* info) {
   // Internalize strings.
-  ast_value_factory()->Internalize(isolate());
+  ast_value_factory()->Internalize(info->isolate());
 
   // Error processing.
-  if (info()->function() == NULL) {
+  if (info->function() == NULL) {
     if (stack_overflow()) {
-      isolate()->StackOverflow();
+      info->isolate()->StackOverflow();
     } else {
-      ThrowPendingError();
+      ThrowPendingError(info->isolate(), info->script());
     }
   }
 
@@ -4330,10 +4346,10 @@ void Parser::Internalize() {
   for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount;
        ++feature) {
     for (int i = 0; i < use_counts_[feature]; ++i) {
-      isolate()->CountUsage(v8::Isolate::UseCounterFeature(feature));
+      info->isolate()->CountUsage(v8::Isolate::UseCounterFeature(feature));
     }
   }
-  isolate()->counters()->total_preparse_skipped()->Increment(
+  info->isolate()->counters()->total_preparse_skipped()->Increment(
       total_preparse_skipped_);
 }
 
@@ -5251,12 +5267,12 @@ bool RegExpParser::ParseRegExp(Isolate* isolate, Zone* zone,
 }
 
 
-bool Parser::Parse(CompilationInfo* info, bool allow_lazy) {
+bool Parser::ParseStatic(CompilationInfo* info, bool allow_lazy) {
   Parser parser(info, info->isolate()->stack_guard()->real_climit(),
                 info->isolate()->heap()->HashSeed(),
                 info->isolate()->unicode_cache());
   parser.set_allow_lazy(allow_lazy);
-  if (parser.Parse()) {
+  if (parser.Parse(info)) {
     info->SetLanguageMode(info->function()->language_mode());
     return true;
   }
@@ -5264,49 +5280,54 @@ bool Parser::Parse(CompilationInfo* info, bool allow_lazy) {
 }
 
 
-bool Parser::Parse() {
-  DCHECK(info()->function() == NULL);
+bool Parser::Parse(CompilationInfo* info) {
+  DCHECK(info->function() == NULL);
   FunctionLiteral* result = NULL;
-  pre_parse_timer_ = isolate()->counters()->pre_parse();
+  // Ok to use Isolate here; this function is only called in the main thread.
+  DCHECK(parsing_on_main_thread_);
+  Isolate* isolate = info->isolate();
+  pre_parse_timer_ = isolate->counters()->pre_parse();
   if (FLAG_trace_parse || allow_natives() || extension_ != NULL) {
     // If intrinsics are allowed, the Parser cannot operate independent of the
     // V8 heap because of Runtime. Tell the string table to internalize strings
     // and values right after they're created.
-    ast_value_factory()->Internalize(isolate());
+    ast_value_factory()->Internalize(isolate);
   }
 
-  if (info()->is_lazy()) {
-    DCHECK(!info()->is_eval());
-    if (info()->shared_info()->is_function()) {
-      result = ParseLazy();
+  if (info->is_lazy()) {
+    DCHECK(!info->is_eval());
+    if (info->shared_info()->is_function()) {
+      result = ParseLazy(info);
     } else {
-      result = ParseProgram();
+      result = ParseProgram(info);
     }
   } else {
-    SetCachedData();
-    result = ParseProgram();
+    SetCachedData(info);
+    result = ParseProgram(info);
   }
-  info()->SetFunction(result);
+  info->SetFunction(result);
 
-  Internalize();
+  Internalize(info);
   DCHECK(ast_value_factory()->IsInternalized());
   return (result != NULL);
 }
 
 
-void Parser::ParseOnBackground() {
-  DCHECK(info()->function() == NULL);
+void Parser::ParseOnBackground(CompilationInfo* info) {
+  parsing_on_main_thread_ = false;
+
+  DCHECK(info->function() == NULL);
   FunctionLiteral* result = NULL;
   fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone());
 
   CompleteParserRecorder recorder;
   if (produce_cached_parse_data()) log_ = &recorder;
 
-  DCHECK(info()->source_stream() != NULL);
-  ExternalStreamingStream stream(info()->source_stream(),
-                                 info()->source_stream_encoding());
+  DCHECK(info->source_stream() != NULL);
+  ExternalStreamingStream stream(info->source_stream(),
+                                 info->source_stream_encoding());
   scanner_.Initialize(&stream);
-  DCHECK(info()->context().is_null() || info()->context()->IsNativeContext());
+  DCHECK(info->context().is_null() || info->context()->IsNativeContext());
 
   // When streaming, we don't know the length of the source until we have parsed
   // it. The raw data can be UTF-8, so we wouldn't know the source length until
@@ -5316,20 +5337,20 @@ void Parser::ParseOnBackground() {
   // scopes) and set their end position after we know the script length.
   Scope* top_scope = NULL;
   Scope* eval_scope = NULL;
-  result = DoParseProgram(info(), &top_scope, &eval_scope);
+  result = DoParseProgram(info, &top_scope, &eval_scope);
 
   top_scope->set_end_position(scanner()->location().end_pos);
   if (eval_scope != NULL) {
     eval_scope->set_end_position(scanner()->location().end_pos);
   }
 
-  info()->SetFunction(result);
+  info->SetFunction(result);
 
   // We cannot internalize on a background thread; a foreground task will take
   // care of calling Parser::Internalize just before compilation.
 
   if (produce_cached_parse_data()) {
-    if (result != NULL) *info_->cached_data() = recorder.GetScriptData();
+    if (result != NULL) *info->cached_data() = recorder.GetScriptData();
     log_ = NULL;
   }
 }
index c1b0361..8707747 100644 (file)
@@ -647,14 +647,14 @@ class Parser : public ParserBase<ParserTraits> {
   // Parses the source code represented by the compilation info and sets its
   // function literal.  Returns false (and deallocates any allocated AST
   // nodes) if parsing failed.
-  static bool Parse(CompilationInfo* info, bool allow_lazy = false);
-  bool Parse();
-  void ParseOnBackground();
+  static bool ParseStatic(CompilationInfo* info, bool allow_lazy = false);
+  bool Parse(CompilationInfo* info);
+  void ParseOnBackground(CompilationInfo* info);
 
   // Handle errors detected during parsing, move statistics to Isolate,
   // internalize strings (move them to the heap).
-  void Internalize();
-  void HandleSourceURLComments();
+  void Internalize(CompilationInfo* info);
+  void HandleSourceURLComments(CompilationInfo* info);
 
  private:
   friend class ParserTraits;
@@ -681,31 +681,28 @@ class Parser : public ParserBase<ParserTraits> {
   };
 
   // Returns NULL if parsing failed.
-  FunctionLiteral* ParseProgram();
+  FunctionLiteral* ParseProgram(CompilationInfo* info);
 
-  FunctionLiteral* ParseLazy();
-  FunctionLiteral* ParseLazy(Utf16CharacterStream* source);
-
-  Isolate* isolate() { return info_->isolate(); }
-  CompilationInfo* info() const { return info_; }
-  Handle<Script> script() const { return info_->script(); }
+  FunctionLiteral* ParseLazy(CompilationInfo* info);
+  FunctionLiteral* ParseLazy(CompilationInfo* info,
+                             Utf16CharacterStream* source);
 
   // Called by ParseProgram after setting up the scanner.
   FunctionLiteral* DoParseProgram(CompilationInfo* info, Scope** scope,
                                   Scope** ad_hoc_eval_scope);
 
-  void SetCachedData();
+  void SetCachedData(CompilationInfo* info);
 
   bool inside_with() const { return scope_->inside_with(); }
   ScriptCompiler::CompileOptions compile_options() const {
-    return info_->compile_options();
+    return compile_options_;
   }
   bool consume_cached_parse_data() const {
-    return compile_options() == ScriptCompiler::kConsumeParserCache &&
+    return compile_options_ == ScriptCompiler::kConsumeParserCache &&
            cached_parse_data_ != NULL;
   }
   bool produce_cached_parse_data() const {
-    return compile_options() == ScriptCompiler::kProduceParserCache;
+    return compile_options_ == ScriptCompiler::kProduceParserCache;
   }
   Scope* DeclarationScope(VariableMode mode) {
     return IsLexicalVariableMode(mode)
@@ -841,7 +838,7 @@ class Parser : public ParserBase<ParserTraits> {
       const AstRawString* function_name, int pos, Variable* fvar,
       Token::Value fvar_init_op, FunctionKind kind, bool* ok);
 
-  void ThrowPendingError();
+  void ThrowPendingError(Isolate* isolate, Handle<Script> script);
 
   TemplateLiteralState OpenTemplateLiteral(int pos);
   void AddTemplateSpan(TemplateLiteralState* state, bool tail);
@@ -855,9 +852,9 @@ class Parser : public ParserBase<ParserTraits> {
   PreParser* reusable_preparser_;
   Scope* original_scope_;  // for ES5 function declarations in sloppy eval
   Target* target_stack_;  // for break, continue statements
+  ScriptCompiler::CompileOptions compile_options_;
   ParseData* cached_parse_data_;
 
-  CompilationInfo* info_;
   bool parsing_lazy_arrow_parameters_;  // for lazily parsed arrow functions.
 
   // Pending errors.
@@ -873,6 +870,8 @@ class Parser : public ParserBase<ParserTraits> {
   int use_counts_[v8::Isolate::kUseCounterFeatureCount];
   int total_preparse_skipped_;
   HistogramTimer* pre_parse_timer_;
+
+  bool parsing_on_main_thread_;
 };
 
 
index 4b526f5..f9faae8 100644 (file)
@@ -67,10 +67,9 @@ class ParserBase : public Traits {
   typedef typename Traits::Type::Literal LiteralT;
   typedef typename Traits::Type::ObjectLiteralProperty ObjectLiteralPropertyT;
 
-  ParserBase(Isolate* isolate, Zone* zone, Scanner* scanner,
-             uintptr_t stack_limit, v8::Extension* extension,
-             AstValueFactory* ast_value_factory, ParserRecorder* log,
-             typename Traits::Type::Parser this_object)
+  ParserBase(Zone* zone, Scanner* scanner, uintptr_t stack_limit,
+             v8::Extension* extension, AstValueFactory* ast_value_factory,
+             ParserRecorder* log, typename Traits::Type::Parser this_object)
       : Traits(this_object),
         parenthesized_function_(false),
         scope_(NULL),
@@ -81,7 +80,6 @@ class ParserBase : public Traits {
         log_(log),
         mode_(PARSE_EAGERLY),  // Lazy mode must be set explicitly.
         stack_limit_(stack_limit),
-        isolate_(isolate),
         zone_(zone),
         scanner_(scanner),
         stack_overflow_(false),
@@ -318,7 +316,6 @@ class ParserBase : public Traits {
     return result;
   }
 
-  Isolate* isolate() const { return isolate_; }
   Scanner* scanner() const { return scanner_; }
   AstValueFactory* ast_value_factory() const { return ast_value_factory_; }
   int position() { return scanner_->location().beg_pos; }
@@ -653,7 +650,6 @@ class ParserBase : public Traits {
   uintptr_t stack_limit_;
 
  private:
-  Isolate* isolate_;
   Zone* zone_;
 
   Scanner* scanner_;
@@ -1507,10 +1503,9 @@ class PreParser : public ParserBase<PreParserTraits> {
     kPreParseSuccess
   };
 
-  PreParser(Isolate* isolate, Zone* zone, Scanner* scanner,
-            AstValueFactory* ast_value_factory, ParserRecorder* log,
-            uintptr_t stack_limit)
-      : ParserBase<PreParserTraits>(isolate, zone, scanner, stack_limit, NULL,
+  PreParser(Zone* zone, Scanner* scanner, AstValueFactory* ast_value_factory,
+            ParserRecorder* log, uintptr_t stack_limit)
+      : ParserBase<PreParserTraits>(zone, scanner, stack_limit, NULL,
                                     ast_value_factory, log, this) {}
 
   // Pre-parse the program from the character stream; returns true on
index a1a5ee1..f8c1238 100644 (file)
@@ -1208,14 +1208,14 @@ class ScopeIterator {
           info.MarkAsEval();
           info.SetContext(Handle<Context>(function_->context()));
         }
-        if (Parser::Parse(&info) && Scope::Analyze(&info)) {
+        if (Parser::ParseStatic(&info) && Scope::Analyze(&info)) {
           scope = info.function()->scope();
         }
         RetrieveScopeChain(scope, shared_info);
       } else {
         // Function code
         CompilationInfoWithZone info(shared_info);
-        if (Parser::Parse(&info) && Scope::Analyze(&info)) {
+        if (Parser::ParseStatic(&info) && Scope::Analyze(&info)) {
           scope = info.function()->scope();
         }
         RetrieveScopeChain(scope, shared_info);
index bd61c46..50b6192 100644 (file)
@@ -166,7 +166,7 @@ RUNTIME_FUNCTION(Runtime_RenderCallSite) {
   Zone zone;
   if (location.function()->shared()->is_function()) {
     CompilationInfo info(location.function(), &zone);
-    if (!Parser::Parse(&info)) {
+    if (!Parser::ParseStatic(&info)) {
       isolate->clear_pending_exception();
       return isolate->heap()->empty_string();
     }
@@ -176,7 +176,7 @@ RUNTIME_FUNCTION(Runtime_RenderCallSite) {
   }
 
   CompilationInfo info(location.script(), &zone);
-  if (!Parser::Parse(&info)) {
+  if (!Parser::ParseStatic(&info)) {
     isolate->clear_pending_exception();
     return isolate->heap()->empty_string();
   }
index 7cb118a..440043c 100644 (file)
@@ -154,7 +154,7 @@ class FunctionTester : public InitializedHandleScope {
 #if V8_TURBOFAN_TARGET
     CompilationInfoWithZone info(function);
 
-    CHECK(Parser::Parse(&info));
+    CHECK(Parser::ParseStatic(&info));
     info.SetOptimizing(BailoutId::None(), Handle<Code>(function->code()));
     if (flags_ & CompilationInfo::kContextSpecializing) {
       info.MarkAsContextSpecializing();
@@ -210,7 +210,7 @@ class FunctionTester : public InitializedHandleScope {
     CHECK(Pipeline::SupportedTarget());
     CompilationInfoWithZone info(function);
 
-    CHECK(Parser::Parse(&info));
+    CHECK(Parser::ParseStatic(&info));
     info.SetOptimizing(BailoutId::None(),
                        Handle<Code>(function->shared()->code()));
     CHECK(Compiler::Analyze(&info));
index e017cd6..a90e402 100644 (file)
@@ -46,7 +46,7 @@ class DeoptCodegenTester {
         function(NewFunction(src)),
         info(function, scope->main_zone()),
         bailout_id(-1) {
-    CHECK(Parser::Parse(&info));
+    CHECK(Parser::ParseStatic(&info));
     info.SetOptimizing(BailoutId::None(), Handle<Code>(function->code()));
     CHECK(Compiler::Analyze(&info));
     CHECK(Compiler::EnsureDeoptimizationSupport(&info));
index 6f37964..7513307 100644 (file)
@@ -31,7 +31,7 @@ struct TestHelper : public HandleAndZoneScope {
     // TODO(titzer): don't scope analyze every single time.
     CompilationInfo info(function, main_zone());
 
-    CHECK(Parser::Parse(&info));
+    CHECK(Parser::ParseStatic(&info));
     CHECK(Rewriter::Rewrite(&info));
     CHECK(Scope::Analyze(&info));
 
index 5c7ff06..9c2f24d 100644 (file)
@@ -160,8 +160,8 @@ TEST(ScanHTMLEndComments) {
     i::Zone zone;
     i::AstValueFactory ast_value_factory(
         &zone, CcTest::i_isolate()->heap()->HashSeed());
-    i::PreParser preparser(CcTest::i_isolate(), &zone, &scanner,
-                           &ast_value_factory, &log, stack_limit);
+    i::PreParser preparser(&zone, &scanner, &ast_value_factory, &log,
+                           stack_limit);
     preparser.set_allow_lazy(true);
     i::PreParser::PreParseResult result = preparser.PreParseProgram();
     CHECK_EQ(i::PreParser::kPreParseSuccess, result);
@@ -178,8 +178,8 @@ TEST(ScanHTMLEndComments) {
     i::Zone zone;
     i::AstValueFactory ast_value_factory(
         &zone, CcTest::i_isolate()->heap()->HashSeed());
-    i::PreParser preparser(CcTest::i_isolate(), &zone, &scanner,
-                           &ast_value_factory, &log, stack_limit);
+    i::PreParser preparser(&zone, &scanner, &ast_value_factory, &log,
+                           stack_limit);
     preparser.set_allow_lazy(true);
     i::PreParser::PreParseResult result = preparser.PreParseProgram();
     // Even in the case of a syntax error, kPreParseSuccess is returned.
@@ -328,8 +328,8 @@ TEST(StandAlonePreParser) {
     i::Zone zone;
     i::AstValueFactory ast_value_factory(
         &zone, CcTest::i_isolate()->heap()->HashSeed());
-    i::PreParser preparser(CcTest::i_isolate(), &zone, &scanner,
-                           &ast_value_factory, &log, stack_limit);
+    i::PreParser preparser(&zone, &scanner, &ast_value_factory, &log,
+                           stack_limit);
     preparser.set_allow_lazy(true);
     preparser.set_allow_natives(true);
     preparser.set_allow_harmony_arrow_functions(true);
@@ -366,8 +366,8 @@ TEST(StandAlonePreParserNoNatives) {
     i::Zone zone;
     i::AstValueFactory ast_value_factory(
         &zone, CcTest::i_isolate()->heap()->HashSeed());
-    i::PreParser preparser(CcTest::i_isolate(), &zone, &scanner,
-                           &ast_value_factory, &log, stack_limit);
+    i::PreParser preparser(&zone, &scanner, &ast_value_factory, &log,
+                           stack_limit);
     preparser.set_allow_lazy(true);
     i::PreParser::PreParseResult result = preparser.PreParseProgram();
     CHECK_EQ(i::PreParser::kPreParseSuccess, result);
@@ -435,8 +435,7 @@ TEST(RegressChromium62639) {
   i::Zone zone;
   i::AstValueFactory ast_value_factory(&zone,
                                        CcTest::i_isolate()->heap()->HashSeed());
-  i::PreParser preparser(CcTest::i_isolate(), &zone, &scanner,
-                         &ast_value_factory, &log,
+  i::PreParser preparser(&zone, &scanner, &ast_value_factory, &log,
                          CcTest::i_isolate()->stack_guard()->real_climit());
   preparser.set_allow_lazy(true);
   i::PreParser::PreParseResult result = preparser.PreParseProgram();
@@ -471,8 +470,7 @@ TEST(Regress928) {
   i::Zone zone;
   i::AstValueFactory ast_value_factory(&zone,
                                        CcTest::i_isolate()->heap()->HashSeed());
-  i::PreParser preparser(CcTest::i_isolate(), &zone, &scanner,
-                         &ast_value_factory, &log,
+  i::PreParser preparser(&zone, &scanner, &ast_value_factory, &log,
                          CcTest::i_isolate()->stack_guard()->real_climit());
   preparser.set_allow_lazy(true);
   i::PreParser::PreParseResult result = preparser.PreParseProgram();
@@ -524,8 +522,8 @@ TEST(PreParseOverflow) {
   i::Zone zone;
   i::AstValueFactory ast_value_factory(&zone,
                                        CcTest::i_isolate()->heap()->HashSeed());
-  i::PreParser preparser(CcTest::i_isolate(), &zone, &scanner,
-                         &ast_value_factory, &log, stack_limit);
+  i::PreParser preparser(&zone, &scanner, &ast_value_factory, &log,
+                         stack_limit);
   preparser.set_allow_lazy(true);
   preparser.set_allow_harmony_arrow_functions(true);
   i::PreParser::PreParseResult result = preparser.PreParseProgram();
@@ -1062,7 +1060,7 @@ TEST(ScopeUsesArgumentsSuperThis) {
       parser.set_allow_harmony_scoping(true);
       parser.set_allow_harmony_sloppy(true);
       info.MarkAsGlobal();
-      CHECK(parser.Parse());
+      CHECK(parser.Parse(&info));
       CHECK(i::Rewriter::Rewrite(&info));
       CHECK(i::Scope::Analyze(&info));
       CHECK(info.function() != NULL);
@@ -1317,7 +1315,7 @@ TEST(ScopePositions) {
     parser.set_allow_harmony_arrow_functions(true);
     info.MarkAsGlobal();
     info.SetLanguageMode(source_data[i].language_mode);
-    parser.Parse();
+    parser.Parse(&info);
     CHECK(info.function() != NULL);
 
     // Check scope types and positions.
@@ -1453,8 +1451,8 @@ void TestParserSyncWithFlags(i::Handle<i::String> source,
     i::Zone zone;
     i::AstValueFactory ast_value_factory(
         &zone, CcTest::i_isolate()->heap()->HashSeed());
-    i::PreParser preparser(CcTest::i_isolate(), &zone, &scanner,
-                           &ast_value_factory, &log, stack_limit);
+    i::PreParser preparser(&zone, &scanner, &ast_value_factory, &log,
+                           stack_limit);
     SetParserFlags(&preparser, flags);
     scanner.Initialize(&stream);
     i::PreParser::PreParseResult result = preparser.PreParseProgram(
@@ -1473,7 +1471,7 @@ void TestParserSyncWithFlags(i::Handle<i::String> source,
                      isolate->heap()->HashSeed(), isolate->unicode_cache());
     SetParserFlags(&parser, flags);
     info.MarkAsGlobal();
-    parser.Parse();
+    parser.Parse(&info);
     function = info.function();
     if (function) {
       parser_materialized_literals = function->materialized_literal_count();
@@ -2558,7 +2556,7 @@ TEST(DontRegressPreParserDataSizes) {
     i::CompilationInfoWithZone info(script);
     i::ScriptData* sd = NULL;
     info.SetCachedData(&sd, v8::ScriptCompiler::kProduceParserCache);
-    i::Parser::Parse(&info, true);
+    i::Parser::ParseStatic(&info, true);
     i::ParseData* pd = i::ParseData::FromCachedData(sd);
 
     if (pd->FunctionCount() != test_cases[i].functions) {
@@ -3437,7 +3435,7 @@ TEST(InnerAssignment) {
                            isolate->heap()->HashSeed(),
                            isolate->unicode_cache());
           parser.set_allow_harmony_scoping(true);
-          CHECK(parser.Parse());
+          CHECK(parser.Parse(&info));
           CHECK(i::Compiler::Analyze(&info));
           CHECK(info.function() != NULL);
 
@@ -5051,7 +5049,7 @@ TEST(BasicImportExportParsing) {
       parser.set_allow_harmony_modules(true);
       parser.set_allow_harmony_scoping(true);
       info.MarkAsModule();
-      if (!parser.Parse()) {
+      if (!parser.Parse(&info)) {
         i::Handle<i::JSObject> exception_handle(
             i::JSObject::cast(isolate->pending_exception()));
         i::Handle<i::String> message_string =
@@ -5079,7 +5077,7 @@ TEST(BasicImportExportParsing) {
       parser.set_allow_harmony_modules(true);
       parser.set_allow_harmony_scoping(true);
       info.MarkAsGlobal();
-      CHECK(!parser.Parse());
+      CHECK(!parser.Parse(&info));
     }
   }
 }
@@ -5169,7 +5167,7 @@ TEST(ImportExportParsingErrors) {
     parser.set_allow_harmony_modules(true);
     parser.set_allow_harmony_scoping(true);
     info.MarkAsModule();
-    CHECK(!parser.Parse());
+    CHECK(!parser.Parse(&info));
   }
 }
 
@@ -5261,7 +5259,7 @@ void TestLanguageMode(const char* source,
                    isolate->heap()->HashSeed(), isolate->unicode_cache());
   parser.set_allow_strong_mode(true);
   info.MarkAsGlobal();
-  parser.Parse();
+  parser.Parse(&info);
   CHECK(info.function() != NULL);
   CHECK_EQ(expected_language_mode, info.function()->language_mode());
 }
index 2cafc83..3e41bf9 100644 (file)
@@ -95,7 +95,7 @@ std::pair<v8::base::TimeDelta, v8::base::TimeDelta> RunBaselineParser(
     v8::base::ElapsedTimer timer;
     timer.Start();
     // Allow lazy parsing; otherwise we won't produce cached data.
-    bool success = Parser::Parse(&info, true);
+    bool success = Parser::ParseStatic(&info, true);
     parse_time1 = timer.Elapsed();
     if (!success) {
       fprintf(stderr, "Parsing failed\n");
@@ -111,7 +111,7 @@ std::pair<v8::base::TimeDelta, v8::base::TimeDelta> RunBaselineParser(
     v8::base::ElapsedTimer timer;
     timer.Start();
     // Allow lazy parsing; otherwise cached data won't help.
-    bool success = Parser::Parse(&info, true);
+    bool success = Parser::ParseStatic(&info, true);
     parse_time2 = timer.Elapsed();
     if (!success) {
       fprintf(stderr, "Parsing failed\n");