3 Star 0 Fork 0

Gitee 极速下载 / gnustep-objective-c-runtime

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
此仓库是为了提升国内下载速度的镜像仓库,每日同步一次。 原始仓库: https://github.com/gnustep/libobjc2
克隆/下载
ivar.c 5.59 KB
一键复制 编辑 原始数据 按行查看 历史
David Chisnall 提交于 2023-02-19 14:11 . Remove Boehm GC support code.
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "objc/runtime.h"
#include "objc/objc-arc.h"
#include "class.h"
#include "visibility.h"
#include "gc_ops.h"
#include "legacy.h"
ptrdiff_t objc_alignof_type(const char *);
ptrdiff_t objc_sizeof_type(const char *);
PRIVATE void objc_compute_ivar_offsets(Class class)
{
if (class->ivars == NULL)
{
Class super_class = class_getSuperclass(class);
if (super_class != Nil)
{
class->instance_size = super_class->instance_size;
}
return;
}
if (class->ivars->size != sizeof(struct objc_ivar))
{
fprintf(stderr, "Downgrading ivar struct not yet implemented");
abort();
}
int i = 0;
/* If this class was compiled with support for late-bound ivars, the
* instance_size field will contain 0 - {the size of the instance variables
* declared for just this class}. The individual instance variable offset
* fields will then be the offsets from the start of the class, and so must
* have the size of the parent class prepended. */
if (class->instance_size <= 0)
{
Class super = class_getSuperclass(class);
long ivar_start = 0;
if (Nil != super)
{
if (super->instance_size <= 0)
{
objc_compute_ivar_offsets(super);
}
ivar_start = super->instance_size;
}
class->instance_size = ivar_start;
/* For each instance variable, we add the offset if required (it will be zero
* if this class is compiled with a static ivar layout). We then set the
* value of a global variable to the offset value.
*
* Any class compiled with support for the non-fragile ABI, but not actually
* using it, will export the ivar offset field as a symbol.
*
* Note that using non-fragile ivars breaks @defs(). If you need equivalent
* functionality, provide an alternative @interface with all variables
* declared @public.
*/
if (class->ivars)
{
// If the first instance variable had any alignment padding, then we need
// to discard it. We will recompute padding ourself later.
long next_ivar = ivar_start;
long last_offset = LONG_MIN;
long last_size = 0;
long last_computed_offset = -1;
size_t refcount_size = sizeof(uintptr_t);
for (i = 0 ; i < class->ivars->count ; i++)
{
struct objc_ivar *ivar = ivar_at_index(class->ivars, i);
// Clang 7 and 8 have a bug where the size of _Bool is encoded
// as 0, not 1. Silently fix this up when we see it.
if (ivar->size == 0 && ivar->type[0] == 'B')
{
ivar->size = 1;
}
// We are going to be allocating an extra word for the reference count
// in front of the object. This doesn't matter for aligment most of
// the time, but if we have an instance variable that is a vector type
// then we will need to ensure that we are properly aligned again.
long ivar_size = ivar->size;
// Bitfields have the same offset - the base of the variable
// that contains them. If we are in a bitfield, then we need
// to make sure that we don't add any displacement from the
// previous value.
if (*ivar->offset < last_offset + last_size)
{
*ivar->offset = last_computed_offset + (*ivar->offset - last_offset);
ivar_size = 0;
continue;
}
last_offset = *ivar->offset;
*ivar->offset = next_ivar;
last_computed_offset = *ivar->offset;
next_ivar += ivar_size;
last_size = ivar->size;
size_t align = ivarGetAlign(ivar);
if ((*ivar->offset + refcount_size) % align != 0)
{
long padding = align - ((*ivar->offset + refcount_size) % align);
*ivar->offset += padding;
class->instance_size += padding;
next_ivar += padding;
}
assert((*ivar->offset + sizeof(uintptr_t)) % ivarGetAlign(ivar) == 0);
class->instance_size += ivar_size;
}
#ifdef OLDABI_COMPAT
// If we have a legacy ivar list, update the offset in it too -
// code from older compilers may access this directly!
struct objc_class_gsv1* legacy = objc_legacy_class_for_class(class);
if (legacy)
{
for (i = 0 ; i < class->ivars->count ; i++)
{
legacy->ivars->ivar_list[i].offset = *ivar_at_index(class->ivars, i)->offset;
}
}
#endif
}
}
}
////////////////////////////////////////////////////////////////////////////////
// Public API functions
////////////////////////////////////////////////////////////////////////////////
void object_setIvar(id object, Ivar ivar, id value)
{
id *addr = (id*)((char*)object + ivar_getOffset(ivar));
switch (ivarGetOwnership(ivar))
{
case ownership_strong:
objc_storeStrong(addr, value);
break;
case ownership_weak:
objc_storeWeak(addr, value);
break;
case ownership_unsafe:
case ownership_invalid:
*addr = value;
break;
}
}
Ivar object_setInstanceVariable(id obj, const char *name, void *value)
{
Ivar ivar = class_getInstanceVariable(object_getClass(obj), name);
if (ivar_getTypeEncoding(ivar)[0] == '@')
{
object_setIvar(obj, ivar, *(id*)value);
}
else
{
size_t size = objc_sizeof_type(ivar_getTypeEncoding(ivar));
memcpy((char*)obj + ivar_getOffset(ivar), value, size);
}
return ivar;
}
id object_getIvar(id object, Ivar ivar)
{
id *addr = (id*)((char*)object + ivar_getOffset(ivar));
switch (ivarGetOwnership(ivar))
{
case ownership_strong:
return objc_retainAutoreleaseReturnValue(*addr);
case ownership_weak:
return objc_loadWeak(addr);
break;
case ownership_unsafe:
case ownership_invalid:
return *addr;
return nil;
}
}
Ivar object_getInstanceVariable(id obj, const char *name, void **outValue)
{
Ivar ivar = class_getInstanceVariable(object_getClass(obj), name);
if (NULL != outValue)
{
*outValue = (((char*)obj) + ivar_getOffset(ivar));
}
return ivar;
}
C/C++
1
https://gitee.com/mirrors/gnustep-objective-c-runtime.git
git@gitee.com:mirrors/gnustep-objective-c-runtime.git
mirrors
gnustep-objective-c-runtime
gnustep-objective-c-runtime
master

搜索帮助