Scope.cpp 5.7 KB

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