diff --git a/blocks_runtime.m b/blocks_runtime.m index 6e5aa5a..7e194c5 100644 --- a/blocks_runtime.m +++ b/blocks_runtime.m @@ -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; + 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, const 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,55 +88,55 @@ 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, const 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) - { - } - else - { - if(flags & BLOCK_FIELD_IS_BYREF) - { - struct psy_block_byref_obj *src = object; - struct psy_block_byref_obj **dst = destAddr; - + // FIXME: Needs to be implemented + if(flags & BLOCK_FIELD_IS_WEAK) + { + } + else + { + if(flags & BLOCK_FIELD_IS_BYREF) + { + const 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) - { - *dst = malloc(src->size); - memcpy(*dst, src, src->size); + */ + 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)) + if(src->size >= sizeof(struct psy_block_byref_obj)) { - src->byref_keep(*dst, src); + src->byref_keep(*dst, src); } - } - else *dst = src; - - (*dst)->flags++; - } - else if((flags & BLOCK_FIELD_IS_BLOCK) == BLOCK_FIELD_IS_BLOCK) - { - struct psy_block_literal *src = object; - struct psy_block_literal **dst = destAddr; - - *dst = Block_copy(src); - } - else if((flags & BLOCK_FIELD_IS_OBJECT) == BLOCK_FIELD_IS_OBJECT) - { - id src = object; - id *dst = destAddr; - *dst = [src retain]; - } - } + } + else *dst = (struct psy_block_byref_obj*)src; + + (*dst)->flags++; + } + else if((flags & BLOCK_FIELD_IS_BLOCK) == BLOCK_FIELD_IS_BLOCK) + { + struct psy_block_literal *src = (struct psy_block_literal*)object; + struct psy_block_literal **dst = destAddr; + + *dst = Block_copy(src); + } + else if((flags & BLOCK_FIELD_IS_OBJECT) == BLOCK_FIELD_IS_OBJECT) + { + id src = object; + id *dst = destAddr; + *dst = [src retain]; + } + } } /* Similarly a compiler generated dispose helper needs to call back for each @@ -145,52 +145,53 @@ 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(const void *object, const int flags) { - // FIXME: Needs to be implemented - if(flags & BLOCK_FIELD_IS_WEAK) - { - } - else - { - if(flags & BLOCK_FIELD_IS_BYREF) - { - 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); - - free(src); - } - } - else if((flags & ~BLOCK_BYREF_CALLER) == BLOCK_FIELD_IS_BLOCK) - { - struct psy_block_literal *src = object; - Block_release(src); - } - else if((flags & ~BLOCK_BYREF_CALLER) == BLOCK_FIELD_IS_OBJECT) - { - id src = object; - [src release]; - } - } + // FIXME: Needs to be implemented + if(flags & BLOCK_FIELD_IS_WEAK) + { + } + else + { + if(flags & BLOCK_FIELD_IS_BYREF) + { + struct psy_block_byref_obj *src = + (struct psy_block_byref_obj*)object; + + src->flags--; + if((src->flags & ~BLOCK_HAS_COPY_DISPOSE) == 0) + { + if(src->size >= sizeof(struct psy_block_byref_obj)) + src->byref_dispose(src); + + free(src); + } + } + else if((flags & ~BLOCK_BYREF_CALLER) == BLOCK_FIELD_IS_BLOCK) + { + struct psy_block_literal *src = (struct psy_block_literal*)object; + Block_release(src); + } + else if((flags & ~BLOCK_BYREF_CALLER) == BLOCK_FIELD_IS_OBJECT) + { + 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; + 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; }; @@ -198,46 +199,46 @@ struct StackBlockClass { // 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)); - - // 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) - { - 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++; - } - return ret; + + // 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) + { + 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++; + } + return ret; } // Release a block and frees the memory when the retain count hits zero. void _Block_release(void *src) { - struct StackBlockClass *self = src; - + struct StackBlockClass *self = src; + 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 ! - { - self->reserved--; - if(self->reserved == 0) - { - if(self->flags & BLOCK_HAS_COPY_DISPOSE) - self->descriptor->dispose_helper(self); - free(self); - } - } + 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) + { + if(self->flags & BLOCK_HAS_COPY_DISPOSE) + self->descriptor->dispose_helper(self); + free(self); + } + } } const char *_Block_get_types(void *blk) diff --git a/dwarf_eh.h b/dwarf_eh.h index 8cd5e4b..7f43c69 100644 --- a/dwarf_eh.h +++ b/dwarf_eh.h @@ -10,10 +10,10 @@ // that it doesn't impact the rest of the program. #ifndef _GNU_SOURCE # define _GNU_SOURCE 1 -# include +# include "unwind.h" # undef _GNU_SOURCE #else -# include +# include "unwind.h" #endif typedef unsigned char *dw_eh_ptr_t; diff --git a/ivar.c b/ivar.c index a734305..987f9eb 100644 --- a/ivar.c +++ b/ivar.c @@ -1,6 +1,6 @@ #include #include -#include +#include "objc/runtime.h" #include "class.h" #include "ivar.h"