diff --git a/es2panda/BUILD.gn b/es2panda/BUILD.gn index 880e24c18bbac0ed972c609b6d7e7da0a17202fd..fa6cc8cb1fcacb2332096412dcfda6fc1968ba3d 100644 --- a/es2panda/BUILD.gn +++ b/es2panda/BUILD.gn @@ -250,7 +250,7 @@ es2panda_src = [ "util/concurrent.cpp", "util/dumper.cpp", "util/helpers.cpp", - "util/hotfix.cpp", + "util/patchFix.cpp", "util/moduleHelpers.cpp", "util/symbolTable.cpp", "util/ustring.cpp", diff --git a/es2panda/aot/options.cpp b/es2panda/aot/options.cpp index 885fa76372c5b91b865a50943e971f79d611b720..f7306e51c03d05e7923b24c7e7fe20b623b1aa1d 100644 --- a/es2panda/aot/options.cpp +++ b/es2panda/aot/options.cpp @@ -228,10 +228,11 @@ bool Options::Parse(int argc, const char **argv) panda::PandArg opNpmModuleEntryList("npm-module-entry-list", "", "entry list file for module compile"); panda::PandArg opMergeAbc("merge-abc", false, "Compile as merge abc"); - // hotfix && hotreload + // patchFix && hotreload panda::PandArg opDumpSymbolTable("dump-symbol-table", "", "dump symbol table to file"); panda::PandArg opInputSymbolTable("input-symbol-table", "", "input symbol table file"); panda::PandArg opGeneratePatch("generate-patch", false, "generate patch abc"); + panda::PandArg opHotfix("hot-fix", false, "generate patch abc as hot-fix mode"); panda::PandArg opHotReload("hot-reload", false, "compile as hot-reload mode"); // version @@ -276,6 +277,7 @@ bool Options::Parse(int argc, const char **argv) argparser_->Add(&opDumpSymbolTable); argparser_->Add(&opInputSymbolTable); argparser_->Add(&opGeneratePatch); + argparser_->Add(&opHotfix); argparser_->Add(&opHotReload); argparser_->Add(&bcVersion); @@ -450,10 +452,11 @@ bool Options::Parse(int argc, const char **argv) compilerOptions_.sourceFiles = sourceFiles_; compilerOptions_.mergeAbc = opMergeAbc.GetValue(); - compilerOptions_.hotfixOptions.dumpSymbolTable = opDumpSymbolTable.GetValue(); - compilerOptions_.hotfixOptions.symbolTable = opInputSymbolTable.GetValue(); - compilerOptions_.hotfixOptions.generatePatch = opGeneratePatch.GetValue(); - compilerOptions_.hotfixOptions.hotReload = opHotReload.GetValue(); + compilerOptions_.patchFixOptions.dumpSymbolTable = opDumpSymbolTable.GetValue(); + compilerOptions_.patchFixOptions.symbolTable = opInputSymbolTable.GetValue(); + compilerOptions_.patchFixOptions.generatePatch = opGeneratePatch.GetValue(); + compilerOptions_.patchFixOptions.hotfix = opHotfix.GetValue(); + compilerOptions_.patchFixOptions.hotReload = opHotReload.GetValue(); return true; } diff --git a/es2panda/binder/binder.cpp b/es2panda/binder/binder.cpp index e203801cb3ea4aa822012f5d1be8651d09e02bd6..3c800d68189fab36e5609352825bd29c1c795cf0 100644 --- a/es2panda/binder/binder.cpp +++ b/es2panda/binder/binder.cpp @@ -236,7 +236,7 @@ void Binder::LookupReference(const util::StringView &name) } ASSERT(res.variable); - res.variable->SetLexical(res.scope, program_->HotfixHelper()); + res.variable->SetLexical(res.scope, program_->PatchFixHelper()); } void Binder::InstantiateArguments() @@ -292,10 +292,9 @@ void Binder::LookupIdentReference(ir::Identifier *ident) } if (res.level != 0) { - ASSERT(res.variable); - if (!res.variable->Declaration()->IsDeclare()) { + ASSERT(res.variable);if (!res.variable->Declaration()->IsDeclare()) { util::Concurrent::VerifyImportVarForConcurrentFunction(Program()->GetLineIndex(), ident, res); - res.variable->SetLexical(res.scope, program_->HotfixHelper()); + res.variable->SetLexical(res.scope, program_->PatchFixHelper()); } } @@ -320,19 +319,46 @@ void Binder::BuildFunction(FunctionScope *funcScope, util::StringView name, cons functionScopes_.push_back(funcScope); funcScope->SetInFunctionScopes(); + std::cout << "func_name: " << name << std::endl; + bool funcNameWithoutDot = (name.Find(".") == std::string::npos); bool funcNameWithoutBackslash = (name.Find("\\") == std::string::npos); if (name != ANONYMOUS_FUNC_NAME && funcNameWithoutDot && funcNameWithoutBackslash && !functionNames_.count(name)) { + // function with normal name, and hasn't been recorded auto internalName = std::string(program_->FormatedRecordName()) + std::string(name); functionNames_.insert(name); funcScope->BindName(name, util::UString(internalName, Allocator()).View()); return; } + std::stringstream ss; ss << std::string(program_->FormatedRecordName()); - uint32_t idx = functionNameIndex_++; - ss << "#" << std::to_string(idx) << "#"; - if (name == ANONYMOUS_FUNC_NAME && func != nullptr) { + + auto startSourcePos = func->Start(); + auto endSourcePos = func->End(); + + auto wholeSourceCode = Program()->SourceCode(); + + auto startIndex = startSourcePos.index; + auto endIndex = endSourcePos.index; + + // For anonymous and duplicated func, get its source and name, make hash code, + // and make #hash_duplicateHashTime#name as its name; + auto funcContentNameStr = wholeSourceCode.Substr(startIndex, endIndex).Mutf8() + name.Mutf8(); + ss << ANONYMOUS_OR_DUPLICATE_FUNCTION_SPECIFIER << std::hash{}(funcContentNameStr); + + std::cout << "funcContentNameStr: " << funcContentNameStr << std::endl; + + auto res = functionHashNames_.find(funcContentNameStr); + if (res != functionHashNames_.end()) { + ss << "_" << res->second++; + } else { + // function name never equal to hash value(all number) + functionHashNames_.insert({funcContentNameStr, 1}); + } + ss << ANONYMOUS_OR_DUPLICATE_FUNCTION_SPECIFIER; + + if (name == ANONYMOUS_FUNC_NAME) { anonymousFunctionNames_[func] = util::UString(ss.str(), Allocator()).View(); } if (funcNameWithoutDot && funcNameWithoutBackslash) { diff --git a/es2panda/binder/binder.h b/es2panda/binder/binder.h index 3d3bfe8f287dc03a933cfc311bd7c8a3dd6f766d..baa51b3dc06630fb19866e1ecb127c30775ebfab 100644 --- a/es2panda/binder/binder.h +++ b/es2panda/binder/binder.h @@ -48,6 +48,7 @@ public: functionScopes_(Allocator()->Adapter()), functionNames_(Allocator()->Adapter()), anonymousFunctionNames_(Allocator()->Adapter()), + functionHashNames_(Allocator()->Adapter()), variableNames_(Allocator()->Adapter()), extension_(extension) { @@ -154,6 +155,7 @@ public: static constexpr std::string_view MAIN_FUNC_NAME = "func_main_0"; static constexpr std::string_view ANONYMOUS_FUNC_NAME = ""; + static constexpr std::string_view ANONYMOUS_OR_DUPLICATE_FUNCTION_SPECIFIER = "#"; private: using MandatoryParams = std::array; @@ -212,8 +214,8 @@ private: ResolveBindingOptions bindingOptions_; ArenaSet functionNames_; ArenaUnorderedMap anonymousFunctionNames_; + ArenaUnorderedMap functionHashNames_; ArenaSet variableNames_; - size_t functionNameIndex_ {1}; ResolveBindingFlags bindingFlags_ {ResolveBindingFlags::ALL}; ScriptExtension extension_; }; diff --git a/es2panda/binder/scope.h b/es2panda/binder/scope.h index fa188a50a35e7604ce47d55b9560659932adaa59..df26bb49997abf2221fc1608ec3b6e559ef50ff1 100644 --- a/es2panda/binder/scope.h +++ b/es2panda/binder/scope.h @@ -442,7 +442,7 @@ protected: VariableScopeFlags flags_ {}; uint32_t slotIndex_ {}; - ArenaMap> lexicalVarNameAndTypes_; // for debuginfo and hotfix + ArenaMap> lexicalVarNameAndTypes_; // for debuginfo and patchFix }; class ParamScope : public Scope { diff --git a/es2panda/binder/variable.cpp b/es2panda/binder/variable.cpp index 0539c9ccc5c0648abfe147207c4e3d992eb9887d..2d5536c11207a7b6b4afbb4ddab8f27e24d7ffe4 100644 --- a/es2panda/binder/variable.cpp +++ b/es2panda/binder/variable.cpp @@ -40,7 +40,7 @@ LocalVariable *LocalVariable::Copy(ArenaAllocator *allocator, Decl *decl) const return var; } -void LocalVariable::SetLexical(Scope *scope, util::Hotfix *hotfixHelper) +void LocalVariable::SetLexical(Scope *scope, util::PatchFix *patchFixHelper) { if (LexicalBound()) { return; @@ -50,10 +50,10 @@ void LocalVariable::SetLexical(Scope *scope, util::Hotfix *hotfixHelper) uint32_t slot = 0; auto name = Declaration()->Name(); - if (hotfixHelper && hotfixHelper->IsScopeValidToPatchLexical(varScope)) { - slot = hotfixHelper->GetSlotIdFromSymbolTable(std::string(name)); - if (hotfixHelper->IsPatchVar(slot)) { - hotfixHelper->AllocSlotfromPatchEnv(std::string(name)); + if (patchFixHelper && patchFixHelper->IsScopeValidToPatchLexical(varScope)) { + slot = patchFixHelper->GetSlotIdFromSymbolTable(std::string(name)); + if (patchFixHelper->IsPatchVar(slot)) { + patchFixHelper->AllocSlotfromPatchEnv(std::string(name)); } } else { slot = varScope->NextSlot(); @@ -65,12 +65,12 @@ void LocalVariable::SetLexical(Scope *scope, util::Hotfix *hotfixHelper) static_cast::type>(Declaration()->Type())); } -void GlobalVariable::SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] util::Hotfix *hotfixHelper) {} -void ModuleVariable::SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] util::Hotfix *hotfixHelper) {} -void EnumVariable::SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] util::Hotfix *hotfixHelper) {} -void NamespaceVariable::SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] util::Hotfix *hotfixHelper) {} -void ImportEqualsVariable::SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] util::Hotfix *hotfixHelper) {} -void EnumLiteralVariable::SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] util::Hotfix *hotfixHelper) {} +void GlobalVariable::SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] util::PatchFix *patchFixHelper) {} +void ModuleVariable::SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] util::PatchFix *patchFixHelper) {} +void EnumVariable::SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] util::PatchFix *patchFixHelper) {} +void NamespaceVariable::SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] util::PatchFix *patchFixHelper) {} +void ImportEqualsVariable::SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] util::PatchFix *patchFixHelper) {} +void EnumLiteralVariable::SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] util::PatchFix *patchFixHelper) {} void EnumVariable::ResetDecl(Decl *decl) { diff --git a/es2panda/binder/variable.h b/es2panda/binder/variable.h index 6ddcf184f224552658d4550034701a6f2b183792..34bbc94bd2d1f9997e9d78fd0dd00a11f0dc5cb6 100644 --- a/es2panda/binder/variable.h +++ b/es2panda/binder/variable.h @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include @@ -116,7 +116,7 @@ public: } const util::StringView &Name() const; - virtual void SetLexical(Scope *scope, util::Hotfix *hotfixHelper = nullptr) = 0; + virtual void SetLexical(Scope *scope, util::PatchFix *patchFixHelper = nullptr) = 0; protected: explicit Variable(Decl *decl, VariableFlags flags) : decl_(decl), flags_(flags) {} @@ -159,7 +159,7 @@ public: return vreg_; } - void SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] util::Hotfix *hotfixHelper = nullptr) override; + void SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] util::PatchFix *patchFixHelper = nullptr) override; LocalVariable *Copy(ArenaAllocator *allocator, Decl *decl) const; private: @@ -175,7 +175,7 @@ public: return VariableType::GLOBAL; } - void SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] util::Hotfix *hotfixHelper = nullptr) override; + void SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] util::PatchFix *patchFixHelper = nullptr) override; }; class ModuleVariable : public Variable { @@ -187,7 +187,7 @@ public: return VariableType::MODULE; } - void SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] util::Hotfix *hotfixHelper = nullptr) override; + void SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] util::PatchFix *patchFixHelper = nullptr) override; void AssignIndex(uint32_t index) { @@ -257,7 +257,7 @@ public: void ResetDecl(Decl *decl); - void SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] util::Hotfix *hotfixHelper = nullptr) override; + void SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] util::PatchFix *patchFixHelper = nullptr) override; private: EnumMemberResult value_ {false}; @@ -275,7 +275,7 @@ public: return VariableType::NAMESPACE; } - void SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] util::Hotfix *hotfixHelper = nullptr) override; + void SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] util::PatchFix *patchFixHelper = nullptr) override; ExportBindings *GetExportBindings() { @@ -305,7 +305,7 @@ public: return VariableType::ENUMLITERAL; } - void SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] util::Hotfix *hotfixHelper = nullptr) override; + void SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] util::PatchFix *patchFixHelper = nullptr) override; VariableMap *GetEnumMembers() const { @@ -339,7 +339,7 @@ public: return VariableType::IMPORT_EQUALS; } - void SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] util::Hotfix *hotfixHelper = nullptr) override; + void SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] util::PatchFix *patchFixHelper = nullptr) override; Scope *GetScope() { diff --git a/es2panda/compiler/core/compileQueue.cpp b/es2panda/compiler/core/compileQueue.cpp index 42743c71ffc544fab463fdbc4cd191cfc9fb1509..d475dacc81912f07b9bd24913f5c862b167cf89d 100644 --- a/es2panda/compiler/core/compileQueue.cpp +++ b/es2panda/compiler/core/compileQueue.cpp @@ -43,7 +43,7 @@ void CompileFunctionJob::Run() Function::Compile(&pg); FunctionEmitter funcEmitter(&allocator, &pg); - funcEmitter.Generate(context_->HotfixHelper()); + funcEmitter.Generate(context_->PatchFixHelper()); context_->GetEmitter()->AddFunction(&funcEmitter, context_); diff --git a/es2panda/compiler/core/compilerContext.cpp b/es2panda/compiler/core/compilerContext.cpp index c9e1f96468355a8b67af0380b6afebf8679c9cf9..31a7a09c2c23552198d959c02e2d0ea0949a96fb 100644 --- a/es2panda/compiler/core/compilerContext.cpp +++ b/es2panda/compiler/core/compilerContext.cpp @@ -23,10 +23,10 @@ namespace panda::es2panda::compiler { CompilerContext::CompilerContext(binder::Binder *binder, bool isDebug, bool isDebuggerEvaluateExpressionMode, bool isMergeAbc, bool isTypeExtractorEnabled, bool isJsonInputFile, std::string sourceFile, std::string pkgName, util::StringView recordName, - util::Hotfix *hotfixHelper) + util::PatchFix *patchFixHelper) : binder_(binder), isDebug_(isDebug), isDebuggerEvaluateExpressionMode_(isDebuggerEvaluateExpressionMode), isMergeAbc_(isMergeAbc), isTypeExtractorEnabled_(isTypeExtractorEnabled), isJsonInputFile_(isJsonInputFile), - sourceFile_(sourceFile), pkgName_(pkgName), recordName_(recordName), hotfixHelper_(hotfixHelper), + sourceFile_(sourceFile), pkgName_(pkgName), recordName_(recordName), patchFixHelper_(patchFixHelper), emitter_(std::make_unique(this)) { } diff --git a/es2panda/compiler/core/compilerContext.h b/es2panda/compiler/core/compilerContext.h index a6af7ed4b069e8f402798b83740b5a4ad5747039..27118a322fca2212a7a6699764aee3b2371c9249 100644 --- a/es2panda/compiler/core/compilerContext.h +++ b/es2panda/compiler/core/compilerContext.h @@ -21,7 +21,7 @@ #include #include -#include +#include #include #include @@ -44,7 +44,7 @@ class CompilerContext { public: CompilerContext(binder::Binder *binder, bool isDebug, bool isDebuggerEvaluateExpressionMode, bool isMergeAbc, bool isTypeExtractorEnabled, bool isJsonInputFile, std::string sourceFile, - std::string pkgName, util::StringView recordName, util::Hotfix *hotfixHelper); + std::string pkgName, util::StringView recordName, util::PatchFix *patchFixHelper); NO_COPY_SEMANTIC(CompilerContext); NO_MOVE_SEMANTIC(CompilerContext); ~CompilerContext() = default; @@ -100,9 +100,9 @@ public: return pkgName_; } - util::Hotfix *HotfixHelper() const + util::PatchFix *PatchFixHelper() const { - return hotfixHelper_; + return patchFixHelper_; } const util::StringView &RecordName() const @@ -142,7 +142,7 @@ private: std::string sourceFile_; std::string pkgName_; util::StringView recordName_; - util::Hotfix *hotfixHelper_ {nullptr}; + util::PatchFix *patchFixHelper_ {nullptr}; std::unique_ptr emitter_; }; diff --git a/es2panda/compiler/core/compilerImpl.cpp b/es2panda/compiler/core/compilerImpl.cpp index 9d840c2be81c34cff327c65bffe4fedde890f5cf..880a25bf5155cdc016ab910977775c14a0c0d5cf 100644 --- a/es2panda/compiler/core/compilerImpl.cpp +++ b/es2panda/compiler/core/compilerImpl.cpp @@ -42,7 +42,7 @@ panda::pandasm::Program *CompilerImpl::Compile(parser::Program *program, const e bool isTypeExtractorEnabled = ((program->Extension() == ScriptExtension::TS) && options.typeExtractor); CompilerContext context(program->Binder(), options.isDebug, options.isDebuggerEvaluateExpressionMode, options.mergeAbc, isTypeExtractorEnabled, false, debugInfoSourceFile, pkgName, - program->RecordName(), hotfixHelper_); + program->RecordName(), patchFixHelper_); ArenaAllocator localAllocator(SpaceType::SPACE_TYPE_COMPILER, nullptr, true); @@ -76,7 +76,7 @@ panda::pandasm::Program *CompilerImpl::Compile(parser::Program *program, const e std::string(program->RecordName())); } - return context.GetEmitter()->Finalize(options.dumpDebugInfo, hotfixHelper_); + return context.GetEmitter()->Finalize(options.dumpDebugInfo, patchFixHelper_); } void CompilerImpl::DumpAsm(const panda::pandasm::Program *prog) diff --git a/es2panda/compiler/core/compilerImpl.h b/es2panda/compiler/core/compilerImpl.h index 595e9521cf072030242e3eaab3a19fe8539559d9..d9d1e7bda18766263d07d890892e0bfe39b4ffe1 100644 --- a/es2panda/compiler/core/compilerImpl.h +++ b/es2panda/compiler/core/compilerImpl.h @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include @@ -47,15 +47,15 @@ public: const std::string &debugInfoSourceFile, const std::string &pkgName); static void DumpAsm(const panda::pandasm::Program *prog); - void AddHotfixHelper(util::Hotfix *hotfixHelper) + void AddPatchFixHelper(util::PatchFix *patchFixHelper) { - hotfixHelper_ = hotfixHelper; + patchFixHelper_ = patchFixHelper; } private: size_t threadCount_ {0}; CompileFuncQueue *queue_ {nullptr}; - util::Hotfix *hotfixHelper_ {nullptr}; + util::PatchFix *patchFixHelper_ {nullptr}; std::unique_ptr extractor_ {}; }; } // namespace panda::es2panda::compiler diff --git a/es2panda/compiler/core/emitter/emitter.cpp b/es2panda/compiler/core/emitter/emitter.cpp index 1c839d3157d702ddcf1a1bd612f45568ff318e7d..96602d14feadaad4a9766983eb71f0c9590b7bc0 100644 --- a/es2panda/compiler/core/emitter/emitter.cpp +++ b/es2panda/compiler/core/emitter/emitter.cpp @@ -56,7 +56,7 @@ FunctionEmitter::FunctionEmitter(ArenaAllocator *allocator, const PandaGen *pg) func_->return_type = panda::pandasm::Type("any", 0); } -void FunctionEmitter::Generate(util::Hotfix *hotfixHelper) +void FunctionEmitter::Generate(util::PatchFix *patchFixHelper) { GenFunctionKind(); GenIcSize(); @@ -65,8 +65,8 @@ void FunctionEmitter::Generate(util::Hotfix *hotfixHelper) GenSourceFileDebugInfo(); GenFunctionCatchTables(); GenLiteralBuffers(); - if (hotfixHelper != nullptr) { - hotfixHelper->ProcessFunction(pg_, func_, literalBuffers_); + if (patchFixHelper != nullptr) { + patchFixHelper->ProcessFunction(pg_, func_, literalBuffers_); } } @@ -353,8 +353,8 @@ void Emitter::GenJsonContentRecord(const CompilerContext *context) jsonContentField.metadata->SetValue(panda::pandasm::ScalarValue::Create( static_cast(context->SourceFile()))); rec_->field_list.emplace_back(std::move(jsonContentField)); - if (context->HotfixHelper()) { - context->HotfixHelper()->ProcessJsonContentRecord(rec_->name, context->SourceFile()); + if (context->PatchFixHelper()) { + context->PatchFixHelper()->ProcessJsonContentRecord(rec_->name, context->SourceFile()); } } @@ -391,8 +391,8 @@ void Emitter::AddSourceTextModuleRecord(ModuleRecordEmitter *module, CompilerCon static_cast(moduleLiteral))); rec_->field_list.emplace_back(std::move(moduleIdxField)); - if (context->HotfixHelper()) { - context->HotfixHelper()->ProcessModule(rec_->name, module->Buffer()); + if (context->PatchFixHelper()) { + context->PatchFixHelper()->ProcessModule(rec_->name, module->Buffer()); } } else { auto ecmaModuleRecord = panda::pandasm::Record("_ESModuleRecord", LANG_EXT); @@ -406,8 +406,8 @@ void Emitter::AddSourceTextModuleRecord(ModuleRecordEmitter *module, CompilerCon static_cast(moduleLiteral))); ecmaModuleRecord.field_list.emplace_back(std::move(moduleIdxField)); - if (context->HotfixHelper()) { - context->HotfixHelper()->ProcessModule(ecmaModuleRecord.name, module->Buffer()); + if (context->PatchFixHelper()) { + context->PatchFixHelper()->ProcessModule(ecmaModuleRecord.name, module->Buffer()); } prog_->record_table.emplace(ecmaModuleRecord.name, std::move(ecmaModuleRecord)); } @@ -555,7 +555,7 @@ void Emitter::DumpAsm(const panda::pandasm::Program *prog) ss << std::endl; } -panda::pandasm::Program *Emitter::Finalize(bool dumpDebugInfo, util::Hotfix *hotfixHelper) +panda::pandasm::Program *Emitter::Finalize(bool dumpDebugInfo, util::PatchFix *patchFixHelper) { if (dumpDebugInfo) { debuginfo::DebugInfoDumper dumper(prog_); @@ -567,8 +567,8 @@ panda::pandasm::Program *Emitter::Finalize(bool dumpDebugInfo, util::Hotfix *hot rec_ = nullptr; } - if (hotfixHelper) { - hotfixHelper->Finalize(&prog_); + if (patchFixHelper) { + patchFixHelper->Finalize(&prog_); } auto *prog = prog_; diff --git a/es2panda/compiler/core/emitter/emitter.h b/es2panda/compiler/core/emitter/emitter.h index 7964889a278add4def4d40b0bd212635a7f72ffd..9abae284bff354fde0c932c4de149719006db38c 100644 --- a/es2panda/compiler/core/emitter/emitter.h +++ b/es2panda/compiler/core/emitter/emitter.h @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include @@ -74,7 +74,7 @@ public: return literalBuffers_; } - void Generate(util::Hotfix *hotfixHelper); + void Generate(util::PatchFix *patchFixHelper); const ArenaSet &Strings() const; private: @@ -113,7 +113,7 @@ public: static void GenBufferLiterals(ArenaVector>> &literalBuffers, const LiteralBuffer *buff); static void DumpAsm(const panda::pandasm::Program *prog); - panda::pandasm::Program *Finalize(bool dumpDebugInfo, util::Hotfix *hotfixHelper); + panda::pandasm::Program *Finalize(bool dumpDebugInfo, util::PatchFix *patchFixHelper); panda::pandasm::Program *GetProgram() const; void GenJsonContentRecord(const CompilerContext *context); void GenRecordNameInfo() const; diff --git a/es2panda/compiler/core/pandagen.cpp b/es2panda/compiler/core/pandagen.cpp index 62b2a863d171175a8ae09a62d534f36688a415a8..9aea7f5dd24a126b63813ad82b3cc301dba5e221 100644 --- a/es2panda/compiler/core/pandagen.cpp +++ b/es2panda/compiler/core/pandagen.cpp @@ -44,7 +44,7 @@ #include #include #include -#include +#include namespace panda::es2panda::compiler { @@ -1791,8 +1791,8 @@ 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_->HotfixHelper() && context_->HotfixHelper()->IsPatchVar(slot)) { - uint32_t patchSlot = context_->HotfixHelper()->GetPatchLexicalIdx(std::string(name)); + if (context_->PatchFixHelper() && context_->PatchFixHelper()->IsPatchVar(slot)) { + uint32_t patchSlot = context_->PatchFixHelper()->GetPatchLexicalIdx(std::string(name)); ra_.Emit(node, patchSlot); return; } @@ -1829,8 +1829,8 @@ 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_->HotfixHelper() && context_->HotfixHelper()->IsPatchVar(slot)) { - uint32_t patchSlot = context_->HotfixHelper()->GetPatchLexicalIdx(std::string(local->Name())); + if (context_->PatchFixHelper() && context_->PatchFixHelper()->IsPatchVar(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 48335c1ac9beb4f8f5504a1112f0643e5c5999b4..22c6cee6057efb2f3ff716284d09330e37ea6999 100644 --- a/es2panda/es2panda.cpp +++ b/es2panda/es2panda.cpp @@ -48,10 +48,10 @@ Compiler::~Compiler() delete compiler_; } -panda::pandasm::Program *CreateJsonContentProgram(std::string src, std::string rname, util::Hotfix *hotfixHelper) +panda::pandasm::Program *CreateJsonContentProgram(std::string src, std::string rname, util::PatchFix *patchFixHelper) { panda::es2panda::compiler::CompilerContext context(nullptr, false, false, false, false, true, - src, "", util::StringView(rname), hotfixHelper); + src, "", util::StringView(rname), patchFixHelper); context.GetEmitter()->GenRecordNameInfo(); return context.GetEmitter()->Finalize(false, nullptr); } @@ -67,10 +67,10 @@ panda::pandasm::Program *Compiler::Compile(const SourceFile &input, const Compil std::string pkgName(input.pkgName); parser::ScriptKind kind(input.scriptKind); - auto *hotfixHelper = InitHotfixHelper(input, options, symbolTable); + auto *patchFixHelper = InitPatchFixHelper(input, options, symbolTable); if (fname.substr(fname.find_last_of(".") + 1) == "json") { - return CreateJsonContentProgram(src, rname, hotfixHelper); + return CreateJsonContentProgram(src, rname, patchFixHelper); } try { @@ -106,37 +106,38 @@ panda::pandasm::Program *Compiler::Compile(const SourceFile &input, const Compil sourcefile : options.debugInfoSourceFile; auto *prog = compiler_->Compile(&ast, options, debugInfoSourceFile, pkgName); - CleanHotfixHelper(hotfixHelper); + CleanPatchFixHelper(patchFixHelper); return prog; } catch (const class Error &e) { error_ = e; - CleanHotfixHelper(hotfixHelper); + CleanPatchFixHelper(patchFixHelper); return nullptr; } } -util::Hotfix *Compiler::InitHotfixHelper(const SourceFile &input, const CompilerOptions &options, +util::PatchFix *Compiler::InitPatchFixHelper(const SourceFile &input, const CompilerOptions &options, util::SymbolTable *symbolTable) { - bool needDumpSymbolFile = !options.hotfixOptions.dumpSymbolTable.empty(); - bool needGeneratePatch = options.hotfixOptions.generatePatch && !options.hotfixOptions.symbolTable.empty(); - bool isHotReload = options.hotfixOptions.hotReload; - util::Hotfix *hotfixHelper = nullptr; + bool needDumpSymbolFile = !options.patchFixOptions.dumpSymbolTable.empty(); + bool needGeneratePatch = options.patchFixOptions.generatePatch && !options.patchFixOptions.symbolTable.empty(); + bool isHotFix = options.patchFixOptions.hotfix; + bool isHotReload = options.patchFixOptions.hotReload; + util::PatchFix *patchFixHelper = nullptr; if (symbolTable && (needDumpSymbolFile || needGeneratePatch || isHotReload)) { - hotfixHelper = new util::Hotfix(needDumpSymbolFile, needGeneratePatch, isHotReload, + patchFixHelper = new util::PatchFix(needDumpSymbolFile, needGeneratePatch, isHotFix, isHotReload, input.recordName, symbolTable); - parser_->AddHotfixHelper(hotfixHelper); - compiler_->AddHotfixHelper(hotfixHelper); + parser_->AddPatchFixHelper(patchFixHelper); + compiler_->AddPatchFixHelper(patchFixHelper); } - return hotfixHelper; + return patchFixHelper; } -void Compiler::CleanHotfixHelper(const util::Hotfix *hotfixHelper) +void Compiler::CleanPatchFixHelper(const util::PatchFix *patchFixHelper) { - if (hotfixHelper) { - delete hotfixHelper; - hotfixHelper = nullptr; + if (patchFixHelper) { + delete patchFixHelper; + patchFixHelper = nullptr; } } @@ -149,8 +150,8 @@ int Compiler::CompileFiles(CompilerOptions &options, std::map &progsInfo, panda::ArenaAllocator *allocator) { util::SymbolTable *symbolTable = nullptr; - if (!options.hotfixOptions.symbolTable.empty() || !options.hotfixOptions.dumpSymbolTable.empty()) { - symbolTable = new util::SymbolTable(options.hotfixOptions.symbolTable, options.hotfixOptions.dumpSymbolTable); + if (!options.patchFixOptions.symbolTable.empty() || !options.patchFixOptions.dumpSymbolTable.empty()) { + symbolTable = new util::SymbolTable(options.patchFixOptions.symbolTable, options.patchFixOptions.dumpSymbolTable); if (!symbolTable->Initialize()) { std::cerr << "Exits due to hot fix initialize failed!" << std::endl; return 1; diff --git a/es2panda/es2panda.h b/es2panda/es2panda.h index 28e8fbae687b6daa5883bee971e457a8395195f0..19939c1fb86f33e3b104af263a57c5df6b417ff0 100644 --- a/es2panda/es2panda.h +++ b/es2panda/es2panda.h @@ -18,7 +18,7 @@ #include #include -#include +#include #include #include @@ -62,10 +62,11 @@ struct SourceFile { uint32_t hash {0}; }; -struct HotfixOptions { +struct PatchFixOptions { std::string dumpSymbolTable {}; std::string symbolTable {}; bool generatePatch {false}; + bool hotfix {false}; bool hotReload {false}; }; @@ -89,7 +90,7 @@ struct CompilerOptions { std::string output {}; std::string debugInfoSourceFile {}; std::vector sourceFiles; - HotfixOptions hotfixOptions; + PatchFixOptions patchFixOptions; bool bcVersion {false}; bool bcMinVersion {false}; std::unordered_map cacheFiles; @@ -195,9 +196,9 @@ public: } private: - util::Hotfix *InitHotfixHelper(const SourceFile &input, const CompilerOptions &options, + util::PatchFix *InitPatchFixHelper(const SourceFile &input, const CompilerOptions &options, util::SymbolTable *symbolTable); - static void CleanHotfixHelper(const util::Hotfix *hotfixHelper); + static void CleanPatchFixHelper(const util::PatchFix *patchFixHelper); parser::ParserImpl *parser_; compiler::CompilerImpl *compiler_; diff --git a/es2panda/parser/parserImpl.cpp b/es2panda/parser/parserImpl.cpp index 769f9b3ef6e5ba4c0a750a24b361b43d09172c49..55f1b14225261992ebde48f9ab5927883404d618 100644 --- a/es2panda/parser/parserImpl.cpp +++ b/es2panda/parser/parserImpl.cpp @@ -3697,9 +3697,9 @@ parser::SourceTextModuleRecord *ParserImpl::GetSourceTextModuleRecord() return Binder()->Program()->ModuleRecord(); } -void ParserImpl::AddHotfixHelper(util::Hotfix *hotfixHelper) +void ParserImpl::AddPatchFixHelper(util::PatchFix *patchFixHelper) { - program_.AddHotfixHelper(hotfixHelper); + program_.AddPatchFixHelper(patchFixHelper); } bool ParserImpl::IsDtsFile() const diff --git a/es2panda/parser/parserImpl.h b/es2panda/parser/parserImpl.h index a8500290bd753d02a539fbfa526d20d43c1c86af..2b2d0d3e1c091e83582d82bc13dc122720c769a7 100644 --- a/es2panda/parser/parserImpl.h +++ b/es2panda/parser/parserImpl.h @@ -183,7 +183,7 @@ public: ScriptExtension Extension() const; - void AddHotfixHelper(util::Hotfix *hotfixHelper); + void AddPatchFixHelper(util::PatchFix *patchFixHelper); ArenaAllocator *Allocator() const { diff --git a/es2panda/parser/program/program.cpp b/es2panda/parser/program/program.cpp index 33c6b908a91febbe872789a417b944e34bd8c1d4..85ba31f9c79ec569327c32159d7b73740488fb6d 100644 --- a/es2panda/parser/program/program.cpp +++ b/es2panda/parser/program/program.cpp @@ -41,7 +41,7 @@ Program::Program(Program &&other) extension_(other.extension_), lineIndex_(other.lineIndex_), moduleRecord_(other.moduleRecord_), - hotfixHelper_(other.hotfixHelper_), + patchFixHelper_(other.patchFixHelper_), isDtsFile_(other.isDtsFile_) { other.binder_ = nullptr; diff --git a/es2panda/parser/program/program.h b/es2panda/parser/program/program.h index f4cac784c02de43aefdaf8eb64a612c21b4f0115..1ec17485cad3def07fc23cd8fe65dcfe9801c89e 100644 --- a/es2panda/parser/program/program.h +++ b/es2panda/parser/program/program.h @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include "es2panda.h" @@ -135,14 +135,14 @@ public: formatedRecordName_ = util::UString(formatedRecordName, Allocator()); } - void AddHotfixHelper(util::Hotfix *hotfixHelper) + void AddPatchFixHelper(util::PatchFix *patchFixHelper) { - hotfixHelper_ = hotfixHelper; + patchFixHelper_ = patchFixHelper; } - util::Hotfix *HotfixHelper() + util::PatchFix *PatchFixHelper() { - return hotfixHelper_; + return patchFixHelper_; } bool IsDtsFile() const @@ -165,7 +165,7 @@ private: ScriptExtension extension_ {}; lexer::LineIndex lineIndex_ {}; SourceTextModuleRecord *moduleRecord_ {nullptr}; - util::Hotfix *hotfixHelper_ {nullptr}; + util::PatchFix *patchFixHelper_ {nullptr}; bool isDtsFile_ {false}; }; diff --git a/es2panda/test/runner.py b/es2panda/test/runner.py index c2665fe54f381d00a4339a23a53ba665be1ddd20..33286ee2ad0c45aa13d4f9769ecd9a669eed8103 100755 --- a/es2panda/test/runner.py +++ b/es2panda/test/runner.py @@ -153,8 +153,8 @@ def get_args(): parser.add_argument( '--tsc-path', dest='tsc_path', default=None, type=lambda arg: is_directory(parser, arg), help='the path of tsc') - parser.add_argument('--hotfix', dest='hotfix', action='store_true', default=False, - help='run hotfix tests') + parser.add_argument('--patchFix', dest='patchFix', action='store_true', default=False, + help='run patchFix tests') parser.add_argument('--hotreload', dest='hotreload', action='store_true', default=False, help='run hotreload tests') parser.add_argument('--base64', dest='base64', action='store_true', default=False, @@ -487,7 +487,7 @@ class Runner: path_str = test.path err_col = {} if test.error: - err_str = test.error.split('[')[0] if "hotfix" not in test.path else " hotfix throw error failed" + err_str = test.error.split('[')[0] if "patchFix" not in test.path else " patchFix throw error failed" err_col = {"path" : [path_str], "status": ["fail"], "error" : [test.error], "type" : [err_str]} else: err_col = {"path" : [path_str], "status": ["fail"], "error" : ["Segmentation fault"], @@ -1065,7 +1065,7 @@ class PatchTest(Test): gen_base_cmd.extend([os.path.join(self.path, origin_input_file)]) self.log_cmd(gen_base_cmd) - if self.mode == 'hotfix': + if self.mode == 'patchFix': mode_arg = "--generate-patch" elif self.mode == 'hotreload': mode_arg = "--hot-reload" @@ -1132,12 +1132,12 @@ class PatchRunner(Runner): return os.path.basename(src) -class HotfixRunner(PatchRunner): +class PatchFixRunner(PatchRunner): def __init__(self, args): - PatchRunner.__init__(self, args, "Hotfix") - self.test_directory = path.join(self.test_root, "hotfix", "hotfix-throwerror") + PatchRunner.__init__(self, args, "PatchFix") + self.test_directory = path.join(self.test_root, "patchFix", "patchFix-throwerror") self.add_directory() - self.tests += list(map(lambda t: PatchTest(t, "hotfix"), self.tests_in_dirs)) + self.tests += list(map(lambda t: PatchTest(t, "patchFix"), self.tests_in_dirs)) class HotreloadRunner(PatchRunner): @@ -1454,8 +1454,8 @@ def main(): runners.append(runner) - if args.hotfix: - runners.append(HotfixRunner(args)) + if args.patchFix: + runners.append(PatchFixRunner(args)) if args.hotreload: runners.append(HotreloadRunner(args)) diff --git a/es2panda/util/hotfix.cpp b/es2panda/util/patchFix.cpp similarity index 80% rename from es2panda/util/hotfix.cpp rename to es2panda/util/patchFix.cpp index 306572389c79873258cdb5e3d2274a0e8962b299..a4947b7050eff1faacd28bf2bab83d4356523625 100644 --- a/es2panda/util/hotfix.cpp +++ b/es2panda/util/patchFix.cpp @@ -13,7 +13,7 @@ * limitations under the License. */ -#include "hotfix.h" +#include "patchFix.h" #include #include #include @@ -31,7 +31,7 @@ constexpr std::string_view ANONYMOUS_OR_DUPLICATE_FUNCTION_SPECIFIER = "#"; const std::string EXTERNAL_ATTRIBUTE = "external"; const panda::panda_file::SourceLang SRC_LANG = panda::panda_file::SourceLang::ECMASCRIPT; -void Hotfix::ProcessFunction(const compiler::PandaGen *pg, panda::pandasm::Function *func, +void PatchFix::ProcessFunction(const compiler::PandaGen *pg, panda::pandasm::Function *func, LiteralBuffers &literalBuffers) { if (generateSymbolFile_) { @@ -45,7 +45,7 @@ void Hotfix::ProcessFunction(const compiler::PandaGen *pg, panda::pandasm::Funct } } -void Hotfix::ProcessModule(const std::string &recordName, +void PatchFix::ProcessModule(const std::string &recordName, std::vector &moduleBuffer) { if (generateSymbolFile_) { @@ -59,7 +59,7 @@ void Hotfix::ProcessModule(const std::string &recordName, } } -void Hotfix::ProcessJsonContentRecord(const std::string &recordName, const std::string &jsonFileContent) +void PatchFix::ProcessJsonContentRecord(const std::string &recordName, const std::string &jsonFileContent) { if (generateSymbolFile_) { DumpJsonContentRecInfo(recordName, jsonFileContent); @@ -72,7 +72,7 @@ void Hotfix::ProcessJsonContentRecord(const std::string &recordName, const std:: } } -void Hotfix::DumpModuleInfo(const std::string &recordName, +void PatchFix::DumpModuleInfo(const std::string &recordName, std::vector &moduleBuffer) { std::stringstream ss; @@ -82,7 +82,7 @@ void Hotfix::DumpModuleInfo(const std::string &recordName, symbolTable_->WriteSymbolTable(ss.str()); } -void Hotfix::ValidateModuleInfo(const std::string &recordName, +void PatchFix::ValidateModuleInfo(const std::string &recordName, std::vector &moduleBuffer) { auto it = originModuleInfo_->find(recordName); @@ -101,7 +101,7 @@ void Hotfix::ValidateModuleInfo(const std::string &recordName, } } -void Hotfix::DumpJsonContentRecInfo(const std::string &recordName, const std::string &jsonFileContent) +void PatchFix::DumpJsonContentRecInfo(const std::string &recordName, const std::string &jsonFileContent) { std::stringstream ss; ss << recordName << SymbolTable::SECOND_LEVEL_SEPERATOR; @@ -110,7 +110,7 @@ void Hotfix::DumpJsonContentRecInfo(const std::string &recordName, const std::st symbolTable_->WriteSymbolTable(ss.str()); } -void Hotfix::ValidateJsonContentRecInfo(const std::string &recordName, const std::string &jsonFileContent) +void PatchFix::ValidateJsonContentRecInfo(const std::string &recordName, const std::string &jsonFileContent) { auto it = originModuleInfo_->find(recordName); if (it == originModuleInfo_->end()) { @@ -129,19 +129,19 @@ void Hotfix::ValidateJsonContentRecInfo(const std::string &recordName, const std } } -bool Hotfix::IsAnonymousOrDuplicateNameFunction(const std::string &funcName) +bool PatchFix::IsAnonymousOrDuplicateNameFunction(const std::string &funcName) { return funcName.find(ANONYMOUS_OR_DUPLICATE_FUNCTION_SPECIFIER) != std::string::npos; } -int64_t Hotfix::GetLiteralIdxFromStringId(const std::string &stringId) +int64_t PatchFix::GetLiteralIdxFromStringId(const std::string &stringId) { auto recordPrefix = recordName_ + "_"; auto idxStr = stringId.substr(recordPrefix.size()); return std::atoi(idxStr.c_str()); } -std::vector> Hotfix::GenerateFunctionAndClassHash(panda::pandasm::Function *func, +std::vector> PatchFix::GenerateFunctionAndClassHash(panda::pandasm::Function *func, LiteralBuffers &literalBuffers) { std::stringstream ss; @@ -164,13 +164,21 @@ std::vector> Hotfix::GenerateFunctionAndClassHash int64_t bufferIdx = GetLiteralIdxFromStringId(ins.ids[0]); ss << ExpandLiteral(bufferIdx, literalBuffers) << " "; } else if (ins.opcode == panda::pandasm::Opcode::DEFINECLASSWITHBUFFER) { + auto funcInfo = funcDefinedClasses_.find(func->name); + if (funcInfo != funcDefinedClasses_.end()) { + funcInfo->second.push_back(ins.ids[0]); + funcDefinedClasses_.insert({func->name, funcInfo->second}); + } else { + std::vector funcDefinedClasses = {ins.ids[0]}; + funcDefinedClasses_.insert({func->name, funcDefinedClasses}); + } int64_t bufferIdx = GetLiteralIdxFromStringId(ins.ids[1]); std::string literalStr = ExpandLiteral(bufferIdx, literalBuffers); auto classHash = std::hash{}(literalStr); + ss << " "; hashList.push_back(std::pair(ins.ids[0], classHash)); CollectClassMemberFunctions(ins.ids[0], bufferIdx, literalBuffers); } - ss << " "; } ss << "}" << std::endl; @@ -185,7 +193,7 @@ std::vector> Hotfix::GenerateFunctionAndClassHash return hashList; } -std::string Hotfix::ConvertLiteralToString(std::vector &literalBuffer) +std::string PatchFix::ConvertLiteralToString(std::vector &literalBuffer) { std::stringstream ss; int count = 0; @@ -207,7 +215,7 @@ std::string Hotfix::ConvertLiteralToString(std::vector Hotfix::GetLiteralMethods(int64_t bufferIdx, Hotfix::LiteralBuffers &literalBuffers) +std::vector PatchFix::GetLiteralMethods(int64_t bufferIdx, PatchFix::LiteralBuffers &literalBuffers) { std::vector methods; for (auto &litPair : literalBuffers) { @@ -242,15 +250,15 @@ std::vector Hotfix::GetLiteralMethods(int64_t bufferIdx, Hotfix::Li return methods; } -void Hotfix::CollectClassMemberFunctions(const std::string &className, int64_t bufferIdx, - Hotfix::LiteralBuffers &literalBuffers) +void PatchFix::CollectClassMemberFunctions(const std::string &className, int64_t bufferIdx, + PatchFix::LiteralBuffers &literalBuffers) { std::vector classMemberFunctions = GetLiteralMethods(bufferIdx, literalBuffers); classMemberFunctions.push_back(className); classMemberFunctions_.insert({className, classMemberFunctions}); } -bool Hotfix::IsScopeValidToPatchLexical(binder::VariableScope *scope) const +bool PatchFix::IsScopeValidToPatchLexical(binder::VariableScope *scope) const { if (!generatePatch_ && !hotReload_) { return false; @@ -267,14 +275,14 @@ bool Hotfix::IsScopeValidToPatchLexical(binder::VariableScope *scope) const return true; } -void Hotfix::AllocSlotfromPatchEnv(const std::string &variableName) +void PatchFix::AllocSlotfromPatchEnv(const std::string &variableName) { if (!topScopeLexEnvs_.count(variableName)) { topScopeLexEnvs_[variableName] = topScopeIdx_++; } } -uint32_t Hotfix::GetSlotIdFromSymbolTable(const std::string &variableName) +uint32_t PatchFix::GetSlotIdFromSymbolTable(const std::string &variableName) { auto functionIter = originFunctionInfo_->find(funcMain0_); if (functionIter != originFunctionInfo_->end()) { @@ -287,7 +295,7 @@ uint32_t Hotfix::GetSlotIdFromSymbolTable(const std::string &variableName) return UINT32_MAX; } -uint32_t Hotfix::GetPatchLexicalIdx(const std::string &variableName) +uint32_t PatchFix::GetPatchLexicalIdx(const std::string &variableName) { ASSERT(topScopeLexEnvs_.count(variableName)); return topScopeLexEnvs_[variableName]; @@ -308,7 +316,7 @@ bool IsStPatchVarIns(panda::pandasm::Ins &ins) return ins.opcode == panda::pandasm::Opcode::WIDE_STPATCHVAR; } -void Hotfix::CollectFuncDefineIns(panda::pandasm::Function *func) +void PatchFix::CollectFuncDefineIns(panda::pandasm::Function *func) { for (size_t i = 0; i < func->ins.size(); ++i) { if (IsFunctionOrClassDefineIns(func->ins[i])) { @@ -318,7 +326,7 @@ void Hotfix::CollectFuncDefineIns(panda::pandasm::Function *func) } } -void Hotfix::HandleModifiedClasses(panda::pandasm::Program *prog) +void PatchFix::HandleModifiedClasses(panda::pandasm::Program *prog) { for (auto &cls: classMemberFunctions_) { for (auto &func: cls.second) { @@ -339,7 +347,19 @@ void Hotfix::HandleModifiedClasses(panda::pandasm::Program *prog) } } -void Hotfix::AddHeadAndTailInsForPatchFuncMain0(std::vector &ins) +void PatchFix::HandleModifiedDefinedClassFunc(panda::pandasm::Program *prog) +{ + for (auto &funcInfo: funcDefinedClasses_) { + for (auto &definedClass: funcInfo.second) { + if (modifiedClassNames_.count(definedClass) && + prog->function_table.at(funcInfo.first).metadata->IsForeign()) { + prog->function_table.at(funcInfo.first).metadata->RemoveAttribute(EXTERNAL_ATTRIBUTE); + } + } + } +} + +void PatchFix::AddHeadAndTailInsForPatchFuncMain0(std::vector &ins) { panda::pandasm::Ins returnUndefine; returnUndefine.opcode = pandasm::Opcode::RETURNUNDEFINED; @@ -359,14 +379,14 @@ void Hotfix::AddHeadAndTailInsForPatchFuncMain0(std::vector ins.push_back(returnUndefine); } -void Hotfix::AddTailInsForPatchFuncMain1(std::vector &ins) +void PatchFix::AddTailInsForPatchFuncMain1(std::vector &ins) { panda::pandasm::Ins returnUndefined; returnUndefined.opcode = pandasm::Opcode::RETURNUNDEFINED; ins.push_back(returnUndefined); } -void Hotfix::CreateFunctionPatchMain0AndMain1(panda::pandasm::Function &patchFuncMain0, +void PatchFix::CreateFunctionPatchMain0AndMain1(panda::pandasm::Function &patchFuncMain0, panda::pandasm::Function &patchFuncMain1) { const size_t defaultParamCount = 3; @@ -405,7 +425,7 @@ void Hotfix::CreateFunctionPatchMain0AndMain1(panda::pandasm::Function &patchFun patchFuncMain1.return_type = panda::pandasm::Type("any", 0); } -void Hotfix::Finalize(panda::pandasm::Program **prog) +void PatchFix::Finalize(panda::pandasm::Program **prog) { if (!generatePatch_ && !hotReload_) { return; @@ -413,13 +433,16 @@ void Hotfix::Finalize(panda::pandasm::Program **prog) HandleModifiedClasses(*prog); + HandleModifiedDefinedClassFunc(*prog); + if (patchError_) { *prog = nullptr; std::cerr << "[Patch] Found unsupported change in file, will not generate patch!" << std::endl; return; } - if (hotReload_) { + if (!hotfix_) { + // hotReload_ and coldPatch return; } @@ -431,12 +454,12 @@ void Hotfix::Finalize(panda::pandasm::Program **prog) (*prog)->function_table.emplace(patchFuncMain1.name, std::move(patchFuncMain1)); } -bool Hotfix::CompareLexenv(const std::string &funcName, const compiler::PandaGen *pg, +bool PatchFix::CompareLexenv(const std::string &funcName, const compiler::PandaGen *pg, SymbolTable::OriginFunctionInfo &bytecodeInfo) { auto &lexicalVarNameAndTypes = pg->TopScope()->GetLexicalVarNameAndTypes(); auto &lexenv = bytecodeInfo.lexenv; - if (funcName != funcMain0_) { + if (hotfix_ && funcName != funcMain0_) { if (lexenv.size() != lexicalVarNameAndTypes.size()) { std::cerr << "[Patch] Found lexical variable added or removed in " << funcName << ", not supported!" << std::endl; @@ -465,7 +488,7 @@ bool Hotfix::CompareLexenv(const std::string &funcName, const compiler::PandaGen return true; } -bool Hotfix::CompareClassHash(std::vector> &hashList, +bool PatchFix::CompareClassHash(std::vector> &hashList, SymbolTable::OriginFunctionInfo &bytecodeInfo) { auto &classInfo = bytecodeInfo.classHash; @@ -474,13 +497,17 @@ bool Hotfix::CompareClassHash(std::vector> &hashL auto classIter = classInfo.find(className); if (classIter != classInfo.end()) { if (classIter->second != std::to_string(hashList[i].second)) { - if (hotReload_) { + if (!hotfix_ && !hotReload_) { + // cold patch + modifiedClassNames_.insert(className); + continue; + } else if (hotfix_) { + std::cerr << "[Patch] Found class " << hashList[i].first << " changed, not supported!" << std::endl; + } else { std::cerr << "[Patch] Found class " << hashList[i].first << " changed, not supported! If " << hashList[i].first << " is not changed and you are changing UI Component, please only " << "change one Component at a time and make sure the Component is placed at the bottom " << "of the file." << std::endl; - } else { - std::cerr << "[Patch] Found class " << hashList[i].first << " changed, not supported!" << std::endl; } patchError_ = true; return false; @@ -490,7 +517,7 @@ bool Hotfix::CompareClassHash(std::vector> &hashL return true; } -void Hotfix::HandleFunction(const compiler::PandaGen *pg, panda::pandasm::Function *func, +void PatchFix::HandleFunction(const compiler::PandaGen *pg, panda::pandasm::Function *func, LiteralBuffers &literalBuffers) { std::string funcName = func->name; @@ -500,7 +527,7 @@ void Hotfix::HandleFunction(const compiler::PandaGen *pg, panda::pandasm::Functi if (hotReload_) { return; } - if (IsAnonymousOrDuplicateNameFunction(funcName)) { + if (hotfix_ && IsAnonymousOrDuplicateNameFunction(funcName)) { std::cerr << "[Patch] Found new anonymous or duplicate name function " << funcName << " not supported!" << std::endl; patchError_ = true; @@ -517,6 +544,7 @@ void Hotfix::HandleFunction(const compiler::PandaGen *pg, panda::pandasm::Functi } auto hashList = GenerateFunctionAndClassHash(func, literalBuffers); + if (!CompareClassHash(hashList, bytecodeInfo)) { return; } @@ -526,17 +554,26 @@ void Hotfix::HandleFunction(const compiler::PandaGen *pg, panda::pandasm::Functi } auto funcHash = std::to_string(hashList.back().second); - if (funcHash == bytecodeInfo.funcHash || funcName == funcMain0_) { - func->metadata->SetAttribute(EXTERNAL_ATTRIBUTE); + + if (funcName == funcMain0_) { + if (hotfix_) { + func->metadata->SetAttribute(EXTERNAL_ATTRIBUTE); + } else { + patchFuncNames_.insert(funcName); + } } else { - patchFuncNames_.insert(funcName); + if (funcHash == bytecodeInfo.funcHash) { + func->metadata->SetAttribute(EXTERNAL_ATTRIBUTE); + } else { + patchFuncNames_.insert(funcName); + } } CollectFuncDefineIns(func); } -void Hotfix::DumpFunctionInfo(const compiler::PandaGen *pg, panda::pandasm::Function *func, - Hotfix::LiteralBuffers &literalBuffers) +void PatchFix::DumpFunctionInfo(const compiler::PandaGen *pg, panda::pandasm::Function *func, + PatchFix::LiteralBuffers &literalBuffers) { std::stringstream ss; @@ -563,7 +600,7 @@ void Hotfix::DumpFunctionInfo(const compiler::PandaGen *pg, panda::pandasm::Func symbolTable_->WriteSymbolTable(ss.str()); } -bool Hotfix::IsPatchVar(uint32_t slot) +bool PatchFix::IsPatchVar(uint32_t slot) { return slot == UINT32_MAX; } diff --git a/es2panda/util/hotfix.h b/es2panda/util/patchFix.h similarity index 91% rename from es2panda/util/hotfix.h rename to es2panda/util/patchFix.h index 16436403b18e2a83296ae8859d190edab3019b66..4528beef2ca9ef81b4b33ae6a4daac1d0c4c94df 100644 --- a/es2panda/util/hotfix.h +++ b/es2panda/util/patchFix.h @@ -34,13 +34,14 @@ class PandaGen; } // namespace panda::es2panda::compiler namespace panda::es2panda::util { -class Hotfix { +class PatchFix { using LiteralBuffers = ArenaVector>>; public: - Hotfix(bool generateSymbolFile, bool generatePatch, bool hotReload, const std::string &recordName, + PatchFix(bool generateSymbolFile, bool generatePatch, bool hotfix, bool hotReload, const std::string &recordName, util::SymbolTable *symbolTable) - : generateSymbolFile_(generateSymbolFile), generatePatch_(generatePatch), hotReload_(hotReload), + : generateSymbolFile_(generateSymbolFile), generatePatch_(generatePatch), hotfix_(hotfix), + hotReload_(hotReload), recordName_(recordName), symbolTable_(symbolTable), allocator_(SpaceType::SPACE_TYPE_COMPILER, nullptr, true), @@ -49,7 +50,8 @@ public: newFuncNames_(allocator_.Adapter()), funcDefineIns_(allocator_.Adapter()), modifiedClassNames_(allocator_.Adapter()), - classMemberFunctions_(allocator_.Adapter()) { + classMemberFunctions_(allocator_.Adapter()), + funcDefinedClasses_(allocator_.Adapter()) { originFunctionInfo_ = symbolTable_->GetOriginFunctionInfo(); originModuleInfo_ = symbolTable_->GetOriginModuleInfo(); patchMain0_ = recordName_ + ".patch_main_0"; @@ -93,6 +95,7 @@ private: void CollectClassMemberFunctions(const std::string &className, int64_t bufferIdx, LiteralBuffers &literalBuffers); std::vector GetLiteralMethods(int64_t bufferIdx, LiteralBuffers &literalBuffers); void HandleModifiedClasses(panda::pandasm::Program *prog); + void HandleModifiedDefinedClassFunc(panda::pandasm::Program *prog); int64_t GetLiteralIdxFromStringId(const std::string &stringId); std::mutex m_; @@ -100,6 +103,7 @@ private: bool patchError_ {false}; bool generateSymbolFile_ {false}; bool generatePatch_ {false}; + bool hotfix_ {false}; bool hotReload_ {false}; std::string recordName_; std::string funcMain0_; @@ -116,7 +120,8 @@ private: ArenaVector funcDefineIns_; ArenaSet modifiedClassNames_; ArenaUnorderedMap> classMemberFunctions_; + ArenaUnorderedMap> funcDefinedClasses_; }; } // namespace panda::es2panda::util -#endif // ES2PANDA_UTIL_HOTFIX_H +#endif // ES2PANDA_UTIL_PATCHFIX_H