Scope.cpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  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. bool notCatch = this->scopeType != ScopeType_Catch && this->scopeType != ScopeType_CatchParamPattern;
  19. if (has && (this == func->GetBodyScope() || this == func->GetParamScope()) || (GetCanMerge() && notCatch))
  20. {
  21. func->SetHasLocalInClosure(true);
  22. }
  23. else
  24. {
  25. if (hasCrossScopeFuncAssignment)
  26. {
  27. func->SetHasMaybeEscapedNestedFunc(DebugOnly(_u("InstantiateScopeWithCrossScopeAssignment")));
  28. }
  29. SetMustInstantiate(true);
  30. }
  31. }
  32. int Scope::AddScopeSlot()
  33. {
  34. int slot = scopeSlotCount++;
  35. if (scopeSlotCount == Js::ScopeSlots::MaxEncodedSlotCount)
  36. {
  37. this->GetEnclosingFunc()->SetHasMaybeEscapedNestedFunc(DebugOnly(_u("TooManySlots")));
  38. }
  39. return slot;
  40. }
  41. void Scope::ForceAllSymbolNonLocalReference(ByteCodeGenerator *byteCodeGenerator)
  42. {
  43. this->ForEachSymbol([this, byteCodeGenerator](Symbol *const sym)
  44. {
  45. if (!sym->GetIsArguments())
  46. {
  47. sym->SetHasNonLocalReference(true, byteCodeGenerator);
  48. this->GetFunc()->SetHasLocalInClosure(true);
  49. }
  50. });
  51. }
  52. bool Scope::IsEmpty() const
  53. {
  54. if (GetFunc()->bodyScope == this || (GetFunc()->IsGlobalFunction() && this->IsGlobalEvalBlockScope()))
  55. {
  56. return Count() == 0 && !GetFunc()->isThisLexicallyCaptured;
  57. }
  58. else
  59. {
  60. return Count() == 0;
  61. }
  62. }
  63. void Scope::SetIsObject()
  64. {
  65. if (this->isObject)
  66. {
  67. return;
  68. }
  69. this->isObject = true;
  70. // We might set the scope to be object after we have process the symbol
  71. // (e.g. "With" scope referencing a symbol in an outer scope).
  72. // If we have func assignment, we need to mark the function to not do stack nested function
  73. // as these are now assigned to a scope object.
  74. FuncInfo * funcInfo = this->GetFunc();
  75. if (funcInfo && !funcInfo->HasMaybeEscapedNestedFunc())
  76. {
  77. this->ForEachSymbolUntil([funcInfo](Symbol * const sym)
  78. {
  79. if (sym->GetHasFuncAssignment())
  80. {
  81. funcInfo->SetHasMaybeEscapedNestedFunc(DebugOnly(_u("DelayedObjectScopeAssignment")));
  82. return true;
  83. }
  84. return false;
  85. });
  86. }
  87. }
  88. void Scope::MergeParamAndBodyScopes(ParseNode *pnodeScope, ByteCodeGenerator *byteCodeGenerator)
  89. {
  90. Assert(pnodeScope->sxFnc.funcInfo);
  91. Scope *paramScope = pnodeScope->sxFnc.pnodeScopes->sxBlock.scope;
  92. Scope *bodyScope = pnodeScope->sxFnc.pnodeBodyScope->sxBlock.scope;
  93. Assert(paramScope->m_symList == nullptr || paramScope->symbolTable == nullptr);
  94. Assert(bodyScope->m_symList == nullptr || bodyScope->symbolTable == nullptr);
  95. if (paramScope->Count() == 0)
  96. {
  97. // Once the scopes are merged, there's no reason to instantiate the param scope.
  98. paramScope->SetMustInstantiate(false);
  99. // Scopes are already merged or we don't have an arguments object. Go ahead and
  100. // remove the param scope from the scope chain.
  101. bodyScope->SetEnclosingScope(paramScope->GetEnclosingScope());
  102. return;
  103. }
  104. bodyScope->scopeSlotCount = paramScope->scopeSlotCount;
  105. paramScope->ForEachSymbol([&](Symbol * sym)
  106. {
  107. bodyScope->AddNewSymbol(sym);
  108. });
  109. if (paramScope->GetIsObject())
  110. {
  111. bodyScope->SetIsObject();
  112. }
  113. if (paramScope->GetMustInstantiate())
  114. {
  115. bodyScope->SetMustInstantiate(true);
  116. }
  117. // Once the scopes are merged, there's no reason to instantiate the param scope.
  118. paramScope->SetMustInstantiate(false);
  119. paramScope->m_count = 0;
  120. paramScope->scopeSlotCount = 0;
  121. paramScope->m_symList = nullptr;
  122. paramScope->symbolTable = nullptr;
  123. // Remove the parameter scope from the scope chain.
  124. bodyScope->SetEnclosingScope(paramScope->GetEnclosingScope());
  125. }