forked from chakra-core/ChakraCore
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathScope.cpp
More file actions
152 lines (132 loc) · 4.91 KB
/
Scope.cpp
File metadata and controls
152 lines (132 loc) · 4.91 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
//-------------------------------------------------------------------------------------------------------
// Copyright (C) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
//-------------------------------------------------------------------------------------------------------
#include "RuntimeByteCodePch.h"
bool Scope::IsGlobalEvalBlockScope() const
{
return this->scopeType == ScopeType_GlobalEvalBlock;
}
bool Scope::IsBlockScope(FuncInfo *funcInfo)
{
return this != funcInfo->GetBodyScope() && this != funcInfo->GetParamScope();
}
void Scope::SetHasLocalInClosure(bool has)
{
SetHasOwnLocalInClosure(has);
// (Note: if any catch var is closure-captured, we won't merge the catch scope with the function scope.
// So don't mark the function scope "has local in closure".)
bool notCatch = this->scopeType != ScopeType_Catch && this->scopeType != ScopeType_CatchParamPattern;
if (has && (this == func->GetBodyScope() || this == func->GetParamScope()) || (GetCanMerge() && notCatch))
{
func->SetHasLocalInClosure(true);
}
else
{
if (hasCrossScopeFuncAssignment)
{
func->SetHasMaybeEscapedNestedFunc(DebugOnly(_u("InstantiateScopeWithCrossScopeAssignment")));
}
SetMustInstantiate(true);
}
}
int Scope::AddScopeSlot()
{
int slot = scopeSlotCount++;
if (scopeSlotCount == Js::ScopeSlots::MaxEncodedSlotCount)
{
this->GetEnclosingFunc()->SetHasMaybeEscapedNestedFunc(DebugOnly(_u("TooManySlots")));
}
return slot;
}
void Scope::ForceAllSymbolNonLocalReference(ByteCodeGenerator *byteCodeGenerator)
{
this->ForEachSymbol([this, byteCodeGenerator](Symbol *const sym)
{
if (!sym->GetIsArguments())
{
sym->SetHasNonLocalReference(true, byteCodeGenerator);
this->GetFunc()->SetHasLocalInClosure(true);
}
});
}
bool Scope::IsEmpty() const
{
if (GetFunc()->bodyScope == this || (GetFunc()->IsGlobalFunction() && this->IsGlobalEvalBlockScope()))
{
return Count() == 0 && !GetFunc()->isThisLexicallyCaptured;
}
else
{
return Count() == 0;
}
}
void Scope::SetIsObject()
{
if (this->isObject)
{
return;
}
this->isObject = true;
// We might set the scope to be object after we have process the symbol
// (e.g. "With" scope referencing a symbol in an outer scope).
// If we have func assignment, we need to mark the function to not do stack nested function
// as these are now assigned to a scope object.
FuncInfo * funcInfo = this->GetFunc();
if (funcInfo && !funcInfo->HasMaybeEscapedNestedFunc())
{
this->ForEachSymbolUntil([funcInfo](Symbol * const sym)
{
if (sym->GetHasFuncAssignment())
{
funcInfo->SetHasMaybeEscapedNestedFunc(DebugOnly(_u("DelayedObjectScopeAssignment")));
return true;
}
return false;
});
}
if (this->GetScopeType() == ScopeType_FunctionBody && funcInfo && funcInfo->paramScope
&& !funcInfo->paramScope->GetIsObject() && !funcInfo->paramScope->GetCanMergeWithBodyScope())
{
// If this is split scope then mark the param scope also as an object
funcInfo->paramScope->SetIsObject();
}
}
void Scope::MergeParamAndBodyScopes(ParseNode *pnodeScope, ByteCodeGenerator *byteCodeGenerator)
{
Assert(pnodeScope->sxFnc.funcInfo);
Scope *paramScope = pnodeScope->sxFnc.pnodeScopes->sxBlock.scope;
Scope *bodyScope = pnodeScope->sxFnc.pnodeBodyScope->sxBlock.scope;
Assert(paramScope->m_symList == nullptr || paramScope->symbolTable == nullptr);
Assert(bodyScope->m_symList == nullptr || bodyScope->symbolTable == nullptr);
if (paramScope->Count() == 0)
{
// Once the scopes are merged, there's no reason to instantiate the param scope.
paramScope->SetMustInstantiate(false);
// Scopes are already merged or we don't have an arguments object. Go ahead and
// remove the param scope from the scope chain.
bodyScope->SetEnclosingScope(paramScope->GetEnclosingScope());
return;
}
bodyScope->scopeSlotCount = paramScope->scopeSlotCount;
paramScope->ForEachSymbol([&](Symbol * sym)
{
bodyScope->AddNewSymbol(sym);
});
if (paramScope->GetIsObject())
{
bodyScope->SetIsObject();
}
if (paramScope->GetMustInstantiate())
{
bodyScope->SetMustInstantiate(true);
}
// Once the scopes are merged, there's no reason to instantiate the param scope.
paramScope->SetMustInstantiate(false);
paramScope->m_count = 0;
paramScope->scopeSlotCount = 0;
paramScope->m_symList = nullptr;
paramScope->symbolTable = nullptr;
// Remove the parameter scope from the scope chain.
bodyScope->SetEnclosingScope(paramScope->GetEnclosingScope());
}