Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(44)

Side by Side Diff: src/ast/scopes.cc

Issue 2306413002: Fully deserialize the scope chain after parsing, not before (Closed)
Patch Set: updates Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/ast/scopes.h ('k') | src/background-parsing-task.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/ast/scopes.h" 5 #include "src/ast/scopes.h"
6 6
7 #include <set> 7 #include <set>
8 8
9 #include "src/accessors.h" 9 #include "src/accessors.h"
10 #include "src/ast/ast.h" 10 #include "src/ast/ast.h"
(...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after
326 // function scope in which we are evaluating. 326 // function scope in which we are evaluating.
327 if (context->IsDebugEvaluateContext()) { 327 if (context->IsDebugEvaluateContext()) {
328 outer_scope->set_is_debug_evaluate_scope(); 328 outer_scope->set_is_debug_evaluate_scope();
329 } 329 }
330 } else if (context->IsScriptContext()) { 330 } else if (context->IsScriptContext()) {
331 // If we reach a script context, it's the outermost context with scope 331 // If we reach a script context, it's the outermost context with scope
332 // info. The next context will be the native context. Install the scope 332 // info. The next context will be the native context. Install the scope
333 // info of this script context onto the existing script scope to avoid 333 // info of this script context onto the existing script scope to avoid
334 // nesting script scopes. 334 // nesting script scopes.
335 Handle<ScopeInfo> scope_info(context->scope_info(), isolate); 335 Handle<ScopeInfo> scope_info(context->scope_info(), isolate);
336 script_scope->SetScriptScopeInfo(scope_info); 336 if (deserialization_mode == DeserializationMode::kIncludingVariables) {
337 script_scope->SetScriptScopeInfo(scope_info);
338 }
337 DCHECK(context->previous()->IsNativeContext()); 339 DCHECK(context->previous()->IsNativeContext());
338 break; 340 break;
339 } else if (context->IsFunctionContext()) { 341 } else if (context->IsFunctionContext()) {
340 Handle<ScopeInfo> scope_info(context->scope_info(), isolate); 342 Handle<ScopeInfo> scope_info(context->scope_info(), isolate);
341 // TODO(neis): For an eval scope, we currently create an ordinary function 343 // TODO(neis): For an eval scope, we currently create an ordinary function
342 // context. This is wrong and needs to be fixed. 344 // context. This is wrong and needs to be fixed.
343 // https://bugs.chromium.org/p/v8/issues/detail?id=5295 345 // https://bugs.chromium.org/p/v8/issues/detail?id=5295
344 DCHECK(scope_info->scope_type() == FUNCTION_SCOPE || 346 DCHECK(scope_info->scope_type() == FUNCTION_SCOPE ||
345 scope_info->scope_type() == EVAL_SCOPE); 347 scope_info->scope_type() == EVAL_SCOPE);
346 outer_scope = 348 outer_scope =
(...skipping 16 matching lines...) Expand all
363 DCHECK_EQ(scope_info->scope_type(), MODULE_SCOPE); 365 DCHECK_EQ(scope_info->scope_type(), MODULE_SCOPE);
364 outer_scope = new (zone) ModuleScope( 366 outer_scope = new (zone) ModuleScope(
365 isolate, Handle<ScopeInfo>(scope_info), ast_value_factory); 367 isolate, Handle<ScopeInfo>(scope_info), ast_value_factory);
366 } else { 368 } else {
367 DCHECK(context->IsCatchContext()); 369 DCHECK(context->IsCatchContext());
368 String* name = context->catch_name(); 370 String* name = context->catch_name();
369 outer_scope = new (zone) 371 outer_scope = new (zone)
370 Scope(zone, ast_value_factory->GetString(handle(name, isolate)), 372 Scope(zone, ast_value_factory->GetString(handle(name, isolate)),
371 Handle<ScopeInfo>(context->scope_info())); 373 Handle<ScopeInfo>(context->scope_info()));
372 } 374 }
375 if (deserialization_mode == DeserializationMode::kScopesOnly) {
376 outer_scope->scope_info_ = Handle<ScopeInfo>::null();
377 }
373 if (current_scope != nullptr) { 378 if (current_scope != nullptr) {
374 outer_scope->AddInnerScope(current_scope); 379 outer_scope->AddInnerScope(current_scope);
375 DCHECK_IMPLIES( 380 DCHECK_IMPLIES(
376 deserialization_mode == DeserializationMode::kKeepScopeInfo, 381 deserialization_mode == DeserializationMode::kIncludingVariables,
377 current_scope->scope_info_->HasOuterScopeInfo()); 382 current_scope->scope_info_->HasOuterScopeInfo());
378 DCHECK_IMPLIES( 383 DCHECK_IMPLIES(
379 deserialization_mode == DeserializationMode::kKeepScopeInfo, 384 deserialization_mode == DeserializationMode::kIncludingVariables,
380 outer_scope->scope_info_->Equals( 385 outer_scope->scope_info_->Equals(
381 current_scope->scope_info_->OuterScopeInfo())); 386 current_scope->scope_info_->OuterScopeInfo()));
382 } 387 }
383 current_scope = outer_scope; 388 current_scope = outer_scope;
384 if (deserialization_mode == DeserializationMode::kDeserializeOffHeap) {
385 current_scope->DeserializeScopeInfo(isolate, ast_value_factory);
386 }
387 if (innermost_scope == nullptr) innermost_scope = current_scope; 389 if (innermost_scope == nullptr) innermost_scope = current_scope;
388 context = context->previous(); 390 context = context->previous();
389 } 391 }
390 392
391 if (innermost_scope == nullptr) return script_scope; 393 if (innermost_scope == nullptr) return script_scope;
392 script_scope->AddInnerScope(current_scope); 394 script_scope->AddInnerScope(current_scope);
393 #if DEBUG 395 #if DEBUG
394 if (deserialization_mode == DeserializationMode::kKeepScopeInfo) { 396 if (deserialization_mode == DeserializationMode::kIncludingVariables) {
395 if (script_scope->scope_info_.is_null()) { 397 if (script_scope->scope_info_.is_null()) {
396 DCHECK(!current_scope->scope_info_->HasOuterScopeInfo()); 398 DCHECK(!current_scope->scope_info_->HasOuterScopeInfo());
397 } else { 399 } else {
398 DCHECK(!script_scope->scope_info_->HasOuterScopeInfo()); 400 DCHECK(!script_scope->scope_info_->HasOuterScopeInfo());
399 DCHECK(script_scope->scope_info_->Equals( 401 DCHECK(script_scope->scope_info_->Equals(
400 current_scope->scope_info_->OuterScopeInfo())); 402 current_scope->scope_info_->OuterScopeInfo()));
401 } 403 }
402 } 404 }
403 #endif 405 #endif
404 return innermost_scope; 406 return innermost_scope;
405 } 407 }
406 408
407 void Scope::DeserializeScopeInfo(Isolate* isolate,
408 AstValueFactory* ast_value_factory) {
409 if (scope_info_.is_null()) return;
410
411 DCHECK(ThreadId::Current().Equals(isolate->thread_id()));
412
413 // Internalize context local variables.
414 for (int var = 0; var < scope_info_->ContextLocalCount(); ++var) {
415 Handle<String> name_handle(scope_info_->ContextLocalName(var), isolate);
416 const AstRawString* name = ast_value_factory->GetString(name_handle);
417 int index = Context::MIN_CONTEXT_SLOTS + var;
418 VariableMode mode = scope_info_->ContextLocalMode(var);
419 InitializationFlag init_flag = scope_info_->ContextLocalInitFlag(var);
420 MaybeAssignedFlag maybe_assigned_flag =
421 scope_info_->ContextLocalMaybeAssignedFlag(var);
422 VariableLocation location = VariableLocation::CONTEXT;
423 VariableKind kind = NORMAL_VARIABLE;
424 if (index == scope_info_->ReceiverContextSlotIndex()) {
425 kind = THIS_VARIABLE;
426 }
427
428 Variable* result = variables_.Declare(zone(), this, name, mode, kind,
429 init_flag, maybe_assigned_flag);
430 result->AllocateTo(location, index);
431 }
432
433 // Internalize function proxy for this scope.
434 if (scope_info_->HasFunctionName()) {
435 Handle<String> name_handle(scope_info_->FunctionName(), isolate);
436 const AstRawString* name = ast_value_factory->GetString(name_handle);
437 int index = scope_info_->FunctionContextSlotIndex(*name_handle);
438 if (index >= 0) {
439 Variable* result = AsDeclarationScope()->DeclareFunctionVar(name);
440 result->AllocateTo(VariableLocation::CONTEXT, index);
441 }
442 }
443
444 scope_info_ = Handle<ScopeInfo>::null();
445 }
446
447 DeclarationScope* Scope::AsDeclarationScope() { 409 DeclarationScope* Scope::AsDeclarationScope() {
448 DCHECK(is_declaration_scope()); 410 DCHECK(is_declaration_scope());
449 return static_cast<DeclarationScope*>(this); 411 return static_cast<DeclarationScope*>(this);
450 } 412 }
451 413
452 const DeclarationScope* Scope::AsDeclarationScope() const { 414 const DeclarationScope* Scope::AsDeclarationScope() const {
453 DCHECK(is_declaration_scope()); 415 DCHECK(is_declaration_scope());
454 return static_cast<const DeclarationScope*>(this); 416 return static_cast<const DeclarationScope*>(this);
455 } 417 }
456 418
457 ModuleScope* Scope::AsModuleScope() { 419 ModuleScope* Scope::AsModuleScope() {
458 DCHECK(is_module_scope()); 420 DCHECK(is_module_scope());
459 return static_cast<ModuleScope*>(this); 421 return static_cast<ModuleScope*>(this);
460 } 422 }
461 423
462 const ModuleScope* Scope::AsModuleScope() const { 424 const ModuleScope* Scope::AsModuleScope() const {
463 DCHECK(is_module_scope()); 425 DCHECK(is_module_scope());
464 return static_cast<const ModuleScope*>(this); 426 return static_cast<const ModuleScope*>(this);
465 } 427 }
466 428
467 int Scope::num_parameters() const { 429 int Scope::num_parameters() const {
468 return is_declaration_scope() ? AsDeclarationScope()->num_parameters() : 0; 430 return is_declaration_scope() ? AsDeclarationScope()->num_parameters() : 0;
469 } 431 }
470 432
471 void DeclarationScope::HoistSloppyBlockFunctions(AstNodeFactory* factory, 433 void DeclarationScope::HoistSloppyBlockFunctions(AstNodeFactory* factory) {
472 bool* ok) {
473 DCHECK(is_sloppy(language_mode())); 434 DCHECK(is_sloppy(language_mode()));
474 DCHECK(is_function_scope() || is_eval_scope() || is_script_scope() || 435 DCHECK(is_function_scope() || is_eval_scope() || is_script_scope() ||
475 (is_block_scope() && outer_scope()->is_function_scope())); 436 (is_block_scope() && outer_scope()->is_function_scope()));
476 DCHECK(HasSimpleParameters() || is_block_scope()); 437 DCHECK(HasSimpleParameters() || is_block_scope());
477 bool has_simple_parameters = HasSimpleParameters(); 438 bool has_simple_parameters = HasSimpleParameters();
478 // For each variable which is used as a function declaration in a sloppy 439 // For each variable which is used as a function declaration in a sloppy
479 // block, 440 // block,
480 SloppyBlockFunctionMap* map = sloppy_block_function_map(); 441 SloppyBlockFunctionMap* map = sloppy_block_function_map();
481 for (ZoneHashMap::Entry* p = map->Start(); p != nullptr; p = map->Next(p)) { 442 for (ZoneHashMap::Entry* p = map->Start(); p != nullptr; p = map->Next(p)) {
482 AstRawString* name = static_cast<AstRawString*>(p->key); 443 AstRawString* name = static_cast<AstRawString*>(p->key);
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
538 499
539 // Declare a var-style binding for the function in the outer scope 500 // Declare a var-style binding for the function in the outer scope
540 if (!var_created) { 501 if (!var_created) {
541 var_created = true; 502 var_created = true;
542 VariableProxy* proxy = NewUnresolved(factory, name); 503 VariableProxy* proxy = NewUnresolved(factory, name);
543 Declaration* declaration = 504 Declaration* declaration =
544 factory->NewVariableDeclaration(proxy, this, kNoSourcePosition); 505 factory->NewVariableDeclaration(proxy, this, kNoSourcePosition);
545 // Based on the preceding check, it doesn't matter what we pass as 506 // Based on the preceding check, it doesn't matter what we pass as
546 // allow_harmony_restrictive_generators and 507 // allow_harmony_restrictive_generators and
547 // sloppy_mode_block_scope_function_redefinition. 508 // sloppy_mode_block_scope_function_redefinition.
509 bool ok = true;
548 DeclareVariable(declaration, VAR, 510 DeclareVariable(declaration, VAR,
549 Variable::DefaultInitializationFlag(VAR), false, 511 Variable::DefaultInitializationFlag(VAR), false,
550 nullptr, ok); 512 nullptr, &ok);
551 DCHECK(*ok); // Based on the preceding check, this should not fail 513 CHECK(ok); // Based on the preceding check, this should not fail
552 if (!*ok) return;
553 } 514 }
554 515
555 // Create VariableProxies for creating an assignment statement 516 Expression* assignment = factory->NewAssignment(
556 // (later). Read from the local lexical scope and write to the function 517 Token::ASSIGN, NewUnresolved(factory, name),
557 // scope. 518 delegate->scope()->NewUnresolved(factory, name), kNoSourcePosition);
558 delegate->set_to(NewUnresolved(factory, name)); 519 Statement* statement =
559 delegate->set_from(delegate->scope()->NewUnresolved(factory, name)); 520 factory->NewExpressionStatement(assignment, kNoSourcePosition);
521 delegate->set_statement(statement);
560 } 522 }
561 } 523 }
562 } 524 }
563 525
564 void DeclarationScope::Analyze(ParseInfo* info, AnalyzeMode mode) { 526 void DeclarationScope::Analyze(ParseInfo* info, AnalyzeMode mode) {
565 DCHECK(info->literal() != NULL); 527 DCHECK(info->literal() != NULL);
566 DeclarationScope* scope = info->literal()->scope(); 528 DeclarationScope* scope = info->literal()->scope();
567 529
530 if (!info->context().is_null() && !info->context()->IsNativeContext()) {
531 if (scope->outer_scope()) {
532 DeclarationScope* script_scope = new (info->zone())
533 DeclarationScope(info->zone(), info->ast_value_factory());
534 info->set_script_scope(script_scope);
535 scope->ReplaceOuterScope(Scope::DeserializeScopeChain(
536 info->isolate(), info->zone(), *info->context(), script_scope,
537 info->ast_value_factory(),
538 Scope::DeserializationMode::kIncludingVariables));
539 } else {
540 DCHECK(info->context()->IsScriptContext());
541 Handle<ScopeInfo> scope_info(info->context()->scope_info(),
542 info->isolate());
543 scope->SetScriptScopeInfo(scope_info);
544 }
545 }
546
547 if (scope->is_eval_scope() && is_sloppy(scope->language_mode())) {
548 AstNodeFactory factory(info->ast_value_factory());
549 scope->HoistSloppyBlockFunctions(&factory);
550 }
551
568 // We are compiling one of three cases: 552 // We are compiling one of three cases:
569 // 1) top-level code, 553 // 1) top-level code,
570 // 2) a function/eval/module on the top-level 554 // 2) a function/eval/module on the top-level
571 // 3) a function/eval in a scope that was already resolved. 555 // 3) a function/eval in a scope that was already resolved.
572 DCHECK(scope->scope_type() == SCRIPT_SCOPE || 556 DCHECK(scope->scope_type() == SCRIPT_SCOPE ||
573 scope->outer_scope()->scope_type() == SCRIPT_SCOPE || 557 scope->outer_scope()->scope_type() == SCRIPT_SCOPE ||
574 scope->outer_scope()->already_resolved_); 558 scope->outer_scope()->already_resolved_);
575 559
576 scope->AllocateVariables(info, mode); 560 scope->AllocateVariables(info, mode);
577 561
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
740 } 724 }
741 } 725 }
742 outer_closure->locals_.Rewind(top_local_); 726 outer_closure->locals_.Rewind(top_local_);
743 outer_closure->decls_.Rewind(top_decl_); 727 outer_closure->decls_.Rewind(top_decl_);
744 } 728 }
745 729
746 void Scope::ReplaceOuterScope(Scope* outer) { 730 void Scope::ReplaceOuterScope(Scope* outer) {
747 DCHECK_NOT_NULL(outer); 731 DCHECK_NOT_NULL(outer);
748 DCHECK_NOT_NULL(outer_scope_); 732 DCHECK_NOT_NULL(outer_scope_);
749 DCHECK(!already_resolved_); 733 DCHECK(!already_resolved_);
750 DCHECK(!outer->already_resolved_);
751 DCHECK(!outer_scope_->already_resolved_);
752 outer_scope_->RemoveInnerScope(this); 734 outer_scope_->RemoveInnerScope(this);
753 outer->AddInnerScope(this); 735 outer->AddInnerScope(this);
754 outer_scope_ = outer; 736 outer_scope_ = outer;
755 } 737 }
756 738
757 739
758 void Scope::PropagateUsageFlagsToScope(Scope* other) { 740 void Scope::PropagateUsageFlagsToScope(Scope* other) {
759 DCHECK_NOT_NULL(other); 741 DCHECK_NOT_NULL(other);
760 DCHECK(!already_resolved_); 742 DCHECK(!already_resolved_);
761 DCHECK(!other->already_resolved_); 743 DCHECK(!other->already_resolved_);
(...skipping 1093 matching lines...) Expand 10 before | Expand all | Expand 10 after
1855 Variable* function = 1837 Variable* function =
1856 is_function_scope() ? AsDeclarationScope()->function_var() : nullptr; 1838 is_function_scope() ? AsDeclarationScope()->function_var() : nullptr;
1857 bool is_function_var_in_context = 1839 bool is_function_var_in_context =
1858 function != nullptr && function->IsContextSlot(); 1840 function != nullptr && function->IsContextSlot();
1859 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - 1841 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS -
1860 (is_function_var_in_context ? 1 : 0); 1842 (is_function_var_in_context ? 1 : 0);
1861 } 1843 }
1862 1844
1863 } // namespace internal 1845 } // namespace internal
1864 } // namespace v8 1846 } // namespace v8
OLDNEW
« no previous file with comments | « src/ast/scopes.h ('k') | src/background-parsing-task.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698