@@ -968,84 +968,101 @@ Js::RegSlot ByteCodeGenerator::EnregisterStringTemplateCallsiteConstant(ParseNod
968
968
//
969
969
// Restore all outer func scope info when reparsing a deferred func.
970
970
//
971
- void ByteCodeGenerator::RestoreScopeInfo (Js::ParseableFunctionInfo* functionBody )
971
+ void ByteCodeGenerator::RestoreScopeInfo (Js::ScopeInfo *scopeInfo, FuncInfo * func )
972
972
{
973
- if (functionBody && functionBody-> GetScopeInfo () )
973
+ if (scopeInfo )
974
974
{
975
975
PROBE_STACK (scriptContext, Js::Constants::MinStackByteCodeVisitor);
976
976
977
- Js::ScopeInfo* scopeInfo = functionBody-> GetScopeInfo ();
978
- RestoreScopeInfo (scopeInfo-> GetParent ()); // Recursively restore outer func scope info
977
+ Js::ParseableFunctionInfo * pfi = scopeInfo-> GetFunctionInfo ()-> GetParseableFunctionInfo ();
978
+ bool newFunc = (func == nullptr || func-> byteCodeFunction != pfi);
979
979
980
- Js::ScopeInfo* paramScopeInfo = scopeInfo->GetParamScopeInfo ();
981
- Scope* paramScope = nullptr ;
982
- if (paramScopeInfo != nullptr )
980
+ if (newFunc)
983
981
{
984
- paramScope = paramScopeInfo->GetScope ();
985
- Assert (paramScope);
986
- if (!paramScopeInfo->GetCanMergeWithBodyScope ())
987
- {
988
- paramScope->SetCannotMergeWithBodyScope ();
989
- }
990
- // We need the funcInfo before continuing the restoration of the param scope, so wait for the funcInfo to be created.
991
- }
992
-
993
- Scope* bodyScope = scopeInfo->GetScope ();
994
-
995
- Assert (bodyScope);
996
- bodyScope->SetHasOwnLocalInClosure (scopeInfo->GetHasOwnLocalInClosure ());
997
-
998
- FuncInfo* func = Anew (alloc, FuncInfo, functionBody->GetDisplayName (), alloc, paramScope, bodyScope, nullptr , functionBody);
999
-
1000
- if (bodyScope->GetScopeType () == ScopeType_GlobalEvalBlock)
1001
- {
1002
- func->bodyScope = this ->currentScope ;
982
+ func = Anew (alloc, FuncInfo, pfi->GetDisplayName (), alloc, nullptr , nullptr , nullptr , pfi);
983
+ newFunc = true ;
1003
984
}
1004
- PushFuncInfo (_u (" RestoreScopeInfo" ), func);
1005
985
1006
- if (!functionBody->DoStackNestedFunc ())
1007
- {
1008
- func->hasEscapedUseNestedFunc = true ;
1009
- }
986
+ // Recursively restore enclosing scope info so outermost scopes/funcs are pushed first.
987
+ this ->RestoreScopeInfo (scopeInfo->GetParentScopeInfo (), func);
988
+ this ->RestoreOneScope (scopeInfo, func);
1010
989
1011
- Js::ScopeInfo* funcExprScopeInfo = scopeInfo->GetFuncExprScopeInfo ();
1012
- if (funcExprScopeInfo)
990
+ if (newFunc)
1013
991
{
1014
- Scope* funcExprScope = funcExprScopeInfo->GetScope ();
1015
- Assert (funcExprScope);
1016
- funcExprScope->SetFunc (func);
1017
- func->SetFuncExprScope (funcExprScope);
1018
- funcExprScopeInfo->GetScopeInfo (nullptr , this , func, funcExprScope);
1019
- }
1020
-
1021
- // Restore the param scope after the function expression scope
1022
- if (paramScope != nullptr )
1023
- {
1024
- paramScope->SetFunc (func);
1025
- paramScopeInfo->GetScopeInfo (nullptr , this , func, paramScope);
992
+ PushFuncInfo (_u (" RestoreScopeInfo" ), func);
993
+ if (!pfi->DoStackNestedFunc ())
994
+ {
995
+ func->hasEscapedUseNestedFunc = true ;
996
+ }
1026
997
}
1027
- scopeInfo->GetScopeInfo (nullptr , this , func, bodyScope);
1028
998
}
1029
999
else
1030
1000
{
1031
1001
Assert (this ->TopFuncInfo () == nullptr );
1032
1002
// funcBody is glo
1003
+ Assert (currentScope == nullptr );
1033
1004
currentScope = Anew (alloc, Scope, alloc, ScopeType_Global);
1034
1005
globalScope = currentScope;
1035
1006
1036
- FuncInfo *func = Anew (alloc, FuncInfo, Js::Constants::GlobalFunction,
1037
- alloc, nullptr , currentScope, nullptr , functionBody);
1038
- PushFuncInfo (_u (" RestoreScopeInfo" ), func);
1007
+ if (func == nullptr || !func->byteCodeFunction ->GetIsGlobalFunc ())
1008
+ {
1009
+ func = Anew (alloc, FuncInfo, Js::Constants::GlobalFunction,
1010
+ alloc, nullptr , nullptr /* currentScope*/ , nullptr , nullptr /* functionBody*/ );
1011
+ PushFuncInfo (_u (" RestoreScopeInfo" ), func);
1012
+ }
1013
+ func->SetBodyScope (currentScope);
1039
1014
}
1040
1015
}
1041
1016
1017
+ void ByteCodeGenerator::RestoreOneScope (Js::ScopeInfo * scopeInfo, FuncInfo * func)
1018
+ {
1019
+ TRACE_BYTECODE (_u (" \n Restore ScopeInfo: %s #symbols: %d %s\n " ),
1020
+ func->name , scopeInfo->GetSymbolCount (), scopeInfo->IsObject () ? _u (" isObject" ) : _u (" " ));
1021
+
1022
+ Scope * scope = scopeInfo->GetScope ();
1023
+
1024
+ scope->SetFunc (func);
1025
+
1026
+ switch (scope->GetScopeType ())
1027
+ {
1028
+ case ScopeType_Parameter:
1029
+ if (!scopeInfo->GetCanMergeWithBodyScope ())
1030
+ {
1031
+ scope->SetCannotMergeWithBodyScope ();
1032
+ }
1033
+ Assert (func->GetParamScope () == nullptr );
1034
+ func->SetParamScope (scope);
1035
+ break ;
1036
+
1037
+ case ScopeType_FuncExpr:
1038
+ Assert (func->GetFuncExprScope () == nullptr );
1039
+ func->SetFuncExprScope (scope);
1040
+ break ;
1041
+
1042
+ case ScopeType_FunctionBody:
1043
+ case ScopeType_GlobalEvalBlock:
1044
+ Assert (func->GetBodyScope () == nullptr || (func->GetBodyScope ()->GetScopeType () == ScopeType_Global && scope->GetScopeType () == ScopeType_GlobalEvalBlock));
1045
+ func->SetBodyScope (scope);
1046
+ func->SetHasCachedScope (scopeInfo->IsCached ());
1047
+ break ;
1048
+ }
1049
+
1050
+ Assert (!scopeInfo->IsCached () || scope == func->GetBodyScope ());
1051
+
1052
+ // scopeInfo->scope was created/saved during parsing.
1053
+ // We no longer need it by now.
1054
+ // Clear it to avoid GC false positive (arena memory later used by GC).
1055
+ scopeInfo->SetScope (nullptr );
1056
+ this ->PushScope (scope);
1057
+ }
1058
+
1042
1059
FuncInfo * ByteCodeGenerator::StartBindGlobalStatements (ParseNode *pnode)
1043
1060
{
1044
- if (parentScopeInfo && parentScopeInfo-> GetParent () && (!parentScopeInfo-> GetParent ()-> GetIsGlobalFunc () || parentScopeInfo-> GetParent ()-> IsEval ()) )
1061
+ if (parentScopeInfo)
1045
1062
{
1046
1063
Assert (CONFIG_FLAG (DeferNested));
1047
1064
trackEnvDepth = true ;
1048
- RestoreScopeInfo (parentScopeInfo-> GetParent () );
1065
+ RestoreScopeInfo (parentScopeInfo, nullptr );
1049
1066
trackEnvDepth = false ;
1050
1067
// "currentScope" is the parentFunc scope. This ensures the deferred func declaration
1051
1068
// symbol will bind to the func declaration symbol already available in parentFunc scope.
@@ -1211,7 +1228,7 @@ FuncInfo * ByteCodeGenerator::StartBindFunction(const char16 *name, uint nameLen
1211
1228
if (parsedFunctionBody->GetScopeInfo ())
1212
1229
{
1213
1230
// Propagate flags from the (real) parent function.
1214
- Js::ParseableFunctionInfo *parent = parsedFunctionBody->GetScopeInfo ()->GetParent ();
1231
+ Js::ParseableFunctionInfo *parent = parsedFunctionBody->GetScopeInfo ()->GetParseableFunctionInfo ();
1215
1232
if (parent)
1216
1233
{
1217
1234
if (parent->GetHasOrParentHasArguments ())
@@ -1632,7 +1649,7 @@ Symbol * ByteCodeGenerator::FindSymbol(Symbol **symRef, IdentPtr pid, bool forRe
1632
1649
1633
1650
bool didTransferToFncVarSym = false ;
1634
1651
1635
- if (! PHASE_OFF (Js::OptimizeBlockScopePhase, top->byteCodeFunction ) &&
1652
+ if (PHASE_ON (Js::OptimizeBlockScopePhase, top->byteCodeFunction ) &&
1636
1653
sym->GetIsBlockVar () &&
1637
1654
!sym->GetScope ()->IsBlockInLoop () &&
1638
1655
sym->GetSymbolType () == STFunction)
@@ -1755,7 +1772,7 @@ Symbol * ByteCodeGenerator::AddSymbolToScope(Scope *scope, const char16 *key, in
1755
1772
// on such compiles, so we essentially have to migrate the symbol to the new scope.
1756
1773
// We check fscrEvalCode, not fscrEval, because the same thing can happen in indirect eval,
1757
1774
// when fscrEval is not set.
1758
- Assert (scope->GetScopeType () == ScopeType_Global);
1775
+ Assert (scope->GetScopeType () == ScopeType_Global || scope-> GetScopeType () == ScopeType_GlobalEvalBlock );
1759
1776
scope->AddNewSymbol (sym);
1760
1777
}
1761
1778
@@ -1995,7 +2012,7 @@ void ByteCodeGenerator::Generate(__in ParseNode *pnode, uint32 grfscr, __in Byte
1995
2012
1996
2013
void ByteCodeGenerator::CheckDeferParseHasMaybeEscapedNestedFunc ()
1997
2014
{
1998
- if (!this ->parentScopeInfo || ( this -> parentScopeInfo -> GetParent () && this -> parentScopeInfo -> GetParent ()-> GetIsGlobalFunc ()) )
2015
+ if (!this ->parentScopeInfo )
1999
2016
{
2000
2017
return ;
2001
2018
}
@@ -2023,7 +2040,7 @@ void ByteCodeGenerator::CheckDeferParseHasMaybeEscapedNestedFunc()
2023
2040
else
2024
2041
{
2025
2042
// We have to wait until it is parsed before we populate the stack nested func parent.
2026
- FuncInfo * parentFunc = top->GetBodyScope ()->GetEnclosingFunc ();
2043
+ FuncInfo * parentFunc = top->GetParamScope () ? top-> GetParamScope ()-> GetEnclosingFunc () : top-> GetBodyScope ()->GetEnclosingFunc ();
2027
2044
if (!parentFunc->IsGlobalFunction ())
2028
2045
{
2029
2046
Assert (parentFunc->byteCodeFunction != rootFuncBody);
@@ -2040,6 +2057,11 @@ void ByteCodeGenerator::CheckDeferParseHasMaybeEscapedNestedFunc()
2040
2057
FuncInfo * funcInfo = i.Data ();
2041
2058
Assert (funcInfo->IsRestored ());
2042
2059
Js::ParseableFunctionInfo * parseableFunctionInfo = funcInfo->byteCodeFunction ;
2060
+ if (parseableFunctionInfo == nullptr )
2061
+ {
2062
+ Assert (funcInfo->GetBodyScope () && funcInfo->GetBodyScope ()->GetScopeType () == ScopeType_Global);
2063
+ return ;
2064
+ }
2043
2065
bool didStackNestedFunc = parseableFunctionInfo->DoStackNestedFunc ();
2044
2066
if (!didStackNestedFunc)
2045
2067
{
@@ -3247,6 +3269,7 @@ void AddFunctionsToScope(ParseNodePtr scope, ByteCodeGenerator * byteCodeGenerat
3247
3269
sym->GetScope () != sym->GetScope ()->GetFunc ()->GetParamScope ())
3248
3270
{
3249
3271
sym->SetIsBlockVar (true );
3272
+ sym->SetHasRealBlockVarRef (true );
3250
3273
}
3251
3274
}
3252
3275
});
@@ -3629,15 +3652,21 @@ void PostVisitBlock(ParseNode *pnode, ByteCodeGenerator *byteCodeGenerator)
3629
3652
return ;
3630
3653
}
3631
3654
3655
+ Scope *scope = pnode->sxBlock .scope ;
3656
+
3632
3657
if (pnode->sxBlock .GetCallsEval () || pnode->sxBlock .GetChildCallsEval () || (byteCodeGenerator->GetFlags () & (fscrEval | fscrImplicitThis | fscrImplicitParents)))
3633
3658
{
3634
- Scope *scope = pnode->sxBlock .scope ;
3635
3659
bool scopeIsEmpty = scope->IsEmpty ();
3636
3660
scope->SetIsObject ();
3637
3661
scope->SetCapturesAll (true );
3638
3662
scope->SetMustInstantiate (!scopeIsEmpty);
3639
3663
}
3640
3664
3665
+ if (scope->GetHasOwnLocalInClosure ())
3666
+ {
3667
+ byteCodeGenerator->ProcessScopeWithCapturedSym (scope);
3668
+ }
3669
+
3641
3670
byteCodeGenerator->PopScope ();
3642
3671
byteCodeGenerator->PopBlock ();
3643
3672
@@ -3686,6 +3715,11 @@ void PreVisitCatch(ParseNode *pnode, ByteCodeGenerator *byteCodeGenerator)
3686
3715
3687
3716
void PostVisitCatch (ParseNode *pnode, ByteCodeGenerator *byteCodeGenerator)
3688
3717
{
3718
+ Scope *scope = pnode->sxCatch .scope ;
3719
+ if (scope->GetHasOwnLocalInClosure ())
3720
+ {
3721
+ byteCodeGenerator->ProcessScopeWithCapturedSym (scope);
3722
+ }
3689
3723
byteCodeGenerator->EndBindCatch ();
3690
3724
}
3691
3725
0 commit comments