From 2a0d3a2b24a9ef6d9a6341f073b407bd9f8923de Mon Sep 17 00:00:00 2001 From: zhuoli72 Date: Mon, 25 Jul 2022 21:36:01 +0800 Subject: [PATCH 1/2] Fix objectLiteral error in test262 Issue: I5HRUY Signed-off-by: zhuoli72 Change-Id: I8a784bcd35491a599441ca0313a852c121cf8975 --- es2panda/compiler/core/emitter.cpp | 4 ++ es2panda/ir/expressions/objectExpression.cpp | 68 ++++++++++++++++++-- 2 files changed, 68 insertions(+), 4 deletions(-) diff --git a/es2panda/compiler/core/emitter.cpp b/es2panda/compiler/core/emitter.cpp index d807dfc245c..1a8b201ebba 100644 --- a/es2panda/compiler/core/emitter.cpp +++ b/es2panda/compiler/core/emitter.cpp @@ -79,6 +79,10 @@ void FunctionEmitter::GenBufferLiterals(const LiteralBuffer *buff) array.reserve(buff->Literals().size() * ARRAY_EXPANSION); for (const auto *literal : buff->Literals()) { + if (literal == nullptr) { + // skip potential empty literals created by property overwrite + continue; + } panda::pandasm::LiteralArray::Literal valueLit; panda::pandasm::LiteralArray::Literal tagLit; diff --git a/es2panda/ir/expressions/objectExpression.cpp b/es2panda/ir/expressions/objectExpression.cpp index bb4e2f62db4..a20b5466d1a 100644 --- a/es2panda/ir/expressions/objectExpression.cpp +++ b/es2panda/ir/expressions/objectExpression.cpp @@ -20,14 +20,19 @@ #include #include #include +#include #include #include #include #include +#include #include +#include +#include #include #include #include +#include #include #include #include @@ -35,6 +40,45 @@ namespace panda::es2panda::ir { +static bool NeedSettingName(const ir::Expression *expr) +{ + const ir::Identifier *identifier; + switch (expr->Type()) { + case ir::AstNodeType::FUNCTION_EXPRESSION: { + identifier = expr->AsFunctionExpression()->Function()->Id(); + break; + } + case ir::AstNodeType::ARROW_FUNCTION_EXPRESSION: { + identifier = expr->AsArrowFunctionExpression()->Function()->Id(); + break; + } + case ir::AstNodeType::CLASS_EXPRESSION: { + identifier = expr->AsClassExpression()->Definition()->Ident(); + break; + } + default: { + return false; + } + } + return identifier == nullptr || identifier->Name().Empty(); +} + +static bool IsTargetNameFormat(const ir::Expression *expr) +{ + util::StringView name; + if (expr->IsIdentifier()) { + name = expr->AsIdentifier()->Name(); + } else if (expr->IsStringLiteral()) { + name = expr->AsStringLiteral()->Str(); + } else if (expr->IsNumberLiteral()) { + name = expr->AsNumberLiteral()->Str(); + } else { + UNREACHABLE(); + } + return name.Find(".") != std::string::npos && name.Find("\\") != std::string::npos; +} + + ValidationInfo ObjectExpression::ValidateExpression() { ValidationInfo info; @@ -245,16 +289,22 @@ void ObjectExpression::CompileStaticProperties(compiler::PandaGen *pg, util::Bit } buf->Add(pg->Allocator()->New(name)); - buf->Add(nullptr); + buf->Add(nullptr); // buf for name + buf->Add(nullptr); // buf for function affiliate } else { bufferPos = res.first->second; } + buf->ResetLiteral(bufferPos + 1, CreateLiteral(pg, prop, compiled, i)); + if (prop->IsMethod()) { hasMethod = true; + const ir::FunctionExpression *func = prop->Value()->AsFunctionExpression(); + Literal *methodAffiliate = pg->Allocator()->New(LiteralTag::METHODAFFILIATE, func->Function()->FormalParamsLength()); + buf->ResetLiteral(bufferPos + 2, methodAffiliate); + } else { + buf->ResetLiteral(bufferPos + 2, nullptr); } - - buf->ResetLiteral(bufferPos + 1, CreateLiteral(pg, prop, compiled, i)); } EmitCreateObjectWithBuffer(pg, buf, hasMethod); @@ -312,12 +362,22 @@ void ObjectExpression::CompileRemainingProperties(compiler::PandaGen *pg, const case ir::PropertyKind::INIT: { compiler::Operand key = pg->ToPropertyKey(prop->Key(), prop->IsComputed()); + bool nameSetting = false; if (prop->IsMethod()) { pg->LoadAccumulator(prop->Value(), objReg); + if (prop -> IsComputed()) { + nameSetting = true; + } + } else { + if (prop->IsComputed()) { + nameSetting = NeedSettingName(prop->Value()); + } else { + nameSetting = NeedSettingName(prop->Value()) && IsTargetNameFormat(prop->Key()); + } } prop->Value()->Compile(pg); - pg->StoreOwnProperty(this, objReg, key); + pg->StoreOwnProperty(this, objReg, key, nameSetting); break; } case ir::PropertyKind::PROTO: { -- Gitee From 894e6f778257af3d0270f66259cfaf00b19c518b Mon Sep 17 00:00:00 2001 From: zhuoli72 Date: Tue, 26 Jul 2022 19:50:11 +0800 Subject: [PATCH 2/2] Fix objectLiteral for the correct overwrite of accessor property Issue: I5HRUY Signed-off-by: zhuoli72 Change-Id: Ia6f361d3c01ced578429401927857ed86caad1e3 --- es2panda/compiler/base/literals.h | 2 +- es2panda/compiler/core/emitter.cpp | 4 -- es2panda/ir/expressions/objectExpression.cpp | 71 ++++++++++++++------ es2panda/ir/expressions/objectExpression.h | 2 + 4 files changed, 55 insertions(+), 24 deletions(-) diff --git a/es2panda/compiler/base/literals.h b/es2panda/compiler/base/literals.h index ddda8fc2386..bd566c69c7d 100644 --- a/es2panda/compiler/base/literals.h +++ b/es2panda/compiler/base/literals.h @@ -41,7 +41,7 @@ public: NO_COPY_SEMANTIC(LiteralBuffer); NO_MOVE_SEMANTIC(LiteralBuffer); - void Add(ir::Literal *lit) + void Add(const ir::Literal *lit) { literals_.push_back(lit); } diff --git a/es2panda/compiler/core/emitter.cpp b/es2panda/compiler/core/emitter.cpp index 1a8b201ebba..d807dfc245c 100644 --- a/es2panda/compiler/core/emitter.cpp +++ b/es2panda/compiler/core/emitter.cpp @@ -79,10 +79,6 @@ void FunctionEmitter::GenBufferLiterals(const LiteralBuffer *buff) array.reserve(buff->Literals().size() * ARRAY_EXPANSION); for (const auto *literal : buff->Literals()) { - if (literal == nullptr) { - // skip potential empty literals created by property overwrite - continue; - } panda::pandasm::LiteralArray::Literal valueLit; panda::pandasm::LiteralArray::Literal tagLit; diff --git a/es2panda/ir/expressions/objectExpression.cpp b/es2panda/ir/expressions/objectExpression.cpp index a20b5466d1a..e6b35dcb3a6 100644 --- a/es2panda/ir/expressions/objectExpression.cpp +++ b/es2panda/ir/expressions/objectExpression.cpp @@ -28,19 +28,19 @@ #include #include #include -#include #include #include #include #include #include #include +#include #include #include namespace panda::es2panda::ir { -static bool NeedSettingName(const ir::Expression *expr) +static bool IsAnonClassOrFuncExpr(const ir::Expression *expr) { const ir::Identifier *identifier; switch (expr->Type()) { @@ -63,7 +63,7 @@ static bool NeedSettingName(const ir::Expression *expr) return identifier == nullptr || identifier->Name().Empty(); } -static bool IsTargetNameFormat(const ir::Expression *expr) +static bool IsLegalNameFormat(const ir::Expression *expr) { util::StringView name; if (expr->IsIdentifier()) { @@ -209,6 +209,21 @@ void ObjectExpression::Dump(ir::AstDumper *dumper) const {"optional", AstDumper::Optional(optional_)}}); } +void ObjectExpression::FillInLiteralBuffer(compiler::LiteralBuffer *buf, + std::vector> &tempLiteralBuffer) const +{ + for (size_t i = 0 ; i < tempLiteralBuffer.size(); i++) { + if (tempLiteralBuffer[i].size() == 0) { + continue; + } + + auto propBuf = tempLiteralBuffer[i]; + for (size_t j = 0; j < propBuf.size(); j++) { + buf->Add(propBuf[j]); + } + } +} + void ObjectExpression::EmitCreateObjectWithBuffer(compiler::PandaGen *pg, compiler::LiteralBuffer *buf, bool hasMethod) const { @@ -264,7 +279,10 @@ void ObjectExpression::CompileStaticProperties(compiler::PandaGen *pg, util::Bit bool hasMethod = false; bool seenComputed = false; auto *buf = pg->NewLiteralBuffer(); + std::vector> tempLiteralBuffer(properties_.size()); std::unordered_map propNameMap; + std::unordered_map getterIndxNameMap; + std::unordered_map setterIndxNameMap; for (size_t i = 0; i < properties_.size(); i++) { if (properties_[i]->IsSpreadElement()) { @@ -280,33 +298,47 @@ void ObjectExpression::CompileStaticProperties(compiler::PandaGen *pg, util::Bit continue; } + std::vector propBuf; util::StringView name = util::Helpers::LiteralToPropName(prop->Key()); - size_t bufferPos = buf->Literals().size(); - auto res = propNameMap.insert({name, bufferPos}); - if (res.second) { + size_t propIndex = i; + auto res = propNameMap.insert({name, propIndex}); + if (res.second) { // name not found in map if (seenComputed) { break; } - - buf->Add(pg->Allocator()->New(name)); - buf->Add(nullptr); // buf for name - buf->Add(nullptr); // buf for function affiliate } else { - bufferPos = res.first->second; + propIndex = res.first->second; + + if (prop->Kind() != ir::PropertyKind::SET && getterIndxNameMap.find(name) != getterIndxNameMap.end()) { + compiled->Set(getterIndxNameMap[name]); + } + + if (prop->Kind() != ir::PropertyKind::GET && setterIndxNameMap.find(name) != setterIndxNameMap.end()) { + compiled->Set(setterIndxNameMap[name]); + } } - buf->ResetLiteral(bufferPos + 1, CreateLiteral(pg, prop, compiled, i)); + if (prop->Kind() == ir::PropertyKind::GET) { + getterIndxNameMap[name] = i; + } else if (prop->Kind() == ir::PropertyKind::SET) { + setterIndxNameMap[name] = i; + } + + propBuf.push_back(pg->Allocator()->New(name)); + propBuf.push_back(CreateLiteral(pg, prop, compiled, i)); if (prop->IsMethod()) { hasMethod = true; const ir::FunctionExpression *func = prop->Value()->AsFunctionExpression(); - Literal *methodAffiliate = pg->Allocator()->New(LiteralTag::METHODAFFILIATE, func->Function()->FormalParamsLength()); - buf->ResetLiteral(bufferPos + 2, methodAffiliate); - } else { - buf->ResetLiteral(bufferPos + 2, nullptr); + size_t paramNum = func->Function()->FormalParamsLength(); + Literal *methodAffiliate = pg->Allocator()->New(LiteralTag::METHODAFFILIATE, paramNum); + propBuf.push_back(methodAffiliate); } + + tempLiteralBuffer[propIndex] = propBuf; } + FillInLiteralBuffer(buf, tempLiteralBuffer); EmitCreateObjectWithBuffer(pg, buf, hasMethod); } @@ -314,6 +346,7 @@ void ObjectExpression::CompileRemainingProperties(compiler::PandaGen *pg, const compiler::VReg objReg) const { for (size_t i = 0; i < properties_.size(); i++) { + // TODO: Compile and store only the last one of re-declared prop if (compiled->Test(i)) { continue; } @@ -365,14 +398,14 @@ void ObjectExpression::CompileRemainingProperties(compiler::PandaGen *pg, const bool nameSetting = false; if (prop->IsMethod()) { pg->LoadAccumulator(prop->Value(), objReg); - if (prop -> IsComputed()) { + if (prop->IsComputed()) { nameSetting = true; } } else { if (prop->IsComputed()) { - nameSetting = NeedSettingName(prop->Value()); + nameSetting = IsAnonClassOrFuncExpr(prop->Value()); } else { - nameSetting = NeedSettingName(prop->Value()) && IsTargetNameFormat(prop->Key()); + nameSetting = IsAnonClassOrFuncExpr(prop->Value()) && IsLegalNameFormat(prop->Key()); } } diff --git a/es2panda/ir/expressions/objectExpression.h b/es2panda/ir/expressions/objectExpression.h index d09eec73d00..39a43bf2853 100644 --- a/es2panda/ir/expressions/objectExpression.h +++ b/es2panda/ir/expressions/objectExpression.h @@ -79,6 +79,8 @@ public: checker::Type *CheckPattern(checker::Checker *checker, bool inAssignment) const; private: + void FillInLiteralBuffer(compiler::LiteralBuffer *buf, + std::vector> &tempLiteralBuffer) const; void EmitCreateObjectWithBuffer(compiler::PandaGen *pg, compiler::LiteralBuffer *buf, bool hasMethod) const; void CompileStaticProperties(compiler::PandaGen *pg, util::BitSet *compiled) const; void CompileRemainingProperties(compiler::PandaGen *pg, const util::BitSet *compiled, compiler::VReg objReg) const; -- Gitee