Eo: Flatten func array, so function fetching will always be fast.

SVN revision: 70866
This commit is contained in:
Tom Hacohen 2012-05-08 06:56:57 +00:00
parent 7d669b8b27
commit 5c1aa9fd7d
1 changed files with 84 additions and 23 deletions

View File

@ -108,6 +108,7 @@ typedef struct _Dich_Chain1 Dich_Chain1;
typedef struct typedef struct
{ {
eo_op_func_type func; eo_op_func_type func;
const Eo_Class *src;
} op_type_funcs; } op_type_funcs;
struct _Dich_Chain1 struct _Dich_Chain1
@ -146,8 +147,52 @@ struct _Eo_Class
Eina_Bool constructed : 1; Eina_Bool constructed : 1;
}; };
static inline eo_op_func_type static inline void
dich_func_get(const Eo_Class *klass, Eo_Op op) _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; 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)) if (!op_klass || (idxl >= op_klass->desc->ops.count))
return NULL; return NULL;
return chain1->funcs[idxl].func; return &chain1->funcs[idxl];
} }
static inline void 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); const Eo_Class *op_klass = OP_CLASS_GET(op);
size_t num_ops; 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; size_t idx1 = DICH_CHAIN1(op) - 1;
Dich_Chain1 *chain1 = &klass->chain[idx1]; Dich_Chain1 *chain1 = &klass->chain[idx1];
if (!chain1->funcs) _dich_chain_alloc(chain1, num_ops);
{
chain1->funcs = calloc(num_ops, sizeof(*(chain1->funcs)));
}
chain1->funcs[DICH_CHAIN_LAST(op)].func = func; chain1->funcs[DICH_CHAIN_LAST(op)].func = func;
chain1->funcs[DICH_CHAIN_LAST(op)].src = klass;
} }
static inline void static inline void
dich_func_clean_all(Eo_Class *klass) _dich_func_clean_all(Eo_Class *klass)
{ {
size_t i; size_t i;
Dich_Chain1 *chain1 = klass->chain; 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; const Eo_Class **kls_itr = obj->mro_itr.kls_itr;
if (*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; obj->mro_itr.kls_itr = kls_itr;
return *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 prev_state;
_eo_kls_itr_init(obj, op, &prev_state); _eo_kls_itr_init(obj, op, &prev_state);
klass = _eo_kls_itr_get(obj); 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; ret = EINA_TRUE;
goto end; goto end;
} }
klass = _eo_kls_itr_next(obj, op);
} }
/* Try composite objects */ /* Try composite objects */
@ -408,10 +459,8 @@ eo_do_super_internal(Eo *obj, Eina_Bool constant, Eo_Op op, ...)
/* Advance the kls itr. */ /* Advance the kls itr. */
obj_klass = _eo_kls_itr_next(obj, op); obj_klass = _eo_kls_itr_next(obj, op);
if (!obj_klass) if (obj->mro_itr.op != op)
{ return EINA_FALSE;
return EINA_FALSE;
}
va_start(p_list, op); va_start(p_list, op);
if (!_eo_op_internal(obj, constant, op, &p_list)) 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))) 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 else
{ {
@ -630,7 +679,7 @@ eo_class_free(Eo_Class *klass)
if (klass->desc->class_destructor) if (klass->desc->class_destructor)
klass->desc->class_destructor(klass); 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); 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_base_op_init(klass);
_eo_class_constructor(klass); _eo_class_constructor(klass);