summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-03-20 23:58:33 +0000
committerDouglas Gregor <dgregor@apple.com>2009-03-20 23:58:33 +0000
commit6d00c993f517196e916b5b5585a60e362dfef6a9 (patch)
treedfb463e6fec877548de11ba743264eaf9e55fa6c /clang
parenta792bad8248a8c7f5f91a713cc61b87d18b771e0 (diff)
downloadbcm5719-llvm-6d00c993f517196e916b5b5585a60e362dfef6a9.tar.gz
bcm5719-llvm-6d00c993f517196e916b5b5585a60e362dfef6a9.zip
When building the structured initializer list, pre-allocate storage in
its vectors based on the subobject type we're initializing and the (unstructured) initializer list. This eliminates some malloc thrashing when parsing initializers (from 117 vector reallocations down to 0 when parsing Cocoa.h). We can't always pre-allocate the right amount of storage, since designated initializers can cause us to initialize in non-predictable patterns. llvm-svn: 67421
Diffstat (limited to 'clang')
-rw-r--r--clang/include/clang/AST/Expr.h3
-rw-r--r--clang/lib/AST/Expr.cpp5
-rw-r--r--clang/lib/Sema/SemaInit.cpp26
3 files changed, 34 insertions, 0 deletions
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 3a91a707048..9ce86ef12d5 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -1757,6 +1757,9 @@ public:
InitExprs[Init] = expr;
}
+ /// \brief Reserve space for some number of initializers.
+ void reserveInits(unsigned NumInits);
+
/// @brief Specify the number of initializers
///
/// If there are more than @p NumInits initializers, the remaining
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index fd1092f64c7..330ba63b589 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -338,6 +338,11 @@ InitListExpr::InitListExpr(SourceLocation lbraceloc,
InitExprs.insert(InitExprs.end(), initExprs, initExprs+numInits);
}
+void InitListExpr::reserveInits(unsigned NumInits) {
+ if (NumInits > InitExprs.size())
+ InitExprs.reserve(NumInits);
+}
+
void InitListExpr::resizeInits(ASTContext &Context, unsigned NumInits) {
for (unsigned Idx = NumInits, LastIdx = InitExprs.size();
Idx < LastIdx; ++Idx)
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 8a5e2c87d34..33641329108 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -1450,6 +1450,32 @@ InitListChecker::getStructuredSubobjectInit(InitListExpr *IList, unsigned Index,
Result->setType(CurrentObjectType);
+ // Pre-allocate storage for the structured initializer list.
+ unsigned NumElements = 0;
+ if (const ArrayType *AType
+ = SemaRef.Context.getAsArrayType(CurrentObjectType)) {
+ if (const ConstantArrayType *CAType = dyn_cast<ConstantArrayType>(AType)) {
+ NumElements = CAType->getSize().getZExtValue();
+ // Simple heuristic so that we don't allocate a very large
+ // initializer with many empty entries at the end.
+ if (IList && NumElements > IList->getNumInits())
+ NumElements = 0;
+ }
+ } else if (const VectorType *VType = CurrentObjectType->getAsVectorType())
+ NumElements = VType->getNumElements();
+ else if (const RecordType *RType = CurrentObjectType->getAsRecordType()) {
+ RecordDecl *RDecl = RType->getDecl();
+ if (RDecl->isUnion())
+ NumElements = 1;
+ else
+ NumElements = std::distance(RDecl->field_begin(), RDecl->field_end());
+ }
+
+ if (IList && NumElements < IList->getNumInits())
+ NumElements = IList->getNumInits();
+
+ Result->reserveInits(NumElements);
+
// Link this new initializer list into the structured initializer
// lists.
if (StructuredList)
OpenPOWER on IntegriCloud