Initial work on protocol uniquing. Protocols are now added to a table and can be looked up at run time.

main
theraven 16 years ago
parent bdf97cf64e
commit e1ae8df5af

@ -938,6 +938,7 @@ init_check_module_version (Module_t module)
} }
} }
struct objc_protocol *__objc_unique_protocol(struct objc_protocol*);
static void static void
__objc_init_protocols (struct objc_protocol_list *protos) __objc_init_protocols (struct objc_protocol_list *protos)
{ {
@ -955,7 +956,8 @@ __objc_init_protocols (struct objc_protocol_list *protos)
if (! proto_class2) if (! proto_class2)
proto_class2 = objc_lookup_class ("Protocol2"); proto_class2 = objc_lookup_class ("Protocol2");
if (! proto_class) /* Protocol2 will always exist if Protocol exists */
if (! proto_class2)
{ {
unclaimed_proto_list = list_cons (protos, unclaimed_proto_list); unclaimed_proto_list = list_cons (protos, unclaimed_proto_list);
UNLOCK(__objc_runtime_mutex); UNLOCK(__objc_runtime_mutex);
@ -988,7 +990,7 @@ __objc_init_protocols (struct objc_protocol_list *protos)
aProto->class_pointer = proto_class2; aProto->class_pointer = proto_class2;
/* init super protocols */ /* init super protocols */
__objc_init_protocols (aProto->protocol_list); __objc_init_protocols (aProto->protocol_list);
//__objc_unique_protocol (aProto); protos->list[i] = __objc_unique_protocol (aProto);
} }
default: default:
{ {

@ -1,25 +1,60 @@
#include <objc/hash.h> #include "objc/objc.h"
#include <objc/objc-api.h> #include "objc/objc-api.h"
#include "lock.h"
#include <stdlib.h>
static cache_ptr Protocols = 0; // Get the functions for string hashing
#include "string_hash.h"
struct objc_method_description_list static int protocol_compare(const char *name,
const struct objc_protocol2 *protocol)
{ {
int count; return string_compare(name, protocol->protocol_name);
struct objc_method_description list[1]; }
}; static int protocol_hash(const struct objc_protocol2 *protocol)
{
return string_hash(protocol->protocol_name);
}
#define MAP_TABLE_NAME protocol
#define MAP_TABLE_COMPARE_FUNCTION protocol_compare
#define MAP_TABLE_HASH_KEY string_hash
#define MAP_TABLE_HASH_VALUE protocol_hash
// This defines the maximum number of classes that the runtime supports.
#define MAP_TABLE_STATIC_SIZE 2048
#include "hash_table.h"
static Class ObjC2ProtocolClass = 0; static protocol_table known_protocol_table;
static mutex_t protocol_table_lock;
void __objc_init_protocol_table(void) void __objc_init_protocol_table(void)
{ {
Protocols = objc_hash_new(128, LOCK(__objc_runtime_mutex);
(hash_func_type)objc_hash_string, INIT_LOCK(protocol_table_lock);
(compare_func_type)objc_compare_strings); UNLOCK(__objc_runtime_mutex);
} }
static void protocol_table_insert(const struct objc_protocol2 *protocol)
{
LOCK(&protocol_table_lock);
protocol_insert(&known_protocol_table, protocol->protocol_name, (void*)protocol);
UNLOCK(&protocol_table_lock);
}
struct objc_protocol2 *protocol_for_name(const char *protocol_name)
{
return protocol_table_get(&known_protocol_table, protocol_name);
}
struct objc_method_description_list
{
int count;
struct objc_method_description list[1];
};
static Class ObjC2ProtocolClass = 0;
static int isEmptyProtocol(struct objc_protocol *aProto) static int isEmptyProtocol(struct objc_protocol2 *aProto)
{ {
int isEmpty = (aProto->instance_methods->count == 0) && int isEmpty = (aProto->instance_methods->count == 0) &&
(aProto->class_methods->count == 0) && (aProto->class_methods->count == 0) &&
@ -36,34 +71,51 @@ static int isEmptyProtocol(struct objc_protocol *aProto)
} }
// FIXME: Make p1 adopt all of the stuff in p2 // FIXME: Make p1 adopt all of the stuff in p2
static void makeProtocolEqualToProtocol(struct objc_protocol *p1, static void makeProtocolEqualToProtocol(struct objc_protocol2 *p1,
struct objc_protocol *p2) {} struct objc_protocol2 *p2)
{
#define COPY(x) p1->x = p2->x
COPY(instance_methods);
COPY(class_methods);
COPY(protocol_list);
if (p1->class_pointer == ObjC2ProtocolClass &&
p2->class_pointer == ObjC2ProtocolClass)
{
COPY(optional_instance_methods);
COPY(optional_class_methods);
COPY(properties);
COPY(optional_properties);
}
#undef COPY
}
void __objc_unique_protocol(struct objc_protocol *aProto) struct objc_protocol2 *__objc_unique_protocol(struct objc_protocol2 *aProto)
{ {
if (ObjC2ProtocolClass == 0) if (ObjC2ProtocolClass == 0)
{ {
ObjC2ProtocolClass = objc_get_class("Protocol2"); ObjC2ProtocolClass = objc_get_class("Protocol2");
} }
struct objc_protocol *oldProtocol = struct objc_protocol2 *oldProtocol =
objc_hash_value_for_key(Protocols, aProto->protocol_name); protocol_for_name(aProto->protocol_name);
if (NULL == oldProtocol) if (NULL == oldProtocol)
{ {
// This is the first time we've seen this protocol, so add it to the // This is the first time we've seen this protocol, so add it to the
// hash table and ignore it. // hash table and ignore it.
objc_hash_add(&Protocols, aProto, aProto->protocol_name); protocol_table_insert(aProto);
return; return aProto;
} }
if (isEmptyProtocol(oldProtocol)) if (isEmptyProtocol(oldProtocol))
{ {
if (isEmptyProtocol(aProto)) if (isEmptyProtocol(aProto))
{ {
return aProto;
// Add protocol to a list somehow. // Add protocol to a list somehow.
} }
else else
{ {
// This protocol is not empty, so we use its definitions // This protocol is not empty, so we use its definitions
makeProtocolEqualToProtocol(oldProtocol, aProto); makeProtocolEqualToProtocol(oldProtocol, aProto);
return aProto;
} }
} }
else else
@ -71,9 +123,11 @@ void __objc_unique_protocol(struct objc_protocol *aProto)
if (isEmptyProtocol(aProto)) if (isEmptyProtocol(aProto))
{ {
makeProtocolEqualToProtocol(aProto, oldProtocol); makeProtocolEqualToProtocol(aProto, oldProtocol);
return oldProtocol;
} }
else else
{ {
return oldProtocol;
//FIXME: We should really perform a check here to make sure the //FIXME: We should really perform a check here to make sure the
//protocols are actually the same. //protocols are actually the same.
} }

Loading…
Cancel
Save