diff --git a/lib/Sema/FlowChecker.cpp b/lib/Sema/FlowChecker.cpp index f4c086b7d06..d49c136b534 100644 --- a/lib/Sema/FlowChecker.cpp +++ b/lib/Sema/FlowChecker.cpp @@ -1949,19 +1949,21 @@ sema::Decl *FlowChecker::specializeGenericWithParsedTypes( }; // Create specialization if it doesn't exist. - // TODO: Determine if the actual clone can be deferred to avoid potential - // stack overflow by cloning from deep in the AST. if (doClone) { LLVM_DEBUG( llvh::dbgs() << "Creating specialization for: " << oldDecl->name.str() << "\n"); - specialization = cloneNode( - astContext_, - semContext_, - declCollectorMap_, - generic.originalNode, - scope->parentFunction, - scope); + // Avoid stack overflow in the clone by executing in a separate stack. + executeInStack( + *stackExecutor_, [this, &generic, scope, &specialization]() -> void { + specialization = cloneNode( + astContext_, + semContext_, + declCollectorMap_, + generic.originalNode, + scope->parentFunction, + scope); + }); if (!specialization) { sm_.error( typeArgsNode->getSourceRange(), diff --git a/lib/Sema/FlowChecker.h b/lib/Sema/FlowChecker.h index 791ae631ec0..188a6db9e04 100644 --- a/lib/Sema/FlowChecker.h +++ b/lib/Sema/FlowChecker.h @@ -16,6 +16,7 @@ #include "hermes/Sema/FlowContext.h" #include "hermes/Sema/Keywords.h" #include "hermes/Sema/SemContext.h" +#include "hermes/Support/StackExecutor.h" namespace hermes { namespace flow { @@ -73,6 +74,13 @@ class FlowChecker : public ESTree::RecursionDepthTracker { /// Keywords we will be checking for. sema::Keywords &kw_; + /// Use an 8MB stack, which is the default size on mac and linux. + static constexpr size_t kExecutorStackSize = 1 << 23; + + /// The executor used for cloning generics. + std::shared_ptr stackExecutor_ = + newStackExecutor(kExecutorStackSize); + struct TypeDecl { /// nullptr is used to indicate a generic declaration. Type *type;