зеркало из https://github.com/microsoft/clang-1.git
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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@166088 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
621915c7a4
Коммит
b03527a9a3
|
@ -1581,8 +1581,12 @@ class ObjCImplementationDecl : public ObjCImplDecl {
|
|||
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 @@ class ObjCImplementationDecl : public ObjCImplDecl {
|
|||
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 @@ public:
|
|||
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.
|
||||
|
|
|
@ -2367,7 +2367,10 @@ enum NonFragileClassFlags {
|
|||
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 @@ void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
|
|||
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 @@ void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) {
|
|||
|
||||
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 @@ void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) {
|
|||
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;
|
||||
|
||||
|
|
|
@ -2541,7 +2541,7 @@ void CodeGenModule::EmitObjCIvarInitializations(ObjCImplementationDecl *D) {
|
|||
/*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 @@ void CodeGenModule::EmitObjCIvarInitializations(ObjCImplementationDecl *D) {
|
|||
ObjCMethodDecl::Required);
|
||||
D->addInstanceMethod(CTORMethod);
|
||||
CodeGenFunction(*this).GenerateObjCCtorDtorMethod(D, CTORMethod, true);
|
||||
D->setHasCXXStructors(true);
|
||||
D->setHasNonZeroConstructors(true);
|
||||
}
|
||||
|
||||
/// EmitNamespace - Emit all declarations in a namespace.
|
||||
|
|
|
@ -855,6 +855,8 @@ void ASTDeclReader::VisitObjCImplementationDecl(ObjCImplementationDecl *D) {
|
|||
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);
|
||||
}
|
||||
|
|
|
@ -606,6 +606,8 @@ void ASTDeclWriter::VisitObjCImplementationDecl(ObjCImplementationDecl *D) {
|
|||
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;
|
||||
|
|
|
@ -602,7 +602,10 @@ void test22(_Bool cond) {
|
|||
|
||||
// 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
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче