From patchwork Tue Oct 12 18:44:03 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nicola Pero X-Patchwork-Id: 67605 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 46940B6EED for ; Wed, 13 Oct 2010 05:44:26 +1100 (EST) Received: (qmail 25754 invoked by alias); 12 Oct 2010 18:44:23 -0000 Received: (qmail 25737 invoked by uid 22791); 12 Oct 2010 18:44:20 -0000 X-SWARE-Spam-Status: No, hits=-1.1 required=5.0 tests=AWL, BAYES_00, 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; Tue, 12 Oct 2010 18:44:12 +0000 Received: from eggs.gnu.org ([140.186.70.92]:49731) by fencepost.gnu.org with esmtps (TLS-1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.69) (envelope-from ) id 1P5jpa-0004KT-DH for gcc-patches@gnu.org; Tue, 12 Oct 2010 14:44:10 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1P5jpU-0001Fh-6w for gcc-patches@gnu.org; Tue, 12 Oct 2010 14:44:10 -0400 Received: from smtp201.iad.emailsrvr.com ([207.97.245.201]:57936) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1P5jpU-0001FV-3d for gcc-patches@gnu.org; Tue, 12 Oct 2010 14:44:04 -0400 Received: from localhost (localhost.localdomain [127.0.0.1]) by smtp40.relay.iad1a.emailsrvr.com (SMTP Server) with ESMTP id AB583350D9E for ; Tue, 12 Oct 2010 14:44:03 -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 smtp40.relay.iad1a.emailsrvr.com (SMTP Server) with ESMTP id 989A2350D94 for ; Tue, 12 Oct 2010 14:44:03 -0400 (EDT) Received: from meta-innovation.com (localhost [127.0.0.1]) by dynamic1.wm-web.iad.mlsrvr.com (Postfix) with ESMTP id 87768C98070 for ; Tue, 12 Oct 2010 14:44:03 -0400 (EDT) Received: by www2.webmail.us (Authenticated sender: nicola.pero@meta-innovation.com, from: nicola.pero@meta-innovation.com) with HTTP; Tue, 12 Oct 2010 20:44:03 +0200 (CEST) Date: Tue, 12 Oct 2010 20:44:03 +0200 (CEST) Subject: =?UTF-8?Q?libobjc=20-=20more=20modern=20Objective-C=20runtime=20API=20(4?= =?UTF-8?Q?)?= From: "Nicola Pero" To: "gcc-patches@gnu.org" MIME-Version: 1.0 X-Type: plain Message-ID: <1286909043.552515932@192.168.2.230> 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 This adds yet another chunk of new API functions. With these, I was able to move another couple of libobjc source files to the new API/headers. :-) No regressions, committed to trunk. Thanks 2010-10-12 Nicola Pero * class.c: Include objc/runtime.h and objc-private/module-abi-8.h instead of objc/objc-api.h. (objc_get_unknown_class_handler): Do not define. (class_isMetaClass): New. (class_getSuperclass): New. (class_getVersion): New. (class_setVersion): New. (class_getInstanceSize): New. * exceptions.c: Include objc/runtime.h instead of objc/objc-api.h. (is_kind_of_exception_matcher): Use objc_getSuperclass instead of objc_get_super_class. (get_ttype_entry): Use objc_getRequiredClass instead of objc_get_class. * ivars.c (class_getClassVariable): New. * objects.c: Include objc/runtime.h, objc/thr.h and objc-private/module-abi-8.h instead of objc/objc-api.h * objc/runtime.h (class_getClassVariable): New. (class_isMetaClass): New. (class_getSuperclass): New. (class_getVersion): New. (class_setVersion): New. (class_getInstanceSize): New. * objc-private/module-abi-8.h (HOST_BITS_PER_LONG): New (from objc/objc-api.h) (__CLS_INFO): Same. (__CLS_ISINFO): Same. (__CLS_SETINFO): Same. (CLS_ISMETA): Same. (CLS_ISCLASS): Same. (CLS_ISRESOLV): Same. (CLS_SETRESOLV): Same. (CLS_ISINITIALIZED): Same. (CLS_SETINITIALIZED): Same. (CLS_GETNUMBER): Same. (CLS_SETNUMBER): Same. Index: objc-private/module-abi-8.h =================================================================== --- objc-private/module-abi-8.h (revision 165349) +++ objc-private/module-abi-8.h (working copy) @@ -183,7 +183,7 @@ struct objc_class { const char* name; /* Name of the class. */ long version; /* Unknown. */ unsigned long info; /* Bit mask. See class masks - defined above. */ + defined below. */ long instance_size; /* Size in bytes of the class. The sum of the class definition and all super @@ -218,6 +218,45 @@ struct objc_class { }; #endif /* __objc_STRUCT_OBJC_CLASS_defined */ +/* This is used to assure consistent access to the info field of + classes. */ +#ifndef HOST_BITS_PER_LONG +# define HOST_BITS_PER_LONG (sizeof(long)*8) +#endif + +#define __CLS_INFO(cls) ((cls)->info) +#define __CLS_ISINFO(cls, mask) ((__CLS_INFO(cls)&mask)==mask) +#define __CLS_SETINFO(cls, mask) (__CLS_INFO(cls) |= mask) + +/* The structure is of type MetaClass */ +#define _CLS_META 0x2L +#define CLS_ISMETA(cls) ((cls)&&__CLS_ISINFO(cls, _CLS_META)) + +/* The structure is of type Class */ +#define _CLS_CLASS 0x1L +#define CLS_ISCLASS(cls) ((cls)&&__CLS_ISINFO(cls, _CLS_CLASS)) + +/* The class is initialized within the runtime. This means that it + has had correct super and sublinks assigned. */ +#define _CLS_RESOLV 0x8L +#define CLS_ISRESOLV(cls) __CLS_ISINFO(cls, _CLS_RESOLV) +#define CLS_SETRESOLV(cls) __CLS_SETINFO(cls, _CLS_RESOLV) + +/* The class has been send a +initialize message or a such is not + defined for this class. */ +#define _CLS_INITIALIZED 0x04L +#define CLS_ISINITIALIZED(cls) __CLS_ISINFO(cls, _CLS_INITIALIZED) +#define CLS_SETINITIALIZED(cls) __CLS_SETINFO(cls, _CLS_INITIALIZED) + +/* The class number of this class. This must be the same for both the + class and its meta class object. */ +#define CLS_GETNUMBER(cls) (__CLS_INFO(cls) >> (HOST_BITS_PER_LONG/2)) +#define CLS_SETNUMBER(cls, num) \ + ({ (cls)->info <<= (HOST_BITS_PER_LONG/2); \ + (cls)->info >>= (HOST_BITS_PER_LONG/2); \ + __CLS_SETINFO(cls, (((unsigned long)num) << (HOST_BITS_PER_LONG/2))); }) + + /* The compiler generates one of these structures for each category. A class may have many categories and contain both instance and factory methods. */ Index: class.c =================================================================== --- class.c (revision 165386) +++ class.c (working copy) @@ -89,10 +89,11 @@ see the files COPYING3 and COPYING.RUNTIME respect #include "objc-private/common.h" #include "objc-private/error.h" -#include "objc/objc-api.h" +#include "objc/runtime.h" #include "objc/thr.h" -#include "objc-private/runtime.h" /* the kitchen sink */ -#include /* For memset */ +#include "objc-private/module-abi-8.h" /* For CLS_ISCLASS and similar. */ +#include "objc-private/runtime.h" /* the kitchen sink */ +#include /* For memset */ /* We use a table which maps a class name to the corresponding class * pointer. The first part of this file defines this table, and @@ -417,11 +418,6 @@ class_table_print_histogram (void) */ 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. */ @@ -591,6 +587,7 @@ objc_lookup_class (const char *name) 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(). */ +/* Note that this is roughly equivalent to objc_getRequiredClass(). */ /* 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. */ @@ -739,6 +736,49 @@ class_getName (Class class_) return class_->name; } +BOOL +class_isMetaClass (Class class_) +{ + /* CLS_ISMETA includes the check for Nil class_. */ + return CLS_ISMETA (class_); +} + +Class +class_getSuperclass (Class class_) +{ + if (class_ == Nil) + return Nil; + + return class_->super_class; +} + +int +class_getVersion (Class class_) +{ + if (class_ == Nil) + return 0; + + return (int)(class_->version); +} + +void +class_setVersion (Class class_, int version) +{ + if (class_ == Nil) + return; + + class_->version = version; +} + +size_t +class_getInstanceSize (Class class_) +{ + if (class_ == Nil) + return 0; + + return class_->instance_size; +} + #define CLASSOF(c) ((c)->class_pointer) Class Index: objects.c =================================================================== --- objects.c (revision 165386) +++ objects.c (working copy) @@ -23,10 +23,12 @@ see the files COPYING3 and COPYING.RUNTIME respect . */ #include "objc-private/common.h" -#include "objc/objc-api.h" -#include "objc-private/runtime.h" /* the kitchen sink */ +#include "objc/runtime.h" +#include "objc/thr.h" /* Required by objc-private/runtime.h. */ +#include "objc-private/module-abi-8.h" /* For CLS_ISCLASS and similar. */ +#include "objc-private/runtime.h" /* the kitchen sink */ -#include /* For memcpy() */ +#include /* For memcpy() */ #if OBJC_WITH_GC # include Index: exception.c =================================================================== --- exception.c (revision 165348) +++ exception.c (working copy) @@ -25,7 +25,7 @@ see the files COPYING3 and COPYING.RUNTIME respect #include "objc-private/common.h" #include #include "config.h" -#include "objc/objc-api.h" +#include "objc/runtime.h" #include "objc/objc-exception.h" #include "unwind.h" #include "unwind-pe.h" @@ -57,7 +57,7 @@ is_kind_of_exception_matcher (Class catch_class, i Class c; for (c = exception->class_pointer; c != Nil; - c = class_get_super_class (c)) + c = class_getSuperclass (c)) if (c == catch_class) return 1; } @@ -191,9 +191,11 @@ get_ttype_entry (struct lsda_header_info *info, _u ptr = (_Unwind_Ptr) (info->TType - (i * 4)); ptr = _Unwind_decode_target2 (ptr); - + + /* NULL ptr means catch-all. Note that if the class is not found, + this will abort the program. */ if (ptr) - return objc_get_class ((const char *) ptr); + return objc_getRequiredClass ((const char *) ptr); else return 0; } @@ -209,9 +211,10 @@ get_ttype_entry (struct lsda_header_info *info, _U read_encoded_value_with_base (info->ttype_encoding, info->ttype_base, info->TType - i, &ptr); - /* NULL ptr means catch-all. */ + /* NULL ptr means catch-all. Note that if the class is not found, + this will abort the program. */ if (ptr) - return objc_get_class ((const char *) ptr); + return objc_getRequiredClass ((const char *) ptr); else return 0; } Index: ChangeLog =================================================================== --- ChangeLog (revision 165386) +++ ChangeLog (working copy) @@ -1,5 +1,43 @@ 2010-10-12 Nicola Pero + * class.c: Include objc/runtime.h and objc-private/module-abi-8.h + instead of objc/objc-api.h. + (objc_get_unknown_class_handler): Do not define. + (class_isMetaClass): New. + (class_getSuperclass): New. + (class_getVersion): New. + (class_setVersion): New. + (class_getInstanceSize): New. + * exceptions.c: Include objc/runtime.h instead of objc/objc-api.h. + (is_kind_of_exception_matcher): Use objc_getSuperclass instead of + objc_get_super_class. + (get_ttype_entry): Use objc_getRequiredClass instead of + objc_get_class. + * ivars.c (class_getClassVariable): New. + * objects.c: Include objc/runtime.h, objc/thr.h and + objc-private/module-abi-8.h instead of objc/objc-api.h + * objc/runtime.h (class_getClassVariable): New. + (class_isMetaClass): New. + (class_getSuperclass): New. + (class_getVersion): New. + (class_setVersion): New. + (class_getInstanceSize): New. + * objc-private/module-abi-8.h (HOST_BITS_PER_LONG): New (from + objc/objc-api.h) + (__CLS_INFO): Same. + (__CLS_ISINFO): Same. + (__CLS_SETINFO): Same. + (CLS_ISMETA): Same. + (CLS_ISCLASS): Same. + (CLS_ISRESOLV): Same. + (CLS_SETRESOLV): Same. + (CLS_ISINITIALIZED): Same. + (CLS_SETINITIALIZED): Same. + (CLS_GETNUMBER): Same. + (CLS_SETNUMBER): Same. + +2010-10-12 Nicola Pero + * archive.c: Do not include objc/objc.h. * class.c: Do not include objc/objc.h. * encoding.c: Include objc/runtime.h, ctype.h and Index: ivars.c =================================================================== --- ivars.c (revision 165386) +++ ivars.c (working copy) @@ -60,6 +60,25 @@ class_getInstanceVariable (Class class_, const cha return NULL; } +struct objc_ivar * +class_getClassVariable (Class class_, const char *name) +{ + if (class_ == Nil) + return NULL; + + /* Logically, since a class is an instance of its meta-class, and + since its class methods are the instance methods of the + meta-class, class variables should be instance variables of the + meta-class. That is different from the normal use of having + 'static' variables in the class implementation file, because + every class would have its own variables. + + Anyway, it is all speculative at this stage, but if we get class + variables in Objective-C, it is conceivable that this + implementation should work. */ + return class_getInstanceVariable (class_->class_pointer, name); +} + void * object_getIndexedIvars (id object) { Index: objc/runtime.h =================================================================== --- objc/runtime.h (revision 165386) +++ objc/runtime.h (working copy) @@ -239,6 +239,14 @@ objc_EXPORT Class object_setClass (id object, Clas reuse the returned Ivar if you can. */ objc_EXPORT Ivar class_getInstanceVariable (Class class_, const char *name); +/* Return a class variable given the class and the class variable + name. This is an expensive function to call, so try to reuse the + returned Ivar if you can. + + This function always returns NULL since class variables are + currently unavailable in Objective-C. */ +objc_EXPORT Ivar class_getClassVariable (Class class_, const char *name); + /* If the object was created in class_createInstance() with some extraBytes, returns a pointer to them. If it was not, then the returned pointer may make no sense. */ @@ -361,7 +369,49 @@ objc_EXPORT int objc_getClassList (Class *returnVa class_ is Nil. */ objc_EXPORT const char * class_getName (Class class_); +/* Return YES if 'class_' is a meta class, and NO if not. If 'class_' + is Nil, return NO. */ +objc_EXPORT BOOL class_isMetaClass (Class class_); +/* Return the superclass of 'class_'. If 'class_' is Nil, or it is a root + class, return Nil. + + TODO: It may be worth to define this inline, since it is usually + used in loops when traversing the class hierarchy. */ +objc_EXPORT Class class_getSuperclass (Class class_); + +/* Return the 'version' number of the class, which is an integer that + can be used to track changes in the class API, methods and + variables. If class_ is Nil, return 0. If class_ is not Nil, the + version is 0 unless class_setVersion() has been called to set a + different one. + + Please note that internally the version is a long, but the API only + allows you to set and retrieve int values. */ +objc_EXPORT int class_getVersion (Class class_); + +/* Set the 'version' number of the class, which is an integer that can + be used to track changes in the class API, methods and variables. + If 'class_' is Nil, does nothing. + + This is typically used internally by "Foundation" libraries such as + GNUstep Base to support serialization / deserialization of objects + that work across changes in the classes. If you are using such a + library, you probably want to use their versioning API, which may + be based on this one, but is integrated with the rest of the + library. + + Please note that internally the version is a long, but the API only + allows you to set and retrieve int values. */ +objc_EXPORT void class_setVersion (Class class_, int version); + +/* Return the size in bytes (a byte is the size of a char) of an + instance of the class. If class_ is Nil, return 0; else it return + a non-zero number (since the 'isa' instance variable is required + for all classes). */ +objc_EXPORT size_t class_getInstanceSize (Class class_); + + /** Implementation: the following functions are in protocols.c. */ /* Return the protocol with name 'name', or nil if it the protocol is