Commit c07499dc by Nicola Pero Committed by Nicola Pero

In libobjc/: 2010-12-21 Nicola Pero <nicola.pero@meta-innovation.com>

In libobjc/:
2010-12-21  Nicola Pero  <nicola.pero@meta-innovation.com>

	PR libobjc/16110
	* init.c (__objc_send_message_in_list): Renamed to
	__objc_send_load_using_method_list.  Do not take an 'op' argument.
	Register the 'load' selector if needed.
	(__objc_send_load): Do not register the 'load' selector.  Updated
	call to __objc_send_message_in_list.
	(__objc_create_classes_tree): Add the class of any claimed
	category that was loaded in the module to the list of classes for
	which we try to execute +load.
	
In gcc/testsuite/:
2010-12-21  Nicola Pero  <nicola.pero@meta-innovation.com>

	PR libobjc/16110
	* objc.dg/special/special.exp: Added new test.
	* objc.dg/special/load-category-1.m: New.
	* objc.dg/special/load-category-1a.m: New.
	* objc.dg/special/load-category-1.h: New.

From-SVN: r168122
parent c8613835
2010-12-21 Nicola Pero <nicola.pero@meta-innovation.com>
PR libobjc/16110
* objc.dg/special/special.exp: Added new test.
* objc.dg/special/load-category-1.m: New.
* objc.dg/special/load-category-1a.m: New.
* objc.dg/special/load-category-1.h: New.
2010-12-21 Steven Bosscher <steven@gcc.gnu.org>
PR middle-end/45310
......
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, December 2010. */
/* Test that +load works when a category is defined in a different
module than the main class. */
/* This function should be called any time +load is invoked, so we can
keep the count. */
extern int increase_load_count (void);
@interface TestClass1
{
id isa;
}
@end
@interface TestClass2
{
id isa;
}
@end
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, December 2010. */
/* { dg-do run } */
/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
#include <stdlib.h>
#include <objc/objc.h>
#include <objc/runtime.h>
#include "load-category-1.h"
@implementation TestClass1
+ + initialize { return self; }
+ load
{
increase_load_count ();
}
@end
@implementation TestClass2 (Category)
+ + load
{
increase_load_count ();
}
@end
static int load_count = 0;
int increase_load_count (void)
{
load_count++;
}
int main (void)
{
if (load_count != 4)
abort ();
return 0;
}
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, December 2010. */
#include <stdlib.h>
#include <objc/objc.h>
#include <objc/runtime.h>
#include "load-category-1.h"
@implementation TestClass2
+ + initialize { return self; }
+ load
{
increase_load_count ();
}
@end
@implementation TestClass1 (Category)
+ + load
{
increase_load_count ();
}
@end
# GCC Objective-C testsuite that uses the `dg.exp' driver.
# Copyright (C) 1997, 2001, 2007 Free Software Foundation, Inc.
# Copyright (C) 1997, 2001, 2007, 2010 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
......@@ -56,6 +56,33 @@ if ![string match "" $lines] then {
}
}
#
# load-category-1 test
#
# This test is similar to the one above. We compile load-category-1.m
# and load-category-1a.m, link them together, and execute the result.
set add_flags "additional_flags=-I${srcdir}/../../libobjc"
lappend add_flags "additional_flags=-fgnu-runtime"
set lines [objc_target_compile "$srcdir/$subdir/load-category-1a.m" "load-category-1a.o" object $add_flags ]
if ![string match "" $lines] then {
fail "load-category-1a.o"
} else {
dg-runtest "$srcdir/$subdir/load-category-1.m" "load-category-1a.o" "-I${srcdir}/../../libobjc -fgnu-runtime"
file delete load-category-1a.o
}
if [istarget "*-*-darwin*" ] {
set add_flags ""
lappend add_flags "additional_flags=-fnext-runtime"
set lines [objc_target_compile "$srcdir/$subdir/load-category-1a.m" "load-category-1a.o" object $add_flags ]
if ![string match "" $lines] then {
fail "load-category-1a.o"
} else {
dg-runtest "$srcdir/$subdir/load-category-1.m" "load-category-1a.o" "-fnext-runtime"
file delete load-category-1a.o
}
}
# All done.
dg-finish
2010-12-21 Nicola Pero <nicola.pero@meta-innovation.com>
PR libobjc/16110
* init.c (__objc_send_message_in_list): Renamed to
__objc_send_load_using_method_list. Do not take an 'op' argument.
Register the 'load' selector if needed.
(__objc_send_load): Do not register the 'load' selector. Updated
call to __objc_send_message_in_list.
(__objc_create_classes_tree): Add the class of any claimed
category that was loaded in the module to the list of classes for
which we try to execute +load.
2010-12-21 Nicola Pero <nicola.pero@meta-innovation.com>
* objc-private/common.h: When DEBUG is defined, include <stdio.h>.
Updated comments.
* init.c (__objc_tree_insert_class): Use %p, not %x, when printing
......
......@@ -44,8 +44,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#define OBJC_VERSION 8
#define PROTOCOL_VERSION 2
/* This list contains all modules currently loaded into the
runtime. */
/* This list contains modules currently loaded into the runtime and
for which the +load method has not been called yet. */
static struct objc_list *__objc_module_list = 0; /* !T:MUTEX */
/* This list contains all proto_list's not yet assigned class
......@@ -359,37 +359,49 @@ __objc_tree_print (objc_class_tree *tree, int level)
#endif
/* Walks on a linked list of methods in the reverse order and executes
all the methods corresponding to `op' selector. Walking in the
reverse order assures the +load of class is executed first and then
+load of categories because of the way in which categories are
added to the class methods. */
all the methods corresponding to the `+load' selector. Walking in
the reverse order assures the +load of class is executed first and
then +load of categories because of the way in which categories are
added to the class methods. This function needs to be called with
the objc_runtime_mutex locked. */
static void
__objc_send_message_in_list (struct objc_method_list *method_list, Class class, SEL op)
__objc_send_load_using_method_list (struct objc_method_list *method_list, Class class)
{
static SEL load_selector = 0;
int i;
if (! method_list)
if (!method_list)
return;
/* First execute the `op' message in the following method lists. */
__objc_send_message_in_list (method_list->method_next, class, op);
/* This needs no lock protection because we are called with the
objc_runtime_mutex locked. */
if (!load_selector)
load_selector = sel_registerName ("load");
/* method_list is a linked list of method lists; since we're
executing in reverse order, we need to do the next list before we
do this one. */
__objc_send_load_using_method_list (method_list->method_next, class);
/* Search the method list. */
for (i = 0; i < method_list->method_count; i++)
{
struct objc_method *mth = &method_list->method_list[i];
if (mth->method_name && sel_eq (mth->method_name, op)
/* We are searching for +load methods that we haven't executed
yet. */
if (mth->method_name && sel_eq (mth->method_name, load_selector)
&& ! objc_hash_is_key_in_hash (__objc_load_methods, mth->method_imp))
{
/* Add this method into the +load hash table. */
/* Add this method into the +load hash table, so we won't
execute it again next time. */
objc_hash_add (&__objc_load_methods,
mth->method_imp,
mth->method_imp);
DEBUG_PRINTF ("sending +load in class: %s\n", class->name);
/* The method was found and wasn't previously executed. */
/* Call +load. */
(*mth->method_imp) ((id)class, mth->method_name);
break;
......@@ -397,18 +409,16 @@ __objc_send_message_in_list (struct objc_method_list *method_list, Class class,
}
}
/* This function needs to be called with the objc_runtime_mutex
locked. */
static void
__objc_send_load (objc_class_tree *tree,
int level __attribute__ ((__unused__)))
{
static SEL load_sel = 0;
Class class = tree->class;
struct objc_method_list *method_list = class->class_pointer->methods;
if (! load_sel)
load_sel = sel_registerName ("load");
__objc_send_message_in_list (method_list, class, load_sel);
__objc_send_load_using_method_list (method_list, class);
}
static void
......@@ -580,8 +590,8 @@ __objc_exec_class (struct objc_module *module)
previous_constructors = 1;
}
/* Save the module pointer for later processing. (not currently
used). */
/* Save the module pointer so that later we remember to call +load
on all classes and categories on it. */
objc_mutex_lock (__objc_runtime_mutex);
__objc_module_list = list_cons (module, __objc_module_list);
......@@ -717,14 +727,16 @@ __objc_exec_class (struct objc_module *module)
objc_mutex_unlock (__objc_runtime_mutex);
}
/* This function needs to be called with the objc_runtime_mutex
locked. */
static void
objc_send_load (void)
{
if (! __objc_module_list)
if (!__objc_module_list)
return;
/* Try to find out if all the classes loaded so far also have their
superclasses known to the runtime. We suppose that the objects
superclasses known to the runtime. We suppose that the objects
that are allocated in the +load method are in general of a class
declared in the same module. */
if (unresolved_classes)
......@@ -742,7 +754,7 @@ objc_send_load (void)
/* If we still have classes for whom we don't have yet their
super classes known to the runtime we don't send the +load
messages. */
messages yet. */
if (unresolved_classes)
return;
}
......@@ -791,6 +803,25 @@ __objc_create_classes_tree (struct objc_module *module)
objc_tree_insert_class (class);
}
/* Now iterate over "claimed" categories too (ie, categories that
extend a class that has already been loaded by the runtime), and
insert them in the classes tree hiearchy too. Otherwise, if you
add a category, its +load method would not be called if the class
is already loaded in the runtime. It the category is
"unclaimed", ie, we haven't loaded the main class yet, postpone
sending +load as we want to execute +load from the class before
we execute the one from the category. */
for (i = 0; i < symtab->cat_def_cnt; ++i)
{
struct objc_category *category = symtab->defs[i + symtab->cls_def_cnt];
Class class = objc_getClass (category->class_name);
/* If the class for the category exists then append its
methods. */
if (class)
objc_tree_insert_class (class);
}
}
static void
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment