Skip to content

Commit

Permalink
Optimize class lookup
Browse files Browse the repository at this point in the history
Gets rid of a small amount of class lookup and reduces codegen slightly from the main library by encoding the classes directly into data structures where possible.
  • Loading branch information
dmaclach authored and thomasvl committed Dec 19, 2019
1 parent 7d1e1e7 commit 1de9728
Showing 1 changed file with 29 additions and 48 deletions.
77 changes: 29 additions & 48 deletions Source/Objects/GTLRRuntimeCommon.m
Original file line number Diff line number Diff line change
Expand Up @@ -320,9 +320,7 @@ typedef NS_ENUM(NSUInteger, GTLRPropertyType) {
// These are the "fixed" return classes, but some properties will require
// looking up the return class instead (because it is a subclass of
// GTLRObject).
const char *returnClassName;
Class returnClass;
BOOL extractReturnClass;

} GTLRDynamicImpInfo;

Expand All @@ -347,6 +345,18 @@ typedef NS_ENUM(NSUInteger, GTLRPropertyType) {
// T@"GTLRLink",D
// T@"NSArray",D

// References to classes that we can put in static structures.
extern const struct {} GTLRNSArrayClass __asm__("_OBJC_CLASS_$_NSArray");
extern const struct {} GTLRNSObjectClass __asm__("_OBJC_CLASS_$_NSObject");
extern const struct {} GTLRNSStringClass __asm__("_OBJC_CLASS_$_NSString");
extern const struct {} GTLRNSNumberClass __asm__("_OBJC_CLASS_$_NSNumber");
extern const struct {} GTLRDateTimeClass
__asm__("_OBJC_CLASS_$_" GTLR_CLASSNAME_CSTR(GTLRDateTime));
extern const struct {} GTLRDurationClass
__asm__("_OBJC_CLASS_$_" GTLR_CLASSNAME_CSTR(GTLRDuration));

// Denotes that the class is dynamic and must be resolved.
const Class kLookupClass = (__bridge Class)(void *)0x1;

static GTLRDynamicImpInfo kImplInfo[] = {
#if !defined(__LP64__) || !__LP64__
Expand All @@ -355,67 +365,59 @@ typedef NS_ENUM(NSUInteger, GTLRPropertyType) {
GTLRPropertyTypeInt32,
"v@:i",
"i@:",
nil, nil,
NO
Nil,
},
{ // NSUInteger on 32bit
"TI",
GTLRPropertyTypeUInt32,
"v@:I",
"I@:",
nil, nil,
NO
Nil,
},
#endif
{ // NSInteger on 64bit, long long on 32bit and 64bit.
"Tq",
GTLRPropertyTypeLongLong,
"v@:q",
"q@:",
nil, nil,
NO
Nil,
},
{ // NSUInteger on 64bit, long long on 32bit and 64bit.
"TQ",
GTLRPropertyTypeULongLong,
"v@:Q",
"Q@:",
nil, nil,
NO
Nil,
},
{ // float
"Tf",
GTLRPropertyTypeFloat,
"v@:f",
"f@:",
nil, nil,
NO
Nil,
},
{ // double
"Td",
GTLRPropertyTypeDouble,
"v@:d",
"d@:",
nil, nil,
NO
Nil,
},
#if defined(OBJC_BOOL_IS_BOOL) && OBJC_BOOL_IS_BOOL
{ // BOOL as bool
"TB",
GTLRPropertyTypeBool,
"v@:B",
"B@:",
nil, nil,
NO
Nil,
},
#elif defined(OBJC_BOOL_IS_CHAR) && OBJC_BOOL_IS_CHAR
{ // BOOL as char
"Tc",
GTLRPropertyTypeBool,
"v@:c",
"c@:",
nil, nil,
NO
Nil,
},
#else
#error unknown definition for ObjC BOOL type
Expand All @@ -425,73 +427,52 @@ typedef NS_ENUM(NSUInteger, GTLRPropertyType) {
GTLRPropertyTypeNSString,
"v@:@",
"@@:",
"NSString", nil,
NO
(__bridge Class)&GTLRNSStringClass,
},
{ // NSNumber
"T@\"NSNumber\"",
GTLRPropertyTypeNSNumber,
"v@:@",
"@@:",
"NSNumber", nil,
NO
(__bridge Class)&GTLRNSNumberClass,
},
{ // GTLRDateTime
"T@\"" GTLR_CLASSNAME_CSTR(GTLRDateTime) "\"",
GTLRPropertyTypeGTLRDateTime,
"v@:@",
"@@:",
GTLR_CLASSNAME_CSTR(GTLRDateTime), nil,
NO
(__bridge Class)&GTLRNSNumberClass,
},
{ // GTLRDuration
"T@\"" GTLR_CLASSNAME_CSTR(GTLRDuration) "\"",
GTLRPropertyTypeGTLRDuration,
"v@:@",
"@@:",
GTLR_CLASSNAME_CSTR(GTLRDuration), nil,
NO
(__bridge Class)&GTLRDurationClass,
},
{ // NSArray with type
"T@\"NSArray\"",
GTLRPropertyTypeNSArray,
"v@:@",
"@@:",
"NSArray", nil,
NO
(__bridge Class)&GTLRNSArrayClass,
},
{ // id (any of the objects above)
"T@,",
GTLRPropertyTypeNSObject,
"v@:@",
"@@:",
"NSObject", nil,
NO
(__bridge Class)&GTLRNSObjectClass,
},
{ // GTLRObject - Last, cause it's a special case and prefix is general
"T@\"",
GTLRPropertyTypeGTLRObject,
"v@:@",
"@@:",
nil, nil,
YES
kLookupClass,
},
};

static BOOL hasLookedUpClasses = NO;
if (!hasLookedUpClasses) {
// Unfortunately, you can't put [NSString class] into the static structure,
// so this lookup has to be done at runtime.
hasLookedUpClasses = YES;
for (uint32_t idx = 0; idx < sizeof(kImplInfo)/sizeof(kImplInfo[0]); ++idx) {
if (kImplInfo[idx].returnClassName) {
kImplInfo[idx].returnClass = objc_getClass(kImplInfo[idx].returnClassName);
NSCAssert1(kImplInfo[idx].returnClass != nil,
@"GTLRRuntimeCommon: class lookup failed: %s", kImplInfo[idx].returnClassName);
}
}
}

const char *attr = property_getAttributes(prop);

const char *dynamicMarker = strstr(attr, ",D");
Expand Down Expand Up @@ -521,7 +502,7 @@ typedef NS_ENUM(NSUInteger, GTLRPropertyType) {
return NULL;
}

if (result->extractReturnClass && outReturnClass) {
if (result->returnClass == kLookupClass && outReturnClass) {

// add a null at the next quotation mark
char *attrCopy = strdup(attr);
Expand All @@ -532,7 +513,7 @@ typedef NS_ENUM(NSUInteger, GTLRPropertyType) {

// Lookup the return class
*outReturnClass = objc_getClass(classNameStart);
if (*outReturnClass == nil) {
if (*outReturnClass == Nil) {
GTLR_DEBUG_LOG(@"GTLRRuntimeCommon: did not find class with name \"%s\" "
@"for property \"%s\" with attributes \"%s\"",
classNameStart, property_getName(prop), attr);
Expand Down

0 comments on commit 1de9728

Please sign in to comment.