]> granicus.if.org Git - clang/commitdiff
When building the structured initializer list, pre-allocate storage in
authorDouglas Gregor <dgregor@apple.com>
Fri, 20 Mar 2009 23:58:33 +0000 (23:58 +0000)
committerDouglas Gregor <dgregor@apple.com>
Fri, 20 Mar 2009 23:58:33 +0000 (23:58 +0000)
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.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@67421 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/Expr.h
lib/AST/Expr.cpp
lib/Sema/SemaInit.cpp

index 3a91a7070487d1ce883f7ffd6bd1bfa37e3e2fa1..9ce86ef12d559544f23bfa244182c7c0aaaf751f 100644 (file)
@@ -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
index fd1092f64c7ce105c2042fdd3d04d7741400ab04..330ba63b589a59e7ee069b8f5e10cac623c4958a 100644 (file)
@@ -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)
index 8a5e2c87d34bd78cb8669b09f58c2ca68082126e..336413291081397809e59ed32d2d85cc7d76308a 100644 (file)
@@ -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)