зеркало из 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;
|
CXXCtorInitializer **IvarInitializers;
|
||||||
unsigned NumIvarInitializers;
|
unsigned NumIvarInitializers;
|
||||||
|
|
||||||
/// true if class has a .cxx_[construct,destruct] method.
|
/// Do the ivars of this class require initialization other than
|
||||||
bool HasCXXStructors : 1;
|
/// zero-initialization?
|
||||||
|
bool HasNonZeroConstructors : 1;
|
||||||
|
|
||||||
|
/// Do the ivars of this class require non-trivial destruction?
|
||||||
|
bool HasDestructors : 1;
|
||||||
|
|
||||||
ObjCImplementationDecl(DeclContext *DC,
|
ObjCImplementationDecl(DeclContext *DC,
|
||||||
ObjCInterfaceDecl *classInterface,
|
ObjCInterfaceDecl *classInterface,
|
||||||
|
@ -1594,7 +1598,7 @@ class ObjCImplementationDecl : public ObjCImplDecl {
|
||||||
SuperClass(superDecl), IvarLBraceLoc(IvarLBraceLoc),
|
SuperClass(superDecl), IvarLBraceLoc(IvarLBraceLoc),
|
||||||
IvarRBraceLoc(IvarRBraceLoc),
|
IvarRBraceLoc(IvarRBraceLoc),
|
||||||
IvarInitializers(0), NumIvarInitializers(0),
|
IvarInitializers(0), NumIvarInitializers(0),
|
||||||
HasCXXStructors(false) {}
|
HasNonZeroConstructors(false), HasDestructors(false) {}
|
||||||
public:
|
public:
|
||||||
static ObjCImplementationDecl *Create(ASTContext &C, DeclContext *DC,
|
static ObjCImplementationDecl *Create(ASTContext &C, DeclContext *DC,
|
||||||
ObjCInterfaceDecl *classInterface,
|
ObjCInterfaceDecl *classInterface,
|
||||||
|
@ -1638,8 +1642,15 @@ public:
|
||||||
CXXCtorInitializer ** initializers,
|
CXXCtorInitializer ** initializers,
|
||||||
unsigned numInitializers);
|
unsigned numInitializers);
|
||||||
|
|
||||||
bool hasCXXStructors() const { return HasCXXStructors; }
|
/// Do any of the ivars of this class (not counting its base classes)
|
||||||
void setHasCXXStructors(bool val) { HasCXXStructors = val; }
|
/// 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
|
/// getIdentifier - Get the identifier that names the class
|
||||||
/// interface associated with this implementation.
|
/// interface associated with this implementation.
|
||||||
|
|
|
@ -2367,7 +2367,10 @@ enum NonFragileClassFlags {
|
||||||
NonFragileABI_Class_HasIvarReleaser = 0x00040,
|
NonFragileABI_Class_HasIvarReleaser = 0x00040,
|
||||||
|
|
||||||
/// Class implementation was compiled under ARC.
|
/// 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_begin(),
|
||||||
Interface->all_referenced_protocol_end());
|
Interface->all_referenced_protocol_end());
|
||||||
unsigned Flags = FragileABI_Class_Factory;
|
unsigned Flags = FragileABI_Class_Factory;
|
||||||
if (ID->hasCXXStructors())
|
if (ID->hasNonZeroConstructors() || ID->hasDestructors())
|
||||||
Flags |= FragileABI_Class_HasCXXStructors;
|
Flags |= FragileABI_Class_HasCXXStructors;
|
||||||
unsigned Size =
|
unsigned Size =
|
||||||
CGM.getContext().getASTObjCImplementationLayout(ID).getSize().getQuantity();
|
CGM.getContext().getASTObjCImplementationLayout(ID).getSize().getQuantity();
|
||||||
|
@ -5154,12 +5157,20 @@ void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) {
|
||||||
|
|
||||||
llvm::GlobalVariable *SuperClassGV, *IsAGV;
|
llvm::GlobalVariable *SuperClassGV, *IsAGV;
|
||||||
|
|
||||||
|
// Build the flags for the metaclass.
|
||||||
bool classIsHidden =
|
bool classIsHidden =
|
||||||
ID->getClassInterface()->getVisibility() == HiddenVisibility;
|
ID->getClassInterface()->getVisibility() == HiddenVisibility;
|
||||||
if (classIsHidden)
|
if (classIsHidden)
|
||||||
flags |= NonFragileABI_Class_Hidden;
|
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;
|
flags |= NonFragileABI_Class_HasCXXStructors;
|
||||||
|
if (!ID->hasNonZeroConstructors())
|
||||||
|
flags |= NonFragileABI_Class_HasCXXDestructorOnly;
|
||||||
|
}
|
||||||
|
|
||||||
if (!ID->getClassInterface()->getSuperClass()) {
|
if (!ID->getClassInterface()->getSuperClass()) {
|
||||||
// class is root
|
// class is root
|
||||||
flags |= NonFragileABI_Class_Root;
|
flags |= NonFragileABI_Class_Root;
|
||||||
|
@ -5194,9 +5205,20 @@ void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) {
|
||||||
flags = 0;
|
flags = 0;
|
||||||
if (classIsHidden)
|
if (classIsHidden)
|
||||||
flags |= NonFragileABI_Class_Hidden;
|
flags |= NonFragileABI_Class_Hidden;
|
||||||
if (ID->hasCXXStructors())
|
|
||||||
|
if (ID->hasNonZeroConstructors() || ID->hasDestructors()) {
|
||||||
flags |= NonFragileABI_Class_HasCXXStructors;
|
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()))
|
if (hasObjCExceptionAttribute(CGM.getContext(), ID->getClassInterface()))
|
||||||
flags |= NonFragileABI_Class_Exception;
|
flags |= NonFragileABI_Class_Exception;
|
||||||
|
|
||||||
|
|
|
@ -2541,7 +2541,7 @@ void CodeGenModule::EmitObjCIvarInitializations(ObjCImplementationDecl *D) {
|
||||||
/*isDefined=*/false, ObjCMethodDecl::Required);
|
/*isDefined=*/false, ObjCMethodDecl::Required);
|
||||||
D->addInstanceMethod(DTORMethod);
|
D->addInstanceMethod(DTORMethod);
|
||||||
CodeGenFunction(*this).GenerateObjCCtorDtorMethod(D, DTORMethod, false);
|
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
|
// If the implementation doesn't have any ivar initializers, we don't need
|
||||||
|
@ -2565,7 +2565,7 @@ void CodeGenModule::EmitObjCIvarInitializations(ObjCImplementationDecl *D) {
|
||||||
ObjCMethodDecl::Required);
|
ObjCMethodDecl::Required);
|
||||||
D->addInstanceMethod(CTORMethod);
|
D->addInstanceMethod(CTORMethod);
|
||||||
CodeGenFunction(*this).GenerateObjCCtorDtorMethod(D, CTORMethod, true);
|
CodeGenFunction(*this).GenerateObjCCtorDtorMethod(D, CTORMethod, true);
|
||||||
D->setHasCXXStructors(true);
|
D->setHasNonZeroConstructors(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// EmitNamespace - Emit all declarations in a namespace.
|
/// EmitNamespace - Emit all declarations in a namespace.
|
||||||
|
|
|
@ -855,6 +855,8 @@ void ASTDeclReader::VisitObjCImplementationDecl(ObjCImplementationDecl *D) {
|
||||||
D->setSuperClass(ReadDeclAs<ObjCInterfaceDecl>(Record, Idx));
|
D->setSuperClass(ReadDeclAs<ObjCInterfaceDecl>(Record, Idx));
|
||||||
D->setIvarLBraceLoc(ReadSourceLocation(Record, Idx));
|
D->setIvarLBraceLoc(ReadSourceLocation(Record, Idx));
|
||||||
D->setIvarRBraceLoc(ReadSourceLocation(Record, Idx));
|
D->setIvarRBraceLoc(ReadSourceLocation(Record, Idx));
|
||||||
|
D->setHasNonZeroConstructors(Record[Idx++]);
|
||||||
|
D->setHasDestructors(Record[Idx++]);
|
||||||
llvm::tie(D->IvarInitializers, D->NumIvarInitializers)
|
llvm::tie(D->IvarInitializers, D->NumIvarInitializers)
|
||||||
= Reader.ReadCXXCtorInitializers(F, Record, Idx);
|
= Reader.ReadCXXCtorInitializers(F, Record, Idx);
|
||||||
}
|
}
|
||||||
|
|
|
@ -606,6 +606,8 @@ void ASTDeclWriter::VisitObjCImplementationDecl(ObjCImplementationDecl *D) {
|
||||||
Writer.AddDeclRef(D->getSuperClass(), Record);
|
Writer.AddDeclRef(D->getSuperClass(), Record);
|
||||||
Writer.AddSourceLocation(D->getIvarLBraceLoc(), Record);
|
Writer.AddSourceLocation(D->getIvarLBraceLoc(), Record);
|
||||||
Writer.AddSourceLocation(D->getIvarRBraceLoc(), Record);
|
Writer.AddSourceLocation(D->getIvarRBraceLoc(), Record);
|
||||||
|
Record.push_back(D->hasNonZeroConstructors());
|
||||||
|
Record.push_back(D->hasDestructors());
|
||||||
Writer.AddCXXCtorInitializers(D->IvarInitializers, D->NumIvarInitializers,
|
Writer.AddCXXCtorInitializers(D->IvarInitializers, D->NumIvarInitializers,
|
||||||
Record);
|
Record);
|
||||||
Code = serialization::DECL_OBJC_IMPLEMENTATION;
|
Code = serialization::DECL_OBJC_IMPLEMENTATION;
|
||||||
|
|
|
@ -602,7 +602,10 @@ void test22(_Bool cond) {
|
||||||
|
|
||||||
// rdar://problem/8922540
|
// rdar://problem/8922540
|
||||||
// Note that we no longer emit .release_ivars flags.
|
// 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
|
@interface Test23 { id x; } @end
|
||||||
@implementation Test23 @end
|
@implementation Test23 @end
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче