Hi, This broke make check (I fixed it now).
Note that this patch probably should not have been merged as a single commit, as the Phab Diff contains multiple patches. Best regards, On Tue, Jan 16, 2018 at 5:50 PM, Jean Guyomarc'h <j...@guyomarch.bzh> wrote: > raster pushed a commit to branch master. > > http://git.enlightenment.org/core/efl.git/commit/?id= > 34d9f2070696027199a56cb621c0526ea1430e8f > > commit 34d9f2070696027199a56cb621c0526ea1430e8f > Author: Jean Guyomarc'h <j...@guyomarch.bzh> > Date: Tue Jan 16 14:58:38 2018 +0900 > > eina: remove usless newline > > Summary: > ecore_evas: remove debug > > eina: unregister log level when done with > > Fixes a constant memory leak. > > eina: introduce EINA_HOT and EINA_COLD > > These attributes respectivelly expand to __attribute__ ((hot)) and > __attribute__ ((cold)) when available. They allow to mark functions are > being hot/cold (frequently used or not) as well as to qualify labels > within a function (likely/unlikely branches). > > eo: speed-up generated calls by removing call cache > > The call cache needed to by thread-local, to avoid concurrency issues. > Problem with TLS is that is adds an extra overhead, which appears to be > greater than the optimization the cache provides. > > Op is naturally atomic, because it is an unsigned integer. As such, it > cannot be tempered with while another thread is reading it. When > entering the generated function, the first operation done is reading > 'op'. If we have concurrency, we will have access sequences returning > either EFL_NOOP or a VALID op, because 'op' is not set until the very > end of the function, when everything has been computed. As such, we now > use the 'op' atomic integer to instore a lock-free/wait-free mechanism, > which allows to drop the TLS nature of the cache, speeding up the > access > to the cache, and therefore making functions execute faster. > > We don't test anymore the generation count. This can be put as a > limitation. If means that if you call efl_object_shutdown() and > re-initialize it later with different data, opcodes will be invalid. > I am not sure there is any usecase for this to ever happen. > We could move all the caches in a dedicated section, that can be > overwritten after a call to efl_object_shutdown(), but I am not sure it > will be very portable. > > Benchmark: mean over 3 executions of > ELM_TEST_AUTOBOUNCE=100 time elementary_test -to genlist > > ``` > BEFORE AFTER > ------------------------------------------------------------ > time (ns) 11114111647.0 9147676220.0 > frames 2872.3333333333335 2904.6666666666665 > time per frame (ns) 3869364.6666666665 3149535.3333333335 > user time (s) 11.096666666666666 9.22 > cpu (%) 22.666666666666668 18.333333333333332 > ``` > > Ref T6580 > > Reviewers: raster, cedric > > Subscribers: cedric, jpeg > > Maniphest Tasks: T6580 > > Differential Revision: https://phab.enlightenment.org/D5738 > --- > src/lib/ecore_evas/ecore_evas_private.h | 2 +- > src/lib/eina/eina_cow.c | 1 + > src/lib/eina/eina_safepointer.c | 2 +- > src/lib/eina/eina_types.h | 8 +++++ > src/lib/eo/Eo.h | 56 +++++++---------------------- > src/lib/eo/eo.c | 64 > ++++++--------------------------- > 6 files changed, 33 insertions(+), 100 deletions(-) > > diff --git a/src/lib/ecore_evas/ecore_evas_private.h > b/src/lib/ecore_evas/ecore_evas_private.h > index 7b83589347..13002402a4 100644 > --- a/src/lib/ecore_evas/ecore_evas_private.h > +++ b/src/lib/ecore_evas/ecore_evas_private.h > @@ -347,7 +347,7 @@ struct _Ecore_Evas > } delayed; > > int refcount; > -#define ECORE_EVAS_ASYNC_RENDER_DEBUG 1 /* TODO: remove me */ > +//#define ECORE_EVAS_ASYNC_RENDER_DEBUG 1 /* TODO: remove me */ > #ifdef ECORE_EVAS_ASYNC_RENDER_DEBUG > double async_render_start; > #endif > diff --git a/src/lib/eina/eina_cow.c b/src/lib/eina/eina_cow.c > index 73a65e5f30..8ec86cfd79 100644 > --- a/src/lib/eina/eina_cow.c > +++ b/src/lib/eina/eina_cow.c > @@ -320,6 +320,7 @@ eina_cow_init(void) > Eina_Bool > eina_cow_shutdown(void) > { > + eina_log_domain_unregister(_eina_cow_log_dom); > eina_mempool_del(gc_pool); > return EINA_TRUE; > } > diff --git a/src/lib/eina/eina_safepointer.c b/src/lib/eina/eina_ > safepointer.c > index 1a19f851c7..8f9d4b62a9 100644 > --- a/src/lib/eina/eina_safepointer.c > +++ b/src/lib/eina/eina_safepointer.c > @@ -370,7 +370,7 @@ eina_safepointer_init(void) > > DBG("entry[Size, Align] = { %zu, %u }", > sizeof (Eina_Memory_Entry), eina_mempool_alignof(sizeof > (Eina_Memory_Entry))); > - DBG("table[Size, Align] = { %zu, %u }\n", > + DBG("table[Size, Align] = { %zu, %u }", > sizeof (Eina_Memory_Table), eina_mempool_alignof(sizeof > (Eina_Memory_Table))); > > return EINA_TRUE; > diff --git a/src/lib/eina/eina_types.h b/src/lib/eina/eina_types.h > index 94e6ebc6f3..3d15a3f42d 100644 > --- a/src/lib/eina/eina_types.h > +++ b/src/lib/eina/eina_types.h > @@ -184,6 +184,14 @@ > # define EINA_PURE > # endif > > +# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) > +# define EINA_HOT __attribute__ ((hot)) > +# define EINA_COLD __attribute__ ((cold)) > +# else > +# define EINA_HOT > +# define EINA_COLD > +# endif > + > # if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4) > # if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 3) > # define EINA_PRINTF(fmt, arg) __attribute__((__format__ > (__gnu_printf__, fmt, arg))) > diff --git a/src/lib/eo/Eo.h b/src/lib/eo/Eo.h > index 3ea20ec2ff..8b489ab72a 100644 > --- a/src/lib/eo/Eo.h > +++ b/src/lib/eo/Eo.h > @@ -1159,37 +1159,6 @@ typedef struct _Efl_Object_Op_Call_Data > void *extn4; // for future use to avoid ABI issues > } Efl_Object_Op_Call_Data; > > -#define EFL_OBJECT_CALL_CACHE_SIZE 1 > - > -typedef struct _Efl_Object_Call_Cache_Index > -{ > - const void *klass; > -} Efl_Object_Call_Cache_Index; > - > -typedef struct _Efl_Object_Call_Cache_Entry > -{ > - const void *func; > -} Efl_Object_Call_Cache_Entry; > - > -typedef struct _Efl_Object_Call_Cache_Off > -{ > - int off; > -} Efl_Object_Call_Cache_Off; > - > -typedef struct _Efl_Object_Call_Cache > -{ > -#if EFL_OBJECT_CALL_CACHE_SIZE > 0 > - Efl_Object_Call_Cache_Index index[EFL_OBJECT_CALL_CACHE_SIZE]; > - Efl_Object_Call_Cache_Entry entry[EFL_OBJECT_CALL_CACHE_SIZE]; > - Efl_Object_Call_Cache_Off off [EFL_OBJECT_CALL_CACHE_SIZE]; > -# if EFL_OBJECT_CALL_CACHE_SIZE > 1 > - int next_slot; > -# endif > -#endif > - Efl_Object_Op op; > - unsigned int generation; > -} Efl_Object_Call_Cache; > - > // to pass the internal function call to EFL_FUNC_BODY (as Func parameter) > #define EFL_FUNC_CALL(...) __VA_ARGS__ > > @@ -1205,17 +1174,18 @@ typedef struct _Efl_Object_Call_Cache > # define EFL_FUNC_TLS __thread > #endif > > + > // cache OP id, get real fct and object data then do the call > #define EFL_FUNC_COMMON_OP(Obj, Name, DefRet) \ > - static EFL_FUNC_TLS Efl_Object_Call_Cache ___cache; /* static 0 by > default */ \ > + static Efl_Object_Op ___op; /* static 0 by default */ \ > Efl_Object_Op_Call_Data ___call; \ > _Eo_##Name##_func _func_; \ > - if (EINA_UNLIKELY((___cache.op == EFL_NOOP) || \ > - (___cache.generation != > _efl_object_init_generation))) \ > + if (EINA_UNLIKELY(___op == EFL_NOOP)) \ > goto __##Name##_op_create; /* yes a goto - see below */ \ > - __##Name##_op_create_done: \ > - if (!_efl_object_call_resolve((Eo *) Obj, #Name, &___call, &___cache, \ > - __FILE__, __LINE__)) goto > __##Name##_failed; \ > + __##Name##_op_create_done: EINA_HOT; \ > + if (EINA_UNLIKELY(!_efl_object_call_resolve( \ > + (Eo *) Obj, #Name, &___call, ___op, __FILE__, __LINE__))) \ > + goto __##Name##_failed; \ > _func_ = (_Eo_##Name##_func) ___call.func; > > // This looks ugly with gotos BUT it moves rare "init" handling code > @@ -1227,13 +1197,11 @@ typedef struct _Efl_Object_Call_Cache > // of the cacheline that was already fetched should yield better cache > // hits. > #define EFL_FUNC_COMMON_OP_END(Obj, Name, DefRet, ErrorCase) \ > -__##Name##_op_create: \ > - if (EINA_UNLIKELY(___cache.op != EFL_NOOP)) memset(&___cache, 0, > sizeof(___cache)); \ > - ___cache.op = _efl_object_op_api_id_get(EFL_FUNC_COMMON_OP_FUNC(Name), > Obj, #Name, __FILE__, __LINE__); \ > - if (___cache.op == EFL_NOOP) goto __##Name##_failed; \ > - ___cache.generation = _efl_object_init_generation; \ > +__##Name##_op_create: EINA_COLD; \ > + ___op = _efl_object_op_api_id_get(EFL_FUNC_COMMON_OP_FUNC(Name), Obj, > #Name, __FILE__, __LINE__); \ > + if (EINA_UNLIKELY(___op == EFL_NOOP)) goto __##Name##_failed; \ > goto __##Name##_op_create_done; \ > -__##Name##_failed: \ > +__##Name##_failed: EINA_COLD; \ > ErrorCase \ > return DefRet; > #define _EFL_OBJECT_API_BEFORE_HOOK > @@ -1335,7 +1303,7 @@ EAPI Efl_Object_Op _efl_object_api_op_id_get(const > void *api_func) EINA_DEPRECAT > EAPI Efl_Object_Op _efl_object_op_api_id_get(const void *api_func, const > Eo *obj, const char *api_func_name, const char *file, int line) > EINA_ARG_NONNULL(1, 2, 3, 4) EINA_WARN_UNUSED_RESULT; > > // gets the real function pointer and the object data > -EAPI Eina_Bool _efl_object_call_resolve(Eo *obj, const char *func_name, > Efl_Object_Op_Call_Data *call, Efl_Object_Call_Cache *callcache, const char > *file, int line); > +EAPI Eina_Bool _efl_object_call_resolve(Eo *obj, const char *func_name, > Efl_Object_Op_Call_Data *call, Efl_Object_Op op, const char *file, int > line); > > // end of the eo call barrier, unref the obj > EAPI void _efl_object_call_end(Efl_Object_Op_Call_Data *call); > diff --git a/src/lib/eo/eo.c b/src/lib/eo/eo.c > index 50df250acf..0db34fc35c 100644 > --- a/src/lib/eo/eo.c > +++ b/src/lib/eo/eo.c > @@ -439,15 +439,14 @@ efl_cast(const Eo *eo_id, const Efl_Class *cur_klass) > } > > EAPI Eina_Bool > -_efl_object_call_resolve(Eo *eo_id, const char *func_name, > Efl_Object_Op_Call_Data *call, Efl_Object_Call_Cache *cache, const char > *file, int line) > +_efl_object_call_resolve(Eo *eo_id, const char *func_name, > Efl_Object_Op_Call_Data *call, Efl_Object_Op op, const char *file, int line) > { > - const _Efl_Class *klass, *inputklass, *main_klass; > + const _Efl_Class *klass, *main_klass; > const _Efl_Class *cur_klass = NULL; > _Eo_Object *obj = NULL; > const Eo_Vtable *vtable = NULL; > const op_type_funcs *func; > Eina_Bool is_obj; > - Eina_Bool is_override = EINA_FALSE; > Eina_Bool super = EINA_TRUE; > > if (EINA_UNLIKELY(!eo_id)) return EINA_FALSE; > @@ -456,14 +455,13 @@ _efl_object_call_resolve(Eo *eo_id, const char > *func_name, Efl_Object_Op_Call_Da > > is_obj = _eo_is_a_obj(eo_id); > > - if (is_obj) > + if (EINA_LIKELY(is_obj == EINA_TRUE)) > { > EO_OBJ_POINTER_RETURN_VAL_PROXY(eo_id, _obj, EINA_FALSE); > > obj = _obj; > klass = _obj->klass; > vtable = EO_VTABLE(obj); > - is_override = _obj_is_override(obj); > if (EINA_UNLIKELY(_obj->cur_klass != NULL)) > { > // YES this is a goto with a label to return. this is a > @@ -485,9 +483,7 @@ obj_super_back: > } > ok_klass_back: > > - inputklass = main_klass = klass; > - > - if (!cache->op) goto err_cache_op; > + main_klass = klass; > > /* If we have a current class, we need to itr to the next. */ > if (cur_klass) > @@ -499,30 +495,7 @@ ok_klass_back: > } > else > { > -# if EFL_OBJECT_CALL_CACHE_SIZE > 0 > - if (!is_override) > - { > -# if EFL_OBJECT_CALL_CACHE_SIZE > 1 > - int i; > - > - for (i = 0; i < EFL_OBJECT_CALL_CACHE_SIZE; i++) > -# else > - const int i = 0; > -# endif > - { > - if ((const void *)inputklass == cache->index[i].klass) > - { > - func = (const op_type_funcs *)cache->entry[i].func; > - call->func = func->func; > - if (is_obj) > - call->data = (char *)obj + cache->off[i].off; > - if (EINA_UNLIKELY(!call->func)) goto err_cache_op; > - return EINA_TRUE; > - } > - } > - } > -#endif > - func = _vtable_func_get(vtable, cache->op); > + func = _vtable_func_get(vtable, op); > // this is not very likely to happen - but may if its an invalid > // call or a composite object, but either way, it's not very > likely > // so make it a goto to save on instruction cache > @@ -536,22 +509,6 @@ ok_cur_klass_back: > > if (is_obj) call->data = _efl_data_scope_get(obj, func->src); > > -# if EFL_OBJECT_CALL_CACHE_SIZE > 0 > - if (!cur_klass && !is_override) > - { > -# if EFL_OBJECT_CALL_CACHE_SIZE > 1 > - const int slot = cache->next_slot; > -# else > - const int slot = 0; > -# 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 *)obj)); > -# if EFL_OBJECT_CALL_CACHE_SIZE > 1 > - cache->next_slot = (slot + 1) % EFL_OBJECT_CALL_CACHE_SIZE; > -# endif > - } > -#endif > return EINA_TRUE; > } > > @@ -570,7 +527,7 @@ end: > EO_OBJ_POINTER_PROXY(emb_obj_id, emb_obj); > if (EINA_UNLIKELY(!emb_obj)) continue; > > - func = _vtable_func_get(EO_VTABLE(emb_obj), cache->op); > + func = _vtable_func_get(EO_VTABLE(emb_obj), op); > if (func == NULL) goto composite_continue; > > if (EINA_LIKELY(func->func && func->src)) > @@ -594,7 +551,7 @@ composite_continue: > 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, > + file, line, func_name, op, main_klass->desc->name, > cur_klass->desc->name); > goto err; > } > @@ -602,7 +559,7 @@ composite_continue: > { > /* we should not be able to take this branch */ > ERR("in %s:%d: func '%s' (%d) could not be resolved for class > '%s'.", > - file, line, func_name, cache->op, main_klass->desc->name); > + file, line, func_name, op, main_klass->desc->name); > goto err; > } > err_cache_op: > @@ -612,7 +569,7 @@ err_cache_op: > goto err; > err_func_src: > ERR("in %s:%d: you called a pure virtual func '%s' (%d) of class > '%s'.", > - file, line, func_name, cache->op, klass->desc->name); > + file, line, func_name, op, klass->desc->name); > err: > if (is_obj) > { > @@ -629,7 +586,7 @@ err: > // yes - special "move out of hot path" code blobs with goto's for > // speed reasons to have intr prefetches work better and miss less > ok_cur_klass: > - func = _eo_kls_itr_next(klass, cur_klass, cache->op, super); > + func = _eo_kls_itr_next(klass, cur_klass, op, super); > if (!func) goto end; > klass = func->src; > goto ok_cur_klass_back; > @@ -661,7 +618,6 @@ obj_super: > cur_klass = NULL; > } > > - is_override = _obj_is_override(obj) && (cur_klass == NULL); > } > goto obj_super_back; > > > -- > > -- > Jean-Philippe André > > ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot _______________________________________________ enlightenment-devel mailing list enlightenment-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/enlightenment-devel