From 70ad396bc49a96f39b7b4fe4c8d3034a4f606022 Mon Sep 17 00:00:00 2001 From: Bruno Ricci Date: Mon, 25 Mar 2019 17:08:51 +0000 Subject: [Sema][NFCI] Don't allocate storage for the various CorrectionCandidateCallback unless we are going to do some typo correction The various CorrectionCandidateCallbacks are currently heap-allocated unconditionally. This was needed because of delayed typo correction. However these allocations represent currently 15.4% of all allocations (number of allocations) when parsing all of Boost (!), mostly because of ParseCastExpression, ParseStatementOrDeclarationAfterAttrtibutes and isCXXDeclarationSpecifier. Note that all of these callback objects are small. Let's not do this. Instead initially allocate the callback on the stack, and only do a heap allocation if we are going to do some typo correction. Do this by: 1. Adding a clone function to each callback, which will do a polymorphic clone of the callback. This clone function is required to be implemented by every callback (of which there is a fair amount). Make sure this is the case by making it pure virtual. 2. Use this clone function when we are going to try to correct a typo. This additionally cut the time of -fsyntax-only on all of Boost by 0.5% (not that much, but still something). No functional changes intended. Differential Revision: https://reviews.llvm.org/D58827 Reviewed By: rnk llvm-svn: 356925 --- clang/lib/Sema/SemaLookup.cpp | 43 ++++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 21 deletions(-) (limited to 'clang/lib/Sema/SemaLookup.cpp') diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index 86960e0a1db..f27a9591dd2 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -4572,8 +4572,7 @@ static void AddKeywordsToConsumer(Sema &SemaRef, std::unique_ptr Sema::makeTypoCorrectionConsumer( const DeclarationNameInfo &TypoName, Sema::LookupNameKind LookupKind, - Scope *S, CXXScopeSpec *SS, - std::unique_ptr CCC, + Scope *S, CXXScopeSpec *SS, CorrectionCandidateCallback &CCC, DeclContext *MemberContext, bool EnteringContext, const ObjCObjectPointerType *OPT, bool ErrorRecovery) { @@ -4635,9 +4634,13 @@ std::unique_ptr Sema::makeTypoCorrectionConsumer( TypoName.getBeginLoc()); } - CorrectionCandidateCallback &CCCRef = *CCC; + // Extend the lifetime of the callback. We delayed this until here + // to avoid allocations in the hot path (which is where no typo correction + // occurs). Note that CorrectionCandidateCallback is polymorphic and + // initially stack-allocated. + std::unique_ptr ClonedCCC = CCC.clone(); auto Consumer = llvm::make_unique( - *this, TypoName, LookupKind, S, SS, std::move(CCC), MemberContext, + *this, TypoName, LookupKind, S, SS, std::move(ClonedCCC), MemberContext, EnteringContext); // Perform name lookup to find visible, similarly-named entities. @@ -4689,7 +4692,9 @@ std::unique_ptr Sema::makeTypoCorrectionConsumer( } } - AddKeywordsToConsumer(*this, *Consumer, S, CCCRef, SS && SS->isNotEmpty()); + AddKeywordsToConsumer(*this, *Consumer, S, + *Consumer->getCorrectionValidator(), + SS && SS->isNotEmpty()); // Build the NestedNameSpecifiers for the KnownNamespaces, if we're going // to search those namespaces. @@ -4743,19 +4748,18 @@ std::unique_ptr Sema::makeTypoCorrectionConsumer( TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, Sema::LookupNameKind LookupKind, Scope *S, CXXScopeSpec *SS, - std::unique_ptr CCC, + CorrectionCandidateCallback &CCC, CorrectTypoKind Mode, DeclContext *MemberContext, bool EnteringContext, const ObjCObjectPointerType *OPT, bool RecordFailure) { - assert(CCC && "CorrectTypo requires a CorrectionCandidateCallback"); - // Always let the ExternalSource have the first chance at correction, even // if we would otherwise have given up. if (ExternalSource) { - if (TypoCorrection Correction = ExternalSource->CorrectTypo( - TypoName, LookupKind, S, SS, *CCC, MemberContext, EnteringContext, OPT)) + if (TypoCorrection Correction = + ExternalSource->CorrectTypo(TypoName, LookupKind, S, SS, CCC, + MemberContext, EnteringContext, OPT)) return Correction; } @@ -4763,12 +4767,12 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, // WantObjCSuper is only true for CTC_ObjCMessageReceiver and for // some instances of CTC_Unknown, while WantRemainingKeywords is true // for CTC_Unknown but not for CTC_ObjCMessageReceiver. - bool ObjCMessageReceiver = CCC->WantObjCSuper && !CCC->WantRemainingKeywords; + bool ObjCMessageReceiver = CCC.WantObjCSuper && !CCC.WantRemainingKeywords; IdentifierInfo *Typo = TypoName.getName().getAsIdentifierInfo(); - auto Consumer = makeTypoCorrectionConsumer( - TypoName, LookupKind, S, SS, std::move(CCC), MemberContext, - EnteringContext, OPT, Mode == CTK_ErrorRecovery); + auto Consumer = makeTypoCorrectionConsumer(TypoName, LookupKind, S, SS, CCC, + MemberContext, EnteringContext, + OPT, Mode == CTK_ErrorRecovery); if (!Consumer) return TypoCorrection(); @@ -4878,16 +4882,13 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, /// needed. TypoExpr *Sema::CorrectTypoDelayed( const DeclarationNameInfo &TypoName, Sema::LookupNameKind LookupKind, - Scope *S, CXXScopeSpec *SS, - std::unique_ptr CCC, + Scope *S, CXXScopeSpec *SS, CorrectionCandidateCallback &CCC, TypoDiagnosticGenerator TDG, TypoRecoveryCallback TRC, CorrectTypoKind Mode, DeclContext *MemberContext, bool EnteringContext, const ObjCObjectPointerType *OPT) { - assert(CCC && "CorrectTypoDelayed requires a CorrectionCandidateCallback"); - - auto Consumer = makeTypoCorrectionConsumer( - TypoName, LookupKind, S, SS, std::move(CCC), MemberContext, - EnteringContext, OPT, Mode == CTK_ErrorRecovery); + auto Consumer = makeTypoCorrectionConsumer(TypoName, LookupKind, S, SS, CCC, + MemberContext, EnteringContext, + OPT, Mode == CTK_ErrorRecovery); // Give the external sema source a chance to correct the typo. TypoCorrection ExternalTypo; -- cgit v1.2.3