From 6459292a40b7f51cd1a246d8f2da74313e162380 Mon Sep 17 00:00:00 2001 From: theraven Date: Thu, 29 Apr 2010 17:52:10 +0000 Subject: [PATCH] Simplified profiling system and enabled it by default. This should be safe, because it no longer depends on dladdr() and friends (which don't work reliably anywhere), and instead expects the profiling modules to register their own symbol table. --- sendmsg2.c | 94 +++++++++++++++++------------------------------------- 1 file changed, 30 insertions(+), 64 deletions(-) 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; }