summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJean Guyomarc'h <jean@guyomarch.bzh>2018-01-11 08:56:09 +0100
committerJean Guyomarc'h <jean@guyomarch.bzh>2018-01-11 08:56:09 +0100
commitaf2d961047ca03149c5342e633344570670020e0 (patch)
tree8a3263c8caa2d609a6e63921da2044c1364bd29c
parent3864b10e50fd531531f437c44db504747250f507 (diff)
downloadefl-af2d961047ca03149c5342e633344570670020e0.tar.gz
wip: got some more frames
-rw-r--r--src/lib/eo/Eo.h5
-rw-r--r--src/lib/eo/eo.c7
-rw-r--r--src/lib/eo/eo_private.h3
-rw-r--r--src/lib/eo/eo_ptr_indirection.c184
-rw-r--r--src/lib/eo/eo_ptr_indirection.x40
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