mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-23 17:10:48 +00:00
Attempt to link in ObjC2 compatibility code if we have an older runtime.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@29670 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
7cc69dfaae
commit
073595b9e9
11 changed files with 1246 additions and 863 deletions
15
ChangeLog
15
ChangeLog
|
@ -1,3 +1,18 @@
|
|||
2010-02-19 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* configure.ac: Add check for ObjC2 support in runtime.
|
||||
* config.mak.in: define OBJC2RUNTIME to yes or no
|
||||
* configure: regenerate
|
||||
* Source/GNUmakefile: Build/link ObjectiveC2 compat code if needed
|
||||
* Source/ObjectiveC2/Availability.h:
|
||||
* Source/ObjectiveC2/runtime.c:
|
||||
* Source/ObjectiveC2/GNUmakefile:
|
||||
* Source/ObjectiveC2/properties.m:
|
||||
* Source/ObjectiveC2/sync.m:
|
||||
* Source/ObjectiveC2/blocks_runtime.m:
|
||||
Attempt to build in ObjectiveC2 compatibility functions when we don't
|
||||
have an ObjC2 runtime.
|
||||
|
||||
2010-02-19 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
Simplify header imports with common headers handled in the correct
|
||||
|
|
|
@ -65,8 +65,13 @@ ifneq ($(base),no)
|
|||
LIBRARY_NAME += libgnustep-base
|
||||
endif
|
||||
|
||||
libgnustep-base_SUBPROJECTS = Additions
|
||||
libgnustep-baseadd_SUBPROJECTS = Additions
|
||||
ifeq ($(OBJC2RUNTIME),no)
|
||||
libgnustep-base_SUBPROJECTS = ObjectiveC2
|
||||
libgnustep-baseadd_SUBPROJECTS += Additions
|
||||
endif
|
||||
|
||||
libgnustep-base_SUBPROJECTS += Additions
|
||||
libgnustep-baseadd_SUBPROJECTS += Additions
|
||||
|
||||
ifeq ($(GNUSTEP_TARGET_OS), mingw32)
|
||||
libgnustep-base_SUBPROJECTS+=win32
|
||||
|
@ -473,7 +478,10 @@ libgnustep-baseadd_NEEDS_GUI = NO
|
|||
# build Additions as a subproject, causing concurrency issues). If it
|
||||
# can be guaranteed that they'll never be built together, this could
|
||||
# be removed.
|
||||
SUBPROJECTS = Additions
|
||||
ifeq ($(OBJC2RUNTIME),no)
|
||||
SUBPROJECTS = ObjectiveC2
|
||||
endif
|
||||
SUBPROJECTS += Additions
|
||||
|
||||
-include Makefile.preamble
|
||||
|
||||
|
|
12
Source/ObjectiveC2/Availability.h
Normal file
12
Source/ObjectiveC2/Availability.h
Normal file
|
@ -0,0 +1,12 @@
|
|||
|
||||
#ifdef STRICT_MACOS_X
|
||||
# define OBJC_NONPORTABLE __attribute__((error("Function not supported by the Apple runtime")))
|
||||
#else
|
||||
# define OBJC_NONPORTABLE
|
||||
#endif
|
||||
|
||||
#if !defined(__DEPRECATE_DIRECT_ACCESS) || defined(__OBJC_LEGACY_GNU_MODE__) || defined(__OBJC_RUNTIME_INTERNAL__)
|
||||
# define OBJC_DEPRECATED
|
||||
#else
|
||||
# define OBJC_DEPRECATED __attribute__((deprecated))
|
||||
#endif
|
|
@ -1,41 +1,59 @@
|
|||
#
|
||||
# src makefile for the GNUstep Base Library
|
||||
#
|
||||
# Copyright (C) 2010 Free Software Foundation, Inc.
|
||||
#
|
||||
# Written by: Richard Frith-Macdonald <rfm@gnu.org>
|
||||
#
|
||||
# This file is part of the GNUstep Base Library.
|
||||
#
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2 of the License, or (at your option) any later version.
|
||||
#
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Library General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free
|
||||
# Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
# Boston, MA 02111 USA.
|
||||
#
|
||||
|
||||
PACKAGE_NAME = gnustep-base
|
||||
GNUSTEP_LOCAL_ADDITIONAL_MAKEFILES=../../base.make
|
||||
|
||||
include $(GNUSTEP_MAKEFILES)/common.make
|
||||
include ../../config.mak
|
||||
|
||||
#
|
||||
# Application
|
||||
#
|
||||
VERSION = 0.1
|
||||
FRAMEWORK_NAME = ObjectiveC2
|
||||
|
||||
#
|
||||
# Resource files
|
||||
#
|
||||
ObjectiveC2_LANGUAGES = English
|
||||
SUBPROJECT_NAME = ObjectiveC2
|
||||
|
||||
ObjectiveC2_OBJC_FILES = \
|
||||
blocks_runtime.m\
|
||||
properties.m\
|
||||
sync.m
|
||||
|
||||
blocks_runtime.m\
|
||||
properties.m\
|
||||
sync.m
|
||||
|
||||
ObjectiveC2_C_FILES = \
|
||||
runtime.c
|
||||
runtime.c
|
||||
|
||||
ObjectiveC2_HEADER_FILES = \
|
||||
Availability.h\
|
||||
blocks_runtime.h\
|
||||
runtime.h
|
||||
|
||||
ADDITIONAL_CFLAGS = -std=c99 -fexceptions
|
||||
ADDITIONAL_OBJCFLAGS = -fobjc-exceptions -fexceptions
|
||||
Availability.h\
|
||||
blocks_runtime.h\
|
||||
runtime.h
|
||||
|
||||
ifeq ($(CC), clang)
|
||||
ADDITIONAL_OBJCFLAGS = -fblocks
|
||||
ADDITIONAL_OBJCFLAGS = -fblocks
|
||||
endif
|
||||
ifeq ($(GNUSTEP_TARGET_CPU), ix86)
|
||||
ADDITIONAL_OBJCFLAGS += -march=i686
|
||||
ADDITIONAL_OBJCFLAGS += -march=i686
|
||||
endif
|
||||
|
||||
ObjectiveC2_OBJCFLAGS += -std=c99
|
||||
-include Makefile.preamble
|
||||
|
||||
include $(GNUSTEP_MAKEFILES)/subproject.make
|
||||
|
||||
-include Makefile.postamble
|
||||
|
||||
include $(GNUSTEP_MAKEFILES)/framework.make
|
||||
-include ../../etoile.make
|
||||
|
|
|
@ -23,8 +23,8 @@
|
|||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#import "objc/blocks_runtime.h"
|
||||
#import "objc/runtime.h"
|
||||
#import "blocks_runtime.h"
|
||||
#import "runtime.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
@ -38,47 +38,47 @@
|
|||
|
||||
// Descriptor attributes
|
||||
enum {
|
||||
BLOCK_HAS_COPY_DISPOSE = (1 << 25),
|
||||
BLOCK_HAS_CTOR = (1 << 26), // helpers have C++ code
|
||||
BLOCK_IS_GLOBAL = (1 << 28),
|
||||
BLOCK_HAS_DESCRIPTOR = (1 << 29), // interim until complete world build is accomplished
|
||||
BLOCK_HAS_COPY_DISPOSE = (1 << 25),
|
||||
BLOCK_HAS_CTOR = (1 << 26), // helpers have C++ code
|
||||
BLOCK_IS_GLOBAL = (1 << 28),
|
||||
BLOCK_HAS_DESCRIPTOR = (1 << 29), // interim until complete world build is accomplished
|
||||
};
|
||||
|
||||
// _Block_object_assign() and _Block_object_dispose() flag helpers.
|
||||
enum {
|
||||
BLOCK_FIELD_IS_OBJECT = 3, // id, NSObject, __attribute__((NSObject)), block, ...
|
||||
BLOCK_FIELD_IS_BLOCK = 7, // a block variable
|
||||
BLOCK_FIELD_IS_BYREF = 8, // the on stack structure holding the __block variable
|
||||
|
||||
BLOCK_FIELD_IS_WEAK = 16, // declared __weak
|
||||
|
||||
BLOCK_BYREF_CALLER = 128, // called from byref copy/dispose helpers
|
||||
BLOCK_FIELD_IS_OBJECT = 3, // id, NSObject, __attribute__((NSObject)), block, ...
|
||||
BLOCK_FIELD_IS_BLOCK = 7, // a block variable
|
||||
BLOCK_FIELD_IS_BYREF = 8, // the on stack structure holding the __block variable
|
||||
|
||||
BLOCK_FIELD_IS_WEAK = 16, // declared __weak
|
||||
|
||||
BLOCK_BYREF_CALLER = 128, // called from byref copy/dispose helpers
|
||||
};
|
||||
|
||||
// Helper structure
|
||||
struct psy_block_literal {
|
||||
void *isa; // initialized to &_NSConcreteStackBlock or &_NSConcreteGlobalBlock
|
||||
int flags;
|
||||
int reserved;
|
||||
void (*invoke)(void *, ...);
|
||||
struct {
|
||||
unsigned long int reserved; // NULL
|
||||
unsigned long int size; // sizeof(struct Block_literal_1)
|
||||
// optional helper functions
|
||||
void (*copy_helper)(void *dst, void *src);
|
||||
void (*dispose_helper)(void *src);
|
||||
} *descriptor;
|
||||
const char *types;
|
||||
void *isa; // initialized to &_NSConcreteStackBlock or &_NSConcreteGlobalBlock
|
||||
int flags;
|
||||
int reserved;
|
||||
void (*invoke)(void *, ...);
|
||||
struct {
|
||||
unsigned long int reserved; // NULL
|
||||
unsigned long int size; // sizeof(struct Block_literal_1)
|
||||
// optional helper functions
|
||||
void (*copy_helper)(void *dst, void *src);
|
||||
void (*dispose_helper)(void *src);
|
||||
} *descriptor;
|
||||
const char *types;
|
||||
};
|
||||
|
||||
// Helper structure
|
||||
struct psy_block_byref_obj {
|
||||
void *isa; // uninitialized
|
||||
struct psy_block_byref_obj *forwarding;
|
||||
int flags; //refcount;
|
||||
int size;
|
||||
void (*byref_keep)(struct psy_block_byref_obj *dst, struct psy_block_byref_obj *src);
|
||||
void (*byref_dispose)(struct psy_block_byref_obj *);
|
||||
void *isa; // uninitialized
|
||||
struct psy_block_byref_obj *forwarding;
|
||||
int flags; //refcount;
|
||||
int size;
|
||||
void (*byref_keep)(struct psy_block_byref_obj *dst, struct psy_block_byref_obj *src);
|
||||
void (*byref_dispose)(struct psy_block_byref_obj *);
|
||||
};
|
||||
|
||||
/* Certain field types require runtime assistance when being copied to the
|
||||
|
@ -88,53 +88,58 @@ struct psy_block_byref_obj {
|
|||
* the other choices which are mutually exclusive. Only in a Block copy helper
|
||||
* will one see BLOCK_FIELD_IS_BYREF.
|
||||
*/
|
||||
void _Block_object_assign(void *destAddr, void *object, const int flags)
|
||||
void
|
||||
_Block_object_assign(void *destAddr, void *object, const int flags)
|
||||
{
|
||||
//printf("Copying %x to %x with flags %x\n", object, destAddr, flags);
|
||||
// FIXME: Needs to be implemented
|
||||
if(flags & BLOCK_FIELD_IS_WEAK)
|
||||
//printf("Copying %x to %x with flags %x\n", object, destAddr, flags);
|
||||
// FIXME: Needs to be implemented
|
||||
if (flags & BLOCK_FIELD_IS_WEAK)
|
||||
{
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
if(flags & BLOCK_FIELD_IS_BYREF)
|
||||
if (flags & BLOCK_FIELD_IS_BYREF)
|
||||
{
|
||||
struct psy_block_byref_obj *src = object;
|
||||
struct psy_block_byref_obj **dst = destAddr;
|
||||
struct psy_block_byref_obj *src = object;
|
||||
struct psy_block_byref_obj **dst = destAddr;
|
||||
|
||||
/* I followed Apple's specs saying byref's "flags" field should
|
||||
* represent the refcount but it still contains real flag, so this
|
||||
* is a little hack...
|
||||
*/
|
||||
if((src->flags & ~BLOCK_HAS_COPY_DISPOSE) == 0)
|
||||
/* I followed Apple's specs saying byref's "flags" field should
|
||||
* represent the refcount but it still contains real flag, so this
|
||||
* is a little hack...
|
||||
*/
|
||||
if ((src->flags & ~BLOCK_HAS_COPY_DISPOSE) == 0)
|
||||
{
|
||||
*dst = malloc(src->size);
|
||||
memcpy(*dst, src, src->size);
|
||||
if (src->forwarding == src)
|
||||
{
|
||||
(*dst)->forwarding = *dst;
|
||||
}
|
||||
if(src->size >= sizeof(struct psy_block_byref_obj))
|
||||
{
|
||||
src->byref_keep(*dst, src);
|
||||
}
|
||||
*dst = malloc(src->size);
|
||||
memcpy(*dst, src, src->size);
|
||||
if (src->forwarding == src)
|
||||
{
|
||||
(*dst)->forwarding = *dst;
|
||||
}
|
||||
if (src->size >= sizeof(struct psy_block_byref_obj))
|
||||
{
|
||||
src->byref_keep(*dst, src);
|
||||
}
|
||||
}
|
||||
else *dst = src;
|
||||
else
|
||||
{
|
||||
*dst = src;
|
||||
}
|
||||
|
||||
(*dst)->flags++;
|
||||
(*dst)->flags++;
|
||||
}
|
||||
else if((flags & BLOCK_FIELD_IS_BLOCK) == BLOCK_FIELD_IS_BLOCK)
|
||||
else if ((flags & BLOCK_FIELD_IS_BLOCK) == BLOCK_FIELD_IS_BLOCK)
|
||||
{
|
||||
struct psy_block_literal *src = object;
|
||||
struct psy_block_literal **dst = destAddr;
|
||||
struct psy_block_literal *src = object;
|
||||
struct psy_block_literal **dst = destAddr;
|
||||
|
||||
*dst = Block_copy(src);
|
||||
*dst = Block_copy(src);
|
||||
}
|
||||
else if((flags & BLOCK_FIELD_IS_OBJECT) == BLOCK_FIELD_IS_OBJECT)
|
||||
else if ((flags & BLOCK_FIELD_IS_OBJECT) == BLOCK_FIELD_IS_OBJECT)
|
||||
{
|
||||
id src = object;
|
||||
id *dst = destAddr;
|
||||
*dst = [src retain];
|
||||
id src = object;
|
||||
id *dst = destAddr;
|
||||
|
||||
*dst = [src retain];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -145,103 +150,113 @@ void _Block_object_assign(void *destAddr, void *object, const int flags)
|
|||
* The same flags used in the copy helper should be used for each call
|
||||
* generated to this function:
|
||||
*/
|
||||
void _Block_object_dispose(void *object, const int flags)
|
||||
void
|
||||
_Block_object_dispose(void *object, const int flags)
|
||||
{
|
||||
// FIXME: Needs to be implemented
|
||||
if(flags & BLOCK_FIELD_IS_WEAK)
|
||||
// FIXME: Needs to be implemented
|
||||
if (flags & BLOCK_FIELD_IS_WEAK)
|
||||
{
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
if(flags & BLOCK_FIELD_IS_BYREF)
|
||||
if (flags & BLOCK_FIELD_IS_BYREF)
|
||||
{
|
||||
struct psy_block_byref_obj *src = object;
|
||||
|
||||
src->flags--;
|
||||
if((src->flags & ~BLOCK_HAS_COPY_DISPOSE) == 0)
|
||||
struct psy_block_byref_obj *src = object;
|
||||
|
||||
src->flags--;
|
||||
if ((src->flags & ~BLOCK_HAS_COPY_DISPOSE) == 0)
|
||||
{
|
||||
if(src->size >= sizeof(struct psy_block_byref_obj))
|
||||
src->byref_dispose(src);
|
||||
if (src->size >= sizeof(struct psy_block_byref_obj))
|
||||
src->byref_dispose(src);
|
||||
|
||||
free(src);
|
||||
free(src);
|
||||
}
|
||||
}
|
||||
else if((flags & ~BLOCK_BYREF_CALLER) == BLOCK_FIELD_IS_BLOCK)
|
||||
else if ((flags & ~BLOCK_BYREF_CALLER) == BLOCK_FIELD_IS_BLOCK)
|
||||
{
|
||||
struct psy_block_literal *src = object;
|
||||
Block_release(src);
|
||||
struct psy_block_literal *src = object;
|
||||
Block_release(src);
|
||||
}
|
||||
else if((flags & ~BLOCK_BYREF_CALLER) == BLOCK_FIELD_IS_OBJECT)
|
||||
else if ((flags & ~BLOCK_BYREF_CALLER) == BLOCK_FIELD_IS_OBJECT)
|
||||
{
|
||||
id src = object;
|
||||
[src release];
|
||||
id src = object;
|
||||
[src release];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct StackBlockClass {
|
||||
void *isa; // initialized to &_NSConcreteStackBlock or &_NSConcreteGlobalBlock
|
||||
int flags;
|
||||
int reserved;
|
||||
void (*invoke)(void *, ...);
|
||||
struct {
|
||||
unsigned long int reserved; // NULL
|
||||
unsigned long int size; // sizeof(struct Block_literal_1)
|
||||
// optional helper functions
|
||||
void (*copy_helper)(void *dst, void *src);
|
||||
void (*dispose_helper)(void *src);
|
||||
} *descriptor;
|
||||
const char *types;
|
||||
void *isa; // initialized to &_NSConcreteStackBlock or &_NSConcreteGlobalBlock
|
||||
int flags;
|
||||
int reserved;
|
||||
void (*invoke)(void *, ...);
|
||||
struct {
|
||||
unsigned long int reserved; // NULL
|
||||
unsigned long int size; // sizeof(struct Block_literal_1)
|
||||
// optional helper functions
|
||||
void (*copy_helper)(void *dst, void *src);
|
||||
void (*dispose_helper)(void *src);
|
||||
} *descriptor;
|
||||
const char *types;
|
||||
};
|
||||
|
||||
|
||||
// Copy a block to the heap if it's still on the stack or increments its retain count.
|
||||
void *_Block_copy(void *src)
|
||||
/* Copy a block to the heap if it's still on the stack or
|
||||
* increments its retain count.
|
||||
*/
|
||||
void *
|
||||
_Block_copy(void *src)
|
||||
{
|
||||
struct StackBlockClass *self = src;
|
||||
struct StackBlockClass *ret = self;
|
||||
struct StackBlockClass *self = src;
|
||||
struct StackBlockClass *ret = self;
|
||||
|
||||
extern void _NSConcreteStackBlock __attribute__((weak));
|
||||
extern void _NSConcreteStackBlock __attribute__((weak));
|
||||
|
||||
// If the block is Global, there's no need to copy it on the heap.
|
||||
if(self->isa == &_NSConcreteStackBlock && self->flags & BLOCK_HAS_DESCRIPTOR)
|
||||
// If the block is Global, there's no need to copy it on the heap.
|
||||
if (self->isa == &_NSConcreteStackBlock
|
||||
&& self->flags & BLOCK_HAS_DESCRIPTOR)
|
||||
{
|
||||
if(self->reserved == 0)
|
||||
if (self->reserved == 0)
|
||||
{
|
||||
ret = malloc(self->descriptor->size);
|
||||
memcpy(ret, self, self->descriptor->size);
|
||||
if(self->flags & BLOCK_HAS_COPY_DISPOSE)
|
||||
self->descriptor->copy_helper(ret, self);
|
||||
memcpy(self, ret, self->descriptor->size);
|
||||
ret = malloc(self->descriptor->size);
|
||||
memcpy(ret, self, self->descriptor->size);
|
||||
if (self->flags & BLOCK_HAS_COPY_DISPOSE)
|
||||
self->descriptor->copy_helper(ret, self);
|
||||
memcpy(self, ret, self->descriptor->size);
|
||||
}
|
||||
ret->reserved++;
|
||||
ret->reserved++;
|
||||
}
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Release a block and frees the memory when the retain count hits zero.
|
||||
void _Block_release(void *src)
|
||||
void
|
||||
_Block_release(void *src)
|
||||
{
|
||||
struct StackBlockClass *self = src;
|
||||
struct StackBlockClass *self = src;
|
||||
|
||||
extern void _NSConcreteStackBlock __attribute__((weak));
|
||||
extern void _NSConcreteStackBlock __attribute__((weak));
|
||||
|
||||
if(self->isa == &_NSConcreteStackBlock && // A Global block doesn't need to be released
|
||||
self->flags & BLOCK_HAS_DESCRIPTOR && // Should always be true...
|
||||
self->reserved > 0) // If false, then it's not allocated on the heap, we won't release auto memory !
|
||||
if (self->isa == &_NSConcreteStackBlock
|
||||
// A Global block doesn't need to be released
|
||||
&& self->flags & BLOCK_HAS_DESCRIPTOR
|
||||
// Should always be true...
|
||||
&& self->reserved > 0)
|
||||
// If false, then it's not allocated on the heap, we won't release auto memory !
|
||||
{
|
||||
self->reserved--;
|
||||
if(self->reserved == 0)
|
||||
self->reserved--;
|
||||
if (self->reserved == 0)
|
||||
{
|
||||
if(self->flags & BLOCK_HAS_COPY_DISPOSE)
|
||||
self->descriptor->dispose_helper(self);
|
||||
free(self);
|
||||
if (self->flags & BLOCK_HAS_COPY_DISPOSE)
|
||||
self->descriptor->dispose_helper(self);
|
||||
free(self);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char *_Block_get_types(void *blk)
|
||||
const char *
|
||||
_Block_get_types(void *blk)
|
||||
{
|
||||
struct psy_block_literal *block = blk;
|
||||
return block->types;
|
||||
struct psy_block_literal *block = blk;
|
||||
return block->types;
|
||||
}
|
||||
|
|
|
@ -8,40 +8,51 @@
|
|||
- (void)release;
|
||||
@end
|
||||
|
||||
id objc_getProperty(id obj, SEL _cmd, ptrdiff_t offset, BOOL isAtomic)
|
||||
id
|
||||
objc_getProperty(id obj, SEL _cmd, ptrdiff_t offset, BOOL isAtomic)
|
||||
{
|
||||
if (isAtomic)
|
||||
char *addr;
|
||||
id ret;
|
||||
|
||||
if (isAtomic)
|
||||
{
|
||||
@synchronized(obj)
|
||||
{
|
||||
@synchronized(obj) {
|
||||
return objc_getProperty(obj, _cmd, offset, NO);
|
||||
}
|
||||
return objc_getProperty(obj, _cmd, offset, NO);
|
||||
}
|
||||
char *addr = (char*)obj;
|
||||
addr += offset;
|
||||
id ret = *(id*)addr;
|
||||
return [[ret retain] autorelease];
|
||||
}
|
||||
addr = (char*)obj;
|
||||
addr += offset;
|
||||
ret = *(id*)addr;
|
||||
return [[ret retain] autorelease];
|
||||
}
|
||||
|
||||
void objc_setProperty(id obj, SEL _cmd, ptrdiff_t offset, id arg, BOOL isAtomic, BOOL isCopy)
|
||||
void
|
||||
objc_setProperty(id obj, SEL _cmd, ptrdiff_t offset, id arg, BOOL isAtomic,
|
||||
BOOL isCopy)
|
||||
{
|
||||
if (isAtomic)
|
||||
char *addr;
|
||||
id old;
|
||||
|
||||
if (isAtomic)
|
||||
{
|
||||
@synchronized(obj)
|
||||
{
|
||||
@synchronized(obj) {
|
||||
objc_setProperty(obj, _cmd, offset, arg, NO, isCopy);
|
||||
return;
|
||||
}
|
||||
objc_setProperty(obj, _cmd, offset, arg, NO, isCopy);
|
||||
return;
|
||||
}
|
||||
if (isCopy)
|
||||
{
|
||||
arg = [arg copy];
|
||||
}
|
||||
else
|
||||
{
|
||||
arg = [arg retain];
|
||||
}
|
||||
char *addr = (char*)obj;
|
||||
addr += offset;
|
||||
id old = *(id*)addr;
|
||||
*(id*)addr = arg;
|
||||
[old release];
|
||||
}
|
||||
if (isCopy)
|
||||
{
|
||||
arg = [arg copy];
|
||||
}
|
||||
else
|
||||
{
|
||||
arg = [arg retain];
|
||||
}
|
||||
addr = (char*)obj;
|
||||
addr += offset;
|
||||
old = *(id*)addr;
|
||||
*(id*)addr = arg;
|
||||
[old release];
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -2,7 +2,7 @@
|
|||
|
||||
/* Ensure Unix98 compatible pthreads for glibc */
|
||||
#if defined __GLIBC__
|
||||
#define __USE_UNIX98 1
|
||||
# define __USE_UNIX98 1
|
||||
#endif
|
||||
|
||||
#include <pthread.h>
|
||||
|
@ -20,88 +20,104 @@ IMP objc_msg_lookup(id, SEL);
|
|||
|
||||
static void deallocLockClass(id obj, SEL _cmd);
|
||||
|
||||
static inline Class findLockClass(id obj)
|
||||
static inline Class
|
||||
findLockClass(id obj)
|
||||
{
|
||||
struct objc_object object = { obj->isa };
|
||||
SEL dealloc = @selector(dealloc);
|
||||
// Find the first class where this lookup is correct
|
||||
if (objc_msg_lookup((id)&object, dealloc) != (IMP)deallocLockClass)
|
||||
struct objc_object object = { obj->isa };
|
||||
SEL dealloc = @selector(dealloc);
|
||||
Class lastClass;
|
||||
|
||||
// Find the first class where this lookup is correct
|
||||
if (objc_msg_lookup((id)&object, dealloc) != (IMP)deallocLockClass)
|
||||
{
|
||||
do {
|
||||
object.isa = class_getSuperclass(object.isa);
|
||||
} while (Nil != object.isa
|
||||
&& objc_msg_lookup((id)&object, dealloc) != (IMP)deallocLockClass);
|
||||
}
|
||||
if (Nil == object.isa)
|
||||
{
|
||||
return Nil;
|
||||
}
|
||||
/* object->isa is now either the lock class, or a class which inherits from
|
||||
* the lock class
|
||||
*/
|
||||
do {
|
||||
lastClass = object.isa;
|
||||
object.isa = class_getSuperclass(object.isa);
|
||||
} while (Nil != object.isa
|
||||
&& objc_msg_lookup((id)&object, dealloc) == (IMP)deallocLockClass);
|
||||
return lastClass;
|
||||
}
|
||||
|
||||
static inline Class
|
||||
initLockObject(id obj)
|
||||
{
|
||||
char nameBuffer[40];
|
||||
Class lockClass;
|
||||
const char *types;
|
||||
pthread_mutex_t *lock;
|
||||
|
||||
snprintf(nameBuffer, 39, "hiddenlockClass%lld", lockClassId++);
|
||||
lockClass = objc_allocateClassPair(obj->isa, nameBuffer,
|
||||
sizeof(pthread_mutex_t));
|
||||
types = method_getTypeEncoding(class_getInstanceMethod(obj->isa,
|
||||
@selector(dealloc)));
|
||||
class_addMethod(lockClass, @selector(dealloc), (IMP)deallocLockClass, types);
|
||||
objc_registerClassPair(lockClass);
|
||||
|
||||
lock = object_getIndexedIvars(lockClass);
|
||||
pthread_mutexattr_t attr;
|
||||
pthread_mutexattr_init(&attr);
|
||||
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
|
||||
pthread_mutex_init(lock, &attr);
|
||||
pthread_mutexattr_destroy(&attr);
|
||||
|
||||
obj->isa = lockClass;
|
||||
return lockClass;
|
||||
}
|
||||
|
||||
static void
|
||||
deallocLockClass(id obj, SEL _cmd)
|
||||
{
|
||||
Class lockClass = findLockClass(obj);
|
||||
Class realClass = class_getSuperclass(lockClass);
|
||||
// Free the lock
|
||||
pthread_mutex_t *lock = object_getIndexedIvars(lockClass);
|
||||
|
||||
pthread_mutex_destroy(lock);
|
||||
// Free the class
|
||||
objc_disposeClassPair(lockClass);
|
||||
// Reset the class then call the real -dealloc
|
||||
obj->isa = realClass;
|
||||
[obj dealloc];
|
||||
}
|
||||
|
||||
void
|
||||
objc_sync_enter(id obj)
|
||||
{
|
||||
Class lockClass = findLockClass(obj);
|
||||
pthread_mutex_t *lock;
|
||||
|
||||
if (Nil == lockClass)
|
||||
{
|
||||
pthread_mutex_lock(&at_sync_init_lock);
|
||||
// Test again in case two threads call objc_sync_enter at once
|
||||
lockClass = findLockClass(obj);
|
||||
if (Nil == lockClass)
|
||||
{
|
||||
do {
|
||||
object.isa = class_getSuperclass(object.isa);
|
||||
} while (Nil != object.isa &&
|
||||
objc_msg_lookup((id)&object, dealloc) != (IMP)deallocLockClass);
|
||||
lockClass = initLockObject(obj);
|
||||
}
|
||||
if (Nil == object.isa) { return Nil; }
|
||||
// object->isa is now either the lock class, or a class which inherits from
|
||||
// the lock class
|
||||
Class lastClass;
|
||||
do {
|
||||
lastClass = object.isa;
|
||||
object.isa = class_getSuperclass(object.isa);
|
||||
} while (Nil != object.isa &&
|
||||
objc_msg_lookup((id)&object, dealloc) == (IMP)deallocLockClass);
|
||||
return lastClass;
|
||||
pthread_mutex_unlock(&at_sync_init_lock);
|
||||
}
|
||||
lock = object_getIndexedIvars(lockClass);
|
||||
pthread_mutex_lock(lock);
|
||||
}
|
||||
|
||||
static inline Class initLockObject(id obj)
|
||||
void
|
||||
objc_sync_exit(id obj)
|
||||
{
|
||||
char nameBuffer[40];
|
||||
snprintf(nameBuffer, 39, "hiddenlockClass%lld", lockClassId++);
|
||||
Class lockClass = objc_allocateClassPair(obj->isa, nameBuffer,
|
||||
sizeof(pthread_mutex_t));
|
||||
const char *types =
|
||||
method_getTypeEncoding(class_getInstanceMethod(obj->isa,
|
||||
@selector(dealloc)));
|
||||
class_addMethod(lockClass, @selector(dealloc), (IMP)deallocLockClass,
|
||||
types);
|
||||
objc_registerClassPair(lockClass);
|
||||
|
||||
pthread_mutex_t *lock = object_getIndexedIvars(lockClass);
|
||||
pthread_mutexattr_t attr;
|
||||
pthread_mutexattr_init(&attr);
|
||||
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
|
||||
pthread_mutex_init(lock, &attr);
|
||||
pthread_mutexattr_destroy(&attr);
|
||||
|
||||
obj->isa = lockClass;
|
||||
return lockClass;
|
||||
}
|
||||
|
||||
static void deallocLockClass(id obj, SEL _cmd)
|
||||
{
|
||||
Class lockClass = findLockClass(obj);
|
||||
Class realClass = class_getSuperclass(lockClass);
|
||||
// Free the lock
|
||||
pthread_mutex_t *lock = object_getIndexedIvars(lockClass);
|
||||
pthread_mutex_destroy(lock);
|
||||
// Free the class
|
||||
objc_disposeClassPair(lockClass);
|
||||
// Reset the class then call the real -dealloc
|
||||
obj->isa = realClass;
|
||||
[obj dealloc];
|
||||
}
|
||||
|
||||
void objc_sync_enter(id obj)
|
||||
{
|
||||
Class lockClass = findLockClass(obj);
|
||||
if (Nil == lockClass)
|
||||
{
|
||||
pthread_mutex_lock(&at_sync_init_lock);
|
||||
// Test again in case two threads call objc_sync_enter at once
|
||||
lockClass = findLockClass(obj);
|
||||
if (Nil == lockClass)
|
||||
{
|
||||
lockClass = initLockObject(obj);
|
||||
}
|
||||
pthread_mutex_unlock(&at_sync_init_lock);
|
||||
}
|
||||
pthread_mutex_t *lock = object_getIndexedIvars(lockClass);
|
||||
pthread_mutex_lock(lock);
|
||||
}
|
||||
void objc_sync_exit(id obj)
|
||||
{
|
||||
Class lockClass = findLockClass(obj);
|
||||
pthread_mutex_t *lock = object_getIndexedIvars(lockClass);
|
||||
pthread_mutex_unlock(lock);
|
||||
Class lockClass = findLockClass(obj);
|
||||
pthread_mutex_t *lock = object_getIndexedIvars(lockClass);
|
||||
pthread_mutex_unlock(lock);
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ WITH_FFI=@WITH_FFI@
|
|||
|
||||
NX_CONST_STRING_CLASS=@NX_CONST_STRING_CLASS@
|
||||
OBJCFLAGS=@OBJCFLAGS@
|
||||
OBJC2RUNTIME=@OBJC2RUNTIME@
|
||||
|
||||
HAVE_INET_PTON=@HAVE_INET_PTON@
|
||||
HAVE_INET_NTOP=@HAVE_INET_NTOP@
|
||||
|
|
115
configure
vendored
115
configure
vendored
|
@ -310,7 +310,7 @@ ac_includes_default="\
|
|||
#endif"
|
||||
|
||||
ac_subdirs_all="$ac_subdirs_all Source/pathconfig Source/mframe SSL"
|
||||
ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CPP WHOAMI EGREP OBJC_WITH_GC GS_WORDS_BIGENDIAN GS_SINT8 GS_UINT8 ac_cv_sizeof_short ac_cv_sizeof_int ac_cv_sizeof_long ac_cv_sizeof_long_long ac_cv_sizeof_float ac_cv_sizeof_double ac_cv_sizeof_voidp GS_SADDR GS_UADDR GS_SINT16 GS_UINT16 GS_SINT32 GS_UINT32 GS_SINT64 GS_UINT64 GS_HAVE_I64 GS_SINT128 GS_UINT128 GS_HAVE_I128 GS_FLT32 GS_FLT64 _GSC_S_SHT _GSC_S_INT _GSC_S_LNG _GSC_S_LNG_LNG DYNAMIC_LINKER NX_CONST_STRING_OBJCFLAGS NX_CONST_STRING_CLASS HAVE_OBJC_SYNC_ENTER GS_SIZEOF_MUTEX_T GS_SIZEOF_COND_T HAVE_PTS_STREAM_MODULES INCLUDE_STDINT DEFINE_INT8_T DEFINE_UINT8_T DEFINE_INT16_T DEFINE_UINT16_T DEFINE_INT32_T DEFINE_UINT32_T DEFINE_INT64_T DEFINE_UINT64_T DEFINE_INTPTR_T DEFINE_UINTPTR_T USE_ZLIB HAVE_INET_PTON HAVE_INET_NTOP GS_PASS_ARGUMENTS GS_FAKE_MAIN OBJCFLAGS WITH_FFI XML2_CONFIG XML_CONFIG XML_CFLAGS XML_LIBS HAVE_LIBXSLT HAVE_LIBXML TLS_CONFIG TLS_CFLAGS TLS_LIBS HAVE_GNUTLS HAVE_MDNS USE_GMP INCLUDE_FLAGS LDIR_FLAGS subdirs VERSION MAJOR_VERSION MINOR_VERSION SUBMINOR_VERSION GCC_VERSION LIBOBJS LTLIBOBJS'
|
||||
ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CPP WHOAMI EGREP OBJC_WITH_GC GS_WORDS_BIGENDIAN GS_SINT8 GS_UINT8 ac_cv_sizeof_short ac_cv_sizeof_int ac_cv_sizeof_long ac_cv_sizeof_long_long ac_cv_sizeof_float ac_cv_sizeof_double ac_cv_sizeof_voidp GS_SADDR GS_UADDR GS_SINT16 GS_UINT16 GS_SINT32 GS_UINT32 GS_SINT64 GS_UINT64 GS_HAVE_I64 GS_SINT128 GS_UINT128 GS_HAVE_I128 GS_FLT32 GS_FLT64 _GSC_S_SHT _GSC_S_INT _GSC_S_LNG _GSC_S_LNG_LNG DYNAMIC_LINKER NX_CONST_STRING_OBJCFLAGS NX_CONST_STRING_CLASS OBJC2RUNTIME HAVE_OBJC_SYNC_ENTER GS_SIZEOF_MUTEX_T GS_SIZEOF_COND_T HAVE_PTS_STREAM_MODULES INCLUDE_STDINT DEFINE_INT8_T DEFINE_UINT8_T DEFINE_INT16_T DEFINE_UINT16_T DEFINE_INT32_T DEFINE_UINT32_T DEFINE_INT64_T DEFINE_UINT64_T DEFINE_INTPTR_T DEFINE_UINTPTR_T USE_ZLIB HAVE_INET_PTON HAVE_INET_NTOP GS_PASS_ARGUMENTS GS_FAKE_MAIN OBJCFLAGS WITH_FFI XML2_CONFIG XML_CONFIG XML_CFLAGS XML_LIBS HAVE_LIBXSLT HAVE_LIBXML TLS_CONFIG TLS_CFLAGS TLS_LIBS HAVE_GNUTLS HAVE_MDNS USE_GMP INCLUDE_FLAGS LDIR_FLAGS subdirs VERSION MAJOR_VERSION MINOR_VERSION SUBMINOR_VERSION GCC_VERSION LIBOBJS LTLIBOBJS'
|
||||
ac_subst_files=''
|
||||
|
||||
# Initialize some variables set by options.
|
||||
|
@ -8647,6 +8647,118 @@ fi
|
|||
done
|
||||
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Check for ObjC2 support in runtime
|
||||
#--------------------------------------------------------------------
|
||||
|
||||
for ac_func in objc_setProperty
|
||||
do
|
||||
as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
|
||||
echo "$as_me:$LINENO: checking for $ac_func" >&5
|
||||
echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
|
||||
if eval "test \"\${$as_ac_var+set}\" = set"; then
|
||||
echo $ECHO_N "(cached) $ECHO_C" >&6
|
||||
else
|
||||
cat >conftest.$ac_ext <<_ACEOF
|
||||
/* confdefs.h. */
|
||||
_ACEOF
|
||||
cat confdefs.h >>conftest.$ac_ext
|
||||
cat >>conftest.$ac_ext <<_ACEOF
|
||||
/* end confdefs.h. */
|
||||
/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
|
||||
For example, HP-UX 11i <limits.h> declares gettimeofday. */
|
||||
#define $ac_func innocuous_$ac_func
|
||||
|
||||
/* System header to define __stub macros and hopefully few prototypes,
|
||||
which can conflict with char $ac_func (); below.
|
||||
Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
|
||||
<limits.h> exists even on freestanding compilers. */
|
||||
|
||||
#ifdef __STDC__
|
||||
# include <limits.h>
|
||||
#else
|
||||
# include <assert.h>
|
||||
#endif
|
||||
|
||||
#undef $ac_func
|
||||
|
||||
/* Override any gcc2 internal prototype to avoid an error. */
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
/* We use char because int might match the return type of a gcc2
|
||||
builtin and then its argument prototype would still apply. */
|
||||
char $ac_func ();
|
||||
/* The GNU C library defines this for functions which it implements
|
||||
to always fail with ENOSYS. Some functions are actually named
|
||||
something starting with __ and the normal name is an alias. */
|
||||
#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
|
||||
choke me
|
||||
#else
|
||||
char (*f) () = $ac_func;
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
return f != $ac_func;
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
rm -f conftest.$ac_objext conftest$ac_exeext
|
||||
if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
|
||||
(eval $ac_link) 2>conftest.er1
|
||||
ac_status=$?
|
||||
grep -v '^ *+' conftest.er1 >conftest.err
|
||||
rm -f conftest.er1
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); } &&
|
||||
{ ac_try='test -z "$ac_c_werror_flag"
|
||||
|| test ! -s conftest.err'
|
||||
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
|
||||
(eval $ac_try) 2>&5
|
||||
ac_status=$?
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); }; } &&
|
||||
{ ac_try='test -s conftest$ac_exeext'
|
||||
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
|
||||
(eval $ac_try) 2>&5
|
||||
ac_status=$?
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); }; }; then
|
||||
eval "$as_ac_var=yes"
|
||||
else
|
||||
echo "$as_me: failed program was:" >&5
|
||||
sed 's/^/| /' conftest.$ac_ext >&5
|
||||
|
||||
eval "$as_ac_var=no"
|
||||
fi
|
||||
rm -f conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
fi
|
||||
echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
|
||||
echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
|
||||
if test `eval echo '${'$as_ac_var'}'` = yes; then
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
|
||||
_ACEOF
|
||||
|
||||
fi
|
||||
done
|
||||
|
||||
if test $ac_cv_func_objc_setProperty = yes ; then
|
||||
OBJC2RUNTIME=yes
|
||||
else
|
||||
OBJC2RUNTIME=no
|
||||
fi
|
||||
|
||||
|
||||
# Don't revert any Objective-C flags as they are used in the next test
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
|
@ -21401,6 +21513,7 @@ s,@_GSC_S_LNG_LNG@,$_GSC_S_LNG_LNG,;t t
|
|||
s,@DYNAMIC_LINKER@,$DYNAMIC_LINKER,;t t
|
||||
s,@NX_CONST_STRING_OBJCFLAGS@,$NX_CONST_STRING_OBJCFLAGS,;t t
|
||||
s,@NX_CONST_STRING_CLASS@,$NX_CONST_STRING_CLASS,;t t
|
||||
s,@OBJC2RUNTIME@,$OBJC2RUNTIME,;t t
|
||||
s,@HAVE_OBJC_SYNC_ENTER@,$HAVE_OBJC_SYNC_ENTER,;t t
|
||||
s,@GS_SIZEOF_MUTEX_T@,$GS_SIZEOF_MUTEX_T,;t t
|
||||
s,@GS_SIZEOF_COND_T@,$GS_SIZEOF_COND_T,;t t
|
||||
|
|
11
configure.ac
11
configure.ac
|
@ -658,6 +658,17 @@ fi
|
|||
#--------------------------------------------------------------------
|
||||
AC_CHECK_FUNCS(objc_thread_add)
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Check for ObjC2 support in runtime
|
||||
#--------------------------------------------------------------------
|
||||
AC_CHECK_FUNCS(objc_setProperty)
|
||||
if test $ac_cv_func_objc_setProperty = yes ; then
|
||||
OBJC2RUNTIME=yes
|
||||
else
|
||||
OBJC2RUNTIME=no
|
||||
fi
|
||||
AC_SUBST(OBJC2RUNTIME)
|
||||
|
||||
# Don't revert any Objective-C flags as they are used in the next test
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
|
|
Loading…
Reference in a new issue