| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298 |
- //-------------------------------------------------------------------------------------------------------
- // Copyright (C) Microsoft. All rights reserved.
- // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
- //-------------------------------------------------------------------------------------------------------
- enum ScopeType
- {
- ScopeType_Unknown,
- ScopeType_Global,
- ScopeType_GlobalEvalBlock,
- ScopeType_FunctionBody,
- ScopeType_FuncExpr,
- ScopeType_Block,
- ScopeType_Catch,
- ScopeType_CatchParamPattern,
- ScopeType_With,
- ScopeType_Parameter
- };
- class Scope
- {
- private:
- Scope *enclosingScope;
- Js::RegSlot location;
- FuncInfo *func;
- SymbolTable *symbolTable;
- Symbol *m_symList;
- int m_count;
- ArenaAllocator *alloc;
- uint scopeSlotCount; // count of slots in the local scope
- uint innerScopeIndex;
- ScopeType const scopeType;
- BYTE isDynamic : 1;
- BYTE isObject : 1;
- BYTE canMerge : 1;
- BYTE capturesAll : 1;
- BYTE mustInstantiate : 1;
- BYTE hasCrossScopeFuncAssignment : 1;
- public:
- #if DBG
- BYTE isRestored : 1;
- #endif
- Scope(ArenaAllocator *alloc, ScopeType scopeType, bool useSymbolTable = false, int capacity = 0) :
- alloc(alloc),
- func(nullptr),
- enclosingScope(nullptr),
- isDynamic(false),
- isObject(false),
- canMerge(true),
- capturesAll(false),
- mustInstantiate(false),
- hasCrossScopeFuncAssignment(false),
- location(Js::Constants::NoRegister),
- symbolTable(nullptr),
- m_symList(nullptr),
- m_count(0),
- scopeSlotCount(0),
- innerScopeIndex((uint)-1),
- scopeType(scopeType)
- #if DBG
- , isRestored(false)
- #endif
- {
- if (useSymbolTable)
- {
- symbolTable = Anew(alloc, SymbolTable, alloc, capacity);
- }
- }
- ~Scope()
- {
- if (symbolTable)
- {
- Adelete(alloc, symbolTable);
- symbolTable = nullptr;
- }
- }
- Symbol *FindLocalSymbol(SymbolName const& key)
- {
- Symbol *sym = nullptr;
- if (symbolTable)
- {
- return symbolTable->Lookup(key);
- }
- for (sym = m_symList; sym; sym = sym->GetNext())
- {
- if (sym->GetName() == key)
- {
- break;
- }
- }
- return sym;
- }
- template<class Fn>
- void ForEachSymbol(Fn fn)
- {
- if (symbolTable)
- {
- symbolTable->Map(fn);
- }
- else
- {
- for (Symbol *sym = m_symList; sym;)
- {
- Symbol *next = sym->GetNext();
- fn(sym);
- sym = next;
- }
- }
- }
- template<class Fn>
- void ForEachSymbolUntil(Fn fn)
- {
- if (symbolTable)
- {
- symbolTable->MapUntil(fn);
- }
- else
- {
- for (Symbol *sym = m_symList; sym;)
- {
- Symbol *next = sym->GetNext();
- if (fn(sym))
- {
- return;
- }
- sym = next;
- }
- }
- }
- // For JScript, this should not return NULL because
- // there is always an enclosing global scope.
- Symbol *FindSymbol(SymbolName const& name, SymbolType symbolType, bool fCreate = true)
- {
- Symbol *sym = FindLocalSymbol(name);
- if (sym == nullptr)
- {
- if (enclosingScope != nullptr)
- {
- sym = enclosingScope->FindSymbol(name, symbolType);
- }
- else if (fCreate)
- {
- sym = Anew(alloc, Symbol, name, nullptr, symbolType);
- AddNewSymbol(sym);
- }
- }
- return sym;
- }
- void AddSymbol(Symbol *sym)
- {
- if (enclosingScope == nullptr)
- {
- sym->SetIsGlobal(true);
- }
- sym->SetScope(this);
- if (symbolTable)
- {
- symbolTable->AddNew(sym);
- }
- else
- {
- for (Symbol *symInList = m_symList; symInList; symInList = symInList->GetNext())
- {
- if (symInList->GetName() == sym->GetName())
- {
- return;
- }
- }
- sym->SetNext(m_symList);
- m_symList = sym;
- m_count++;
- }
- }
- void AddNewSymbol(Symbol *sym)
- {
- if (scopeType == ScopeType_Global)
- {
- sym->SetIsGlobal(true);
- }
- sym->SetScope(this);
- if (symbolTable)
- {
- symbolTable->Add(sym);
- }
- else
- {
- sym->SetNext(m_symList);
- m_symList = sym;
- m_count++;
- }
- }
- bool HasStaticPathToAncestor(Scope const * target) const
- {
- return target == this || (!isDynamic && enclosingScope != nullptr && enclosingScope->HasStaticPathToAncestor(target));
- }
- void SetEnclosingScope(Scope *enclosingScope)
- {
- // Check for scope cycles
- Assert(enclosingScope != this);
- Assert(enclosingScope == nullptr || this != enclosingScope->GetEnclosingScope());
- this->enclosingScope = enclosingScope;
- }
- Scope *GetEnclosingScope() const
- {
- return enclosingScope;
- }
- ScopeType GetScopeType() const
- {
- return this->scopeType;
- }
- bool IsInnerScope() const
- {
- return scopeType == ScopeType_Block || scopeType == ScopeType_Catch || scopeType == ScopeType_CatchParamPattern || scopeType == ScopeType_GlobalEvalBlock;
- }
- int Count() const
- {
- if (symbolTable)
- {
- return symbolTable->Count();
- }
- return m_count;
- }
- void SetFunc(FuncInfo *func)
- {
- this->func = func;
- }
- FuncInfo *GetFunc() const
- {
- return func;
- }
- FuncInfo *GetEnclosingFunc()
- {
- Scope *scope = this;
- while (scope && scope->func == nullptr)
- {
- scope = scope->GetEnclosingScope();
- }
- AnalysisAssert(scope);
- return scope->func;
- }
- void SetLocation(Js::RegSlot loc) { location = loc; }
- Js::RegSlot GetLocation() const { return location; }
- void SetIsDynamic(bool is) { isDynamic = is; }
- bool GetIsDynamic() const { return isDynamic; }
- bool IsEmpty() const;
- bool IsBlockScope(FuncInfo *funcInfo);
- void SetIsObject();
- bool GetIsObject() const { return isObject; }
- void SetCapturesAll(bool does) { capturesAll = does; }
- bool GetCapturesAll() const { return capturesAll; }
- void SetMustInstantiate(bool must) { mustInstantiate = must; }
- bool GetMustInstantiate() const { return mustInstantiate; }
- void SetCanMerge(bool can) { canMerge = can; }
- bool GetCanMerge() const { return canMerge && !mustInstantiate && !isObject; }
- void SetScopeSlotCount(uint i) { scopeSlotCount = i; }
- uint GetScopeSlotCount() const { return scopeSlotCount; }
- void SetHasLocalInClosure(bool has);
- bool HasInnerScopeIndex() const { return innerScopeIndex != (uint)-1; }
- uint GetInnerScopeIndex() const { return innerScopeIndex; }
- void SetInnerScopeIndex(uint index) { Assert(innerScopeIndex == (uint)-1 || innerScopeIndex == index); innerScopeIndex = index; }
- int AddScopeSlot();
- void SetHasCrossScopeFuncAssignment() { hasCrossScopeFuncAssignment = true; }
- void ForceAllSymbolNonLocalReference(ByteCodeGenerator *byteCodeGenerator);
- bool IsGlobalEvalBlockScope() const;
- static void MergeParamAndBodyScopes(ParseNode *pnodeScope, ByteCodeGenerator * byteCodeGenerator);
- };
|