From: Bruno Ricci Date: Tue, 20 Nov 2018 16:20:40 +0000 (+0000) Subject: [AST] Store the expressions in ParenListExpr in a trailing array X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b918bb9ddb1f23ec287ba6cb7b3cd7352acb205c;p=clang [AST] Store the expressions in ParenListExpr in a trailing array Use the newly available space in the bit-fields of Stmt and store the expressions in a trailing array. This saves 2 pointer per ParenListExpr. Differential Revision: https://reviews.llvm.org/D54675 Reviewed By: rjmccall git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@347320 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index c2aa8fd767..6165ff4bb6 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -4844,31 +4844,46 @@ public: } }; -class ParenListExpr : public Expr { - Stmt **Exprs; - unsigned NumExprs; +class ParenListExpr final + : public Expr, + private llvm::TrailingObjects { + friend class ASTStmtReader; + friend TrailingObjects; + + /// The location of the left and right parentheses. SourceLocation LParenLoc, RParenLoc; -public: - ParenListExpr(const ASTContext& C, SourceLocation lparenloc, - ArrayRef exprs, SourceLocation rparenloc); + /// Build a paren list. + ParenListExpr(SourceLocation LParenLoc, ArrayRef Exprs, + SourceLocation RParenLoc); /// Build an empty paren list. - explicit ParenListExpr(EmptyShell Empty) : Expr(ParenListExprClass, Empty) { } + ParenListExpr(EmptyShell Empty, unsigned NumExprs); + +public: + /// Create a paren list. + static ParenListExpr *Create(const ASTContext &Ctx, SourceLocation LParenLoc, + ArrayRef Exprs, + SourceLocation RParenLoc); + + /// Create an empty paren list. + static ParenListExpr *CreateEmpty(const ASTContext &Ctx, unsigned NumExprs); - unsigned getNumExprs() const { return NumExprs; } + /// Return the number of expressions in this paren list. + unsigned getNumExprs() const { return ParenListExprBits.NumExprs; } - const Expr* getExpr(unsigned Init) const { + Expr *getExpr(unsigned Init) { assert(Init < getNumExprs() && "Initializer access out of range!"); - return cast_or_null(Exprs[Init]); + return getExprs()[Init]; } - Expr* getExpr(unsigned Init) { - assert(Init < getNumExprs() && "Initializer access out of range!"); - return cast_or_null(Exprs[Init]); + const Expr *getExpr(unsigned Init) const { + return const_cast(this)->getExpr(Init); } - Expr **getExprs() { return reinterpret_cast(Exprs); } + Expr **getExprs() { + return reinterpret_cast(getTrailingObjects()); + } ArrayRef exprs() { return llvm::makeArrayRef(getExprs(), getNumExprs()); @@ -4876,9 +4891,8 @@ public: SourceLocation getLParenLoc() const { return LParenLoc; } SourceLocation getRParenLoc() const { return RParenLoc; } - - SourceLocation getBeginLoc() const LLVM_READONLY { return LParenLoc; } - SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; } + SourceLocation getBeginLoc() const { return getLParenLoc(); } + SourceLocation getEndLoc() const { return getRParenLoc(); } static bool classof(const Stmt *T) { return T->getStmtClass() == ParenListExprClass; @@ -4886,14 +4900,13 @@ public: // Iterators child_range children() { - return child_range(&Exprs[0], &Exprs[0]+NumExprs); + return child_range(getTrailingObjects(), + getTrailingObjects() + getNumExprs()); } const_child_range children() const { - return const_child_range(&Exprs[0], &Exprs[0] + NumExprs); + return const_child_range(getTrailingObjects(), + getTrailingObjects() + getNumExprs()); } - - friend class ASTStmtReader; - friend class ASTStmtWriter; }; /// Represents a C11 generic selection. diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h index 4883aa71e0..a78e461940 100644 --- a/include/clang/AST/Stmt.h +++ b/include/clang/AST/Stmt.h @@ -496,6 +496,16 @@ protected: unsigned HadArrayRangeDesignator : 1; }; + class ParenListExprBitfields { + friend class ASTStmtReader; + friend class ParenListExpr; + + unsigned : NumExprBits; + + /// The number of expressions in the paren list. + unsigned NumExprs; + }; + class PseudoObjectExprBitfields { friend class ASTStmtReader; // deserialization friend class PseudoObjectExpr; @@ -672,6 +682,7 @@ protected: CastExprBitfields CastExprBits; BinaryOperatorBitfields BinaryOperatorBits; InitListExprBitfields InitListExprBits; + ParenListExprBitfields ParenListExprBits; PseudoObjectExprBitfields PseudoObjectExprBits; // C++ Expressions diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index a8808185a1..31607dcf44 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -6409,8 +6409,8 @@ ExpectedStmt ASTNodeImporter::VisitParenListExpr(ParenListExpr *E) { if (!ToRParenLocOrErr) return ToRParenLocOrErr.takeError(); - return new (Importer.getToContext()) ParenListExpr( - Importer.getToContext(), *ToLParenLocOrErr, ToExprs, *ToRParenLocOrErr); + return ParenListExpr::Create(Importer.getToContext(), *ToLParenLocOrErr, + ToExprs, *ToRParenLocOrErr); } ExpectedStmt ASTNodeImporter::VisitStmtExpr(StmtExpr *E) { diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 2e26500862..ec6f084aed 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -4004,27 +4004,48 @@ SourceLocation DesignatedInitUpdateExpr::getEndLoc() const { return getBase()->getEndLoc(); } -ParenListExpr::ParenListExpr(const ASTContext& C, SourceLocation lparenloc, - ArrayRef exprs, - SourceLocation rparenloc) - : Expr(ParenListExprClass, QualType(), VK_RValue, OK_Ordinary, - false, false, false, false), - NumExprs(exprs.size()), LParenLoc(lparenloc), RParenLoc(rparenloc) { - Exprs = new (C) Stmt*[exprs.size()]; - for (unsigned i = 0; i != exprs.size(); ++i) { - if (exprs[i]->isTypeDependent()) +ParenListExpr::ParenListExpr(SourceLocation LParenLoc, ArrayRef Exprs, + SourceLocation RParenLoc) + : Expr(ParenListExprClass, QualType(), VK_RValue, OK_Ordinary, false, false, + false, false), + LParenLoc(LParenLoc), RParenLoc(RParenLoc) { + ParenListExprBits.NumExprs = Exprs.size(); + + for (unsigned I = 0, N = Exprs.size(); I != N; ++I) { + if (Exprs[I]->isTypeDependent()) ExprBits.TypeDependent = true; - if (exprs[i]->isValueDependent()) + if (Exprs[I]->isValueDependent()) ExprBits.ValueDependent = true; - if (exprs[i]->isInstantiationDependent()) + if (Exprs[I]->isInstantiationDependent()) ExprBits.InstantiationDependent = true; - if (exprs[i]->containsUnexpandedParameterPack()) + if (Exprs[I]->containsUnexpandedParameterPack()) ExprBits.ContainsUnexpandedParameterPack = true; - Exprs[i] = exprs[i]; + getTrailingObjects()[I] = Exprs[I]; } } +ParenListExpr::ParenListExpr(EmptyShell Empty, unsigned NumExprs) + : Expr(ParenListExprClass, Empty) { + ParenListExprBits.NumExprs = NumExprs; +} + +ParenListExpr *ParenListExpr::Create(const ASTContext &Ctx, + SourceLocation LParenLoc, + ArrayRef Exprs, + SourceLocation RParenLoc) { + void *Mem = Ctx.Allocate(totalSizeToAlloc(Exprs.size()), + alignof(ParenListExpr)); + return new (Mem) ParenListExpr(LParenLoc, Exprs, RParenLoc); +} + +ParenListExpr *ParenListExpr::CreateEmpty(const ASTContext &Ctx, + unsigned NumExprs) { + void *Mem = + Ctx.Allocate(totalSizeToAlloc(NumExprs), alignof(ParenListExpr)); + return new (Mem) ParenListExpr(EmptyShell(), NumExprs); +} + const OpaqueValueExpr *OpaqueValueExpr::findInCopyConstruct(const Expr *e) { if (const ExprWithCleanups *ewc = dyn_cast(e)) e = ewc->getSubExpr(); diff --git a/lib/Sema/SemaCoroutine.cpp b/lib/Sema/SemaCoroutine.cpp index 9c9d266d3d..cc79238470 100644 --- a/lib/Sema/SemaCoroutine.cpp +++ b/lib/Sema/SemaCoroutine.cpp @@ -565,8 +565,8 @@ VarDecl *Sema::buildCoroutinePromise(SourceLocation Loc) { // Create an initialization sequence for the promise type using the // constructor arguments, wrapped in a parenthesized list expression. - Expr *PLE = new (Context) ParenListExpr(Context, FD->getLocation(), - CtorArgExprs, FD->getLocation()); + Expr *PLE = ParenListExpr::Create(Context, FD->getLocation(), + CtorArgExprs, FD->getLocation()); InitializedEntity Entity = InitializedEntity::InitializeVariable(VD); InitializationKind Kind = InitializationKind::CreateForInit( VD->getLocation(), /*DirectInit=*/true, PLE); diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 6f173b165f..61ef7cb937 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -3731,8 +3731,7 @@ Sema::ActOnMemInitializer(Decl *ConstructorD, ArrayRef Args, SourceLocation RParenLoc, SourceLocation EllipsisLoc) { - Expr *List = new (Context) ParenListExpr(Context, LParenLoc, - Args, RParenLoc); + Expr *List = ParenListExpr::Create(Context, LParenLoc, Args, RParenLoc); return BuildMemInitializer(ConstructorD, S, SS, MemberOrBase, TemplateTypeTy, DS, IdLoc, List, EllipsisLoc); } diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 980dbf9921..50ace94018 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -6410,8 +6410,7 @@ Sema::MaybeConvertParenListExprToParenExpr(Scope *S, Expr *OrigExpr) { ExprResult Sema::ActOnParenListExpr(SourceLocation L, SourceLocation R, MultiExprArg Val) { - Expr *expr = new (Context) ParenListExpr(Context, L, Val, R); - return expr; + return ParenListExpr::Create(Context, L, Val, R); } /// Emit a specialized diagnostic when one expression is a null pointer diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp index db790c5ebf..a9baca8774 100644 --- a/lib/Serialization/ASTReaderStmt.cpp +++ b/lib/Serialization/ASTReaderStmt.cpp @@ -643,10 +643,9 @@ void ASTStmtReader::VisitParenExpr(ParenExpr *E) { void ASTStmtReader::VisitParenListExpr(ParenListExpr *E) { VisitExpr(E); unsigned NumExprs = Record.readInt(); - E->Exprs = new (Record.getContext()) Stmt*[NumExprs]; - for (unsigned i = 0; i != NumExprs; ++i) - E->Exprs[i] = Record.readSubStmt(); - E->NumExprs = NumExprs; + assert((NumExprs == E->getNumExprs()) && "Wrong NumExprs!"); + for (unsigned I = 0; I != NumExprs; ++I) + E->getTrailingObjects()[I] = Record.readSubStmt(); E->LParenLoc = ReadSourceLocation(); E->RParenLoc = ReadSourceLocation(); } @@ -2452,7 +2451,9 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { break; case EXPR_PAREN_LIST: - S = new (Context) ParenListExpr(Empty); + S = ParenListExpr::CreateEmpty( + Context, + /* NumExprs=*/Record[ASTStmtReader::NumExprFields + 0]); break; case EXPR_UNARY_OPERATOR: diff --git a/lib/Serialization/ASTWriterStmt.cpp b/lib/Serialization/ASTWriterStmt.cpp index 9f861bef89..e36b557533 100644 --- a/lib/Serialization/ASTWriterStmt.cpp +++ b/lib/Serialization/ASTWriterStmt.cpp @@ -559,11 +559,11 @@ void ASTStmtWriter::VisitParenExpr(ParenExpr *E) { void ASTStmtWriter::VisitParenListExpr(ParenListExpr *E) { VisitExpr(E); - Record.push_back(E->NumExprs); - for (unsigned i=0; i != E->NumExprs; ++i) - Record.AddStmt(E->Exprs[i]); - Record.AddSourceLocation(E->LParenLoc); - Record.AddSourceLocation(E->RParenLoc); + Record.push_back(E->getNumExprs()); + for (auto *SubStmt : E->exprs()) + Record.AddStmt(SubStmt); + Record.AddSourceLocation(E->getLParenLoc()); + Record.AddSourceLocation(E->getRParenLoc()); Code = serialization::EXPR_PAREN_LIST; }