From fc88037977dcc39dfd6d817c522cce01f5bfa024 Mon Sep 17 00:00:00 2001 From: Tom Hacohen Date: Mon, 9 Nov 2015 11:45:04 +0000 Subject: [PATCH] Eo: Migrate to the new syntax (Eo 4). The syntax is described in: https://phab.enlightenment.org/w/eo/ Summary: eo_do(obj, a_set(1)) -> a_set(obj, 1) eo_do_super(obj, CLASS, a_set(1)) -> a_set(eo_super(obj, CLASS), 1) eo_do_*_ret() set of functions are no longer needed. This is the first step, the next step would be to also fix up eo_add() which currently still uses the old syntax and is not 100% portable. @feature --- src/lib/eo/Eo.h | 136 +++++-------- src/lib/eo/eo.c | 422 ++++++++-------------------------------- src/lib/eo/eo_private.h | 7 +- src/lib/eo/eo_ptr_indirection.x | 21 +- 4 files changed, 154 insertions(+), 432 deletions(-) diff --git a/src/lib/eo/Eo.h b/src/lib/eo/Eo.h index cfabd74..a0b817c 100644 --- a/src/lib/eo/Eo.h +++ b/src/lib/eo/Eo.h @@ -99,6 +99,8 @@ extern "C" { * @{ */ +typedef struct _Eo_Object _Eo_Object; + /** * @typedef Eo * The basic Object type. @@ -452,7 +454,8 @@ EAPI Eina_Bool eo_shutdown(void); // to fetch internal function and object data at once typedef struct _Eo_Op_Call_Data { - Eo *obj; + Eo *eo_id; + _Eo_Object *obj; void *func; void *data; } Eo_Op_Call_Data; @@ -497,7 +500,7 @@ typedef struct _Eo_Call_Cache #endif // cache OP id, get real fct and object data then do the call -#define EO_FUNC_COMMON_OP(Name, DefRet) \ +#define EO_FUNC_COMMON_OP(Obj, Name, DefRet) \ static Eo_Call_Cache ___cache; /* static 0 by default */ \ Eo_Op_Call_Data ___call; \ if (EINA_UNLIKELY(___cache.op == EO_NOOP)) \ @@ -505,51 +508,65 @@ typedef struct _Eo_Call_Cache ___cache.op = _eo_api_op_id_get(EO_FUNC_COMMON_OP_FUNC(Name)); \ if (___cache.op == EO_NOOP) return DefRet; \ } \ - if (!_eo_call_resolve(#Name, &___call, &___cache, \ + if (!_eo_call_resolve((Eo *) Obj, #Name, &___call, &___cache, \ __FILE__, __LINE__)) return DefRet; \ _Eo_##Name##_func _func_ = (_Eo_##Name##_func) ___call.func; \ // to define an EAPI function -#define EO_FUNC_BODY(Name, Ret, DefRet) \ +#define _EO_FUNC_BODY(Name, ObjType, Ret, DefRet) \ Ret \ - Name(void) \ + Name(ObjType obj) \ { \ typedef Ret (*_Eo_##Name##_func)(Eo *, void *obj_data); \ Ret _r; \ - EO_FUNC_COMMON_OP(Name, DefRet); \ - _r = _func_(___call.obj, ___call.data); \ + EO_FUNC_COMMON_OP(obj, Name, DefRet); \ + _r = _func_(___call.eo_id, ___call.data); \ + _eo_call_end(&___call); \ return _r; \ } -#define EO_VOID_FUNC_BODY(Name) \ +#define _EO_VOID_FUNC_BODY(Name, ObjType) \ void \ - Name(void) \ + Name(ObjType obj) \ { \ typedef void (*_Eo_##Name##_func)(Eo *, void *obj_data); \ - EO_FUNC_COMMON_OP(Name, ); \ - _func_(___call.obj, ___call.data); \ + EO_FUNC_COMMON_OP(obj, Name, ); \ + _func_(___call.eo_id, ___call.data); \ + _eo_call_end(&___call); \ } -#define EO_FUNC_BODYV(Name, Ret, DefRet, Arguments, ...) \ +#define _EO_FUNC_BODYV(Name, ObjType, Ret, DefRet, Arguments, ...) \ Ret \ - Name(__VA_ARGS__) \ + Name(ObjType obj, __VA_ARGS__) \ { \ typedef Ret (*_Eo_##Name##_func)(Eo *, void *obj_data, __VA_ARGS__); \ Ret _r; \ - EO_FUNC_COMMON_OP(Name, DefRet); \ - _r = _func_(___call.obj, ___call.data, Arguments); \ + EO_FUNC_COMMON_OP(obj, Name, DefRet); \ + _r = _func_(___call.eo_id, ___call.data, Arguments); \ + _eo_call_end(&___call); \ return _r; \ } -#define EO_VOID_FUNC_BODYV(Name, Arguments, ...) \ +#define _EO_VOID_FUNC_BODYV(Name, ObjType, Arguments, ...) \ void \ - Name(__VA_ARGS__) \ + Name(ObjType obj, __VA_ARGS__) \ { \ typedef void (*_Eo_##Name##_func)(Eo *, void *obj_data, __VA_ARGS__); \ - EO_FUNC_COMMON_OP(Name, ); \ - _func_(___call.obj, ___call.data, Arguments); \ + EO_FUNC_COMMON_OP(obj, Name, ); \ + _func_(___call.eo_id, ___call.data, Arguments); \ + _eo_call_end(&___call); \ } +#define EO_FUNC_BODY(Name, Ret, DefRet) _EO_FUNC_BODY(Name, Eo *, Ret, DefRet) +#define EO_VOID_FUNC_BODY(Name) _EO_VOID_FUNC_BODY(Name, Eo *) +#define EO_FUNC_BODYV(Name, Ret, DefRet, Arguments, ...) _EO_FUNC_BODYV(Name, Eo *, Ret, DefRet, EO_FUNC_CALL(Arguments), __VA_ARGS__) +#define EO_VOID_FUNC_BODYV(Name, Arguments, ...) _EO_VOID_FUNC_BODYV(Name, Eo *, EO_FUNC_CALL(Arguments), __VA_ARGS__) + +#define EO_FUNC_BODY_CONST(Name, Ret, DefRet) _EO_FUNC_BODY(Name, const Eo *, Ret, DefRet) +#define EO_VOID_FUNC_BODY_CONST(Name) _EO_VOID_FUNC_BODY(Name, const Eo *) +#define EO_FUNC_BODYV_CONST(Name, Ret, DefRet, Arguments, ...) _EO_FUNC_BODYV(Name, const Eo *, Ret, DefRet, EO_FUNC_CALL(Arguments), __VA_ARGS__) +#define EO_VOID_FUNC_BODYV_CONST(Name, Arguments, ...) _EO_VOID_FUNC_BODYV(Name, const Eo *, EO_FUNC_CALL(Arguments), __VA_ARGS__) + #ifndef _WIN32 # define _EO_OP_API_ENTRY(a) (void*)a #else @@ -565,52 +582,15 @@ typedef struct _Eo_Call_Cache EAPI Eo_Op _eo_api_op_id_get(const void *api_func); // gets the real function pointer and the object data -EAPI Eina_Bool _eo_call_resolve(const char *func_name, Eo_Op_Call_Data *call, Eo_Call_Cache *callcache, const char *file, int line); +EAPI Eina_Bool _eo_call_resolve(Eo *obj, const char *func_name, Eo_Op_Call_Data *call, Eo_Call_Cache *callcache, const char *file, int line); -// start of eo_do barrier, gets the object pointer and ref it, put it on the stask -EAPI Eina_Bool _eo_do_start(const Eo *obj, const Eo_Class *cur_klass, Eina_Bool is_super, void *eo_stack); - -// end of the eo_do barrier, unref the obj, move the stack pointer -EAPI void _eo_do_end(void *eo_stack); +// end of the eo call barrier, unref the obj +EAPI void _eo_call_end(Eo_Op_Call_Data *call); // end of the eo_add. Calls finalize among others -EAPI Eo * _eo_add_end(void *eo_stack); - -// XXX: We cheat and make it const to indicate to the compiler that the value never changes -EAPI EINA_CONST void *_eo_stack_get(void); - -// eo object method calls batch, - -#define _eo_do_common(eoid, clsid, is_super, ...) \ - do { \ - _eo_do_start(eoid, clsid, is_super, _eo_stack_get()); \ - __VA_ARGS__; \ - _eo_do_end(_eo_stack_get()); \ - } while (0) +EAPI Eo * _eo_add_end(Eo *obj); -#define _eo_do_common_ret(eoid, clsid, is_super, ret_tmp, func) \ - ( \ - _eo_do_start(eoid, clsid, is_super, _eo_stack_get()), \ - ret_tmp = func, \ - _eo_do_end(_eo_stack_get()), \ - ret_tmp \ - ) - - -#define eo_do(eoid, ...) _eo_do_common(eoid, NULL, EINA_FALSE, __VA_ARGS__) - -#define eo_do_super(eoid, clsid, func) _eo_do_common(eoid, clsid, EINA_TRUE, func) - -#define eo_do_ret(eoid, ret_tmp, func) _eo_do_common_ret(eoid, NULL, EINA_FALSE, ret_tmp, func) - -#define eo_do_super_ret(eoid, clsid, ret_tmp, func) _eo_do_common_ret(eoid, clsid, EINA_TRUE, ret_tmp, func) - -#define eo_do_part(eoid, part_func, ...) \ - do { \ - Eo *__eo_part = eoid; \ - eo_do(eoid, __eo_part = part_func); \ - eo_do(__eo_part, __VA_ARGS__); \ - } while (0) +EAPI Eo *eo_super(const Eo *obj, const Eo_Class *cur_klass); /*****************************************************************************/ @@ -624,12 +604,11 @@ EAPI EINA_CONST void *_eo_stack_get(void); EAPI const Eo_Class *eo_class_get(const Eo *obj); #define _eo_add_common(klass, parent, is_ref, ...) \ - ( \ - _eo_do_start(_eo_add_internal_start(__FILE__, __LINE__, klass, parent, is_ref), \ - klass, EINA_FALSE, _eo_stack_get()) \ - , ##__VA_ARGS__, \ - (Eo *) _eo_add_end(_eo_stack_get()) \ - ) + ({ \ + Eo * const eoid = _eo_add_internal_start(__FILE__, __LINE__, klass, parent, is_ref); \ + __VA_ARGS__; \ + (Eo *) _eo_add_end(eoid); \ + }) /** * @def eo_add @@ -900,16 +879,12 @@ typedef void (*eo_key_data_free_func)(void *); * @brief Reference a pointer to an Eo object * @param wref the pointer to use for the weak ref * - * Same as eo_wref_add() with the difference that it call eo_do() itself. Checking - * for *wref NULL and making sure that you pass the right pointer to both side of - * eo_do(). - * * @see eo_weak_unref * @see eo_wref_add */ #define eo_weak_ref(wref) \ do { \ - if (*wref) eo_do(*wref, eo_wref_add(wref)); \ + if (*wref) eo_wref_add(*wref, wref); \ } while (0) /** @@ -917,17 +892,13 @@ typedef void (*eo_key_data_free_func)(void *); * @brief Unreference a pointer to an Eo object * @param wref the pointer to use for the weak unref * - * Same as eo_wref_del() with the difference that it call eo_do() itself. Checking - * for *wref NULL and making sure that you pass the right pointer to both side of - * eo_do(). - * * @see eo_weak_ref * @see eo_wref_del * @see eo_wref_del_safe */ #define eo_weak_unref(wref) \ do { \ - if (*wref) eo_do(*wref, eo_wref_del(wref)); \ + if (*wref) eo_wref_del(*wref, wref); \ } while (0) /** @@ -935,9 +906,6 @@ typedef void (*eo_key_data_free_func)(void *); * @brief Delete the weak reference passed. * @param wref the weak reference to free. * - * Same as eo_wref_del(), with the different that it's not called from eo_do() - * so you don't need to check if *wref is not NULL. - * * @see #eo_wref_del */ #define eo_wref_del_safe(wref) eo_weak_unref(wref) @@ -1018,8 +986,8 @@ EAPI const Eo_Event_Description *eo_base_legacy_only_event_description_get(const * * @see eo_event_callback_priority_add() */ -#define eo_event_callback_add(desc, cb, data) \ - eo_event_callback_priority_add(desc, \ +#define eo_event_callback_add(obj, desc, cb, data) \ + eo_event_callback_priority_add(obj, desc, \ EO_CALLBACK_PRIORITY_DEFAULT, cb, data) /** @@ -1032,8 +1000,8 @@ EAPI const Eo_Event_Description *eo_base_legacy_only_event_description_get(const * * @see eo_event_callback_array_priority_add() */ -#define eo_event_callback_array_add(array, data) \ - eo_event_callback_array_priority_add(array, \ +#define eo_event_callback_array_add(obj, array, data) \ + eo_event_callback_array_priority_add(obj, array, \ EO_CALLBACK_PRIORITY_DEFAULT, data) /** diff --git a/src/lib/eo/eo.c b/src/lib/eo/eo.c index 6baa7e9..7408f41 100644 --- a/src/lib/eo/eo.c +++ b/src/lib/eo/eo.c @@ -249,288 +249,69 @@ _eo_kls_itr_next(const _Eo_Class *orig_kls, const _Eo_Class *cur_klass, Eo_Op op /************************************ EO ************************************/ -// 1024 entries == 16k or 32k (32 or 64bit) for eo call stack. that's 1023 -// imbricated/recursive calls it can handle before barfing. i'd say that's ok -#define EO_CALL_STACK_DEPTH_MIN 1024 -#define EO_CALL_STACK_SHRINK_DROP (EO_CALL_STACK_DEPTH_MIN >> 1) +static const Eo_Class *_super_class = NULL; +static Eina_Spinlock _super_class_lock; -typedef struct _Eo_Stack_Frame +EAPI Eo * +eo_super(const Eo *obj, const Eo_Class *cur_klass) { - union { - _Eo_Object *obj; - const _Eo_Class *kls; - } o; - const _Eo_Class *cur_klass; - Eina_Bool is_obj : 1; -} Eo_Stack_Frame; - -#define EO_CALL_STACK_SIZE (EO_CALL_STACK_DEPTH_MIN * sizeof(Eo_Stack_Frame)) - -static Eina_TLS _eo_call_stack_key = 0; + /* FIXME: Switch to atomic operations intead of lock. */ + eina_spinlock_take(&_super_class_lock); + _super_class = cur_klass; -typedef struct _Eo_Call_Stack { - Eo_Stack_Frame *frames; - Eo_Stack_Frame *frame_ptr; - Eo_Stack_Frame *last_frame; - Eo_Stack_Frame *shrink_frame; -} Eo_Call_Stack; - -#define MEM_PAGE_SIZE 4096 - -static void * -_eo_call_stack_mem_alloc(size_t size) -{ -#ifdef HAVE_MMAP - // allocate eo call stack via mmped anon segment if on linux - more - // secure and safe. also gives page aligned memory allowing madvise - void *ptr; - size_t newsize; - newsize = MEM_PAGE_SIZE * ((size + MEM_PAGE_SIZE - 1) / - MEM_PAGE_SIZE); - ptr = mmap(NULL, newsize, PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANON, -1, 0); - if (ptr == MAP_FAILED) - { - ERR("eo call stack mmap failed."); - return NULL; - } - return ptr; -#else - //in regular cases just use malloc - return calloc(1, size); -#endif + return (Eo *) ((Eo_Id) obj | MASK_SUPER_TAG); } -#ifdef HAVE_MMAP -static void -_eo_call_stack_mem_resize(void **ptr EINA_UNUSED, size_t newsize, size_t size) -{ - if (newsize > size) - { - CRI("eo call stack overflow, abort."); - abort(); - } - return; // Do nothing, code for actual implementation in history. See commit message for details. -#else -static void -_eo_call_stack_mem_resize(void **ptr, size_t newsize, size_t size EINA_UNUSED) -{ - *ptr = realloc(*ptr, newsize); - if (!*ptr) - { - CRI("eo call stack resize failed, abort."); - abort(); - } -#endif -} - -#ifdef HAVE_MMAP -static void -_eo_call_stack_mem_free(void *ptr, size_t size) -{ - // free mmaped memory - munmap(ptr, size); -#else -static void -_eo_call_stack_mem_free(void *ptr, size_t size EINA_UNUSED) -{ - // free regular memory - free(ptr); -#endif -} - -static Eo_Call_Stack * -_eo_call_stack_create() +EAPI Eina_Bool +_eo_call_resolve(Eo *eo_id, const char *func_name, Eo_Op_Call_Data *call, Eo_Call_Cache *cache, const char *file, int line) { - Eo_Call_Stack *stack; - - stack = calloc(1, sizeof(Eo_Call_Stack)); - if (!stack) - return NULL; + const _Eo_Class *klass, *inputklass, *main_klass; + const _Eo_Class *cur_klass = NULL; + _Eo_Object *obj = NULL; + const op_type_funcs *func; + Eina_Bool is_obj; - stack->frames = _eo_call_stack_mem_alloc(EO_CALL_STACK_SIZE); - if (!stack->frames) + if (((Eo_Id) eo_id) & MASK_SUPER_TAG) { - free(stack); - return NULL; - } + const Eo_Class *tmp = _super_class; + _super_class = NULL; + eina_spinlock_release(&_super_class_lock); - // first frame is never used - stack->frame_ptr = stack->frames; - stack->last_frame = &stack->frames[EO_CALL_STACK_DEPTH_MIN - 1]; - stack->shrink_frame = stack->frames; - - return stack; -} - -static void -_eo_call_stack_free(void *ptr) -{ - Eo_Call_Stack *stack = (Eo_Call_Stack *) ptr; + eo_id = (Eo *) ((Eo_Id) eo_id & ~MASK_SUPER_TAG); - if (!stack) return; - - if (stack->frames) - _eo_call_stack_mem_free(stack->frames, EO_CALL_STACK_SIZE); - - free(stack); -} - -#ifdef HAVE_THREAD_SPECIFIER -static __thread Eo_Call_Stack *_eo_thread_stack = NULL; - -#define _EO_CALL_STACK_GET() ((_eo_thread_stack) ? _eo_thread_stack : (_eo_thread_stack = _eo_call_stack_create())) - -#else - -static Eo_Call_Stack *main_loop_stack = NULL; - -#define _EO_CALL_STACK_GET() ((EINA_LIKELY(eina_main_loop_is())) ? main_loop_stack : _eo_call_stack_get_thread()) - -static inline Eo_Call_Stack * -_eo_call_stack_get_thread(void) -{ - Eo_Call_Stack *stack = eina_tls_get(_eo_call_stack_key); - - if (stack) return stack; - - stack = _eo_call_stack_create(); - eina_tls_set(_eo_call_stack_key, stack); - - return stack; -} -#endif - -EAPI EINA_CONST void * -_eo_stack_get(void) -{ - return _EO_CALL_STACK_GET(); -} - -static inline void -_eo_call_stack_resize(Eo_Call_Stack *stack, Eina_Bool grow) -{ - size_t sz, next_sz; - int frame_offset; - - sz = stack->last_frame - stack->frames + 1; - if (grow) - next_sz = sz * 2; - else - next_sz = sz / 2; - frame_offset = stack->frame_ptr - stack->frames; - - _eo_call_stack_mem_resize((void **)&(stack->frames), - next_sz * sizeof(Eo_Stack_Frame), - sz * sizeof(Eo_Stack_Frame)); + cur_klass = _eo_class_pointer_get(tmp); + if (!cur_klass) + { + ERR("Invalid super class found. Aborting."); + return EINA_FALSE; + } + } - stack->frame_ptr = &stack->frames[frame_offset]; - stack->last_frame = &stack->frames[next_sz - 1]; + if (EINA_UNLIKELY(!eo_id)) + return EINA_FALSE; - if (next_sz == EO_CALL_STACK_DEPTH_MIN) - frame_offset = 0; - else - { - if (grow) - frame_offset = sz - EO_CALL_STACK_SHRINK_DROP; - else - frame_offset = (next_sz / 2) - EO_CALL_STACK_SHRINK_DROP; - } - stack->shrink_frame = &stack->frames[frame_offset]; -} + call->eo_id = eo_id; -static inline Eina_Bool -_eo_do_internal(const Eo *eo_id, const Eo_Class *cur_klass_id, - Eina_Bool is_super, Eo_Stack_Frame *fptr) -{ - fptr->is_obj = _eo_is_a_obj(eo_id); + is_obj = _eo_is_a_obj(eo_id); - /* If we are already in the same object context, we inherit info from it. */ - if (fptr->is_obj) + if (is_obj) { EO_OBJ_POINTER_RETURN_VAL(eo_id, _obj, EINA_FALSE); - fptr->o.obj = _obj; + obj = _obj; + klass = _obj->klass; + call->obj = obj; _eo_ref(_obj); } else { EO_CLASS_POINTER_RETURN_VAL(eo_id, _klass, EINA_FALSE); - fptr->o.kls = _klass; - } - - if (is_super) - { - EO_CLASS_POINTER_RETURN_VAL(cur_klass_id, cur_klass, EINA_FALSE); - fptr->cur_klass = cur_klass; - } - else - { - fptr->cur_klass = NULL; - } - - return EINA_TRUE; -} - -EAPI Eina_Bool -_eo_do_start(const Eo *eo_id, const Eo_Class *cur_klass_id, Eina_Bool is_super, void *eo_stack) -{ - Eina_Bool ret = EINA_TRUE; - Eo_Stack_Frame *fptr; - Eo_Call_Stack *stack = eo_stack; - - if (stack->frame_ptr == stack->last_frame) - _eo_call_stack_resize(stack, EINA_TRUE); - - fptr = stack->frame_ptr; - - fptr++; - - if (!_eo_do_internal(eo_id, cur_klass_id, is_super, fptr)) - { - fptr->o.obj = NULL; - fptr->cur_klass = NULL; - - ret = EINA_FALSE; + klass = _klass; + call->obj = NULL; + call->data = NULL; } - stack->frame_ptr++; + inputklass = main_klass = klass; - return ret; -} - -EAPI void -_eo_do_end(void *eo_stack) -{ - Eo_Stack_Frame *fptr; - Eo_Call_Stack *stack = eo_stack; - - fptr = stack->frame_ptr; - - if (fptr->is_obj && fptr->o.obj) - _eo_unref(fptr->o.obj); - - stack->frame_ptr--; - - if (fptr == stack->shrink_frame) - _eo_call_stack_resize(stack, EINA_FALSE); -} - -EAPI Eina_Bool -_eo_call_resolve(const char *func_name, Eo_Op_Call_Data *call, Eo_Call_Cache *cache, const char *file, int line) -{ - Eo_Stack_Frame *fptr; - const _Eo_Class *klass, *inputklass; - const op_type_funcs *func; - Eina_Bool is_obj; - - fptr = _EO_CALL_STACK_GET()->frame_ptr; - - if (EINA_UNLIKELY(!fptr->o.obj)) - return EINA_FALSE; - - is_obj = fptr->is_obj; - - inputklass = klass = (is_obj) ? fptr->o.obj->klass : fptr->o.kls; if (!cache->op) { @@ -542,9 +323,9 @@ _eo_call_resolve(const char *func_name, Eo_Op_Call_Data *call, Eo_Call_Cache *ca } /* If we have a current class, we need to itr to the next. */ - if (fptr->cur_klass) + if (cur_klass) { - func = _eo_kls_itr_next(klass, fptr->cur_klass, cache->op); + func = _eo_kls_itr_next(klass, cur_klass, cache->op); if (!func) goto end; @@ -568,13 +349,7 @@ _eo_call_resolve(const char *func_name, Eo_Op_Call_Data *call, Eo_Call_Cache *ca call->func = func->func; if (is_obj) { - call->obj = (Eo *) fptr->o.obj->header.id; - call->data = (char *)fptr->o.obj + cache->off[i].off; - } - else - { - call->obj = _eo_class_id_get(inputklass); - call->data = NULL; + call->data = (char *) obj + cache->off[i].off; } return EINA_TRUE; } @@ -593,17 +368,11 @@ _eo_call_resolve(const char *func_name, Eo_Op_Call_Data *call, Eo_Call_Cache *ca if (is_obj) { - call->obj = (Eo *) fptr->o.obj->header.id; - call->data = _eo_data_scope_get(fptr->o.obj, func->src); - } - else - { - call->obj = _eo_class_id_get(klass); - call->data = NULL; + call->data = _eo_data_scope_get(obj, func->src); } # if EO_CALL_CACHE_SIZE > 0 - if (!fptr->cur_klass) + if (!cur_klass) { # if EO_CALL_CACHE_SIZE > 1 const int slot = cache->next_slot; @@ -612,7 +381,7 @@ _eo_call_resolve(const char *func_name, Eo_Op_Call_Data *call, Eo_Call_Cache *ca # endif cache->index[slot].klass = (const void *)inputklass; cache->entry[slot].func = (const void *)func; - cache->off[slot].off = (int)((long)((char *)call->data - (char *)fptr->o.obj)); + cache->off[slot].off = (int)((long)((char *)call->data - (char *)obj)); # if EO_CALL_CACHE_SIZE > 1 cache->next_slot = (slot + 1) % EO_CALL_CACHE_SIZE; # endif @@ -636,7 +405,7 @@ end: { Eina_List *itr; Eo *emb_obj_id; - EINA_LIST_FOREACH(((_Eo_Object *) fptr->o.obj)->composite_objects, itr, emb_obj_id) + EINA_LIST_FOREACH(obj->composite_objects, itr, emb_obj_id) { _Eo_Object *emb_obj = _eo_obj_pointer_get((Eo_Id)emb_obj_id); @@ -649,7 +418,8 @@ end: if (EINA_LIKELY(func->func && func->src)) { - call->obj = _eo_id_get(emb_obj); + call->eo_id = _eo_id_get(emb_obj); + call->obj = obj; /* FIXME-eo4: Hack, we retain the previous object so we unref it... */ call->func = func->func; call->data = _eo_data_scope_get(emb_obj, func->src); @@ -659,15 +429,12 @@ end: } { - const _Eo_Class *main_klass; - main_klass = (is_obj) ? fptr->o.obj->klass : fptr->o.kls; - /* If it's a do_super call. */ - if (fptr->cur_klass) + if (cur_klass) { ERR("in %s:%d: func '%s' (%d) could not be resolved for class '%s' for super of '%s'.", file, line, func_name, cache->op, main_klass->desc->name, - fptr->cur_klass->desc->name); + cur_klass->desc->name); } else { @@ -679,6 +446,15 @@ end: return EINA_FALSE; } +EAPI void +_eo_call_end(Eo_Op_Call_Data *call) +{ + if (EINA_LIKELY(!!call->obj)) + { + _eo_unref(call->obj); + } +} + static inline Eina_Bool _eo_api_func_equal(const void *api_func1, const void *api_func2) { @@ -882,20 +658,19 @@ _eo_add_internal_start(const char *file, int line, const Eo_Class *klass_id, Eo _eo_ref(obj); - eo_do(eo_id, eo_parent_set(parent_id)); + eo_parent_set(eo_id, parent_id); /* If there's a parent. Ref. Eo_add should return an object with either a * parent ref, or with the lack of, just a ref. */ { - Eo *parent_tmp; - if (ref && eo_do_ret(eo_id, parent_tmp, eo_parent_get())) + if (ref && eo_parent_get(eo_id)) { _eo_ref(obj); } } /* eo_id can change here. Freeing is done on the resolved object. */ - eo_do(eo_id, eo_id = eo_constructor()); + eo_id = eo_constructor(eo_id); if (!eo_id) { ERR("Object of class '%s' - Error while constructing object", @@ -909,28 +684,20 @@ _eo_add_internal_start(const char *file, int line, const Eo_Class *klass_id, Eo } static Eo * -_eo_add_internal_end(Eo *eo_id, Eo_Call_Stack *stack) +_eo_add_internal_end(Eo *eo_id, Eo *finalized_id) { - Eo_Stack_Frame *fptr; - - fptr = stack->frame_ptr; - - if (EINA_UNLIKELY(!fptr->o.obj)) - { - ERR("Corrupt call stack, shouldn't happen, please report!"); - return NULL; - } + EO_OBJ_POINTER_RETURN_VAL(eo_id, obj, NULL); - if (!fptr->o.obj->condtor_done) + if (!obj->condtor_done) { - const _Eo_Class *klass = fptr->o.obj->klass; + const _Eo_Class *klass = obj->klass; ERR("Object of class '%s' - Not all of the object constructors have been executed.", klass->desc->name); goto cleanup; } - if (!eo_id) + if (!finalized_id) { // XXX: Given EFL usage of objects, construction is a perfectly valid thing // to do. we shouldn't complain about it as handling a NULL obj creation is @@ -946,24 +713,24 @@ _eo_add_internal_end(Eo *eo_id, Eo_Call_Stack *stack) goto cleanup; } - fptr->o.obj->finalized = EINA_TRUE; + obj->finalized = EINA_TRUE; - _eo_unref(fptr->o.obj); + _eo_unref(obj); return (Eo *)eo_id; cleanup: - _eo_unref(fptr->o.obj); - eo_del((Eo *) fptr->o.obj->header.id); + _eo_unref(obj); + eo_del((Eo *) obj->header.id); return NULL; } EAPI Eo * -_eo_add_end(void *eo_stack) +_eo_add_end(Eo *eo_id) { - Eo *ret = eo_finalize(); - ret = _eo_add_internal_end(ret, eo_stack); - _eo_do_end(eo_stack); + Eo *ret = eo_finalize(eo_id); + ret = _eo_add_internal_end(eo_id, ret); + return ret; } @@ -1552,10 +1319,9 @@ eo_unref(const Eo *obj_id) EAPI void eo_del(const Eo *obj) { - Eo *parent_tmp; - if (eo_do_ret(obj, parent_tmp, eo_parent_get())) + if (eo_parent_get((Eo *) obj)) { - eo_do(obj, eo_parent_set(NULL)); + eo_parent_set((Eo *) obj, NULL); } else { @@ -1800,6 +1566,12 @@ eo_init(void) return EINA_FALSE; } + if (!eina_spinlock_new(&_super_class_lock)) + { + EINA_LOG_ERR("Could not init lock."); + return EINA_FALSE; + } + eina_magic_string_static_set(EO_EINA_MAGIC, EO_EINA_MAGIC_STR); eina_magic_string_static_set(EO_FREED_EINA_MAGIC, EO_FREED_EINA_MAGIC_STR); @@ -1825,27 +1597,6 @@ eo_init(void) /* bootstrap EO_CLASS_CLASS */ (void) EO_ABSTRACT_CLASS_CLASS; - if (_eo_call_stack_key != 0) - WRN("_eo_call_stack_key already set, this should not happen."); - else - { - if (!eina_tls_cb_new(&_eo_call_stack_key, _eo_call_stack_free)) - { - EINA_LOG_ERR("Could not create TLS key for call stack."); - return EINA_FALSE; - - } - } - -#ifndef HAVE_THREAD_SPECIFIER - main_loop_stack = _eo_call_stack_create(); - if (!main_loop_stack) - { - EINA_LOG_ERR("Could not alloc eo call stack."); - return EINA_FALSE; - } -#endif - return EINA_TRUE; } @@ -1873,15 +1624,10 @@ eo_shutdown(void) eina_hash_free(_ops_storage); + eina_spinlock_free(&_super_class_lock); eina_spinlock_free(&_ops_storage_lock); eina_spinlock_free(&_eo_class_creation_lock); - if (_eo_call_stack_key != 0) - { - eina_tls_free(_eo_call_stack_key); - _eo_call_stack_key = 0; - } - _eo_free_ids_tables(); eina_log_domain_unregister(_eo_log_dom); diff --git a/src/lib/eo/eo_private.h b/src/lib/eo/eo_private.h index 869745c..3ee4134 100644 --- a/src/lib/eo/eo_private.h +++ b/src/lib/eo/eo_private.h @@ -61,7 +61,6 @@ extern int _eo_log_dom; typedef uintptr_t Eo_Id; typedef struct _Eo_Class _Eo_Class; -typedef struct _Eo_Object _Eo_Object; typedef struct _Eo_Header Eo_Header; /* Retrieves the pointer to the object from the id */ @@ -214,11 +213,11 @@ _eo_del_internal(const char *file, int line, _Eo_Object *obj) const _Eo_Class *klass = obj->klass; - eo_do(_eo_id_get(obj), eo_event_callback_call(EO_BASE_EVENT_DEL, NULL)); + eo_event_callback_call(_eo_id_get(obj), EO_BASE_EVENT_DEL, NULL); _eo_condtor_reset(obj); - eo_do(_eo_id_get(obj), eo_destructor()); + eo_destructor(_eo_id_get(obj)); if (!obj->condtor_done) { @@ -232,7 +231,7 @@ _eo_del_internal(const char *file, int line, _Eo_Object *obj) Eo *emb_obj; EINA_LIST_FOREACH_SAFE(obj->composite_objects, itr, itr_n, emb_obj) { - eo_do(_eo_id_get(obj), eo_composite_detach(emb_obj)); + eo_composite_detach(_eo_id_get(obj), emb_obj); } } diff --git a/src/lib/eo/eo_ptr_indirection.x b/src/lib/eo/eo_ptr_indirection.x index 2faae75..0e6ef34 100644 --- a/src/lib/eo/eo_ptr_indirection.x +++ b/src/lib/eo/eo_ptr_indirection.x @@ -57,14 +57,14 @@ * it to the fifo. */ -/* most significant bit is kept to tag Eo_Id with 1 */ #if SIZEOF_UINTPTR_T == 4 /* 32 bits */ # define BITS_MID_TABLE_ID 5 # define BITS_TABLE_ID 5 # define BITS_ENTRY_ID 12 -# define BITS_GENERATION_COUNTER 9 -# define REF_TAG_SHIFT 31 +# define BITS_GENERATION_COUNTER 8 +# define REF_TAG_SHIFT 30 +# define SUPER_TAG_SHIF 31 # define DROPPED_TABLES 0 # define DROPPED_ENTRIES 4 typedef int16_t Table_Index; @@ -74,8 +74,9 @@ typedef uint16_t Generation_Counter; # define BITS_MID_TABLE_ID 11 # define BITS_TABLE_ID 11 # define BITS_ENTRY_ID 12 -# define BITS_GENERATION_COUNTER 29 -# define REF_TAG_SHIFT 63 +# define BITS_GENERATION_COUNTER 28 +# define REF_TAG_SHIFT 62 +# define SUPER_TAG_SHIFT 63 # define DROPPED_TABLES 2 # define DROPPED_ENTRIES 3 typedef int16_t Table_Index; @@ -101,6 +102,15 @@ typedef uint32_t Generation_Counter; #define MASK_ENTRY_ID ((1 << BITS_ENTRY_ID) - 1) #define MASK_GENERATIONS (MAX_GENERATIONS - 1) #define MASK_OBJ_TAG (((Eo_Id) 1) << (REF_TAG_SHIFT)) +/* When we have EO_ID use the highest bit. + When we don't have EO_ID, we can repurpose the lowest bit, because allocation + is at least 8 byte aligned. + XXX: If this is ever not the case, we need to allocate from a mempool and ensure it, or find another trick. */ +#ifdef HAVE_EO_ID +# define MASK_SUPER_TAG (((Eo_Id) 1) << (SUPER_TAG_SHIFT)) +#else +# define MASK_SUPER_TAG ((Eo_Id) 1) +#endif /* This only applies to classes. Used to artificially enlarge the class ids * to reduce the likelihood of a clash with normal integers. */ @@ -417,7 +427,6 @@ _eo_id_allocate(const _Eo_Object *obj) (entry - _current_table->entries), entry->generation); #else - Eo_Id ret = 0x1; (void) obj; return MASK_OBJ_TAG; #endif -- 2.7.4