summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Hacohen <tom@stosb.com>2015-09-28 17:18:43 +0100
committerTom Hacohen <tom@stosb.com>2015-09-28 18:39:15 +0100
commite2344b9b9ef664c8a251ef21d1afabee0b8326fd (patch)
tree00f7d07aa5355ba694549c9e015fded30313e727 /src
parent17f4c45fc929d26bcbf4e3e8b10d2066d9a1341f (diff)
Eo: reduce memory usage across applications.
As described by Carsten in his email to edev ML titled: "[E-devel] eo stability - i think we need to postpone that" with the switch to Eo2 we significantly increased our usage of RW memory pages, and thus significantly increased our memory usage when running multiple applications. The problem was that during the migration to Eo2 the op id cache and the op description arrays were merged, causing the op description arrays to no longer be RO. This patch enables users of Eo (mainly Eolian) to declare those arrays as const (RO) again, saving that memory. There might be performance implications with this patch. I had to remove the op desc array sorting, and I used a hash table for the lookup. I think the op desc sorting doesn't really affect performance because that array is seldom accessed and is usually pretty short. The hash table is not a problem either, because it's behind the scenes, so it can be changed to a more efficient data structure if the hash table is not good enough. The hash table itself is also rarely accessed, so it's mostly about memory. Please keep an eye for any bugs, performance or excessive memory usage. I believe this should be better on all fronts. This commit *BREAKS ABI*. @fix
Diffstat (limited to 'src')
-rw-r--r--src/bin/eolian/eo_generator.c2
-rw-r--r--src/lib/eo/Eo.h20
-rw-r--r--src/lib/eo/eo.c185
-rw-r--r--src/tests/eo/suite/eo_test_call_errors.c2
-rw-r--r--src/tests/eo/suite/eo_test_class_errors.c6
-rw-r--r--src/tests/eolian/data/class_simple_ref.c4
-rw-r--r--src/tests/eolian/data/override_ref.c4
7 files changed, 83 insertions, 140 deletions
diff --git a/src/bin/eolian/eo_generator.c b/src/bin/eolian/eo_generator.c
index 85d3cb7ec0..2e4f545391 100644
--- a/src/bin/eolian/eo_generator.c
+++ b/src/bin/eolian/eo_generator.c
@@ -19,7 +19,7 @@ static Eina_Hash *_funcs_params_init = NULL;
19 19
20static const char 20static const char
21tmpl_eo_ops_desc[] = "\ 21tmpl_eo_ops_desc[] = "\
22static Eo_Op_Description _@#class_op_desc[] = {@#list_op\n};\n\n"; 22static const Eo_Op_Description _@#class_op_desc[] = {@#list_op\n};\n\n";
23 23
24static const char 24static const char
25tmpl_events_desc[] = "\ 25tmpl_events_desc[] = "\
diff --git a/src/lib/eo/Eo.h b/src/lib/eo/Eo.h
index da16feb3b8..3f551f481d 100644
--- a/src/lib/eo/Eo.h
+++ b/src/lib/eo/Eo.h
@@ -132,6 +132,8 @@ enum _Eo_Op_Type
132 EO_OP_TYPE_INVALID = -1, /**< Invalid op. */ 132 EO_OP_TYPE_INVALID = -1, /**< Invalid op. */
133 EO_OP_TYPE_REGULAR = 0, /**< Regular op. */ 133 EO_OP_TYPE_REGULAR = 0, /**< Regular op. */
134 EO_OP_TYPE_CLASS, /**< Class op - a class op. Like static in Java/C++. */ 134 EO_OP_TYPE_CLASS, /**< Class op - a class op. Like static in Java/C++. */
135 EO_OP_TYPE_REGULAR_OVERRIDE, /**< Regular op override (previously defined) */
136 EO_OP_TYPE_CLASS_OVERRIDE, /**< Class op override (previously defined) */
135}; 137};
136 138
137/** 139/**
@@ -344,7 +346,6 @@ typedef struct _Eo_Op_Description
344{ 346{
345 void *api_func; /**< The EAPI function offering this op. (The name of the func on windows) */ 347 void *api_func; /**< The EAPI function offering this op. (The name of the func on windows) */
346 void *func; /**< The static function to call for the op. */ 348 void *func; /**< The static function to call for the op. */
347 Eo_Op op; /**< The op. */
348 Eo_Op_Type op_type; /**< The type of the Op. */ 349 Eo_Op_Type op_type; /**< The type of the Op. */
349} Eo_Op_Description; 350} Eo_Op_Description;
350 351
@@ -360,7 +361,7 @@ struct _Eo_Class_Description
360 const char *name; /**< The name of the class. */ 361 const char *name; /**< The name of the class. */
361 Eo_Class_Type type; /**< The type of the class. */ 362 Eo_Class_Type type; /**< The type of the class. */
362 struct { 363 struct {
363 Eo_Op_Description *descs; /**< The op descriptions array of size count. */ 364 const Eo_Op_Description *descs; /**< The op descriptions array of size count. */
364 size_t count; /**< Number of op descriptions. */ 365 size_t count; /**< Number of op descriptions. */
365 } ops; /**< The ops description, should be filled using #EO_CLASS_DESCRIPTION_OPS (later sorted by Eo). */ 366 } ops; /**< The ops description, should be filled using #EO_CLASS_DESCRIPTION_OPS (later sorted by Eo). */
366 const Eo_Event_Description **events; /**< The event descriptions for this class. */ 367 const Eo_Event_Description **events; /**< The event descriptions for this class. */
@@ -469,7 +470,7 @@ EAPI extern Eo_Hook_Call eo_hook_call_post;
469 Eina_Bool ___is_main_loop = eina_main_loop_is(); \ 470 Eina_Bool ___is_main_loop = eina_main_loop_is(); \
470 static Eo_Op ___op = EO_NOOP; \ 471 static Eo_Op ___op = EO_NOOP; \
471 if (___op == EO_NOOP) \ 472 if (___op == EO_NOOP) \
472 ___op = _eo_api_op_id_get(EO_FUNC_COMMON_OP_FUNC(Name), ___is_main_loop, __FILE__, __LINE__); \ 473 ___op = _eo_api_op_id_get(EO_FUNC_COMMON_OP_FUNC(Name)); \
473 if (!_eo_call_resolve(#Name, ___op, &___call, ___is_main_loop, __FILE__, __LINE__)) return DefRet; \ 474 if (!_eo_call_resolve(#Name, ___op, &___call, ___is_main_loop, __FILE__, __LINE__)) return DefRet; \
474 _Eo_##Name##_func _func_ = (_Eo_##Name##_func) ___call.func; \ 475 _Eo_##Name##_func _func_ = (_Eo_##Name##_func) ___call.func; \
475 476
@@ -522,22 +523,19 @@ EAPI extern Eo_Hook_Call eo_hook_call_post;
522 EO_HOOK_CALL_PREPAREV(eo_hook_call_post, #Name, Arguments); \ 523 EO_HOOK_CALL_PREPAREV(eo_hook_call_post, #Name, Arguments); \
523 } 524 }
524 525
525// OP ID of an overriding function
526#define EO_OP_OVERRIDE ((Eo_Op) -1)
527
528#ifndef _WIN32 526#ifndef _WIN32
529# define _EO_OP_API_ENTRY(a) a 527# define _EO_OP_API_ENTRY(a) a
530#else 528#else
531# define _EO_OP_API_ENTRY(a) #a 529# define _EO_OP_API_ENTRY(a) #a
532#endif 530#endif
533 531
534#define EO_OP_FUNC(_api, _private) { _EO_OP_API_ENTRY(_api), _private, EO_NOOP, EO_OP_TYPE_REGULAR } 532#define EO_OP_FUNC(_api, _private) { _EO_OP_API_ENTRY(_api), _private, EO_OP_TYPE_REGULAR }
535#define EO_OP_CLASS_FUNC(_api, _private) { _EO_OP_API_ENTRY(_api), _private, EO_NOOP, EO_OP_TYPE_CLASS } 533#define EO_OP_CLASS_FUNC(_api, _private) { _EO_OP_API_ENTRY(_api), _private, EO_OP_TYPE_CLASS }
536#define EO_OP_FUNC_OVERRIDE(_api, _private) { _EO_OP_API_ENTRY(_api), _private, EO_OP_OVERRIDE, EO_OP_TYPE_REGULAR } 534#define EO_OP_FUNC_OVERRIDE(_api, _private) { _EO_OP_API_ENTRY(_api), _private, EO_OP_TYPE_REGULAR_OVERRIDE }
537#define EO_OP_CLASS_FUNC_OVERRIDE(_api, _private) { _EO_OP_API_ENTRY(_api), _private, EO_OP_OVERRIDE, EO_OP_TYPE_CLASS } 535#define EO_OP_CLASS_FUNC_OVERRIDE(_api, _private) { _EO_OP_API_ENTRY(_api), _private, EO_OP_TYPE_CLASS_OVERRIDE }
538 536
539// returns the OP id corresponding to the given api_func 537// returns the OP id corresponding to the given api_func
540EAPI Eo_Op _eo_api_op_id_get(const void *api_func, Eina_Bool is_main_loop, const char *file, int line); 538EAPI Eo_Op _eo_api_op_id_get(const void *api_func);
541 539
542// gets the real function pointer and the object data 540// gets the real function pointer and the object data
543EAPI Eina_Bool _eo_call_resolve(const char *func_name, const Eo_Op op, Eo_Op_Call_Data *call, Eina_Bool is_main_loop, const char *file, int line); 541EAPI Eina_Bool _eo_call_resolve(const char *func_name, const Eo_Op op, Eo_Op_Call_Data *call, Eina_Bool is_main_loop, const char *file, int line);
diff --git a/src/lib/eo/eo.c b/src/lib/eo/eo.c
index b92aa8e05a..7e9b0a5633 100644
--- a/src/lib/eo/eo.c
+++ b/src/lib/eo/eo.c
@@ -25,6 +25,8 @@ static _Eo_Class **_eo_classes;
25static Eo_Id _eo_classes_last_id; 25static Eo_Id _eo_classes_last_id;
26static int _eo_init_count = 0; 26static int _eo_init_count = 0;
27static Eo_Op _eo_ops_last_id = 0; 27static Eo_Op _eo_ops_last_id = 0;
28static Eina_Hash *_ops_storage = NULL;
29static Eina_Spinlock _ops_storage_lock;
28 30
29static size_t _eo_sz = 0; 31static size_t _eo_sz = 0;
30static size_t _eo_class_sz = 0; 32static size_t _eo_class_sz = 0;
@@ -34,7 +36,6 @@ static inline void *_eo_data_scope_get(const _Eo_Object *obj, const _Eo_Class *k
34static inline void *_eo_data_xref_internal(const char *file, int line, _Eo_Object *obj, const _Eo_Class *klass, const _Eo_Object *ref_obj); 36static inline void *_eo_data_xref_internal(const char *file, int line, _Eo_Object *obj, const _Eo_Class *klass, const _Eo_Object *ref_obj);
35static inline void _eo_data_xunref_internal(_Eo_Object *obj, void *data, const _Eo_Object *ref_obj); 37static inline void _eo_data_xunref_internal(_Eo_Object *obj, void *data, const _Eo_Object *ref_obj);
36static const _Eo_Class *_eo_op_class_get(Eo_Op op); 38static const _Eo_Class *_eo_op_class_get(Eo_Op op);
37static const char * _eo_op_id_name_get(Eo_Op op);
38 39
39/* Start of Dich */ 40/* Start of Dich */
40 41
@@ -113,9 +114,8 @@ _dich_func_set(_Eo_Class *klass, Eo_Op op, eo_op_func_type func)
113 if (fsrc->src == klass) 114 if (fsrc->src == klass)
114 { 115 {
115 const _Eo_Class *op_kls = _eo_op_class_get(op); 116 const _Eo_Class *op_kls = _eo_op_class_get(op);
116 const char *op_name = _eo_op_id_name_get(op); 117 ERR("Class '%s': Overriding func %p for op %d (%s) with %p.",
117 ERR("Class '%s': Overriding func %p for op %d (%s:'%s') with %p.", 118 klass->desc->name, fsrc->func, op, op_kls->desc->name, func);
118 klass->desc->name, fsrc->func, op, op_kls->desc->name, op_name, func);
119 return EINA_FALSE; 119 return EINA_FALSE;
120 } 120 }
121 121
@@ -191,33 +191,6 @@ _eo_op_class_get(Eo_Op op)
191 return NULL; 191 return NULL;
192} 192}
193 193
194static const Eo_Op_Description *
195_eo_op_id_desc_get(Eo_Op op)
196{
197 unsigned int i;
198 const _Eo_Class *klass;
199 const Eo_Op_Description *op_descs;
200
201 if (op == EO_NOOP)
202 return NULL;
203
204 klass = _eo_op_class_get(op);
205
206 if (klass)
207 {
208 DBG("klass %p %s", klass, klass->desc->name);
209
210 op_descs = klass->desc->ops.descs;
211 for (i = 0; i < klass->desc->ops.count; i++)
212 {
213 if (op_descs[i].op == op)
214 return &op_descs[i];
215 }
216 }
217
218 return NULL;
219}
220
221static const char * 194static const char *
222_eo_op_desc_name_get(const Eo_Op_Description *desc) 195_eo_op_desc_name_get(const Eo_Op_Description *desc)
223{ 196{
@@ -240,13 +213,6 @@ _eo_op_desc_name_get(const Eo_Op_Description *desc)
240 return fct_name; 213 return fct_name;
241} 214}
242 215
243static const char *
244_eo_op_id_name_get(Eo_Op op)
245{
246 const Eo_Op_Description *desc = _eo_op_id_desc_get(op);
247 return _eo_op_desc_name_get(desc);
248}
249
250static inline const op_type_funcs * 216static inline const op_type_funcs *
251_eo_kls_itr_next(const _Eo_Class *orig_kls, const _Eo_Class *cur_klass, Eo_Op op) 217_eo_kls_itr_next(const _Eo_Class *orig_kls, const _Eo_Class *cur_klass, Eo_Op op)
252{ 218{
@@ -582,15 +548,13 @@ _eo_do_end(void)
582} 548}
583 549
584EAPI Eina_Bool 550EAPI Eina_Bool
585 _eo_call_resolve(const char *func_name, const Eo_Op op, Eo_Op_Call_Data *call, Eina_Bool is_main_loop, const char *file, int line) 551_eo_call_resolve(const char *func_name, const Eo_Op op, Eo_Op_Call_Data *call, Eina_Bool is_main_loop, const char *file, int line)
586{ 552{
587 Eo_Stack_Frame *fptr; 553 Eo_Stack_Frame *fptr;
588 const _Eo_Class *klass; 554 const _Eo_Class *klass;
589 const op_type_funcs *func; 555 const op_type_funcs *func;
590 Eina_Bool is_obj; 556 Eina_Bool is_obj;
591 557
592 if (op == EO_NOOP) return EINA_FALSE;
593
594 fptr = _eo_call_stack_get(is_main_loop)->frame_ptr; 558 fptr = _eo_call_stack_get(is_main_loop)->frame_ptr;
595 559
596 if (EINA_UNLIKELY(!fptr->o.obj)) 560 if (EINA_UNLIKELY(!fptr->o.obj))
@@ -600,6 +564,15 @@ EAPI Eina_Bool
600 564
601 klass = (is_obj) ? fptr->o.obj->klass : fptr->o.kls; 565 klass = (is_obj) ? fptr->o.obj->klass : fptr->o.kls;
602 566
567 if (op == EO_NOOP)
568 {
569 ERR("%s:%d: unable to resolve %s api func '%s' in class '%s'.",
570 file, line, (!is_obj ? "class" : "regular"),
571 func_name, klass->desc->name);
572
573 return EINA_FALSE;
574 }
575
603 /* If we have a current class, we need to itr to the next. */ 576 /* If we have a current class, we need to itr to the next. */
604 if (fptr->cur_klass) 577 if (fptr->cur_klass)
605 { 578 {
@@ -718,25 +691,17 @@ _eo_api_desc_get(const void *api_func, const _Eo_Class *klass, const _Eo_Class *
718 { 691 {
719 for (kls_itr = klass->mro ; *kls_itr ; kls_itr++) 692 for (kls_itr = klass->mro ; *kls_itr ; kls_itr++)
720 { 693 {
694 unsigned int i;
721 cur_klass = *kls_itr; 695 cur_klass = *kls_itr;
722 op_descs = cur_klass->desc->ops.descs; 696 op_descs = cur_klass->desc->ops.descs;
723 697
724#ifndef _WIN32 698#ifndef _WIN32
725 int imin, imax, imid; 699 for (i = 0, op_desc = op_descs; i < cur_klass->desc->ops.count; i++, op_desc++)
726 imin = 0;
727 imax = cur_klass->desc->ops.count - 1;
728
729 while (imax >= imin)
730 { 700 {
731 imid = (imax + imin) / 2; 701 if (op_desc->api_func == api_func)
732 op_desc = op_descs + imid; 702 {
733 703 return op_desc;
734 if (op_desc->api_func > api_func) 704 }
735 imin = imid + 1;
736 else if (op_desc->api_func < api_func)
737 imax = imid - 1;
738 else
739 return op_desc;
740 } 705 }
741#else 706#else
742 /* On Windows, DLL API's will be exported using the dllexport flag. 707 /* On Windows, DLL API's will be exported using the dllexport flag.
@@ -746,7 +711,7 @@ _eo_api_desc_get(const void *api_func, const _Eo_Class *klass, const _Eo_Class *
746 * them. We fallback to plain string comparison based on the 711 * them. We fallback to plain string comparison based on the
747 * function name itself. Slow, but this should rarely happen. 712 * function name itself. Slow, but this should rarely happen.
748 */ 713 */
749 for (unsigned int i = 0; i < cur_klass->desc->ops.count; i++) 714 for (i = 0; i < cur_klass->desc->ops.count; i++)
750 { 715 {
751 if (((op_descs[i].api_func != NULL) && (op_descs[i].api_func != ((void (*)())-1))) && 716 if (((op_descs[i].api_func != NULL) && (op_descs[i].api_func != ((void (*)())-1))) &&
752 (api_func && !strcmp(api_func, op_descs[i].api_func))) 717 (api_func && !strcmp(api_func, op_descs[i].api_func)))
@@ -772,45 +737,13 @@ _eo_api_desc_get(const void *api_func, const _Eo_Class *klass, const _Eo_Class *
772} 737}
773 738
774EAPI Eo_Op 739EAPI Eo_Op
775_eo_api_op_id_get(const void *api_func, Eina_Bool is_main_loop, const char *file, int line) 740_eo_api_op_id_get(const void *api_func)
776{ 741{
777 const Eo_Op_Description *desc; 742 eina_spinlock_take(&_ops_storage_lock);
778 const _Eo_Class *klass; 743 Eo_Op op = (uintptr_t) eina_hash_find(_ops_storage, &api_func);
779 Eo_Call_Stack *stack = _eo_call_stack_get(is_main_loop); 744 eina_spinlock_release(&_ops_storage_lock);
780
781 Eina_Bool class_ref = _eo_is_a_class(stack->frame_ptr->eo_id);
782
783 if (EINA_UNLIKELY(!stack->frame_ptr->o.obj))
784 return EO_NOOP;
785
786 if (class_ref)
787 klass = stack->frame_ptr->o.kls;
788 else
789 klass = stack->frame_ptr->o.obj->klass;
790
791 desc = _eo_api_desc_get(api_func, klass, klass->extensions);
792
793 if (desc == NULL)
794 {
795 const char *fct_name = _eo_op_desc_name_get(desc);
796 ERR("in %s:%d: unable to resolve %s api func '%s' %p in class '%s'.",
797 file, line, (class_ref ? "class" : "regular"),
798 fct_name, api_func, klass->desc->name);
799 return EO_NOOP;
800 }
801
802 return desc->op;
803}
804 745
805static int 746 return op;
806eo_api_funcs_cmp(const void *p1, const void *p2)
807{
808 const Eo_Op_Description *op1, *op2;
809 op1 = (Eo_Op_Description *) p1;
810 op2 = (Eo_Op_Description *) p2;
811 if (op1->api_func > op2->api_func) return -1;
812 else if (op1->api_func < op2->api_func) return 1;
813 else return 0;
814} 747}
815 748
816static Eina_Bool 749static Eina_Bool
@@ -819,9 +752,8 @@ _eo_class_funcs_set(_Eo_Class *klass)
819 unsigned int i; 752 unsigned int i;
820 int op_id; 753 int op_id;
821 const void *last_api_func; 754 const void *last_api_func;
822 const Eo_Op_Description *api_desc; 755 const Eo_Op_Description *op_desc;
823 Eo_Op_Description *op_desc; 756 const Eo_Op_Description *op_descs;
824 Eo_Op_Description *op_descs;
825 757
826 op_id = klass->base_id; 758 op_id = klass->base_id;
827 op_descs = klass->desc->ops.descs; 759 op_descs = klass->desc->ops.descs;
@@ -830,31 +762,37 @@ _eo_class_funcs_set(_Eo_Class *klass)
830 762
831 if (!op_descs) return EINA_TRUE; 763 if (!op_descs) return EINA_TRUE;
832 764
833 qsort((void*)op_descs, klass->desc->ops.count, sizeof(Eo_Op_Description), eo_api_funcs_cmp);
834
835 last_api_func = NULL; 765 last_api_func = NULL;
836 for (i = 0, op_desc = op_descs; i < klass->desc->ops.count; i++, op_desc++) 766 for (i = 0, op_desc = op_descs; i < klass->desc->ops.count; i++, op_desc++)
837 { 767 {
838 if(op_desc->api_func == NULL) 768 Eo_Op op = EO_NOOP;
769
770 if (op_desc->api_func == NULL)
839 { 771 {
840 ERR("Class '%s': NULL API not allowed (%d NULL->%p '%s').", 772 ERR("Class '%s': NULL API not allowed (NULL->%p '%s').",
841 klass->desc->name, op_desc->op, op_desc->func, _eo_op_desc_name_get(op_desc)); 773 klass->desc->name, op_desc->func, _eo_op_desc_name_get(op_desc));
842 return EINA_FALSE; 774 return EINA_FALSE;
843 } 775 }
844 776
845 if (op_desc->op == EO_NOOP) 777 if ((op_desc->op_type == EO_OP_TYPE_REGULAR) || (op_desc->op_type == EO_OP_TYPE_CLASS))
846 { 778 {
847 if (op_desc->api_func == last_api_func) 779 if (op_desc->api_func == last_api_func)
848 { 780 {
849 ERR("Class '%s': API previously defined (%d %p->%p '%s').", 781 ERR("Class '%s': API previously defined (%p->%p '%s').",
850 klass->desc->name, op_desc->op, op_desc->api_func, op_desc->func, _eo_op_desc_name_get(op_desc)); 782 klass->desc->name, op_desc->api_func, op_desc->func, _eo_op_desc_name_get(op_desc));
851 return EINA_FALSE; 783 return EINA_FALSE;
852 } 784 }
853 op_desc->op = op_id; 785
786 op = op_id;
787 eina_spinlock_take(&_ops_storage_lock);
788 eina_hash_add(_ops_storage, &op_desc->api_func, (void *) (uintptr_t) op);
789 eina_spinlock_release(&_ops_storage_lock);
790
854 op_id++; 791 op_id++;
855 } 792 }
856 else if (op_desc->op == EO_OP_OVERRIDE) 793 else if ((op_desc->op_type == EO_OP_TYPE_REGULAR_OVERRIDE) || (op_desc->op_type == EO_OP_TYPE_CLASS_OVERRIDE))
857 { 794 {
795 const Eo_Op_Description *api_desc;
858 api_desc = _eo_api_desc_get(op_desc->api_func, klass->parent, klass->extensions); 796 api_desc = _eo_api_desc_get(op_desc->api_func, klass->parent, klass->extensions);
859 797
860 if (api_desc == NULL) 798 if (api_desc == NULL)
@@ -864,12 +802,19 @@ _eo_class_funcs_set(_Eo_Class *klass)
864 return EINA_FALSE; 802 return EINA_FALSE;
865 } 803 }
866 804
867 op_desc->op = api_desc->op; 805 op = _eo_api_op_id_get(op_desc->api_func);
806 }
807
808 if (op == EO_NOOP)
809 {
810 ERR("Class '%s': Invalid op 'EO_NOOP' (%p->%p '%s').",
811 klass->desc->name, op_desc->api_func, op_desc->func, _eo_op_desc_name_get(op_desc));
812 return EINA_FALSE;
868 } 813 }
869 814
870 DBG(" %4d %p->%p '%s'", op_desc->op, op_desc->api_func, op_desc->func, _eo_op_desc_name_get(op_desc)); 815 DBG("%p->%p '%s'", op_desc->api_func, op_desc->func, _eo_op_desc_name_get(op_desc));
871 816
872 if (!_dich_func_set(klass, op_desc->op, op_desc->func)) 817 if (!_dich_func_set(klass, op, op_desc->func))
873 return EINA_FALSE; 818 return EINA_FALSE;
874 819
875 last_api_func = op_desc->api_func; 820 last_api_func = op_desc->api_func;
@@ -1019,17 +964,6 @@ _eo_add_end(void)
1019 964
1020/*****************************************************************************/ 965/*****************************************************************************/
1021 966
1022#define _EO_OP_ERR_NO_OP_PRINT(file, line, op, klass) \
1023 do \
1024 { \
1025 const _Eo_Class *op_klass = _eo_op_class_get(op); \
1026 const char *_dom_name = (op_klass) ? op_klass->desc->name : NULL; \
1027 ERR("in %s:%d: Can't execute function %s:%s (op 0x%x) for class '%s'. Aborting.", \
1028 file, line, _dom_name, _eo_op_id_name_get(op), op, \
1029 (klass) ? klass->desc->name : NULL); \
1030 } \
1031 while (0)
1032
1033EAPI const Eo_Class * 967EAPI const Eo_Class *
1034eo_class_get(const Eo *eo_id) 968eo_class_get(const Eo *eo_id)
1035{ 969{
@@ -1834,12 +1768,20 @@ eo_init(void)
1834 return EINA_FALSE; 1768 return EINA_FALSE;
1835 } 1769 }
1836 1770
1771 if (!eina_spinlock_new(&_ops_storage_lock))
1772 {
1773 EINA_LOG_ERR("Could not init lock.");
1774 return EINA_FALSE;
1775 }
1776
1837 eina_magic_string_static_set(EO_EINA_MAGIC, EO_EINA_MAGIC_STR); 1777 eina_magic_string_static_set(EO_EINA_MAGIC, EO_EINA_MAGIC_STR);
1838 eina_magic_string_static_set(EO_FREED_EINA_MAGIC, 1778 eina_magic_string_static_set(EO_FREED_EINA_MAGIC,
1839 EO_FREED_EINA_MAGIC_STR); 1779 EO_FREED_EINA_MAGIC_STR);
1840 eina_magic_string_static_set(EO_CLASS_EINA_MAGIC, 1780 eina_magic_string_static_set(EO_CLASS_EINA_MAGIC,
1841 EO_CLASS_EINA_MAGIC_STR); 1781 EO_CLASS_EINA_MAGIC_STR);
1842 1782
1783 _ops_storage = eina_hash_pointer_new(NULL);
1784
1843#ifdef EO_DEBUG 1785#ifdef EO_DEBUG
1844 /* Call it just for coverage purposes. Ugly I know, but I like it better than 1786 /* Call it just for coverage purposes. Ugly I know, but I like it better than
1845 * casting everywhere else. */ 1787 * casting everywhere else. */
@@ -1890,6 +1832,9 @@ eo_shutdown(void)
1890 if (_eo_classes) 1832 if (_eo_classes)
1891 free(_eo_classes); 1833 free(_eo_classes);
1892 1834
1835 eina_hash_free(_ops_storage);
1836
1837 eina_spinlock_free(&_ops_storage_lock);
1893 eina_spinlock_free(&_eo_class_creation_lock); 1838 eina_spinlock_free(&_eo_class_creation_lock);
1894 1839
1895 if (_eo_call_stack_key != 0) 1840 if (_eo_call_stack_key != 0)
diff --git a/src/tests/eo/suite/eo_test_call_errors.c b/src/tests/eo/suite/eo_test_call_errors.c
index 7e00fc1529..e6a9883d6c 100644
--- a/src/tests/eo/suite/eo_test_call_errors.c
+++ b/src/tests/eo/suite/eo_test_call_errors.c
@@ -37,7 +37,7 @@ START_TEST(eo_api_not_implemented_call)
37 Eo *obj = eo_add(SIMPLE_CLASS, NULL); 37 Eo *obj = eo_add(SIMPLE_CLASS, NULL);
38 fail_if(!obj); 38 fail_if(!obj);
39 39
40 TEST_EO_ERROR("_eo_api_op_id_get", "in %s:%d: unable to resolve %s api func '%s' %p in class '%s'."); 40 TEST_EO_ERROR("_eo_call_resolve", "%s:%d: unable to resolve %s api func '%s' in class '%s'.");
41 eo_do(obj, simple_no_implementation()); 41 eo_do(obj, simple_no_implementation());
42 fail_unless(ctx.did); 42 fail_unless(ctx.did);
43 43
diff --git a/src/tests/eo/suite/eo_test_class_errors.c b/src/tests/eo/suite/eo_test_class_errors.c
index e108b5c2d1..03f6eb8f7a 100644
--- a/src/tests/eo/suite/eo_test_class_errors.c
+++ b/src/tests/eo/suite/eo_test_class_errors.c
@@ -230,7 +230,7 @@ START_TEST(eo_null_api)
230 NULL 230 NULL
231 }; 231 };
232 232
233 TEST_EO_ERROR("_eo_class_funcs_set", "Class '%s': NULL API not allowed (%d NULL->%p '%s')."); 233 TEST_EO_ERROR("_eo_class_funcs_set", "Class '%s': NULL API not allowed (NULL->%p '%s').");
234 klass = eo_class_new(&class_desc, NULL, NULL); 234 klass = eo_class_new(&class_desc, NULL, NULL);
235 fail_if(klass); 235 fail_if(klass);
236 fail_unless(ctx.did); 236 fail_unless(ctx.did);
@@ -295,7 +295,7 @@ START_TEST(eo_api_redefined)
295 NULL 295 NULL
296 }; 296 };
297 297
298 TEST_EO_ERROR("_eo_class_funcs_set", "Class '%s': API previously defined (%d %p->%p '%s')."); 298 TEST_EO_ERROR("_eo_class_funcs_set", "Class '%s': API previously defined (%p->%p '%s').");
299 klass = eo_class_new(&class_desc, NULL, NULL); 299 klass = eo_class_new(&class_desc, NULL, NULL);
300 fail_if(klass); 300 fail_if(klass);
301 fail_unless(ctx.did); 301 fail_unless(ctx.did);
@@ -328,7 +328,7 @@ START_TEST(eo_dich_func_override)
328 NULL 328 NULL
329 }; 329 };
330 330
331 TEST_EO_ERROR("_dich_func_set", "Class '%s': Overriding func %p for op %d (%s:'%s') with %p."); 331 TEST_EO_ERROR("_dich_func_set", "Class '%s': Overriding func %p for op %d (%s) with %p.");
332 klass = eo_class_new(&class_desc, SIMPLE_CLASS, NULL); 332 klass = eo_class_new(&class_desc, SIMPLE_CLASS, NULL);
333 fail_if(klass); 333 fail_if(klass);
334 fail_unless(ctx.did); 334 fail_unless(ctx.did);
diff --git a/src/tests/eolian/data/class_simple_ref.c b/src/tests/eolian/data/class_simple_ref.c
index cd1b28ac60..0c6a86fec2 100644
--- a/src/tests/eolian/data/class_simple_ref.c
+++ b/src/tests/eolian/data/class_simple_ref.c
@@ -25,7 +25,7 @@ int _class_simple_bar(Eo *obj, Evas_Simple_Data *pd, int x);
25 25
26EOAPI EO_FUNC_BODYV(evas_obj_simple_bar, int, 0, EO_FUNC_CALL(x), int x); 26EOAPI EO_FUNC_BODYV(evas_obj_simple_bar, int, 0, EO_FUNC_CALL(x), int x);
27 27
28static Eo_Op_Description _class_simple_op_desc[] = { 28static const Eo_Op_Description _class_simple_op_desc[] = {
29 EO_OP_FUNC(evas_obj_simple_a_set, _class_simple_a_set), 29 EO_OP_FUNC(evas_obj_simple_a_set, _class_simple_a_set),
30 EO_OP_FUNC(evas_obj_simple_a_get, _class_simple_a_get), 30 EO_OP_FUNC(evas_obj_simple_a_get, _class_simple_a_get),
31 EO_OP_FUNC(evas_obj_simple_foo, __eolian_class_simple_foo), 31 EO_OP_FUNC(evas_obj_simple_foo, __eolian_class_simple_foo),
@@ -42,4 +42,4 @@ static const Eo_Class_Description _class_simple_class_desc = {
42 NULL 42 NULL
43}; 43};
44 44
45EO_DEFINE_CLASS(class_simple_class_get, &_class_simple_class_desc, NULL, NULL); \ No newline at end of file 45EO_DEFINE_CLASS(class_simple_class_get, &_class_simple_class_desc, NULL, NULL);
diff --git a/src/tests/eolian/data/override_ref.c b/src/tests/eolian/data/override_ref.c
index 2998affe31..934e15ec82 100644
--- a/src/tests/eolian/data/override_ref.c
+++ b/src/tests/eolian/data/override_ref.c
@@ -53,7 +53,7 @@ static void __eolian_override_base_z_set(Eo *obj EINA_UNUSED, Override_Data *pd
53} 53}
54 54
55 55
56static Eo_Op_Description _override_op_desc[] = { 56static const Eo_Op_Description _override_op_desc[] = {
57 EO_OP_FUNC_OVERRIDE(base_constructor, _override_base_constructor), 57 EO_OP_FUNC_OVERRIDE(base_constructor, _override_base_constructor),
58 EO_OP_FUNC_OVERRIDE(base_z_get, __eolian_override_base_z_get), 58 EO_OP_FUNC_OVERRIDE(base_z_get, __eolian_override_base_z_get),
59 EO_OP_FUNC_OVERRIDE(base_z_set, __eolian_override_base_z_set), 59 EO_OP_FUNC_OVERRIDE(base_z_set, __eolian_override_base_z_set),
@@ -78,4 +78,4 @@ static const Eo_Class_Description _override_class_desc = {
78 NULL 78 NULL
79}; 79};
80 80
81EO_DEFINE_CLASS(override_class_get, &_override_class_desc, BASE_CLASS, NULL); \ No newline at end of file 81EO_DEFINE_CLASS(override_class_get, &_override_class_desc, BASE_CLASS, NULL);