mirror of
https://github.com/darlinghq/darling-libobjc2.git
synced 2024-12-18 01:26:53 +00:00
Initial work on protocol uniquing. Protocols are now added to a table and can be looked up at run time.
This commit is contained in:
parent
bdf97cf64e
commit
e1ae8df5af
6
init.c
6
init.c
@ -938,6 +938,7 @@ init_check_module_version (Module_t module)
|
||||
}
|
||||
}
|
||||
|
||||
struct objc_protocol *__objc_unique_protocol(struct objc_protocol*);
|
||||
static void
|
||||
__objc_init_protocols (struct objc_protocol_list *protos)
|
||||
{
|
||||
@ -955,7 +956,8 @@ __objc_init_protocols (struct objc_protocol_list *protos)
|
||||
if (! proto_class2)
|
||||
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);
|
||||
UNLOCK(__objc_runtime_mutex);
|
||||
@ -988,7 +990,7 @@ __objc_init_protocols (struct objc_protocol_list *protos)
|
||||
aProto->class_pointer = proto_class2;
|
||||
/* init super protocols */
|
||||
__objc_init_protocols (aProto->protocol_list);
|
||||
//__objc_unique_protocol (aProto);
|
||||
protos->list[i] = __objc_unique_protocol (aProto);
|
||||
}
|
||||
default:
|
||||
{
|
||||
|
94
protocol.c
94
protocol.c
@ -1,9 +1,52 @@
|
||||
#include <objc/hash.h>
|
||||
#include <objc/objc-api.h>
|
||||
#include "objc/objc.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)
|
||||
{
|
||||
return string_compare(name, protocol->protocol_name);
|
||||
}
|
||||
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 protocol_table known_protocol_table;
|
||||
|
||||
static mutex_t protocol_table_lock;
|
||||
|
||||
void __objc_init_protocol_table(void)
|
||||
{
|
||||
LOCK(__objc_runtime_mutex);
|
||||
INIT_LOCK(protocol_table_lock);
|
||||
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];
|
||||
@ -11,15 +54,7 @@ struct objc_method_description_list
|
||||
|
||||
static Class ObjC2ProtocolClass = 0;
|
||||
|
||||
void __objc_init_protocol_table(void)
|
||||
{
|
||||
Protocols = objc_hash_new(128,
|
||||
(hash_func_type)objc_hash_string,
|
||||
(compare_func_type)objc_compare_strings);
|
||||
}
|
||||
|
||||
|
||||
static int isEmptyProtocol(struct objc_protocol *aProto)
|
||||
static int isEmptyProtocol(struct objc_protocol2 *aProto)
|
||||
{
|
||||
int isEmpty = (aProto->instance_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
|
||||
static void makeProtocolEqualToProtocol(struct objc_protocol *p1,
|
||||
struct objc_protocol *p2) {}
|
||||
static void makeProtocolEqualToProtocol(struct objc_protocol2 *p1,
|
||||
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)
|
||||
{
|
||||
ObjC2ProtocolClass = objc_get_class("Protocol2");
|
||||
}
|
||||
struct objc_protocol *oldProtocol =
|
||||
objc_hash_value_for_key(Protocols, aProto->protocol_name);
|
||||
struct objc_protocol2 *oldProtocol =
|
||||
protocol_for_name(aProto->protocol_name);
|
||||
if (NULL == oldProtocol)
|
||||
{
|
||||
// This is the first time we've seen this protocol, so add it to the
|
||||
// hash table and ignore it.
|
||||
objc_hash_add(&Protocols, aProto, aProto->protocol_name);
|
||||
return;
|
||||
protocol_table_insert(aProto);
|
||||
return aProto;
|
||||
}
|
||||
if (isEmptyProtocol(oldProtocol))
|
||||
{
|
||||
if (isEmptyProtocol(aProto))
|
||||
{
|
||||
return aProto;
|
||||
// Add protocol to a list somehow.
|
||||
}
|
||||
else
|
||||
{
|
||||
// This protocol is not empty, so we use its definitions
|
||||
makeProtocolEqualToProtocol(oldProtocol, aProto);
|
||||
return aProto;
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -71,9 +123,11 @@ void __objc_unique_protocol(struct objc_protocol *aProto)
|
||||
if (isEmptyProtocol(aProto))
|
||||
{
|
||||
makeProtocolEqualToProtocol(aProto, oldProtocol);
|
||||
return oldProtocol;
|
||||
}
|
||||
else
|
||||
{
|
||||
return oldProtocol;
|
||||
//FIXME: We should really perform a check here to make sure the
|
||||
//protocols are actually the same.
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user