diff --git a/ets2panda/checker/ETSAnalyzer.cpp b/ets2panda/checker/ETSAnalyzer.cpp index e611b5aef73fe58ff9f00506411528c7c118e0aa..b142ddbe1db8d3b060c0d347d38520aa3bd9197f 100644 --- a/ets2panda/checker/ETSAnalyzer.cpp +++ b/ets2panda/checker/ETSAnalyzer.cpp @@ -29,6 +29,7 @@ #include "types/type.h" #include "checker/types/typeError.h" #include "util/es2pandaMacros.h" +#include "util/perfMetrics.h" #include @@ -44,6 +45,7 @@ ETSChecker *ETSAnalyzer::GetETSChecker() const // from base folder checker::Type *ETSAnalyzer::Check(ir::CatchClause *st) const { + ES2PANDA_PERF_SCOPELESS("@Check-CatchClause"); ETSChecker *checker = GetETSChecker(); checker::Type *exceptionType = checker->GlobalTypeError(); @@ -83,6 +85,7 @@ checker::Type *ETSAnalyzer::Check(ir::CatchClause *st) const checker::Type *ETSAnalyzer::Check(ir::ClassDefinition *node) const { + ES2PANDA_PERF_SCOPELESS("@Check-ClassDefinition"); ETSChecker *checker = GetETSChecker(); if (node->TsType() == nullptr) { @@ -98,6 +101,7 @@ checker::Type *ETSAnalyzer::Check(ir::ClassDefinition *node) const checker::Type *ETSAnalyzer::Check(ir::ClassProperty *st) const { + ES2PANDA_PERF_SCOPELESS("@Check-ClassProperty"); if (st->TsType() != nullptr) { return st->TsType(); } @@ -150,6 +154,7 @@ checker::Type *ETSAnalyzer::Check(ir::ClassProperty *st) const checker::Type *ETSAnalyzer::Check(ir::ClassStaticBlock *st) const { + ES2PANDA_PERF_SCOPELESS("@Check-StaticBlock"); ETSChecker *checker = GetETSChecker(); if (checker->HasStatus(checker::CheckerStatus::INNER_CLASS)) { @@ -218,6 +223,7 @@ static bool IsInitializerBlockTransfer(std::string_view str) checker::Type *ETSAnalyzer::Check(ir::MethodDefinition *node) const { + ES2PANDA_PERF_SCOPELESS("@Check-MethodDefinition"); ETSChecker *checker = GetETSChecker(); auto *scriptFunc = node->Function(); @@ -366,6 +372,7 @@ static void CheckOverloadSameNameMethod(ETSChecker *const checker, ir::OverloadD checker::Type *ETSAnalyzer::Check(ir::OverloadDeclaration *node) const { + ES2PANDA_PERF_SCOPELESS("@Check-OverloadDeclaration"); ETSChecker *checker = GetETSChecker(); ES2PANDA_ASSERT(node != nullptr); ES2PANDA_ASSERT(node->Key()); @@ -394,12 +401,14 @@ checker::Type *ETSAnalyzer::Check(ir::OverloadDeclaration *node) const checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::Property *expr) const { + ES2PANDA_PERF_SCOPELESS("@Check-Property"); ETSChecker *checker = GetETSChecker(); return checker->GlobalTypeError(); } checker::Type *ETSAnalyzer::Check(ir::SpreadElement *expr) const { + ES2PANDA_PERF_SCOPELESS("@Check-SpreadElement"); if (expr->TsType() != nullptr) { return expr->TsType(); } @@ -429,6 +438,7 @@ checker::Type *ETSAnalyzer::Check(ir::SpreadElement *expr) const checker::Type *ETSAnalyzer::Check(ir::TemplateElement *expr) const { + ES2PANDA_PERF_SCOPELESS("@Check-SpreadElement"); ETSChecker *checker = GetETSChecker(); expr->SetTsType(checker->CreateETSStringLiteralType(expr->Raw())); return expr->TsType(); @@ -436,6 +446,7 @@ checker::Type *ETSAnalyzer::Check(ir::TemplateElement *expr) const checker::Type *ETSAnalyzer::Check(ir::ETSClassLiteral *expr) const { + ES2PANDA_PERF_SCOPELESS("@Check-ETSClassLiteral"); ETSChecker *checker = GetETSChecker(); auto *const literal = expr->Expr(); @@ -462,6 +473,7 @@ checker::Type *ETSAnalyzer::Check(ir::ETSClassLiteral *expr) const checker::Type *ETSAnalyzer::Check(ir::ETSFunctionType *node) const { + ES2PANDA_PERF_SCOPELESS("@Check-ETSFunctionType"); if (node->TsType() != nullptr) { return node->TsType(); } @@ -538,6 +550,7 @@ static bool NeedCreateETSResizableArrayType(ETSChecker *checker, Type *type) checker::Type *ETSAnalyzer::Check(ir::ETSNewArrayInstanceExpression *expr) const { + ES2PANDA_PERF_SCOPELESS("@Check-ETSNewArrayInstanceExpression"); if (expr->TsType() != nullptr) { return expr->TsType(); } @@ -602,6 +615,7 @@ static checker::Type *CheckInstantiatedNewType(ETSChecker *checker, ir::ETSNewCl checker::Type *ETSAnalyzer::Check(ir::ETSNewClassInstanceExpression *expr) const { + ES2PANDA_PERF_SCOPELESS("@Check-ETSNewClassInstanceExpression"); if (expr->TsType() != nullptr) { return expr->TsType(); } @@ -630,6 +644,7 @@ checker::Type *ETSAnalyzer::Check(ir::ETSNewClassInstanceExpression *expr) const checker::Type *ETSAnalyzer::Check(ir::ETSNewMultiDimArrayInstanceExpression *expr) const { + ES2PANDA_PERF_SCOPELESS("@Check-ETSNewMultiDimArrayInstanceExpression"); if (expr->TsType() != nullptr) { return expr->TsType(); } @@ -662,11 +677,13 @@ checker::Type *ETSAnalyzer::Check(ir::ETSNewMultiDimArrayInstanceExpression *exp checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::ETSPackageDeclaration *st) const { + ES2PANDA_PERF_SCOPELESS("@Check-ETSPackageDeclaration"); return ReturnTypeForStatement(st); } checker::Type *ETSAnalyzer::Check(ir::ETSParameterExpression *expr) const { + ES2PANDA_PERF_SCOPELESS("@Check-ETSParameterExpression"); ETSChecker *checker = GetETSChecker(); if (expr->TsType() != nullptr) { return expr->TsType(); @@ -687,12 +704,14 @@ checker::Type *ETSAnalyzer::Check(ir::ETSParameterExpression *expr) const checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::ETSPrimitiveType *node) const { + ES2PANDA_PERF_SCOPELESS("@Check-ETSPrimitiveType"); ETSChecker *checker = GetETSChecker(); return node->GetType(checker); } checker::Type *ETSAnalyzer::Check(ir::ETSStructDeclaration *node) const { + ES2PANDA_PERF_SCOPELESS("@Check-ETSStructDeclaration"); ETSChecker *checker = GetETSChecker(); node->Definition()->Check(checker); return ReturnTypeForStatement(node); @@ -700,6 +719,7 @@ checker::Type *ETSAnalyzer::Check(ir::ETSStructDeclaration *node) const checker::Type *ETSAnalyzer::Check(ir::ETSTypeReference *node) const { + ES2PANDA_PERF_SCOPELESS("@Check-ETSTypeReference"); ETSChecker *checker = GetETSChecker(); checker->CheckAnnotations(node->Annotations()); return node->GetType(checker); @@ -707,12 +727,14 @@ checker::Type *ETSAnalyzer::Check(ir::ETSTypeReference *node) const checker::Type *ETSAnalyzer::Check(ir::ETSTypeReferencePart *node) const { + ES2PANDA_PERF_SCOPELESS("@Check-ETSTypeReferencePart"); ETSChecker *checker = GetETSChecker(); return node->GetType(checker); } checker::Type *ETSAnalyzer::Check(ir::ETSNonNullishTypeNode *node) const { + ES2PANDA_PERF_SCOPELESS("@Check-ETSNonNullishTypeNode"); if (node->TsType() != nullptr) { return node->TsType(); } @@ -722,6 +744,7 @@ checker::Type *ETSAnalyzer::Check(ir::ETSNonNullishTypeNode *node) const checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::ETSNullType *node) const { + ES2PANDA_PERF_SCOPELESS("@Check-ETSNullType"); ETSChecker *checker = GetETSChecker(); checker->CheckAnnotations(node->Annotations()); return node->SetTsType(checker->GlobalETSNullType()); @@ -729,6 +752,7 @@ checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::ETSNullType *node) const checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::ETSUndefinedType *node) const { + ES2PANDA_PERF_SCOPELESS("@Check-ETSUndefinedType"); ETSChecker *checker = GetETSChecker(); checker->CheckAnnotations(node->Annotations()); return node->SetTsType(checker->GlobalETSUndefinedType()); @@ -736,12 +760,14 @@ checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::ETSUndefinedType *node) c checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::ETSNeverType *node) const { + ES2PANDA_PERF_SCOPELESS("@Check-ETSNeverType"); ETSChecker *checker = GetETSChecker(); return checker->GlobalETSNeverType(); } checker::Type *ETSAnalyzer::Check(ir::ETSStringLiteralType *node) const { + ES2PANDA_PERF_SCOPELESS("@Check-ETSStringLiteralType"); ETSChecker *checker = GetETSChecker(); checker->CheckAnnotations(node->Annotations()); return node->GetType(checker); @@ -749,6 +775,7 @@ checker::Type *ETSAnalyzer::Check(ir::ETSStringLiteralType *node) const checker::Type *ETSAnalyzer::Check(ir::ETSKeyofType *node) const { + ES2PANDA_PERF_SCOPELESS("@Check-ETSKeyofType"); ETSChecker *checker = GetETSChecker(); return node->GetType(checker); } @@ -968,6 +995,7 @@ static Type *GetAppropriatePreferredType(Type *originalType, std::functionTsType() != nullptr) { return expr->TsType(); @@ -1036,6 +1064,7 @@ void TryInferPreferredType(ir::ArrowFunctionExpression *expr, checker::Type *pre checker::Type *ETSAnalyzer::Check(ir::ArrowFunctionExpression *expr) const { + ES2PANDA_PERF_SCOPELESS("@Check-ArrowFunctionExpession"); ETSChecker *checker = GetETSChecker(); checker->CheckAnnotations(expr->Annotations()); if (expr->TsType() != nullptr) { @@ -1231,6 +1260,7 @@ bool ETSAnalyzer::SetAssignmentExpressionTarget(ir::AssignmentExpression *const checker::Type *ETSAnalyzer::Check(ir::AssignmentExpression *const expr) const { + ES2PANDA_PERF_SCOPELESS("@Check-AssignmentExpression"); if (expr->TsType() != nullptr) { return expr->TsType(); } @@ -1359,6 +1389,7 @@ static bool IsPromiseType(checker::Type *type, ETSChecker *checker) checker::Type *ETSAnalyzer::Check(ir::AwaitExpression *expr) const { + ES2PANDA_PERF_SCOPELESS("@Check-AwaitExpression"); ETSChecker *checker = GetETSChecker(); if (expr->TsType() != nullptr) { return expr->TsType(); @@ -1420,6 +1451,7 @@ checker::Type *ETSAnalyzer::UnwrapPromiseType(checker::Type *type) const checker::Type *ETSAnalyzer::Check(ir::BinaryExpression *expr) const { + ES2PANDA_PERF_SCOPELESS("@Check-BinaryExpression"); if (expr->TsType() != nullptr) { return expr->TsType(); } @@ -1461,6 +1493,7 @@ checker::Type *ETSAnalyzer::Check(ir::BinaryExpression *expr) const checker::Type *ETSAnalyzer::Check(ir::BlockExpression *st) const { + ES2PANDA_PERF_SCOPELESS("@Check-BlockExpression"); if (st->TsType() != nullptr) { return st->TsType(); } @@ -1711,6 +1744,7 @@ static void CheckOverloadCall(ETSChecker *checker, ir::CallExpression *expr) checker::Type *ETSAnalyzer::Check(ir::CallExpression *expr) const { + ES2PANDA_PERF_SCOPELESS("@Check-CallExpression"); ETSChecker *checker = GetETSChecker(); if (expr->TsType() != nullptr) { return expr->TsType(); @@ -1799,6 +1833,7 @@ static Type *BiggerNumericType(ETSChecker *checker, Type *t1, Type *t2) checker::Type *ETSAnalyzer::Check(ir::ConditionalExpression *expr) const { + ES2PANDA_PERF_SCOPELESS("@Check-ConditionalExpression"); if (expr->TsType() != nullptr) { return expr->TsType(); } @@ -1902,6 +1937,7 @@ static Type *TransformTypeForMethodReference(ETSChecker *checker, ir::Expression checker::Type *ETSAnalyzer::Check(ir::Identifier *expr) const { + ES2PANDA_PERF_SCOPELESS("@Check-Identifier"); if (expr->TsType() != nullptr) { return expr->TsType(); } @@ -2760,6 +2796,7 @@ static checker::Type *ComputeTypeOfType(ETSChecker *checker, checker::Type *argT checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::TypeofExpression *expr) const { + ES2PANDA_PERF_SCOPELESS("@Check-TypeofExpression"); ETSChecker *checker = GetETSChecker(); if (expr->TsType() != nullptr) { return expr->TsType(); @@ -2772,6 +2809,7 @@ checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::TypeofExpression *expr) c checker::Type *ETSAnalyzer::Check(ir::UnaryExpression *expr) const { + ES2PANDA_PERF_SCOPELESS("@Check-UnaryExpression"); ETSChecker *checker = GetETSChecker(); if (expr->TsType() != nullptr) { @@ -2822,6 +2860,7 @@ checker::Type *ETSAnalyzer::Check(ir::UnaryExpression *expr) const checker::Type *ETSAnalyzer::Check(ir::UpdateExpression *expr) const { + ES2PANDA_PERF_SCOPELESS("@Check-UpdateExpression"); ETSChecker *checker = GetETSChecker(); if (expr->TsType() != nullptr) { return expr->TsType(); @@ -2868,6 +2907,7 @@ checker::Type *ETSAnalyzer::Check(ir::UpdateExpression *expr) const // compile methods for LITERAL EXPRESSIONS in alphabetical order checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::BigIntLiteral *expr) const { + ES2PANDA_PERF_SCOPELESS("@Check-BigIntLiteral"); ETSChecker *checker = GetETSChecker(); expr->SetTsType(checker->CreateETSBigIntLiteralType(expr->Str())); return expr->TsType(); @@ -2875,6 +2915,7 @@ checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::BigIntLiteral *expr) cons checker::Type *ETSAnalyzer::Check(ir::BooleanLiteral *expr) const { + ES2PANDA_PERF_SCOPELESS("@Check-BooleanLiteral"); ETSChecker *checker = GetETSChecker(); if (expr->TsType() == nullptr) { auto type = checker->GlobalETSBooleanBuiltinType()->Clone(GetChecker()); @@ -2886,6 +2927,7 @@ checker::Type *ETSAnalyzer::Check(ir::BooleanLiteral *expr) const checker::Type *ETSAnalyzer::Check(ir::CharLiteral *expr) const { + ES2PANDA_PERF_SCOPELESS("@Check-CharLiteral"); ETSChecker *checker = GetETSChecker(); if (expr->TsType() == nullptr) { auto type = checker->GlobalCharBuiltinType()->Clone(GetChecker()); @@ -2897,6 +2939,7 @@ checker::Type *ETSAnalyzer::Check(ir::CharLiteral *expr) const checker::Type *ETSAnalyzer::Check(ir::NullLiteral *expr) const { + ES2PANDA_PERF_SCOPELESS("@Check-NullLiteral"); ETSChecker *checker = GetETSChecker(); if (expr->TsType() == nullptr) { expr->SetTsType(checker->GlobalETSNullType()); @@ -2942,6 +2985,7 @@ static bool CheckIfLiteralValueIsAppropriate(ETSChecker *checker, Type *type, ir checker::Type *ETSAnalyzer::Check(ir::NumberLiteral *expr) const { + ES2PANDA_PERF_SCOPELESS("@Check-NumberLiteral"); if (expr->TsType() != nullptr) { return expr->TsType(); } @@ -2976,6 +3020,7 @@ checker::Type *ETSAnalyzer::Check(ir::NumberLiteral *expr) const checker::Type *ETSAnalyzer::Check(ir::StringLiteral *expr) const { + ES2PANDA_PERF_SCOPELESS("@Check-StringLiteral"); ETSChecker *checker = GetETSChecker(); if (expr->TsType() == nullptr) { expr->SetTsType(checker->CreateETSStringLiteralType(expr->Str())); @@ -2985,6 +3030,7 @@ checker::Type *ETSAnalyzer::Check(ir::StringLiteral *expr) const checker::Type *ETSAnalyzer::Check(ir::ETSIntrinsicNode *node) const { + ES2PANDA_PERF_SCOPELESS("@Check-ETSIntrinsicNode"); ETSChecker *checker = GetETSChecker(); for (auto *arg : node->Arguments()) { arg->Check(checker); @@ -3004,6 +3050,7 @@ checker::Type *ETSAnalyzer::Check(ir::ETSIntrinsicNode *node) const checker::Type *ETSAnalyzer::Check(ir::ImportDeclaration *st) const { + ES2PANDA_PERF_SCOPELESS("@Check-ImportDeclaration"); ETSChecker *checker = GetETSChecker(); checker::Type *type = nullptr; for (auto *spec : st->Specifiers()) { @@ -3017,6 +3064,7 @@ checker::Type *ETSAnalyzer::Check(ir::ImportDeclaration *st) const checker::Type *ETSAnalyzer::Check(ir::ImportNamespaceSpecifier *st) const { + ES2PANDA_PERF_SCOPELESS("@Check-ImportNamespaceSpecifier"); ETSChecker *checker = GetETSChecker(); if (st->Local()->Name().Empty()) { return ReturnTypeForStatement(st); @@ -3047,11 +3095,13 @@ checker::Type *ETSAnalyzer::Check(ir::ImportNamespaceSpecifier *st) const // compile methods for STATEMENTS in alphabetical order checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::AssertStatement *st) const { + ES2PANDA_PERF_SCOPELESS("@Check-AssertStement"); ES2PANDA_UNREACHABLE(); } checker::Type *ETSAnalyzer::Check(ir::BlockStatement *st) const { + ES2PANDA_PERF_SCOPELESS("@Check-BlockStement"); ETSChecker *checker = GetETSChecker(); checker::ScopeContext scopeCtx(checker, st->Scope()); @@ -3103,6 +3153,7 @@ checker::Type *ETSAnalyzer::Check(ir::BlockStatement *st) const checker::Type *ETSAnalyzer::Check(ir::BreakStatement *st) const { + ES2PANDA_PERF_SCOPELESS("@Check-BreakStatement"); ETSChecker *checker = GetETSChecker(); if (!st->HasTarget()) { @@ -3120,6 +3171,7 @@ checker::Type *ETSAnalyzer::Check(ir::BreakStatement *st) const checker::Type *ETSAnalyzer::Check(ir::ClassDeclaration *st) const { + ES2PANDA_PERF_SCOPELESS("@Check-ClassDeclaration"); ETSChecker *checker = GetETSChecker(); st->Definition()->Check(checker); return ReturnTypeForStatement(st); @@ -3127,6 +3179,7 @@ checker::Type *ETSAnalyzer::Check(ir::ClassDeclaration *st) const checker::Type *ETSAnalyzer::Check(ir::AnnotationDeclaration *st) const { + ES2PANDA_PERF_SCOPELESS("@Check-AnnotationDeclaration"); if (st->Expr()->TsType() != nullptr) { return ReturnTypeForStatement(st); } @@ -3174,6 +3227,7 @@ static void ProcessRequiredFields(ArenaUnorderedMapExpr()->TsType() != nullptr) { return ReturnTypeForStatement(st); } @@ -3219,6 +3273,7 @@ checker::Type *ETSAnalyzer::Check(ir::AnnotationUsage *st) const checker::Type *ETSAnalyzer::Check(ir::ContinueStatement *st) const { + ES2PANDA_PERF_SCOPELESS("@Check-ContinueStatement"); ETSChecker *checker = GetETSChecker(); if (!st->HasTarget()) { @@ -3249,6 +3304,7 @@ checker::Type *ETSAnalyzer::Check(ir::ContinueStatement *st) const checker::Type *ETSAnalyzer::Check(ir::DoWhileStatement *st) const { + ES2PANDA_PERF_SCOPELESS("@Check-DoWhileStatement"); ETSChecker *checker = GetETSChecker(); checker::ScopeContext scopeCtx(checker, st->Scope()); @@ -3264,11 +3320,13 @@ checker::Type *ETSAnalyzer::Check(ir::DoWhileStatement *st) const checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::EmptyStatement *st) const { + ES2PANDA_PERF_SCOPELESS("@Check-EmptyStatement"); return ReturnTypeForStatement(st); } checker::Type *ETSAnalyzer::Check(ir::ExpressionStatement *st) const { + ES2PANDA_PERF_SCOPELESS("@Check-ExpressionStatement"); ETSChecker *checker = GetETSChecker(); return st->GetExpression()->Check(checker); } @@ -3308,6 +3366,7 @@ static bool ValidateAndProcessIteratorType(ETSChecker *checker, Type *elemType, checker::Type *ETSAnalyzer::Check(ir::ForOfStatement *const st) const { + ES2PANDA_PERF_SCOPELESS("@Check-ForOfStatement"); ETSChecker *checker = GetETSChecker(); checker::ScopeContext scopeCtx(checker, st->Scope()); @@ -3344,6 +3403,7 @@ checker::Type *ETSAnalyzer::Check(ir::ForOfStatement *const st) const checker::Type *ETSAnalyzer::Check(ir::ForUpdateStatement *st) const { + ES2PANDA_PERF_SCOPELESS("@Check-ForUpdateStatement"); ETSChecker *checker = GetETSChecker(); checker::ScopeContext scopeCtx(checker, st->Scope()); @@ -3370,6 +3430,7 @@ checker::Type *ETSAnalyzer::Check(ir::ForUpdateStatement *st) const checker::Type *ETSAnalyzer::Check(ir::IfStatement *st) const { + ES2PANDA_PERF_SCOPELESS("@Check-IfStatement"); ETSChecker *const checker = GetETSChecker(); SmartCastArray smartCasts = checker->Context().EnterTestExpression(); @@ -3423,6 +3484,7 @@ checker::Type *ETSAnalyzer::Check(ir::IfStatement *st) const checker::Type *ETSAnalyzer::Check(ir::LabelledStatement *st) const { + ES2PANDA_PERF_SCOPELESS("@Check-LabeledStatement"); ETSChecker *checker = GetETSChecker(); st->body_->Check(checker); return ReturnTypeForStatement(st); @@ -3541,6 +3603,7 @@ checker::Type *ETSAnalyzer::GetFunctionReturnType(ir::ReturnStatement *st, ir::S checker::Type *ETSAnalyzer::Check(ir::ReturnStatement *st) const { + ES2PANDA_PERF_SCOPELESS("@Check-ReturnStatement"); ETSChecker *checker = GetETSChecker(); ir::AstNode *ancestor = util::Helpers::FindAncestorGivenByType(st, ir::AstNodeType::SCRIPT_FUNCTION); @@ -3575,6 +3638,7 @@ checker::Type *ETSAnalyzer::Check(ir::ReturnStatement *st) const checker::Type *ETSAnalyzer::Check(ir::SwitchStatement *st) const { + ES2PANDA_PERF_SCOPELESS("@Check-SwitchStatement"); ETSChecker *checker = GetETSChecker(); checker::ScopeContext scopeCtx(checker, st->Scope()); checker::SavedTypeRelationFlagsContext savedTypeRelationFlagCtx(checker->Relation(), @@ -3622,6 +3686,7 @@ checker::Type *ETSAnalyzer::Check(ir::SwitchStatement *st) const checker::Type *ETSAnalyzer::Check(ir::ThrowStatement *st) const { + ES2PANDA_PERF_SCOPELESS("@Check-ThrowStatement"); ETSChecker *checker = GetETSChecker(); const auto *arg = st->argument_; checker::Type *argType = st->argument_->Check(checker); @@ -3644,6 +3709,7 @@ checker::Type *ETSAnalyzer::Check(ir::ThrowStatement *st) const checker::Type *ETSAnalyzer::Check(ir::TryStatement *st) const { + ES2PANDA_PERF_SCOPELESS("@Check-TryStatement"); ETSChecker *checker = GetETSChecker(); std::vector exceptions {}; @@ -3687,6 +3753,7 @@ checker::Type *ETSAnalyzer::Check(ir::TryStatement *st) const checker::Type *ETSAnalyzer::Check(ir::VariableDeclarator *st) const { + ES2PANDA_PERF_SCOPELESS("@Check-VariableDeclarator"); if (st->TsType() != nullptr) { return st->TsType(); } @@ -3733,6 +3800,7 @@ checker::Type *ETSAnalyzer::Check(ir::VariableDeclarator *st) const checker::Type *ETSAnalyzer::Check(ir::VariableDeclaration *st) const { + ES2PANDA_PERF_SCOPELESS("@Check-VariableDeclaration"); ETSChecker *checker = GetETSChecker(); checker->CheckAnnotations(st->Annotations()); @@ -3746,6 +3814,7 @@ checker::Type *ETSAnalyzer::Check(ir::VariableDeclaration *st) const checker::Type *ETSAnalyzer::Check(ir::WhileStatement *st) const { + ES2PANDA_PERF_SCOPELESS("@Check-WhileStatement"); ETSChecker *checker = GetETSChecker(); checker::ScopeContext scopeCtx(checker, st->Scope()); @@ -3772,6 +3841,7 @@ checker::Type *ETSAnalyzer::Check(ir::WhileStatement *st) const checker::Type *ETSAnalyzer::Check(ir::TSArrayType *node) const { + ES2PANDA_PERF_SCOPELESS("@Check-TSArrayType"); ETSChecker *checker = GetETSChecker(); checker->CheckAnnotations(node->Annotations()); node->elementType_->Check(checker); @@ -3784,6 +3854,7 @@ checker::Type *ETSAnalyzer::Check(ir::TSArrayType *node) const checker::Type *ETSAnalyzer::Check(ir::TSAsExpression *expr) const { + ES2PANDA_PERF_SCOPELESS("@Check-TSAsExpression"); ETSChecker *checker = GetETSChecker(); if (expr->TsType() != nullptr) { @@ -3829,12 +3900,15 @@ checker::Type *ETSAnalyzer::Check(ir::TSAsExpression *expr) const checker::Type *ETSAnalyzer::Check(ir::TSEnumDeclaration *st) const { + ES2PANDA_PERF_SCOPELESS("@Check-TSEnumDeclaration"); + // Some invalid TSEnumDeclaration will not be transformed to class. return ReturnTypeForStatement(st); } checker::Type *ETSAnalyzer::Check(ir::TSInterfaceDeclaration *st) const { + ES2PANDA_PERF_SCOPELESS("@Check-TSInterfaceDeclaration"); if (st->TsType() != nullptr) { return st->TsType(); } @@ -3865,6 +3939,7 @@ checker::Type *ETSAnalyzer::Check(ir::TSInterfaceDeclaration *st) const checker::Type *ETSAnalyzer::Check(ir::TSNonNullExpression *expr) const { + ES2PANDA_PERF_SCOPELESS("@Check-TSNonNullExpression"); if (expr->TsType() != nullptr) { return expr->TsType(); } @@ -3945,6 +4020,7 @@ static varbinder::Variable *FindNameForImportNamespace(ETSChecker *checker, util checker::Type *ETSAnalyzer::Check(ir::TSQualifiedName *expr) const { + ES2PANDA_PERF_SCOPELESS("@Check-TSQualifiedName"); ETSChecker *checker = GetETSChecker(); checker::Type *baseType = expr->Left()->Check(checker)->MaybeBaseTypeOfGradualType(); if (baseType->IsETSObjectType()) { @@ -3978,6 +4054,7 @@ checker::Type *ETSAnalyzer::Check(ir::TSQualifiedName *expr) const checker::Type *ETSAnalyzer::Check(ir::TSTypeAliasDeclaration *st) const { + ES2PANDA_PERF_SCOPELESS("@Check-TSTypeAliasDeclaration"); ETSChecker *checker = GetETSChecker(); auto checkerContext = SavedCheckerContext(checker, CheckerStatus::NO_OPTS, checker->Context().ContainingClass()); diff --git a/ets2panda/checker/ETSchecker.cpp b/ets2panda/checker/ETSchecker.cpp index 3cde016475c0dc517a15fc6c6871511390634a11..049b1bc0e0c9891461fdba3cddd03ec5616939a6 100644 --- a/ets2panda/checker/ETSchecker.cpp +++ b/ets2panda/checker/ETSchecker.cpp @@ -391,7 +391,10 @@ void ETSChecker::CheckProgram(parser::Program *program, bool runAnalysis) ES2PANDA_ASSERT(Program()->Ast()->IsProgram()); - Program()->Ast()->Check(this); + { + ES2PANDA_PERF_SCOPELESS("@Check-AST"); + Program()->Ast()->Check(this); + } if (runAnalysis && !IsAnyError()) { AliveAnalyzer aliveAnalyzer(Program()->Ast(), this); diff --git a/ets2panda/checker/ETSchecker.h b/ets2panda/checker/ETSchecker.h index 481375559cf7a1d105189fdaa104afa7843f3637..8e3b18b353d684885ce2819747f400d31e0caf93 100644 --- a/ets2panda/checker/ETSchecker.h +++ b/ets2panda/checker/ETSchecker.h @@ -106,6 +106,7 @@ public: overloadSigContainer_(Allocator()->Adapter()), readdedChecker_(Allocator()->Adapter()) { + apparentTypes_.reserve(50000); } ~ETSChecker() override = default; diff --git a/ets2panda/checker/checker.cpp b/ets2panda/checker/checker.cpp index ab4e17a2e079d1182cf78b6a0e32ecc6eedbaa1d..ef3edf778f4ad37d91e7bba3be87252559257c7d 100644 --- a/ets2panda/checker/checker.cpp +++ b/ets2panda/checker/checker.cpp @@ -29,6 +29,10 @@ Checker::Checker(ThreadSafeArenaAllocator *allocator, util::DiagnosticEngine &di { relation_ = ProgramAllocator()->New(this); globalTypes_ = ProgramAllocator()->New(ProgramAllocator()); + identicalResults_.Reserve(800000); // Preallocate for large type relationships + assignableResults_.Reserve(500); // Base capacity for assignments + uncheckedCastableResults_.Reserve(50000); // Mid-sized cast buffer + supertypeResults_.Reserve(800000); // Match identicalResults_ capacity } void Checker::Initialize(varbinder::VarBinder *varbinder) diff --git a/ets2panda/checker/ets/utilityTypeHandlers.cpp b/ets2panda/checker/ets/utilityTypeHandlers.cpp index 26c11a60a30b020d7c9630ea8b82a3c0f812561c..519bb79f676245f25bc45334311fbb36b3fcf80a 100644 --- a/ets2panda/checker/ets/utilityTypeHandlers.cpp +++ b/ets2panda/checker/ets/utilityTypeHandlers.cpp @@ -1127,8 +1127,7 @@ void ETSChecker::MakePropertyNonNullish(ETSObjectType *const classType, varbinde auto *const propCopy = prop->Copy(ProgramAllocator(), prop->Declaration()); ES2PANDA_ASSERT(propCopy != nullptr); propCopy->SetTsType(nonNullishPropType); - classType->RemoveProperty(prop); - classType->AddProperty(propCopy); + classType->UpdateProperty(prop, propCopy); } static bool StringEqualsPropertyName(const util::StringView pname1, const ir::Expression *const prop2Key) diff --git a/ets2panda/checker/types/ets/etsObjectType.cpp b/ets2panda/checker/types/ets/etsObjectType.cpp index 4bf8a2f7c12e504a9444cd6f11cb62e1de1d65c8..ec72e7fe486c1dfcdc50cb96f6fffee295f8cc2b 100644 --- a/ets2panda/checker/types/ets/etsObjectType.cpp +++ b/ets2panda/checker/types/ets/etsObjectType.cpp @@ -1258,14 +1258,11 @@ void ETSObjectType::UpdateTypeProperty(varbinder::LocalVariable *const prop, Pro PropertyProcesser const &func) { auto const propType = prop->Declaration()->Node()->Check(GetETSChecker()); - auto *const propCopy = func(prop, propType); if (fieldType == PropertyType::INSTANCE_FIELD) { - RemoveProperty(prop); - AddProperty(propCopy); + UpdateProperty(prop, propCopy); } else { - RemoveProperty(prop); - AddProperty(propCopy); + UpdateProperty(prop, propCopy); } } diff --git a/ets2panda/checker/types/ets/etsObjectType.h b/ets2panda/checker/types/ets/etsObjectType.h index a86f126b974a89484f4a1ec9f5d7795a66d6a498..3398bf6167a877ee5e3e89726d6278a7cae186ec 100644 --- a/ets2panda/checker/types/ets/etsObjectType.h +++ b/ets2panda/checker/types/ets/etsObjectType.h @@ -329,6 +329,7 @@ public: propertiesInstantiated_ = true; } + // Do not erase in loop of properties_' iteration template void RemoveProperty(varbinder::LocalVariable *prop) { @@ -336,6 +337,13 @@ public: propertiesInstantiated_ = true; } + template + void UpdateProperty(varbinder::LocalVariable *oldProp, varbinder::LocalVariable *newProp) + { + properties_[static_cast(TYPE)][oldProp->Name()] = newProp; + propertiesInstantiated_ = true; + } + [[nodiscard]] bool IsGeneric() const noexcept { return !typeArguments_.empty(); diff --git a/ets2panda/checker/types/typeRelation.h b/ets2panda/checker/types/typeRelation.h index 33c32e789cfada5d83580cd839f5aacf80fa48e5..dbc0ea064c491a76a3d05a64dd9c4ae984a9ace4 100644 --- a/ets2panda/checker/types/typeRelation.h +++ b/ets2panda/checker/types/typeRelation.h @@ -122,6 +122,11 @@ public: cached_.clear(); } + void Reserve(size_t cnt) + { + cached_.reserve(cnt); + } + private: ArenaUnorderedMap cached_; }; diff --git a/ets2panda/compiler/lowering/ets/asyncMethodLowering.cpp b/ets2panda/compiler/lowering/ets/asyncMethodLowering.cpp index 7283b469f5621f520dae3328d144ddd035e214e9..8539c96d3d550dd822c2a8c38c9b28bb45feb55d 100644 --- a/ets2panda/compiler/lowering/ets/asyncMethodLowering.cpp +++ b/ets2panda/compiler/lowering/ets/asyncMethodLowering.cpp @@ -205,9 +205,10 @@ void UpdateClassDefintion(checker::ETSChecker *checker, ir::ClassDefinition *cla { checker::SavedCheckerContext savedContext(checker, checker->Context().Status(), classDef->TsType()->AsETSObjectType()); - for (auto *it : classDef->Body()) { - if (it->IsMethodDefinition()) { - HandleMethod(checker, it->AsMethodDefinition()); + for (size_t i = 0; i < classDef->Body().size(); ++i) { + auto *node = classDef->Body()[i]; + if (node->IsMethodDefinition()) { + HandleMethod(checker, node->AsMethodDefinition()); } } } diff --git a/ets2panda/compiler/lowering/util.cpp b/ets2panda/compiler/lowering/util.cpp index 84e9ccb559117e1aae09adbe17912d061a0cd87c..b6043c1c183a7d080497722e6212d9307c5fdba4 100644 --- a/ets2panda/compiler/lowering/util.cpp +++ b/ets2panda/compiler/lowering/util.cpp @@ -21,6 +21,7 @@ #include "checker/ETSAnalyzer.h" #include "checker/types/gradualType.h" #include "parser/JsdocHelper.h" +#include "util/perfMetrics.h" namespace ark::es2panda::compiler { @@ -275,6 +276,7 @@ void Recheck(PhaseManager *phaseManager, varbinder::ETSBinder *varBinder, checke } for (auto *phase : phaseManager->RecheckPhases()) { + ES2PANDA_PERF_EVENT_SCOPE("@Recheck-Prog-" + std::string(phase->Name())); phase->Apply(ctx, program); } phaseManager->SetCurrentPhaseIdToAfterCheck(); diff --git a/ets2panda/driver/build_system/src/build/base_mode.ts b/ets2panda/driver/build_system/src/build/base_mode.ts index 4294c512eeb8e469a66935cf1f0e9423ad7404ec..0985ccb4ee0943bee98a430d73469380a6aa55a8 100644 --- a/ets2panda/driver/build_system/src/build/base_mode.ts +++ b/ets2panda/driver/build_system/src/build/base_mode.ts @@ -117,6 +117,7 @@ export abstract class BaseMode { public byteCodeHar: boolean; public es2pandaMode: number; public skipDeclCheck: boolean; + public dumpPerf: boolean = true; constructor(buildConfig: BuildConfig) { this.buildConfig = buildConfig; @@ -354,6 +355,9 @@ export abstract class BaseMode { ets2pandaCmd.push('--debug-info'); ets2pandaCmd.push('--opt-level=0'); } + if (this.dumpPerf) { + ets2pandaCmd.push('--dump-perf-metrics'); + } ets2pandaCmd.push(this.buildConfig.compileFiles[0]); this.logger.printInfo('ets2pandaCmd: ' + ets2pandaCmd.join(' ')); diff --git a/ets2panda/public/es2panda_lib.cpp b/ets2panda/public/es2panda_lib.cpp index f9295c138b39925fae9abee5f58d562e4e0266a8..f6213a4d1e71d0e0cc3468515fac207b8738a1fd 100644 --- a/ets2panda/public/es2panda_lib.cpp +++ b/ets2panda/public/es2panda_lib.cpp @@ -19,6 +19,7 @@ #include #include "util/diagnostic.h" +#include "util/perfMetrics.h" #include "varbinder/varbinder.h" #include "varbinder/scope.h" #include "public/public.h" @@ -253,6 +254,9 @@ extern "C" void DestroyConfig(es2panda_Config *config) return; } + if (cfg->options->IsDumpPerfMetrics()) { + util::DumpPerfMetrics(); + } delete cfg->options; cfg->diagnosticEngine->FlushDiagnostic(); delete cfg->diagnosticEngine; @@ -531,6 +535,7 @@ __attribute__((unused)) static Context *Parse(Context *ctx) } ctx->phaseManager->Reset(); + ES2PANDA_PERF_SCOPE("@Parser"); if (ctx->isExternal && ctx->allocator != ctx->globalContext->stdLibAllocator) { ctx->sourceFileNames.emplace_back(ctx->sourceFileName); @@ -599,6 +604,7 @@ __attribute__((unused)) static Context *Check(Context *ctx) if (phase->Name() == "plugins-after-check") { break; } + ES2PANDA_PERF_EVENT_SCOPE("@phases/" + std::string(phase->Name())); phase->Apply(ctx, ctx->parserProgram); } ctx->phaseManager->SetCurrentPhaseIdToAfterCheck(); @@ -639,6 +645,7 @@ __attribute__((unused)) static Context *Lower(Context *ctx) ES2PANDA_ASSERT(ctx->state == ES2PANDA_STATE_CHECKED); while (auto phase = ctx->phaseManager->NextPhase()) { + ES2PANDA_PERF_EVENT_SCOPE("@phases/" + std::string(phase->Name())); phase->Apply(ctx, ctx->parserProgram); } ctx->state = !ctx->diagnosticEngine->IsAnyError() ? ES2PANDA_STATE_LOWERED : ES2PANDA_STATE_ERROR; @@ -669,6 +676,7 @@ __attribute__((unused)) static Context *GenerateAsm(Context *ctx) ES2PANDA_ASSERT(ctx->state == ES2PANDA_STATE_LOWERED); + ES2PANDA_PERF_SCOPE("@EmitProgram"); auto *emitter = ctx->emitter; emitter->GenAnnotation(); @@ -1071,6 +1079,7 @@ extern "C" es2panda_Scope *AstNodeRebind(es2panda_Context *ctx, es2panda_AstNode extern "C" void AstNodeRecheck(es2panda_Context *ctx, es2panda_AstNode *node) { + ES2PANDA_PERF_SCOPE("@Recheck"); auto E2pNode = reinterpret_cast(node); auto context = reinterpret_cast(ctx); auto varbinder = context->parserProgram->VarBinder()->AsETSBinder(); diff --git a/ets2panda/util/perfMetrics.cpp b/ets2panda/util/perfMetrics.cpp index 981ec934c40d631b1461b4f71c4f1e24e5b40a8e..76a1487beb44b2141c8488a6c20ecb15854856d7 100644 --- a/ets2panda/util/perfMetrics.cpp +++ b/ets2panda/util/perfMetrics.cpp @@ -14,14 +14,18 @@ */ #include "util/perfMetrics.h" +#include "util/es2pandaMacros.h" #include "libpandabase/utils/logger.h" #include "libpandabase/utils/type_converter.h" #include "libpandabase/mem/mem.h" +#include "libpandabase/mem/arena_allocator_stl_adapter.h" #include #include +#include #include #include +#include #ifdef PANDA_TARGET_UNIX #include "sys/resource.h" @@ -72,6 +76,14 @@ public: return Combine(acc, diff, true); } + static PerfMetricValue Accumulate(PerfMetricValue const &acc, PerfMetricValue const &begin, + PerfMetricValue const &end, PerfMetricValue const &other) + { + PerfMetricValue diff = Combine(end, begin, false); + PerfMetricValue preciseDiff = Combine(diff, other, false); + return Combine(acc, preciseDiff, true); + } + int64_t GetTimeNanoseconds() const { return time_; @@ -81,14 +93,6 @@ public: { return mem_; } - - DEFAULT_COPY_SEMANTIC(PerfMetricValue); - DEFAULT_MOVE_SEMANTIC(PerfMetricValue); - ~PerfMetricValue() = default; - -private: - PerfMetricValue() = default; - static PerfMetricValue Combine(PerfMetricValue const &st1, PerfMetricValue const &st2, bool sum) { int mult = sum ? 1 : -1; @@ -98,19 +102,37 @@ private: return res; } + DEFAULT_COPY_SEMANTIC(PerfMetricValue); + DEFAULT_MOVE_SEMANTIC(PerfMetricValue); + ~PerfMetricValue() = default; + +private: + PerfMetricValue() = default; + int64_t time_ {}; int64_t mem_ {}; }; class PerfMetricRecord { public: - explicit PerfMetricRecord(std::string_view name) : name_(name) {} + explicit PerfMetricRecord(std::string_view name) : name_(name), aRecord(GetName()), cRecord(GetName()) {} PerfMetricValue const &GetStats() const { return acc_; } - + PerfMetricValue const &GetMin() const + { + return min_; + } + PerfMetricValue const &GetMax() const + { + return max_; + } + PerfMetricValue const &GetLast() const + { + return last_; + } std::string const &GetName() const { return name_; @@ -125,6 +147,8 @@ public: if (++nesting_ > maxNesting_) { maxNesting_ = nesting_; } + aRecord.begin(); + cRecord.begin(); } void EndTrace() @@ -132,8 +156,61 @@ public: if (--nesting_ == 0) { acc_ = PerfMetricValue::Accumulate(acc_, begin_, PerfMetricValue::Now()); } + aRecord.end(); + cRecord.end(); + } + + void BeginTrace(PerfMetricRecord *rec) + { + auto now = PerfMetricValue::Now(); + std::vector arr; + callStack.push(now); + calleeStack.push(arr); + calleeArr = &calleeStack.top(); + callerStack.push(rec); + caller = rec; + + ++nesting_; + invokationsCount_++; + begin_ = now; + } + + void EndTrace(PerfMetricValue &other) + { + begin_ = callStack.top(); + calleeArr = &calleeStack.top(); + caller = callerStack.top(); + + for (size_t idx = 0; idx < calleeArr->size(); ++idx) { + auto item = (*calleeArr)[idx]; + other = PerfMetricValue::Combine(other, item, true); + } + PerfMetricValue curr = PerfMetricValue::Now(); + last_ = PerfMetricValue::Combine(curr, begin_, false); + acc_ = PerfMetricValue::Accumulate(acc_, begin_, curr, other); + auto preciseLast = PerfMetricValue::Combine(last_, other, false); + ES2PANDA_ASSERT(last_.GetTimeNanoseconds() >= other.GetTimeNanoseconds()); + if (preciseLast.GetTimeNanoseconds() > max_.GetTimeNanoseconds()) { + max_ = preciseLast; + } + if (invokationsCount_ == 1 || preciseLast.GetTimeNanoseconds() < min_.GetTimeNanoseconds()) { + min_ = preciseLast; + } + + callStack.pop(); + calleeStack.pop(); + callerStack.pop(); + calleeArr = nullptr; + if (!calleeStack.empty()) { + calleeArr = &calleeStack.top(); + } + --nesting_; } + size_t GetNesting() const + { + return nesting_; + } size_t GetMaxNesting() const { return maxNesting_; @@ -148,13 +225,25 @@ public: DEFAULT_MOVE_SEMANTIC(PerfMetricRecord); ~PerfMetricRecord() = default; + PerfMetricValue begin_ = PerfMetricValue::Zero(); + PerfMetricRecord *caller; + std::vector *calleeArr; + std::stack> calleeStack; + std::stack callerStack; + private: size_t nesting_ {}; size_t maxNesting_ {}; size_t invokationsCount_ {}; std::string name_; PerfMetricValue acc_ = PerfMetricValue::Zero(); - PerfMetricValue begin_ = PerfMetricValue::Zero(); + PerfMetricValue last_ = PerfMetricValue::Zero(); + PerfMetricValue min_ = PerfMetricValue::Zero(); + PerfMetricValue max_ = PerfMetricValue::Zero(); + std::stack callStack; + ark::ArenaMemRecord aRecord; + ark::ContMemRecord cRecord; + }; PerfMetricScope::PerfMetricScope(PerfMetricRecord *record) : record_(record) @@ -168,6 +257,7 @@ PerfMetricScope::~PerfMetricScope() } // NOLINTBEGIN(fuchsia-statically-constructed-objects) +static std::forward_list>> g_perfMetricsStackList; static std::forward_list>> g_perfMetricsLists; static std::mutex g_perfMetricsListsMtx; // NOLINTEND(fuchsia-statically-constructed-objects) @@ -183,6 +273,70 @@ std::forward_list *GetTLSPerfMetricsData() return tls; } +std::stack *GetTLSPerfMetricsStack() +{ + thread_local auto tls = ([]() { + std::lock_guard lk(g_perfMetricsListsMtx); + g_perfMetricsStackList.push_front({os::thread::GetCurrentThreadId(), std::stack()}); + return &g_perfMetricsStackList.begin()->second; + })(); + + return tls; +} + +PrecisePerfMetricScope::PrecisePerfMetricScope(PerfMetricRecord *record) : record_(record) +{ + PerfMetricRecord *caller = nullptr; + if (!GetTLSPerfMetricsStack()->empty()) { + caller = GetTLSPerfMetricsStack()->top(); + } + record_->BeginTrace(caller); + GetTLSPerfMetricsStack()->push(record); + // if (caller) { + // std::cout << std::left << std::setw(16) << "[stack dep]: " << GetTLSPerfMetricsStack()->size() << + // std::left + // << std::setw(20) << " [scope begin] : " << std::setw(25) << record_->GetName() << ", " + // << std::setw(12) << record_ << ", " << record_->GetNesting() << std::setw(10) + // << " [parent]: " << caller->GetName() << ", " << caller << ", " << caller->GetNesting() << + // std::endl; + // + // } else { + // std::cout << std::left << std::setw(16) << "[stack dep]: " << GetTLSPerfMetricsStack()->size() << + // std::left + // << std::setw(20) << " [scope begin] : " << std::setw(25) << record_->GetName() << ", " + // << std::setw(12) << record_ << ", " << record_->GetNesting() << " ,parent: NULL" + // << std::endl; + // } +} + +PrecisePerfMetricScope::~PrecisePerfMetricScope() +{ + auto *tlStack = GetTLSPerfMetricsStack(); + auto childCost = PerfMetricValue::Zero(); + + record_->EndTrace(childCost); + + tlStack->pop(); + if (record_->caller != nullptr) { + record_->caller->calleeArr->push_back(record_->GetLast()); + // auto caller = record_->caller; + // std::cout << std::left << std::setw(16) << "[stack dep]: " << GetTLSPerfMetricsStack()->size() << + // std::left + // << std::setw(20) << " [scope end] : " << std::setw(25) << record_->GetName() << ", " << + // std::setw(12) + // << record_ << ", " << record_->GetNesting() << std::setw(10) << " [parent]: " << + // caller->GetName() + // << ", " << caller << ", " << caller->GetNesting() << std::endl; + + } else { + // std::cout << std::left << std::setw(16) << "[stack dep]: " << GetTLSPerfMetricsStack()->size() << + // std::left + // << std::setw(20) << " [scope end] : " << std::setw(25) << record_->GetName() << ", " << + // std::setw(12) + // << record_ << ", nesting: " << record_->GetNesting() << " parent: NULL" << std::endl; + } +} + PerfMetricRecord *RegisterPerfMetricRecord(std::string_view name) { auto *tls = GetTLSPerfMetricsData(); @@ -190,30 +344,36 @@ PerfMetricRecord *RegisterPerfMetricRecord(std::string_view name) return &tls->front(); } -static std::string PrettyTimeNs(uint64_t duration) +static std::string PrettyTimeNs(uint64_t duration, bool pretty = true) { - // CC-OFF(G.NAM.03-CPP) project code style - constexpr std::array TIME_UNITS = {"ns", "us", "ms", "s"}; - // CC-OFF(G.NAM.03-CPP) project code style - constexpr double K_SCALE = 1E3; - - if (duration == 0) { - return "0s"; - } + if (pretty) { + // CC-OFF(G.NAM.03-CPP) project code style + constexpr std::array TIME_UNITS = {"ns", "us", "ms", "s"}; + // CC-OFF(G.NAM.03-CPP) project code style + constexpr double K_SCALE = 1E3; + + if (duration == 0) { + return "0s"; + } - double val = duration; - size_t unitIdx = 0; + double val = duration; + size_t unitIdx = 0; - for (;; ++unitIdx) { - double nextVal = val / K_SCALE; - if (unitIdx == TIME_UNITS.size() || nextVal < 1.0) { - break; + for (;; ++unitIdx) { + double nextVal = val / K_SCALE; + if (unitIdx == TIME_UNITS.size() || nextVal < 1.0) { + break; + } + val = nextVal; } - val = nextVal; - } + std::stringstream ss; + ss << std::setprecision(3U) << val << TIME_UNITS[unitIdx]; + return ss.str(); + } + double val = duration; std::stringstream ss; - ss << std::setprecision(3U) << val << TIME_UNITS[unitIdx]; + ss << std::setprecision(3U) << val; return ss.str(); } @@ -234,8 +394,11 @@ static void DumpPerfMetricRecord(std::stringstream &ss, PerfMetricRecord const * if (rec->GetInvokationsCount() > 1) { metric("count", 8U) << rec->GetInvokationsCount(); } - metric("time", 10U) << PrettyTimeNs(stats.GetTimeNanoseconds()); - auto memValue = ark::helpers::MemoryConverter(stats.GetMemorySize()); + metric("all", 10U) << PrettyTimeNs(stats.GetTimeNanoseconds(), false); + metric("avg", 10U) << PrettyTimeNs(stats.GetTimeNanoseconds() / rec->GetInvokationsCount(), false); + metric("min", 10U) << PrettyTimeNs(rec->GetMin().GetTimeNanoseconds()); + metric("max", 10U) << PrettyTimeNs(rec->GetMax().GetTimeNanoseconds()); + auto memValue = ark::helpers::MemoryConverter(stats.GetMemorySize() / rec->GetInvokationsCount()); metric("mem", 10U) << (std::to_string(static_cast(memValue.GetDoubleValue())) + std::string(memValue.GetLiteral())); // NOLINTEND(readability-magic-numbers) @@ -273,6 +436,8 @@ static void DumpPerfMetricsImpl(std::optional prefix) } std::cout << ss.str(); + ark::ArenaMemRecord::Print(); + ark::ContMemRecord::Print(); } void DumpPerfMetrics() diff --git a/ets2panda/util/perfMetrics.h b/ets2panda/util/perfMetrics.h index 37f72ffbcacc6dd4219ba85d673c657142288610..16935a1ca8c6c4029115ae7919af6cd4a8ee7503 100644 --- a/ets2panda/util/perfMetrics.h +++ b/ets2panda/util/perfMetrics.h @@ -34,6 +34,12 @@ namespace ark::es2panda::util { ark::es2panda::util::PerfMetricScope ES2PANDA_PERF_CONCAT2(e2pPerfScope, __LINE__)( \ ES2PANDA_PERF_CONCAT2(e2pPerfRecord, __LINE__)) +#define ES2PANDA_PERF_SCOPELESS(name) \ + thread_local auto ES2PANDA_PERF_CONCAT2(e2pPerfRecord, __LINE__) = \ + ark::es2panda::util::RegisterPerfMetricRecord(name); \ + ark::es2panda::util::PrecisePerfMetricScope ES2PANDA_PERF_CONCAT2(e2pPerfScope, __LINE__)( \ + ES2PANDA_PERF_CONCAT2(e2pPerfRecord, __LINE__)) + // Similar to ES2PANDA_PERF_SCOPE, the current functions name is assigned to the performance record. // CC-OFFNXT(G.PRE.02-CPP) macro definition #define ES2PANDA_PERF_FN_SCOPE() ES2PANDA_PERF_SCOPE(__PRETTY_FUNCTION__) @@ -63,6 +69,18 @@ private: PerfMetricRecord *record_; }; +class PrecisePerfMetricScope { +public: + explicit PrecisePerfMetricScope(PerfMetricRecord *record); + ~PrecisePerfMetricScope(); + + NO_COPY_SEMANTIC(PrecisePerfMetricScope); + NO_MOVE_SEMANTIC(PrecisePerfMetricScope); + +private: + PerfMetricRecord *record_; +}; + } // namespace ark::es2panda::util #endif diff --git a/ets2panda/varbinder/scope.h b/ets2panda/varbinder/scope.h index 7e671e719f56c9e52edea5cba58d5cc7d9e0ea19..4be0c8f5ebedda6f5d3350240cdf8e950302e7ba 100644 --- a/ets2panda/varbinder/scope.h +++ b/ets2panda/varbinder/scope.h @@ -73,7 +73,7 @@ public: NO_COPY_SEMANTIC(Scope); NO_MOVE_SEMANTIC(Scope); - using VariableMap = ArenaUnorderedMap; + using VariableMap = ArenaMap; using InsertResult = std::pair; virtual ScopeType Type() const = 0;