From 59aac59298a4b4f3d77679ea6086f6f8cd7fe079 Mon Sep 17 00:00:00 2001 From: chenyiyuan Date: Wed, 8 Nov 2023 20:05:53 +0800 Subject: [PATCH] top level lexical variable add/delete support Signed-off-by: chenyiyuan Change-Id: I4b891e944ca8aee0f20f2a69196786dcc1352b8e --- es2panda/binder/binder.cpp | 9 +++++++++ es2panda/binder/scope.h | 5 +++++ es2panda/binder/variable.cpp | 9 +++++++-- es2panda/binder/variableFlags.h | 1 + es2panda/compiler/core/pandagen.cpp | 4 ++-- es2panda/es2panda.cpp | 2 +- .../hotreload-noerror/lexenv-increase/expected.txt | 10 +++++----- .../hotreload-noerror/lexenv-reduce/base.js | 2 +- .../hotreload-noerror/lexenv-reduce/base_mod.js | 2 +- .../hotreload-noerror/lexenv-reduce/expected.txt | 14 ++++++++++++-- es2panda/util/patchFix.cpp | 9 ++++++++- es2panda/util/patchFix.h | 3 ++- 12 files changed, 54 insertions(+), 16 deletions(-) diff --git a/es2panda/binder/binder.cpp b/es2panda/binder/binder.cpp index 784a32cb71..5fe48fd9f9 100644 --- a/es2panda/binder/binder.cpp +++ b/es2panda/binder/binder.cpp @@ -179,8 +179,17 @@ void Binder::IdentifierAnalysis(ResolveBindingFlags flags) ASSERT(scope_ == topScope_); bindingFlags_ = flags; + // Bind function main0 first to determine whether a lexical variable is in it or not under hot-reload mode if (bindingFlags_ & ResolveBindingFlags::TS_BEFORE_TRANSFORM) { + BuildFunction(topScope_, MAIN_FUNC_NAME); + ResolveReferences(program_->Ast()); + } else if (bindingFlags_ & ResolveBindingFlags::TS_AFTER_TRANSFORM) { + // Basically same as js, except of function main0 will not be bound after transform ResolveReferences(program_->Ast()); + AddMandatoryParams(); + if (topScope_->IsModuleScope()) { + AssignIndexToModuleVariable(); + } } else if (bindingFlags_ & ResolveBindingFlags::ALL) { BuildFunction(topScope_, MAIN_FUNC_NAME); ResolveReferences(program_->Ast()); diff --git a/es2panda/binder/scope.h b/es2panda/binder/scope.h index 7b00997390..a8ef3f48fc 100644 --- a/es2panda/binder/scope.h +++ b/es2panda/binder/scope.h @@ -394,6 +394,11 @@ public: return (flags_ & flag) != 0; } + void RestoreFuncMain0LexEnv(uint32_t slotSize) + { + slotIndex_ = slotSize; + } + uint32_t NextSlot() { return slotIndex_++; diff --git a/es2panda/binder/variable.cpp b/es2panda/binder/variable.cpp index 23c37db31a..42d1d45b26 100644 --- a/es2panda/binder/variable.cpp +++ b/es2panda/binder/variable.cpp @@ -50,10 +50,15 @@ void LocalVariable::SetLexical(Scope *scope, util::PatchFix *patchFixHelper) uint32_t slot = 0; auto name = Declaration()->Name(); - if (patchFixHelper && !patchFixHelper->IsHotReload() && patchFixHelper->IsScopeValidToPatchLexical(varScope)) { + if (patchFixHelper && patchFixHelper->IsScopeValidToPatchLexical(varScope)) { + // get slot from symbol table for lexical variable, if not found, slot is set to UINT32_MAX slot = patchFixHelper->GetSlotIdFromSymbolTable(std::string(name)); - if (patchFixHelper->IsPatchVar(slot)) { + // Store the additional lexical variable into PatchEnv + if (patchFixHelper->IsAdditionalVarInPatch(slot)) { patchFixHelper->AllocSlotfromPatchEnv(std::string(name)); + } else { + // Just for restore 'newlexenv' instruction for func_main_0 in patch + varScope->RestoreFuncMain0LexEnv(patchFixHelper->GetEnvSizeOfFuncMain0()); } } else { slot = varScope->NextSlot(); diff --git a/es2panda/binder/variableFlags.h b/es2panda/binder/variableFlags.h index d870bca045..3bdb668a0a 100644 --- a/es2panda/binder/variableFlags.h +++ b/es2panda/binder/variableFlags.h @@ -79,6 +79,7 @@ DEFINE_BITOPS(ResolveBindingOptions) enum class ResolveBindingFlags { ALL = 1U << 0U, TS_BEFORE_TRANSFORM = 1U << 1U, + TS_AFTER_TRANSFORM = 1U << 2U, }; DEFINE_BITOPS(ResolveBindingFlags) diff --git a/es2panda/compiler/core/pandagen.cpp b/es2panda/compiler/core/pandagen.cpp index c138f1c323..53786cbdf5 100644 --- a/es2panda/compiler/core/pandagen.cpp +++ b/es2panda/compiler/core/pandagen.cpp @@ -1809,7 +1809,7 @@ void PandaGen::LoadLexicalVar(const ir::AstNode *node, uint32_t level, uint32_t void PandaGen::LoadLexicalVar(const ir::AstNode *node, uint32_t level, uint32_t slot, const util::StringView &name) { - if (context_->PatchFixHelper() && context_->PatchFixHelper()->IsPatchVar(slot)) { + if (context_->PatchFixHelper() && context_->PatchFixHelper()->IsAdditionalVarInPatch(slot)) { uint32_t patchSlot = context_->PatchFixHelper()->GetPatchLexicalIdx(std::string(name)); ra_.Emit(node, patchSlot); return; @@ -1847,7 +1847,7 @@ void PandaGen::StoreLexicalVar(const ir::AstNode *node, uint32_t level, uint32_t void PandaGen::StoreLexicalVar(const ir::AstNode *node, uint32_t level, uint32_t slot, const binder::LocalVariable *local) { - if (context_->PatchFixHelper() && context_->PatchFixHelper()->IsPatchVar(slot)) { + if (context_->PatchFixHelper() && context_->PatchFixHelper()->IsAdditionalVarInPatch(slot)) { uint32_t patchSlot = context_->PatchFixHelper()->GetPatchLexicalIdx(std::string(local->Name())); ra_.Emit(node, patchSlot); return; diff --git a/es2panda/es2panda.cpp b/es2panda/es2panda.cpp index 6038195d6a..38ec4c58a3 100644 --- a/es2panda/es2panda.cpp +++ b/es2panda/es2panda.cpp @@ -90,7 +90,7 @@ panda::pandasm::Program *Compiler::Compile(const SourceFile &input, const Compil if (ast.Extension() == ScriptExtension::TS) { transformer_->Transform(&ast); - ast.Binder()->IdentifierAnalysis(binder::ResolveBindingFlags::ALL); + ast.Binder()->IdentifierAnalysis(binder::ResolveBindingFlags::TS_AFTER_TRANSFORM); if (options.dumpTransformedAst) { std::cout << ast.Dump() << std::endl; } diff --git a/es2panda/test/hotreload/hotreload-noerror/lexenv-increase/expected.txt b/es2panda/test/hotreload/hotreload-noerror/lexenv-increase/expected.txt index 5d8ca0489d..b8064d65e5 100644 --- a/es2panda/test/hotreload/hotreload-noerror/lexenv-increase/expected.txt +++ b/es2panda/test/hotreload/hotreload-noerror/lexenv-increase/expected.txt @@ -24,7 +24,7 @@ label_0: lda v1 add2 0x0, v0 sta v0 - ldlexvar 0x0, 0x2 + wide.ldpatchvar 0x0 sta v1 throw.undefinedifholewithname c lda v1 @@ -33,7 +33,7 @@ label_0: ldai 0x3 add2 0x2, v0 sta v0 - ldlexvar 0x0, 0x3 + wide.ldpatchvar 0x1 sta v1 throw.undefinedifholewithname n lda v1 @@ -45,7 +45,7 @@ label_2: .function any .func_main_0(any a0, any a1, any a2) { label_1: label_0: - newlexenv 0x4 + newlexenv 0x2 definefunc 0x0, .A, 0x0 ldai 0x1 sta v0 @@ -54,9 +54,9 @@ label_0: lda v0 stlexvar 0x0, 0x1 lda v0 - stlexvar 0x0, 0x2 + wide.stpatchvar 0x0 ldai 0x2 - stlexvar 0x0, 0x3 + wide.stpatchvar 0x1 ldundefined returnundefined label_2: diff --git a/es2panda/test/hotreload/hotreload-noerror/lexenv-reduce/base.js b/es2panda/test/hotreload/hotreload-noerror/lexenv-reduce/base.js index b377a08164..f5717a46eb 100644 --- a/es2panda/test/hotreload/hotreload-noerror/lexenv-reduce/base.js +++ b/es2panda/test/hotreload/hotreload-noerror/lexenv-reduce/base.js @@ -2,7 +2,7 @@ let a = 1; let b = 1; let c = 1; function A() { - let d = a + b; + let d = a + b + c; let e = 3; let m = d + e; return m; diff --git a/es2panda/test/hotreload/hotreload-noerror/lexenv-reduce/base_mod.js b/es2panda/test/hotreload/hotreload-noerror/lexenv-reduce/base_mod.js index 3f9da8bb7b..0127642414 100644 --- a/es2panda/test/hotreload/hotreload-noerror/lexenv-reduce/base_mod.js +++ b/es2panda/test/hotreload/hotreload-noerror/lexenv-reduce/base_mod.js @@ -2,7 +2,7 @@ let a = 1; let b = 1; let c = 1; function A() { - let d = a; + let d = a + c; let e = 3; let m = d + e; return m; diff --git a/es2panda/test/hotreload/hotreload-noerror/lexenv-reduce/expected.txt b/es2panda/test/hotreload/hotreload-noerror/lexenv-reduce/expected.txt index d94e48e675..33ac3f73ec 100644 --- a/es2panda/test/hotreload/hotreload-noerror/lexenv-reduce/expected.txt +++ b/es2panda/test/hotreload/hotreload-noerror/lexenv-reduce/expected.txt @@ -18,8 +18,14 @@ label_0: ldlexvar 0x0, 0x0 sta v0 throw.undefinedifholewithname a - ldai 0x3 + ldlexvar 0x0, 0x2 + sta v1 + throw.undefinedifholewithname c + lda v1 add2 0x0, v0 + sta v0 + ldai 0x3 + add2 0x1, v0 return label_2: } @@ -27,10 +33,14 @@ label_2: .function any .func_main_0(any a0, any a1, any a2) { label_1: label_0: - newlexenv 0x1 + newlexenv 0x3 definefunc 0x0, .A, 0x0 ldai 0x1 + sta v0 + lda v0 stlexvar 0x0, 0x0 + lda v0 + stlexvar 0x0, 0x2 ldundefined returnundefined label_2: diff --git a/es2panda/util/patchFix.cpp b/es2panda/util/patchFix.cpp index e5a8a8ad55..867ad9da22 100644 --- a/es2panda/util/patchFix.cpp +++ b/es2panda/util/patchFix.cpp @@ -293,6 +293,13 @@ uint32_t PatchFix::GetSlotIdFromSymbolTable(const std::string &variableName) return UINT32_MAX; } +uint32_t PatchFix::GetEnvSizeOfFuncMain0() +{ + auto functionIter = originFunctionInfo_->find(funcMain0_); + ASSERT(functionIter != originFunctionInfo_->end()); + return functionIter->second.lexenv.size(); +} + uint32_t PatchFix::GetPatchLexicalIdx(const std::string &variableName) { ASSERT(topScopeLexEnvs_.count(variableName)); @@ -618,7 +625,7 @@ void PatchFix::DumpFunctionInfo(const compiler::PandaGen *pg, panda::pandasm::Fu symbolTable_->WriteSymbolTable(ss.str()); } -bool PatchFix::IsPatchVar(uint32_t slot) +bool PatchFix::IsAdditionalVarInPatch(uint32_t slot) { return slot == UINT32_MAX; } diff --git a/es2panda/util/patchFix.h b/es2panda/util/patchFix.h index 3b255b2328..0c99c71d07 100644 --- a/es2panda/util/patchFix.h +++ b/es2panda/util/patchFix.h @@ -66,9 +66,10 @@ public: void Finalize(panda::pandasm::Program **prog); bool IsScopeValidToPatchLexical(binder::VariableScope *scope) const; uint32_t GetSlotIdFromSymbolTable(const std::string &variableName); + uint32_t GetEnvSizeOfFuncMain0(); void AllocSlotfromPatchEnv(const std::string &variableName); uint32_t GetPatchLexicalIdx(const std::string &variableName); - bool IsPatchVar(uint32_t slot); + bool IsAdditionalVarInPatch(uint32_t slot); void ProcessFunction(const compiler::PandaGen *pg, panda::pandasm::Function *func, LiteralBuffers &literalBuffers); void ProcessModule(const std::string &recordName, std::vector &moduleBuffer); void ProcessJsonContentRecord(const std::string &recordName, const std::string &jsonFileContent); -- Gitee