diff --git a/sendmsg2.c b/sendmsg2.c index 8240542..4b7fd19 100644 --- a/sendmsg2.c +++ b/sendmsg2.c @@ -2,6 +2,7 @@ #include #include +#define PROFILE __thread id objc_msg_sender; static struct objc_slot nil_slot = { Nil, Nil, "", 1, (IMP)nil_method }; @@ -80,6 +81,7 @@ Slot_t (*objc_plane_lookup)(id *receiver, SEL op, id sender) = */ Slot_t objc_msg_lookup_sender(id *receiver, SEL selector, id sender) { + //fprintf(stderr, "Looking up slot %s\n", sel_get_name(selector)); // Returning a nil slot allows the caller to cache the lookup for nil too, // although this is not particularly useful because the nil method can be // inlined trivially. @@ -110,12 +112,6 @@ Slot_t objc_msg_lookup_sender(id *receiver, SEL selector, id sender) } #ifdef PROFILE -/** - * When profiling, the runtime writes out two files, one containing tuples of - * call sites and associated information, the other containing symbolic - * information for resolving these. The loggedValues sparse array is used to prevent duplication of - */ -static struct sarray *loggedValues; /** * Mutex used to protect non-thread-safe parts of the profiling subsystem. */ @@ -129,35 +125,46 @@ FILE *profileSymbols; */ FILE *profileData; -static char *objc_profile_resolve_symbol_null(void *addr) { return NULL; } -/** - * Hook allowing JIT'd functions to be resolved. Takes an address as an - * argument and returns the symbol name. - */ -char *(*objc_profile_resolve_symbol)(void *addr) = - objc_profile_resolve_symbol_null; - - -// Don't enable profiling in the default build (yet) struct profile_info { const char *module; int32_t callsite; IMP method; - Class cls; }; static void __objc_profile_init(void) { INIT_LOCK(profileLock); - loggedValues = sarray_new(128, 0); profileSymbols = fopen("objc_profile.symbols", "a"); profileData = fopen("objc_profile.data", "a"); // Write markers indicating a new run. fprintf(profileSymbols, "=== NEW TRACE ===\n"); - struct profile_info profile_data = { 0, 0, 0, 0}; + struct profile_info profile_data = { 0, 0, 0 }; fwrite(&profile_data, sizeof(profile_data), 1, profileData); } + +void objc_profile_write_symbols(char **symbols) +{ + if (NULL == profileData) + { + LOCK(__objc_runtime_mutex); + if (NULL == profileData) + { + __objc_profile_init(); + } + UNLOCK(__objc_runtime_mutex); + } + LOCK(&profileLock); + while(*symbols) + { + char *address = *(symbols++); + char *symbol = *(symbols++); + fprintf(profileSymbols, "%zx %s\n", (size_t)address, symbol); + } + UNLOCK(&profileLock); + fflush(profileSymbols); +} + /** * Profiling version of the slot lookup. This takes a unique ID for the module * and the callsite as extra arguments. The type of the receiver and the @@ -170,60 +177,19 @@ Slot_t objc_msg_lookup_profile(id *receiver, SEL selector, id sender, { // Initialize the logging lazily. This prevents us from wasting any memory // when we are not profiling. - if (NULL == loggedValues) + if (NULL == profileData) { LOCK(__objc_runtime_mutex); - if (NULL == loggedValues) + if (NULL == profileData) { __objc_profile_init(); } UNLOCK(__objc_runtime_mutex); } // Look up the class if the receiver is not nil - Class cls = Nil; - if (nil != *receiver) - { - cls = (*receiver)->class_pointer; - if (!sarray_get_safe(loggedValues, (size_t)cls)) - { - LOCK(&profileLock); - if (!sarray_get_safe(loggedValues, (size_t)cls)) - { - fprintf(profileSymbols, "%zx %s\n", (size_t)cls, cls->name); - } - UNLOCK(&profileLock); - } - } Slot_t slot = objc_msg_lookup_sender(receiver, selector, sender); - IMP method = (IMP)0; - if (0 != slot->version) - { - method = slot->method; - if (!sarray_get_safe(loggedValues, (size_t)method)) - { - Dl_info info; - const char *symbolName; - if (dladdr((void*)method, &info)) - { - symbolName = info.dli_sname; - } - else - { - symbolName = objc_profile_resolve_symbol((void*)method); - } - if (NULL != symbolName) - { - LOCK(&profileLock); - if (!sarray_get_safe(loggedValues, (size_t)method)) - { - fprintf(profileSymbols, "%zx %s\n", (size_t)method, symbolName); - } - UNLOCK(&profileLock); - sarray_at_put_safe(loggedValues, (size_t)method, (void*)1); - } - } - } - struct profile_info profile_data = { module, callsite, method, cls }; + IMP method = slot->method; + struct profile_info profile_data = { module, callsite, method }; fwrite(&profile_data, sizeof(profile_data), 1, profileData); return slot; }