Some source tidies.

main
theraven 16 years ago
parent 9986294a51
commit 943ed5e714

@ -1,10 +1,19 @@
#include "lock.h"
#include "class.h"
#include "sarray2.h"
#ifdef __LIBOBJC_LOW_MEMORY__
struct objc_dtable* dtable_t;
Slot_t objc_dtable_lookup(dtable_t dtable, uint32_t uid);
#else
typedef SparseArray* dtable_t;
# define objc_dtable_lookup SparseArrayLookup
#endif
/**
* Pointer to the sparse array representing the pretend (uninstalled) dtable.
*/
extern SparseArray *__objc_uninstalled_dtable;
extern dtable_t __objc_uninstalled_dtable;
/**
* Structure for maintaining a linked list of temporary dtables. When sending
* an +initialize message to a class, we create a temporary dtables and store
@ -16,21 +25,21 @@ typedef struct _InitializingDtable
/** The class that owns the dtable. */
Class class;
/** The dtable for this class. */
void *dtable;
dtable_t dtable;
/** The next uninstalled dtable in the list. */
struct _InitializingDtable *next;
} InitializingDtable;
/** Head of the list of temporary dtables. Protected by initialize_lock. */
extern InitializingDtable *temporary_dtables;
mutex_t initialize_lock;
extern mutex_t initialize_lock;
/**
* Returns whether a class has an installed dtable.
*/
static inline int classHasInstalledDtable(struct objc_class *cls)
{
return ((void*)cls->dtable != __objc_uninstalled_dtable);
return (cls->dtable != __objc_uninstalled_dtable);
}
/**
@ -38,22 +47,22 @@ static inline int classHasInstalledDtable(struct objc_class *cls)
* method then this will block if called from a thread other than the one
* running the +initialize method.
*/
static inline SparseArray *dtable_for_class(Class cls)
static inline dtable_t dtable_for_class(Class cls)
{
if (classHasInstalledDtable(cls))
{
return (SparseArray*)cls->dtable;
return cls->dtable;
}
LOCK_UNTIL_RETURN(&initialize_lock);
if (classHasInstalledDtable(cls))
{
return (SparseArray*)cls->dtable;
return cls->dtable;
}
/* This is a linear search, and so, in theory, could be very slow. It is
* O(n) where n is the number of +initialize methods on the stack. In
* practice, this is a very small number. Profiling with GNUstep showed that
* this peaks at 8. */
SparseArray *dtable = __objc_uninstalled_dtable;
dtable_t dtable = __objc_uninstalled_dtable;
InitializingDtable *buffer = temporary_dtables;
while (NULL != buffer)
{
@ -85,3 +94,4 @@ static inline int classHasDtable(struct objc_class *cls)
* modifying a class's method list.
*/
void objc_update_dtable_for_class(Class);

@ -7,15 +7,17 @@
#include "objc/hooks.h"
#include "class.h"
#define fprintf(...)
/**
* Class of exceptions to distinguish between this and other exception types.
*/
#define objc_exception_class (*(int64_t*)"GNUCC++\0")
#define objc_exception_class (*(int64_t*)"GNUCOBJC")
/**
* Class used for C++ exceptions. Used to box them.
* Type info used for catch handlers that catch id.
*/
#define cxx_exception_class (*(int64_t*)"GNUCC++\0")
const char *__objc_id_typeinfo = "id";
/**
* Structure used as a header on thrown exceptions.
@ -36,6 +38,14 @@ struct objc_exception
id object;
};
typedef enum
{
handler_none,
handler_cleanup,
handler_catchall,
handler_class
} handler_type;
static void cleanup(_Unwind_Reason_Code reason, struct _Unwind_Exception *e)
{
free((struct objc_exception*) ((char*)e - offsetof(struct objc_exception,
@ -79,10 +89,14 @@ Class get_type_table_entry(struct _Unwind_Context *context,
if (0 == class_name) { return Nil; }
fprintf(stderr, "Class name: %d\n", class_name);
if (__objc_id_typeinfo == class_name) { return (Class)1; }
return (Class)objc_getClass(class_name);
}
static BOOL isKindOfClass(Class thrown, Class type, BOOL foreignException)
static BOOL isKindOfClass(Class thrown, Class type)
{
do
{
@ -97,43 +111,64 @@ static BOOL isKindOfClass(Class thrown, Class type, BOOL foreignException)
}
static BOOL check_action_record(struct _Unwind_Context *context,
BOOL foreignException,
struct dwarf_eh_lsda *lsda,
dw_eh_ptr_t action_record,
Class thrown_class,
unsigned long *selector)
static handler_type check_action_record(struct _Unwind_Context *context,
BOOL foreignException,
struct dwarf_eh_lsda *lsda,
dw_eh_ptr_t action_record,
Class thrown_class,
unsigned long *selector)
{
//if (!action_record) { return handler_cleanup; }
while (action_record)
{
int filter = read_sleb128(&action_record);
dw_eh_ptr_t action_record_offset_base = action_record;
int displacement = read_sleb128(&action_record);
*selector = filter;
fprintf(stderr, "Filter: %d\n", filter);
if (filter > 0)
{
Class type = get_type_table_entry(context, lsda, filter);
// If the handler is a cleanup, we don't want to do mark it as a
// handler, but we might unwind through it.
fprintf(stderr, "%p type: %d\n", type, !foreignException);
// Catchall
if (Nil == type)
{
return YES;
return handler_catchall;
}
// We treat id catches as catchalls when an object is thrown and as
// nothing when a foreign exception is thrown
else if ((Class)1 == type)
{
if (!foreignException)
{
return handler_catchall;
}
}
if (isKindOfClass(thrown_class, type, foreignException))
else if (!foreignException && isKindOfClass(thrown_class, type))
{
return YES;
fprintf(stderr, "found handler for %s\n", type->name);
return handler_class;
}
}
else if (filter == 0)
{
// Catchall
return YES;
fprintf(stderr, "0 filter\n");
// Cleanup? I think the GNU ABI doesn't actually use this, but it
// would be a good way of indicating a non-id catchall...
return handler_cleanup;
}
else
{
fprintf(stderr, "Filter value: %d\n"
"Your compiler and I disagree on the correct layout of EH data.\n",
filter);
abort();
}
*selector = 0;
action_record = displacement ?
action_record_offset_base + displacement : 0;
}
return NO;
return handler_none;
}
/**
@ -154,6 +189,8 @@ _Unwind_Reason_Code __gnu_objc_personality_v0(int version,
}
struct objc_exception *ex = 0;
//char *cls = (char*)&exceptionClass;
fprintf(stderr, "Class: %c%c%c%c%c%c%c%c\n", cls[0], cls[1], cls[2], cls[3], cls[4], cls[5], cls[6], cls[7]);
// Check if this is a foreign exception. If it is a C++ exception, then we
// have to box it. If it's something else, like a LanguageKit exception
@ -174,6 +211,7 @@ _Unwind_Reason_Code __gnu_objc_personality_v0(int version,
else if (_objc_class_for_boxing_foreign_exception)
{
thrown_class = _objc_class_for_boxing_foreign_exception(exceptionClass);
fprintf(stderr, "Foreign class: %p\n", thrown_class);
}
unsigned char *lsda_addr = (void*)_Unwind_GetLanguageSpecificData(context);
@ -188,11 +226,12 @@ _Unwind_Reason_Code __gnu_objc_personality_v0(int version,
{
struct dwarf_eh_lsda lsda = parse_lsda(context, lsda_addr);
action = dwarf_eh_find_callsite(context, &lsda);
BOOL found_handler = check_action_record(context, foreignException,
handler_type handler = check_action_record(context, foreignException,
&lsda, action.action_record, thrown_class, &selector);
// If there's no action record, we've only found a cleanup, so keep
// searching for something real
if (found_handler)
if (handler == handler_class ||
((handler == handler_catchall)))// && !foreignException))
{
// Cache the results for the phase 2 unwind, if we found a handler
// and this is not a foreign exception.
@ -201,10 +240,12 @@ _Unwind_Reason_Code __gnu_objc_personality_v0(int version,
ex->handlerSwitchValue = selector;
ex->landingPad = action.landing_pad;
}
fprintf(stderr, "Found handler! %d\n", handler);
return _URC_HANDLER_FOUND;
}
return _URC_CONTINUE_UNWIND;
}
fprintf(stderr, "Phase 2: Fight!\n");
// TODO: If this is a C++ exception, we can cache the lookup and cheat a
// bit
@ -214,14 +255,30 @@ _Unwind_Reason_Code __gnu_objc_personality_v0(int version,
struct dwarf_eh_lsda lsda = parse_lsda(context, lsda_addr);
action = dwarf_eh_find_callsite(context, &lsda);
// If there's no cleanup here, continue unwinding.
if (0 == action.landing_pad) { return _URC_CONTINUE_UNWIND; }
if (0 == action.landing_pad)
{
return _URC_CONTINUE_UNWIND;
}
handler_type handler = check_action_record(context, foreignException,
&lsda, action.action_record, thrown_class, &selector);
fprintf(stderr, "handler! %d %d\n",handler, selector);
// If this is not a cleanup, ignore it and keep unwinding.
//if (check_action_record(context, foreignException, &lsda,
//action.action_record, thrown_class, &selector) != handler_cleanup)
if (handler != handler_cleanup)
{
fprintf(stderr, "Ignoring handler! %d\n",handler);
return _URC_CONTINUE_UNWIND;
}
fprintf(stderr, "Installing cleanup...\n");
// If there is a cleanup, we need to return the exception structure
// (not the object) to the calling frame. The exception object
object = exceptionObject;
selector = 0;
//selector = 0;
}
else if (foreignException)
{
fprintf(stderr, "Doing the foreign exception thing...\n");
struct dwarf_eh_lsda lsda = parse_lsda(context, lsda_addr);
action = dwarf_eh_find_callsite(context, &lsda);
check_action_record(context, foreignException, &lsda,

@ -35,28 +35,28 @@ Slot_t objc_msg_lookup_internal(id *receiver,
SEL selector,
id sender)
{
Slot_t result = SparseArrayLookup((*receiver)->isa->dtable,
Slot_t result = objc_dtable_lookup((*receiver)->isa->dtable,
PTR_TO_IDX(selector->name));
if (0 == result)
{
Class class = (*receiver)->isa;
void *dtable = dtable_for_class(class);
dtable_t dtable = dtable_for_class(class);
/* Install the dtable if it hasn't already been initialized. */
if (dtable == __objc_uninstalled_dtable)
{
objc_send_initialize(*receiver);
dtable = dtable_for_class(class);
result = SparseArrayLookup(dtable, PTR_TO_IDX(selector->name));
result = objc_dtable_lookup(dtable, PTR_TO_IDX(selector->name));
}
else
{
// Check again incase another thread updated the dtable while we
// weren't looking
result = SparseArrayLookup(dtable, PTR_TO_IDX(selector->name));
result = objc_dtable_lookup(dtable, PTR_TO_IDX(selector->name));
}
if (0 == result)
{
if ((result = SparseArrayLookup(dtable, get_untyped_idx(selector))))
if ((result = objc_dtable_lookup(dtable, get_untyped_idx(selector))))
{
fprintf(stderr, "Calling %s with incorrect signature. "
"Method has %s, selector has %s\n",
@ -128,7 +128,7 @@ Slot_t objc_slot_lookup_super(struct objc_super *super, SEL selector)
if (receiver)
{
Class class = super->class;
Slot_t result = SparseArrayLookup(dtable_for_class(class),
Slot_t result = objc_dtable_lookup(dtable_for_class(class),
PTR_TO_IDX(selector->name));
if (0 == result)
{
@ -231,7 +231,7 @@ void objc_msg_profile(id receiver, IMP method,
*/
Slot_t objc_get_slot(Class cls, SEL selector)
{
Slot_t result = SparseArrayLookup(cls->dtable, PTR_TO_IDX(selector->name));
Slot_t result = objc_dtable_lookup(cls->dtable, PTR_TO_IDX(selector->name));
if (0 == result)
{
void *dtable = dtable_for_class(cls);
@ -240,17 +240,17 @@ Slot_t objc_get_slot(Class cls, SEL selector)
{
//objc_send_initialize((id)cls);
dtable = dtable_for_class(cls);
result = SparseArrayLookup(dtable, PTR_TO_IDX(selector->name));
result = objc_dtable_lookup(dtable, PTR_TO_IDX(selector->name));
}
else
{
// Check again incase another thread updated the dtable while we
// weren't looking
result = SparseArrayLookup(dtable, PTR_TO_IDX(selector->name));
result = objc_dtable_lookup(dtable, PTR_TO_IDX(selector->name));
}
if (NULL == result)
{
if ((result = SparseArrayLookup(dtable, get_untyped_idx(selector))))
if ((result = objc_dtable_lookup(dtable, get_untyped_idx(selector))))
{
fprintf(stderr, "Calling %s with incorrect signature. "
"Method has %s, selector has %s\n",

Loading…
Cancel
Save