Skip to content

Commit

Permalink
Add objc/blocks_private.h header to expose some internals of the bloc…
Browse files Browse the repository at this point in the history
…ks runtime

that are accessed by libdispatch. Also rename the relevant structs to be
compatible with the BlocksRuntime from compiler-rt.
  • Loading branch information
ngrewe committed Mar 11, 2012
1 parent c3e4ea1 commit f845df3
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 84 deletions.
1 change: 1 addition & 0 deletions GNUmakefile
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ ${LIBOBJC}_HEADER_FILES = \
Availability.h\
Object.h\
Protocol.h\
blocks_private.h\
blocks_runtime.h\
capabilities.h\
developer.h\
Expand Down
2 changes: 1 addition & 1 deletion block_to_imp.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ extern void __objc_block_trampoline_end_sret;

IMP imp_implementationWithBlock(void *block)
{
struct block_literal *b = block;
struct Block_layout *b = block;
void *start;
void *end;

Expand Down
76 changes: 10 additions & 66 deletions blocks_runtime.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Block descriptor flags.
* Block descriptor flags.
*/
enum block_flags
{
Expand Down Expand Up @@ -37,7 +37,7 @@ enum block_flags
* _Block_object_dispose(). These indicate the type of copy or dispose to
* perform.
*/
enum
enum
{
/**
* The value is of some id-like type, and should be copied as an
Expand All @@ -54,43 +54,23 @@ enum
* __block storage qualifier.
*/
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
};
#define IS_SET(x, y) ((x & y) == y)

/**
* Block descriptor that contains copy and dispose operations.
/*
* Include the block_descriptor_copydispose and block_literal definitions that
* are also made public under different names for use in libdispatch.
*/
struct block_descriptor_copydispose
{
/**
* Reserved for future use. Currently always 0.
*/
unsigned long int reserved;
/** Size of the block. */
unsigned long int size;
/**
* Copy function, generated by the compiler to help copy the block if it
* contains nontrivial copy operations.
*/
void (*copy_helper)(void *dst, void *src);
/**
* Dispose function, generated by the compiler to help copy the block if it
* contains nontrivial destructors.
*/
void (*dispose_helper)(void *src);
/**
* Objective-C type encoding of the block.
*/
const char *encoding;
};
#include "objc/blocks_private.h"

/**
* Block descriptor that does not contain copy and dispose helper functions.
*/
struct block_descriptor
struct Block_descriptor_basic
{
/**
* Reserved for future use, currently always 0.
Expand All @@ -104,42 +84,6 @@ struct block_descriptor
const char *encoding;
};

// Helper structure
struct block_literal
{
/**
* Class pointer. Always initialised to &_NSConcreteStackBlock for blocks
* that are created on the stack or &_NSConcreteGlobalBlock for blocks that
* are created in global storage.
*/
void *isa;
/**
* Flags. See the block_flags enumerated type for possible values.
*/
int flags;
/**
* Reserved - always initialised to 0 by the compiler. Used for the
* reference count in this implementation.
*/
int reserved;
/**
* The function that implements the block. The first argument is this
* structure, the subsequent arguments are the block's explicit parameters.
* If the BLOCK_USE_SRET flag is set, there is an additional hidden
* argument, which is a pointer to the space on the stack allocated to hold
* the return value.
*/
void (*invoke)(void *, ...);
/**
* The block's descriptor. This is either block_descriptor or
* block_descriptor_copydispose, depending on whether the
* BLOCK_HAS_COPY_DISPOSE flag is set.
*/
struct block_descriptor_copydispose *descriptor;
/**
* Block variables are appended to this structure.
*/
};

/**
* Structure used for on-stack variables that are referenced by blocks.
Expand Down
34 changes: 17 additions & 17 deletions blocks_runtime.m
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* Copyright (c) 2009 Remy Demarest
* Portions Copyright (c) 2009 David Chisnall
*
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
Expand All @@ -10,10 +10,10 @@
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
Expand Down Expand Up @@ -44,14 +44,14 @@
*/
const char *block_getType_np(void *b)
{
struct block_literal *block = b;
struct Block_layout *block = b;
if ((NULL == block) || !(block->flags & BLOCK_HAS_SIGNATURE))
{
return NULL;
}
if (!(block->flags & BLOCK_HAS_COPY_DISPOSE))
{
return ((struct block_descriptor*)block->descriptor)->encoding;
return ((struct Block_descriptor_basic*)block->descriptor)->encoding;
}
return block->descriptor->encoding;
}
Expand Down Expand Up @@ -121,7 +121,7 @@ void _Block_object_assign(void *destAddr, const void *object, const int flags)
struct block_byref_obj *src = (struct block_byref_obj *)object;
struct block_byref_obj **dst = destAddr;
src = src->forwarding;

if ((src->flags & BLOCK_REFCOUNT_MASK) == 0)
{
*dst = gc->malloc(src->size);
Expand Down Expand Up @@ -161,9 +161,9 @@ void _Block_object_assign(void *destAddr, const void *object, const int flags)
}
else if (IS_SET(flags, BLOCK_FIELD_IS_BLOCK))
{
struct block_literal *src = (struct block_literal*)object;
struct block_literal **dst = destAddr;
struct Block_layout *src = (struct Block_layout*)object;
struct Block_layout **dst = destAddr;

*dst = Block_copy(src);
}
else if (IS_SET(flags, BLOCK_FIELD_IS_OBJECT) &&
Expand Down Expand Up @@ -196,7 +196,7 @@ void _Block_object_dispose(const void *object, const int flags)
{
if (IS_SET(flags, BLOCK_FIELD_IS_BYREF))
{
struct block_byref_obj *src =
struct block_byref_obj *src =
(struct block_byref_obj*)object;
if (src->isa == _HeapBlockByRef)
{
Expand Down Expand Up @@ -228,7 +228,7 @@ void _Block_object_dispose(const void *object, const int flags)
}
else if (IS_SET(flags, BLOCK_FIELD_IS_BLOCK))
{
struct block_literal *src = (struct block_literal*)object;
struct Block_layout *src = (struct Block_layout*)object;
Block_release(src);
}
else if (IS_SET(flags, BLOCK_FIELD_IS_OBJECT) &&
Expand All @@ -248,12 +248,12 @@ void _Block_object_dispose(const void *object, const int flags)
void *_Block_copy(void *src)
{
if (NULL == src) { return NULL; }
struct block_literal *self = src;
struct block_literal *ret = self;
struct Block_layout *self = src;
struct Block_layout *ret = self;

extern void _NSConcreteStackBlock;
extern void _NSConcreteMallocBlock;

// If the block is Global, there's no need to copy it on the heap.
if(self->isa == &_NSConcreteStackBlock)
{
Expand Down Expand Up @@ -282,8 +282,8 @@ void _Block_object_dispose(const void *object, const int flags)
void _Block_release(void *src)
{
if (NULL == src) { return; }
struct block_literal *self = src;
struct Block_layout *self = src;

extern void _NSConcreteStackBlock;
extern void _NSConcreteMallocBlock;

Expand All @@ -305,6 +305,6 @@ void _Block_release(void *src)

PRIVATE void* block_load_weak(void *block)
{
struct block_literal *self = block;
struct Block_layout *self = block;
return (self->reserved) > 0 ? block : 0;
}
90 changes: 90 additions & 0 deletions objc/blocks_private.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
#ifndef __LIBOBJC_BLOCKS_PRIVATE_H_INCLUDED__
#define __LIBOBJC_BLOCKS_PRIVATE_H_INCLUDED__

/*
* This header file exposes some implementation details of the blocks runtime
* that are needed, e.g., by libdispatch.
*/


/**
* Block descriptor that contains copy and dispose operations.
*/
struct Block_descriptor
{
/**
* Reserved for future use. Currently always 0.
*/
unsigned long int reserved;
/** Size of the block. */
unsigned long int size;
/**
* Copy function, generated by the compiler to help copy the block if it
* contains nontrivial copy operations.
*/
void (*copy_helper)(void *dst, void *src);
/**
* Dispose function, generated by the compiler to help copy the block if it
* contains nontrivial destructors.
*/
void (*dispose_helper)(void *src);
/**
* Objective-C type encoding of the block.
*/
const char *encoding;
};

// Helper structure
struct Block_layout
{
/**
* Class pointer. Always initialised to &_NSConcreteStackBlock for blocks
* that are created on the stack or &_NSConcreteGlobalBlock for blocks that
* are created in global storage.
*/
void *isa;
/**
* Flags. See the block_flags enumerated type for possible values.
*/
int flags;
/**
* Reserved - always initialised to 0 by the compiler. Used for the
* reference count in this implementation.
*/
int reserved;
/**
* The function that implements the block. The first argument is this
* structure, the subsequent arguments are the block's explicit parameters.
* If the BLOCK_USE_SRET flag is set, there is an additional hidden
* argument, which is a pointer to the space on the stack allocated to hold
* the return value.
*/
void (*invoke)(void *, ...);
/**
* The block's descriptor. This is either Block_descriptor_basic or
* Block_descriptor, depending on whether the
* BLOCK_HAS_COPY_DISPOSE flag is set.
*/
struct Block_descriptor *descriptor;
/**
* Block variables are appended to this structure.
*/
};



#ifndef __OBJC_RUNTIME_INTERNAL__
/*
* Deprecated Block_basic datastructure needed by libdispatch
*/
struct Block_basic {
void *isa;
int Block_flags;
int Block_size;
void (*Block_invoke)(void *);
void (*Block_copy)(void *dst, void *src);
void (*Block_dispose)(void *);
};
#endif // __OBJC_RUNTIME_INTERNAL__
#endif //__LIBOBJC_BLOCKS_PRIVATE_H_INCLUDED__

0 comments on commit f845df3

Please sign in to comment.