forked from RetVal/objc-runtime
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
37 changed files
with
2,711 additions
and
0 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
/* | ||
* Copyright (c) 2006-2007 Apple Inc. All Rights Reserved. | ||
* | ||
* @APPLE_LICENSE_HEADER_START@ | ||
* | ||
* This file contains Original Code and/or Modifications of Original Code | ||
* as defined in and that are subject to the Apple Public Source License | ||
* Version 2.0 (the 'License'). You may not use this file except in | ||
* compliance with the License. Please obtain a copy of the License at | ||
* http://www.opensource.apple.com/apsl/ and read it before using this | ||
* file. | ||
* | ||
* The Original Code and all software distributed under the License are | ||
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | ||
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | ||
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | ||
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. | ||
* Please see the License for the specific language governing rights and | ||
* limitations under the License. | ||
* | ||
* @APPLE_LICENSE_HEADER_END@ | ||
*/ | ||
|
||
#ifndef _OBJC_ACCESSORS_H_ | ||
#define _OBJC_ACCESSORS_H_ | ||
|
||
#include <objc/objc.h> | ||
#include <stddef.h> | ||
|
||
__BEGIN_DECLS | ||
|
||
#if SUPPORT_GC | ||
|
||
extern void objc_setProperty_non_gc(id self, SEL _cmd, ptrdiff_t offset, id newValue, BOOL atomic, signed char shouldCopy); | ||
extern id objc_getProperty_non_gc(id self, SEL _cmd, ptrdiff_t offset, BOOL atomic); | ||
|
||
extern void objc_setProperty_gc(id self, SEL _cmd, ptrdiff_t offset, id newValue, BOOL atomic, signed char shouldCopy); | ||
extern id objc_getProperty_gc(id self, SEL _cmd, ptrdiff_t offset, BOOL atomic); | ||
|
||
#endif | ||
|
||
__END_DECLS | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,200 @@ | ||
/* | ||
* Copyright (c) 2006-2008 Apple Inc. All Rights Reserved. | ||
* | ||
* @APPLE_LICENSE_HEADER_START@ | ||
* | ||
* This file contains Original Code and/or Modifications of Original Code | ||
* as defined in and that are subject to the Apple Public Source License | ||
* Version 2.0 (the 'License'). You may not use this file except in | ||
* compliance with the License. Please obtain a copy of the License at | ||
* http://www.opensource.apple.com/apsl/ and read it before using this | ||
* file. | ||
* | ||
* The Original Code and all software distributed under the License are | ||
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | ||
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | ||
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | ||
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. | ||
* Please see the License for the specific language governing rights and | ||
* limitations under the License. | ||
* | ||
* @APPLE_LICENSE_HEADER_END@ | ||
*/ | ||
|
||
#include <string.h> | ||
#include <stddef.h> | ||
|
||
#include <libkern/OSAtomic.h> | ||
|
||
#include "objc-private.h" | ||
#include "objc-auto.h" | ||
#include "runtime.h" | ||
#include "objc-accessors.h" | ||
|
||
// stub interface declarations to make compiler happy. | ||
|
||
@interface __NSCopyable | ||
- (id)copyWithZone:(void *)zone; | ||
@end | ||
|
||
@interface __NSMutableCopyable | ||
- (id)mutableCopyWithZone:(void *)zone; | ||
@end | ||
|
||
static StripedMap<spinlock_t> PropertyLocks; | ||
|
||
#define MUTABLE_COPY 2 | ||
|
||
id objc_getProperty_non_gc(id self, SEL _cmd, ptrdiff_t offset, BOOL atomic) { | ||
if (offset == 0) { | ||
return object_getClass(self); | ||
} | ||
|
||
// Retain release world | ||
id *slot = (id*) ((char*)self + offset); | ||
if (!atomic) return *slot; | ||
|
||
// Atomic retain release world | ||
spinlock_t& slotlock = PropertyLocks[slot]; | ||
slotlock.lock(); | ||
id value = objc_retain(*slot); | ||
slotlock.unlock(); | ||
|
||
// for performance, we (safely) issue the autorelease OUTSIDE of the spinlock. | ||
return objc_autoreleaseReturnValue(value); | ||
} | ||
|
||
|
||
static inline void reallySetProperty(id self, SEL _cmd, id newValue, ptrdiff_t offset, bool atomic, bool copy, bool mutableCopy) __attribute__((always_inline)); | ||
|
||
static inline void reallySetProperty(id self, SEL _cmd, id newValue, ptrdiff_t offset, bool atomic, bool copy, bool mutableCopy) | ||
{ | ||
if (offset == 0) { | ||
object_setClass(self, newValue); | ||
return; | ||
} | ||
|
||
id oldValue; | ||
id *slot = (id*) ((char*)self + offset); | ||
|
||
if (copy) { | ||
newValue = [newValue copyWithZone:nil]; | ||
} else if (mutableCopy) { | ||
newValue = [newValue mutableCopyWithZone:nil]; | ||
} else { | ||
if (*slot == newValue) return; | ||
newValue = objc_retain(newValue); | ||
} | ||
|
||
if (!atomic) { | ||
oldValue = *slot; | ||
*slot = newValue; | ||
} else { | ||
spinlock_t& slotlock = PropertyLocks[slot]; | ||
slotlock.lock(); | ||
oldValue = *slot; | ||
*slot = newValue; | ||
slotlock.unlock(); | ||
} | ||
|
||
objc_release(oldValue); | ||
} | ||
|
||
void objc_setProperty_non_gc(id self, SEL _cmd, ptrdiff_t offset, id newValue, BOOL atomic, signed char shouldCopy) | ||
{ | ||
bool copy = (shouldCopy && shouldCopy != MUTABLE_COPY); | ||
bool mutableCopy = (shouldCopy == MUTABLE_COPY); | ||
reallySetProperty(self, _cmd, newValue, offset, atomic, copy, mutableCopy); | ||
} | ||
|
||
void objc_setProperty_atomic(id self, SEL _cmd, id newValue, ptrdiff_t offset) | ||
{ | ||
reallySetProperty(self, _cmd, newValue, offset, true, false, false); | ||
} | ||
|
||
void objc_setProperty_nonatomic(id self, SEL _cmd, id newValue, ptrdiff_t offset) | ||
{ | ||
reallySetProperty(self, _cmd, newValue, offset, false, false, false); | ||
} | ||
|
||
|
||
void objc_setProperty_atomic_copy(id self, SEL _cmd, id newValue, ptrdiff_t offset) | ||
{ | ||
reallySetProperty(self, _cmd, newValue, offset, true, true, false); | ||
} | ||
|
||
void objc_setProperty_nonatomic_copy(id self, SEL _cmd, id newValue, ptrdiff_t offset) | ||
{ | ||
reallySetProperty(self, _cmd, newValue, offset, false, true, false); | ||
} | ||
|
||
|
||
#if SUPPORT_GC | ||
|
||
id objc_getProperty_gc(id self, SEL _cmd, ptrdiff_t offset, BOOL atomic) { | ||
return *(id*) ((char*)self + offset); | ||
} | ||
|
||
void objc_setProperty_gc(id self, SEL _cmd, ptrdiff_t offset, id newValue, BOOL atomic, signed char shouldCopy) { | ||
if (shouldCopy) { | ||
newValue = (shouldCopy == MUTABLE_COPY ? [newValue mutableCopyWithZone:nil] : [newValue copyWithZone:nil]); | ||
} | ||
objc_assign_ivar(newValue, self, offset); | ||
} | ||
|
||
// objc_getProperty and objc_setProperty are resolver functions in objc-auto.mm | ||
|
||
#else | ||
|
||
id | ||
objc_getProperty(id self, SEL _cmd, ptrdiff_t offset, BOOL atomic) | ||
{ | ||
return objc_getProperty_non_gc(self, _cmd, offset, atomic); | ||
} | ||
|
||
void | ||
objc_setProperty(id self, SEL _cmd, ptrdiff_t offset, id newValue, | ||
BOOL atomic, signed char shouldCopy) | ||
{ | ||
objc_setProperty_non_gc(self, _cmd, offset, newValue, atomic, shouldCopy); | ||
} | ||
|
||
#endif | ||
|
||
|
||
// This entry point was designed wrong. When used as a getter, src needs to be locked so that | ||
// if simultaneously used for a setter then there would be contention on src. | ||
// So we need two locks - one of which will be contended. | ||
void objc_copyStruct(void *dest, const void *src, ptrdiff_t size, BOOL atomic, BOOL hasStrong) { | ||
static StripedMap<spinlock_t> StructLocks; | ||
spinlock_t *srcLock = nil; | ||
spinlock_t *dstLock = nil; | ||
if (atomic) { | ||
srcLock = &StructLocks[src]; | ||
dstLock = &StructLocks[dest]; | ||
spinlock_t::lockTwo(srcLock, dstLock); | ||
} | ||
#if SUPPORT_GC | ||
if (UseGC && hasStrong) { | ||
auto_zone_write_barrier_memmove(gc_zone, dest, src, size); | ||
} else | ||
#endif | ||
{ | ||
memmove(dest, src, size); | ||
} | ||
if (atomic) { | ||
spinlock_t::unlockTwo(srcLock, dstLock); | ||
} | ||
} | ||
|
||
void objc_copyCppObjectAtomic(void *dest, const void *src, void (*copyHelper) (void *dest, const void *source)) { | ||
static StripedMap<spinlock_t> CppObjectLocks; | ||
spinlock_t *srcLock = &CppObjectLocks[src]; | ||
spinlock_t *dstLock = &CppObjectLocks[dest]; | ||
spinlock_t::lockTwo(srcLock, dstLock); | ||
|
||
// let C++ code perform the actual copy. | ||
copyHelper(dest, src); | ||
|
||
spinlock_t::unlockTwo(srcLock, dstLock); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
/* | ||
* Copyright (c) 2015 Apple Inc. All Rights Reserved. | ||
* | ||
* @APPLE_LICENSE_HEADER_START@ | ||
* | ||
* This file contains Original Code and/or Modifications of Original Code | ||
* as defined in and that are subject to the Apple Public Source License | ||
* Version 2.0 (the 'License'). You may not use this file except in | ||
* compliance with the License. Please obtain a copy of the License at | ||
* http://www.opensource.apple.com/apsl/ and read it before using this | ||
* file. | ||
* | ||
* The Original Code and all software distributed under the License are | ||
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | ||
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | ||
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | ||
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. | ||
* Please see the License for the specific language governing rights and | ||
* limitations under the License. | ||
* | ||
* @APPLE_LICENSE_HEADER_END@ | ||
*/ | ||
|
||
extern void lockdebug_mutex_lock(mutex_tt<true> *lock); | ||
extern void lockdebug_mutex_try_lock(mutex_tt<true> *lock); | ||
extern void lockdebug_mutex_unlock(mutex_tt<true> *lock); | ||
extern void lockdebug_mutex_assert_locked(mutex_tt<true> *lock); | ||
extern void lockdebug_mutex_assert_unlocked(mutex_tt<true> *lock); | ||
|
||
static inline void lockdebug_mutex_lock(mutex_tt<false> *lock) { } | ||
static inline void lockdebug_mutex_try_lock(mutex_tt<false> *lock) { } | ||
static inline void lockdebug_mutex_unlock(mutex_tt<false> *lock) { } | ||
static inline void lockdebug_mutex_assert_locked(mutex_tt<false> *lock) { } | ||
static inline void lockdebug_mutex_assert_unlocked(mutex_tt<false> *lock) { } | ||
|
||
|
||
extern void lockdebug_monitor_enter(monitor_tt<true> *lock); | ||
extern void lockdebug_monitor_leave(monitor_tt<true> *lock); | ||
extern void lockdebug_monitor_wait(monitor_tt<true> *lock); | ||
extern void lockdebug_monitor_assert_locked(monitor_tt<true> *lock); | ||
extern void lockdebug_monitor_assert_unlocked(monitor_tt<true> *lock); | ||
|
||
static inline void lockdebug_monitor_enter(monitor_tt<false> *lock) { } | ||
static inline void lockdebug_monitor_leave(monitor_tt<false> *lock) { } | ||
static inline void lockdebug_monitor_wait(monitor_tt<false> *lock) { } | ||
static inline void lockdebug_monitor_assert_locked(monitor_tt<false> *lock) { } | ||
static inline void lockdebug_monitor_assert_unlocked(monitor_tt<false> *lock) {} | ||
|
||
|
||
extern void | ||
lockdebug_recursive_mutex_lock(recursive_mutex_tt<true> *lock); | ||
extern void | ||
lockdebug_recursive_mutex_unlock(recursive_mutex_tt<true> *lock); | ||
extern void | ||
lockdebug_recursive_mutex_assert_locked(recursive_mutex_tt<true> *lock); | ||
extern void | ||
lockdebug_recursive_mutex_assert_unlocked(recursive_mutex_tt<true> *lock); | ||
|
||
static inline void | ||
lockdebug_recursive_mutex_lock(recursive_mutex_tt<false> *lock) { } | ||
static inline void | ||
lockdebug_recursive_mutex_unlock(recursive_mutex_tt<false> *lock) { } | ||
static inline void | ||
lockdebug_recursive_mutex_assert_locked(recursive_mutex_tt<false> *lock) { } | ||
static inline void | ||
lockdebug_recursive_mutex_assert_unlocked(recursive_mutex_tt<false> *lock) { } | ||
|
||
|
||
extern void lockdebug_rwlock_read(rwlock_tt<true> *lock); | ||
extern void lockdebug_rwlock_try_read_success(rwlock_tt<true> *lock); | ||
extern void lockdebug_rwlock_unlock_read(rwlock_tt<true> *lock); | ||
extern void lockdebug_rwlock_write(rwlock_tt<true> *lock); | ||
extern void lockdebug_rwlock_try_write_success(rwlock_tt<true> *lock); | ||
extern void lockdebug_rwlock_unlock_write(rwlock_tt<true> *lock); | ||
extern void lockdebug_rwlock_assert_reading(rwlock_tt<true> *lock); | ||
extern void lockdebug_rwlock_assert_writing(rwlock_tt<true> *lock); | ||
extern void lockdebug_rwlock_assert_locked(rwlock_tt<true> *lock); | ||
extern void lockdebug_rwlock_assert_unlocked(rwlock_tt<true> *lock); | ||
|
||
static inline void lockdebug_rwlock_read(rwlock_tt<false> *) { } | ||
static inline void lockdebug_rwlock_try_read_success(rwlock_tt<false> *) { } | ||
static inline void lockdebug_rwlock_unlock_read(rwlock_tt<false> *) { } | ||
static inline void lockdebug_rwlock_write(rwlock_tt<false> *) { } | ||
static inline void lockdebug_rwlock_try_write_success(rwlock_tt<false> *) { } | ||
static inline void lockdebug_rwlock_unlock_write(rwlock_tt<false> *) { } | ||
static inline void lockdebug_rwlock_assert_reading(rwlock_tt<false> *) { } | ||
static inline void lockdebug_rwlock_assert_writing(rwlock_tt<false> *) { } | ||
static inline void lockdebug_rwlock_assert_locked(rwlock_tt<false> *) { } | ||
static inline void lockdebug_rwlock_assert_unlocked(rwlock_tt<false> *) { } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
// TEST_CONFIG OS=macosx | ||
// TEST_CFLAGS -framework AppleScriptObjC -framework Foundation | ||
|
||
// Verify that trivial AppleScriptObjC apps run with GC off. | ||
|
||
#include <Foundation/Foundation.h> | ||
#include "test.h" | ||
|
||
int main() | ||
{ | ||
[NSBundle class]; | ||
testassert(!objc_collectingEnabled()); | ||
succeed(__FILE__); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
// TEST_CFLAGS -framework AppleScriptObjC -framework Foundation | ||
// TEST_CONFIG MEM=gc | ||
|
||
// Verify that non-trivial AppleScriptObjC apps run with GC ON. | ||
|
||
#include <Foundation/Foundation.h> | ||
#include "test.h" | ||
|
||
@interface NonTrivial : NSObject @end | ||
@implementation NonTrivial @end | ||
|
||
int main() | ||
{ | ||
[NSBundle class]; | ||
testassert(objc_collectingEnabled()); | ||
succeed(__FILE__); | ||
} |
Oops, something went wrong.