From 337fe6cd7e8a8000b7ad8b8a1eb18f1fd64dcf66 Mon Sep 17 00:00:00 2001 From: gavin1012_hw Date: Tue, 21 Feb 2023 18:29:26 +0800 Subject: [PATCH 1/2] Support hotfix for importing json Issue: I69D2R Signed-off-by: gavin1012_hw --- es2panda/compiler/core/compilerContext.cpp | 5 +-- es2panda/compiler/core/compilerContext.h | 11 ++---- es2panda/compiler/core/compilerImpl.cpp | 6 +--- es2panda/compiler/core/emitter/emitter.cpp | 3 ++ es2panda/es2panda.cpp | 10 +++--- es2panda/util/hotfix.cpp | 41 ++++++++++++++++++++++ es2panda/util/hotfix.h | 3 ++ 7 files changed, 59 insertions(+), 20 deletions(-) diff --git a/es2panda/compiler/core/compilerContext.cpp b/es2panda/compiler/core/compilerContext.cpp index 32d6a6e3d8..c9e1f96468 100644 --- a/es2panda/compiler/core/compilerContext.cpp +++ b/es2panda/compiler/core/compilerContext.cpp @@ -22,10 +22,11 @@ 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) + std::string sourceFile, std::string pkgName, util::StringView recordName, + util::Hotfix *hotfixHelper) : binder_(binder), isDebug_(isDebug), isDebuggerEvaluateExpressionMode_(isDebuggerEvaluateExpressionMode), isMergeAbc_(isMergeAbc), isTypeExtractorEnabled_(isTypeExtractorEnabled), isJsonInputFile_(isJsonInputFile), - sourceFile_(sourceFile), pkgName_(pkgName), recordName_(recordName), + sourceFile_(sourceFile), pkgName_(pkgName), recordName_(recordName), hotfixHelper_(hotfixHelper), emitter_(std::make_unique(this)) { } diff --git a/es2panda/compiler/core/compilerContext.h b/es2panda/compiler/core/compilerContext.h index 2cd7829f8d..a6af7ed4b0 100644 --- a/es2panda/compiler/core/compilerContext.h +++ b/es2panda/compiler/core/compilerContext.h @@ -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); + std::string pkgName, util::StringView recordName, util::Hotfix *hotfixHelper); NO_COPY_SEMANTIC(CompilerContext); NO_MOVE_SEMANTIC(CompilerContext); ~CompilerContext() = default; @@ -100,12 +100,7 @@ public: return pkgName_; } - void AddHotfixHelper(util::Hotfix *hotfixHelper) - { - hotfixHelper_ = hotfixHelper; - } - - util::Hotfix *HotfixHelper() + util::Hotfix *HotfixHelper() const { return hotfixHelper_; } @@ -147,8 +142,8 @@ private: std::string sourceFile_; std::string pkgName_; util::StringView recordName_; - std::unique_ptr emitter_; util::Hotfix *hotfixHelper_ {nullptr}; + std::unique_ptr emitter_; }; } // namespace panda::es2panda::compiler diff --git a/es2panda/compiler/core/compilerImpl.cpp b/es2panda/compiler/core/compilerImpl.cpp index 4245749bfa..fa66ae6961 100644 --- a/es2panda/compiler/core/compilerImpl.cpp +++ b/es2panda/compiler/core/compilerImpl.cpp @@ -41,11 +41,7 @@ panda::pandasm::Program *CompilerImpl::Compile(parser::Program *program, const e { CompilerContext context(program->Binder(), options.isDebug, options.isDebuggerEvaluateExpressionMode, options.mergeAbc, options.typeExtractor, false, debugInfoSourceFile, pkgName, - program->RecordName()); - - if (hotfixHelper_ != nullptr) { - context.AddHotfixHelper(hotfixHelper_); - } + program->RecordName(), hotfixHelper_); ArenaAllocator localAllocator(SpaceType::SPACE_TYPE_COMPILER, nullptr, true); diff --git a/es2panda/compiler/core/emitter/emitter.cpp b/es2panda/compiler/core/emitter/emitter.cpp index b4185b1f7a..d3229edb2c 100644 --- a/es2panda/compiler/core/emitter/emitter.cpp +++ b/es2panda/compiler/core/emitter/emitter.cpp @@ -349,6 +349,9 @@ 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()); + } } void Emitter::AddFunction(FunctionEmitter *func, CompilerContext *context) diff --git a/es2panda/es2panda.cpp b/es2panda/es2panda.cpp index 48a97b78bc..e823f2e393 100644 --- a/es2panda/es2panda.cpp +++ b/es2panda/es2panda.cpp @@ -51,10 +51,10 @@ Compiler::~Compiler() delete compiler_; } -panda::pandasm::Program *CreateJsonContentProgram(std::string src, std::string rname) +panda::pandasm::Program *CreateJsonContentProgram(std::string src, std::string rname, util::Hotfix *hotfixHelper) { panda::es2panda::compiler::CompilerContext context(nullptr, false, false, false, false, true, - src, "", util::StringView(rname)); + src, "", util::StringView(rname), hotfixHelper); return context.GetEmitter()->Finalize(false, nullptr); } @@ -69,12 +69,12 @@ 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); + if (fname.substr(fname.find_last_of(".") + 1) == "json") { - return CreateJsonContentProgram(src, rname); + return CreateJsonContentProgram(src, rname, hotfixHelper); } - auto *hotfixHelper = InitHotfixHelper(input, options, symbolTable); - try { auto ast = parser_->Parse(fname, src, rname, kind); ast.Binder()->SetProgram(&ast); diff --git a/es2panda/util/hotfix.cpp b/es2panda/util/hotfix.cpp index b7aefc3c1d..090eb36eaa 100644 --- a/es2panda/util/hotfix.cpp +++ b/es2panda/util/hotfix.cpp @@ -59,6 +59,19 @@ void Hotfix::ProcessModule(const std::string &recordName, } } +void Hotfix::ProcessJsonContentRecord(const std::string &recordName, const std::string &jsonFileContent) +{ + if (generateSymbolFile_) { + DumpJsonContentRecInfo(recordName, jsonFileContent); + return; + } + + if (generatePatch_) { + ValidateJsonContentRecInfo(recordName, jsonFileContent); + return; + } +} + void Hotfix::DumpModuleInfo(const std::string &recordName, std::vector &moduleBuffer) { @@ -88,6 +101,34 @@ void Hotfix::ValidateModuleInfo(const std::string &recordName, } } +void Hotfix::DumpJsonContentRecInfo(const std::string &recordName, const std::string &jsonFileContent) +{ + std::stringstream ss; + ss << recordName << SymbolTable::SECOND_LEVEL_SEPERATOR; + auto hash = std::hash{}(jsonFileContent); + ss << hash << std::endl; + symbolTable_->WriteSymbolTable(ss.str()); +} + +void Hotfix::ValidateJsonContentRecInfo(const std::string &recordName, const std::string &jsonFileContent) +{ + auto it = originModuleInfo_->find(recordName); + if (it == originModuleInfo_->end()) { + std::cerr << "[Patch] Found new import/require json file expression in " << recordName + << ", not supported!" << std::endl; + patchError_ = true; + return; + } + + auto hash = std::hash{}(jsonFileContent); + if (std::to_string(hash) != it->second) { + std::cerr << "[Patch] Found imported/required json file content changed in " << recordName + << ", not supported!" << std::endl; + patchError_ = true; + return; + } +} + bool Hotfix::IsAnonymousOrDuplicateNameFunction(const std::string &funcName) { return funcName.find(ANONYMOUS_OR_DUPLICATE_FUNCTION_SPECIFIER) != std::string::npos; diff --git a/es2panda/util/hotfix.h b/es2panda/util/hotfix.h index 36e06ddb51..06001d60ca 100644 --- a/es2panda/util/hotfix.h +++ b/es2panda/util/hotfix.h @@ -63,6 +63,7 @@ public: bool IsPatchVar(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); private: void DumpFunctionInfo(const compiler::PandaGen *pg, panda::pandasm::Function *func, LiteralBuffers &literalBuffers); @@ -72,6 +73,8 @@ private: void DumpModuleInfo(const std::string &recordName, std::vector &moduleBuffer); void ValidateModuleInfo(const std::string &recordName, std::vector &moduleBuffer); + void DumpJsonContentRecInfo(const std::string &recordName, const std::string &jsonFileContent); + void ValidateJsonContentRecInfo(const std::string &recordName, const std::string &jsonFileContent); std::string ExpandLiteral(int64_t bufferIdx, LiteralBuffers &literalBuffers); std::string ConvertLiteralToString(std::vector &literalBuffer); -- Gitee From 8df88f149b11cd9ffa76c8cbbff4541f67b6e387 Mon Sep 17 00:00:00 2001 From: gavin1012_hw Date: Tue, 21 Feb 2023 18:31:29 +0800 Subject: [PATCH 2/2] Enhance reload ability for IDE compiling Issue: I6GP7S Signed-off-by: gavin1012_hw --- es2panda/aot/options.cpp | 5 ++++- es2panda/es2panda.cpp | 6 ++++-- es2panda/es2panda.h | 1 + es2panda/util/hotfix.cpp | 24 +++++++++++++++++------- es2panda/util/hotfix.h | 7 +++++-- 5 files changed, 31 insertions(+), 12 deletions(-) diff --git a/es2panda/aot/options.cpp b/es2panda/aot/options.cpp index e8d2e3ead6..82645cc4f5 100644 --- a/es2panda/aot/options.cpp +++ b/es2panda/aot/options.cpp @@ -164,10 +164,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 + // hotfix && 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 opHotReload("hot-reload", false, "compile as hot-reload mode"); // version panda::PandArg bcVersion("bc-version", false, "Print ark bytecode version"); @@ -209,6 +210,7 @@ bool Options::Parse(int argc, const char **argv) argparser_->Add(&opDumpSymbolTable); argparser_->Add(&opInputSymbolTable); argparser_->Add(&opGeneratePatch); + argparser_->Add(&opHotReload); argparser_->Add(&bcVersion); argparser_->Add(&bcMinVersion); @@ -388,6 +390,7 @@ bool Options::Parse(int argc, const char **argv) compilerOptions_.hotfixOptions.dumpSymbolTable = opDumpSymbolTable.GetValue(); compilerOptions_.hotfixOptions.symbolTable = opInputSymbolTable.GetValue(); compilerOptions_.hotfixOptions.generatePatch = opGeneratePatch.GetValue(); + compilerOptions_.hotfixOptions.hotReload = opHotReload.GetValue(); return true; } diff --git a/es2panda/es2panda.cpp b/es2panda/es2panda.cpp index e823f2e393..f593468d9c 100644 --- a/es2panda/es2panda.cpp +++ b/es2panda/es2panda.cpp @@ -117,9 +117,11 @@ util::Hotfix *Compiler::InitHotfixHelper(const SourceFile &input, const Compiler { bool needDumpSymbolFile = !options.hotfixOptions.dumpSymbolTable.empty(); bool needGeneratePatch = options.hotfixOptions.generatePatch && !options.hotfixOptions.symbolTable.empty(); + bool isHotReload = options.hotfixOptions.hotReload; util::Hotfix *hotfixHelper = nullptr; - if (symbolTable && (needDumpSymbolFile || needGeneratePatch)) { - hotfixHelper = new util::Hotfix(needDumpSymbolFile, needGeneratePatch, input.recordName, symbolTable); + if (symbolTable && (needDumpSymbolFile || needGeneratePatch || isHotReload)) { + hotfixHelper = new util::Hotfix(needDumpSymbolFile, needGeneratePatch, isHotReload, + input.recordName, symbolTable); parser_->AddHotfixHelper(hotfixHelper); compiler_->AddHotfixHelper(hotfixHelper); } diff --git a/es2panda/es2panda.h b/es2panda/es2panda.h index efe53ae44d..d4d201855e 100644 --- a/es2panda/es2panda.h +++ b/es2panda/es2panda.h @@ -65,6 +65,7 @@ struct HotfixOptions { std::string dumpSymbolTable {}; std::string symbolTable {}; bool generatePatch {false}; + bool hotReload {false}; }; struct CompilerOptions { diff --git a/es2panda/util/hotfix.cpp b/es2panda/util/hotfix.cpp index 090eb36eaa..ae0b0fc036 100644 --- a/es2panda/util/hotfix.cpp +++ b/es2panda/util/hotfix.cpp @@ -39,7 +39,7 @@ void Hotfix::ProcessFunction(const compiler::PandaGen *pg, panda::pandasm::Funct return; } - if (generatePatch_) { + if (generatePatch_ || hotReload_) { HandleFunction(pg, func, literalBuffers); return; } @@ -53,7 +53,7 @@ void Hotfix::ProcessModule(const std::string &recordName, return; } - if (generatePatch_) { + if (generatePatch_ || hotReload_) { ValidateModuleInfo(recordName, moduleBuffer); return; } @@ -66,7 +66,7 @@ void Hotfix::ProcessJsonContentRecord(const std::string &recordName, const std:: return; } - if (generatePatch_) { + if (generatePatch_ || hotReload_) { ValidateJsonContentRecInfo(recordName, jsonFileContent); return; } @@ -252,7 +252,7 @@ void Hotfix::CollectClassMemberFunctions(const std::string &className, int64_t b bool Hotfix::IsScopeValidToPatchLexical(binder::VariableScope *scope) const { - if (!generatePatch_) { + if (!generatePatch_ && !hotReload_) { return false; } @@ -398,7 +398,7 @@ void Hotfix::CreateFunctionPatchMain0AndMain1(panda::pandasm::Function &patchFun void Hotfix::Finalize(panda::pandasm::Program **prog) { - if (!generatePatch_) { + if (!generatePatch_ && !hotReload_) { return; } @@ -410,6 +410,10 @@ void Hotfix::Finalize(panda::pandasm::Program **prog) return; } + if (hotReload_) { + return; + } + panda::pandasm::Function patchFuncMain0(patchMain0_, SRC_LANG); panda::pandasm::Function patchFuncMain1(patchMain1_, SRC_LANG); CreateFunctionPatchMain0AndMain1(patchFuncMain0, patchFuncMain1); @@ -433,14 +437,16 @@ bool Hotfix::CompareLexenv(const std::string &funcName, const compiler::PandaGen auto varName = std::string(variable.second.first); auto lexenvIter = lexenv.find(varName); if (lexenvIter == lexenv.end()) { - std::cerr << "[Patch] Found new lex env added, not supported!" << std::endl; + std::cerr << "[Patch] Found new lex env added in function " << funcName << ", not supported!" + << std::endl; patchError_ = true; return false; } auto &lexInfo = lexenvIter->second; if (variable.first != lexInfo.first || variable.second.second != lexInfo.second) { - std::cerr << "[Patch] Found new lex env changed(slot or type), not supported!" << std::endl; + std::cerr << "[Patch] Found new lex env changed(slot or type) in function " << funcName + << ", not supported!" << std::endl; patchError_ = true; return false; } @@ -494,6 +500,10 @@ void Hotfix::HandleFunction(const compiler::PandaGen *pg, panda::pandasm::Functi return; } + if (hotReload_) { + return; + } + auto funcHash = std::to_string(hashList.back().second); if (funcHash == bytecodeInfo.funcHash || funcName == funcMain0_) { func->metadata->SetAttribute(EXTERNAL_ATTRIBUTE); diff --git a/es2panda/util/hotfix.h b/es2panda/util/hotfix.h index 06001d60ca..0a76368a3d 100644 --- a/es2panda/util/hotfix.h +++ b/es2panda/util/hotfix.h @@ -38,8 +38,10 @@ class Hotfix { using LiteralBuffers = ArenaVector>>; public: - Hotfix(bool generateSymbolFile, bool generatePatch, const std::string &recordName, util::SymbolTable *symbolTable) - : generateSymbolFile_(generateSymbolFile), generatePatch_(generatePatch), recordName_(recordName), + Hotfix(bool generateSymbolFile, bool generatePatch, bool hotReload, const std::string &recordName, + util::SymbolTable *symbolTable) + : generateSymbolFile_(generateSymbolFile), generatePatch_(generatePatch), hotReload_(hotReload), + recordName_(recordName), symbolTable_(symbolTable), allocator_(SpaceType::SPACE_TYPE_COMPILER, nullptr, true), topScopeLexEnvs_(allocator_.Adapter()), @@ -97,6 +99,7 @@ private: bool patchError_ {false}; bool generateSymbolFile_ {false}; bool generatePatch_ {false}; + bool hotReload_ {false}; std::string recordName_; std::string funcMain0_; std::string patchMain0_; // stores newly added function define ins, runtime will execute -- Gitee