[cfe-commits] r166088 - in /cfe/trunk: include/clang/AST/DeclObjC.h lib/CodeGen/CGObjCMac.cpp lib/CodeGen/CodeGenModule.cpp lib/Serialization/ASTReaderDecl.cpp lib/Serialization/ASTWriterDecl.cpp test/CodeGenObjC/arc.m

John McCall rjmccall at apple.com
Tue Oct 16 21:53:31 PDT 2012


Author: rjmccall
Date: Tue Oct 16 23:53:31 2012
New Revision: 166088

URL: http://llvm.org/viewvc/llvm-project?rev=166088&view=rev
Log:
Set a special flag in class metadata when an Objective-C class
has ivars that require destruction, but none that require anything
except zero-initialization.  This is common in ARC and (when true
throughout a class hierarchy) permits the elimination of an
unnecessary message-send during allocation.

Modified:
    cfe/trunk/include/clang/AST/DeclObjC.h
    cfe/trunk/lib/CodeGen/CGObjCMac.cpp
    cfe/trunk/lib/CodeGen/CodeGenModule.cpp
    cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
    cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
    cfe/trunk/test/CodeGenObjC/arc.m

Modified: cfe/trunk/include/clang/AST/DeclObjC.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclObjC.h?rev=166088&r1=166087&r2=166088&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclObjC.h (original)
+++ cfe/trunk/include/clang/AST/DeclObjC.h Tue Oct 16 23:53:31 2012
@@ -1581,8 +1581,12 @@
   CXXCtorInitializer **IvarInitializers;
   unsigned NumIvarInitializers;
 
-  /// true if class has a .cxx_[construct,destruct] method.
-  bool HasCXXStructors : 1;
+  /// Do the ivars of this class require initialization other than
+  /// zero-initialization?
+  bool HasNonZeroConstructors : 1;
+
+  /// Do the ivars of this class require non-trivial destruction?
+  bool HasDestructors : 1;
 
   ObjCImplementationDecl(DeclContext *DC,
                          ObjCInterfaceDecl *classInterface,
@@ -1594,7 +1598,7 @@
        SuperClass(superDecl), IvarLBraceLoc(IvarLBraceLoc), 
        IvarRBraceLoc(IvarRBraceLoc),
        IvarInitializers(0), NumIvarInitializers(0),
-       HasCXXStructors(false) {}
+       HasNonZeroConstructors(false), HasDestructors(false) {}
 public:
   static ObjCImplementationDecl *Create(ASTContext &C, DeclContext *DC,
                                         ObjCInterfaceDecl *classInterface,
@@ -1638,8 +1642,15 @@
                            CXXCtorInitializer ** initializers,
                            unsigned numInitializers);
 
-  bool hasCXXStructors() const { return HasCXXStructors; }
-  void setHasCXXStructors(bool val) { HasCXXStructors = val; }
+  /// Do any of the ivars of this class (not counting its base classes)
+  /// require construction other than zero-initialization?
+  bool hasNonZeroConstructors() const { return HasNonZeroConstructors; }
+  void setHasNonZeroConstructors(bool val) { HasNonZeroConstructors = val; }
+
+  /// Do any of the ivars of this class (not counting its base classes)
+  /// require non-trivial destruction?
+  bool hasDestructors() const { return HasDestructors; }
+  void setHasDestructors(bool val) { HasDestructors = val; }
 
   /// getIdentifier - Get the identifier that names the class
   /// interface associated with this implementation.

Modified: cfe/trunk/lib/CodeGen/CGObjCMac.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCMac.cpp?rev=166088&r1=166087&r2=166088&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjCMac.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjCMac.cpp Tue Oct 16 23:53:31 2012
@@ -2367,7 +2367,10 @@
   NonFragileABI_Class_HasIvarReleaser      = 0x00040,
 
   /// Class implementation was compiled under ARC.
-  NonFragileABI_Class_CompiledByARC        = 0x00080
+  NonFragileABI_Class_CompiledByARC        = 0x00080,
+
+  /// Class has non-trivial destructors, but zero-initialization is okay.
+  NonFragileABI_Class_HasCXXDestructorOnly = 0x00100
 };
 
 /*
@@ -2401,7 +2404,7 @@
                      Interface->all_referenced_protocol_begin(),
                      Interface->all_referenced_protocol_end());
   unsigned Flags = FragileABI_Class_Factory;
-  if (ID->hasCXXStructors())
+  if (ID->hasNonZeroConstructors() || ID->hasDestructors())
     Flags |= FragileABI_Class_HasCXXStructors;
   unsigned Size =
     CGM.getContext().getASTObjCImplementationLayout(ID).getSize().getQuantity();
@@ -5154,12 +5157,20 @@
 
   llvm::GlobalVariable *SuperClassGV, *IsAGV;
 
+  // Build the flags for the metaclass.
   bool classIsHidden =
     ID->getClassInterface()->getVisibility() == HiddenVisibility;
   if (classIsHidden)
     flags |= NonFragileABI_Class_Hidden;
-  if (ID->hasCXXStructors())
+
+  // FIXME: why is this flag set on the metaclass?
+  // ObjC metaclasses have no fields and don't really get constructed.
+  if (ID->hasNonZeroConstructors() || ID->hasDestructors()) {
     flags |= NonFragileABI_Class_HasCXXStructors;
+    if (!ID->hasNonZeroConstructors())
+      flags |= NonFragileABI_Class_HasCXXDestructorOnly;  
+  }
+
   if (!ID->getClassInterface()->getSuperClass()) {
     // class is root
     flags |= NonFragileABI_Class_Root;
@@ -5194,9 +5205,20 @@
   flags = 0;
   if (classIsHidden)
     flags |= NonFragileABI_Class_Hidden;
-  if (ID->hasCXXStructors())
+
+  if (ID->hasNonZeroConstructors() || ID->hasDestructors()) {
     flags |= NonFragileABI_Class_HasCXXStructors;
 
+    // Set a flag to enable a runtime optimization when a class has
+    // fields that require destruction but which don't require
+    // anything except zero-initialization during construction.  This
+    // is most notably true of __strong and __weak types, but you can
+    // also imagine there being C++ types with non-trivial default
+    // constructors that merely set all fields to null.
+    if (!ID->hasNonZeroConstructors())
+      flags |= NonFragileABI_Class_HasCXXDestructorOnly;
+  }
+
   if (hasObjCExceptionAttribute(CGM.getContext(), ID->getClassInterface()))
     flags |= NonFragileABI_Class_Exception;
 

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=166088&r1=166087&r2=166088&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Tue Oct 16 23:53:31 2012
@@ -2541,7 +2541,7 @@
                              /*isDefined=*/false, ObjCMethodDecl::Required);
     D->addInstanceMethod(DTORMethod);
     CodeGenFunction(*this).GenerateObjCCtorDtorMethod(D, DTORMethod, false);
-    D->setHasCXXStructors(true);
+    D->setHasDestructors(true);
   }
 
   // If the implementation doesn't have any ivar initializers, we don't need
@@ -2565,7 +2565,7 @@
                                                 ObjCMethodDecl::Required);
   D->addInstanceMethod(CTORMethod);
   CodeGenFunction(*this).GenerateObjCCtorDtorMethod(D, CTORMethod, true);
-  D->setHasCXXStructors(true);
+  D->setHasNonZeroConstructors(true);
 }
 
 /// EmitNamespace - Emit all declarations in a namespace.

Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=166088&r1=166087&r2=166088&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Tue Oct 16 23:53:31 2012
@@ -855,6 +855,8 @@
   D->setSuperClass(ReadDeclAs<ObjCInterfaceDecl>(Record, Idx));
   D->setIvarLBraceLoc(ReadSourceLocation(Record, Idx));
   D->setIvarRBraceLoc(ReadSourceLocation(Record, Idx));
+  D->setHasNonZeroConstructors(Record[Idx++]);
+  D->setHasDestructors(Record[Idx++]);
   llvm::tie(D->IvarInitializers, D->NumIvarInitializers)
       = Reader.ReadCXXCtorInitializers(F, Record, Idx);
 }

Modified: cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterDecl.cpp?rev=166088&r1=166087&r2=166088&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriterDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriterDecl.cpp Tue Oct 16 23:53:31 2012
@@ -606,6 +606,8 @@
   Writer.AddDeclRef(D->getSuperClass(), Record);
   Writer.AddSourceLocation(D->getIvarLBraceLoc(), Record);
   Writer.AddSourceLocation(D->getIvarRBraceLoc(), Record);
+  Record.push_back(D->hasNonZeroConstructors());
+  Record.push_back(D->hasDestructors());
   Writer.AddCXXCtorInitializers(D->IvarInitializers, D->NumIvarInitializers,
                                 Record);
   Code = serialization::DECL_OBJC_IMPLEMENTATION;

Modified: cfe/trunk/test/CodeGenObjC/arc.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/arc.m?rev=166088&r1=166087&r2=166088&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenObjC/arc.m (original)
+++ cfe/trunk/test/CodeGenObjC/arc.m Tue Oct 16 23:53:31 2012
@@ -602,7 +602,10 @@
 
 // rdar://problem/8922540
 //   Note that we no longer emit .release_ivars flags.
-// CHECK-GLOBALS: @"\01l_OBJC_CLASS_RO_$_Test23" = internal global [[RO_T:%.*]] { i32 134,
+// rdar://problem/12492434
+//   Note that we set the flag saying that we need destruction *and*
+//   the flag saying that we don't also need construction.
+// CHECK-GLOBALS: @"\01l_OBJC_CLASS_RO_$_Test23" = internal global [[RO_T:%.*]] { i32 390,
 @interface Test23 { id x; } @end
 @implementation Test23 @end
 





More information about the cfe-commits mailing list