@@ -329,6 +329,7 @@ void DeclarationScope::SetDefaults() {
329329 is_skipped_function_ = false ;
330330 preparse_data_builder_ = nullptr ;
331331 class_scope_has_private_brand_ = false ;
332+ eval_state_ = false ;
332333#ifdef DEBUG
333334 DeclarationScope* outer_declaration_scope =
334335 outer_scope_ ? outer_scope_->GetDeclarationScope () : nullptr ;
@@ -353,6 +354,7 @@ void Scope::SetDefaults() {
353354
354355 calls_eval_ = false ;
355356 sloppy_eval_can_extend_vars_ = false ;
357+ eval_state_ = false ;
356358 scope_nonlinear_ = false ;
357359 is_hidden_ = false ;
358360 is_debug_evaluate_scope_ = false ;
@@ -556,6 +558,16 @@ const DeclarationScope* Scope::AsDeclarationScope() const {
556558 return static_cast <const DeclarationScope*>(this );
557559}
558560
561+ void DeclarationScope::set_eval_state () {
562+ DCHECK (is_eval_scope ());
563+ if (outer_scope_->scope_info_ .is_null ()) {
564+ CHECK (outer_scope_->is_script_scope ());
565+ eval_state_ = true ;
566+ } else {
567+ eval_state_ = !outer_scope_->scope_info ()->EvalState ();
568+ }
569+ }
570+
559571ModuleScope* Scope::AsModuleScope () {
560572 SBXCHECK (is_module_scope ());
561573 return static_cast <ModuleScope*>(this );
@@ -2611,6 +2623,23 @@ void ModuleScope::AllocateModuleVariables() {
26112623 }
26122624}
26132625
2626+ // Needs to be kept in sync with ScopeInfo::UniqueIdInScript.
2627+ int Scope::UniqueIdInScript () const {
2628+ // Script scopes start "before" the script to avoid clashing with a scope that
2629+ // starts on character 0.
2630+ if (is_script_scope () || scope_type () == EVAL_SCOPE ||
2631+ scope_type () == MODULE_SCOPE) {
2632+ return -1 ;
2633+ }
2634+ if (is_declaration_scope ()) {
2635+ // Default constructors have the same start position as their parent class
2636+ // scope. Use the next char position to distinguish this scope.
2637+ return start_position () +
2638+ IsDefaultConstructor (AsDeclarationScope ()->function_kind ());
2639+ }
2640+ return start_position ();
2641+ }
2642+
26142643void Scope::AllocateVariablesRecursively () {
26152644 this ->ForEach ([](Scope* scope) -> Iteration {
26162645 DCHECK (!scope->already_resolved_ );
@@ -2662,33 +2691,59 @@ void Scope::AllocateVariablesRecursively() {
26622691}
26632692
26642693template <typename IsolateT>
2665- void Scope::AllocateScopeInfosRecursively (IsolateT* isolate,
2666- MaybeHandle<ScopeInfo> outer_scope) {
2694+ void Scope::AllocateScopeInfosRecursively (
2695+ IsolateT* isolate, MaybeHandle<ScopeInfo> outer_scope,
2696+ std::unordered_map<int , Handle<ScopeInfo>>& scope_infos_to_reuse) {
26672697 DCHECK (scope_info_.is_null ());
26682698 MaybeHandle<ScopeInfo> next_outer_scope = outer_scope;
26692699
2670- if (NeedsScopeInfo ()) {
2700+ auto it = scope_infos_to_reuse.find (UniqueIdInScript ());
2701+ if (it != scope_infos_to_reuse.end ()) {
2702+ scope_info_ = it->second ;
2703+ CHECK (NeedsContext ());
2704+ // The ScopeInfo chain mirrors the context chain, so we only link to the
2705+ // next outer scope that needs a context.
2706+ next_outer_scope = scope_info_;
2707+ DCHECK (!scope_info_.is_null ());
2708+ CHECK_EQ (scope_info_->scope_type (), scope_type_);
2709+ CHECK_EQ (scope_info_->ContextLength (), num_heap_slots_);
2710+ #ifdef DEBUG
2711+ // Consume the scope info.
2712+ it->second = {};
2713+ #endif
2714+ } else if (NeedsScopeInfo ()) {
2715+ #ifdef DEBUG
2716+ // Mark this ID as being used.
2717+ scope_infos_to_reuse[UniqueIdInScript ()] = {};
2718+ #endif
26712719 scope_info_ = ScopeInfo::Create (isolate, zone (), this , outer_scope);
2672- // The ScopeInfo chain should mirror the context chain, so we only link to
2673- // the next outer scope that needs a context.
2720+ DCHECK_EQ (UniqueIdInScript (), scope_info_->UniqueIdInScript ());
2721+ // The ScopeInfo chain mirrors the context chain, so we only link to the
2722+ // next outer scope that needs a context.
26742723 if (NeedsContext ()) next_outer_scope = scope_info_;
26752724 }
26762725
26772726 // Allocate ScopeInfos for inner scopes.
26782727 for (Scope* scope = inner_scope_; scope != nullptr ; scope = scope->sibling_ ) {
2728+ DCHECK_GT (scope->UniqueIdInScript (), UniqueIdInScript ());
2729+ DCHECK_IMPLIES (scope->sibling_ , scope->sibling_ ->UniqueIdInScript () !=
2730+ scope->UniqueIdInScript ());
26792731 if (!scope->is_function_scope () ||
26802732 scope->AsDeclarationScope ()->ShouldEagerCompile ()) {
2681- scope->AllocateScopeInfosRecursively (isolate, next_outer_scope);
2733+ scope->AllocateScopeInfosRecursively (isolate, next_outer_scope,
2734+ scope_infos_to_reuse);
26822735 }
26832736 }
26842737}
26852738
26862739template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE) void Scope::
2687- AllocateScopeInfosRecursively<Isolate>(Isolate* isolate,
2688- MaybeHandle<ScopeInfo> outer_scope);
2740+ AllocateScopeInfosRecursively<Isolate>(
2741+ Isolate* isolate, MaybeHandle<ScopeInfo> outer_scope,
2742+ std::unordered_map<int , Handle<ScopeInfo>>& scope_infos_to_reuse);
26892743template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE) void Scope::
26902744 AllocateScopeInfosRecursively<LocalIsolate>(
2691- LocalIsolate* isolate, MaybeHandle<ScopeInfo> outer_scope);
2745+ LocalIsolate* isolate, MaybeHandle<ScopeInfo> outer_scope,
2746+ std::unordered_map<int , Handle<ScopeInfo>>& scope_infos_to_reuse);
26922747
26932748void DeclarationScope::RecalcPrivateNameContextChain () {
26942749 // The outermost scope in a class heritage expression is marked to skip the
@@ -2733,7 +2788,9 @@ void DeclarationScope::RecordNeedsPrivateNameContextChainRecalc() {
27332788
27342789// static
27352790template <typename IsolateT>
2736- void DeclarationScope::AllocateScopeInfos (ParseInfo* info, IsolateT* isolate) {
2791+ void DeclarationScope::AllocateScopeInfos (ParseInfo* info,
2792+ Handle<Script> script,
2793+ IsolateT* isolate) {
27372794 DeclarationScope* scope = info->literal ()->scope ();
27382795
27392796 // No one else should have allocated a scope info for this scope yet.
@@ -2748,7 +2805,41 @@ void DeclarationScope::AllocateScopeInfos(ParseInfo* info, IsolateT* isolate) {
27482805 if (scope->needs_private_name_context_chain_recalc ()) {
27492806 scope->RecalcPrivateNameContextChain ();
27502807 }
2751- scope->AllocateScopeInfosRecursively (isolate, outer_scope);
2808+
2809+ Tagged<WeakFixedArray> infos = script->shared_function_infos ();
2810+ std::unordered_map<int , Handle<ScopeInfo>> scope_infos_to_reuse;
2811+ if (infos->length () != 0 ) {
2812+ // Look at all the existing inner functions (they are numbered id+1 until
2813+ // max_id+1) to reattach their outer scope infos to corresponding scopes.
2814+ for (int i = info->literal ()->function_literal_id () + 1 ;
2815+ i < info->max_function_literal_id () + 1 ; ++i) {
2816+ Tagged<MaybeObject> maybe_sfi = infos->get (i);
2817+ if (maybe_sfi.IsWeak ()) {
2818+ Tagged<SharedFunctionInfo> sfi =
2819+ Cast<SharedFunctionInfo>(maybe_sfi.GetHeapObjectAssumeWeak ());
2820+ // Reuse outer scope infos. Don't look at sfi->scope_info() because that
2821+ // might be empty if the sfi isn't compiled yet.
2822+ if (!sfi->HasOuterScopeInfo ()) continue ;
2823+ Tagged<ScopeInfo> scope_info = sfi->GetOuterScopeInfo ();
2824+ while (true ) {
2825+ if (scope_info->EvalState () != scope->eval_state ()) break ;
2826+ if (scope_info->StartPosition () < scope->start_position ()) break ;
2827+ int id = scope_info->UniqueIdInScript ();
2828+ auto it = scope_infos_to_reuse.find (id);
2829+ if (it != scope_infos_to_reuse.end ()) {
2830+ CHECK_EQ (*it->second , scope_info);
2831+ break ;
2832+ }
2833+ scope_infos_to_reuse[id] = handle (scope_info, isolate);
2834+ if (!scope_info->HasOuterScopeInfo ()) break ;
2835+ scope_info = scope_info->OuterScopeInfo ();
2836+ }
2837+ }
2838+ }
2839+ }
2840+
2841+ scope->AllocateScopeInfosRecursively (isolate, outer_scope,
2842+ scope_infos_to_reuse);
27522843
27532844 // The debugger expects all shared function infos to contain a scope info.
27542845 // Since the top-most scope will end up in a shared function info, make sure
@@ -2767,9 +2858,9 @@ void DeclarationScope::AllocateScopeInfos(ParseInfo* info, IsolateT* isolate) {
27672858}
27682859
27692860template V8_EXPORT_PRIVATE void DeclarationScope::AllocateScopeInfos (
2770- ParseInfo* info, Isolate* isolate);
2861+ ParseInfo* info, Handle<Script> script, Isolate* isolate);
27712862template V8_EXPORT_PRIVATE void DeclarationScope::AllocateScopeInfos (
2772- ParseInfo* info, LocalIsolate* isolate);
2863+ ParseInfo* info, Handle<Script> script, LocalIsolate* isolate);
27732864
27742865int Scope::ContextLocalCount () const {
27752866 if (num_heap_slots () == 0 ) return 0 ;
0 commit comments