diff --git a/ets2panda/checker/ETSAnalyzer.cpp b/ets2panda/checker/ETSAnalyzer.cpp index 1fec1bafe8b24dbdcded94cee335d42627d4ddde..150a2d72ff7fc16a1b2202a723f806df4f0141be 100644 --- a/ets2panda/checker/ETSAnalyzer.cpp +++ b/ets2panda/checker/ETSAnalyzer.cpp @@ -29,6 +29,7 @@ #include "types/type.h" #include "types/typeFlag.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_SCOPE("@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_SCOPE("@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_SCOPE("@Check-ClassProperty"); if (st->TsType() != nullptr) { return st->TsType(); } @@ -139,6 +143,7 @@ checker::Type *ETSAnalyzer::Check(ir::ClassProperty *st) const checker::Type *ETSAnalyzer::Check(ir::ClassStaticBlock *st) const { + ES2PANDA_PERF_SCOPE("@Check-StaticBlock"); ETSChecker *checker = GetETSChecker(); if (checker->HasStatus(checker::CheckerStatus::INNER_CLASS)) { @@ -213,6 +218,7 @@ static bool IsInitializerBlockTransfer(std::string_view str) checker::Type *ETSAnalyzer::Check(ir::MethodDefinition *node) const { + ES2PANDA_PERF_SCOPE("@Check-MethodDefinition"); ETSChecker *checker = GetETSChecker(); auto *scriptFunc = node->Function(); @@ -345,6 +351,7 @@ static void CheckDuplicationInOverloadDeclaration(ETSChecker *const checker, ir: checker::Type *ETSAnalyzer::Check(ir::OverloadDeclaration *node) const { + ES2PANDA_PERF_SCOPE("@Check-OverloadDeclaration"); ETSChecker *checker = GetETSChecker(); ES2PANDA_ASSERT(node != nullptr); ES2PANDA_ASSERT(node->Key()); @@ -386,12 +393,14 @@ checker::Type *ETSAnalyzer::Check(ir::OverloadDeclaration *node) const checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::Property *expr) const { + ES2PANDA_PERF_SCOPE("@Check-Property"); ETSChecker *checker = GetETSChecker(); return checker->GlobalTypeError(); } checker::Type *ETSAnalyzer::Check(ir::SpreadElement *expr) const { + ES2PANDA_PERF_SCOPE("@Check-SpreadElement"); if (expr->TsType() != nullptr) { return expr->TsType(); } @@ -421,6 +430,7 @@ checker::Type *ETSAnalyzer::Check(ir::SpreadElement *expr) const checker::Type *ETSAnalyzer::Check(ir::TemplateElement *expr) const { + ES2PANDA_PERF_SCOPE("@Check-SpreadElement"); ETSChecker *checker = GetETSChecker(); expr->SetTsType(checker->CreateETSStringLiteralType(expr->Raw())); return expr->TsType(); @@ -428,6 +438,7 @@ checker::Type *ETSAnalyzer::Check(ir::TemplateElement *expr) const checker::Type *ETSAnalyzer::Check(ir::ETSClassLiteral *expr) const { + ES2PANDA_PERF_SCOPE("@Check-ETSClassLiteral"); ETSChecker *checker = GetETSChecker(); auto *const literal = expr->Expr(); @@ -454,6 +465,7 @@ checker::Type *ETSAnalyzer::Check(ir::ETSClassLiteral *expr) const checker::Type *ETSAnalyzer::Check(ir::ETSFunctionType *node) const { + ES2PANDA_PERF_SCOPE("@Check-ETSFunctionType"); if (node->TsType() != nullptr) { return node->TsType(); } @@ -526,6 +538,7 @@ static bool NeedCreateETSResizableArrayType(ETSChecker *checker, Type *type) checker::Type *ETSAnalyzer::Check(ir::ETSNewArrayInstanceExpression *expr) const { + ES2PANDA_PERF_SCOPE("@Check-ETSNewArrayInstanceExpression"); if (expr->TsType() != nullptr) { return expr->TsType(); } @@ -591,6 +604,7 @@ static checker::Type *CheckInstantiatedNewType(ETSChecker *checker, ir::ETSNewCl checker::Type *ETSAnalyzer::Check(ir::ETSNewClassInstanceExpression *expr) const { + ES2PANDA_PERF_SCOPE("@Check-ETSNewClassInstanceExpression"); if (expr->TsType() != nullptr) { return expr->TsType(); } @@ -619,6 +633,7 @@ checker::Type *ETSAnalyzer::Check(ir::ETSNewClassInstanceExpression *expr) const checker::Type *ETSAnalyzer::Check(ir::ETSNewMultiDimArrayInstanceExpression *expr) const { + ES2PANDA_PERF_SCOPE("@Check-ETSNewMultiDimArrayInstanceExpression"); if (expr->TsType() != nullptr) { return expr->TsType(); } @@ -651,11 +666,13 @@ checker::Type *ETSAnalyzer::Check(ir::ETSNewMultiDimArrayInstanceExpression *exp checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::ETSPackageDeclaration *st) const { + ES2PANDA_PERF_SCOPE("@Check-ETSPackageDeclaration"); return ReturnTypeForStatement(st); } checker::Type *ETSAnalyzer::Check(ir::ETSParameterExpression *expr) const { + ES2PANDA_PERF_SCOPE("@Check-ETSParameterExpression"); ETSChecker *checker = GetETSChecker(); if (expr->TsType() != nullptr) { return expr->TsType(); @@ -676,12 +693,14 @@ checker::Type *ETSAnalyzer::Check(ir::ETSParameterExpression *expr) const checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::ETSPrimitiveType *node) const { + ES2PANDA_PERF_SCOPE("@Check-ETSPrimitiveType"); ETSChecker *checker = GetETSChecker(); return node->GetType(checker); } checker::Type *ETSAnalyzer::Check(ir::ETSStructDeclaration *node) const { + ES2PANDA_PERF_SCOPE("@Check-ETSStructDeclaration"); ETSChecker *checker = GetETSChecker(); node->Definition()->Check(checker); return ReturnTypeForStatement(node); @@ -689,6 +708,7 @@ checker::Type *ETSAnalyzer::Check(ir::ETSStructDeclaration *node) const checker::Type *ETSAnalyzer::Check(ir::ETSTypeReference *node) const { + ES2PANDA_PERF_SCOPE("@Check-ETSTypeReference"); ETSChecker *checker = GetETSChecker(); checker->CheckAnnotations(node->Annotations()); return node->GetType(checker); @@ -696,12 +716,14 @@ checker::Type *ETSAnalyzer::Check(ir::ETSTypeReference *node) const checker::Type *ETSAnalyzer::Check(ir::ETSTypeReferencePart *node) const { + ES2PANDA_PERF_SCOPE("@Check-ETSTypeReferencePart"); ETSChecker *checker = GetETSChecker(); return node->GetType(checker); } checker::Type *ETSAnalyzer::Check(ir::ETSNonNullishTypeNode *node) const { + ES2PANDA_PERF_SCOPE("@Check-ETSNonNullishTypeNode"); if (node->TsType() != nullptr) { return node->TsType(); } @@ -716,6 +738,7 @@ checker::Type *ETSAnalyzer::Check(ir::ETSNonNullishTypeNode *node) const checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::ETSNullType *node) const { + ES2PANDA_PERF_SCOPE("@Check-ETSNullType"); ETSChecker *checker = GetETSChecker(); checker->CheckAnnotations(node->Annotations()); return node->SetTsType(checker->GlobalETSNullType()); @@ -723,6 +746,7 @@ checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::ETSNullType *node) const checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::ETSUndefinedType *node) const { + ES2PANDA_PERF_SCOPE("@Check-ETSUndefinedType"); ETSChecker *checker = GetETSChecker(); checker->CheckAnnotations(node->Annotations()); return node->SetTsType(checker->GlobalETSUndefinedType()); @@ -730,12 +754,14 @@ checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::ETSUndefinedType *node) c checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::ETSNeverType *node) const { + ES2PANDA_PERF_SCOPE("@Check-ETSNeverType"); ETSChecker *checker = GetETSChecker(); return checker->GlobalETSNeverType(); } checker::Type *ETSAnalyzer::Check(ir::ETSStringLiteralType *node) const { + ES2PANDA_PERF_SCOPE("@Check-ETSStringLiteralType"); ETSChecker *checker = GetETSChecker(); checker->CheckAnnotations(node->Annotations()); return node->GetType(checker); @@ -743,6 +769,7 @@ checker::Type *ETSAnalyzer::Check(ir::ETSStringLiteralType *node) const checker::Type *ETSAnalyzer::Check(ir::ETSKeyofType *node) const { + ES2PANDA_PERF_SCOPE("@Check-ETSKeyofType"); ETSChecker *checker = GetETSChecker(); return node->GetType(checker); } @@ -962,6 +989,7 @@ static Type *GetAppropriatePreferredType(Type *originalType, std::functionTsType() != nullptr) { return expr->TsType(); @@ -1027,6 +1055,7 @@ void TryInferPreferredType(ir::ArrowFunctionExpression *expr, checker::Type *pre checker::Type *ETSAnalyzer::Check(ir::ArrowFunctionExpression *expr) const { + ES2PANDA_PERF_SCOPE("@Check-ArrowFunctionExpession"); ETSChecker *checker = GetETSChecker(); checker->CheckAnnotations(expr->Annotations()); if (expr->TsType() != nullptr) { @@ -1186,6 +1215,7 @@ static bool IsInvalidMethodAssignment(const ir::AssignmentExpression *const expr checker::Type *ETSAnalyzer::Check(ir::AssignmentExpression *const expr) const { + ES2PANDA_PERF_SCOPE("@Check-AssignmentExpression"); if (expr->TsType() != nullptr) { return expr->TsType(); } @@ -1317,6 +1347,7 @@ static bool IsPromiseType(checker::Type *type, ETSChecker *checker) checker::Type *ETSAnalyzer::Check(ir::AwaitExpression *expr) const { + ES2PANDA_PERF_SCOPE("@Check-AwaitExpression"); ETSChecker *checker = GetETSChecker(); if (expr->TsType() != nullptr) { return expr->TsType(); @@ -1378,6 +1409,7 @@ checker::Type *ETSAnalyzer::UnwrapPromiseType(checker::Type *type) const checker::Type *ETSAnalyzer::Check(ir::BinaryExpression *expr) const { + ES2PANDA_PERF_SCOPE("@Check-BinaryExpression"); if (expr->TsType() != nullptr) { return expr->TsType(); } @@ -1419,6 +1451,7 @@ checker::Type *ETSAnalyzer::Check(ir::BinaryExpression *expr) const checker::Type *ETSAnalyzer::Check(ir::BlockExpression *st) const { + ES2PANDA_PERF_SCOPE("@Check-BlockExpression"); if (st->TsType() != nullptr) { return st->TsType(); } @@ -1650,6 +1683,7 @@ checker::Type *ETSAnalyzer::GetCallExpressionReturnType(ir::CallExpression *expr checker::Type *ETSAnalyzer::Check(ir::CallExpression *expr) const { + ES2PANDA_PERF_SCOPE("@Check-CallExpression"); ETSChecker *checker = GetETSChecker(); if (expr->TsType() != nullptr) { return expr->TsType(); @@ -1743,6 +1777,7 @@ static Type *BiggerNumericType(ETSChecker *checker, Type *t1, Type *t2) checker::Type *ETSAnalyzer::Check(ir::ConditionalExpression *expr) const { + ES2PANDA_PERF_SCOPE("@Check-ConditionalExpression"); if (expr->TsType() != nullptr) { return expr->TsType(); } @@ -1841,6 +1876,7 @@ static Type *TransformTypeForMethodReference(ETSChecker *checker, ir::Expression checker::Type *ETSAnalyzer::Check(ir::Identifier *expr) const { + ES2PANDA_PERF_SCOPE("@Check-Identifier"); if (expr->TsType() != nullptr) { return expr->TsType(); } @@ -2691,6 +2727,7 @@ static checker::Type *ComputeTypeOfType(ETSChecker *checker, checker::Type *argT checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::TypeofExpression *expr) const { + ES2PANDA_PERF_SCOPE("@Check-TypeofExpression"); ETSChecker *checker = GetETSChecker(); if (expr->TsType() != nullptr) { return expr->TsType(); @@ -2703,6 +2740,7 @@ checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::TypeofExpression *expr) c checker::Type *ETSAnalyzer::Check(ir::UnaryExpression *expr) const { + ES2PANDA_PERF_SCOPE("@Check-UnaryExpression"); ETSChecker *checker = GetETSChecker(); if (expr->TsType() != nullptr) { @@ -2752,6 +2790,7 @@ checker::Type *ETSAnalyzer::Check(ir::UnaryExpression *expr) const checker::Type *ETSAnalyzer::Check(ir::UpdateExpression *expr) const { + ES2PANDA_PERF_SCOPE("@Check-UpdateExpression"); ETSChecker *checker = GetETSChecker(); if (expr->TsType() != nullptr) { return expr->TsType(); @@ -2800,6 +2839,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_SCOPE("@Check-BigIntLiteral"); ETSChecker *checker = GetETSChecker(); expr->SetTsType(checker->CreateETSBigIntLiteralType(expr->Str())); return expr->TsType(); @@ -2807,6 +2847,7 @@ checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::BigIntLiteral *expr) cons checker::Type *ETSAnalyzer::Check(ir::BooleanLiteral *expr) const { + ES2PANDA_PERF_SCOPE("@Check-BooleanLiteral"); ETSChecker *checker = GetETSChecker(); if (expr->TsType() == nullptr) { auto type = checker->GlobalETSBooleanBuiltinType()->Clone(GetChecker()); @@ -2818,6 +2859,7 @@ checker::Type *ETSAnalyzer::Check(ir::BooleanLiteral *expr) const checker::Type *ETSAnalyzer::Check(ir::CharLiteral *expr) const { + ES2PANDA_PERF_SCOPE("@Check-CharLiteral"); ETSChecker *checker = GetETSChecker(); if (expr->TsType() == nullptr) { auto type = checker->GlobalCharBuiltinType()->Clone(GetChecker()); @@ -2829,6 +2871,7 @@ checker::Type *ETSAnalyzer::Check(ir::CharLiteral *expr) const checker::Type *ETSAnalyzer::Check(ir::NullLiteral *expr) const { + ES2PANDA_PERF_SCOPE("@Check-NullLiteral"); ETSChecker *checker = GetETSChecker(); if (expr->TsType() == nullptr) { expr->SetTsType(checker->GlobalETSNullType()); @@ -2866,6 +2909,7 @@ static bool CheckIfLiteralValueIsAppropriate(ETSChecker *checker, Type *type, ir checker::Type *ETSAnalyzer::Check(ir::NumberLiteral *expr) const { + ES2PANDA_PERF_SCOPE("@Check-NumberLiteral"); if (expr->TsType() != nullptr) { return expr->TsType(); } @@ -2900,6 +2944,7 @@ checker::Type *ETSAnalyzer::Check(ir::NumberLiteral *expr) const checker::Type *ETSAnalyzer::Check(ir::StringLiteral *expr) const { + ES2PANDA_PERF_SCOPE("@Check-StringLiteral"); ETSChecker *checker = GetETSChecker(); if (expr->TsType() == nullptr) { expr->SetTsType(checker->CreateETSStringLiteralType(expr->Str())); @@ -2909,6 +2954,7 @@ checker::Type *ETSAnalyzer::Check(ir::StringLiteral *expr) const checker::Type *ETSAnalyzer::Check(ir::ETSIntrinsicNode *node) const { + ES2PANDA_PERF_SCOPE("@Check-ETSIntrinsicNode"); ETSChecker *checker = GetETSChecker(); for (auto *arg : node->Arguments()) { arg->Check(checker); @@ -2928,6 +2974,7 @@ checker::Type *ETSAnalyzer::Check(ir::ETSIntrinsicNode *node) const checker::Type *ETSAnalyzer::Check(ir::ImportDeclaration *st) const { + ES2PANDA_PERF_SCOPE("@Check-ImportDeclaration"); ETSChecker *checker = GetETSChecker(); checker::Type *type = nullptr; for (auto *spec : st->Specifiers()) { @@ -2941,6 +2988,7 @@ checker::Type *ETSAnalyzer::Check(ir::ImportDeclaration *st) const checker::Type *ETSAnalyzer::Check(ir::ImportNamespaceSpecifier *st) const { + ES2PANDA_PERF_SCOPE("@Check-ImportNamespaceSpecifier"); ETSChecker *checker = GetETSChecker(); if (st->Local()->Name().Empty()) { return ReturnTypeForStatement(st); @@ -2971,11 +3019,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_SCOPE("@Check-AssertStement"); ES2PANDA_UNREACHABLE(); } checker::Type *ETSAnalyzer::Check(ir::BlockStatement *st) const { + ES2PANDA_PERF_SCOPE("@Check-BlockStement"); ETSChecker *checker = GetETSChecker(); checker::ScopeContext scopeCtx(checker, st->Scope()); @@ -3027,6 +3077,7 @@ checker::Type *ETSAnalyzer::Check(ir::BlockStatement *st) const checker::Type *ETSAnalyzer::Check(ir::BreakStatement *st) const { + ES2PANDA_PERF_SCOPE("@Check-BreakStatement"); ETSChecker *checker = GetETSChecker(); if (!st->HasTarget()) { @@ -3044,6 +3095,7 @@ checker::Type *ETSAnalyzer::Check(ir::BreakStatement *st) const checker::Type *ETSAnalyzer::Check(ir::ClassDeclaration *st) const { + ES2PANDA_PERF_SCOPE("@Check-ClassDeclaration"); ETSChecker *checker = GetETSChecker(); st->Definition()->Check(checker); return ReturnTypeForStatement(st); @@ -3051,6 +3103,7 @@ checker::Type *ETSAnalyzer::Check(ir::ClassDeclaration *st) const checker::Type *ETSAnalyzer::Check(ir::AnnotationDeclaration *st) const { + ES2PANDA_PERF_SCOPE("@Check-AnnotationDeclaration"); if (st->Expr()->TsType() != nullptr) { return ReturnTypeForStatement(st); } @@ -3095,6 +3148,7 @@ static void ProcessRequiredFields(ArenaUnorderedMapExpr()->TsType() != nullptr) { return ReturnTypeForStatement(st); } @@ -3135,6 +3189,7 @@ checker::Type *ETSAnalyzer::Check(ir::AnnotationUsage *st) const checker::Type *ETSAnalyzer::Check(ir::ContinueStatement *st) const { + ES2PANDA_PERF_SCOPE("@Check-ContinueStatement"); ETSChecker *checker = GetETSChecker(); if (!st->HasTarget()) { @@ -3152,6 +3207,7 @@ checker::Type *ETSAnalyzer::Check(ir::ContinueStatement *st) const checker::Type *ETSAnalyzer::Check(ir::DoWhileStatement *st) const { + ES2PANDA_PERF_SCOPE("@Check-DoWhileStatement"); ETSChecker *checker = GetETSChecker(); checker::ScopeContext scopeCtx(checker, st->Scope()); @@ -3167,11 +3223,13 @@ checker::Type *ETSAnalyzer::Check(ir::DoWhileStatement *st) const checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::EmptyStatement *st) const { + ES2PANDA_PERF_SCOPE("@Check-EmptyStatement"); return ReturnTypeForStatement(st); } checker::Type *ETSAnalyzer::Check(ir::ExpressionStatement *st) const { + ES2PANDA_PERF_SCOPE("@Check-ExpressionStatement"); ETSChecker *checker = GetETSChecker(); return st->GetExpression()->Check(checker); } @@ -3211,6 +3269,7 @@ static bool ValidateAndProcessIteratorType(ETSChecker *checker, Type *elemType, checker::Type *ETSAnalyzer::Check(ir::ForOfStatement *const st) const { + ES2PANDA_PERF_SCOPE("@Check-ForOfStatement"); ETSChecker *checker = GetETSChecker(); checker::ScopeContext scopeCtx(checker, st->Scope()); @@ -3252,6 +3311,7 @@ checker::Type *ETSAnalyzer::Check(ir::ForOfStatement *const st) const checker::Type *ETSAnalyzer::Check(ir::ForUpdateStatement *st) const { + ES2PANDA_PERF_SCOPE("@Check-ForUpdateStatement"); ETSChecker *checker = GetETSChecker(); checker::ScopeContext scopeCtx(checker, st->Scope()); @@ -3278,6 +3338,7 @@ checker::Type *ETSAnalyzer::Check(ir::ForUpdateStatement *st) const checker::Type *ETSAnalyzer::Check(ir::IfStatement *st) const { + ES2PANDA_PERF_SCOPE("@Check-IfStatement"); ETSChecker *const checker = GetETSChecker(); SmartCastArray smartCasts = checker->Context().EnterTestExpression(); @@ -3331,6 +3392,7 @@ checker::Type *ETSAnalyzer::Check(ir::IfStatement *st) const checker::Type *ETSAnalyzer::Check(ir::LabelledStatement *st) const { + ES2PANDA_PERF_SCOPE("@Check-LabeledStatement"); ETSChecker *checker = GetETSChecker(); st->body_->Check(checker); return ReturnTypeForStatement(st); @@ -3449,6 +3511,7 @@ checker::Type *ETSAnalyzer::GetFunctionReturnType(ir::ReturnStatement *st, ir::S checker::Type *ETSAnalyzer::Check(ir::ReturnStatement *st) const { + ES2PANDA_PERF_SCOPE("@Check-ReturnStatement"); ETSChecker *checker = GetETSChecker(); ir::AstNode *ancestor = util::Helpers::FindAncestorGivenByType(st, ir::AstNodeType::SCRIPT_FUNCTION); @@ -3483,6 +3546,7 @@ checker::Type *ETSAnalyzer::Check(ir::ReturnStatement *st) const checker::Type *ETSAnalyzer::Check(ir::SwitchStatement *st) const { + ES2PANDA_PERF_SCOPE("@Check-SwitchStatement"); ETSChecker *checker = GetETSChecker(); checker::ScopeContext scopeCtx(checker, st->Scope()); checker::SavedTypeRelationFlagsContext savedTypeRelationFlagCtx(checker->Relation(), @@ -3530,6 +3594,7 @@ checker::Type *ETSAnalyzer::Check(ir::SwitchStatement *st) const checker::Type *ETSAnalyzer::Check(ir::ThrowStatement *st) const { + ES2PANDA_PERF_SCOPE("@Check-ThrowStatement"); ETSChecker *checker = GetETSChecker(); const auto *arg = st->argument_; checker::Type *argType = st->argument_->Check(checker); @@ -3552,6 +3617,7 @@ checker::Type *ETSAnalyzer::Check(ir::ThrowStatement *st) const checker::Type *ETSAnalyzer::Check(ir::TryStatement *st) const { + ES2PANDA_PERF_SCOPE("@Check-TryStatement"); ETSChecker *checker = GetETSChecker(); std::vector exceptions {}; @@ -3595,6 +3661,7 @@ checker::Type *ETSAnalyzer::Check(ir::TryStatement *st) const checker::Type *ETSAnalyzer::Check(ir::VariableDeclarator *st) const { + ES2PANDA_PERF_SCOPE("@Check-VariableDeclarator"); if (st->TsType() != nullptr) { return st->TsType(); } @@ -3641,6 +3708,7 @@ checker::Type *ETSAnalyzer::Check(ir::VariableDeclarator *st) const checker::Type *ETSAnalyzer::Check(ir::VariableDeclaration *st) const { + ES2PANDA_PERF_SCOPE("@Check-VariableDeclaration"); ETSChecker *checker = GetETSChecker(); checker->CheckAnnotations(st->Annotations()); @@ -3654,6 +3722,7 @@ checker::Type *ETSAnalyzer::Check(ir::VariableDeclaration *st) const checker::Type *ETSAnalyzer::Check(ir::WhileStatement *st) const { + ES2PANDA_PERF_SCOPE("@Check-WhileStatement"); ETSChecker *checker = GetETSChecker(); checker::ScopeContext scopeCtx(checker, st->Scope()); @@ -3680,6 +3749,7 @@ checker::Type *ETSAnalyzer::Check(ir::WhileStatement *st) const checker::Type *ETSAnalyzer::Check(ir::TSArrayType *node) const { + ES2PANDA_PERF_SCOPE("@Check-TSArrayType"); ETSChecker *checker = GetETSChecker(); checker->CheckAnnotations(node->Annotations()); node->elementType_->Check(checker); @@ -3692,6 +3762,7 @@ checker::Type *ETSAnalyzer::Check(ir::TSArrayType *node) const checker::Type *ETSAnalyzer::Check(ir::TSAsExpression *expr) const { + ES2PANDA_PERF_SCOPE("@Check-TSAsExpression"); ETSChecker *checker = GetETSChecker(); if (expr->TsType() != nullptr) { @@ -3741,12 +3812,15 @@ checker::Type *ETSAnalyzer::Check(ir::TSAsExpression *expr) const checker::Type *ETSAnalyzer::Check(ir::TSEnumDeclaration *st) const { + ES2PANDA_PERF_SCOPE("@Check-TSEnumDeclaration"); + // Some invalid TSEnumDeclaration will not be transformed to class. return ReturnTypeForStatement(st); } checker::Type *ETSAnalyzer::Check(ir::TSInterfaceDeclaration *st) const { + ES2PANDA_PERF_SCOPE("@Check-TSInterfaceDeclaration"); if (st->TsType() != nullptr) { return st->TsType(); } @@ -3779,6 +3853,7 @@ checker::Type *ETSAnalyzer::Check(ir::TSInterfaceDeclaration *st) const checker::Type *ETSAnalyzer::Check(ir::TSNonNullExpression *expr) const { + ES2PANDA_PERF_SCOPE("@Check-TSNonNullExpression"); if (expr->TsType() != nullptr) { return expr->TsType(); } @@ -3859,6 +3934,7 @@ static varbinder::Variable *FindNameForImportNamespace(ETSChecker *checker, util checker::Type *ETSAnalyzer::Check(ir::TSQualifiedName *expr) const { + ES2PANDA_PERF_SCOPE("@Check-TSQualifiedName"); ETSChecker *checker = GetETSChecker(); checker::Type *baseType = expr->Left()->Check(checker)->MaybeBaseTypeOfGradualType(); if (baseType->IsETSObjectType()) { @@ -3892,6 +3968,7 @@ checker::Type *ETSAnalyzer::Check(ir::TSQualifiedName *expr) const checker::Type *ETSAnalyzer::Check(ir::TSTypeAliasDeclaration *st) const { + ES2PANDA_PERF_SCOPE("@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 c301c826b3faae4f4f5fdb00713854d26a5dda92..7126579ded268f7065b3338fd0cf5a6ffcd80619 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_SCOPE("@Check-AST"); + Program()->Ast()->Check(this); + } if (runAnalysis && !IsAnyError()) { AliveAnalyzer aliveAnalyzer(Program()->Ast(), this); diff --git a/ets2panda/compiler/lowering/util.cpp b/ets2panda/compiler/lowering/util.cpp index 865e9d1827b9d161c0c176f01eef75d344f621a1..a31d7c8c02fafcac277112d46859c654f312f28a 100644 --- a/ets2panda/compiler/lowering/util.cpp +++ b/ets2panda/compiler/lowering/util.cpp @@ -20,6 +20,7 @@ #include "checker/checker.h" #include "checker/ETSAnalyzer.h" #include "checker/types/gradualType.h" +#include "util/perfMetrics.h" namespace ark::es2panda::compiler { @@ -271,12 +272,14 @@ 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(); return; } + ES2PANDA_PERF_SCOPE("@Recheck-Prog-None"); auto *scope = Rebind(phaseManager, varBinder, node); // NOTE(gogabr: should determine checker status more finely. diff --git a/ets2panda/driver/build_system/src/build/base_mode.ts b/ets2panda/driver/build_system/src/build/base_mode.ts index 93a3e9b2203afbcfe53dc9efaf85f1e89452cc65..9996d1f94b36027ef6ee98db3e6d1ba550a9f5c9 100644 --- a/ets2panda/driver/build_system/src/build/base_mode.ts +++ b/ets2panda/driver/build_system/src/build/base_mode.ts @@ -106,6 +106,7 @@ export abstract class BaseMode { public hasCleanWorker: boolean; public byteCodeHar: boolean; public es2pandaMode: number; + public dumpPerf: boolean = true; constructor(buildConfig: BuildConfig) { this.buildConfig = buildConfig; @@ -315,6 +316,9 @@ export abstract class BaseMode { if (this.isDebug) { ets2pandaCmd.push('--debug-info'); } + if (this.dumpPerf) { + ets2pandaCmd.push('--dump-perf-metrics'); + } ets2pandaCmd.push(this.buildConfig.compileFiles[0]); this.logger.printInfo('ets2pandaCmd: ' + ets2pandaCmd.join(' ')); @@ -1511,4 +1515,4 @@ function createHash(str: string): string { // -- runConcurrent code ends -- -let finishedJob: string[] = []; \ No newline at end of file +let finishedJob: string[] = []; diff --git a/ets2panda/public/es2panda_lib.cpp b/ets2panda/public/es2panda_lib.cpp index 0b0638b0f7878fd3396d306664bcc06b6e844ee9..6ab557187d4690a1c6b3699666a324b38573f144 100644 --- a/ets2panda/public/es2panda_lib.cpp +++ b/ets2panda/public/es2panda_lib.cpp @@ -18,6 +18,7 @@ #include #include "util/diagnostic.h" +#include "util/perfMetrics.h" #include "varbinder/varbinder.h" #include "varbinder/scope.h" #include "public/public.h" @@ -283,6 +284,9 @@ extern "C" void DestroyConfig(es2panda_Config *config) return; } + if (cfg->options->IsDumpPerfMetrics()) { + util::DumpPerfMetrics(); + } delete cfg->options; cfg->diagnosticEngine->FlushDiagnostic(); delete cfg->diagnosticEngine; @@ -551,6 +555,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); @@ -619,6 +624,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(); @@ -659,6 +665,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; @@ -689,6 +696,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(); @@ -1079,6 +1087,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..911a31ce5e64e88bd8cca26cccc06cca04b8b50c 100644 --- a/ets2panda/util/perfMetrics.cpp +++ b/ets2panda/util/perfMetrics.cpp @@ -14,14 +14,17 @@ */ #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 #include +#include #include #include +#include #ifdef PANDA_TARGET_UNIX #include "sys/resource.h" @@ -72,6 +75,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 +92,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,6 +101,13 @@ private: return res; } + DEFAULT_COPY_SEMANTIC(PerfMetricValue); + DEFAULT_MOVE_SEMANTIC(PerfMetricValue); + ~PerfMetricValue() = default; + +private: + PerfMetricValue() = default; + int64_t time_ {}; int64_t mem_ {}; }; @@ -110,7 +120,18 @@ public: { 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_; @@ -134,6 +155,57 @@ public: } } + 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 +220,22 @@ 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; }; PerfMetricScope::PerfMetricScope(PerfMetricRecord *record) : record_(record) @@ -168,6 +249,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 +265,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 +336,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 +386,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) diff --git a/ets2panda/util/perfMetrics.h b/ets2panda/util/perfMetrics.h index 37f72ffbcacc6dd4219ba85d673c657142288610..37ef2a373e0836b704b77cfa4c1ada8aa7629962 100644 --- a/ets2panda/util/perfMetrics.h +++ b/ets2panda/util/perfMetrics.h @@ -31,7 +31,7 @@ namespace ark::es2panda::util { #define ES2PANDA_PERF_SCOPE(name) \ thread_local auto ES2PANDA_PERF_CONCAT2(e2pPerfRecord, __LINE__) = \ ark::es2panda::util::RegisterPerfMetricRecord(name); \ - ark::es2panda::util::PerfMetricScope ES2PANDA_PERF_CONCAT2(e2pPerfScope, __LINE__)( \ + 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. @@ -42,7 +42,7 @@ namespace ark::es2panda::util { // a new performance record. Do not use it if scope is created frequently. // CC-OFFNXT(G.PRE.02-CPP) macro definition #define ES2PANDA_PERF_EVENT_SCOPE(name) \ - ark::es2panda::util::PerfMetricScope e2pPerfScope(ark::es2panda::util::RegisterPerfMetricRecord(name)) + ark::es2panda::util::PrecisePerfMetricScope e2pPerfScope(ark::es2panda::util::RegisterPerfMetricRecord(name)) // NOLINTEND(cppcoreguidelines-macro-usage) // Dump all the collected performance records. Should not be called if there are active threads using the profile. @@ -63,6 +63,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