diff options
author | Jean Guyomarc'h <jean@guyomarch.bzh> | 2018-01-11 08:56:09 +0100 |
---|---|---|
committer | Jean Guyomarc'h <jean@guyomarch.bzh> | 2018-01-11 08:56:09 +0100 |
commit | af2d961047ca03149c5342e633344570670020e0 (patch) | |
tree | 8a3263c8caa2d609a6e63921da2044c1364bd29c | |
parent | 3864b10e50fd531531f437c44db504747250f507 (diff) | |
download | efl-af2d961047ca03149c5342e633344570670020e0.tar.gz |
wip: got some more frames
-rw-r--r-- | src/lib/eo/Eo.h | 5 | ||||
-rw-r--r-- | src/lib/eo/eo.c | 7 | ||||
-rw-r--r-- | src/lib/eo/eo_private.h | 3 | ||||
-rw-r--r-- | src/lib/eo/eo_ptr_indirection.c | 184 | ||||
-rw-r--r-- | src/lib/eo/eo_ptr_indirection.x | 40 |
5 files changed, 176 insertions, 63 deletions
diff --git a/src/lib/eo/Eo.h b/src/lib/eo/Eo.h index 1c036f7252..8672ac6709 100644 --- a/src/lib/eo/Eo.h +++ b/src/lib/eo/Eo.h @@ -41,6 +41,9 @@ #ifdef __cplusplus extern "C" { +# define __restrict__ +#else +# define __restrict__ restrict #endif /** @@ -1340,7 +1343,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 *__restrict__ obj, const char *__restrict__ func_name, Efl_Object_Op_Call_Data *__restrict__ call, Efl_Object_Call_Cache *__restrict__ callcache, const char *__restrict__ 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 ed54056872..1298a0e1c0 100644 --- a/src/lib/eo/eo.c +++ b/src/lib/eo/eo.c @@ -439,7 +439,7 @@ 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 *restrict eo_id, const char *restrict func_name, Efl_Object_Op_Call_Data *restrict call, Efl_Object_Call_Cache *restrict cache, const char *restrict file, int line) { const _Efl_Class *klass, *inputklass, *main_klass; const _Efl_Class *cur_klass = NULL; @@ -487,8 +487,6 @@ ok_klass_back: inputklass = main_klass = klass; - if (!cache->op) goto err_cache_op; - /* If we have a current class, we need to itr to the next. */ if (cur_klass) { @@ -2293,6 +2291,8 @@ efl_object_init(void) return EINA_TRUE; } +void eo_dump_stats(void); + EAPI Eina_Bool efl_object_shutdown(void) { @@ -2346,6 +2346,7 @@ efl_object_shutdown(void) ++_efl_object_init_generation; eina_shutdown(); + eo_dump_stats(); return EINA_FALSE; } diff --git a/src/lib/eo/eo_private.h b/src/lib/eo/eo_private.h index 38f8c9eb03..79ad8be2ea 100644 --- a/src/lib/eo/eo_private.h +++ b/src/lib/eo/eo_private.h @@ -226,7 +226,7 @@ Eo *_eo_header_id_get(const Eo_Header *header) } /* Retrieves the pointer to the object from the id */ -_Eo_Object *_eo_obj_pointer_get(const Eo_Id obj_id, const char *func_name, const char *file, int line); +_Eo_Object *_eo_obj_pointer_get(const Eo_Id obj_id, const char *restrict func_name, const char *restrict file, int line); static inline Efl_Class *_eo_class_id_get(const _Efl_Class *klass) @@ -378,5 +378,6 @@ _efl_unref_internal(_Eo_Object *obj, const char *func_name, const char *file, in Eina_Bool efl_future_init(void); Eina_Bool efl_future_shutdown(void); +Eina_Bool eo_main_table_data_init(void); #endif diff --git a/src/lib/eo/eo_ptr_indirection.c b/src/lib/eo/eo_ptr_indirection.c index 01db8a289a..d7fd68520a 100644 --- a/src/lib/eo/eo_ptr_indirection.c +++ b/src/lib/eo/eo_ptr_indirection.c @@ -12,6 +12,9 @@ Eina_TLS _eo_table_data; Eo_Id_Data *_eo_table_data_shared = NULL; Eo_Id_Table_Data *_eo_table_data_shared_data = NULL; +Eo_Id_Data _eo_main_table_data; +Eo_Id_Table_Data _eo_table_main_table_data; + ////////////////////////////////////////////////////////////////////////// void @@ -27,7 +30,7 @@ _eo_pointer_error(const Eo *obj_id, const char *func_name, const char *file, int static void _eo_obj_pointer_invalid(const Eo_Id obj_id, - Eo_Id_Data *data, + const Eo_Id_Data *data, unsigned char domain, const char *func_name, const char *file, @@ -76,32 +79,94 @@ _eo_obj_pointer_invalid(const Eo_Id obj_id, _eo_log_obj_report(obj_id, EINA_LOG_LEVEL_ERR, func_name, file, line); } +static long unsigned int _calls = 0; +static long unsigned int _hits = 0; + _Eo_Object * -_eo_obj_pointer_get(const Eo_Id obj_id, const char *func_name, const char *file, int line) +_eo_obj_pointer_get(const Eo_Id obj_id, const char *restrict func_name, const char *restrict file, int line) { - _Eo_Id_Entry *entry; - Generation_Counter generation; - Table_Index mid_table_id, table_id, entry_id; - Eo_Id tag_bit; - Eo_Id_Data *data; - Eo_Id_Table_Data *tdata; - unsigned char domain; - - // NULL objects will just be sensibly ignored. not worth complaining - // every single time. - - data = _eo_table_data_get(); - EINA_PREFETCH(&(data->tables[0])); - domain = (obj_id >> SHIFT_DOMAIN) & MASK_DOMAIN; - tdata = _eo_table_data_table_get(data, domain); - EINA_PREFETCH(&(tdata->cache.id)); - if (EINA_UNLIKELY(!tdata)) goto err; - - - if (EINA_LIKELY(domain != EFL_ID_DOMAIN_SHARED)) + if (EINA_UNLIKELY(! obj_id)) goto err_null; + + static const void *const jump[] = { + &&do_domain_main, + &&do_domain_shared, + &&do_domain_thread, + &&do_domain_other, + }; + const unsigned int domain = (obj_id >> SHIFT_DOMAIN) & MASK_DOMAIN; + goto *jump[domain]; + +do_domain_main: EINA_HOT + { + __builtin_prefetch(&_eo_table_main_table_data, 0, 3); + if (obj_id == _eo_table_main_table_data.cache.id) + return _eo_table_main_table_data.cache.object; + + /* XXX This could definitely be done in one go with vectorization */ + const unsigned int mid_table_id = (obj_id >> SHIFT_MID_TABLE_ID) & MASK_MID_TABLE_ID; + const unsigned int table_id = (obj_id >> SHIFT_TABLE_ID) & MASK_TABLE_ID; + const unsigned int entry_id = (obj_id >> SHIFT_ENTRY_ID) & MASK_ENTRY_ID; + const Generation_Counter generation = obj_id & MASK_GENERATIONS; + + // get tag bit to check later down below - pipelining + const Eo_Id tag_bit = (obj_id) & MASK_OBJ_TAG; + if (EINA_UNLIKELY(!tag_bit)) goto main_err; + + __builtin_prefetch(&(_eo_table_main_table_data.eo_ids_tables[mid_table_id]), 0, 3); + + // Check the validity of the entry + if (EINA_LIKELY(_eo_table_main_table_data.eo_ids_tables[mid_table_id] != NULL)) + { + register const _Eo_Ids_Table *const tab = + _eo_table_main_table_data.eo_ids_tables[mid_table_id][table_id]; + + if (EINA_LIKELY(tab != NULL)) + { + register const _Eo_Id_Entry *const entry = &(tab->entries[entry_id]); + if (EINA_LIKELY(entry->active && (entry->generation == generation))) + { + // Cache the result of that lookup + _eo_table_main_table_data.cache.object = entry->ptr; + _eo_table_main_table_data.cache.id = obj_id; + return _eo_table_main_table_data.cache.object; + } + } + } + + + goto main_err; + } + + +main_err: EINA_COLD + _eo_obj_pointer_invalid(obj_id, &_eo_main_table_data, domain, func_name, file, line); + return NULL; + + + +do_domain_thread: EINA_COLD +do_domain_other: EINA_COLD { + _Eo_Id_Entry *entry; + Generation_Counter generation; + unsigned int mid_table_id, table_id, entry_id; + Eo_Id tag_bit; + Eo_Id_Data *data; + Eo_Id_Table_Data *tdata; + + + // NULL objects will just be sensibly ignored. not worth complaining + // every single time. + + data = _eo_table_data_get(); + EINA_PREFETCH(&(data->tables[0])); + tdata = _eo_table_data_table_get(data, domain); + EINA_PREFETCH(&(tdata->cache.id)); + if (EINA_UNLIKELY(!tdata)) goto err; + + if (obj_id == tdata->cache.id) - return tdata->cache.object; + return tdata->cache.object; mid_table_id = (obj_id >> SHIFT_MID_TABLE_ID) & MASK_MID_TABLE_ID; EINA_PREFETCH(&(tdata->eo_ids_tables[mid_table_id])); @@ -111,32 +176,53 @@ _eo_obj_pointer_get(const Eo_Id obj_id, const char *func_name, const char *file, // get tag bit to check later down below - pipelining tag_bit = (obj_id) & MASK_OBJ_TAG; - if (!obj_id) goto err_null; - else if (!tag_bit) goto err; + if (EINA_UNLIKELY(!obj_id)) goto err_null; + else if (EINA_UNLIKELY(!tag_bit)) goto err; // Check the validity of the entry if (tdata->eo_ids_tables[mid_table_id]) - { - _Eo_Ids_Table *tab = TABLE_FROM_IDS; + { + _Eo_Ids_Table *tab = TABLE_FROM_IDS; - if (tab) - { - entry = &(tab->entries[entry_id]); - if (entry->active && (entry->generation == generation)) - { - // Cache the result of that lookup - tdata->cache.object = entry->ptr; - tdata->cache.id = obj_id; - return entry->ptr; - } - } - } + if (tab) + { + entry = &(tab->entries[entry_id]); + if (entry->active && (entry->generation == generation)) + { + // Cache the result of that lookup + tdata->cache.object = entry->ptr; + tdata->cache.id = obj_id; + return entry->ptr; + } + } + } goto err; + +err_null: EINA_COLD + return NULL; +err: EINA_COLD + _eo_obj_pointer_invalid(obj_id, data, domain, func_name, file, line); + return NULL; } - else + +do_domain_shared: EINA_COLD { + _Eo_Id_Entry *entry; + Generation_Counter generation; + unsigned int mid_table_id, table_id, entry_id; + Eo_Id tag_bit; + Eo_Id_Data *data; + Eo_Id_Table_Data *tdata; + + data = _eo_table_data_get(); + EINA_PREFETCH(&(data->tables[0])); + tdata = _eo_table_data_table_get(data, domain); + EINA_PREFETCH(&(tdata->cache.id)); + if (EINA_UNLIKELY(!tdata)) goto err_shared_err; + + eina_lock_take(&(_eo_table_data_shared_data->obj_lock)); - if (obj_id == tdata->cache.id) + if (EINA_LIKELY(obj_id == tdata->cache.id)) // yes we return keeping the lock locked. thats why // you must call _eo_obj_pointer_done() wrapped // by EO_OBJ_DONE() to release @@ -174,18 +260,24 @@ _eo_obj_pointer_get(const Eo_Id obj_id, const char *func_name, const char *file, } } goto err_shared; - } -err_shared_null: + +err_shared_null: EINA_COLD eina_lock_release(&(_eo_table_data_shared_data->obj_lock)); -err_null: eina_log_print(_eo_log_dom, EINA_LOG_LEVEL_DBG, file, func_name, line, "obj_id is NULL. Possibly unintended access?"); return NULL; -err_shared: +err_shared: EINA_COLD eina_lock_release(&(_eo_table_data_shared_data->obj_lock)); -err: +err_shared_err: EINA_COLD _eo_obj_pointer_invalid(obj_id, data, domain, func_name, file, line); return NULL; + } +} + +void eo_dump_stats(void) +{ + // printf("Eo ptr resolution. %lu calls, %lu hits\n", + // _calls, _hits); } diff --git a/src/lib/eo/eo_ptr_indirection.x b/src/lib/eo/eo_ptr_indirection.x index f4311e1c3a..b8724b1148 100644 --- a/src/lib/eo/eo_ptr_indirection.x +++ b/src/lib/eo/eo_ptr_indirection.x @@ -230,10 +230,8 @@ typedef struct _Eo_Object *ptr; /* Indicates where to find the next entry to recycle */ Table_Index next_in_fifo; - /* Active flag */ - unsigned int active : 1; /* Generation */ - unsigned int generation : BITS_GENERATION_COUNTER; + unsigned int generation; } _Eo_Id_Entry; @@ -296,6 +294,9 @@ struct _Eo_Id_Data extern Eina_TLS _eo_table_data; extern Eo_Id_Data *_eo_table_data_shared; extern Eo_Id_Table_Data *_eo_table_data_shared_data; +extern Eo_Id_Data _eo_main_table_data; +extern Eo_Id_Table_Data _eo_table_main_table_data; + static inline Eo_Id_Table_Data * _eo_table_data_table_new(Efl_Id_Domain domain) @@ -317,11 +318,29 @@ _eo_table_data_table_new(Efl_Id_Domain domain) return tdata; } + +static inline Eo_Id_Data * +_eo_main_table_data_new(void) +{ + Eo_Id_Data *const d = &_eo_main_table_data; + d->local_domain = EFL_ID_DOMAIN_MAIN; + d->domain_stack[d->stack_top] = EFL_ID_DOMAIN_MAIN; + d->tables[EFL_ID_DOMAIN_MAIN] = &_eo_table_main_table_data; + + /* Init table */ + _eo_table_main_table_data.generation = rand() % MAX_GENERATIONS; + + return d; +} + static inline Eo_Id_Data * _eo_table_data_new(Efl_Id_Domain domain) { Eo_Id_Data *data; + if (domain == EFL_ID_DOMAIN_MAIN) + return _eo_main_table_data_new(); + data = calloc(1, sizeof(Eo_Id_Data)); if (!data) return NULL; data->local_domain = domain; @@ -344,12 +363,6 @@ static inline Eo_Id_Data * _eo_table_data_get(void) { Eo_Id_Data *data = eina_tls_get(_eo_table_data); - if (EINA_LIKELY(data != NULL)) return data; - - data = _eo_table_data_new(EFL_ID_DOMAIN_THREAD); - if (!data) return NULL; - - eina_tls_set(_eo_table_data, data); return data; } @@ -720,9 +733,12 @@ _eo_free_ids_tables(Eo_Id_Data *data) } if (tdata->empty_table) _eo_id_mem_free(tdata->empty_table); tdata->empty_table = tdata->current_table = NULL; - _eo_table_data_table_free(tdata); - data->tables[data->local_domain] = NULL; - free(data); + if (data->local_domain != EFL_ID_DOMAIN_MAIN) + { + _eo_table_data_table_free(tdata); + data->tables[data->local_domain] = NULL; + free(data); + } } #ifdef EFL_DEBUG |