From cba041613682c61a5c17c90a2417ac262bbc40bb Mon Sep 17 00:00:00 2001 From: Will Holen Date: Tue, 8 Sep 2020 14:27:55 -0700 Subject: [PATCH] Lift restriction on serializing a single scope at a time Summary: Since we only ever lazily compiled one layer of functions at a time, we only serialized a single scope and asserted that this was sufficient. This diff lifts this restriction, so that we can lazily compile multiple depths in one go. #utd-hermes-ignore-android Reviewed By: tmikov Differential Revision: D23580248 fbshipit-source-id: 449cd68c2bc155dac5564fb154da229e37c834f5 --- lib/IRGen/ESTreeIRGen.cpp | 25 +++++++++++-------------- lib/IRGen/ESTreeIRGen.h | 10 +++++++++- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/lib/IRGen/ESTreeIRGen.cpp b/lib/IRGen/ESTreeIRGen.cpp index 5c448b52c9a..1e0e77f66c0 100644 --- a/lib/IRGen/ESTreeIRGen.cpp +++ b/lib/IRGen/ESTreeIRGen.cpp @@ -1279,22 +1279,19 @@ void ESTreeIRGen::addLexicalDebugInfo( addLexicalDebugInfo(current, global, scope->parentScope); } -#ifndef HERMESVM_LEAN -std::shared_ptr ESTreeIRGen::saveCurrentScope() { - auto *func = curFunction()->function; - assert(func && "Missing function when saving scope"); +std::shared_ptr ESTreeIRGen::serializeScope( + FunctionContext *ctx, + bool includeGlobal) { + // Serialize the global scope if and only if it's the only scope. + // We serialize the global scope to avoid re-declaring variables, + // and only do it once to avoid creating spurious scopes. + if (!ctx || (ctx->function->isGlobalScope() && !includeGlobal)) + return lexicalScopeChain; auto scope = std::make_shared(); + auto *func = ctx->function; + assert(func && "Missing function when saving scope"); - // We currently only lazy compile a single level at a time. If we later start - // compiling multiple, this method would need to walk the scopes. - assert( - ((func->isGlobalScope() && !curFunction()->getPreviousContext()) || - (!func->isGlobalScope() && curFunction()->getPreviousContext() && - !curFunction()->getPreviousContext()->getPreviousContext())) && - "Expected exactly one function on the stack."); - - scope->parentScope = lexicalScopeChain; scope->originalName = func->getOriginalOrInferredName(); if (auto *closure = func->getLazyClosureAlias()) { scope->closureAlias = closure->getName(); @@ -1302,9 +1299,9 @@ std::shared_ptr ESTreeIRGen::saveCurrentScope() { for (auto *var : func->getFunctionScope()->getVariables()) { scope->variables.push_back(var->getName()); } + scope->parentScope = serializeScope(ctx->getPreviousContext(), false); return scope; } -#endif } // namespace irgen } // namespace hermes diff --git a/lib/IRGen/ESTreeIRGen.h b/lib/IRGen/ESTreeIRGen.h index e0d3f92a955..59b29cd16d9 100644 --- a/lib/IRGen/ESTreeIRGen.h +++ b/lib/IRGen/ESTreeIRGen.h @@ -1007,7 +1007,15 @@ class ESTreeIRGen { const std::shared_ptr &scope); /// Save all variables currently in scope, for lazy compilation. - std::shared_ptr saveCurrentScope(); + std::shared_ptr saveCurrentScope() { + return serializeScope(curFunction(), true); + } + + /// Recursively serialize scopes. The global scope is serialized + /// if and only if it's the first scope and includeGlobal is true. + std::shared_ptr serializeScope( + FunctionContext *ctx, + bool includeGlobal); }; template