From 0a3e91f2f066c7563d140d6dc9c43c08e753dee4 Mon Sep 17 00:00:00 2001 From: Geng Chen Date: Thu, 7 Aug 2025 09:33:46 +0800 Subject: [PATCH 1/6] use bitfile to reduce 4B for each astNode Signed-off-by: Geng Chen --- ets2panda/checker/ETSAnalyzer.cpp | 6 +- ets2panda/ir/astNode.cpp | 18 ++--- ets2panda/ir/astNode.h | 66 +++++++++++++++---- ets2panda/ir/base/overloadDeclaration.cpp | 2 +- ets2panda/ir/base/spreadElement.cpp | 2 +- ets2panda/ir/ets/etsModule.h | 4 +- ets2panda/ir/ets/etsTuple.cpp | 2 +- ets2panda/ir/ets/etsTypeReference.cpp | 2 +- ets2panda/ir/expressions/arrayExpression.cpp | 2 +- .../ir/expressions/assignmentExpression.cpp | 2 +- ets2panda/ir/expressions/binaryExpression.h | 2 +- .../ir/expressions/directEvalExpression.h | 2 +- ets2panda/ir/expressions/identifier.cpp | 6 +- ets2panda/ir/expressions/objectExpression.cpp | 2 +- ets2panda/ir/statements/functionDeclaration.h | 4 +- ets2panda/ir/ts/tsArrayType.cpp | 2 +- 16 files changed, 82 insertions(+), 42 deletions(-) diff --git a/ets2panda/checker/ETSAnalyzer.cpp b/ets2panda/checker/ETSAnalyzer.cpp index 2974d4837a..f454ef87c6 100644 --- a/ets2panda/checker/ETSAnalyzer.cpp +++ b/ets2panda/checker/ETSAnalyzer.cpp @@ -267,7 +267,7 @@ void ETSAnalyzer::CheckMethodModifiers(ir::MethodDefinition *node) const auto const notValidInAbstract = ir::ModifierFlags::NATIVE | ir::ModifierFlags::PRIVATE | ir::ModifierFlags::OVERRIDE | ir::ModifierFlags::FINAL | ir::ModifierFlags::STATIC; - if (node->IsAbstract() && (node->flags_ & notValidInAbstract) != 0U) { + if (node->IsAbstract() && (static_cast(node->bitFields_.flags_) & notValidInAbstract) != 0U) { checker->LogError(diagnostic::ABSTRACT_METHOD_INVALID_MODIFIER, {}, node->Start()); node->SetTsType(checker->GlobalTypeError()); return; @@ -282,14 +282,14 @@ void ETSAnalyzer::CheckMethodModifiers(ir::MethodDefinition *node) const auto const notValidInFinal = ir::ModifierFlags::ABSTRACT | ir::ModifierFlags::STATIC; - if (node->IsFinal() && (node->flags_ & notValidInFinal) != 0U) { + if (node->IsFinal() && (static_cast(node->bitFields_.flags_) & notValidInFinal) != 0U) { checker->LogError(diagnostic::FINAL_METHOD_INVALID_MODIFIER, {}, node->Start()); node->SetTsType(checker->GlobalTypeError()); } auto const notValidInStatic = ir::ModifierFlags::ABSTRACT | ir::ModifierFlags::FINAL | ir::ModifierFlags::OVERRIDE; - if (node->IsStatic() && (node->flags_ & notValidInStatic) != 0U) { + if (node->IsStatic() && (static_cast(node->bitFields_.flags_) & notValidInStatic) != 0U) { checker->LogError(diagnostic::STATIC_METHOD_INVALID_MODIFIER, {}, node->Start()); node->SetTsType(checker->GlobalTypeError()); } diff --git a/ets2panda/ir/astNode.cpp b/ets2panda/ir/astNode.cpp index 8114961153..daf2c3587f 100644 --- a/ets2panda/ir/astNode.cpp +++ b/ets2panda/ir/astNode.cpp @@ -26,12 +26,12 @@ AstNode::AstNode(AstNode const &other) { auto otherHistoryNode = other.GetHistoryNode(); range_ = otherHistoryNode->range_; - type_ = otherHistoryNode->type_; + bitFields_.type_ = otherHistoryNode->bitFields_.type_; if (otherHistoryNode->variable_ != nullptr) { variable_ = otherHistoryNode->variable_; } - flags_ = otherHistoryNode->flags_; - astNodeFlags_ = otherHistoryNode->astNodeFlags_; + bitFields_.flags_ = otherHistoryNode->bitFields_.flags_; + bitFields_.astNodeFlags_ = otherHistoryNode->bitFields_.astNodeFlags_; // boxing_unboxing_flags_ {}; leave default value! } @@ -68,7 +68,7 @@ AstNode::AstNode(AstNode const &other) return GetHistoryNode()->parent_->HasExportAlias(); } - return (GetHistoryNode()->astNodeFlags_ & AstNodeFlags::HAS_EXPORT_ALIAS) != 0; + return (static_cast(GetHistoryNode()->bitFields_.astNodeFlags_) & AstNodeFlags::HAS_EXPORT_ALIAS) != 0; } bool AstNode::IsScopeBearer() const noexcept @@ -223,12 +223,12 @@ AstNode *AstNode::ShallowClone(ArenaAllocator *allocator) void AstNode::CopyTo(AstNode *other) const { - ES2PANDA_ASSERT(other->type_ == type_); + ES2PANDA_ASSERT(static_cast(other->bitFields_.type_) == static_cast(bitFields_.type_)); other->parent_ = parent_; other->range_ = range_; - other->flags_ = flags_; - other->astNodeFlags_ = astNodeFlags_; + other->bitFields_.flags_ = bitFields_.flags_; + other->bitFields_.astNodeFlags_ = bitFields_.astNodeFlags_; other->history_ = history_; other->variable_ = variable_; other->originalNode_ = originalNode_; @@ -286,14 +286,14 @@ AstNode *AstNode::GetOrCreateHistoryNode() const void AstNode::AddModifier(ModifierFlags const flags) noexcept { if (!All(Modifiers(), flags)) { - GetOrCreateHistoryNode()->flags_ |= flags; + GetOrCreateHistoryNode()->bitFields_.flags_ |= static_cast(flags); } } void AstNode::ClearModifier(ModifierFlags const flags) noexcept { if (Any(Modifiers(), flags)) { - GetOrCreateHistoryNode()->flags_ &= ~flags; + GetOrCreateHistoryNode()->bitFields_.flags_ &= ~static_cast(flags); } } diff --git a/ets2panda/ir/astNode.h b/ets2panda/ir/astNode.h index 751d44cefc..40de0f3d2c 100644 --- a/ets2panda/ir/astNode.h +++ b/ets2panda/ir/astNode.h @@ -134,8 +134,8 @@ AST_NODE_REINTERPRET_MAPPING(DECLARE_CLASSES) class AstNode { public: - explicit AstNode(AstNodeType type) : type_(type) {}; - explicit AstNode(AstNodeType type, ModifierFlags flags) : flags_(flags), type_(type) {}; + explicit AstNode(AstNodeType type) : bitFields_{0, 0, static_cast(type)} {}; + explicit AstNode(AstNodeType type, ModifierFlags flags) : bitFields_{static_cast(flags), 0, static_cast(type)} {}; virtual ~AstNode() = default; AstNode() = delete; @@ -152,7 +152,7 @@ public: { \ /* CC-OFFNXT(G.PRE.02) name part*/ \ /* CC-OFFNXT(G.PRE.05) The macro is used to generate a function. Return is needed */ \ - return GetHistoryNode()->type_ == AstNodeType::nodeType; /* CC-OFF(G.PRE.02) name part*/ \ + return static_cast(GetHistoryNode()->bitFields_.type_) == AstNodeType::nodeType; /* CC-OFF(G.PRE.02) name part*/ \ } AST_NODE_MAPPING(DECLARE_IS_CHECKS) #undef DECLARE_IS_CHECKS @@ -162,12 +162,12 @@ public: bool Is##baseClass() const \ { \ /* CC-OFFNXT(G.PRE.05) The macro is used to generate a function. Return is needed */ \ - return GetHistoryNode()->type_ == AstNodeType::nodeType1; /* CC-OFF(G.PRE.02) name part*/ \ + return static_cast(GetHistoryNode()->bitFields_.type_) == AstNodeType::nodeType1; /* CC-OFF(G.PRE.02) name part*/ \ } \ bool Is##reinterpretClass() const \ { \ /* CC-OFFNXT(G.PRE.05) The macro is used to generate a function. Return is needed */ \ - return GetHistoryNode()->type_ == AstNodeType::nodeType2; /* CC-OFF(G.PRE.02) name part*/ \ + return static_cast(GetHistoryNode()->bitFields_.type_) == AstNodeType::nodeType2; /* CC-OFF(G.PRE.02) name part*/ \ } AST_NODE_REINTERPRET_MAPPING(DECLARE_IS_CHECKS) #undef DECLARE_IS_CHECKS @@ -317,7 +317,7 @@ public: [[nodiscard]] AstNodeType Type() const noexcept { - return GetHistoryNode()->type_; + return static_cast(GetHistoryNode()->bitFields_.type_); } [[nodiscard]] AstNode *Parent() noexcept @@ -470,12 +470,12 @@ public: [[nodiscard]] ModifierFlags Modifiers() noexcept { - return GetHistoryNode()->flags_; + return static_cast(GetHistoryNode()->bitFields_.flags_); } [[nodiscard]] ModifierFlags Modifiers() const noexcept { - return GetHistoryNode()->flags_; + return static_cast(GetHistoryNode()->bitFields_.flags_); } [[nodiscard]] bool HasExportAlias() const noexcept; @@ -514,8 +514,46 @@ public: } \ } - DECLARE_FLAG_OPERATIONS(AstNodeFlags, astNodeFlags_); + // CC-OFFNXT(G.PRE.06) solid logic + // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) +#define DECLARE_BITFIELD_FLAG_OPERATIONS(flag_type, member_name) \ + void Set##flag_type(flag_type flags) const noexcept \ + { \ + if (static_cast(GetHistoryNode()->member_name) != flags) { \ + GetOrCreateHistoryNode()->member_name = static_cast(flags); \ + } \ + } \ + \ + void Add##flag_type(flag_type flag) const noexcept \ + { \ + if (!All(static_cast(GetHistoryNode()->member_name), flag)) { \ + GetOrCreateHistoryNode()->member_name |= static_cast(flag); \ + } \ + } \ + \ + [[nodiscard]] flag_type Get##flag_type() const noexcept \ + { \ + /* CC-OFFNXT(G.PRE.05) The macro is used to generate a function. Return is needed*/ \ + return static_cast(GetHistoryNode()->member_name); \ + } \ + \ + bool Has##flag_type(flag_type flag) const noexcept \ + { \ + /* CC-OFFNXT(G.PRE.05) The macro is used to generate a function. Return is needed*/ \ + return (static_cast(GetHistoryNode()->member_name) & flag) != 0U; \ + } \ + void Remove##flag_type(flag_type flag) const noexcept \ + { \ + if (Any(static_cast(GetHistoryNode()->member_name), flag)) { \ + GetOrCreateHistoryNode()->member_name &= ~static_cast(flag); \ + } \ + } + + // Use macro to generate AstNodeFlags operations + DECLARE_BITFIELD_FLAG_OPERATIONS(AstNodeFlags, bitFields_.astNodeFlags_) + #undef DECLARE_FLAG_OPERATIONS +#undef DECLARE_BITFIELD_FLAG_OPERATIONS ir::ClassElement *AsClassElement(); const ir::ClassElement *AsClassElement() const; @@ -702,7 +740,7 @@ protected: void SetType(AstNodeType const type) noexcept { if (Type() != type) { - GetOrCreateHistoryNode()->type_ = type; + GetOrCreateHistoryNode()->bitFields_.type_ = static_cast(type); } } @@ -728,9 +766,11 @@ protected: AstNode *parent_ {}; AstNodeHistory *history_ {nullptr}; lexer::CompressedSourceRange range_ {}; - ModifierFlags flags_ {}; - mutable AstNodeFlags astNodeFlags_ {}; - AstNodeType type_; + struct { + uint64_t flags_ : 32; + uint64_t astNodeFlags_ : 24; + uint64_t type_ : 8; + } bitFields_ {}; // NOLINTEND(misc-non-private-member-variables-in-classes) private: diff --git a/ets2panda/ir/base/overloadDeclaration.cpp b/ets2panda/ir/base/overloadDeclaration.cpp index 7af8f592ff..ff3e81fd93 100644 --- a/ets2panda/ir/base/overloadDeclaration.cpp +++ b/ets2panda/ir/base/overloadDeclaration.cpp @@ -55,7 +55,7 @@ void OverloadDeclaration::Dump(ir::AstDumper *dumper) const { dumper->Add({{"type", "OverloadDeclaration"}, {"key", key_}, - {"optional", AstDumper::Optional(AstDumper::ModifierToString(flags_))}, + {"optional", AstDumper::Optional(AstDumper::ModifierToString(Modifiers()))}, {"static", IsStatic()}, {"overloadedList", overloadedList_}}); } diff --git a/ets2panda/ir/base/spreadElement.cpp b/ets2panda/ir/base/spreadElement.cpp index 39bac966aa..ed7cff3a17 100644 --- a/ets2panda/ir/base/spreadElement.cpp +++ b/ets2panda/ir/base/spreadElement.cpp @@ -133,7 +133,7 @@ void SpreadElement::Iterate(const NodeTraverser &cb) const void SpreadElement::Dump(ir::AstDumper *dumper) const { - dumper->Add({{"type", (type_ == AstNodeType::SPREAD_ELEMENT) ? "SpreadElement" : "RestElement"}, + dumper->Add({{"type", (Type() == AstNodeType::SPREAD_ELEMENT) ? "SpreadElement" : "RestElement"}, {"decorators", AstDumper::Optional(decorators_)}, {"argument", argument_}, {"typeAnnotation", AstDumper::Optional(TypeAnnotation())}}); diff --git a/ets2panda/ir/ets/etsModule.h b/ets2panda/ir/ets/etsModule.h index abc2a5eca1..ed06c3f6cc 100644 --- a/ets2panda/ir/ets/etsModule.h +++ b/ets2panda/ir/ets/etsModule.h @@ -54,7 +54,7 @@ public: lang_(lang), program_(program) { - type_ = AstNodeType::ETS_MODULE; + SetType(AstNodeType::ETS_MODULE); InitHistory(); } @@ -67,7 +67,7 @@ public: lang_(lang), program_(program) { - type_ = AstNodeType::ETS_MODULE; + SetType(AstNodeType::ETS_MODULE); if (history != nullptr) { history_ = history; } else { diff --git a/ets2panda/ir/ets/etsTuple.cpp b/ets2panda/ir/ets/etsTuple.cpp index 0a21e35971..1c4df98c10 100644 --- a/ets2panda/ir/ets/etsTuple.cpp +++ b/ets2panda/ir/ets/etsTuple.cpp @@ -133,7 +133,7 @@ ETSTuple *ETSTuple::Clone(ArenaAllocator *const allocator, AstNode *const parent auto *const clone = allocator->New(allocator, size_); ES2PANDA_ASSERT(clone != nullptr); - clone->AddModifier(flags_); + clone->AddModifier(Modifiers()); if (parent != nullptr) { clone->SetParent(parent); diff --git a/ets2panda/ir/ets/etsTypeReference.cpp b/ets2panda/ir/ets/etsTypeReference.cpp index e659e05474..a3ade0d1e6 100644 --- a/ets2panda/ir/ets/etsTypeReference.cpp +++ b/ets2panda/ir/ets/etsTypeReference.cpp @@ -139,7 +139,7 @@ ETSTypeReference *ETSTypeReference::Clone(ArenaAllocator *const allocator, AstNo partClone->SetParent(clone); } - clone->flags_ = Modifiers(); + clone->AddModifier(Modifiers()); if (parent != nullptr) { clone->SetParent(parent); diff --git a/ets2panda/ir/expressions/arrayExpression.cpp b/ets2panda/ir/expressions/arrayExpression.cpp index 76bc0c22bc..d8c5a7d53e 100644 --- a/ets2panda/ir/expressions/arrayExpression.cpp +++ b/ets2panda/ir/expressions/arrayExpression.cpp @@ -198,7 +198,7 @@ void ArrayExpression::Iterate(const NodeTraverser &cb) const void ArrayExpression::Dump(ir::AstDumper *dumper) const { - dumper->Add({{"type", type_ == AstNodeType::ARRAY_EXPRESSION ? "ArrayExpression" : "ArrayPattern"}, + dumper->Add({{"type", Type() == AstNodeType::ARRAY_EXPRESSION ? "ArrayExpression" : "ArrayPattern"}, {"decorators", AstDumper::Optional(decorators_)}, {"elements", elements_}, {"typeAnnotation", AstDumper::Optional(TypeAnnotation())}, diff --git a/ets2panda/ir/expressions/assignmentExpression.cpp b/ets2panda/ir/expressions/assignmentExpression.cpp index 2505910c5f..30f2d7888d 100644 --- a/ets2panda/ir/expressions/assignmentExpression.cpp +++ b/ets2panda/ir/expressions/assignmentExpression.cpp @@ -103,7 +103,7 @@ void AssignmentExpression::Iterate(const NodeTraverser &cb) const void AssignmentExpression::Dump(ir::AstDumper *dumper) const { - if (type_ == AstNodeType::ASSIGNMENT_EXPRESSION) { + if (Type() == AstNodeType::ASSIGNMENT_EXPRESSION) { dumper->Add({{"type", "AssignmentExpression"}, {"operator", operator_}, {"left", left_}, {"right", right_}}); } else { dumper->Add({{"type", "AssignmentPattern"}, {"left", left_}, {"right", right_}}); diff --git a/ets2panda/ir/expressions/binaryExpression.h b/ets2panda/ir/expressions/binaryExpression.h index 87c4377c86..ad02394904 100644 --- a/ets2panda/ir/expressions/binaryExpression.h +++ b/ets2panda/ir/expressions/binaryExpression.h @@ -133,7 +133,7 @@ public: void SetOperator(lexer::TokenType operatorType) noexcept { operator_ = operatorType; - type_ = AstNodeType::BINARY_EXPRESSION; + SetType(AstNodeType::BINARY_EXPRESSION); } [[nodiscard]] checker::Type *OperationType() noexcept diff --git a/ets2panda/ir/expressions/directEvalExpression.h b/ets2panda/ir/expressions/directEvalExpression.h index 3e959c30f2..f51e7aa563 100644 --- a/ets2panda/ir/expressions/directEvalExpression.h +++ b/ets2panda/ir/expressions/directEvalExpression.h @@ -29,7 +29,7 @@ public: TSTypeParameterInstantiation *typeParams, bool optional, uint32_t parserStatus) : CallExpression(callee, std::move(arguments), typeParams, optional), parserStatus_(parserStatus) { - type_ = AstNodeType::DIRECT_EVAL; + SetType(AstNodeType::DIRECT_EVAL); } // NOTE (csabahurton): friend relationship can be removed once there are getters for private fields diff --git a/ets2panda/ir/expressions/identifier.cpp b/ets2panda/ir/expressions/identifier.cpp index 57419e8539..761294fc28 100644 --- a/ets2panda/ir/expressions/identifier.cpp +++ b/ets2panda/ir/expressions/identifier.cpp @@ -35,7 +35,7 @@ Identifier::Identifier([[maybe_unused]] Tag const tag, Identifier const &other, Identifier::Identifier(ArenaAllocator *const allocator) : Identifier(ERROR_LITERAL, allocator) { - flags_ |= IdentifierFlags::ERROR_PLACEHOLDER; + AddIdFlags(IdentifierFlags::ERROR_PLACEHOLDER); InitHistory(); } @@ -43,7 +43,7 @@ Identifier::Identifier(util::StringView const name, ArenaAllocator *const alloca : AnnotatedExpression(AstNodeType::IDENTIFIER), name_(name), decorators_(allocator->Adapter()) { if (name == ERROR_LITERAL) { - flags_ |= IdentifierFlags::ERROR_PLACEHOLDER; + AddIdFlags(IdentifierFlags::ERROR_PLACEHOLDER); } InitHistory(); } @@ -52,7 +52,7 @@ Identifier::Identifier(util::StringView const name, TypeNode *const typeAnnotati : AnnotatedExpression(AstNodeType::IDENTIFIER, typeAnnotation), name_(name), decorators_(allocator->Adapter()) { if (name == ERROR_LITERAL) { - flags_ |= IdentifierFlags::ERROR_PLACEHOLDER; + AddIdFlags(IdentifierFlags::ERROR_PLACEHOLDER); } InitHistory(); } diff --git a/ets2panda/ir/expressions/objectExpression.cpp b/ets2panda/ir/expressions/objectExpression.cpp index 13fff0d89b..f10bb038ea 100644 --- a/ets2panda/ir/expressions/objectExpression.cpp +++ b/ets2panda/ir/expressions/objectExpression.cpp @@ -215,7 +215,7 @@ void ObjectExpression::Iterate(const NodeTraverser &cb) const void ObjectExpression::Dump(ir::AstDumper *dumper) const { - dumper->Add({{"type", (type_ == AstNodeType::OBJECT_EXPRESSION) ? "ObjectExpression" : "ObjectPattern"}, + dumper->Add({{"type", (Type() == AstNodeType::OBJECT_EXPRESSION) ? "ObjectExpression" : "ObjectPattern"}, {"decorators", AstDumper::Optional(decorators_)}, {"properties", properties_}, {"typeAnnotation", AstDumper::Optional(TypeAnnotation())}, diff --git a/ets2panda/ir/statements/functionDeclaration.h b/ets2panda/ir/statements/functionDeclaration.h index 264207ceba..9068ff3806 100644 --- a/ets2panda/ir/statements/functionDeclaration.h +++ b/ets2panda/ir/statements/functionDeclaration.h @@ -36,7 +36,7 @@ public: { InitHistory(); if (func != nullptr) { - flags_ = func->Modifiers(); + AddModifier(func->Modifiers()); } } @@ -48,7 +48,7 @@ public: { InitHistory(); if (func != nullptr) { - flags_ = func->Modifiers(); + AddModifier(func->Modifiers()); } } diff --git a/ets2panda/ir/ts/tsArrayType.cpp b/ets2panda/ir/ts/tsArrayType.cpp index b5f988027e..a7d1651706 100644 --- a/ets2panda/ir/ts/tsArrayType.cpp +++ b/ets2panda/ir/ts/tsArrayType.cpp @@ -103,7 +103,7 @@ TSArrayType *TSArrayType::Clone(ArenaAllocator *const allocator, AstNode *const auto *const clone = allocator->New(elementTypeClone, allocator); ES2PANDA_ASSERT(clone != nullptr); - clone->AddModifier(flags_); + clone->AddModifier(Modifiers()); if (elementTypeClone != nullptr) { elementTypeClone->SetParent(clone); -- Gitee From f73602524338016cb441231817eefccfc63ab7c3 Mon Sep 17 00:00:00 2001 From: Geng Chen Date: Thu, 7 Aug 2025 11:29:17 +0800 Subject: [PATCH 2/6] remove locks to save space Signed-off-by: Geng Chen --- ets2panda/checker/ETSchecker.h | 7 +------ ets2panda/checker/types/ets/etsObjectType.cpp | 1 - ets2panda/checker/types/type.cpp | 2 -- ets2panda/checker/types/type.h | 4 +--- ets2panda/ir/astNodeHistory.cpp | 3 --- ets2panda/ir/astNodeHistory.h | 3 --- 6 files changed, 2 insertions(+), 18 deletions(-) diff --git a/ets2panda/checker/ETSchecker.h b/ets2panda/checker/ETSchecker.h index d27cf96faa..8206f0c52f 100644 --- a/ets2panda/checker/ETSchecker.h +++ b/ets2panda/checker/ETSchecker.h @@ -17,7 +17,6 @@ #define ES2PANDA_CHECKER_ETS_CHECKER_H #include -#include #include "checker/checker.h" @@ -859,10 +858,7 @@ public: return &dynamicCallNames_[static_cast(isConstruct)]; } - std::recursive_mutex *Mutex() - { - return &mtx_; - } + template T *AllocNode(Args &&...args) @@ -1118,7 +1114,6 @@ private: FunctionalInterfaceMap functionalInterfaceCache_; TypeMapping apparentTypes_; std::array dynamicCallNames_; - std::recursive_mutex mtx_; evaluate::ScopedDebugInfoPlugin *debugInfoPlugin_ {nullptr}; std::unordered_set elementStack_; ArenaVector overloadSigContainer_; diff --git a/ets2panda/checker/types/ets/etsObjectType.cpp b/ets2panda/checker/types/ets/etsObjectType.cpp index ebca1b901c..02a5305466 100644 --- a/ets2panda/checker/types/ets/etsObjectType.cpp +++ b/ets2panda/checker/types/ets/etsObjectType.cpp @@ -1126,7 +1126,6 @@ Type *ETSObjectType::Instantiate(ArenaAllocator *const allocator, TypeRelation * { relation = relation_; auto *const checker = relation->GetChecker()->AsETSChecker(); - std::lock_guard guard {*checker->Mutex()}; auto *const base = GetOriginalBaseType(); if (!relation->IsAtTypeDepthLimit(base)) { diff --git a/ets2panda/checker/types/type.cpp b/ets2panda/checker/types/type.cpp index 61a6b8568e..2b0e81e9b8 100644 --- a/ets2panda/checker/types/type.cpp +++ b/ets2panda/checker/types/type.cpp @@ -23,8 +23,6 @@ namespace ark::es2panda::checker { -std::mutex Type::idLock_ {}; - bool Type::IsETSResizableArrayType() const { return IsETSObjectType() && AsETSObjectType()->HasObjectFlag(ETSObjectFlags::BUILTIN_ARRAY); diff --git a/ets2panda/checker/types/type.h b/ets2panda/checker/types/type.h index 3840d6ab66..ac9cdfe75b 100644 --- a/ets2panda/checker/types/type.h +++ b/ets2panda/checker/types/type.h @@ -16,7 +16,6 @@ #ifndef ES2PANDA_COMPILER_CHECKER_TYPES_TYPE_H #define ES2PANDA_COMPILER_CHECKER_TYPES_TYPE_H -#include #include "generated/signatures.h" #include "checker/types/typeMapping.h" #include "checker/types/typeRelation.h" @@ -51,7 +50,6 @@ class Type { public: explicit Type(TypeFlag flag) : typeFlags_(flag) { - std::lock_guard lock(idLock_); static uint32_t typeId = 0; ES2PANDA_ASSERT(typeId < std::numeric_limits::max()); id_ = ++typeId; @@ -61,7 +59,7 @@ public: NO_MOVE_SEMANTIC(Type); virtual ~Type() = default; - static std::mutex idLock_; + // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) #define TYPE_IS_CHECKS(typeFlag, typeName) \ diff --git a/ets2panda/ir/astNodeHistory.cpp b/ets2panda/ir/astNodeHistory.cpp index 5d46aea8b2..89a87fad29 100644 --- a/ets2panda/ir/astNodeHistory.cpp +++ b/ets2panda/ir/astNodeHistory.cpp @@ -55,7 +55,6 @@ AstNode *AstNodeHistory::FindForwardEquals(compiler::PhaseId phaseId) // (e.g. find the node history record with `phaseId` equal to a given value) AstNode *AstNodeHistory::At(compiler::PhaseId phaseId) { - std::lock_guard lock(itemMutex_); if (LIKELY(item_->data.phaseId == phaseId)) { // Start searching with last accessed item // In most cases last accessed item is the one we are looking for @@ -73,7 +72,6 @@ AstNode *AstNodeHistory::At(compiler::PhaseId phaseId) // (e.g. find last node history record with `phaseId` less or equal to a given value) AstNode *AstNodeHistory::Get(compiler::PhaseId phaseId) { - std::lock_guard lock(itemMutex_); auto found = FindLessOrEquals(phaseId); if (LIKELY(found != nullptr)) { item_ = found; @@ -86,7 +84,6 @@ AstNode *AstNodeHistory::Get(compiler::PhaseId phaseId) // Find node state at phase with a given ID and set its new value, insert new history record if not found void AstNodeHistory::Set(AstNode *node, compiler::PhaseId phaseId) { - std::lock_guard lock(itemMutex_); HistoryRecord record {node, phaseId}; if (LIKELY(list_.Empty() || list_.Tail()->data.phaseId < phaseId)) { item_ = list_.Append(record); diff --git a/ets2panda/ir/astNodeHistory.h b/ets2panda/ir/astNodeHistory.h index e424046403..ffad5b770d 100644 --- a/ets2panda/ir/astNodeHistory.h +++ b/ets2panda/ir/astNodeHistory.h @@ -16,8 +16,6 @@ #ifndef ES2PANDA_IR_AST_NODE_HISTORY_H #define ES2PANDA_IR_AST_NODE_HISTORY_H -#include - #include "ir/astNode.h" #include "compiler/lowering/phase_id.h" #include "util/doubleLinkedList.h" @@ -50,7 +48,6 @@ private: HistoryList list_; // Node history list HistoryList::Item *item_ {nullptr}; // Last accessed history record - std::mutex itemMutex_ {}; }; } // namespace ark::es2panda::ir #endif -- Gitee From 7c9f40a76c6de54fa93a9fc613a185b4d5bcd1ec Mon Sep 17 00:00:00 2001 From: Geng Chen Date: Thu, 7 Aug 2025 12:02:10 +0800 Subject: [PATCH 3/6] use lazy init in ETSFunctionType for extensionFunctionSigs_ and extensionAccessorSigs_; Signed-off-by: Geng Chen --- ets2panda/checker/ets/function.cpp | 4 +-- ets2panda/checker/ets/helpers.cpp | 6 ++-- .../checker/types/ets/etsFunctionType.cpp | 36 +++++++++++++++---- ets2panda/checker/types/ets/etsFunctionType.h | 20 ++++------- 4 files changed, 41 insertions(+), 25 deletions(-) diff --git a/ets2panda/checker/ets/function.cpp b/ets2panda/checker/ets/function.cpp index 44b4e29a22..8384276129 100644 --- a/ets2panda/checker/ets/function.cpp +++ b/ets2panda/checker/ets/function.cpp @@ -1454,9 +1454,9 @@ static bool CollectOverload(checker::ETSChecker *checker, ir::MethodDefinition * auto overloadSig = currentFunc->Function()->Signature(); funcType->AddCallSignature(overloadSig); if (overloadSig->IsExtensionAccessor()) { - funcType->GetExtensionAccessorSigs().emplace_back(overloadSig); + funcType->GetExtensionAccessorSigs(checker).emplace_back(overloadSig); } else if (overloadSig->IsExtensionFunction()) { - funcType->GetExtensionFunctionSigs().emplace_back(overloadSig); + funcType->GetExtensionFunctionSigs(checker).emplace_back(overloadSig); } overloads.push_back(overloadType); diff --git a/ets2panda/checker/ets/helpers.cpp b/ets2panda/checker/ets/helpers.cpp index bf9c6c2c56..7047e7df22 100644 --- a/ets2panda/checker/ets/helpers.cpp +++ b/ets2panda/checker/ets/helpers.cpp @@ -1004,7 +1004,7 @@ Signature *ETSChecker::FindRelativeExtensionGetter(ir::MemberExpression *const e ArenaVector arguments(ProgramAllocator()->Adapter()); arguments.insert(arguments.begin(), expr->Object()); // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - Signature *signature = ValidateSignatures(funcType->GetExtensionAccessorSigs(), nullptr, arguments, expr->Start(), + Signature *signature = ValidateSignatures(funcType->GetExtensionAccessorSigs(this), nullptr, arguments, expr->Start(), "call", TypeRelationFlag::NO_THROW); if (signature != nullptr) { InsertExtensionGetterToMap(funcType->Name(), expr->ObjType(), signature); @@ -1028,7 +1028,7 @@ Signature *ETSChecker::FindRelativeExtensionSetter(ir::MemberExpression *expr, E if (expr->Parent()->IsAssignmentExpression()) { arguments.emplace_back(expr->Parent()->AsAssignmentExpression()->Right()); // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - signature = ValidateSignatures(funcType->GetExtensionAccessorSigs(), nullptr, arguments, expr->Start(), "call", + signature = ValidateSignatures(funcType->GetExtensionAccessorSigs(this), nullptr, arguments, expr->Start(), "call", TypeRelationFlag::NO_THROW); } else { // When handle ++a.m, a.m++, is mean to check whether a.m(xx, 1) existed. @@ -1036,7 +1036,7 @@ Signature *ETSChecker::FindRelativeExtensionSetter(ir::MemberExpression *expr, E Type *getterReturnType = ResolveGetter(this, expr, funcType); expr->SetTsType(getterReturnType); arguments.emplace_back(expr); - signature = ValidateSignatures(funcType->GetExtensionAccessorSigs(), nullptr, arguments, expr->Start(), "call", + signature = ValidateSignatures(funcType->GetExtensionAccessorSigs(this), nullptr, arguments, expr->Start(), "call", TypeRelationFlag::NO_THROW); } diff --git a/ets2panda/checker/types/ets/etsFunctionType.cpp b/ets2panda/checker/types/ets/etsFunctionType.cpp index b3d97f28b7..a0c9b6c34c 100644 --- a/ets2panda/checker/types/ets/etsFunctionType.cpp +++ b/ets2panda/checker/types/ets/etsFunctionType.cpp @@ -23,8 +23,8 @@ ETSFunctionType::ETSFunctionType([[maybe_unused]] ETSChecker *checker, util::Str ArenaVector &&signatures) : Type(TypeFlag::FUNCTION | TypeFlag::ETS_METHOD), callSignatures_(std::move(signatures)), - extensionFunctionSigs_(ArenaVector(checker->ProgramAllocator()->Adapter())), - extensionAccessorSigs_(ArenaVector(checker->ProgramAllocator()->Adapter())), + extensionFunctionSigs_(nullptr), + extensionAccessorSigs_(nullptr), name_(name) { auto flag = TypeFlag::NONE; @@ -32,9 +32,15 @@ ETSFunctionType::ETSFunctionType([[maybe_unused]] ETSChecker *checker, util::Str flag |= sig->HasSignatureFlag(SignatureFlags::GETTER) ? TypeFlag::GETTER : TypeFlag::NONE; flag |= sig->HasSignatureFlag(SignatureFlags::SETTER) ? TypeFlag::SETTER : TypeFlag::NONE; if (sig->IsExtensionAccessor()) { - extensionAccessorSigs_.emplace_back(sig); + if (extensionAccessorSigs_ == nullptr) { + extensionAccessorSigs_ = checker->ProgramAllocator()->New>(checker->ProgramAllocator()->Adapter()); + } + extensionAccessorSigs_->emplace_back(sig); } else if (sig->IsExtensionFunction()) { - extensionFunctionSigs_.emplace_back(sig); + if (extensionFunctionSigs_ == nullptr) { + extensionFunctionSigs_ = checker->ProgramAllocator()->New>(checker->ProgramAllocator()->Adapter()); + } + extensionFunctionSigs_->emplace_back(sig); } } AddTypeFlag(flag); @@ -43,8 +49,8 @@ ETSFunctionType::ETSFunctionType([[maybe_unused]] ETSChecker *checker, util::Str ETSFunctionType::ETSFunctionType(ETSChecker *checker, Signature *signature) : Type(TypeFlag::FUNCTION), callSignatures_({{signature->ToArrowSignature(checker)}, checker->ProgramAllocator()->Adapter()}), - extensionFunctionSigs_(ArenaVector(checker->ProgramAllocator()->Adapter())), - extensionAccessorSigs_(ArenaVector(checker->ProgramAllocator()->Adapter())), + extensionFunctionSigs_(nullptr), + extensionAccessorSigs_(nullptr), name_(""), assemblerName_(checker->GlobalBuiltinFunctionType(signature->MinArgCount(), signature->HasRestParameter()) != nullptr @@ -416,4 +422,22 @@ void ETSFunctionType::CheckVarianceRecursively(TypeRelation *relation, VarianceF } } +ArenaVector &ETSFunctionType::GetExtensionAccessorSigs(ETSChecker *checker) +{ + ES2PANDA_ASSERT(!IsETSArrowType()); + if (extensionAccessorSigs_ == nullptr) { + extensionAccessorSigs_ = checker->ProgramAllocator()->New>(checker->ProgramAllocator()->Adapter()); + } + return *extensionAccessorSigs_; +} + +ArenaVector &ETSFunctionType::GetExtensionFunctionSigs(ETSChecker *checker) +{ + ES2PANDA_ASSERT(!IsETSArrowType()); + if (extensionFunctionSigs_ == nullptr) { + extensionFunctionSigs_ = checker->ProgramAllocator()->New>(checker->ProgramAllocator()->Adapter()); + } + return *extensionFunctionSigs_; +} + } // namespace ark::es2panda::checker diff --git a/ets2panda/checker/types/ets/etsFunctionType.h b/ets2panda/checker/types/ets/etsFunctionType.h index ffc9e8ea59..3ebb6ef10d 100644 --- a/ets2panda/checker/types/ets/etsFunctionType.h +++ b/ets2panda/checker/types/ets/etsFunctionType.h @@ -79,17 +79,9 @@ public: return FindSpecificSignature([](auto const *const sig) -> bool { return sig->Function()->IsSetter(); }); } - [[nodiscard]] ArenaVector &GetExtensionAccessorSigs() - { - ES2PANDA_ASSERT(!IsETSArrowType()); - return extensionAccessorSigs_; - } + [[nodiscard]] ArenaVector &GetExtensionAccessorSigs(ETSChecker *checker); - [[nodiscard]] ArenaVector &GetExtensionFunctionSigs() - { - ES2PANDA_ASSERT(!IsETSArrowType()); - return extensionFunctionSigs_; - } + [[nodiscard]] ArenaVector &GetExtensionFunctionSigs(ETSChecker *checker); [[nodiscard]] Signature *FirstAbstractSignature() const noexcept { @@ -111,12 +103,12 @@ public: ETSObjectType *ArrowToFunctionalInterfaceDesiredArity(ETSChecker *checker, size_t arity); [[nodiscard]] bool IsExtensionFunctionType() const { - return !extensionFunctionSigs_.empty() || !extensionAccessorSigs_.empty(); + return extensionFunctionSigs_ != nullptr && !extensionFunctionSigs_->empty(); } [[nodiscard]] bool IsExtensionAccessorType() const { - return !extensionAccessorSigs_.empty(); + return extensionAccessorSigs_ != nullptr && !extensionAccessorSigs_->empty(); } void ToAssemblerType(std::stringstream &ss) const override; @@ -156,8 +148,8 @@ public: private: ArenaVector callSignatures_; - ArenaVector extensionFunctionSigs_; - ArenaVector extensionAccessorSigs_; + ArenaVector *extensionFunctionSigs_; + ArenaVector *extensionAccessorSigs_; util::StringView const name_; util::StringView const assemblerName_; Signature *helperSignature_ {}; -- Gitee From 71b5b7c73137183d78b7a6dd0f8a639a037e9316 Mon Sep 17 00:00:00 2001 From: Geng Chen Date: Thu, 7 Aug 2025 14:50:02 +0800 Subject: [PATCH 4/6] use uint8_t in enum class MemberExpressionKind to save space Signed-off-by: Geng Chen --- ets2panda/ir/expressions/memberExpression.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ets2panda/ir/expressions/memberExpression.h b/ets2panda/ir/expressions/memberExpression.h index 4c72e652fe..0f2554fe11 100644 --- a/ets2panda/ir/expressions/memberExpression.h +++ b/ets2panda/ir/expressions/memberExpression.h @@ -38,7 +38,7 @@ inline constexpr char const PREDEFINED_METHOD[] = "The special predefined method using ENUMBITOPS_OPERATORS; -enum class MemberExpressionKind : uint32_t { +enum class MemberExpressionKind : uint8_t { NONE = 0, ELEMENT_ACCESS = 1U << 0U, PROPERTY_ACCESS = 1U << 1U, -- Gitee From b59663ff013b704b1ad0ed3f72aeedb784c20c65 Mon Sep 17 00:00:00 2001 From: Geng Chen Date: Thu, 7 Aug 2025 15:31:44 +0800 Subject: [PATCH 5/6] use bitfield to save 8B for every CallExpression Signed-off-by: Geng Chen --- ets2panda/ir/expressions/callExpression.cpp | 35 ++++++++++----------- ets2panda/ir/expressions/callExpression.h | 32 +++++++++---------- ets2panda/parser/expressionParser.cpp | 2 +- 3 files changed, 34 insertions(+), 35 deletions(-) diff --git a/ets2panda/ir/expressions/callExpression.cpp b/ets2panda/ir/expressions/callExpression.cpp index c0619e941d..920db4593e 100644 --- a/ets2panda/ir/expressions/callExpression.cpp +++ b/ets2panda/ir/expressions/callExpression.cpp @@ -41,10 +41,10 @@ void CallExpression::TransformChildren(const NodeTransformer &cb, std::string_vi } } - if (trailingLambdaInfo_.block != nullptr) { - if (auto *transformedNode = cb(trailingLambdaInfo_.block); trailingLambdaInfo_.block != transformedNode) { - trailingLambdaInfo_.block->SetTransformedNode(transformationName, transformedNode); - trailingLambdaInfo_.block = transformedNode->AsBlockStatement(); + if (trailingBlock_ != nullptr) { + if (auto *transformedNode = cb(trailingBlock_); trailingBlock_ != transformedNode) { + trailingBlock_->SetTransformedNode(transformationName, transformedNode); + trailingBlock_ = transformedNode->AsBlockStatement(); } } } @@ -61,8 +61,8 @@ void CallExpression::Iterate(const NodeTraverser &cb) const cb(it); } - if (trailingLambdaInfo_.block != nullptr) { - cb(trailingLambdaInfo_.block); + if (trailingBlock_ != nullptr) { + cb(trailingBlock_); } } @@ -96,11 +96,11 @@ void CallExpression::Dump(ir::SrcDumper *dumper) const } } dumper->Add(")"); - if (trailingLambdaInfo_.block != nullptr) { - if (trailingLambdaInfo_.isBlockInNewLine) { + if (trailingBlock_ != nullptr) { + if (flags_.isBlockInNewLine_) { dumper->Endl(); } - trailingLambdaInfo_.block->Dump(dumper); + trailingBlock_->Dump(dumper); } } @@ -128,9 +128,8 @@ CallExpression::CallExpression(CallExpression const &other, ArenaAllocator *cons : MaybeOptionalExpression(static_cast(other)), arguments_(allocator->Adapter()), signature_(other.signature_), - trailingComma_(other.trailingComma_), - trailingLambdaInfo_({other.trailingLambdaInfo_.block, other.trailingLambdaInfo_.isBlockInNewLine, - other.trailingLambdaInfo_.isTrailingCall}) + flags_(other.flags_), + trailingBlock_(nullptr) { callee_ = other.callee_->Clone(allocator, this)->AsExpression(); typeParams_ = other.typeParams_ != nullptr ? other.typeParams_->Clone(allocator, this) : nullptr; @@ -139,9 +138,9 @@ CallExpression::CallExpression(CallExpression const &other, ArenaAllocator *cons arguments_.emplace_back(argument->Clone(allocator, this)->AsExpression()); } - trailingLambdaInfo_.block = other.trailingLambdaInfo_.block != nullptr - ? other.trailingLambdaInfo_.block->Clone(allocator, this)->AsBlockStatement() - : nullptr; + trailingBlock_ = other.trailingBlock_ != nullptr + ? other.trailingBlock_->Clone(allocator, this)->AsBlockStatement() + : nullptr; } CallExpression *CallExpression::Clone(ArenaAllocator *const allocator, AstNode *const parent) @@ -166,9 +165,9 @@ void CallExpression::SetTypeParams(TSTypeParameterInstantiation *typeParams) noe void CallExpression::SetTrailingBlock(ir::BlockStatement *const block) noexcept { - trailingLambdaInfo_.block = block; - if (trailingLambdaInfo_.block != nullptr) { - trailingLambdaInfo_.block->SetParent(this); + trailingBlock_ = block; + if (trailingBlock_ != nullptr) { + trailingBlock_->SetParent(this); } } diff --git a/ets2panda/ir/expressions/callExpression.h b/ets2panda/ir/expressions/callExpression.h index 36d3e3be58..b8de73ea8b 100644 --- a/ets2panda/ir/expressions/callExpression.h +++ b/ets2panda/ir/expressions/callExpression.h @@ -49,9 +49,9 @@ public: : MaybeOptionalExpression(AstNodeType::CALL_EXPRESSION, optional), callee_(callee), arguments_(std::move(arguments)), - typeParams_(typeParams), - trailingComma_(trailingComma) + typeParams_(typeParams) { + flags_.trailingComma_ = trailingComma; } explicit CallExpression(CallExpression const &other, ArenaAllocator *allocator); @@ -98,9 +98,9 @@ public: return arguments_; } - [[nodiscard]] bool HasTrailingComma() const noexcept + [[nodiscard]] bool TrailingComma() const noexcept { - return trailingComma_; + return flags_.trailingComma_; } [[nodiscard]] checker::Signature *Signature() noexcept @@ -136,27 +136,27 @@ public: [[nodiscard]] ir::BlockStatement *TrailingBlock() const noexcept { - return trailingLambdaInfo_.block; + return trailingBlock_; } void SetIsTrailingBlockInNewLine(bool const isNewLine) noexcept { - trailingLambdaInfo_.isBlockInNewLine = isNewLine; + flags_.isBlockInNewLine_ = isNewLine; } [[nodiscard]] bool IsTrailingBlockInNewLine() const noexcept { - return trailingLambdaInfo_.isBlockInNewLine; + return flags_.isBlockInNewLine_; } void SetIsTrailingCall(bool const isTrailingCall) noexcept { - trailingLambdaInfo_.isTrailingCall = isTrailingCall; + flags_.isTrailingCall_ = isTrailingCall; } [[nodiscard]] bool IsTrailingCall() const noexcept { - return trailingLambdaInfo_.isTrailingCall; + return flags_.isTrailingCall_; } bool IsETSConstructorCall() const noexcept @@ -191,10 +191,11 @@ public: } private: - struct TrailingLambdaInfo { - ir::BlockStatement *block {nullptr}; - bool isTrailingCall {false}; - bool isBlockInNewLine {false}; + struct CallFlags { + bool trailingComma_ : 1; + bool isTrailingCall_ : 1; + bool isBlockInNewLine_ : 1; + uint32_t reserved_ : 29; }; protected: @@ -203,9 +204,8 @@ protected: ArenaVector arguments_; TSTypeParameterInstantiation *typeParams_; checker::Signature *signature_ {}; - bool trailingComma_; - // for trailing lambda feature in ets - TrailingLambdaInfo trailingLambdaInfo_ {}; + CallFlags flags_ {}; + ir::BlockStatement *trailingBlock_ = nullptr; checker::Type *uncheckedType_ {}; // NOLINTEND(misc-non-private-member-variables-in-classes) }; diff --git a/ets2panda/parser/expressionParser.cpp b/ets2panda/parser/expressionParser.cpp index 89cd7fa069..6510e038ed 100644 --- a/ets2panda/parser/expressionParser.cpp +++ b/ets2panda/parser/expressionParser.cpp @@ -391,7 +391,7 @@ ArrowFunctionDescriptor ParserImpl::ConvertToArrowParameter(ir::Expression *expr auto *callExpression = expr->AsCallExpression(); auto &arguments = callExpression->Arguments(); - if (callExpression->HasTrailingComma()) { + if (callExpression->TrailingComma()) { ES2PANDA_ASSERT(!arguments.empty()); LogError(diagnostic::REST_PARAM_NOT_LAST, {}, arguments.back()->End()); } -- Gitee From 46f5e9b85f7a3b3b23d07562a7a6744e0f96c15a Mon Sep 17 00:00:00 2001 From: Geng Chen Date: Thu, 7 Aug 2025 20:05:46 +0800 Subject: [PATCH 6/6] use bitfield to save 4B for scriptFunction Signed-off-by: Geng Chen --- ets2panda/ir/base/scriptFunction.cpp | 9 +++----- ets2panda/ir/base/scriptFunction.h | 29 +++++++++++++++++++----- ets2panda/test/unit/sizeof_node_test.cpp | 3 +-- 3 files changed, 27 insertions(+), 14 deletions(-) diff --git a/ets2panda/ir/base/scriptFunction.cpp b/ets2panda/ir/base/scriptFunction.cpp index a2bf25c587..ad9c4f061f 100644 --- a/ets2panda/ir/base/scriptFunction.cpp +++ b/ets2panda/ir/base/scriptFunction.cpp @@ -113,8 +113,7 @@ ScriptFunction::ScriptFunction(ArenaAllocator *allocator, ScriptFunctionData &&d : AnnotationAllowed(AstNodeType::SCRIPT_FUNCTION, data.flags, allocator), irSignature_(std::move(data.signature)), body_(data.body), - funcFlags_(data.funcFlags), - lang_(data.lang), + packed_{static_cast(data.funcFlags), static_cast(data.lang.GetId()), 0}, returnStatements_(allocator->Adapter()) { for (auto *param : irSignature_.Params()) { @@ -135,8 +134,7 @@ ScriptFunction::ScriptFunction(ArenaAllocator *allocator, ScriptFunctionData &&d : AnnotationAllowed(AstNodeType::SCRIPT_FUNCTION, data.flags, allocator), irSignature_(std::move(data.signature)), body_(data.body), - funcFlags_(data.funcFlags), - lang_(data.lang), + packed_{static_cast(data.funcFlags), static_cast(data.lang.GetId()), 0}, returnStatements_(allocator->Adapter()) { for (auto *param : irSignature_.Params()) { @@ -392,10 +390,9 @@ void ScriptFunction::CopyTo(AstNode *other) const otherImpl->body_ = body_; otherImpl->scope_ = scope_; - otherImpl->funcFlags_ = funcFlags_; + otherImpl->packed_ = packed_; otherImpl->signature_ = signature_; otherImpl->preferredReturnType_ = preferredReturnType_; - otherImpl->lang_ = lang_; otherImpl->returnStatements_ = returnStatements_; AnnotationAllowed::CopyTo(other); diff --git a/ets2panda/ir/base/scriptFunction.h b/ets2panda/ir/base/scriptFunction.h index e0d169804b..3947a3e1c6 100644 --- a/ets2panda/ir/base/scriptFunction.h +++ b/ets2panda/ir/base/scriptFunction.h @@ -265,7 +265,7 @@ public: [[nodiscard]] ir::ScriptFunctionFlags Flags() const noexcept { - return GetHistoryNodeAs()->funcFlags_; + return static_cast(GetHistoryNodeAs()->packed_.funcFlags); } [[nodiscard]] bool HasReceiver() const noexcept @@ -280,17 +280,27 @@ public: void AddFlag(ir::ScriptFunctionFlags flags) noexcept { if (!All(Flags(), flags)) { - GetOrCreateHistoryNode()->AsScriptFunction()->funcFlags_ |= flags; + GetOrCreateHistoryNode()->AsScriptFunction()->packed_.funcFlags |= static_cast(flags); } } void ClearFlag(ir::ScriptFunctionFlags flags) noexcept { if (Any(Flags(), flags)) { - GetOrCreateHistoryNode()->AsScriptFunction()->funcFlags_ &= ~flags; + GetOrCreateHistoryNode()->AsScriptFunction()->packed_.funcFlags &= ~static_cast(flags); } } + void SetFlag(ir::ScriptFunctionFlags flags) noexcept + { + GetOrCreateHistoryNode()->AsScriptFunction()->packed_.funcFlags = static_cast(flags); + } + + void SetLanguage(es2panda::Language lang) noexcept + { + GetOrCreateHistoryNode()->AsScriptFunction()->packed_.lang = static_cast(lang.GetId()); + } + [[nodiscard]] std::size_t FormalParamsLength() const noexcept; [[nodiscard]] bool IsScopeBearer() const noexcept override @@ -312,7 +322,7 @@ public: [[nodiscard]] es2panda::Language Language() const noexcept { - return GetHistoryNodeAs()->lang_; + return es2panda::Language(static_cast(GetHistoryNodeAs()->packed_.lang)); } void SetPreferredReturnType(checker::Type *preferredReturnType); @@ -367,14 +377,21 @@ private: void DumpBody(ir::SrcDumper *dumper) const; void DumpCheckerTypeForDeclGen(ir::SrcDumper *dumper) const; friend class SizeOfNodeTest; + + // Bit-field optimization: pack funcFlags_ and lang_ into 32 bits + struct PackedData { + uint32_t funcFlags : 25; // ScriptFunctionFlags needs 25 bits (0-24) + uint32_t lang : 3; // Language::Id needs 3 bits (AS, JS, TS, ETS, COUNT) + uint32_t reserved : 4; // Reserved for future use + }; + Identifier *id_ {}; FunctionSignature irSignature_; AstNode *body_; varbinder::FunctionScope *scope_ {nullptr}; - ir::ScriptFunctionFlags funcFlags_; + PackedData packed_ {}; checker::Signature *signature_ {}; checker::Type *preferredReturnType_ {}; - es2panda::Language lang_; ArenaVector returnStatements_; }; } // namespace ark::es2panda::ir diff --git a/ets2panda/test/unit/sizeof_node_test.cpp b/ets2panda/test/unit/sizeof_node_test.cpp index 5980cba512..669eb84786 100644 --- a/ets2panda/test/unit/sizeof_node_test.cpp +++ b/ets2panda/test/unit/sizeof_node_test.cpp @@ -245,10 +245,9 @@ size_t SizeOfNodeTest::SizeOf() Align(sizeof(node->irSignature_)) + sizeof(node->body_) + sizeof(node->scope_) + - Align(sizeof(node->funcFlags_)) + + Align(sizeof(node->packed_)) + sizeof(node->signature_) + sizeof(node->preferredReturnType_) + - Align(sizeof(node->lang_)) + sizeof(node->returnStatements_); // clang-format on } -- Gitee