Various tidies.

main
theraven 16 years ago
parent 718c9398e5
commit 569a48650d

@ -38,47 +38,47 @@
// Descriptor attributes // Descriptor attributes
enum { enum {
BLOCK_HAS_COPY_DISPOSE = (1 << 25), BLOCK_HAS_COPY_DISPOSE = (1 << 25),
BLOCK_HAS_CTOR = (1 << 26), // helpers have C++ code BLOCK_HAS_CTOR = (1 << 26), // helpers have C++ code
BLOCK_IS_GLOBAL = (1 << 28), BLOCK_IS_GLOBAL = (1 << 28),
BLOCK_HAS_DESCRIPTOR = (1 << 29), // interim until complete world build is accomplished BLOCK_HAS_DESCRIPTOR = (1 << 29), // interim until complete world build is accomplished
}; };
// _Block_object_assign() and _Block_object_dispose() flag helpers. // _Block_object_assign() and _Block_object_dispose() flag helpers.
enum { enum {
BLOCK_FIELD_IS_OBJECT = 3, // id, NSObject, __attribute__((NSObject)), block, ... BLOCK_FIELD_IS_OBJECT = 3, // id, NSObject, __attribute__((NSObject)), block, ...
BLOCK_FIELD_IS_BLOCK = 7, // a block variable BLOCK_FIELD_IS_BLOCK = 7, // a block variable
BLOCK_FIELD_IS_BYREF = 8, // the on stack structure holding the __block variable BLOCK_FIELD_IS_BYREF = 8, // the on stack structure holding the __block variable
BLOCK_FIELD_IS_WEAK = 16, // declared __weak BLOCK_FIELD_IS_WEAK = 16, // declared __weak
BLOCK_BYREF_CALLER = 128, // called from byref copy/dispose helpers BLOCK_BYREF_CALLER = 128, // called from byref copy/dispose helpers
}; };
// Helper structure // Helper structure
struct psy_block_literal { struct psy_block_literal {
void *isa; // initialized to &_NSConcreteStackBlock or &_NSConcreteGlobalBlock void *isa; // initialized to &_NSConcreteStackBlock or &_NSConcreteGlobalBlock
int flags; int flags;
int reserved; int reserved;
void (*invoke)(void *, ...); void (*invoke)(void *, ...);
struct { struct {
unsigned long int reserved; // NULL unsigned long int reserved; // NULL
unsigned long int size; // sizeof(struct Block_literal_1) unsigned long int size; // sizeof(struct Block_literal_1)
// optional helper functions // optional helper functions
void (*copy_helper)(void *dst, void *src); void (*copy_helper)(void *dst, void *src);
void (*dispose_helper)(void *src); void (*dispose_helper)(void *src);
} *descriptor; } *descriptor;
const char *types; const char *types;
}; };
// Helper structure // Helper structure
struct psy_block_byref_obj { struct psy_block_byref_obj {
void *isa; // uninitialized void *isa; // uninitialized
struct psy_block_byref_obj *forwarding; struct psy_block_byref_obj *forwarding;
int flags; //refcount; int flags; //refcount;
int size; int size;
void (*byref_keep)(struct psy_block_byref_obj *dst, struct psy_block_byref_obj *src); void (*byref_keep)(struct psy_block_byref_obj *dst, const struct psy_block_byref_obj *src);
void (*byref_dispose)(struct psy_block_byref_obj *); void (*byref_dispose)(struct psy_block_byref_obj *);
}; };
/* Certain field types require runtime assistance when being copied to the /* 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 * the other choices which are mutually exclusive. Only in a Block copy helper
* will one see BLOCK_FIELD_IS_BYREF. * 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); //printf("Copying %x to %x with flags %x\n", object, destAddr, flags);
// FIXME: Needs to be implemented // FIXME: Needs to be implemented
if(flags & BLOCK_FIELD_IS_WEAK) 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; const struct psy_block_byref_obj *src = object;
struct psy_block_byref_obj **dst = destAddr; struct psy_block_byref_obj **dst = destAddr;
/* I followed Apple's specs saying byref's "flags" field should /* I followed Apple's specs saying byref's "flags" field should
* represent the refcount but it still contains real flag, so this * represent the refcount but it still contains real flag, so this
* is a little hack... * is a little hack...
*/ */
if((src->flags & ~BLOCK_HAS_COPY_DISPOSE) == 0) if((src->flags & ~BLOCK_HAS_COPY_DISPOSE) == 0)
{ {
*dst = malloc(src->size); *dst = malloc(src->size);
memcpy(*dst, src, src->size); memcpy(*dst, src, src->size);
if (src->forwarding == src) if (src->forwarding == src)
{ {
(*dst)->forwarding = *dst; (*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; else *dst = (struct psy_block_byref_obj*)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 *src = (struct psy_block_literal*)object;
struct psy_block_literal **dst = destAddr; 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 src = object;
id *dst = destAddr; id *dst = destAddr;
*dst = [src retain]; *dst = [src retain];
} }
} }
} }
/* Similarly a compiler generated dispose helper needs to call back for each /* 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 * The same flags used in the copy helper should be used for each call
* generated to this function: * 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 // FIXME: Needs to be implemented
if(flags & BLOCK_FIELD_IS_WEAK) 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 *src =
(struct psy_block_byref_obj*)object;
src->flags--;
if((src->flags & ~BLOCK_HAS_COPY_DISPOSE) == 0) 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 = (struct psy_block_literal*)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 { struct StackBlockClass {
void *isa; // initialized to &_NSConcreteStackBlock or &_NSConcreteGlobalBlock void *isa; // initialized to &_NSConcreteStackBlock or &_NSConcreteGlobalBlock
int flags; int flags;
int reserved; int reserved;
void (*invoke)(void *, ...); void (*invoke)(void *, ...);
struct { struct {
unsigned long int reserved; // NULL unsigned long int reserved; // NULL
unsigned long int size; // sizeof(struct Block_literal_1) unsigned long int size; // sizeof(struct Block_literal_1)
// optional helper functions // optional helper functions
void (*copy_helper)(void *dst, void *src); void (*copy_helper)(void *dst, void *src);
void (*dispose_helper)(void *src); void (*dispose_helper)(void *src);
} *descriptor; } *descriptor;
const char *types; 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. // Copy a block to the heap if it's still on the stack or increments its retain count.
void *_Block_copy(void *src) void *_Block_copy(void *src)
{ {
struct StackBlockClass *self = src; struct StackBlockClass *self = src;
struct StackBlockClass *ret = self; 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 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->isa == &_NSConcreteStackBlock && self->flags & BLOCK_HAS_DESCRIPTOR)
{ {
if(self->reserved == 0) if(self->reserved == 0)
{ {
ret = malloc(self->descriptor->size); ret = malloc(self->descriptor->size);
memcpy(ret, self, self->descriptor->size); memcpy(ret, self, self->descriptor->size);
if(self->flags & BLOCK_HAS_COPY_DISPOSE) if(self->flags & BLOCK_HAS_COPY_DISPOSE)
self->descriptor->copy_helper(ret, self); self->descriptor->copy_helper(ret, self);
memcpy(self, ret, self->descriptor->size); 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. // 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 if(self->isa == &_NSConcreteStackBlock && // A Global block doesn't need to be released
self->flags & BLOCK_HAS_DESCRIPTOR && // Should always be true... 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 > 0) // If false, then it's not allocated on the heap, we won't release auto memory !
{ {
self->reserved--; self->reserved--;
if(self->reserved == 0) if(self->reserved == 0)
{ {
if(self->flags & BLOCK_HAS_COPY_DISPOSE) if(self->flags & BLOCK_HAS_COPY_DISPOSE)
self->descriptor->dispose_helper(self); self->descriptor->dispose_helper(self);
free(self); free(self);
} }
} }
} }
const char *_Block_get_types(void *blk) const char *_Block_get_types(void *blk)

@ -10,10 +10,10 @@
// that it doesn't impact the rest of the program. // that it doesn't impact the rest of the program.
#ifndef _GNU_SOURCE #ifndef _GNU_SOURCE
# define _GNU_SOURCE 1 # define _GNU_SOURCE 1
# include <unwind.h> # include "unwind.h"
# undef _GNU_SOURCE # undef _GNU_SOURCE
#else #else
# include <unwind.h> # include "unwind.h"
#endif #endif
typedef unsigned char *dw_eh_ptr_t; typedef unsigned char *dw_eh_ptr_t;

@ -1,6 +1,6 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <objc/runtime.h> #include "objc/runtime.h"
#include "class.h" #include "class.h"
#include "ivar.h" #include "ivar.h"

Loading…
Cancel
Save