diff --git a/es2panda/compiler/core/emitter.cpp b/es2panda/compiler/core/emitter.cpp index ac04127360e7dd7c2b6bba3e29f049b18963d528..94129c54462ed950c793ed6304bd958d6e477266 100644 --- a/es2panda/compiler/core/emitter.cpp +++ b/es2panda/compiler/core/emitter.cpp @@ -115,6 +115,11 @@ void FunctionEmitter::GenBufferLiterals(const LiteralBuffer *buff) valueLit.value_ = literal->GetMethod().Mutf8(); break; } + case ir::LiteralTag::METHODAFFILIATE: { + valueLit.tag_ = panda::panda_file::LiteralTag::METHODAFFILIATE; + valueLit.value_ = literal->GetMethodAffiliate(); + break; + } case ir::LiteralTag::GENERATOR_METHOD: { valueLit.tag_ = panda::panda_file::LiteralTag::GENERATORMETHOD; valueLit.value_ = literal->GetMethod().Mutf8(); diff --git a/es2panda/compiler/core/pandagen.cpp b/es2panda/compiler/core/pandagen.cpp index c95c4539d4942e7030c06e9343aa27681b74a142..17375d9a93e8359e6e7b4374cc5bc0e9888b6ca9 100644 --- a/es2panda/compiler/core/pandagen.cpp +++ b/es2panda/compiler/core/pandagen.cpp @@ -31,8 +31,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -320,10 +322,10 @@ void PandaGen::StoreObjProperty(const ir::AstNode *node, VReg obj, const Operand StoreObjByName(node, obj, std::get(prop)); } -void PandaGen::StoreOwnProperty(const ir::AstNode *node, VReg obj, const Operand &prop) +void PandaGen::StoreOwnProperty(const ir::AstNode *node, VReg obj, const Operand &prop, bool nameSetting) { if (std::holds_alternative(prop)) { - StOwnByValue(node, obj, std::get(prop)); + StOwnByValue(node, obj, std::get(prop), nameSetting); return; } @@ -333,7 +335,7 @@ void PandaGen::StoreOwnProperty(const ir::AstNode *node, VReg obj, const Operand } ASSERT(std::holds_alternative(prop)); - StOwnByName(node, obj, std::get(prop)); + StOwnByName(node, obj, std::get(prop), nameSetting); } void PandaGen::TryLoadGlobalByName(const ir::AstNode *node, const util::StringView &name) @@ -380,20 +382,22 @@ void PandaGen::StoreObjByIndex(const ir::AstNode *node, VReg obj, int64_t index) ra_.Emit(node, index, obj); } -void PandaGen::StOwnByName(const ir::AstNode *node, VReg obj, const util::StringView &prop) +void PandaGen::StOwnByName(const ir::AstNode *node, VReg obj, const util::StringView &prop, bool nameSetting) { - ra_.Emit(node, prop, obj); + nameSetting ? ra_.Emit(node, prop, obj) : + ra_.Emit(node, prop, obj); strings_.insert(prop); } -void PandaGen::StOwnByValue(const ir::AstNode *node, VReg obj, VReg prop) +void PandaGen::StOwnByValue(const ir::AstNode *node, VReg obj, VReg prop, bool nameSetting) { - ra_.Emit(node, obj, prop); + nameSetting ? ra_.Emit(node, obj, prop) : + ra_.Emit(node, obj, prop); } void PandaGen::StOwnByIndex(const ir::AstNode *node, VReg obj, int64_t index) { - ra_.Emit(node, index, obj); + ra_.Emit(node, obj, index); } void PandaGen::DeleteObjProperty(const ir::AstNode *node, VReg obj, const Operand &prop) @@ -828,6 +832,16 @@ void PandaGen::BranchIfNotUndefined(const ir::AstNode *node, Label *target) sa_.Emit(node, target); } +void PandaGen::BranchIfStrictNotUndefined(const ir::AstNode *node, class Label *target) +{ + RegScope rs(this); + VReg tmp = AllocReg(); + StoreAccumulator(node, tmp); + LoadConst(node, Constant::JS_UNDEFINED); + ra_.Emit(node, tmp); + sa_.Emit(node, target); +} + void PandaGen::BranchIfTrue(const ir::AstNode *node, Label *target) { sa_.Emit(node); @@ -891,7 +905,7 @@ void PandaGen::ValidateClassDirectReturn(const ir::AstNode *node) auto *notUndefined = AllocLabel(); auto *condEnd = AllocLabel(); - BranchIfNotUndefined(node, notUndefined); + BranchIfStrictNotUndefined(node, notUndefined); GetThis(func); ThrowIfSuperNotCorrectCall(func, 0); Branch(node, condEnd); @@ -968,7 +982,7 @@ void PandaGen::LoadHomeObject(const ir::AstNode *node) void PandaGen::DefineFunction(const ir::AstNode *node, const ir::ScriptFunction *realNode, const util::StringView &name) { - auto formalParamCnt = FormalParametersCount(); + auto formalParamCnt = realNode->FormalParamsLength(); if (realNode->IsAsync()) { if (realNode->IsGenerator()) { // TODO(): async generator @@ -1369,7 +1383,7 @@ void PandaGen::ImportModule(const ir::AstNode *node, const util::StringView &nam void PandaGen::DefineClassWithBuffer(const ir::AstNode *node, const util::StringView &ctorId, int32_t litIdx, VReg lexenv, VReg base) { - auto formalParamCnt = FormalParametersCount(); + auto formalParamCnt = node->AsClassDefinition()->Ctor()->Function()->FormalParamsLength(); ra_.Emit(node, ctorId, litIdx, static_cast(formalParamCnt), lexenv, base); strings_.insert(ctorId); } @@ -1558,11 +1572,15 @@ Operand PandaGen::ToNamedPropertyKey(const ir::Expression *prop, bool isComputed { VReg res {0}; - if (!isComputed) { - if (prop->IsIdentifier()) { - return prop->AsIdentifier()->Name(); - } - } else if (prop->IsStringLiteral()) { + if (isComputed) { + return res; + } + + if (prop->IsIdentifier()) { + return prop->AsIdentifier()->Name(); + } + + if (prop->IsStringLiteral()) { const util::StringView &str = prop->AsStringLiteral()->Str(); /* TODO(dbatyai): remove this when runtime handles __proto__ as property name correctly */ @@ -1576,7 +1594,9 @@ Operand PandaGen::ToNamedPropertyKey(const ir::Expression *prop, bool isComputed } return str; - } else if (prop->IsNumberLiteral()) { + } + + if (prop->IsNumberLiteral()) { auto num = prop->AsNumberLiteral()->Number(); if (util::Helpers::IsIndex(num)) { return static_cast(num); diff --git a/es2panda/compiler/core/pandagen.h b/es2panda/compiler/core/pandagen.h index 375c0e6de371fa9d1e7dbb9a43ce637124015938..67582f92e3112017278889585a03aef2304ed600 100644 --- a/es2panda/compiler/core/pandagen.h +++ b/es2panda/compiler/core/pandagen.h @@ -219,7 +219,7 @@ public: void LoadObjByName(const ir::AstNode *node, VReg obj, const util::StringView &prop); void StoreObjProperty(const ir::AstNode *node, VReg obj, const Operand &prop); - void StoreOwnProperty(const ir::AstNode *node, VReg obj, const Operand &prop); + void StoreOwnProperty(const ir::AstNode *node, VReg obj, const Operand &prop, bool nameSetting = false); void DeleteObjProperty(const ir::AstNode *node, VReg obj, const Operand &prop); void LoadAccumulator(const ir::AstNode *node, VReg reg); void LoadGlobalVar(const ir::AstNode *node, const util::StringView &name); @@ -255,6 +255,7 @@ public: void Binary(const ir::AstNode *node, lexer::TokenType op, VReg lhs); void BranchIfUndefined(const ir::AstNode *node, class Label *target); + void BranchIfStrictNotUndefined(const ir::AstNode *node, class Label *target); void BranchIfNotUndefined(const ir::AstNode *node, class Label *target); void BranchIfHole(const ir::AstNode *node, class Label *target); void BranchIfTrue(const ir::AstNode *node, class Label *target); @@ -370,8 +371,8 @@ public: void StoreObjByIndex(const ir::AstNode *node, VReg obj, int64_t index); void StoreObjByValue(const ir::AstNode *node, VReg obj, VReg prop); - void StOwnByName(const ir::AstNode *node, VReg obj, const util::StringView &prop); - void StOwnByValue(const ir::AstNode *node, VReg obj, VReg prop); + void StOwnByName(const ir::AstNode *node, VReg obj, const util::StringView &prop, bool nameSetting = false); + void StOwnByValue(const ir::AstNode *node, VReg obj, VReg prop, bool nameSetting = false); void StOwnByIndex(const ir::AstNode *node, VReg obj, int64_t index); static Operand ToNamedPropertyKey(const ir::Expression *prop, bool isComputed); diff --git a/es2panda/ir/base/classDefinition.cpp b/es2panda/ir/base/classDefinition.cpp index 7eea3dab228b16c8064e93f5295287fb999a2a12..260910e252d47833b4f7ce1bc7ccf1c74bf22fe2 100644 --- a/es2panda/ir/base/classDefinition.cpp +++ b/es2panda/ir/base/classDefinition.cpp @@ -120,6 +120,7 @@ int32_t ClassDefinition::CreateClassStaticProperties(compiler::PandaGen *pg, uti auto *buf = pg->NewLiteralBuffer(); compiler::LiteralBuffer staticBuf(pg->Allocator()); bool seenComputed = false; + uint32_t instancePropertyCount = 0; std::unordered_map propNameMap; std::unordered_map staticPropNameMap; @@ -131,12 +132,15 @@ int32_t ClassDefinition::CreateClassStaticProperties(compiler::PandaGen *pg, uti } const ir::MethodDefinition *prop = properties[i]->AsMethodDefinition(); - if (!util::Helpers::IsConstantPropertyKey(prop->Key(), prop->Computed()) || - (prop->Computed() && util::Helpers::IsSpecialPropertyKey(prop->Key()))) { + if (prop->Computed()) { seenComputed = true; continue; } + if (prop->IsAccessor()) { + break; + } + util::StringView name = util::Helpers::LiteralToPropName(prop->Key()); compiler::LiteralBuffer *literalBuf = prop->IsStatic() ? &staticBuf : buf; auto &nameMap = prop->IsStatic() ? staticPropNameMap : propNameMap; @@ -149,7 +153,8 @@ int32_t ClassDefinition::CreateClassStaticProperties(compiler::PandaGen *pg, uti } literalBuf->Add(pg->Allocator()->New(name)); - literalBuf->Add(nullptr); + literalBuf->Add(nullptr); // save for method internalname + literalBuf->Add(nullptr); // save for method affiliate } else { bufferPos = res.first->second; } @@ -162,12 +167,18 @@ int32_t ClassDefinition::CreateClassStaticProperties(compiler::PandaGen *pg, uti const util::StringView &internalName = func->Function()->Scope()->InternalName(); value = pg->Allocator()->New(LiteralTag::METHOD, internalName); + literalBuf->ResetLiteral(bufferPos + 1, value); + Literal *methodAffiliate = pg->Allocator()->New(LiteralTag::METHODAFFILIATE, + func->Function()->FormalParamsLength()); + literalBuf->ResetLiteral(bufferPos + 2, methodAffiliate); // bufferPos + 2 is saved for method affiliate compiled.Set(i); break; } + // TODO refactor this part later case ir::MethodDefinitionKind::GET: case ir::MethodDefinitionKind::SET: { value = pg->Allocator()->New(); + literalBuf->ResetLiteral(bufferPos + 1, value); break; } default: { @@ -175,17 +186,17 @@ int32_t ClassDefinition::CreateClassStaticProperties(compiler::PandaGen *pg, uti } } - literalBuf->ResetLiteral(bufferPos + 1, value); + if (!prop->IsStatic()) { + instancePropertyCount++; + } } - uint32_t litPairs = buf->Size() / 2; - /* Static items are stored at the end of the buffer */ buf->Insert(&staticBuf); /* The last literal item represents the offset of the first static property. The regular property literal count * is divided by 2 as key/value pairs count as one. */ - buf->Add(pg->Allocator()->New(litPairs)); + buf->Add(pg->Allocator()->New(instancePropertyCount)); return pg->AddLiteralBuffer(buf); } @@ -217,7 +228,7 @@ void ClassDefinition::CompileMissingProperties(compiler::PandaGen *pg, const uti const ir::FunctionExpression *func = prop->Value()->AsFunctionExpression(); func->Compile(pg); - pg->StoreOwnProperty(prop->Value()->Parent(), dest, key); + pg->StoreOwnProperty(prop->Value()->Parent(), dest, key, prop->Computed()); break; } case ir::MethodDefinitionKind::GET: @@ -269,6 +280,7 @@ void ClassDefinition::Compile(compiler::PandaGen *pg) const int32_t bufIdx = CreateClassStaticProperties(pg, compiled); pg->DefineClassWithBuffer(this, ctorId, bufIdx, lexenv, baseReg); + pg->StoreAccumulator(this, classReg); InitializeClassName(pg); diff --git a/es2panda/ir/base/methodDefinition.h b/es2panda/ir/base/methodDefinition.h index e304cd084e23e350d8457da1bb9b7e676f6fc26b..1170e01693b500da39d45e68134bcc105aed9a82 100644 --- a/es2panda/ir/base/methodDefinition.h +++ b/es2panda/ir/base/methodDefinition.h @@ -80,6 +80,11 @@ public: return (modifiers_ & ModifierFlags::STATIC) != 0; } + bool IsAccessor() const + { + return (kind_ == MethodDefinitionKind::GET) || (kind_ == MethodDefinitionKind::SET); + } + bool IsOptional() const { return (modifiers_ & ModifierFlags::OPTIONAL) != 0; diff --git a/es2panda/ir/expressions/literal.cpp b/es2panda/ir/expressions/literal.cpp index 48cb9a94d4317a7940cc7c06ae92c416f03258de..4a021f470ff5a8323d89922856ed064cf09c6ec9 100644 --- a/es2panda/ir/expressions/literal.cpp +++ b/es2panda/ir/expressions/literal.cpp @@ -52,4 +52,10 @@ const util::StringView &Literal::GetMethod() const return AsTaggedLiteral()->Method(); } +uint16_t Literal::GetMethodAffiliate() const +{ + ASSERT(IsTaggedLiteral()); + return AsTaggedLiteral()->MethodAffiliate(); +} + } // namespace panda::es2panda::ir diff --git a/es2panda/ir/expressions/literal.h b/es2panda/ir/expressions/literal.h index ee6bc7af23e6d239b26b2b8275c6cb6428c67bb2..c38869152df2e7338db52a515f8029cdae40e525 100644 --- a/es2panda/ir/expressions/literal.h +++ b/es2panda/ir/expressions/literal.h @@ -37,11 +37,12 @@ enum class LiteralTag { FLOAT, DOUBLE, STRING, - ACCESSOR, METHOD, GENERATOR_METHOD, + ACCESSOR, + METHODAFFILIATE, ASYNC_GENERATOR_METHOD, - NULL_VALUE, + NULL_VALUE = 255, }; class Literal : public Expression { @@ -58,6 +59,7 @@ public: double GetDouble() const; const util::StringView &GetString() const; const util::StringView &GetMethod() const; + uint16_t GetMethodAffiliate() const; protected: explicit Literal(AstNodeType type) : Expression(type) {} diff --git a/es2panda/ir/expressions/literals/taggedLiteral.h b/es2panda/ir/expressions/literals/taggedLiteral.h index 69a4b6486a38bd9e10ad389b8551b24fcf30fcea..c8ecd27e70eb55ca5392b6ff75ddfeb348adee47 100644 --- a/es2panda/ir/expressions/literals/taggedLiteral.h +++ b/es2panda/ir/expressions/literals/taggedLiteral.h @@ -37,6 +37,11 @@ public: { } + explicit TaggedLiteral(LiteralTag tag, uint16_t num) + : Literal(AstNodeType::TAGGED_LITERAL), num_(num), tag_(tag) + { + } + const util::StringView &Str() const { return str_; @@ -59,12 +64,19 @@ public: return str_; } + uint16_t MethodAffiliate() const + { + ASSERT(tag_ == LiteralTag::METHODAFFILIATE); + return num_; + } + void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; void Compile([[maybe_unused]] compiler::PandaGen *pg) const override; checker::Type *Check([[maybe_unused]] checker::Checker *checker) const override; private: + uint16_t num_ {}; util::StringView str_ {}; LiteralTag tag_ {LiteralTag::NULL_VALUE}; };