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)
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 @@
41 41
42#ifdef __cplusplus 42#ifdef __cplusplus
43extern "C" { 43extern "C" {
44# define __restrict__
45#else
46# define __restrict__ restrict
44#endif 47#endif
45 48
46/** 49/**
@@ -1340,7 +1343,7 @@ EAPI Efl_Object_Op _efl_object_api_op_id_get(const void *api_func) EINA_DEPRECAT
1340EAPI 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; 1343EAPI 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;
1341 1344
1342// gets the real function pointer and the object data 1345// gets the real function pointer and the object data
1343EAPI 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); 1346EAPI 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);
1344 1347
1345// end of the eo call barrier, unref the obj 1348// end of the eo call barrier, unref the obj
1346EAPI void _efl_object_call_end(Efl_Object_Op_Call_Data *call); 1349EAPI 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)
439} 439}
440 440
441EAPI Eina_Bool 441EAPI Eina_Bool
442_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) 442_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)
443{ 443{
444 const _Efl_Class *klass, *inputklass, *main_klass; 444 const _Efl_Class *klass, *inputklass, *main_klass;
445 const _Efl_Class *cur_klass = NULL; 445 const _Efl_Class *cur_klass = NULL;
@@ -487,8 +487,6 @@ ok_klass_back:
487 487
488 inputklass = main_klass = klass; 488 inputklass = main_klass = klass;
489 489
490 if (!cache->op) goto err_cache_op;
491
492 /* If we have a current class, we need to itr to the next. */ 490 /* If we have a current class, we need to itr to the next. */
493 if (cur_klass) 491 if (cur_klass)
494 { 492 {
@@ -2293,6 +2291,8 @@ efl_object_init(void)
2293 return EINA_TRUE; 2291 return EINA_TRUE;
2294} 2292}
2295 2293
2294void eo_dump_stats(void);
2295
2296EAPI Eina_Bool 2296EAPI Eina_Bool
2297efl_object_shutdown(void) 2297efl_object_shutdown(void)
2298{ 2298{
@@ -2346,6 +2346,7 @@ efl_object_shutdown(void)
2346 ++_efl_object_init_generation; 2346 ++_efl_object_init_generation;
2347 2347
2348 eina_shutdown(); 2348 eina_shutdown();
2349 eo_dump_stats();
2349 return EINA_FALSE; 2350 return EINA_FALSE;
2350} 2351}
2351 2352
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)
226} 226}
227 227
228/* Retrieves the pointer to the object from the id */ 228/* Retrieves the pointer to the object from the id */
229_Eo_Object *_eo_obj_pointer_get(const Eo_Id obj_id, const char *func_name, const char *file, int line); 229_Eo_Object *_eo_obj_pointer_get(const Eo_Id obj_id, const char *restrict func_name, const char *restrict file, int line);
230 230
231static inline 231static inline
232Efl_Class *_eo_class_id_get(const _Efl_Class *klass) 232Efl_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
378 378
379Eina_Bool efl_future_init(void); 379Eina_Bool efl_future_init(void);
380Eina_Bool efl_future_shutdown(void); 380Eina_Bool efl_future_shutdown(void);
381Eina_Bool eo_main_table_data_init(void);
381 382
382#endif 383#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;
12Eo_Id_Data *_eo_table_data_shared = NULL; 12Eo_Id_Data *_eo_table_data_shared = NULL;
13Eo_Id_Table_Data *_eo_table_data_shared_data = NULL; 13Eo_Id_Table_Data *_eo_table_data_shared_data = NULL;
14 14
15Eo_Id_Data _eo_main_table_data;
16Eo_Id_Table_Data _eo_table_main_table_data;
17
15////////////////////////////////////////////////////////////////////////// 18//////////////////////////////////////////////////////////////////////////
16 19
17void 20void
@@ -27,7 +30,7 @@ _eo_pointer_error(const Eo *obj_id, const char *func_name, const char *file, int
27 30
28static void 31static void
29_eo_obj_pointer_invalid(const Eo_Id obj_id, 32_eo_obj_pointer_invalid(const Eo_Id obj_id,
30 Eo_Id_Data *data, 33 const Eo_Id_Data *data,
31 unsigned char domain, 34 unsigned char domain,
32 const char *func_name, 35 const char *func_name,
33 const char *file, 36 const char *file,
@@ -76,32 +79,94 @@ _eo_obj_pointer_invalid(const Eo_Id obj_id,
76 _eo_log_obj_report(obj_id, EINA_LOG_LEVEL_ERR, func_name, file, line); 79 _eo_log_obj_report(obj_id, EINA_LOG_LEVEL_ERR, func_name, file, line);
77} 80}
78 81
82static long unsigned int _calls = 0;
83static long unsigned int _hits = 0;
84
79_Eo_Object * 85_Eo_Object *
80_eo_obj_pointer_get(const Eo_Id obj_id, const char *func_name, const char *file, int line) 86_eo_obj_pointer_get(const Eo_Id obj_id, const char *restrict func_name, const char *restrict file, int line)
81{ 87{
82 _Eo_Id_Entry *entry; 88 if (EINA_UNLIKELY(! obj_id)) goto err_null;
83 Generation_Counter generation; 89
84 Table_Index mid_table_id, table_id, entry_id; 90 static const void *const jump[] = {
85 Eo_Id tag_bit; 91 &&do_domain_main,
86 Eo_Id_Data *data; 92 &&do_domain_shared,
87 Eo_Id_Table_Data *tdata; 93 &&do_domain_thread,
88 unsigned char domain; 94 &&do_domain_other,
89 95 };
90 // NULL objects will just be sensibly ignored. not worth complaining 96 const unsigned int domain = (obj_id >> SHIFT_DOMAIN) & MASK_DOMAIN;
91 // every single time. 97 goto *jump[domain];
92 98
93 data = _eo_table_data_get(); 99do_domain_main: EINA_HOT
94 EINA_PREFETCH(&(data->tables[0])); 100 {
95 domain = (obj_id >> SHIFT_DOMAIN) & MASK_DOMAIN; 101 __builtin_prefetch(&_eo_table_main_table_data, 0, 3);
96 tdata = _eo_table_data_table_get(data, domain); 102 if (obj_id == _eo_table_main_table_data.cache.id)
97 EINA_PREFETCH(&(tdata->cache.id)); 103 return _eo_table_main_table_data.cache.object;
98 if (EINA_UNLIKELY(!tdata)) goto err; 104
99 105 /* XXX This could definitely be done in one go with vectorization */
100 106 const unsigned int mid_table_id = (obj_id >> SHIFT_MID_TABLE_ID) & MASK_MID_TABLE_ID;
101 if (EINA_LIKELY(domain != EFL_ID_DOMAIN_SHARED)) 107 const unsigned int table_id = (obj_id >> SHIFT_TABLE_ID) & MASK_TABLE_ID;
108 const unsigned int entry_id = (obj_id >> SHIFT_ENTRY_ID) & MASK_ENTRY_ID;
109 const Generation_Counter generation = obj_id & MASK_GENERATIONS;
110
111 // get tag bit to check later down below - pipelining
112 const Eo_Id tag_bit = (obj_id) & MASK_OBJ_TAG;
113 if (EINA_UNLIKELY(!tag_bit)) goto main_err;
114
115 __builtin_prefetch(&(_eo_table_main_table_data.eo_ids_tables[mid_table_id]), 0, 3);
116
117 // Check the validity of the entry
118 if (EINA_LIKELY(_eo_table_main_table_data.eo_ids_tables[mid_table_id] != NULL))
119 {
120 register const _Eo_Ids_Table *const tab =
121 _eo_table_main_table_data.eo_ids_tables[mid_table_id][table_id];
122
123 if (EINA_LIKELY(tab != NULL))
124 {
125 register const _Eo_Id_Entry *const entry = &(tab->entries[entry_id]);
126 if (EINA_LIKELY(entry->active && (entry->generation == generation)))
127 {
128 // Cache the result of that lookup
129 _eo_table_main_table_data.cache.object = entry->ptr;
130 _eo_table_main_table_data.cache.id = obj_id;
131 return _eo_table_main_table_data.cache.object;
132 }
133 }
134 }
135
136
137 goto main_err;
138 }
139
140
141main_err: EINA_COLD
142 _eo_obj_pointer_invalid(obj_id, &_eo_main_table_data, domain, func_name, file, line);
143 return NULL;
144
145
146
147do_domain_thread: EINA_COLD
148do_domain_other: EINA_COLD
102 { 149 {
150 _Eo_Id_Entry *entry;
151 Generation_Counter generation;
152 unsigned int mid_table_id, table_id, entry_id;
153 Eo_Id tag_bit;
154 Eo_Id_Data *data;
155 Eo_Id_Table_Data *tdata;
156
157
158 // NULL objects will just be sensibly ignored. not worth complaining
159 // every single time.
160
161 data = _eo_table_data_get();
162 EINA_PREFETCH(&(data->tables[0]));
163 tdata = _eo_table_data_table_get(data, domain);
164 EINA_PREFETCH(&(tdata->cache.id));
165 if (EINA_UNLIKELY(!tdata)) goto err;
166
167
103 if (obj_id == tdata->cache.id) 168 if (obj_id == tdata->cache.id)
104 return tdata->cache.object; 169 return tdata->cache.object;
105 170
106 mid_table_id = (obj_id >> SHIFT_MID_TABLE_ID) & MASK_MID_TABLE_ID; 171 mid_table_id = (obj_id >> SHIFT_MID_TABLE_ID) & MASK_MID_TABLE_ID;
107 EINA_PREFETCH(&(tdata->eo_ids_tables[mid_table_id])); 172 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,
111 176
112 // get tag bit to check later down below - pipelining 177 // get tag bit to check later down below - pipelining
113 tag_bit = (obj_id) & MASK_OBJ_TAG; 178 tag_bit = (obj_id) & MASK_OBJ_TAG;
114 if (!obj_id) goto err_null; 179 if (EINA_UNLIKELY(!obj_id)) goto err_null;
115 else if (!tag_bit) goto err; 180 else if (EINA_UNLIKELY(!tag_bit)) goto err;
116 181
117 // Check the validity of the entry 182 // Check the validity of the entry
118 if (tdata->eo_ids_tables[mid_table_id]) 183 if (tdata->eo_ids_tables[mid_table_id])
119 { 184 {
120 _Eo_Ids_Table *tab = TABLE_FROM_IDS; 185 _Eo_Ids_Table *tab = TABLE_FROM_IDS;
121 186
122 if (tab) 187 if (tab)
123 { 188 {
124 entry = &(tab->entries[entry_id]); 189 entry = &(tab->entries[entry_id]);
125 if (entry->active && (entry->generation == generation)) 190 if (entry->active && (entry->generation == generation))
126 { 191 {
127 // Cache the result of that lookup 192 // Cache the result of that lookup
128 tdata->cache.object = entry->ptr; 193 tdata->cache.object = entry->ptr;
129 tdata->cache.id = obj_id; 194 tdata->cache.id = obj_id;
130 return entry->ptr; 195 return entry->ptr;
131 } 196 }
132 } 197 }
133 } 198 }
134 goto err; 199 goto err;
200
201err_null: EINA_COLD
202 return NULL;
203err: EINA_COLD
204 _eo_obj_pointer_invalid(obj_id, data, domain, func_name, file, line);
205 return NULL;
135 } 206 }
136 else 207
208do_domain_shared: EINA_COLD
137 { 209 {
210 _Eo_Id_Entry *entry;
211 Generation_Counter generation;
212 unsigned int mid_table_id, table_id, entry_id;
213 Eo_Id tag_bit;
214 Eo_Id_Data *data;
215 Eo_Id_Table_Data *tdata;
216
217 data = _eo_table_data_get();
218 EINA_PREFETCH(&(data->tables[0]));
219 tdata = _eo_table_data_table_get(data, domain);
220 EINA_PREFETCH(&(tdata->cache.id));
221 if (EINA_UNLIKELY(!tdata)) goto err_shared_err;
222
223
138 eina_lock_take(&(_eo_table_data_shared_data->obj_lock)); 224 eina_lock_take(&(_eo_table_data_shared_data->obj_lock));
139 if (obj_id == tdata->cache.id) 225 if (EINA_LIKELY(obj_id == tdata->cache.id))
140 // yes we return keeping the lock locked. thats why 226 // yes we return keeping the lock locked. thats why
141 // you must call _eo_obj_pointer_done() wrapped 227 // you must call _eo_obj_pointer_done() wrapped
142 // by EO_OBJ_DONE() to release 228 // 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,
174 } 260 }
175 } 261 }
176 goto err_shared; 262 goto err_shared;
177 } 263
178err_shared_null: 264err_shared_null: EINA_COLD
179 eina_lock_release(&(_eo_table_data_shared_data->obj_lock)); 265 eina_lock_release(&(_eo_table_data_shared_data->obj_lock));
180err_null:
181 eina_log_print(_eo_log_dom, 266 eina_log_print(_eo_log_dom,
182 EINA_LOG_LEVEL_DBG, 267 EINA_LOG_LEVEL_DBG,
183 file, func_name, line, 268 file, func_name, line,
184 "obj_id is NULL. Possibly unintended access?"); 269 "obj_id is NULL. Possibly unintended access?");
185 return NULL; 270 return NULL;
186err_shared: 271err_shared: EINA_COLD
187 eina_lock_release(&(_eo_table_data_shared_data->obj_lock)); 272 eina_lock_release(&(_eo_table_data_shared_data->obj_lock));
188err: 273err_shared_err: EINA_COLD
189 _eo_obj_pointer_invalid(obj_id, data, domain, func_name, file, line); 274 _eo_obj_pointer_invalid(obj_id, data, domain, func_name, file, line);
190 return NULL; 275 return NULL;
276 }
277}
278
279void eo_dump_stats(void)
280{
281 // printf("Eo ptr resolution. %lu calls, %lu hits\n",
282 // _calls, _hits);
191} 283}
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
230 _Eo_Object *ptr; 230 _Eo_Object *ptr;
231 /* Indicates where to find the next entry to recycle */ 231 /* Indicates where to find the next entry to recycle */
232 Table_Index next_in_fifo; 232 Table_Index next_in_fifo;
233 /* Active flag */
234 unsigned int active : 1;
235 /* Generation */ 233 /* Generation */
236 unsigned int generation : BITS_GENERATION_COUNTER; 234 unsigned int generation;
237 235
238} _Eo_Id_Entry; 236} _Eo_Id_Entry;
239 237
@@ -296,6 +294,9 @@ struct _Eo_Id_Data
296extern Eina_TLS _eo_table_data; 294extern Eina_TLS _eo_table_data;
297extern Eo_Id_Data *_eo_table_data_shared; 295extern Eo_Id_Data *_eo_table_data_shared;
298extern Eo_Id_Table_Data *_eo_table_data_shared_data; 296extern Eo_Id_Table_Data *_eo_table_data_shared_data;
297extern Eo_Id_Data _eo_main_table_data;
298extern Eo_Id_Table_Data _eo_table_main_table_data;
299
299 300
300static inline Eo_Id_Table_Data * 301static inline Eo_Id_Table_Data *
301_eo_table_data_table_new(Efl_Id_Domain domain) 302_eo_table_data_table_new(Efl_Id_Domain domain)
@@ -317,11 +318,29 @@ _eo_table_data_table_new(Efl_Id_Domain domain)
317 return tdata; 318 return tdata;
318} 319}
319 320
321
322static inline Eo_Id_Data *
323_eo_main_table_data_new(void)
324{
325 Eo_Id_Data *const d = &_eo_main_table_data;
326 d->local_domain = EFL_ID_DOMAIN_MAIN;
327 d->domain_stack[d->stack_top] = EFL_ID_DOMAIN_MAIN;
328 d->tables[EFL_ID_DOMAIN_MAIN] = &_eo_table_main_table_data;
329
330 /* Init table */
331 _eo_table_main_table_data.generation = rand() % MAX_GENERATIONS;
332
333 return d;
334}
335
320static inline Eo_Id_Data * 336static inline Eo_Id_Data *
321_eo_table_data_new(Efl_Id_Domain domain) 337_eo_table_data_new(Efl_Id_Domain domain)
322{ 338{
323 Eo_Id_Data *data; 339 Eo_Id_Data *data;
324 340
341 if (domain == EFL_ID_DOMAIN_MAIN)
342 return _eo_main_table_data_new();
343
325 data = calloc(1, sizeof(Eo_Id_Data)); 344 data = calloc(1, sizeof(Eo_Id_Data));
326 if (!data) return NULL; 345 if (!data) return NULL;
327 data->local_domain = domain; 346 data->local_domain = domain;
@@ -344,12 +363,6 @@ static inline Eo_Id_Data *
344_eo_table_data_get(void) 363_eo_table_data_get(void)
345{ 364{
346 Eo_Id_Data *data = eina_tls_get(_eo_table_data); 365 Eo_Id_Data *data = eina_tls_get(_eo_table_data);
347 if (EINA_LIKELY(data != NULL)) return data;
348
349 data = _eo_table_data_new(EFL_ID_DOMAIN_THREAD);
350 if (!data) return NULL;
351
352 eina_tls_set(_eo_table_data, data);
353 return data; 366 return data;
354} 367}
355 368
@@ -720,9 +733,12 @@ _eo_free_ids_tables(Eo_Id_Data *data)
720 } 733 }
721 if (tdata->empty_table) _eo_id_mem_free(tdata->empty_table); 734 if (tdata->empty_table) _eo_id_mem_free(tdata->empty_table);
722 tdata->empty_table = tdata->current_table = NULL; 735 tdata->empty_table = tdata->current_table = NULL;
723 _eo_table_data_table_free(tdata); 736 if (data->local_domain != EFL_ID_DOMAIN_MAIN)
724 data->tables[data->local_domain] = NULL; 737 {
725 free(data); 738 _eo_table_data_table_free(tdata);
739 data->tables[data->local_domain] = NULL;
740 free(data);
741 }
726} 742}
727 743
728#ifdef EFL_DEBUG 744#ifdef EFL_DEBUG