diff --git a/es2panda/binder/scope.cpp b/es2panda/binder/scope.cpp index e044f66c4670a2bb72881a2be4ce5d001f26a580..90a0c64cebba9176b51b860c6c8087244d6c0068 100644 --- a/es2panda/binder/scope.cpp +++ b/es2panda/binder/scope.cpp @@ -49,6 +49,20 @@ VariableScope *Scope::EnclosingVariableScope() return nullptr; } +FunctionScope *Scope::EnclosingFunctionVariableScope() +{ + Scope *iter = this; + while (iter) { + if (iter->IsFunctionVariableScope()) { + return iter->AsFunctionVariableScope(); + } + + iter = iter->Parent(); + } + + return nullptr; +} + Variable *Scope::FindLocal(const util::StringView &name, ResolveBindingOptions options) const { if (options & ResolveBindingOptions::INTERFACES) { @@ -78,6 +92,23 @@ ScopeFindResult Scope::Find(const util::StringView &name, ResolveBindingOptions uint32_t lexLevel = 0; const auto *iter = this; + if (iter->IsFunctionParamScope()) { + Variable *v = iter->FindLocal(name, options); + + if (v != nullptr) { + return {name, const_cast(iter), level, lexLevel, v}; + } + + level++; + auto *funcVariableScope = iter->AsFunctionParamScope()->GetFunctionScope(); + + if (funcVariableScope->NeedLexEnv()) { + lexLevel++; + } + + iter = iter->Parent(); + } + while (iter != nullptr) { Variable *v = iter->FindLocal(name, options); diff --git a/es2panda/binder/scope.h b/es2panda/binder/scope.h index 9621858f36bc2b887ed1fcbdbfc61b26cdb6b729..0dfda446f97fd19617d51a7fbdc27babaa2843d1 100644 --- a/es2panda/binder/scope.h +++ b/es2panda/binder/scope.h @@ -121,6 +121,8 @@ public: VariableScope *EnclosingVariableScope(); + FunctionScope *EnclosingFunctionVariableScope(); + const ArenaVector &Decls() const { return decls_; @@ -314,6 +316,17 @@ public: return params_; } + bool HasParam(util::StringView name) const + { + for (auto *param : params_) { + if (param->Name() == name) { + return true; + } + } + + return false; + } + std::tuple AddParamDecl(ArenaAllocator *allocator, const ir::AstNode *param); protected: diff --git a/es2panda/compiler/base/hoisting.cpp b/es2panda/compiler/base/hoisting.cpp index 07621e8d630c5793019c81bf2641fc2da9f5b9e2..815bf147a86f6909f90fd4781086b0773e07651c 100644 --- a/es2panda/compiler/base/hoisting.cpp +++ b/es2panda/compiler/base/hoisting.cpp @@ -31,6 +31,11 @@ static void HoistVar(PandaGen *pg, binder::Variable *var, const binder::VarDecl return; } + auto *funcScope = scope->EnclosingFunctionVariableScope(); + if (funcScope->ParamScope()->HasParam(decl->Name())) { + return; + } + binder::ScopeFindResult result(decl->Name(), scope, 0, var); pg->LoadConst(decl->Node(), Constant::JS_UNDEFINED); diff --git a/es2panda/compiler/core/envScope.cpp b/es2panda/compiler/core/envScope.cpp index 6e2fa13c78c7038bb1a0d4e2a0eb7405af141868..93fa239666a9f0cab650072dbb4b6ac52c1c080e 100644 --- a/es2panda/compiler/core/envScope.cpp +++ b/es2panda/compiler/core/envScope.cpp @@ -77,8 +77,23 @@ void LoopEnvScope::CopyPetIterationCtx() return; } - pg_->CopyLexEnv(scope_->Node()); + auto num = scope_->LexicalSlots(); + RegScope rs(pg_); + std::vector lexicals; + lexicals.reserve(num); + for (uint32_t i = 0; i < num; i++) { + VReg lexical = pg_->AllocReg(); + pg_->LoadLexicalVar(scope_->Node(), 0, i); + pg_->StoreAccumulator(scope_->Node(), lexical); + lexicals.push_back(lexical); + } + pg_->PopLexEnv(scope_->Node()); + pg_->NewLexEnv(scope_->Node(), num); pg_->StoreAccumulator(scope_->Node(), lexEnv_); + + for (uint32_t i = 0; i < num; i++) { + pg_->StoreLexicalVar(scope_->Node(), 0, i, lexicals[i]); + } } } // namespace panda::es2panda::compiler diff --git a/es2panda/compiler/core/pandagen.cpp b/es2panda/compiler/core/pandagen.cpp index 17375d9a93e8359e6e7b4374cc5bc0e9888b6ca9..97e7983ee3cef1e22ef61d078d7e9f2072a48833 100644 --- a/es2panda/compiler/core/pandagen.cpp +++ b/es2panda/compiler/core/pandagen.cpp @@ -164,8 +164,7 @@ void PandaGen::CopyFunctionArguments(const ir::AstNode *node) for (const auto *param : topScope_->ParamScope()->Params()) { if (param->LexicalBound()) { - LoadAccumulator(node, targetReg++); - StoreLexicalVar(node, 0, param->LexIdx()); + StoreLexicalVar(node, 0, param->LexIdx(), targetReg++); } else { ra_.Emit(node, param->Vreg(), targetReg++); } @@ -1353,11 +1352,13 @@ void PandaGen::GetAsyncIterator(const ir::AstNode *node) void PandaGen::CreateObjectWithExcludedKeys(const ir::AstNode *node, VReg obj, VReg argStart, size_t argCount) { ASSERT(argStart == obj + 1); - if (argCount == 0) { // Do not emit undefined register - argStart = obj; + if (argCount == 0) { + LoadConst(node, Constant::JS_UNDEFINED); + StoreAccumulator(node, argStart); } - rra_.Emit(node, argStart, argCount, static_cast(argCount), obj, + size_t argRegCnt = (argCount == 0 ? argCount : argCount - 1); + rra_.Emit(node, argStart, argCount, static_cast(argRegCnt), obj, argStart); } @@ -1482,13 +1483,17 @@ void PandaGen::LoadLexicalVar(const ir::AstNode *node, uint32_t level, uint32_t void PandaGen::StoreLexicalVar(const ir::AstNode *node, uint32_t level, uint32_t slot) { - // TODO: need to reconsider this part RegScope rs(this); VReg value = AllocReg(); StoreAccumulator(node, value); ra_.Emit(node, level, slot, value); } +void PandaGen::StoreLexicalVar(const ir::AstNode *node, uint32_t level, uint32_t slot, VReg value) +{ + ra_.Emit(node, level, slot, value); +} + void PandaGen::ThrowIfSuperNotCorrectCall(const ir::AstNode *node, int64_t num) { sa_.Emit(node, num); @@ -1503,6 +1508,7 @@ void PandaGen::ThrowUndefinedIfHole(const ir::AstNode *node, const util::StringV VReg nameReg = AllocReg(); StoreAccumulator(node, nameReg); ra_.Emit(node, holeReg, nameReg); + LoadAccumulator(node, holeReg); strings_.insert(name); } @@ -1524,7 +1530,7 @@ void PandaGen::PopLexEnv(const ir::AstNode *node) void PandaGen::CopyLexEnv(const ir::AstNode *node) { /* - * TODO: copy lexenv + * TODO: add copy lexenv to optimize the loop env creation * sa_.Emit(node); */ } diff --git a/es2panda/compiler/core/pandagen.h b/es2panda/compiler/core/pandagen.h index 67582f92e3112017278889585a03aef2304ed600..2236ffa5ca7d8094851883bad4e6c4bb830e7e45 100644 --- a/es2panda/compiler/core/pandagen.h +++ b/es2panda/compiler/core/pandagen.h @@ -355,6 +355,7 @@ public: void NewLexEnv(const ir::AstNode *node, uint32_t num); void LoadLexicalVar(const ir::AstNode *node, uint32_t level, uint32_t slot); void StoreLexicalVar(const ir::AstNode *node, uint32_t level, uint32_t slot); + void StoreLexicalVar(const ir::AstNode *node, uint32_t level, uint32_t slot, VReg value); void ThrowIfSuperNotCorrectCall(const ir::AstNode *node, int64_t num); void ThrowUndefinedIfHole(const ir::AstNode *node, const util::StringView &name);