diff --git a/OAT.xml b/OAT.xml index 4efd6e9cf074a78838fd6ee5b40f42db6156fafe..4b367e99e643623db481d37410d810620a587119 100644 --- a/OAT.xml +++ b/OAT.xml @@ -57,6 +57,9 @@ Note:If the text contains special characters, please escape them according to th + + + diff --git a/README.md b/README.md index 0c894ee386418d794e8dcaa5f4dc1cf3706b01a0..4815374f4443f6407b2103ddd5f3b205f118921a 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ ## Introduction -ets_frontend is a front-end tool in the ARK Runtime Subsystem. It converts JavaScript(JS) files into ARK bytecode files. +ets_frontend is a front-end tool in the ARK Runtime Subsystem. Combined with the ace-ets2bundle component, it supports converting ETS files into ARK bytecode files. For more information, see: [ARK Runtime Subsystem](https://gitee.com/openharmony/docs/blob/master/en/readme/ARK-Runtime-Subsystem.md). diff --git a/README_zh.md b/README_zh.md index 5966da79727f8d7b1b67dfbaa51b2c8f541e4953..7f78b6595b327e099a2bdcdb438fbda2fa454ba1 100644 --- a/README_zh.md +++ b/README_zh.md @@ -9,7 +9,7 @@ ## 简介 -ets_frontend组件是方舟运行时子系统的前端工具,支持将JavaScript文件转换为方舟字节码文件。 +ets_frontend组件是方舟运行时子系统的前端工具,结合ace-ets2bundle组件,支持将ets文件转换为方舟字节码文件。 更多信息请参考:[方舟运行时子系统](https://gitee.com/openharmony/docs/blob/master/zh-cn/readme/ARK-Runtime-Subsystem-zh.md) diff --git a/es2panda/BUILD.gn b/es2panda/BUILD.gn index 17dff9d9cdd6d0bdd9092612e130d56cb8686b94..ed23cba1148da0c5fc285dec613bf4caf588c6ff 100644 --- a/es2panda/BUILD.gn +++ b/es2panda/BUILD.gn @@ -29,6 +29,7 @@ es2panda_src = [ "compiler/base/lexenv.cpp", "compiler/base/literals.cpp", "compiler/base/lreference.cpp", + "compiler/base/optionalChain.cpp", "compiler/core/compileQueue.cpp", "compiler/core/compilerContext.cpp", "compiler/core/compilerImpl.cpp", @@ -157,13 +158,16 @@ es2panda_src = [ "ir/ts/tsNullKeyword.cpp", "ir/ts/tsNumberKeyword.cpp", "ir/ts/tsObjectKeyword.cpp", + "ir/ts/tsOptionalType.cpp", "ir/ts/tsParameterProperty.cpp", "ir/ts/tsParenthesizedType.cpp", "ir/ts/tsPrivateIdentifier.cpp", "ir/ts/tsPropertySignature.cpp", "ir/ts/tsQualifiedName.cpp", + "ir/ts/tsRestType.cpp", "ir/ts/tsSignatureDeclaration.cpp", "ir/ts/tsStringKeyword.cpp", + "ir/ts/tsSymbolKeyword.cpp", "ir/ts/tsTemplateLiteralType.cpp", "ir/ts/tsThisType.cpp", "ir/ts/tsTupleType.cpp", @@ -227,6 +231,7 @@ es2panda_src = [ "typescript/types/signature.cpp", "typescript/types/stringLiteralType.cpp", "typescript/types/stringType.cpp", + "typescript/types/symbolType.cpp", "typescript/types/tupleType.cpp", "typescript/types/type.cpp", "typescript/types/typeParameter.cpp", @@ -531,5 +536,6 @@ group("es2panda_build_win") { group("es2abc_tests") { deps = [ "./test:es2abc_parser_tests" ] + deps += [ "./test:es2abc_parser_tsc_tests" ] deps += [ "./test:es2abc_compiler_tests" ] } diff --git a/es2panda/CMakeLists.txt b/es2panda/CMakeLists.txt index 9a213084ed639501358bb18e51bac2756085c22f..80e619467f5f4ab45c16b5e7a51456022fad7a14 100644 --- a/es2panda/CMakeLists.txt +++ b/es2panda/CMakeLists.txt @@ -206,13 +206,16 @@ set(ES2PANDA_LIB_SRC ir/ts/tsNullKeyword.cpp ir/ts/tsNumberKeyword.cpp ir/ts/tsObjectKeyword.cpp + ir/ts/tsOptionalType.cpp ir/ts/tsParameterProperty.cpp ir/ts/tsParenthesizedType.cpp ir/ts/tsPrivateIdentifier.cpp ir/ts/tsPropertySignature.cpp ir/ts/tsQualifiedName.cpp + ir/ts/tsRestType.cpp ir/ts/tsSignatureDeclaration.cpp ir/ts/tsStringKeyword.cpp + ir/ts/tsSymbolKeyword.cpp ir/ts/tsTemplateLiteralType.cpp ir/ts/tsThisType.cpp ir/ts/tsTupleType.cpp @@ -274,6 +277,7 @@ set(ES2PANDA_LIB_SRC typescript/types/signature.cpp typescript/types/stringLiteralType.cpp typescript/types/stringType.cpp + typescript/types/symbolType.cpp typescript/types/tupleType.cpp typescript/types/type.cpp typescript/types/typeParameter.cpp diff --git a/es2panda/aot/main.cpp b/es2panda/aot/main.cpp index 2da57c1bb0edd3ccb5ad60058ec827725194fae1..6b0f618d48360e24550ba4bfe0b5790057e17d44 100644 --- a/es2panda/aot/main.cpp +++ b/es2panda/aot/main.cpp @@ -141,6 +141,14 @@ int Run(int argc, const char **argv) return 1; } + if (options->CompilerOptions().bcVersion || options->CompilerOptions().bcMinVersion) { + std::string version = options->CompilerOptions().bcVersion ? + panda::panda_file::GetVersion(panda::panda_file::version) : + panda::panda_file::GetVersion(panda::panda_file::minVersion); + std::cout << version << std::endl; + return 0; + } + std::map programsInfo; size_t expectedProgsCount = options->CompilerOptions().sourceFiles.size(); panda::ArenaAllocator allocator(panda::SpaceType::SPACE_TYPE_COMPILER, nullptr, true); diff --git a/es2panda/aot/options.cpp b/es2panda/aot/options.cpp index 7d56cfb73cda5854536aa510be4af5dee0ff57da..eb03d55c07e4bd47d52bf59e7e463169dbb2dac9 100644 --- a/es2panda/aot/options.cpp +++ b/es2panda/aot/options.cpp @@ -71,7 +71,7 @@ bool Options::CollectInputFilesFromFileList(const std::string &input) return false; } - constexpr size_t ITEM_COUNT = 3; + constexpr size_t ITEM_COUNT = 4; while (std::getline(ifs, line)) { const std::string seperator = ";"; std::vector itemList = GetStringItems(line, seperator); @@ -79,6 +79,7 @@ bool Options::CollectInputFilesFromFileList(const std::string &input) std::cerr << "Failed to parse input file" << std::endl; return false; } + // itemList: [filePath, recordName, moduleKind, sourceFile] std::string fileName = itemList[0]; std::string recordName = FormatRecordName(itemList[1]); parser::ScriptKind scriptKind; @@ -91,6 +92,7 @@ bool Options::CollectInputFilesFromFileList(const std::string &input) } es2panda::SourceFile src(fileName, recordName, scriptKind); + src.sourcefile = itemList[3]; sourceFiles_.push_back(src); } return true; @@ -158,6 +160,10 @@ bool Options::Parse(int argc, const char **argv) panda::PandArg opInputSymbolTable("input-symbol-table", "", "input symbol table file"); panda::PandArg opGeneratePatch("generate-patch", false, "generate patch abc"); + // version + panda::PandArg bcVersion("bc-version", false, "Print ark bytecode version"); + panda::PandArg bcMinVersion("bc-min-version", false, "Print ark bytecode minimum supported version"); + // tail arguments panda::PandArg inputFile("input", "", "input file"); @@ -193,12 +199,22 @@ bool Options::Parse(int argc, const char **argv) argparser_->Add(&opInputSymbolTable); argparser_->Add(&opGeneratePatch); + argparser_->Add(&bcVersion); + argparser_->Add(&bcMinVersion); + argparser_->PushBackTail(&inputFile); argparser_->EnableTail(); argparser_->EnableRemainder(); - if (!argparser_->Parse(argc, argv) || opHelp.GetValue() || (inputFile.GetValue().empty() - && base64Input.GetValue().empty())) { + bool parseStatus = argparser_->Parse(argc, argv); + + if (parseStatus && (bcVersion.GetValue() || bcMinVersion.GetValue())) { + compilerOptions_.bcVersion = bcVersion.GetValue(); + compilerOptions_.bcMinVersion = bcMinVersion.GetValue(); + return true; + } + + if (!parseStatus || opHelp.GetValue() || (inputFile.GetValue().empty() && base64Input.GetValue().empty())) { std::stringstream ss; ss << argparser_->GetErrorString() << std::endl; diff --git a/es2panda/binder/binder.cpp b/es2panda/binder/binder.cpp index 43a98efbaadad7c669278604df5e3d24fc8176da..a094a339ee453509c84826ba16be5d8415e58c52 100644 --- a/es2panda/binder/binder.cpp +++ b/es2panda/binder/binder.cpp @@ -93,6 +93,12 @@ void Binder::ThrowUndeclaredExport(const lexer::SourcePosition &pos, const util: throw Error(ErrorType::SYNTAX, ss.str(), loc.line, loc.col); } +void Binder::AssignIndexToModuleVariable() +{ + ASSERT(program_->ModuleRecord()); + program_->ModuleRecord()->AssignIndexToModuleVariable(topScope_->AsModuleScope()); +} + void Binder::IdentifierAnalysis() { ASSERT(program_->Ast()); @@ -101,6 +107,9 @@ void Binder::IdentifierAnalysis() BuildFunction(topScope_, MAIN_FUNC_NAME); ResolveReferences(program_->Ast()); AddMandatoryParams(); + if (topScope_->IsModuleScope()) { + AssignIndexToModuleVariable(); + } } void Binder::ValidateExportDecl(const ir::ExportNamedDeclaration *exportDecl) diff --git a/es2panda/binder/binder.h b/es2panda/binder/binder.h index 7f07e686e203f76e8e12131625a62b5037b58526..e9213c472e5ba71165c7711659bbb279ff672a93 100644 --- a/es2panda/binder/binder.h +++ b/es2panda/binder/binder.h @@ -161,6 +161,7 @@ private: } void AddMandatoryParams(); + void AssignIndexToModuleVariable(); void BuildFunction(FunctionScope *funcScope, util::StringView name); void BuildScriptFunction(Scope *outerScope, const ir::ScriptFunction *scriptFunc); void BuildClassDefinition(ir::ClassDefinition *classDef); diff --git a/es2panda/binder/scope.cpp b/es2panda/binder/scope.cpp index 21649a4b8c95046eb94d3c3392e067af5c7bd9fc..634676482a8d63ea7f5b39091cba8c71b4bab17c 100644 --- a/es2panda/binder/scope.cpp +++ b/es2panda/binder/scope.cpp @@ -358,6 +358,14 @@ void ModuleScope::ConvertLocalVariableToModuleVariable(ArenaAllocator *allocator } } +void ModuleScope::AssignIndexToModuleVariable(util::StringView name, uint32_t index) +{ + auto *moduleVar = FindLocal(name); + ASSERT(moduleVar != nullptr); + ASSERT(moduleVar->IsModuleVariable()); + moduleVar->AsModuleVariable()->AssignIndex(index); +} + bool ModuleScope::AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, [[maybe_unused]] ScriptExtension extension) { diff --git a/es2panda/binder/scope.h b/es2panda/binder/scope.h index ad0783e33bf004ab87618cc4b0b3cc8fc50a2113..94b3791028e56c0f3558af5cb6b36aebd20cc862 100644 --- a/es2panda/binder/scope.h +++ b/es2panda/binder/scope.h @@ -599,6 +599,8 @@ public: return ScopeType::MODULE; } + void AssignIndexToModuleVariable(util::StringView name, uint32_t index); + void ConvertLocalVariableToModuleVariable(ArenaAllocator *allocator, util::StringView localName); bool AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, diff --git a/es2panda/binder/variable.h b/es2panda/binder/variable.h index 80086ef9f65b1926f1b65501ea19a41d1cb0c504..a17b88885a19d065ed153e5c86eeee397dcdf73b 100644 --- a/es2panda/binder/variable.h +++ b/es2panda/binder/variable.h @@ -184,6 +184,19 @@ public: } void SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] util::Hotfix *hotfixHelper = nullptr) override; + + void AssignIndex(uint32_t index) + { + index_ = index; + } + + uint32_t Index() const + { + return index_; + } + +private: + uint32_t index_; }; class EnumVariable : public Variable { diff --git a/es2panda/compiler/base/destructuring.cpp b/es2panda/compiler/base/destructuring.cpp index 70d9ef0754d749ed9ca0aee4dbe9c1fd9857bf7c..5761a021774bc9898ddb012a2f56585f9e508ed6 100644 --- a/es2panda/compiler/base/destructuring.cpp +++ b/es2panda/compiler/base/destructuring.cpp @@ -145,8 +145,8 @@ static void GenArray(PandaGen *pg, const ir::ArrayExpression *array) pg->SetLabel(array, labelSet.CatchEnd()); } -static void GenObjectProperty(PandaGen *pg, const ir::ObjectExpression *object, const ir::Expression *element, - VReg value, VReg propReg) +static void GenObjectProperty(PandaGen *pg, const ir::ObjectExpression *object, + const ir::Expression *element, VReg value) { RegScope propScope(pg); VReg loadedValue = pg->AllocReg(); @@ -169,12 +169,10 @@ static void GenObjectProperty(PandaGen *pg, const ir::ObjectExpression *object, key->Compile(pg); } - pg->StoreAccumulator(key, propReg); - LReference lref = LReference::CreateLRef(pg, target, object->IsDeclaration()); // load obj property from rhs, return undefined if no corresponding property exists - pg->LoadObjByValue(element, value, propReg); + pg->LoadObjByValue(element, value); pg->StoreAccumulator(element, loadedValue); if (init != nullptr) { @@ -211,8 +209,7 @@ static void GenObjectWithRest(PandaGen *pg, const ir::ObjectExpression *object, break; } - VReg propReg = pg->AllocReg(); - GenObjectProperty(pg, object, element, rhs, propReg); + GenObjectProperty(pg, object, element, rhs); } } @@ -241,10 +238,7 @@ static void GenObject(PandaGen *pg, const ir::ObjectExpression *object, VReg rhs } for (const auto *element : properties) { - RegScope rs(pg); - VReg propReg = pg->AllocReg(); - - GenObjectProperty(pg, object, element, rhs, propReg); + GenObjectProperty(pg, object, element, rhs); } } diff --git a/es2panda/compiler/base/hoisting.cpp b/es2panda/compiler/base/hoisting.cpp index e8b61fc97d3252b521f595b266bd3675664f6729..5f5b6370b65be4bfa2cc4122dbe808fd3a1a6ac8 100644 --- a/es2panda/compiler/base/hoisting.cpp +++ b/es2panda/compiler/base/hoisting.cpp @@ -27,7 +27,9 @@ static void StoreModuleVarOrLocalVar(PandaGen *pg, binder::ScopeFindResult &resu { if (decl->IsImportOrExportDecl()) { ASSERT(pg->Scope()->IsModuleScope()); - pg->StoreModuleVariable(decl->Node(), decl->Name()); + auto *var = pg->Scope()->FindLocal(decl->Name()); + ASSERT(var->IsModuleVariable()); + pg->StoreModuleVariable(decl->Node(), var->AsModuleVariable()); } else { pg->StoreAccToLexEnv(decl->Node(), result, true); } @@ -84,7 +86,7 @@ static void HoistNameSpaceImports(PandaGen *pg) ASSERT(var != nullptr); auto *node = var->Declaration()->Node(); ASSERT(node != nullptr); - pg->GetModuleNamespace(node, nameSpaceEntry->localName_); + pg->GetModuleNamespace(node, nameSpaceEntry->moduleRequestIdx_); pg->StoreVar(node, {nameSpaceEntry->localName_, pg->TopScope(), 0, var}, true); } } diff --git a/es2panda/compiler/base/optionalChain.cpp b/es2panda/compiler/base/optionalChain.cpp new file mode 100644 index 0000000000000000000000000000000000000000..af6ec45f5f9be9bdf34f62146e32992b0bacc9fe --- /dev/null +++ b/es2panda/compiler/base/optionalChain.cpp @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "optionalChain.h" + +#include + +namespace panda::es2panda::compiler { +OptionalChain::OptionalChain(PandaGen *pg, const ir::AstNode *node) : pg_(pg), node_(node), prev_(pg->optionalChain_) +{ + pg_->optionalChain_ = this; +} + +OptionalChain::~OptionalChain() +{ + if (label_) { + pg_->SetLabel(node_, label_); + } + pg_->optionalChain_ = prev_; +} + +void OptionalChain::CheckNullish(bool optional, compiler::VReg obj) +{ + if (!optional) { + return; + } + + if (!label_) { + label_ = pg_->AllocLabel(); + } + + RegScope rs(pg_); + + auto *notNullish = pg_->AllocLabel(); + auto *nullish = pg_->AllocLabel(); + + pg_->LoadConst(node_, Constant::JS_NULL); + pg_->Condition(node_, lexer::TokenType::PUNCTUATOR_NOT_STRICT_EQUAL, obj, nullish); + pg_->LoadConst(node_, Constant::JS_UNDEFINED); + pg_->Condition(node_, lexer::TokenType::PUNCTUATOR_NOT_STRICT_EQUAL, obj, nullish); + pg_->Branch(node_, notNullish); + pg_->SetLabel(node_, nullish); + + pg_->LoadConst(node_, compiler::Constant::JS_UNDEFINED); + pg_->Branch(node_, label_); + pg_->SetLabel(node_, notNullish); + pg_->LoadAccumulator(node_, obj); +} + +} // namespace panda::es2panda::compiler diff --git a/es2panda/compiler/base/optionalChain.h b/es2panda/compiler/base/optionalChain.h new file mode 100644 index 0000000000000000000000000000000000000000..c6005d03b2c892dc728fa025f161f6604687c510 --- /dev/null +++ b/es2panda/compiler/base/optionalChain.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ES2PANDA_COMPILER_BASE_OPTIONAL_CHAIN_H +#define ES2PANDA_COMPILER_BASE_OPTIONAL_CHAIN_H + +#include +#include + +namespace panda::es2panda::compiler { +class PandaGen; +class Label; + +class OptionalChain { +public: + explicit OptionalChain(PandaGen *pg, const ir::AstNode *node); + ~OptionalChain(); + + void CheckNullish(bool optional, compiler::VReg obj); + + NO_COPY_SEMANTIC(OptionalChain); + NO_MOVE_SEMANTIC(OptionalChain); + +private: + PandaGen *pg_ {}; + const ir::AstNode *node_ {}; + Label *label_ {}; + OptionalChain *prev_ {}; +}; +} // namespace panda::es2panda::compiler + +#endif diff --git a/es2panda/compiler/core/compileQueue.h b/es2panda/compiler/core/compileQueue.h index 17392fe4a0409a48bc24a12994872b7ce6320a29..fe1f0da29090b54ee92606849af43b87edb76d36 100644 --- a/es2panda/compiler/core/compileQueue.h +++ b/es2panda/compiler/core/compileQueue.h @@ -55,7 +55,7 @@ public: explicit CompileFunctionJob(CompilerContext *context) : context_(context) {}; NO_COPY_SEMANTIC(CompileFunctionJob); NO_MOVE_SEMANTIC(CompileFunctionJob); - ~CompileFunctionJob() = default; + ~CompileFunctionJob() override = default; binder::FunctionScope *Scope() const { @@ -79,7 +79,7 @@ public: explicit CompileModuleRecordJob(CompilerContext *context) : context_(context) {}; NO_COPY_SEMANTIC(CompileModuleRecordJob); NO_MOVE_SEMANTIC(CompileModuleRecordJob); - ~CompileModuleRecordJob() = default; + ~CompileModuleRecordJob() override = default; void Run() override; @@ -95,7 +95,7 @@ public: : src_(src), options_(options), progsInfo_(progsInfo), symbolTable_(symbolTable), allocator_(allocator) {}; NO_COPY_SEMANTIC(CompileFileJob); NO_MOVE_SEMANTIC(CompileFileJob); - ~CompileFileJob() = default; + ~CompileFileJob() override = default; void Run() override; @@ -140,7 +140,7 @@ public: NO_COPY_SEMANTIC(CompileFuncQueue); NO_MOVE_SEMANTIC(CompileFuncQueue); - ~CompileFuncQueue() = default; + ~CompileFuncQueue() override = default; void Schedule() override; @@ -158,7 +158,7 @@ public: NO_COPY_SEMANTIC(CompileFileQueue); NO_MOVE_SEMANTIC(CompileFileQueue); - ~CompileFileQueue() = default; + ~CompileFileQueue() override = default; void Schedule() override; diff --git a/es2panda/compiler/core/compilerContext.cpp b/es2panda/compiler/core/compilerContext.cpp index 81434e630b0a4cdccc30fa37dc54886355150f91..f3549110db087121ab07c049dfe76cea3a76e401 100644 --- a/es2panda/compiler/core/compilerContext.cpp +++ b/es2panda/compiler/core/compilerContext.cpp @@ -20,9 +20,10 @@ namespace panda::es2panda::compiler { CompilerContext::CompilerContext(binder::Binder *binder, bool isDebug, bool isDebuggerEvaluateExpressionMode, - bool isMergeAbc, std::string sourceFile) + bool isMergeAbc, std::string sourceFile, util::StringView recordName) : binder_(binder), isDebug_(isDebug), isDebuggerEvaluateExpressionMode_(isDebuggerEvaluateExpressionMode), - isMergeAbc_(isMergeAbc), sourceFile_(sourceFile), emitter_(std::make_unique(this)) + isMergeAbc_(isMergeAbc), sourceFile_(sourceFile), emitter_(std::make_unique(this)), + recordName_(recordName) { } diff --git a/es2panda/compiler/core/compilerContext.h b/es2panda/compiler/core/compilerContext.h index 6acc7b83fb53a24cf1004237abdbab7734ca6349..64fa445db1e19d7af4960bd2bfb0b4501f145afb 100644 --- a/es2panda/compiler/core/compilerContext.h +++ b/es2panda/compiler/core/compilerContext.h @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -35,7 +36,7 @@ class Emitter; class CompilerContext { public: CompilerContext(binder::Binder *binder, bool isDebug, bool isDebuggerEvaluateExpressionMode, - bool isMergeAbc, std::string sourceFile); + bool isMergeAbc, std::string sourceFile, util::StringView recordName); NO_COPY_SEMANTIC(CompilerContext); NO_MOVE_SEMANTIC(CompilerContext); ~CompilerContext() = default; @@ -96,6 +97,11 @@ public: return hotfixHelper_; } + util::StringView &RecordName() + { + return recordName_; + } + private: binder::Binder *binder_; int32_t literalBufferIdx_ {0}; @@ -106,6 +112,7 @@ private: std::string sourceFile_; std::unique_ptr emitter_; util::Hotfix *hotfixHelper_ {nullptr}; + util::StringView recordName_; }; } // namespace panda::es2panda::compiler diff --git a/es2panda/compiler/core/compilerImpl.cpp b/es2panda/compiler/core/compilerImpl.cpp index 5561346b974793c47b68f0e8599a6c22d805f6e7..368783be9633a58dc2a8ce8f99c98582a2344101 100644 --- a/es2panda/compiler/core/compilerImpl.cpp +++ b/es2panda/compiler/core/compilerImpl.cpp @@ -39,7 +39,7 @@ panda::pandasm::Program *CompilerImpl::Compile(parser::Program *program, const e const std::string &debugInfoSourceFile) { CompilerContext context(program->Binder(), options.isDebug, options.isDebuggerEvaluateExpressionMode, - options.mergeAbc, debugInfoSourceFile); + options.mergeAbc, debugInfoSourceFile, program->RecordName()); if (hotfixHelper_ != nullptr) { context.AddHotfixHelper(hotfixHelper_); diff --git a/es2panda/compiler/core/dynamicContext.h b/es2panda/compiler/core/dynamicContext.h index 2e13faab6e9ab022393fa06168150f4af0fa2590..8edb42e5c2dd2331875e5dda377be4326fc97a2f 100644 --- a/es2panda/compiler/core/dynamicContext.h +++ b/es2panda/compiler/core/dynamicContext.h @@ -39,7 +39,7 @@ class DynamicContext { public: NO_COPY_SEMANTIC(DynamicContext); NO_MOVE_SEMANTIC(DynamicContext); - ~DynamicContext(); + virtual ~DynamicContext(); void *operator new(size_t) = delete; void *operator new[](size_t) = delete; diff --git a/es2panda/compiler/core/emitter/emitter.cpp b/es2panda/compiler/core/emitter/emitter.cpp index 53064fdc1dea20e7c450060e75a09504cadcdc15..a438ad9515aa03324004fd51a0488f8dbef0ab88 100644 --- a/es2panda/compiler/core/emitter/emitter.cpp +++ b/es2panda/compiler/core/emitter/emitter.cpp @@ -57,6 +57,8 @@ FunctionEmitter::FunctionEmitter(ArenaAllocator *allocator, const PandaGen *pg) void FunctionEmitter::Generate(util::Hotfix *hotfixHelper) { + GenFunctionKind(); + GenIcSize(); GenFunctionInstructions(); GenVariablesDebugInfo(); GenSourceFileDebugInfo(); @@ -72,6 +74,16 @@ const ArenaSet &FunctionEmitter::Strings() const return pg_->Strings(); } +void FunctionEmitter::GenFunctionKind() +{ + func_->SetFunctionKind(static_cast(pg_->GetFunctionKind())); +} + +void FunctionEmitter::GenIcSize() +{ + func_->SetSlotsNum(pg_->GetCurrentSlot()); +} + void FunctionEmitter::GenBufferLiterals(const LiteralBuffer *buff) { auto &[idx, array] = literalBuffers_.emplace_back(); @@ -274,10 +286,10 @@ void FunctionEmitter::GenLiteralBuffers() void FunctionEmitter::GenSourceFileDebugInfo() { - if (pg_->SourceFile().size() > 0) { - func_->source_file = pg_->SourceFile(); - } else { + if (pg_->SourceFile().empty()) { func_->source_file = std::string {pg_->Binder()->Program()->SourceFile()}; + } else { + func_->source_file = pg_->SourceFile(); } if (!pg_->IsDebug()) { diff --git a/es2panda/compiler/core/emitter/emitter.h b/es2panda/compiler/core/emitter/emitter.h index f689a4e57c80e973f81be76d7c0064134343f076..3bf135f729da4656bed90d9673739d5ed3e30223 100644 --- a/es2panda/compiler/core/emitter/emitter.h +++ b/es2panda/compiler/core/emitter/emitter.h @@ -81,6 +81,8 @@ private: void GenScopeVariableInfo(const binder::Scope *scope); void GenSourceFileDebugInfo(); void GenVariablesDebugInfo(); + void GenFunctionKind(); + void GenIcSize(); util::StringView SourceCode() const; lexer::LineIndex &GetLineIndex() const; diff --git a/es2panda/compiler/core/envScope.cpp b/es2panda/compiler/core/envScope.cpp index a6c123937c6f11cf1f0d2398dc394504f5ebffed..6cb007c87e5599bda9ef68b52009c49f28edf250 100644 --- a/es2panda/compiler/core/envScope.cpp +++ b/es2panda/compiler/core/envScope.cpp @@ -30,11 +30,10 @@ ScopeContext::~ScopeContext() pg_->scope_ = prevScope_; } -void EnvScope::Initialize(PandaGen *pg, VReg lexEnv) +void EnvScope::Initialize(PandaGen *pg) { pg_ = pg; prev_ = pg_->envScope_; - lexEnv_ = lexEnv; pg_->envScope_ = this; } @@ -53,10 +52,9 @@ void LoopEnvScope::CopyBindings(PandaGen *pg, binder::VariableScope *scope, bind return; } - Initialize(pg, pg->AllocReg()); + Initialize(pg); pg_->NewLexicalEnv(scope_->Node(), scope->LexicalSlots(), scope_); - pg_->StoreAccumulator(scope_->Node(), lexEnv_); ASSERT(scope->NeedLexEnv()); @@ -89,7 +87,6 @@ void LoopEnvScope::CopyPetIterationCtx() } pg_->PopLexEnv(scope_->Node()); pg_->NewLexicalEnv(scope_->Node(), num, scope_); - pg_->StoreAccumulator(scope_->Node(), lexEnv_); for (uint32_t i = 0; i < num; i++) { pg_->StoreLexicalVar(scope_->Node(), 0, i, lexicals[i]); diff --git a/es2panda/compiler/core/envScope.h b/es2panda/compiler/core/envScope.h index 55b801a7a1f3e026a9403344d896fdbedc68ecbe..a21c2a3e52022a8ec6e51467b395d410cda5f5e8 100644 --- a/es2panda/compiler/core/envScope.h +++ b/es2panda/compiler/core/envScope.h @@ -52,12 +52,7 @@ public: NO_MOVE_SEMANTIC(EnvScope); ~EnvScope(); - void Initialize(PandaGen *pg, VReg lexEnv); - - VReg LexEnv() const - { - return lexEnv_; - } + void Initialize(PandaGen *pg); EnvScope *Prev() const { @@ -69,7 +64,6 @@ protected: PandaGen *pg_ {}; EnvScope *prev_ {}; - VReg lexEnv_ {}; }; class LoopEnvScope : public EnvScope { diff --git a/es2panda/compiler/core/function.cpp b/es2panda/compiler/core/function.cpp index 3f4a050ea07cc44fde3dc3c1d3779b8e2fdf6b89..c2f0f7298e577bbe4928853c1e08e5c0ff6dcf3d 100644 --- a/es2panda/compiler/core/function.cpp +++ b/es2panda/compiler/core/function.cpp @@ -75,7 +75,7 @@ static void CompileFunctionParameterDeclaration(PandaGen *pg, const ir::ScriptFu if (param->IsAssignmentPattern()) { RegScope rs(pg); - pg->LoadAccumulator(func, paramReg); + ref.GetValue(); auto *nonDefaultLabel = pg->AllocLabel(); if (ref.Kind() == ReferenceKind::DESTRUCTURING) { @@ -170,7 +170,7 @@ static void CompileFunction(PandaGen *pg) pg->FunctionExit(); } -static VReg CompileFunctionOrProgram(PandaGen *pg) +static void CompileFunctionOrProgram(PandaGen *pg) { FunctionRegScope lrs(pg); const auto *topScope = pg->TopScope(); @@ -192,16 +192,15 @@ static VReg CompileFunctionOrProgram(PandaGen *pg) CompileSourceBlock(pg, pg->RootNode()->AsBlockStatement()); } } - - return pg->GetEnvScope()->LexEnv(); } void Function::Compile(PandaGen *pg) { - VReg lexEnv = CompileFunctionOrProgram(pg); + CompileFunctionOrProgram(pg); + pg->SetFunctionKind(); pg->SetSourceLocationFlag(lexer::SourceLocationFlag::INVALID_SOURCE_LOCATION); pg->CopyFunctionArguments(pg->RootNode()); - pg->InitializeLexEnv(pg->RootNode(), lexEnv); + pg->InitializeLexEnv(pg->RootNode()); pg->SetSourceLocationFlag(lexer::SourceLocationFlag::VALID_SOURCE_LOCATION); pg->SortCatchTables(); } diff --git a/es2panda/compiler/core/pandagen.cpp b/es2panda/compiler/core/pandagen.cpp index e56e28c72dc42d6fc0fdc2f07c3049f0955913d6..7dcf427b52304bdb7e32952dcba69efa2a79f074 100644 --- a/es2panda/compiler/core/pandagen.cpp +++ b/es2panda/compiler/core/pandagen.cpp @@ -47,6 +47,46 @@ namespace panda::es2panda::compiler { // PandaGen +void PandaGen::SetFunctionKind() +{ + if (rootNode_->IsProgram()) { + funcKind_ = panda::panda_file::FunctionKind::FUNCTION; + return; + } + + auto *func = rootNode_->AsScriptFunction(); + if (func->IsMethod()) { + return; + } + + if (func->IsAsync()) { + if (func->IsGenerator()) { + funcKind_ = panda::panda_file::FunctionKind::ASYNC_GENERATOR_FUNCTION; + return; + } + + if (func->IsArrow()) { + funcKind_ = panda::panda_file::FunctionKind::ASYNC_NC_FUNCTION; + return; + } + + funcKind_ = panda::panda_file::FunctionKind::ASYNC_FUNCTION; + return; + } + + if (func->IsGenerator()) { + funcKind_ = panda::panda_file::FunctionKind::GENERATOR_FUNCTION; + return; + } + + if (func->IsArrow()) { + funcKind_ = panda::panda_file::FunctionKind::NC_FUNCTION; + return; + } + + funcKind_ = panda::panda_file::FunctionKind::FUNCTION; +} + Label *PandaGen::AllocLabel() { std::string id = std::string {Label::PREFIX} + std::to_string(labelId_++); @@ -157,17 +197,13 @@ void PandaGen::FunctionExit() builder_->CleanUp(rootNode_->AsScriptFunction()); } -void PandaGen::InitializeLexEnv(const ir::AstNode *node, VReg lexEnv) +void PandaGen::InitializeLexEnv(const ir::AstNode *node) { FrontAllocator fa(this); if (topScope_->NeedLexEnv()) { NewLexicalEnv(node, topScope_->LexicalSlots(), topScope_); - } else { - LdLexEnv(node); } - - StoreAccumulator(node, lexEnv); } void PandaGen::CopyFunctionArguments(const ir::AstNode *node) @@ -179,7 +215,7 @@ void PandaGen::CopyFunctionArguments(const ir::AstNode *node) if (param->LexicalBound()) { StoreLexicalVar(node, 0, param->LexIdx(), targetReg++); } else { - ra_.Emit(node, param->Vreg(), targetReg++); + MoveVreg(node, param->Vreg(), targetReg++); } } } @@ -242,7 +278,8 @@ void PandaGen::LoadVar(const ir::Identifier *node, const binder::ScopeFindResult } if (var->IsModuleVariable()) { - LoadModuleVariable(node, var->Name(), var->HasFlag(binder::VariableFlags::LOCAL_EXPORT)); + var->HasFlag(binder::VariableFlags::LOCAL_EXPORT) ? LoadLocalModuleVariable(node, var->AsModuleVariable()) : + LoadExternalModuleVariable(node, var->AsModuleVariable()); if (var->Declaration()->IsLetOrConstOrClassDecl()) { ThrowUndefinedIfHole(node, var->Name()); } @@ -284,12 +321,12 @@ void PandaGen::StoreVar(const ir::AstNode *node, const binder::ScopeFindResult & RegScope rs(this); VReg valueReg = AllocReg(); StoreAccumulator(node, valueReg); - LoadModuleVariable(node, var->Name(), true); + LoadLocalModuleVariable(node, var->AsModuleVariable()); ThrowUndefinedIfHole(node, var->Name()); LoadAccumulator(node, valueReg); } - StoreModuleVariable(node, var->Name()); + StoreModuleVariable(node, var->AsModuleVariable()); return; } @@ -298,13 +335,12 @@ void PandaGen::StoreVar(const ir::AstNode *node, const binder::ScopeFindResult & if (var->Declaration()->IsLetOrConstOrClassDecl() && result.scope->IsGlobalScope()) { if (!isDeclaration) { TryStoreGlobalByName(node, var->Name()); - } else if (var->Declaration()->IsLetDecl()) { - StLetToGlobalRecord(node, var->Name()); + } else if (var->Declaration()->IsLetDecl() || var->Declaration()->IsClassDecl()) { + StLetOrClassToGlobalRecord(node, var->Name()); } else if (var->Declaration()->IsConstDecl()) { StConstToGlobalRecord(node, var->Name()); - } else if (var->Declaration()->IsClassDecl()) { - StClassToGlobalRecord(node, var->Name()); } + return; } @@ -313,7 +349,7 @@ void PandaGen::StoreVar(const ir::AstNode *node, const binder::ScopeFindResult & void PandaGen::StoreAccumulator(const ir::AstNode *node, VReg vreg) { - ra_.Emit(node, vreg); + ra_.Emit(node, vreg); } void PandaGen::LoadAccFromArgs(const ir::AstNode *node) @@ -334,7 +370,8 @@ void PandaGen::LoadAccFromArgs(const ir::AstNode *node) void PandaGen::LoadObjProperty(const ir::AstNode *node, VReg obj, const Operand &prop) { if (std::holds_alternative(prop)) { - LoadObjByValue(node, obj, std::get(prop)); + LoadAccumulator(node, std::get(prop)); + LoadObjByValue(node, obj); return; } @@ -409,7 +446,7 @@ void PandaGen::TryLoadGlobalByName(const ir::AstNode *node, const util::StringVi if (isDebuggerEvaluateExpressionMode()) { LoadObjByNameViaDebugger(node, name, true); } else { - sa_.Emit(node, name); + sa_.Emit(node, 0, name); } strings_.insert(name); } @@ -437,109 +474,109 @@ void PandaGen::TryStoreGlobalByName(const ir::AstNode *node, const util::StringV if (isDebuggerEvaluateExpressionMode()) { StoreObjByNameViaDebugger(node, name); } else { - sa_.Emit(node, name); + sa_.Emit(node, 0, name); } strings_.insert(name); } void PandaGen::LoadObjByName(const ir::AstNode *node, VReg obj, const util::StringView &prop) { - ra_.Emit(node, prop, obj); + LoadAccumulator(node, obj); // object is load to acc + sa_.Emit(node, 0, prop); strings_.insert(prop); } void PandaGen::StoreObjByName(const ir::AstNode *node, VReg obj, const util::StringView &prop) { - ra_.Emit(node, prop, obj); + ra_.Emit(node, 0, prop, obj); strings_.insert(prop); } void PandaGen::LoadObjByIndex(const ir::AstNode *node, VReg obj, int64_t index) { - ra_.Emit(node, index, obj); + LoadAccumulator(node, obj); // object is load to acc + if (index <= util::Helpers::MAX_INT16) { + sa_.Emit(node, 0, index); + return; + } + + sa_.Emit(node, index); } -void PandaGen::LoadObjByValue(const ir::AstNode *node, VReg obj, VReg prop) +void PandaGen::LoadObjByValue(const ir::AstNode *node, VReg obj) { - ra_.Emit(node, obj, prop); + ra_.Emit(node, 0, obj); // prop is in acc } void PandaGen::StoreObjByValue(const ir::AstNode *node, VReg obj, VReg prop) { - ra_.Emit(node, obj, prop); + ra_.Emit(node, 0, obj, prop); } void PandaGen::StoreObjByIndex(const ir::AstNode *node, VReg obj, int64_t index) { - ra_.Emit(node, index, obj); + if (index <= util::Helpers::MAX_INT16) { + ra_.Emit(node, 0, obj, index); + return; + } + + ra_.Emit(node, obj, index); } void PandaGen::StOwnByName(const ir::AstNode *node, VReg obj, const util::StringView &prop, bool nameSetting) { - nameSetting ? ra_.Emit(node, prop, obj) : - ra_.Emit(node, prop, obj); + nameSetting ? ra_.Emit(node, 0, prop, obj) : + ra_.Emit(node, 0, prop, obj); strings_.insert(prop); } void PandaGen::StOwnByValue(const ir::AstNode *node, VReg obj, VReg prop, bool nameSetting) { - nameSetting ? ra_.Emit(node, obj, prop) : - ra_.Emit(node, obj, prop); + nameSetting ? ra_.Emit(node, 0, obj, prop) : + ra_.Emit(node, 0, obj, prop); } void PandaGen::StOwnByIndex(const ir::AstNode *node, VReg obj, int64_t index) { - ra_.Emit(node, obj, index); + if (index <= util::Helpers::MAX_INT16) { + ra_.Emit(node, 0, obj, index); + return; + } + + ra_.Emit(node, obj, index); } void PandaGen::DeleteObjProperty(const ir::AstNode *node, VReg obj, const Operand &prop) { - VReg property {}; - if (std::holds_alternative(prop)) { - property = std::get(prop); + LoadAccumulator(node, std::get(prop)); } else if (std::holds_alternative(prop)) { LoadAccumulatorInt(node, static_cast(std::get(prop))); - property = AllocReg(); - StoreAccumulator(node, property); } else { ASSERT(std::holds_alternative(prop)); LoadAccumulatorString(node, std::get(prop)); - property = AllocReg(); - StoreAccumulator(node, property); } - ra_.Emit(node, obj, property); + ra_.Emit(node, obj); // property is load to acc } void PandaGen::LoadAccumulator(const ir::AstNode *node, VReg reg) { - ra_.Emit(node, reg); + ra_.Emit(node, reg); } void PandaGen::LoadGlobalVar(const ir::AstNode *node, const util::StringView &name) { - sa_.Emit(node, name); + sa_.Emit(node, 0, name); strings_.insert(name); } void PandaGen::StoreGlobalVar(const ir::AstNode *node, const util::StringView &name) { - sa_.Emit(node, name); - strings_.insert(name); -} - -void PandaGen::StoreGlobalLet(const ir::AstNode *node, const util::StringView &name) -{ - sa_.Emit(node, name); + sa_.Emit(node, 0, name); strings_.insert(name); } -VReg PandaGen::LexEnv() const -{ - return envScope_->LexEnv(); -} - void PandaGen::LoadAccFromLexEnv(const ir::AstNode *node, const binder::ScopeFindResult &result) { VirtualLoadVar::Expand(this, node, result); @@ -558,22 +595,22 @@ void PandaGen::LoadAccumulatorString(const ir::AstNode *node, const util::String void PandaGen::LoadAccumulatorFloat(const ir::AstNode *node, double num) { - sa_.Emit(node, num); + sa_.Emit(node, num); } void PandaGen::LoadAccumulatorInt(const ir::AstNode *node, int32_t num) { - sa_.Emit(node, num); + sa_.Emit(node, num); } void PandaGen::LoadAccumulatorInt(const ir::AstNode *node, size_t num) { - sa_.Emit(node, static_cast(num)); + sa_.Emit(node, static_cast(num)); } void PandaGen::LoadAccumulatorBigInt(const ir::AstNode *node, const util::StringView &num) { - sa_.Emit(node, num); + sa_.Emit(node, num); strings_.insert(num); } @@ -587,39 +624,39 @@ void PandaGen::LoadConst(const ir::AstNode *node, Constant id) { switch (id) { case Constant::JS_HOLE: { - sa_.Emit(node); + sa_.Emit(node); break; } case Constant::JS_NAN: { - sa_.Emit(node); + sa_.Emit(node); break; } case Constant::JS_INFINITY: { - sa_.Emit(node); + sa_.Emit(node); break; } case Constant::JS_GLOBAL: { - sa_.Emit(node); + sa_.Emit(node); break; } case Constant::JS_UNDEFINED: { - sa_.Emit(node); + sa_.Emit(node); break; } case Constant::JS_SYMBOL: { - sa_.Emit(node); + sa_.Emit(node); break; } case Constant::JS_NULL: { - sa_.Emit(node); + sa_.Emit(node); break; } case Constant::JS_TRUE: { - sa_.Emit(node); + sa_.Emit(node); break; } case Constant::JS_FALSE: { - sa_.Emit(node); + sa_.Emit(node); break; } default: { @@ -630,7 +667,7 @@ void PandaGen::LoadConst(const ir::AstNode *node, Constant id) void PandaGen::MoveVreg(const ir::AstNode *node, VReg vd, VReg vs) { - ra_.Emit(node, vd, vs); + ra_.Emit(node, vd, vs); } void PandaGen::SetLabel([[maybe_unused]] const ir::AstNode *node, Label *label) @@ -643,7 +680,7 @@ void PandaGen::Branch(const ir::AstNode *node, Label *label) sa_.Emit(node, label); } -bool PandaGen::CheckControlFlowChange() +bool PandaGen::CheckControlFlowChange() const { const auto *iter = dynamicContext_; @@ -713,35 +750,35 @@ void PandaGen::Condition(const ir::AstNode *node, lexer::TokenType op, VReg lhs, { switch (op) { case lexer::TokenType::PUNCTUATOR_EQUAL: { - ra_.Emit(node, lhs); + Equal(node, lhs); break; } case lexer::TokenType::PUNCTUATOR_NOT_EQUAL: { - ra_.Emit(node, lhs); + NotEqual(node, lhs); break; } case lexer::TokenType::PUNCTUATOR_STRICT_EQUAL: { - ra_.Emit(node, lhs); + StrictEqual(node, lhs); break; } case lexer::TokenType::PUNCTUATOR_NOT_STRICT_EQUAL: { - ra_.Emit(node, lhs); + StrictNotEqual(node, lhs); break; } case lexer::TokenType::PUNCTUATOR_LESS_THAN: { - ra_.Emit(node, lhs); + LessThan(node, lhs); break; } case lexer::TokenType::PUNCTUATOR_LESS_THAN_EQUAL: { - ra_.Emit(node, lhs); + LessEqual(node, lhs); break; } case lexer::TokenType::PUNCTUATOR_GREATER_THAN: { - ra_.Emit(node, lhs); + GreaterThan(node, lhs); break; } case lexer::TokenType::PUNCTUATOR_GREATER_THAN_EQUAL: { - ra_.Emit(node, lhs); + GreaterEqual(node, lhs); break; } default: { @@ -756,15 +793,17 @@ void PandaGen::Unary(const ir::AstNode *node, lexer::TokenType op, VReg operand) { switch (op) { case lexer::TokenType::PUNCTUATOR_PLUS: { - ra_.Emit(node, operand); + ToNumber(node, operand); break; } case lexer::TokenType::PUNCTUATOR_MINUS: { - ra_.Emit(node, operand); + LoadAccumulator(node, operand); + sa_.Emit(node, 0); break; } case lexer::TokenType::PUNCTUATOR_TILDE: { - ra_.Emit(node, operand); + LoadAccumulator(node, operand); + sa_.Emit(node, 0); break; } case lexer::TokenType::PUNCTUATOR_EXCLAMATION_MARK: { @@ -772,11 +811,13 @@ void PandaGen::Unary(const ir::AstNode *node, lexer::TokenType op, VReg operand) break; } case lexer::TokenType::PUNCTUATOR_PLUS_PLUS: { - ra_.Emit(node, operand); + LoadAccumulator(node, operand); + sa_.Emit(node, 0); break; } case lexer::TokenType::PUNCTUATOR_MINUS_MINUS: { - ra_.Emit(node, operand); + LoadAccumulator(node, operand); + sa_.Emit(node, 0); break; } case lexer::TokenType::KEYW_VOID: @@ -794,103 +835,103 @@ void PandaGen::Binary(const ir::AstNode *node, lexer::TokenType op, VReg lhs) { switch (op) { case lexer::TokenType::PUNCTUATOR_EQUAL: { - ra_.Emit(node, lhs); + Equal(node, lhs); break; } case lexer::TokenType::PUNCTUATOR_NOT_EQUAL: { - ra_.Emit(node, lhs); + NotEqual(node, lhs); break; } case lexer::TokenType::PUNCTUATOR_STRICT_EQUAL: { - ra_.Emit(node, lhs); + StrictEqual(node, lhs); break; } case lexer::TokenType::PUNCTUATOR_NOT_STRICT_EQUAL: { - ra_.Emit(node, lhs); + StrictNotEqual(node, lhs); break; } case lexer::TokenType::PUNCTUATOR_LESS_THAN: { - ra_.Emit(node, lhs); + LessThan(node, lhs); break; } case lexer::TokenType::PUNCTUATOR_LESS_THAN_EQUAL: { - ra_.Emit(node, lhs); + LessEqual(node, lhs); break; } case lexer::TokenType::PUNCTUATOR_GREATER_THAN: { - ra_.Emit(node, lhs); + GreaterThan(node, lhs); break; } case lexer::TokenType::PUNCTUATOR_GREATER_THAN_EQUAL: { - ra_.Emit(node, lhs); + GreaterEqual(node, lhs); break; } case lexer::TokenType::PUNCTUATOR_PLUS: case lexer::TokenType::PUNCTUATOR_PLUS_EQUAL: { - ra_.Emit(node, lhs); + ra_.Emit(node, 0, lhs); break; } case lexer::TokenType::PUNCTUATOR_MINUS: case lexer::TokenType::PUNCTUATOR_MINUS_EQUAL: { - ra_.Emit(node, lhs); + ra_.Emit(node, 0, lhs); break; } case lexer::TokenType::PUNCTUATOR_MULTIPLY: case lexer::TokenType::PUNCTUATOR_MULTIPLY_EQUAL: { - ra_.Emit(node, lhs); + ra_.Emit(node, 0, lhs); break; } case lexer::TokenType::PUNCTUATOR_DIVIDE: case lexer::TokenType::PUNCTUATOR_DIVIDE_EQUAL: { - ra_.Emit(node, lhs); + ra_.Emit(node, 0, lhs); break; } case lexer::TokenType::PUNCTUATOR_MOD: case lexer::TokenType::PUNCTUATOR_MOD_EQUAL: { - ra_.Emit(node, lhs); + ra_.Emit(node, 0, lhs); break; } case lexer::TokenType::PUNCTUATOR_EXPONENTIATION_EQUAL: case lexer::TokenType::PUNCTUATOR_EXPONENTIATION: { - ra_.Emit(node, lhs); + ra_.Emit(node, 0, lhs); break; } case lexer::TokenType::PUNCTUATOR_LEFT_SHIFT: case lexer::TokenType::PUNCTUATOR_LEFT_SHIFT_EQUAL: { - ra_.Emit(node, lhs); + ra_.Emit(node, 0, lhs); break; } case lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT: case lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT_EQUAL: { - ra_.Emit(node, lhs); + ra_.Emit(node, 0, lhs); break; } case lexer::TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT: case lexer::TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT_EQUAL: { - ra_.Emit(node, lhs); + ra_.Emit(node, 0, lhs); break; } case lexer::TokenType::PUNCTUATOR_BITWISE_AND: case lexer::TokenType::PUNCTUATOR_BITWISE_AND_EQUAL: { - ra_.Emit(node, lhs); + ra_.Emit(node, 0, lhs); break; } case lexer::TokenType::PUNCTUATOR_BITWISE_OR: case lexer::TokenType::PUNCTUATOR_BITWISE_OR_EQUAL: { - ra_.Emit(node, lhs); + ra_.Emit(node, 0, lhs); break; } case lexer::TokenType::PUNCTUATOR_BITWISE_XOR: case lexer::TokenType::PUNCTUATOR_BITWISE_XOR_EQUAL: { - ra_.Emit(node, lhs); + ra_.Emit(node, 0, lhs); break; } case lexer::TokenType::KEYW_IN: { - ra_.Emit(node, lhs); + ra_.Emit(node, 0, lhs); break; } case lexer::TokenType::KEYW_INSTANCEOF: { - ra_.Emit(node, lhs); + ra_.Emit(node, 0, lhs); break; } case lexer::TokenType::PUNCTUATOR_NULLISH_COALESCING: @@ -904,13 +945,58 @@ void PandaGen::Binary(const ir::AstNode *node, lexer::TokenType op, VReg lhs) } } +void PandaGen::Equal(const ir::AstNode *node, VReg lhs) +{ + ra_.Emit(node, 0, lhs); +} + +void PandaGen::NotEqual(const ir::AstNode *node, VReg lhs) +{ + ra_.Emit(node, 0, lhs); +} + +void PandaGen::StrictEqual(const ir::AstNode *node, VReg lhs) +{ + ra_.Emit(node, 0, lhs); +} + +void PandaGen::StrictNotEqual(const ir::AstNode *node, VReg lhs) +{ + ra_.Emit(node, 0, lhs); +} + +void PandaGen::LessThan(const ir::AstNode *node, VReg lhs) +{ + ra_.Emit(node, 0, lhs); +} + +void PandaGen::LessEqual(const ir::AstNode *node, VReg lhs) +{ + ra_.Emit(node, 0, lhs); +} + +void PandaGen::GreaterThan(const ir::AstNode *node, VReg lhs) +{ + ra_.Emit(node, 0, lhs); +} + +void PandaGen::GreaterEqual(const ir::AstNode *node, VReg lhs) +{ + ra_.Emit(node, 0, lhs); +} + +void PandaGen::IsTrue(const ir::AstNode *node) +{ + sa_.Emit(node); +} + void PandaGen::BranchIfUndefined(const ir::AstNode *node, Label *target) { RegScope rs(this); VReg tmp = AllocReg(); StoreAccumulator(node, tmp); - sa_.Emit(node); - ra_.Emit(node, tmp); + LoadConst(node, Constant::JS_UNDEFINED); + Equal(node, tmp); sa_.Emit(node, target); } @@ -919,8 +1005,8 @@ void PandaGen::BranchIfNotUndefined(const ir::AstNode *node, Label *target) RegScope rs(this); VReg tmp = AllocReg(); StoreAccumulator(node, tmp); - sa_.Emit(node); - ra_.Emit(node, tmp); + LoadConst(node, Constant::JS_UNDEFINED); + Equal(node, tmp); sa_.Emit(node, target); } @@ -930,31 +1016,31 @@ void PandaGen::BranchIfStrictNotUndefined(const ir::AstNode *node, class Label * VReg tmp = AllocReg(); StoreAccumulator(node, tmp); LoadConst(node, Constant::JS_UNDEFINED); - ra_.Emit(node, tmp); + StrictEqual(node, tmp); sa_.Emit(node, target); } void PandaGen::BranchIfTrue(const ir::AstNode *node, Label *target) { - sa_.Emit(node); + IsTrue(node); sa_.Emit(node, target); } void PandaGen::BranchIfNotTrue(const ir::AstNode *node, Label *target) { - sa_.Emit(node); + IsTrue(node); BranchIfFalse(node, target); } void PandaGen::BranchIfFalse(const ir::AstNode *node, Label *target) { - sa_.Emit(node); + sa_.Emit(node); sa_.Emit(node, target); } void PandaGen::EmitThrow(const ir::AstNode *node) { - sa_.Emit(node); + sa_.Emit(node); } void PandaGen::EmitRethrow(const ir::AstNode *node) @@ -970,24 +1056,24 @@ void PandaGen::EmitRethrow(const ir::AstNode *node) StoreConst(node, hole, Constant::JS_HOLE); LoadAccumulator(node, exception); - ra_.Emit(node, hole); + NotEqual(node, hole); sa_.Emit(node, skipThrow); SetLabel(node, doThrow); LoadAccumulator(node, exception); - sa_.Emit(node); + EmitThrow(node); SetLabel(node, skipThrow); } void PandaGen::EmitReturn(const ir::AstNode *node) { - sa_.Emit(node); + sa_.Emit(node); } void PandaGen::EmitReturnUndefined(const ir::AstNode *node) { - sa_.Emit(node); + sa_.Emit(node); } void PandaGen::ImplicitReturn(const ir::AstNode *node) @@ -1033,38 +1119,78 @@ void PandaGen::EmitAwait(const ir::AstNode *node) void PandaGen::CallThis(const ir::AstNode *node, VReg startReg, size_t argCount) { - rra_.Emit(node, startReg, argCount + 2, static_cast(argCount), startReg); + LoadAccumulator(node, startReg); // callee is load to acc + VReg thisReg = startReg + 1; + switch (argCount) { + case 1: { // no args + ra_.Emit(node, 0, thisReg); + break; + } + case 2: { // 1 arg + VReg arg0 = thisReg + 1; + ra_.Emit(node, 0, thisReg, arg0); + break; + } + case 3: { // 2 args + VReg arg0 = thisReg + 1; + VReg arg1 = arg0 + 1; + ra_.Emit(node, 0, thisReg , arg0, arg1); + break; + } + case 4: { // 3 args + VReg arg0 = thisReg + 1; + VReg arg1 = arg0 + 1; + VReg arg2 = arg1 + 1; + ra_.Emit(node, 0, thisReg , arg0, arg1, arg2); + break; + } + default: { + int64_t actualArgs = argCount - 1; + if (actualArgs <= util::Helpers::MAX_INT8) { + rra_.Emit(node, thisReg, argCount + 1, 0, actualArgs, thisReg); + break; + } + + rra_.Emit(node, thisReg, argCount + 1, actualArgs, thisReg); + break; + } + } } void PandaGen::Call(const ir::AstNode *node, VReg startReg, size_t argCount) { - VReg callee = startReg; - + LoadAccumulator(node, startReg); // callee is load to acc switch (argCount) { case 0: { // 0 args - ra_.Emit(node, callee); + sa_.Emit(node, 0); break; } case 1: { // 1 arg - VReg arg0 = callee + 1; - ra_.Emit(node, callee, arg0); + VReg arg0 = startReg + 1; + ra_.Emit(node, 0, arg0); break; } case 2: { // 2 args - VReg arg0 = callee + 1; + VReg arg0 = startReg + 1; VReg arg1 = arg0 + 1; - ra_.Emit(node, callee, arg0, arg1); + ra_.Emit(node, 0, arg0, arg1); break; } case 3: { // 3 args - VReg arg0 = callee + 1; + VReg arg0 = startReg + 1; VReg arg1 = arg0 + 1; VReg arg2 = arg1 + 1; - ra_.Emit(node, callee, arg0, arg1, arg2); + ra_.Emit(node, 0, arg0, arg1, arg2); break; } default: { - rra_.Emit(node, startReg, argCount + 1, static_cast(argCount), startReg); + VReg arg0 = startReg + 1; + if (argCount <= util::Helpers::MAX_INT8) { + rra_.Emit(node, arg0, argCount, 0, argCount, arg0); + break; + } + + rra_.Emit(node, arg0, argCount, argCount, arg0); break; } } @@ -1072,22 +1198,38 @@ void PandaGen::Call(const ir::AstNode *node, VReg startReg, size_t argCount) void PandaGen::SuperCall(const ir::AstNode *node, VReg startReg, size_t argCount) { - rra_.Emit(node, startReg, argCount, static_cast(argCount), startReg); + if (RootNode()->AsScriptFunction()->IsArrow()) { + GetFunctionObject(node); // load funcobj to acc for super call in arrow function + if (argCount <= util::Helpers::MAX_INT8) { + rra_.Emit(node, startReg, argCount, 0, static_cast(argCount), startReg); + } else { + rra_.Emit(node, startReg, argCount, static_cast(argCount), startReg); + } + return; + } + + if (argCount <= util::Helpers::MAX_INT8) { + // no need to load funcobj to acc for super call in other kinds of functions + rra_.Emit(node, startReg, argCount, 0, static_cast(argCount), startReg); + return; + } + + rra_.Emit(node, startReg, argCount, static_cast(argCount), startReg); } void PandaGen::SuperCallSpread(const ir::AstNode *node, VReg vs) { - ra_.Emit(node, vs); + ra_.Emit(node, 0, vs); } void PandaGen::NewObject(const ir::AstNode *node, VReg startReg, size_t argCount) { - rra_.Emit(node, startReg, argCount, static_cast(argCount), startReg); -} + if (argCount <= util::Helpers::MAX_INT8) { + rra_.Emit(node, startReg, argCount, 0, static_cast(argCount), startReg); + return; + } -void PandaGen::LoadHomeObject(const ir::AstNode *node) -{ - sa_.Emit(node); + rra_.Emit(node, startReg, argCount, static_cast(argCount), startReg); } void PandaGen::DefineFunction(const ir::AstNode *node, const ir::ScriptFunction *realNode, const util::StringView &name) @@ -1098,20 +1240,9 @@ void PandaGen::DefineFunction(const ir::AstNode *node, const ir::ScriptFunction auto formalParamCnt = realNode->FormalParamsLength(); if (realNode->IsMethod()) { - ra_.Emit(node, name, static_cast(formalParamCnt), LexEnv()); - } else if (realNode->IsAsync()) { - if (realNode->IsGenerator()) { - // TODO(): async generator - } else { - ra_.Emit(node, name, static_cast(formalParamCnt), LexEnv()); - } - } else if (realNode->IsGenerator()) { - ra_.Emit(node, name, static_cast(formalParamCnt), LexEnv()); - } else if (realNode->IsArrow()) { - LoadHomeObject(node); - ra_.Emit(node, name, static_cast(formalParamCnt), LexEnv()); - } else { - ra_.Emit(node, name, static_cast(formalParamCnt), LexEnv()); + ra_.Emit(node, 0, name, static_cast(formalParamCnt)); + } else { + ra_.Emit(node, 0, name, static_cast(formalParamCnt)); } strings_.insert(name); @@ -1119,22 +1250,23 @@ void PandaGen::DefineFunction(const ir::AstNode *node, const ir::ScriptFunction void PandaGen::TypeOf(const ir::AstNode *node) { - sa_.Emit(node); + sa_.Emit(node, 0); } void PandaGen::CallSpread(const ir::AstNode *node, VReg func, VReg thisReg, VReg args) { - ra_.Emit(node, func, thisReg, args); + LoadAccumulator(node, func); // callee is load to acc + ra_.Emit(node, 0, thisReg, args); } -void PandaGen::NewObjSpread(const ir::AstNode *node, VReg obj, VReg target) +void PandaGen::NewObjSpread(const ir::AstNode *node, VReg obj) { - ra_.Emit(node, obj, target); + ra_.Emit(node, 0, obj); } void PandaGen::GetUnmappedArgs(const ir::AstNode *node) { - sa_.Emit(node); + sa_.Emit(node); } void PandaGen::Negate(const ir::AstNode *node) @@ -1151,35 +1283,34 @@ void PandaGen::Negate(const ir::AstNode *node) void PandaGen::ToNumber(const ir::AstNode *node, VReg arg) { - ra_.Emit(node, arg); + LoadAccumulator(node, arg); + sa_.Emit(node, 0); } void PandaGen::ToNumeric(const ir::AstNode *node, VReg arg) { - ra_.Emit(node, arg); + LoadAccumulator(node, arg); + sa_.Emit(node, 0); } void PandaGen::CreateGeneratorObj(const ir::AstNode *node, VReg funcObj) { - ra_.Emit(node, funcObj); + ra_.Emit(node, funcObj); } void PandaGen::CreateAsyncGeneratorObj(const ir::AstNode *node, VReg funcObj) { - /* - * TODO: async generator - * ra_.Emit(node, funcObj); - */ + ra_.Emit(node, funcObj); } void PandaGen::CreateIterResultObject(const ir::AstNode *node, VReg value, VReg done) { - ra_.Emit(node, value, done); + ra_.Emit(node, value, done); } -void PandaGen::SuspendGenerator(const ir::AstNode *node, VReg genObj, VReg iterResult) +void PandaGen::SuspendGenerator(const ir::AstNode *node, VReg genObj) { - ra_.Emit(node, genObj, iterResult); + ra_.Emit(node, genObj); // iterResult is in acc } void PandaGen::SuspendAsyncGenerator(const ir::AstNode *node, VReg asyncGenObj) @@ -1208,114 +1339,109 @@ void PandaGen::GeneratorComplete(const ir::AstNode *node, VReg genObj) void PandaGen::ResumeGenerator(const ir::AstNode *node, VReg genObj) { - ra_.Emit(node, genObj); + LoadAccumulator(node, genObj); + sa_.Emit(node); } void PandaGen::GetResumeMode(const ir::AstNode *node, VReg genObj) { - ra_.Emit(node, genObj); + LoadAccumulator(node, genObj); + sa_.Emit(node); } void PandaGen::AsyncFunctionEnter(const ir::AstNode *node) { - sa_.Emit(node); + sa_.Emit(node); } -void PandaGen::AsyncFunctionAwait(const ir::AstNode *node, VReg asyncFuncObj, VReg retVal) +void PandaGen::AsyncFunctionAwait(const ir::AstNode *node, VReg asyncFuncObj) { - ra_.Emit(node, asyncFuncObj, retVal); + ra_.Emit(node, asyncFuncObj); // receivedValue is in acc } -void PandaGen::AsyncFunctionResolve(const ir::AstNode *node, VReg asyncFuncObj, VReg value, VReg canSuspend) +void PandaGen::AsyncFunctionResolve(const ir::AstNode *node, VReg asyncFuncObj) { - ra_.Emit(node, asyncFuncObj, canSuspend, value); + ra_.Emit(node, asyncFuncObj); // use retVal in acc } -void PandaGen::AsyncFunctionReject(const ir::AstNode *node, VReg asyncFuncObj, VReg value, VReg canSuspend) +void PandaGen::AsyncFunctionReject(const ir::AstNode *node, VReg asyncFuncObj) { - ra_.Emit(node, asyncFuncObj, canSuspend, value); + ra_.Emit(node, asyncFuncObj); // exception is in acc } -void PandaGen::AsyncGeneratorResolve(const ir::AstNode *node, VReg asyncGenObj) +void PandaGen::AsyncGeneratorResolve(const ir::AstNode *node, VReg asyncGenObj, VReg value, VReg canSuspend) { - /* - * TODO: async generator resolve - * ra_.Emit(node, asyncGenObj); - */ + ra_.Emit(node, asyncGenObj, value, canSuspend); } void PandaGen::AsyncGeneratorReject(const ir::AstNode *node, VReg asyncGenObj) { - /* - * TODO: async generator reject - * ra_.Emit(node, asyncGenObj); - */ + ra_.Emit(node, asyncGenObj); // value is in acc } void PandaGen::GetTemplateObject(const ir::AstNode *node, VReg value) { - ra_.Emit(node, value); + LoadAccumulator(node, value); + sa_.Emit(node, 0); } void PandaGen::CopyRestArgs(const ir::AstNode *node, uint32_t index) { - sa_.Emit(node, index); + index <= util::Helpers::MAX_INT8 ? sa_.Emit(node, index) : sa_.Emit(node, index); } void PandaGen::GetPropIterator(const ir::AstNode *node) { - sa_.Emit(node); + sa_.Emit(node); } void PandaGen::GetNextPropName(const ir::AstNode *node, VReg iter) { - ra_.Emit(node, iter); + ra_.Emit(node, iter); } void PandaGen::CreateEmptyObject(const ir::AstNode *node) { - sa_.Emit(node); + sa_.Emit(node); } void PandaGen::CreateObjectWithBuffer(const ir::AstNode *node, uint32_t idx) { ASSERT(util::Helpers::IsInteger(idx)); - sa_.Emit(node, idx); -} - -void PandaGen::CreateObjectHavingMethod(const ir::AstNode *node, uint32_t idx) -{ - ASSERT(util::Helpers::IsInteger(idx)); - LoadAccumulator(node, LexEnv()); - sa_.Emit(node, idx); + std::string idxStr = std::string(context_->RecordName()) + std::to_string(idx); + util::UString litId(idxStr, allocator_); + sa_.Emit(node, 0, litId.View()); } void PandaGen::SetObjectWithProto(const ir::AstNode *node, VReg proto, VReg obj) { - ra_.Emit(node, proto, obj); + LoadAccumulator(node, obj); + ra_.Emit(node, 0, proto); } -void PandaGen::CopyDataProperties(const ir::AstNode *node, VReg dst, VReg src) +void PandaGen::CopyDataProperties(const ir::AstNode *node, VReg dst) { - ra_.Emit(node, dst, src); + ra_.Emit(node, dst); // use acc as srcObj } void PandaGen::DefineGetterSetterByValue(const ir::AstNode *node, VReg obj, VReg name, VReg getter, VReg setter, bool setName) { LoadConst(node, setName ? Constant::JS_TRUE : Constant::JS_FALSE); - ra_.Emit(node, obj, name, getter, setter); + ra_.Emit(node, obj, name, getter, setter); } void PandaGen::CreateEmptyArray(const ir::AstNode *node) { - sa_.Emit(node); + sa_.Emit(node, 0); } void PandaGen::CreateArrayWithBuffer(const ir::AstNode *node, uint32_t idx) { ASSERT(util::Helpers::IsInteger(idx)); - sa_.Emit(node, idx); + std::string idxStr = std::string(context_->RecordName()) + std::to_string(idx); + util::UString litId(idxStr, allocator_); + sa_.Emit(node, 0, litId.View()); } void PandaGen::CreateArray(const ir::AstNode *node, const ArenaVector &elements, VReg obj) @@ -1416,22 +1542,22 @@ void PandaGen::CreateArray(const ir::AstNode *node, const ArenaVector(node, array, index); + ra_.Emit(node, array, index); } void PandaGen::ThrowIfNotObject(const ir::AstNode *node, VReg obj) { - ra_.Emit(node, obj); + ra_.Emit(node, obj); } void PandaGen::ThrowThrowNotExist(const ir::AstNode *node) { - sa_.Emit(node); + sa_.Emit(node); } void PandaGen::GetIterator(const ir::AstNode *node) { - sa_.Emit(node); + sa_.Emit(node, 0); } void PandaGen::GetAsyncIterator(const ir::AstNode *node) @@ -1451,71 +1577,89 @@ void PandaGen::CreateObjectWithExcludedKeys(const ir::AstNode *node, VReg obj, V } size_t argRegCnt = (argCount == 0 ? argCount : argCount - 1); - rra_.Emit(node, argStart, argCount, static_cast(argRegCnt), obj, - argStart); + + if (argRegCnt <= util::Helpers::MAX_INT8) { + rra_.Emit(node, argStart, argCount, static_cast(argRegCnt), + obj, argStart); + return; + } + + rra_.Emit(node, argStart, argCount, static_cast(argRegCnt), + obj, argStart); } void PandaGen::ThrowObjectNonCoercible(const ir::AstNode *node) { - sa_.Emit(node); + sa_.Emit(node); } void PandaGen::CloseIterator(const ir::AstNode *node, VReg iter) { - ra_.Emit(node, iter); + ra_.Emit(node, 0, iter); } -void PandaGen::DefineClassWithBuffer(const ir::AstNode *node, const util::StringView &ctorId, int32_t litIdx, - VReg lexenv, VReg base) +void PandaGen::DefineClassWithBuffer(const ir::AstNode *node, const util::StringView &ctorId, int32_t litIdx, VReg base) { auto formalParamCnt = node->AsClassDefinition()->Ctor()->Function()->FormalParamsLength(); - ra_.Emit(node, ctorId, litIdx, static_cast(formalParamCnt), lexenv, base); + std::string idxStr = std::string(context_->RecordName()) + std::to_string(litIdx); + util::UString litId(idxStr, allocator_); + ra_.Emit(node, 0, ctorId, litId.View(), static_cast(formalParamCnt), base); strings_.insert(ctorId); } -void PandaGen::LoadModuleVariable(const ir::AstNode *node, const util::StringView &name, bool isLocalExport) +void PandaGen::LoadLocalModuleVariable(const ir::AstNode *node, const binder::ModuleVariable *variable) { - ra_.Emit(node, name, isLocalExport ? static_cast(1) : static_cast(0)); - strings_.insert(name); + auto index = variable->Index(); + index <= util::Helpers::MAX_INT8 ? sa_.Emit(node, index) : + sa_.Emit(node, index); } -void PandaGen::StoreModuleVariable(const ir::AstNode *node, const util::StringView &name) +void PandaGen::LoadExternalModuleVariable(const ir::AstNode *node, const binder::ModuleVariable *variable) { - sa_.Emit(node, name); - strings_.insert(name); + auto index = variable->Index(); + index <= util::Helpers::MAX_INT8 ? sa_.Emit(node, index) : + sa_.Emit(node, index); } -void PandaGen::GetModuleNamespace(const ir::AstNode *node, const util::StringView &name) +void PandaGen::StoreModuleVariable(const ir::AstNode *node, const binder::ModuleVariable *variable) { - sa_.Emit(node, name); - strings_.insert(name); + auto index = variable->Index(); + index <= util::Helpers::MAX_INT8 ? sa_.Emit(node, index) : + sa_.Emit(node, index); } -void PandaGen::DynamicImportCall(const ir::AstNode *node, VReg moduleSpecifier) +void PandaGen::GetModuleNamespace(const ir::AstNode *node, uint32_t index) { - ra_.Emit(node, moduleSpecifier); + index <= util::Helpers::MAX_INT8 ? sa_.Emit(node, index) : + sa_.Emit(node, index); +} + +void PandaGen::DynamicImportCall(const ir::AstNode *node) +{ + ra_.Emit(node); } void PandaGen::StSuperByName(const ir::AstNode *node, VReg obj, const util::StringView &key) { - ra_.Emit(node, key, obj); + ra_.Emit(node, 0, key, obj); strings_.insert(key); } void PandaGen::LdSuperByName(const ir::AstNode *node, VReg obj, const util::StringView &key) { - ra_.Emit(node, key, obj); + LoadAccumulator(node, obj); // object is load to acc + sa_.Emit(node, 0, key); strings_.insert(key); } void PandaGen::StSuperByValue(const ir::AstNode *node, VReg obj, VReg prop) { - ra_.Emit(node, obj, prop); + ra_.Emit(node, 0, obj, prop); } -void PandaGen::LdSuperByValue(const ir::AstNode *node, VReg obj, VReg prop) +void PandaGen::LdSuperByValue(const ir::AstNode *node, VReg obj) { - ra_.Emit(node, obj, prop); + ra_.Emit(node, 0, obj); // prop is in acc } void PandaGen::StoreSuperProperty(const ir::AstNode *node, VReg obj, const Operand &prop) @@ -1550,63 +1694,80 @@ void PandaGen::LoadSuperProperty(const ir::AstNode *node, VReg obj, const Operan } if (std::holds_alternative(prop)) { - LdSuperByValue(node, obj, std::get(prop)); + LoadAccumulator(node, std::get(prop)); + LdSuperByValue(node, obj); return; } ASSERT(std::holds_alternative(prop)); - RegScope rs(this); LoadAccumulatorInt(node, static_cast(std::get(prop))); - VReg property = AllocReg(); - StoreAccumulator(node, property); - LdSuperByValue(node, obj, property); + LdSuperByValue(node, obj); } void PandaGen::LoadLexicalVar(const ir::AstNode *node, uint32_t level, uint32_t slot) { - sa_.Emit(node, level, slot); + if ((level > util::Helpers::MAX_INT8) || (slot > util::Helpers::MAX_INT8)) { + sa_.Emit(node, level, slot); + return; + } + + sa_.Emit(node, level, slot); } 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)); - sa_.Emit(node, patchSlot); + sa_.Emit(node, patchSlot); + return; + } + + if ((level > util::Helpers::MAX_INT8) || (slot > util::Helpers::MAX_INT8)) { + sa_.Emit(node, level, slot); return; } - sa_.Emit(node, level, slot); + + sa_.Emit(node, level, slot); } void PandaGen::StoreLexicalVar(const ir::AstNode *node, uint32_t level, uint32_t slot) { - RegScope rs(this); - VReg value = AllocReg(); - StoreAccumulator(node, value); - ra_.Emit(node, level, slot, value); + if ((level > util::Helpers::MAX_INT8) || (slot > util::Helpers::MAX_INT8)) { + ra_.Emit(node, level, slot); + return; + } + + ra_.Emit(node, level, slot); } void PandaGen::StoreLexicalVar(const ir::AstNode *node, uint32_t level, uint32_t slot, VReg value) { - ra_.Emit(node, level, slot, value); + LoadAccumulator(node, value); + if ((level > util::Helpers::MAX_INT8) || (slot > util::Helpers::MAX_INT8)) { + ra_.Emit(node, level, slot); + return; + } + + ra_.Emit(node, level, slot); } void PandaGen::StoreLexicalVar(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)); - sa_.Emit(node, patchSlot); + sa_.Emit(node, patchSlot); return; } RegScope rs(this); VReg value = AllocReg(); StoreAccumulator(node, value); - ra_.Emit(node, level, slot, value); + StoreLexicalVar(node, level, slot, value); } void PandaGen::ThrowIfSuperNotCorrectCall(const ir::AstNode *node, int64_t num) { - sa_.Emit(node, num); + sa_.Emit(node, num); } void PandaGen::ThrowUndefinedIfHole(const ir::AstNode *node, const util::StringView &name) @@ -1617,7 +1778,7 @@ void PandaGen::ThrowUndefinedIfHole(const ir::AstNode *node, const util::StringV LoadAccumulatorString(node, name); VReg nameReg = AllocReg(); StoreAccumulator(node, nameReg); - ra_.Emit(node, holeReg, nameReg); + ra_.Emit(node, holeReg, nameReg); LoadAccumulator(node, holeReg); strings_.insert(name); } @@ -1628,13 +1789,13 @@ void PandaGen::ThrowConstAssignment(const ir::AstNode *node, const util::StringV LoadAccumulatorString(node, name); VReg nameReg = AllocReg(); StoreAccumulator(node, nameReg); - ra_.Emit(node, nameReg); + ra_.Emit(node, nameReg); strings_.insert(name); } void PandaGen::PopLexEnv(const ir::AstNode *node) { - sa_.Emit(node); + sa_.Emit(node); } void PandaGen::CopyLexEnv(const ir::AstNode *node) @@ -1658,17 +1819,15 @@ void PandaGen::NewLexicalEnv(const ir::AstNode *node, uint32_t num, binder::Vari void PandaGen::NewLexEnv(const ir::AstNode *node, uint32_t num) { - sa_.Emit(node, num); + num <= util::Helpers::MAX_INT8 ? sa_.Emit(node, num) : sa_.Emit(node, num); } void PandaGen::NewLexEnvWithScopeInfo(const ir::AstNode *node, uint32_t num, int32_t scopeInfoIdx) { - sa_.Emit(node, num, scopeInfoIdx); -} - -void PandaGen::LdLexEnv(const ir::AstNode *node) -{ - sa_.Emit(node); + std::string idxStr = std::string(context_->RecordName()) + std::to_string(scopeInfoIdx); + util::UString litId(idxStr, allocator_); + num <= util::Helpers::MAX_INT8 ? sa_.Emit(node, num, litId.View()) : + sa_.Emit(node, num, litId.View()); } uint32_t PandaGen::TryDepth() const @@ -1786,21 +1945,15 @@ VReg PandaGen::LoadPropertyKey(const ir::Expression *prop, bool isComputed) return propReg; } -void PandaGen::StLetToGlobalRecord(const ir::AstNode *node, const util::StringView &name) +void PandaGen::StLetOrClassToGlobalRecord(const ir::AstNode *node, const util::StringView &name) { - sa_.Emit(node, name); + sa_.Emit(node, 0, name); strings_.insert(name); } void PandaGen::StConstToGlobalRecord(const ir::AstNode *node, const util::StringView &name) { - sa_.Emit(node, name); - strings_.insert(name); -} - -void PandaGen::StClassToGlobalRecord(const ir::AstNode *node, const util::StringView &name) -{ - sa_.Emit(node, name); + sa_.Emit(node, 0, name); strings_.insert(name); } diff --git a/es2panda/compiler/core/pandagen.h b/es2panda/compiler/core/pandagen.h index 64fe2d6132bd853e72f05f55102588d262f135a5..1334ff54f6a0d9adff02e0280482425850e6d43f 100644 --- a/es2panda/compiler/core/pandagen.h +++ b/es2panda/compiler/core/pandagen.h @@ -16,18 +16,21 @@ #ifndef ES2PANDA_COMPILER_CORE_PANDAGEN_H #define ES2PANDA_COMPILER_CORE_PANDAGEN_H +#include #include #include #include #include #include #include +#include #include #include namespace panda::es2panda::binder { class FunctionScope; +class ModuleVaribale; class ScopeFindResult; class Scope; } // namespace panda::es2panda::binder @@ -174,6 +177,11 @@ public: return buffStorage_; } + OptionalChain *GetOptionalChain() const + { + return optionalChain_; + } + uint32_t IcSize() const { return ic_.Size(); @@ -186,6 +194,13 @@ public: rra_.SetSourceLocationFlag(flag); } + panda::panda_file::FunctionKind GetFunctionKind() const + { + return funcKind_; + } + + void SetFunctionKind(); + bool IsDebug() const; bool isDebuggerEvaluateExpressionMode() const; std::string SourceFile() const; @@ -198,8 +213,6 @@ public: Label *AllocLabel(); - VReg LexEnv() const; - bool FunctionHasFinalizer() const; void FunctionInit(CatchTable* catchTable); void FunctionEnter(); @@ -207,9 +220,9 @@ public: LiteralBuffer *NewLiteralBuffer(); int32_t AddLiteralBuffer(LiteralBuffer *buf); - int32_t AddLexicalVarNamesForDebugInfo(ArenaMap> &lexicalMap); + int32_t AddLexicalVarNamesForDebugInfo(ArenaMap> &lexicalVars); - void InitializeLexEnv(const ir::AstNode *node, VReg lexEnv); + void InitializeLexEnv(const ir::AstNode *node); void CopyFunctionArguments(const ir::AstNode *node); void GetFunctionObject(const ir::AstNode *node); void GetNewTarget(const ir::AstNode *node); @@ -218,9 +231,8 @@ public: void LoadVar(const ir::Identifier *node, const binder::ScopeFindResult &result); void StoreVar(const ir::AstNode *node, const binder::ScopeFindResult &result, bool isDeclaration); - void StLetToGlobalRecord(const ir::AstNode *node, const util::StringView &name); + void StLetOrClassToGlobalRecord(const ir::AstNode *node, const util::StringView &name); void StConstToGlobalRecord(const ir::AstNode *node, const util::StringView &name); - void StClassToGlobalRecord(const ir::AstNode *node, const util::StringView &name); void StoreAccumulator(const ir::AstNode *node, VReg vreg); void LoadAccFromArgs(const ir::AstNode *node); @@ -234,7 +246,6 @@ public: void LoadAccumulator(const ir::AstNode *node, VReg reg); void LoadGlobalVar(const ir::AstNode *node, const util::StringView &name); void StoreGlobalVar(const ir::AstNode *node, const util::StringView &name); - void StoreGlobalLet(const ir::AstNode *node, const util::StringView &name); void TryLoadGlobalByValue(const ir::AstNode *node, VReg key); void TryStoreGlobalByValue(const ir::AstNode *node, VReg key); @@ -258,13 +269,22 @@ public: void SetLabel(const ir::AstNode *node, Label *label); void Branch(const ir::AstNode *node, class Label *label); - bool CheckControlFlowChange(); + bool CheckControlFlowChange() const; Label *ControlFlowChangeBreak(const ir::Identifier *label = nullptr); Label *ControlFlowChangeContinue(const ir::Identifier *label); void Condition(const ir::AstNode *node, lexer::TokenType op, VReg lhs, class Label *ifFalse); void Unary(const ir::AstNode *node, lexer::TokenType op, VReg operand); void Binary(const ir::AstNode *node, lexer::TokenType op, VReg lhs); + void Equal(const ir::AstNode *node, VReg lhs); + void NotEqual(const ir::AstNode *node, VReg lhs); + void StrictEqual(const ir::AstNode *node, VReg lhs); + void StrictNotEqual(const ir::AstNode *node, VReg lhs); + void LessThan(const ir::AstNode *node, VReg lhs); + void LessEqual(const ir::AstNode *node, VReg lhs); + void GreaterThan(const ir::AstNode *node, VReg lhs); + void GreaterEqual(const ir::AstNode *node, VReg lhs); + void IsTrue(const ir::AstNode *node); void BranchIfUndefined(const ir::AstNode *node, class Label *target); void BranchIfStrictNotUndefined(const ir::AstNode *node, class Label *target); @@ -290,12 +310,11 @@ public: void SuperCall(const ir::AstNode *node, VReg startReg, size_t argCount); void SuperCallSpread(const ir::AstNode *node, VReg vs); - void LoadHomeObject(const ir::AstNode *node); void NewObject(const ir::AstNode *node, VReg startReg, size_t argCount); void DefineFunction(const ir::AstNode *node, const ir::ScriptFunction *realNode, const util::StringView &name); void TypeOf(const ir::AstNode *node); - void NewObjSpread(const ir::AstNode *node, VReg obj, VReg target); + void NewObjSpread(const ir::AstNode *node, VReg obj); void GetUnmappedArgs(const ir::AstNode *node); void Negate(const ir::AstNode *node); @@ -307,18 +326,18 @@ public: void GetResumeMode(const ir::AstNode *node, VReg genObj); void AsyncFunctionEnter(const ir::AstNode *node); - void AsyncFunctionAwait(const ir::AstNode *node, VReg asyncFuncObj, VReg retVal); - void AsyncFunctionResolve(const ir::AstNode *node, VReg asyncFuncObj, VReg value, VReg canSuspend); - void AsyncFunctionReject(const ir::AstNode *node, VReg asyncFuncObj, VReg value, VReg canSuspend); + void AsyncFunctionAwait(const ir::AstNode *node, VReg asyncFuncObj); + void AsyncFunctionResolve(const ir::AstNode *node, VReg asyncFuncObj); + void AsyncFunctionReject(const ir::AstNode *node, VReg asyncFuncObj); void GeneratorYield(const ir::AstNode *node, VReg genObj); void GeneratorComplete(const ir::AstNode *node, VReg genObj); void CreateAsyncGeneratorObj(const ir::AstNode *node, VReg funcObj); void CreateIterResultObject(const ir::AstNode *node, VReg value, VReg done); - void SuspendGenerator(const ir::AstNode *node, VReg genObj, VReg iterResult); + void SuspendGenerator(const ir::AstNode *node, VReg genObj); void SuspendAsyncGenerator(const ir::AstNode *node, VReg asyncGenObj); - void AsyncGeneratorResolve(const ir::AstNode *node, VReg asyncGenObj); + void AsyncGeneratorResolve(const ir::AstNode *node, VReg asyncGenObj, VReg value, VReg canSuspend); void AsyncGeneratorReject(const ir::AstNode *node, VReg asyncGenObj); void GetTemplateObject(const ir::AstNode *node, VReg value); @@ -328,9 +347,8 @@ public: void GetNextPropName(const ir::AstNode *node, VReg iter); void CreateEmptyObject(const ir::AstNode *node); void CreateObjectWithBuffer(const ir::AstNode *node, uint32_t idx); - void CreateObjectHavingMethod(const ir::AstNode *node, uint32_t idx); void SetObjectWithProto(const ir::AstNode *node, VReg proto, VReg obj); - void CopyDataProperties(const ir::AstNode *node, VReg dst, VReg src); + void CopyDataProperties(const ir::AstNode *node, VReg dst); void DefineGetterSetterByValue(const ir::AstNode *node, VReg obj, VReg name, VReg getter, VReg setter, bool setName); void CreateEmptyArray(const ir::AstNode *node); @@ -346,22 +364,21 @@ public: void CreateObjectWithExcludedKeys(const ir::AstNode *node, VReg obj, VReg argStart, size_t argCount); void ThrowObjectNonCoercible(const ir::AstNode *node); void CloseIterator(const ir::AstNode *node, VReg iter); - void DefineClassWithBuffer(const ir::AstNode *node, const util::StringView &ctorId, int32_t litIdx, VReg lexenv, - VReg base); + void DefineClassWithBuffer(const ir::AstNode *node, const util::StringView &ctorId, int32_t litIdx, VReg base); - void LoadModuleVariable(const ir::AstNode *node, const util::StringView &name, bool isLocalExport); - void StoreModuleVariable(const ir::AstNode *node, const util::StringView &name); - void GetModuleNamespace(const ir::AstNode *node, const util::StringView &name); - void DynamicImportCall(const ir::AstNode *node, VReg moduleSpecifier); + void LoadLocalModuleVariable(const ir::AstNode *node, const binder::ModuleVariable *variable); + void LoadExternalModuleVariable(const ir::AstNode *node, const binder::ModuleVariable *variable); + void StoreModuleVariable(const ir::AstNode *node, const binder::ModuleVariable *variable); + void GetModuleNamespace(const ir::AstNode *node, uint32_t index); + void DynamicImportCall(const ir::AstNode *node); void StSuperByName(const ir::AstNode *node, VReg obj, const util::StringView &key); void LdSuperByName(const ir::AstNode *node, VReg obj, const util::StringView &key); void StSuperByValue(const ir::AstNode *node, VReg obj, VReg prop); - void LdSuperByValue(const ir::AstNode *node, VReg obj, VReg prop); + void LdSuperByValue(const ir::AstNode *node, VReg obj); void StoreSuperProperty(const ir::AstNode *node, VReg obj, const Operand &prop); void LoadSuperProperty(const ir::AstNode *node, VReg obj, const Operand &prop); - void LdLexEnv(const ir::AstNode *node); void PopLexEnv(const ir::AstNode *node); void CopyLexEnv(const ir::AstNode *node); void NewLexicalEnv(const ir::AstNode *node, uint32_t num, binder::VariableScope *scope); @@ -382,7 +399,7 @@ public: void SortCatchTables(); void LoadObjByIndex(const ir::AstNode *node, VReg obj, int64_t index); - void LoadObjByValue(const ir::AstNode *node, VReg obj, VReg prop); + void LoadObjByValue(const ir::AstNode *node, VReg obj); void StoreObjByName(const ir::AstNode *node, VReg obj, const util::StringView &prop); void StoreObjByIndex(const ir::AstNode *node, VReg obj, int64_t index); @@ -416,6 +433,16 @@ public: throw Error(ErrorType::GENERIC, "Unimplemented code path"); } + IcSizeType GetCurrentSlot() const + { + return currentSlot_; + } + + void IncreaseCurrentSlot(ICSlot inc) + { + currentSlot_ += inc; + } + private: ArenaAllocator *allocator_; CompilerContext *context_; @@ -430,10 +457,12 @@ private: ArenaVector buffStorage_; EnvScope *envScope_ {}; DynamicContext *dynamicContext_ {}; + OptionalChain *optionalChain_ {}; InlineCache ic_; SimpleAllocator sa_; RegAllocator ra_; RangeRegAllocator rra_; + IcSizeType currentSlot_ {0}; uint32_t usedRegs_ {0}; uint32_t totalRegs_ {0}; @@ -446,7 +475,9 @@ private: friend class EnvScope; friend class LoopEnvScope; friend class DynamicContext; + friend class OptionalChain; size_t labelId_ {0}; + panda::panda_file::FunctionKind funcKind_ {panda::panda_file::FunctionKind::NONE}; }; } // namespace panda::es2panda::compiler diff --git a/es2panda/compiler/core/regAllocator.cpp b/es2panda/compiler/core/regAllocator.cpp index 1601722e66e1080bf507fe7015f1136c82073397..01f3f81ebad6c75d7f63b52f373fbd1aa3cae358 100644 --- a/es2panda/compiler/core/regAllocator.cpp +++ b/es2panda/compiler/core/regAllocator.cpp @@ -21,7 +21,7 @@ namespace panda::es2panda::compiler { -// RegAllocatorBase +// AllocatorBase void AllocatorBase::PushBack(IRNode *ins) { @@ -33,12 +33,10 @@ ArenaAllocator *AllocatorBase::Allocator() const return pg_->Allocator(); } -// SimpleAllocator - -Label *SimpleAllocator::AllocLabel(std::string &&id) +void AllocatorBase::UpdateIcSlot(IRNode *node) { - const auto *lastInsNode = pg_->Insns().empty() ? FIRST_NODE_OF_FUNCTION : pg_->Insns().back()->Node(); - return Alloc