From patchwork Mon Oct 11 18:17:36 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nicola Pero X-Patchwork-Id: 67462 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id 94633B6F11 for ; Tue, 12 Oct 2010 05:17:58 +1100 (EST) Received: (qmail 32541 invoked by alias); 11 Oct 2010 18:17:56 -0000 Received: (qmail 32526 invoked by uid 22791); 11 Oct 2010 18:17:53 -0000 X-SWARE-Spam-Status: No, hits=0.2 required=5.0 tests=AWL, BAYES_50, SARE_SUB_ENC_UTF8, TW_BJ, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from fencepost.gnu.org (HELO fencepost.gnu.org) (140.186.70.10) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 11 Oct 2010 18:17:45 +0000 Received: from eggs.gnu.org ([140.186.70.92]:54785) by fencepost.gnu.org with esmtps (TLS-1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.69) (envelope-from ) id 1P5MwR-0007D6-BL for gcc-patches@gnu.org; Mon, 11 Oct 2010 14:17:43 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1P5MwL-0001Oi-EE for gcc-patches@gnu.org; Mon, 11 Oct 2010 14:17:43 -0400 Received: from smtp181.iad.emailsrvr.com ([207.97.245.181]:60798) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1P5MwL-0001OY-9o for gcc-patches@gnu.org; Mon, 11 Oct 2010 14:17:37 -0400 Received: from localhost (localhost.localdomain [127.0.0.1]) by smtp38.relay.iad1a.emailsrvr.com (SMTP Server) with ESMTP id A3EBD3482BB for ; Mon, 11 Oct 2010 14:17:36 -0400 (EDT) X-Orig-To: gcc-patches@gnu.org Received: from dynamic1.wm-web.iad.mlsrvr.com (dynamic1.wm-web.iad1a.rsapps.net [192.168.2.150]) by smtp38.relay.iad1a.emailsrvr.com (SMTP Server) with ESMTP id 897F43482B9 for ; Mon, 11 Oct 2010 14:17:36 -0400 (EDT) Received: from meta-innovation.com (localhost [127.0.0.1]) by dynamic1.wm-web.iad.mlsrvr.com (Postfix) with ESMTP id 78C3CC98070 for ; Mon, 11 Oct 2010 14:17:36 -0400 (EDT) Received: by www2.webmail.us (Authenticated sender: nicola.pero@meta-innovation.com, from: nicola.pero@meta-innovation.com) with HTTP; Mon, 11 Oct 2010 20:17:36 +0200 (CEST) Date: Mon, 11 Oct 2010 20:17:36 +0200 (CEST) Subject: =?UTF-8?Q?libobjc=20-=20more=20modern=20Objective-C=20runtime=20API=20(1?= =?UTF-8?Q?)?= From: "Nicola Pero" To: "gcc-patches@gnu.org" MIME-Version: 1.0 X-Type: plain Message-ID: <1286821056.491413870@192.168.2.229> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 3) X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Another patch that adds more meat to objc/runtime.h. Committed to trunk. Thanks PS: We do need testcases for the GNU Objective-C runtime APIs. The existing Objective-C tests currently work nicely as tests for the Traditional GNU Objective-C Runtime API, ie, that I'm not breaking stuff that used to work :-), but they don't test the new API, ie, that the new stuff that I'm adding actually works ;-). Once I get the bulk done, I'll start writing some tests. 2010-10-11 Nicola Pero * class.c (objc_getClassList): New. (objc_getRequiredClass): New. (objc_getMetaClass): New. (objc_lookupClass): New. (objc_getClass): New. (__objc_get_unknown_class_handler): New. (objc_setGetUnknownClassHandler): New. (objc_get_class): Use __objc_get_unknown_class_handler. (objc_lookup_class): Call objc_getClass. * objc/objc-api.h: Updated comment and copyright notice. * objc/runtime.h: Updated comments. (objc_getClass): New. (objc_lookupClass): New. (objc_getMetaClass): New. (objc_getRequiredClass): New. (objc_getClassList): New. (objc_setGetUnknownClassHandler): New. (objc_get_unknown_class_handler): New. * objc-private/runtime.h: Use __objc_private_runtime_INCLUDE_GNU instead of __objc_runtime_INCLUDE_GNU as include guard. * objc-private/error.h (_objc_abort): Mark as noreturn. Index: objc-private/error.h =================================================================== --- objc-private/error.h (revision 165248) +++ objc-private/error.h (working copy) @@ -29,9 +29,10 @@ see the files COPYING3 and COPYING.RUNTIME respect This should only be used for errors that really are unrecorevable: failure to allocate memory, and failure to load an Objective-C module. All other usages of this function should be converted into - some milder type of error. + some milder type of error (unless aborting is explicitly required + by the documentation/API). */ void -_objc_abort (const char *fmt, ...); +_objc_abort (const char *fmt, ...) __attribute__ ((noreturn)); #endif /* __objc_private_error_INCLUDE_GNU */ Index: objc-private/runtime.h =================================================================== --- objc-private/runtime.h (revision 165248) +++ objc-private/runtime.h (working copy) @@ -36,8 +36,8 @@ but can almost certainly be shrinked down. */ -#ifndef __objc_runtime_INCLUDE_GNU -#define __objc_runtime_INCLUDE_GNU +#ifndef __objc_private_runtime_INCLUDE_GNU +#define __objc_private_runtime_INCLUDE_GNU #include /* for varargs and va_list's */ @@ -98,4 +98,4 @@ extern void __objc_generate_gc_type_description (C } #endif /* __cplusplus */ -#endif /* not __objc_runtime_INCLUDE_GNU */ +#endif /* not __objc_private_runtime_INCLUDE_GNU */ Index: class.c =================================================================== --- class.c (revision 165248) +++ class.c (working copy) @@ -408,10 +408,37 @@ class_table_print_histogram (void) /* This is a hook which is called by objc_get_class and objc_lookup_class if the runtime is not able to find the class. - This may e.g. try to load in the class using dynamic loading. */ + This may e.g. try to load in the class using dynamic loading. + + This hook was a public, global variable in the Traditional GNU + Objective-C Runtime API (objc/objc-api.h). The modern GNU + Objective-C Runtime API (objc/runtime.h) provides the + objc_setGetUnknownClassHandler() function instead. +*/ Class (*_objc_lookup_class) (const char *name) = 0; /* !T:SAFE */ +/* Temporarily while we still include objc/objc-api.h instead of objc/runtime.h. */ +#ifndef __objc_runtime_INCLUDE_GNU +typedef Class (*objc_get_unknown_class_handler)(const char *class_name); +#endif +/* The handler currently in use. PS: if both + __obj_get_unknown_class_handler and _objc_lookup_class are defined, + __objc_get_unknown_class_handler is called first. */ +static objc_get_unknown_class_handler +__objc_get_unknown_class_handler = NULL; + +objc_get_unknown_class_handler +objc_setGetUnknownClassHandler (objc_get_unknown_class_handler + new_handler) +{ + objc_get_unknown_class_handler old_handler + = __objc_get_unknown_class_handler; + __objc_get_unknown_class_handler = new_handler; + return old_handler; +} + + /* True when class links has been resolved. */ BOOL __objc_class_links_resolved = NO; /* !T:UNUSED */ @@ -464,27 +491,108 @@ __objc_add_class_to_hash (Class class) objc_mutex_unlock (__objc_runtime_mutex); } -/* Get the class object for the class named NAME. If NAME does not - identify a known class, the hook _objc_lookup_class is called. If - this fails, nil is returned. */ Class -objc_lookup_class (const char *name) +objc_getClass (const char *name) { Class class; + if (name == NULL) + return Nil; + class = class_table_get_safe (name); - + if (class) return class; + + if (__objc_get_unknown_class_handler) + return (*__objc_get_unknown_class_handler) (name); if (_objc_lookup_class) return (*_objc_lookup_class) (name); + + return Nil; +} + +Class +objc_lookupClass (const char *name) +{ + if (name == NULL) + return Nil; else - return 0; + return class_table_get_safe (name); } +Class +objc_getMetaClass (const char *name) +{ + Class class = objc_getClass (name); + + if (class) + return class->class_pointer; + else + return Nil; +} + +Class +objc_getRequiredClass (const char *name) +{ + Class class = objc_getClass (name); + + if (class) + return class; + else + _objc_abort ("objc_getRequiredClass ('%s') failed: class not found\n", name); +} + +int +objc_getClassList (Class *returnValue, int maxNumberOfClassesToReturn) +{ + /* Iterate over all entries in the table. */ + int hash, count = 0; + + objc_mutex_lock (__class_table_lock); + + for (hash = 0; hash < CLASS_TABLE_SIZE; hash++) + { + class_node_ptr node = class_table_array[hash]; + + while (node != NULL) + { + if (returnValue) + { + if (count < maxNumberOfClassesToReturn) + returnValue[count] = node->pointer; + else + { + objc_mutex_unlock (__class_table_lock); + return count; + } + } + count++; + node = node->next; + } + } + + objc_mutex_unlock (__class_table_lock); + return count; +} + +/* Traditional GNU Objective-C Runtime API. */ /* Get the class object for the class named NAME. If NAME does not identify a known class, the hook _objc_lookup_class is called. If + this fails, nil is returned. */ +Class +objc_lookup_class (const char *name) +{ + return objc_getClass (name); +} + +/* Traditional GNU Objective-C Runtime API. Important: this method is + called automatically by the compiler while messaging (if using the + traditional ABI), so it is worth keeping it fast; don't make it + just a wrapper around objc_getClass(). */ +/* Get the class object for the class named NAME. If NAME does not + identify a known class, the hook _objc_lookup_class is called. If this fails, an error message is issued and the system aborts. */ Class objc_get_class (const char *name) @@ -496,13 +604,15 @@ objc_get_class (const char *name) if (class) return class; - if (_objc_lookup_class) + if (__objc_get_unknown_class_handler) + class = (*__objc_get_unknown_class_handler) (name); + + if ((!class) && _objc_lookup_class) class = (*_objc_lookup_class) (name); if (class) return class; - /* FIXME: Should we abort the program here ? */ _objc_abort ("objc runtime: cannot find class %s\n", name); return 0; Index: ChangeLog =================================================================== --- ChangeLog (revision 165269) +++ ChangeLog (working copy) @@ -1,5 +1,29 @@ 2010-10-11 Nicola Pero + * class.c (objc_getClassList): New. + (objc_getRequiredClass): New. + (objc_getMetaClass): New. + (objc_lookupClass): New. + (objc_getClass): New. + (__objc_get_unknown_class_handler): New. + (objc_setGetUnknownClassHandler): New. + (objc_get_class): Use __objc_get_unknown_class_handler. + (objc_lookup_class): Call objc_getClass. + * objc/objc-api.h: Updated comment and copyright notice. + * objc/runtime.h: Updated comments. + (objc_getClass): New. + (objc_lookupClass): New. + (objc_getMetaClass): New. + (objc_getRequiredClass): New. + (objc_getClassList): New. + (objc_setGetUnknownClassHandler): New. + (objc_get_unknown_class_handler): New. + * objc-private/runtime.h: Use __objc_private_runtime_INCLUDE_GNU + instead of __objc_runtime_INCLUDE_GNU as include guard. + * objc-private/error.h (_objc_abort): Mark as noreturn. + +2010-10-11 Nicola Pero + * Makefile.in (C_SOURCE_FILES): Added ivars.c. * ivars.c: New. * objc/objc.h: Updated comments. Index: objc/runtime.h =================================================================== --- objc/runtime.h (revision 165269) +++ objc/runtime.h (working copy) @@ -1,4 +1,4 @@ -/* GNU Objective-C Runtime API. +/* GNU Objective-C Runtime API - Modern API Copyright (C) 2010 Free Software Foundation, Inc. Contributed by Nicola Pero @@ -146,14 +146,16 @@ struct objc_method_description #define _F_GCINVISIBLE 0x20 -/** Internals: defined inline. */ +/** Implementation: the following functions are defined inline. */ /* Return the class of 'object', or Nil if the object is nil. If 'object' is a class, the meta class is returned; if 'object' is a meta class, the root meta class is returned (note that this is different from the traditional GNU Objective-C Runtime API function object_get_class(), which for a meta class would return the meta - class itself). */ + class itself). This function is inline, so it is really fast and + should be used instead of accessing object->class_pointer + directly. */ static inline Class object_getClass (id object) { @@ -164,7 +166,7 @@ object_getClass (id object) } -/** Internals: the following functions are in selector.c. */ +/** Implementation: the following functions are in selector.c. */ /* Return the name of a given selector. */ objc_EXPORT const char *sel_getName (SEL selector); @@ -198,7 +200,7 @@ objc_EXPORT SEL set_registerTypedName (const char objc_EXPORT BOOL sel_isEqual (SEL first_selector, SEL second_selector); -/** Internals: the following functions are in objects.c. */ +/** Implementation: the following functions are in objects.c. */ /* Create an instance of class 'class_', adding extraBytes to the size of the returned object. This method allocates the appropriate @@ -228,7 +230,7 @@ objc_EXPORT const char * object_getClassName (id o objc_EXPORT Class object_setClass (id object, Class class_); -/** Internals: the following functions are in ivars.c. */ +/** Implementation: the following functions are in ivars.c. */ /* Return an instance variable given the class and the instance variable name. This is an expensive function to call, so try to @@ -283,10 +285,81 @@ objc_EXPORT ptrdiff_t ivar_getOffset (Ivar variabl objc_EXPORT const char * ivar_getTypeEncoding (Ivar variable); +/** Implementation: the following functions are in class.c. */ + +/* Compatibility Note: The Apple/NeXT runtime does not have + objc_get_unknown_class_handler and + objc_setGetUnknownClassHandler(). They provide functionality that + the traditional GNU Objective-C Runtime API used to provide via the + _objc_lookup_class hook. */ + +/* An 'objc_get_unknown_class_handler' function is used by + objc_getClass() to get a class that is currently unknown to the + compiler. You could use it for example to have the class loaded by + dynamically loading a library. 'class_name' is the name of the + class. The function should return the Class object if it manages to + load the class, and Nil if not. */ +typedef Class (*objc_get_unknown_class_handler)(const char *class_name); + +/* Sets a new handler function for getting unknown classes (to be used + by objc_getClass () and related), and returns the previous one. + This function is not safe to call in a multi-threaded environment + because other threads may be trying to use the get unknown class + handler while you change it! */ +objc_get_unknown_class_handler +objc_setGetUnknownClassHandler (objc_get_unknown_class_handler new_handler); + + +/* Return the class with name 'name', if it is already registered with + the runtime. If it is not registered, and + objc_setGetUnknownClassHandler() has been called to set a handler + for unknown classes, the handler is called to give it a chance to + load the class in some other way. If the class is not known to the + runtime and the handler is not set or returns Nil, objc_getClass() + returns Nil. */ +objc_EXPORT Class objc_getClass (const char *name); + +/* Return the class with name 'name', if it is already registered with + the runtime. Return Nil if not. This function does not call the + objc_get_unknown_class_handler function if the class is not + found. */ +objc_EXPORT Class objc_lookupClass (const char *name); + +/* Return the meta class associated to the class with name 'name', if + it is already registered with the runtime. First, it finds the + class using objc_getClass(). Then, it returns the associated meta + class. If the class could not be found using objc_getClass(), + returns Nil. */ +objc_EXPORT Class objc_getMetaClass (const char *name); + +/* This is identical to objc_getClass(), but if the class is not found, + it aborts the process instead of returning Nil. */ +objc_EXPORT Class objc_getRequiredClass (const char *name); + +/* If 'returnValue' is NULL, 'objc_getClassList' returns the number of + classes currently registered with the runtime. If 'returnValue' is + not NULL, it should be a (Class *) pointer to an area of memory + which can contain up to 'maxNumberOfClassesToReturn' Class records. + 'objc_getClassList' will fill the area pointed to by 'returnValue' + with all the Classes registered with the runtime (or up to + maxNumberOfClassesToReturn if there are more than + maxNumberOfClassesToReturn). The function return value is the + number of classes actually returned in 'returnValue'. */ +objc_EXPORT int objc_getClassList (Class *returnValue, int maxNumberOfClassesToReturn); + +/* Compatibility Note: The Apple/NeXT runtime also has + + Class objc_getFutureClass (const char *name); + void objc_setFutureClass (Class class_, const char *name); + + the documentation is unclear on what they are supposed to do, and + the GNU Objective-C Runtime currently does not provide them. */ + + /* TODO: Add all the other functions in the API. */ -/** Internals: the following functions are in objc-foreach.c. */ +/** Implementation: the following functions are in objc-foreach.c. */ /* 'objc_enumerationMutation()' is called when a collection is mutated while being "fast enumerated". That is a hard error, and @@ -337,7 +410,7 @@ struct __objcFastEnumerationState */ -/** Internals: the following functions are implemented in encoding.c. */ +/** Implementation: the following functions are in encoding.c. */ /* Traditional GNU Objective-C Runtime functions that are currently used to implement method forwarding. Index: objc/objc-api.h =================================================================== --- objc/objc-api.h (revision 165264) +++ objc/objc-api.h (working copy) @@ -1,6 +1,6 @@ -/* GNU Objective-C Runtime API. +/* GNU Objective-C Runtime API - Traditional API Copyright (C) 1993, 1995, 1996, 1997, 2001, 2002, 2003, 2004, 2005, - 2007, 2009 Free Software Foundation, Inc. + 2007, 2009, 2010 Free Software Foundation, Inc. This file is part of GCC.