Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a UserType flag for registered types, and use it to improve the performance for is_user_type. #5017

Merged
merged 2 commits into from
Oct 22, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 37 additions & 5 deletions runtime/runtime.m
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@
};

enum InitializationFlags : int {
/* unused = 0x01,*/
InitializationFlagsIsPartialStaticRegistrar = 0x01,
/* unused = 0x02,*/
InitializationFlagsDynamicRegistrar = 0x04,
/* unused = 0x08,*/
Expand Down Expand Up @@ -1014,14 +1014,15 @@ -(void) xamarinSetGCHandle: (int) gc_handle;
}

void
xamarin_add_registration_map (struct MTRegistrationMap *map)
xamarin_add_registration_map (struct MTRegistrationMap *map, bool partial)
{
// COOP: no managed memory access: any mode
options.RegistrationData = map;
if (partial)
options.flags = (InitializationFlags) (options.flags | InitializationFlagsIsPartialStaticRegistrar);

// Sort the type map according to Class
qsort (map->map, map->map_count - map->custom_type_count, sizeof (MTClassMap), compare_mtclassmap);
qsort (&map->map [map->map_count - map->custom_type_count], map->custom_type_count, sizeof (MTClassMap), compare_mtclassmap);
qsort (map->map, map->map_count, sizeof (MTClassMap), compare_mtclassmap);
}

/*
Expand Down Expand Up @@ -1895,11 +1896,42 @@ -(void) xamarinSetGCHandle: (int) gc_handle;
set_raw_gchandle (self, gchandle);
}

static int
find_user_type_index (MTClassMap *map, int lo, int hi, Class cls)
{
if (hi >= lo) {
int mid = lo + (hi - lo) / 2;

if (map [mid].handle == cls)
return mid;

if ((intptr_t) map [mid].handle > (intptr_t) cls)
return find_user_type_index (map, lo, mid - 1, cls);

return find_user_type_index (map, mid + 1, hi, cls);
}

return -1;
}

static inline bool
is_user_type (id self)
{
Class cls = object_getClass (self);

if (options.RegistrationData != NULL && options.RegistrationData->map_count > 0) {
MTClassMap *map = options.RegistrationData->map;
int idx = find_user_type_index (map, 0, options.RegistrationData->map_count - 1, cls);
if (idx >= 0)
return (map [idx].flags & MTTypeFlagsUserType) == MTTypeFlagsUserType;
// If using the partial static registrar, we need to continue
// If full static registrar, we can return false
if ((options.flags & InitializationFlagsIsPartialStaticRegistrar) != InitializationFlagsIsPartialStaticRegistrar)
return false;
}

// COOP: no managed memory access: any mode
return class_getInstanceMethod (object_getClass (self), @selector (xamarinSetGCHandle:)) != NULL;
return class_getInstanceMethod (cls, @selector (xamarinSetGCHandle:)) != NULL;
}

#if defined(DEBUG_REF_COUNTING)
Expand Down
10 changes: 8 additions & 2 deletions runtime/xamarin/runtime.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,16 @@ typedef struct __attribute__((packed)) {
} MTTokenReference;
static const uint32_t INVALID_TOKEN_REF = 0xFFFFFFFF;

enum MTTypeFlags {
MTTypeFlagsNone = 0,
MTTypeFlagsCustomType = 1, // not a platform type
MTTypeFlagsUserType = 2, // not a wrapped type
};

typedef struct __attribute__((packed)) {
void *handle;
uint32_t /* MTTokenReference */ type_reference;
uint32_t /* MTTypeFlags */ flags;
} MTClassMap;

typedef struct __attribute__((packed)) {
Expand Down Expand Up @@ -109,7 +116,6 @@ struct MTRegistrationMap {
const MTProtocolMap protocols;
int assembly_count;
int map_count;
int custom_type_count;
int full_token_reference_count;
int skipped_map_count;
int protocol_wrapper_count;
Expand Down Expand Up @@ -198,7 +204,7 @@ void xamarin_unhandled_exception_handler (MonoObject *exc, gpointer user_data)
void xamarin_ftnptr_exception_handler (guint32 gchandle);
void xamarin_create_classes ();
const char * xamarin_skip_encoding_flags (const char *encoding);
void xamarin_add_registration_map (struct MTRegistrationMap *map);
void xamarin_add_registration_map (struct MTRegistrationMap *map, bool partial);
uint32_t xamarin_find_protocol_wrapper_type (uint32_t token_ref);
void xamarin_release_block_on_main_thread (void *obj);

Expand Down
11 changes: 4 additions & 7 deletions src/ObjCRuntime/Class.cs
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ unsafe static IntPtr FindClass (Type type, out bool is_custom_type)
continue;

var rv = map->map [i].handle;
is_custom_type = i >= (map->map_count - map->custom_type_count);
is_custom_type = (map->map [i].flags & Runtime.MTTypeFlags.CustomType) == Runtime.MTTypeFlags.CustomType;
#if LOG_TYPELOAD
Console.WriteLine ($"FindClass ({type.FullName}, {is_custom_type}): 0x{rv.ToString ("x")} = {class_getName (rv)}.");
#endif
Expand Down Expand Up @@ -331,19 +331,16 @@ internal unsafe static Type FindType (IntPtr @class, out bool is_custom_type)
}

// Find the ObjC class pointer in our map
var mapIndex = FindMapIndex (map->map, 0, map->map_count - map->custom_type_count - 1, @class);
if (mapIndex == -1) {
mapIndex = FindMapIndex (map->map, map->map_count - map->custom_type_count, map->map_count - 1, @class);
is_custom_type = true;
}

var mapIndex = FindMapIndex (map->map, 0, map->map_count - 1, @class);
if (mapIndex == -1) {
#if LOG_TYPELOAD
Console.WriteLine ($"FindType (0x{@class:X} = {Marshal.PtrToStringAuto (class_getName (@class))}) => found no type.");
#endif
return null;
}

is_custom_type = (map->map [mapIndex].flags & Runtime.MTTypeFlags.CustomType) == Runtime.MTTypeFlags.CustomType;

Type type = class_to_type [mapIndex];
if (type != null)
return type;
Expand Down
12 changes: 10 additions & 2 deletions src/ObjCRuntime/Runtime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,17 +65,25 @@ internal unsafe struct MTRegistrationMap {
public MTProtocolMap protocol_map;
public int assembly_count;
public int map_count;
public int custom_type_count;
public int full_token_reference_count;
public int skipped_map_count;
public int protocol_wrapper_count;
public int protocol_count;
}

[Flags]
internal enum MTTypeFlags : uint
{
None = 0,
CustomType = 1,
UserType = 2,
}

[StructLayout (LayoutKind.Sequential, Pack = 1)]
internal struct MTClassMap {
public IntPtr handle;
public uint type_reference;
public MTTypeFlags flags;
}

[StructLayout (LayoutKind.Sequential, Pack = 1)]
Expand Down Expand Up @@ -124,7 +132,7 @@ internal struct Trampolines {

[Flags]
internal enum InitializationFlags : int {
/* unused = 0x01 */
IsPartialStaticRegistrar= 0x01,
/* unused = 0x02,*/
DynamicRegistrar = 0x04,
/* unused = 0x08,*/
Expand Down
43 changes: 18 additions & 25 deletions tools/common/StaticRegistrar.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2725,48 +2725,34 @@ void Specialize (AutoIndentStringBuilder sb)
allTypes.Add (@class);
}

// Move all the custom types to the end of the list, respecting
// existing order (so that a derived type always comes after
// its base type; the Types.Values has that property, and we
// need to keep it that way).

var mappedEnd = allTypes.Count;
var counter = 0;
while (counter < mappedEnd) {
if (!IsPlatformType (allTypes [counter].Type)) {
var t = allTypes [counter];
allTypes.RemoveAt (counter);
allTypes.Add (t);
mappedEnd--;
} else {
counter++;
}
}

if (string.IsNullOrEmpty (single_assembly)) {
foreach (var assembly in GetAssemblies ())
registered_assemblies.Add (GetAssemblyName (assembly));
} else {
registered_assemblies.Add (single_assembly);
}

var customTypeCount = 0;
foreach (var @class in allTypes) {
var isPlatformType = IsPlatformType (@class.Type);
var flags = MTTypeFlags.None;

skip.Clear ();

uint token_ref = uint.MaxValue;
if (!@class.IsProtocol && !@class.IsCategory) {
if (!isPlatformType)
customTypeCount++;

flags |= MTTypeFlags.CustomType;

if (!@class.IsWrapper && !@class.IsModel)
flags |= MTTypeFlags.UserType;

CheckNamespace (@class, exceptions);
token_ref = CreateTokenReference (@class.Type, TokenType.TypeDef);
map.AppendLine ("{{ NULL, 0x{1:X} /* #{3} '{0}' => '{2}' */ }},",
map.AppendLine ("{{ NULL, 0x{1:X} /* #{3} '{0}' => '{2}' */, (MTTypeFlags) ({4}) /* {5} */ }},",
@class.ExportedName,
CreateTokenReference (@class.Type, TokenType.TypeDef),
GetAssemblyQualifiedName (@class.Type), map_entries);
GetAssemblyQualifiedName (@class.Type), map_entries,
(int) flags, flags);
map_dict [@class] = map_entries++;

bool use_dynamic;
Expand Down Expand Up @@ -3110,15 +3096,14 @@ void Specialize (AutoIndentStringBuilder sb)
}
map.AppendLine ("{0},", count);
map.AppendLine ("{0},", i);
map.AppendLine ("{0},", customTypeCount);
map.AppendLine ("{0},", full_token_reference_count);
map.AppendLine ("{0},", skipped_types.Count);
map.AppendLine ("{0},", protocol_wrapper_map.Count);
map.AppendLine ("{0}", needs_protocol_map ? protocols.Count : 0);
map.AppendLine ("};");


map_init.AppendLine ("xamarin_add_registration_map (&__xamarin_registration_map);");
map_init.AppendLine ("xamarin_add_registration_map (&__xamarin_registration_map, {0});", string.IsNullOrEmpty (single_assembly) ? "false" : "true");
map_init.AppendLine ("}");

sb.WriteLine (map.ToString ());
Expand Down Expand Up @@ -5005,4 +4990,12 @@ class AdoptsAttribute : Attribute
{
public string ProtocolType { get; set; }
}

[Flags]
internal enum MTTypeFlags : uint
{
None = 0,
CustomType = 1,
UserType = 2,
}
}