Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Finished rewriting the loader. It's now cleanly separated into logica…
…lly-separate components, so there's a chance it might actually be maintainable...
- Loading branch information
theraven
committed
Jun 2, 2010
1 parent
7c72069
commit bb8cafa
Showing
19 changed files
with
787 additions
and
468 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
/** | ||
* buffer.h defines a simple dynamic array that is used to store temporary | ||
* values for later processing. Define BUFFER_TYPE before including this file. | ||
*/ | ||
|
||
#include <stdlib.h> | ||
|
||
#define BUFFER_SIZE 128 | ||
static BUFFER_TYPE *buffered_object_buffer[BUFFER_SIZE]; | ||
static BUFFER_TYPE **buffered_object_overflow; | ||
static int buffered_objects; | ||
static int buffered_object_overflow_space; | ||
|
||
static void set_buffered_object_at_index(BUFFER_TYPE *cat, unsigned int i) | ||
{ | ||
if (i < BUFFER_SIZE) | ||
{ | ||
buffered_object_buffer[i] = cat; | ||
} | ||
else | ||
{ | ||
i -= BUFFER_SIZE; | ||
if (NULL == buffered_object_overflow) | ||
{ | ||
buffered_object_overflow = | ||
calloc(BUFFER_SIZE, sizeof(BUFFER_TYPE*)); | ||
buffered_object_overflow_space = BUFFER_SIZE; | ||
} | ||
while (i > buffered_object_overflow_space) | ||
{ | ||
buffered_object_overflow_space <<= 1; | ||
buffered_object_overflow = realloc(buffered_object_overflow, | ||
buffered_object_overflow_space * sizeof(BUFFER_TYPE*)); | ||
} | ||
buffered_object_overflow[i] = cat; | ||
} | ||
} | ||
|
||
static BUFFER_TYPE *buffered_object_at_index(unsigned int i) | ||
{ | ||
if (i<BUFFER_SIZE) | ||
{ | ||
return buffered_object_buffer[i]; | ||
} | ||
return buffered_object_overflow[i-BUFFER_SIZE]; | ||
} | ||
|
||
static void compact_buffer(void) | ||
{ | ||
// Move up all of the non-NULL pointers | ||
unsigned size = buffered_objects; | ||
unsigned insert = 0; | ||
for (unsigned i=0 ; i<size ; i++) | ||
{ | ||
BUFFER_TYPE *c = buffered_object_at_index(i); | ||
if (c != NULL) | ||
{ | ||
set_buffered_object_at_index(c, insert++); | ||
} | ||
} | ||
buffered_objects = insert; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
|
||
/** | ||
* The structure used to represent a category. | ||
* | ||
* This provides a set of new definitions that are used to replace those | ||
* contained within a class. | ||
* | ||
* Note: Objective-C 2 allows properties to be added to classes. The current | ||
* ABI does not provide a field for adding properties in categories. This is | ||
* likely to be added with ABI version 10. Until then, the methods created by | ||
* a declared property will work, but introspection on the property will not. | ||
*/ | ||
struct objc_category | ||
{ | ||
/** | ||
* The name of this category. | ||
*/ | ||
const char *name; | ||
/** | ||
* The name of the class to which this category should be applied. | ||
*/ | ||
const char *class_name; | ||
/** | ||
* The list of instance methods to add to the class. | ||
*/ | ||
struct objc_method_list *instance_methods; | ||
/** | ||
* The list of class methods to add to the class. | ||
*/ | ||
struct objc_method_list *class_methods; | ||
/** | ||
* The list of protocols adopted by this category. | ||
*/ | ||
struct objc_protocol_list *protocols; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
#include <stdio.h> | ||
#include "objc/runtime.h" | ||
#include "loader.h" | ||
|
||
#define BUFFER_TYPE struct objc_category | ||
#include "buffer.h" | ||
|
||
static void register_methods(struct objc_class *cls, struct objc_method_list *l) | ||
{ | ||
if (NULL == l) { return; } | ||
|
||
// Replace the method names with selectors. | ||
objc_register_selectors_from_list(l); | ||
// Add the method list at the head of the list of lists. | ||
l->next = cls->methods; | ||
cls->methods = l; | ||
// Update the dtable to catch the new methods. | ||
// FIXME: We can make this more efficient by simply passing the new method | ||
// list to the dtable and telling it only to update those methods. | ||
objc_update_dtable_for_class(cls); | ||
} | ||
|
||
static void load_category(struct objc_category *cat, struct objc_class *class) | ||
{ | ||
register_methods(class, cat->instance_methods); | ||
register_methods(class->isa, cat->class_methods); | ||
|
||
if (cat->protocols) | ||
{ | ||
objc_init_protocols(cat->protocols); | ||
cat->protocols->next = class->protocols; | ||
class->protocols = cat->protocols; | ||
} | ||
} | ||
|
||
static BOOL try_load_category(struct objc_category *cat) | ||
{ | ||
Class class = (Class)objc_getClass(cat->class_name); | ||
if (Nil != class) | ||
{ | ||
load_category(cat, class); | ||
return YES; | ||
} | ||
return NO; | ||
} | ||
|
||
/** | ||
* Attaches a category to its class, if the class is already loaded. Buffers | ||
* it for future resolution if not. | ||
*/ | ||
void objc_try_load_category(struct objc_category *cat) | ||
{ | ||
if (!try_load_category(cat)) | ||
{ | ||
set_buffered_object_at_index(cat, buffered_objects++); | ||
} | ||
} | ||
|
||
void objc_load_buffered_categories(void) | ||
{ | ||
BOOL shouldReshuffle = NO; | ||
|
||
for (unsigned i=0 ; i<buffered_objects ; i++) | ||
{ | ||
struct objc_category *c = buffered_object_at_index(i); | ||
if (NULL != c) | ||
{ | ||
if (try_load_category(c)) | ||
{ | ||
set_buffered_object_at_index(NULL, i); | ||
shouldReshuffle = YES; | ||
} | ||
} | ||
} | ||
|
||
if (shouldReshuffle) | ||
{ | ||
compact_buffer(); | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.