From 5c1aa9fd7d15ca60a49489f04ff4dfcb8a1b284f Mon Sep 17 00:00:00 2001 From: Tom Hacohen Date: Tue, 8 May 2012 06:56:57 +0000 Subject: [PATCH] Eo: Flatten func array, so function fetching will always be fast. SVN revision: 70866 --- legacy/eobj/lib/eo.c | 107 +++++++++++++++++++++++++++++++++---------- 1 file changed, 84 insertions(+), 23 deletions(-) diff --git a/legacy/eobj/lib/eo.c b/legacy/eobj/lib/eo.c index 6203e92422..bcaca21a6e 100644 --- a/legacy/eobj/lib/eo.c +++ b/legacy/eobj/lib/eo.c @@ -108,6 +108,7 @@ typedef struct _Dich_Chain1 Dich_Chain1; typedef struct { eo_op_func_type func; + const Eo_Class *src; } op_type_funcs; struct _Dich_Chain1 @@ -146,8 +147,52 @@ struct _Eo_Class Eina_Bool constructed : 1; }; -static inline eo_op_func_type -dich_func_get(const Eo_Class *klass, Eo_Op op) +static inline void +_dich_chain_alloc(Dich_Chain1 *chain1, size_t num_ops) +{ + if (!chain1->funcs) + { + chain1->funcs = calloc(num_ops, sizeof(*(chain1->funcs))); + } +} + +static inline void +_dich_copy_all(Eo_Class *dst, const Eo_Class *src) +{ + if (!src->chain) return; + + if (!dst->chain) + { + dst->chain = calloc(dst->class_id, sizeof(*dst->chain)); + } + + Eo_Class_Id i; + const Dich_Chain1 *sc1 = src->chain; + Dich_Chain1 *dc1 = dst->chain; + for (i = 0 ; i < src->class_id ; i++, sc1++, dc1++) + { + if (sc1->funcs) + { + size_t j; + const Eo_Class *op_klass = ID_CLASS_GET(i + 1); + size_t num_ops = op_klass->desc->ops.count; + _dich_chain_alloc(dc1, num_ops); + + const op_type_funcs *sf = sc1->funcs; + op_type_funcs *df = dc1->funcs; + for (j = 0 ; j < num_ops ; j++, df++, sf++) + { + if (sf->func) + { + memcpy(df, sf, sizeof(*df)); + } + } + } + } +} + +static inline const op_type_funcs * +_dich_func_get(const Eo_Class *klass, Eo_Op op) { if (!klass->chain) return NULL; @@ -162,11 +207,11 @@ dich_func_get(const Eo_Class *klass, Eo_Op op) if (!op_klass || (idxl >= op_klass->desc->ops.count)) return NULL; - return chain1->funcs[idxl].func; + return &chain1->funcs[idxl]; } static inline void -dich_func_set(Eo_Class *klass, Eo_Op op, eo_op_func_type func) +_dich_func_set(Eo_Class *klass, Eo_Op op, eo_op_func_type func) { const Eo_Class *op_klass = OP_CLASS_GET(op); size_t num_ops; @@ -196,16 +241,13 @@ dich_func_set(Eo_Class *klass, Eo_Op op, eo_op_func_type func) size_t idx1 = DICH_CHAIN1(op) - 1; Dich_Chain1 *chain1 = &klass->chain[idx1]; - if (!chain1->funcs) - { - chain1->funcs = calloc(num_ops, sizeof(*(chain1->funcs))); - } - + _dich_chain_alloc(chain1, num_ops); chain1->funcs[DICH_CHAIN_LAST(op)].func = func; + chain1->funcs[DICH_CHAIN_LAST(op)].src = klass; } static inline void -dich_func_clean_all(Eo_Class *klass) +_dich_func_clean_all(Eo_Class *klass) { size_t i; Dich_Chain1 *chain1 = klass->chain; @@ -294,7 +336,18 @@ _eo_kls_itr_next(Eo *obj, Eo_Op op) const Eo_Class **kls_itr = obj->mro_itr.kls_itr; if (*kls_itr) { - kls_itr++; + if (op != EO_NOOP) + { + const op_type_funcs *fsrc = _dich_func_get(*kls_itr, op); + + while (*kls_itr && (*(kls_itr++) != fsrc->src)) + ; + } + else + { + kls_itr++; + } + obj->mro_itr.kls_itr = kls_itr; return *kls_itr; } @@ -329,18 +382,16 @@ _eo_op_internal(Eo *obj, Eina_Bool constant, Eo_Op op, va_list *p_list) Eo_Kls_Itr prev_state; _eo_kls_itr_init(obj, op, &prev_state); klass = _eo_kls_itr_get(obj); - while (klass) + if (klass) { - eo_op_func_type func = dich_func_get(klass, op); + const op_type_funcs *func = _dich_func_get(klass, op); - if (func) + if (func && func->func) { - func(obj, _eo_data_get(obj, klass), p_list); + func->func(obj, _eo_data_get(obj, func->src), p_list); ret = EINA_TRUE; goto end; } - - klass = _eo_kls_itr_next(obj, op); } /* Try composite objects */ @@ -408,10 +459,8 @@ eo_do_super_internal(Eo *obj, Eina_Bool constant, Eo_Op op, ...) /* Advance the kls itr. */ obj_klass = _eo_kls_itr_next(obj, op); - if (!obj_klass) - { - return EINA_FALSE; - } + if (obj->mro_itr.op != op) + return EINA_FALSE; va_start(p_list, op); if (!_eo_op_internal(obj, constant, op, &p_list)) @@ -612,7 +661,7 @@ eo_class_funcs_set(Eo_Class *klass, const Eo_Op_Func_Description *func_descs) if (EINA_LIKELY(!op_desc || (itr->constant == op_desc->constant))) { - dich_func_set(klass, itr->op, itr->func); + _dich_func_set(klass, itr->op, itr->func); } else { @@ -630,7 +679,7 @@ eo_class_free(Eo_Class *klass) if (klass->desc->class_destructor) klass->desc->class_destructor(klass); - dich_func_clean_all(klass); + _dich_func_clean_all(klass); } { @@ -860,6 +909,18 @@ eo_class_new(const Eo_Class_Description *desc, const Eo_Class *parent, ...) EINA_MAGIC_SET(klass, EO_CLASS_EINA_MAGIC); + /* Flatten the function array */ + { + const Eo_Class **mro_itr = klass->mro; + for ( ; *mro_itr ; mro_itr++) + ; + + for ( mro_itr-- ; mro_itr >= klass->mro ; mro_itr--) + { + _dich_copy_all(klass, *mro_itr); + } + } + _eo_class_base_op_init(klass); _eo_class_constructor(klass);