EAPI Eo *
efl_super(const Eo *obj, const Efl_Class *cur_klass)
{
- EO_CLASS_POINTER_RETURN_VAL(cur_klass, klass, NULL);
+ EO_CLASS_POINTER_GOTO(cur_klass, klass, err);
/* FIXME: Switch to atomic operations intead of lock. */
eina_spinlock_take(&_super_class_lock);
_super_class = klass;
return (Eo *) ((Eo_Id) obj | MASK_SUPER_TAG);
+err:
+ _EO_POINTER_ERR("Class (%p) is an invalid ref.", cur_klass);
+ return NULL;
}
EAPI Eina_Bool
eo_id = (Eo *) ((Eo_Id) eo_id & ~MASK_SUPER_TAG);
}
- if (EINA_UNLIKELY(!eo_id))
- return EINA_FALSE;
+ if (EINA_UNLIKELY(!eo_id)) return EINA_FALSE;
call->eo_id = eo_id;
}
#endif
func = _vtable_func_get(vtable, cache->op);
+ // this is not very likely to happen - but may if its an invalid
+ // call or a composite object, but either way, it's not very likely
+ // so make it a goto to save on instruction cache
if (!func) goto end;
}
ok_cur_klass_back:
return EINA_TRUE;
}
+ // very unlikely in general to use a goto to move code out of l1 cache
+ // ie instruction cache
if (func->src != NULL) goto err_func_src;
end:
}
}
- /* If it's a do_super call. */
+ // all of this is error handling at the end so... rare-ish
+ // If it's a do_super call.
if (cur_klass)
{
ERR("in %s:%d: func '%s' (%d) could not be resolved for class '%s' for super of '%s'.",
// yes - special "move out of hot path" code blobs with goto's for
// speed reasons to have intr prefetches work better and miss less
ok_cur_klass:
- {
- func = _eo_kls_itr_next(klass, cur_klass, cache->op);
- if (!func) goto end;
- klass = func->src;
- }
+ func = _eo_kls_itr_next(klass, cur_klass, cache->op);
+ if (!func) goto end;
+ klass = func->src;
goto ok_cur_klass_back;
ok_klass:
{
- EO_CLASS_POINTER_RETURN_VAL(eo_id, _klass, EINA_FALSE);
+ EO_CLASS_POINTER_GOTO(eo_id, _klass, err_klass);
klass = _klass;
vtable = &klass->vtable;
call->obj = NULL;
}
goto ok_klass_back;
+err_klass:
+ _EO_POINTER_ERR("Class (%p) is an invalid ref.", eo_id);
return EINA_FALSE;
}
}
}
-/*
-EAPI void
-_efl_shared_lock(const Eo *eo_id)
-{
-#ifdef HAVE_EO_ID
- Efl_Id_Domain domain = ((Eo_Id)eo_id >> SHIFT_DOMAIN) & MASK_DOMAIN;
- if (EINA_LIKELY(domain != EFL_ID_DOMAIN_SHARED)) return;
- eina_lock_take(&(_eo_table_data_shared_data->obj_lock));
-#endif
-}
-
-EAPI void
-_efl_shared_unlock(const Eo *eo_id)
-{
-#ifdef HAVE_EO_ID
- Efl_Id_Domain domain = ((Eo_Id)eo_id >> SHIFT_DOMAIN) & MASK_DOMAIN;
- if (EINA_LIKELY(domain != EFL_ID_DOMAIN_SHARED)) return;
- eina_lock_release(&(_eo_table_data_shared_data->obj_lock));
-#endif
-}
-*/
-
static inline Eina_Bool
_eo_api_func_equal(const void *api_func1, const void *api_func2)
{
EAPI Eina_Bool
efl_class_functions_set(const Efl_Class *klass_id, const Efl_Object_Ops *object_ops, const Efl_Object_Ops *class_ops)
{
- EO_CLASS_POINTER_RETURN_VAL(klass_id, klass, EINA_FALSE);
+ EO_CLASS_POINTER_GOTO(klass_id, klass, err_klass);
Efl_Object_Ops empty_ops = { 0 };
- if (klass->functions_set)
- {
- ERR("Class %s already had its functions set..", klass->desc->name);
- return EINA_FALSE;
- }
+ // not likely so use goto to alleviate l1 instruction cache of rare code
+ if (klass->functions_set) goto err_funcs;
klass->functions_set = EINA_TRUE;
- if (!object_ops)
- {
- object_ops = &empty_ops;
- }
+ if (!object_ops) object_ops = &empty_ops;
- if (!class_ops)
- {
- class_ops = &empty_ops;
- }
+ if (!class_ops) class_ops = &empty_ops;
klass->ops_count = object_ops->count + class_ops->count;
_vtable_init(&klass->vtable, DICH_CHAIN1(_eo_ops_last_id) + 1);
-
/* Flatten the function array */
{
const _Efl_Class **mro_itr = klass->mro;
- for ( ; *mro_itr ; mro_itr++)
- ;
+ for ( ; *mro_itr ; mro_itr++) ;
/* Skip ourselves. */
for ( mro_itr-- ; mro_itr > klass->mro ; mro_itr--)
- {
- _vtable_copy_all(&klass->vtable, &(*mro_itr)->vtable);
- }
+ _vtable_copy_all(&klass->vtable, &(*mro_itr)->vtable);
}
return _eo_class_funcs_set(&klass->vtable, object_ops, klass, klass, 0, EINA_FALSE) &&
_eo_class_funcs_set(&klass->vtable, class_ops, klass, klass, object_ops->count, EINA_FALSE);
+
+err_funcs:
+ ERR("Class %s already had its functions set..", klass->desc->name);
+ return EINA_FALSE;
+err_klass:
+ _EO_POINTER_ERR("Class (%p) is an invalid ref.", klass_id);
+ return EINA_FALSE;
}
EAPI Eo *
_Eo_Object *obj;
Eo_Stack_Frame *fptr = NULL;
- if (is_fallback)
- {
- fptr = _efl_add_fallback_stack_push(NULL);
- }
+ if (is_fallback) fptr = _efl_add_fallback_stack_push(NULL);
- EO_CLASS_POINTER_RETURN_VAL(klass_id, klass, NULL);
+ EO_CLASS_POINTER_GOTO(klass_id, klass, err_klass);
if (parent_id)
{
- EO_OBJ_POINTER_RETURN_VAL(parent_id, parent, NULL);
+ EO_OBJ_POINTER_GOTO(parent_id, parent, err_parent);
}
+ // not likely so use goto to alleviate l1 instruction cache of rare code
if (EINA_UNLIKELY(klass->desc->type != EFL_CLASS_TYPE_REGULAR))
- {
- ERR("in %s:%d: Class '%s' is not instantiate-able. Aborting.", file, line, klass->desc->name);
- if (parent_id) EO_OBJ_DONE(parent_id);
- return NULL;
- }
+ goto err_noreg;
eina_spinlock_take(&klass->objects.trash_lock);
obj = eina_trash_pop(&klass->objects.trash);
/* eo_id can change here. Freeing is done on the resolved object. */
eo_id = efl_constructor(eo_id);
- if (!eo_id)
- {
- ERR("Object of class '%s' - Error while constructing object",
- klass->desc->name);
+ // not likely so use goto to alleviate l1 instruction cache of rare code
+ if (!eo_id) goto err_noid;
+ // not likely so use goto to alleviate l1 instruction cache of rare code
+ else if (eo_id != _eo_obj_id_get(obj)) goto ok_nomatch;
+ok_nomatch_back:
+ if (is_fallback) fptr->obj = eo_id;
+ if (parent_id) EO_OBJ_DONE(parent_id);
+ return eo_id;
- /* We have two refs at this point. */
- _efl_unref(obj);
- efl_del((Eo *) obj->header.id);
- if (parent_id) EO_OBJ_DONE(parent_id);
- return NULL;
- }
- else if (eo_id != _eo_obj_id_get(obj))
+ok_nomatch:
{
- EO_OBJ_POINTER_RETURN_VAL(eo_id, new_obj, NULL);
+ EO_OBJ_POINTER_GOTO(eo_id, new_obj, err_newid);
/* We have two refs at this point. */
_efl_unref(obj);
- efl_del((Eo *) obj->header.id);
-
+ efl_del((Eo *)obj->header.id);
_efl_ref(new_obj);
EO_OBJ_DONE(eo_id);
}
+ goto ok_nomatch_back;
- if (is_fallback)
- {
- fptr->obj = eo_id;
- }
-
+err_noid:
+ ERR("Object of class '%s' - Error while constructing object",
+ klass->desc->name);
+ /* We have two refs at this point. */
+ _efl_unref(obj);
+ efl_del((Eo *) obj->header.id);
+err_newid:
if (parent_id) EO_OBJ_DONE(parent_id);
- return eo_id;
+ return NULL;
+err_noreg:
+ ERR("in %s:%d: Class '%s' is not instantiate-able. Aborting.", file, line, klass->desc->name);
+ if (parent_id) EO_OBJ_DONE(parent_id);
+ return NULL;
+
+err_klass:
+ _EO_POINTER_ERR("Class (%p) is an invalid ref.", klass_id);
+err_parent:
+ return NULL;
}
static Eo *
{
EO_OBJ_POINTER_RETURN_VAL(eo_id, obj, NULL);
- if (!obj->condtor_done)
- {
- const _Efl_Class *klass = obj->klass;
-
- ERR("Object of class '%s' - Not all of the object constructors have been executed.",
- klass->desc->name);
- goto cleanup;
- }
-
+ // rare so move error handling to end to save l1 instruction cache
+ if (!obj->condtor_done) goto err_condtor;
if (!finalized_id)
{
// XXX: Given EFL usage of objects, construction is a perfectly valid thing
}
obj->finalized = EINA_TRUE;
-
_efl_unref(obj);
EO_OBJ_DONE(eo_id);
return (Eo *)eo_id;
+err_condtor:
+ {
+ const _Efl_Class *klass = obj->klass;
+ ERR("Object of class '%s' - Not all of the object constructors have been executed.",
+ klass->desc->name);
+ }
cleanup:
_efl_unref(obj);
efl_del((Eo *) obj->header.id);
if (_eo_is_a_class(eo_id))
{
- EO_CLASS_POINTER_RETURN_VAL(eo_id, _klass, NULL);
+ EO_CLASS_POINTER_GOTO(eo_id, _klass, err_klass);
return EFL_CLASS_CLASS;
}
- EO_OBJ_POINTER_RETURN_VAL(eo_id, obj, NULL);
+ EO_OBJ_POINTER_GOTO(eo_id, obj, err_obj);
klass = _eo_class_id_get(obj->klass);
EO_OBJ_DONE(eo_id);
return klass;
+
+err_klass:
+ _EO_POINTER_ERR("Class (%p) is an invalid ref.", eo_id);
+err_obj:
+ return NULL;
}
EAPI const char *
if (_eo_is_a_class(eo_id))
{
- EO_CLASS_POINTER_RETURN_VAL(eo_id, _klass, NULL);
+ EO_CLASS_POINTER_GOTO(eo_id, _klass, err_klass);
klass = _klass;
}
else
{
- EO_OBJ_POINTER_RETURN_VAL(eo_id, obj, NULL);
+ EO_OBJ_POINTER_GOTO(eo_id, obj, err_obj);
klass = obj->klass;
EO_OBJ_DONE(eo_id);
}
return klass->desc->name;
+
+err_klass:
+ _EO_POINTER_ERR("Class (%p) is an invalid ref.", eo_id);
+err_obj:
+ return NULL;
}
static void
efl_object_override(Eo *eo_id, const Efl_Object_Ops *ops)
{
EO_OBJ_POINTER_RETURN_VAL(eo_id, obj, EINA_FALSE);
- EO_CLASS_POINTER_RETURN_VAL(EFL_OBJECT_OVERRIDE_CLASS, klass, EINA_FALSE);
+ EO_CLASS_POINTER_GOTO(EFL_OBJECT_OVERRIDE_CLASS, klass, err_done);
Eo_Vtable *previous = obj->vtable;
if (ops)
obj->vtable = calloc(1, sizeof(*obj->vtable));
_vtable_init(obj->vtable, previous->size);
_vtable_copy_all(obj->vtable, previous);
+ // rare so move error handling to end to save l1 instruction cache
if (!_eo_class_funcs_set(obj->vtable, ops, obj->klass,
klass, 0, EINA_TRUE))
goto err;
goto done;
}
+ // rare so move error handling to end to save l1 instruction cache
else goto err_already;
}
else
(tdata->cache.klass == klass_id))
{
isa = tdata->cache.isa;
- goto done;
+ // since this is the cache we hope this gets a lot of hits and
+ // thus lets assume the hit is the mot important thing thus
+ // put the lock release and return here inline in the l1
+ // instruction cache hopefully already fetched
+ eina_lock_release(&(_eo_table_data_shared_data->obj_lock));
+ return isa;
}
EO_OBJ_POINTER_GOTO(eo_id, obj, err_shared_obj);
// Currently implemented by reusing the LAST op id. Just marking it with
// _eo_class_isa_func.
isa = tdata->cache.isa = (func && (func->func == _eo_class_isa_func));
-done:
eina_lock_release(&(_eo_table_data_shared_data->obj_lock));
}
return isa;
EAPI void *
efl_data_scope_get(const Eo *obj_id, const Efl_Class *klass_id)
{
- void *ret;
+ void *ret = NULL;
EO_OBJ_POINTER_RETURN_VAL(obj_id, obj, NULL);
- EO_CLASS_POINTER_RETURN_VAL(klass_id, klass, NULL);
+ EO_CLASS_POINTER_GOTO(klass_id, klass, err_klass);
#ifdef EO_DEBUG
- if (!_eo_class_mro_has(obj->klass, klass))
- {
- ERR("Tried getting data of class '%s' from object of class '%s', but the former is not a direct inheritance of the latter.", klass->desc->name, obj->klass->desc->name);
- EO_OBJ_DONE(obj_id);
- return NULL;
- }
+ if (_eo_class_mro_has(obj->klass, klass))
#endif
-
- ret = _efl_data_scope_safe_get(obj, klass);
+ ret = _efl_data_scope_safe_get(obj, klass);
#ifdef EO_DEBUG
- if (!ret && (klass->desc->data_size == 0))
- ERR("Tried getting data of class '%s', but it has none.", klass->desc->name);
+ // rare to make it a goto to clear out instruction cache of rare code
+ else goto err_mro;
+ // rare to make it a goto to clear out instruction cache of rare code
+ if (!ret && (klass->desc->data_size == 0)) goto err_ret;
+ EO_OBJ_DONE(obj_id);
+ return ret;
+
+err_ret:
+ ERR("Tried getting data of class '%s', but it has none.", klass->desc->name);
+ goto err_klass;
+err_mro:
+ ERR("Tried getting data of class '%s' from object of class '%s', but the former is not a direct inheritance of the latter.", klass->desc->name, obj->klass->desc->name);
#endif
+err_klass:
EO_OBJ_DONE(obj_id);
return ret;
}
{
if (klass_id)
{
- EO_CLASS_POINTER_RETURN_VAL(klass_id, klass2, NULL);
+ EO_CLASS_POINTER_GOTO(klass_id, klass2, err_klass);
klass = klass2;
#ifdef EO_DEBUG
- if (!_eo_class_mro_has(obj->klass, klass))
- {
- ERR("Tried getting data of class '%s' from object of class '%s', but the former is not a direct inheritance of the latter.", klass->desc->name, obj->klass->desc->name);
- EO_OBJ_DONE(obj_id);
- EO_OBJ_DONE(ref_obj_id);
- return NULL;
- }
+ // rare to use goto to keep instruction cache cleaner
+ if (!_eo_class_mro_has(obj->klass, klass)) goto err_mro;
#endif
}
ret = _efl_data_xref_internal(file, line, obj, klass, ref_obj);
#ifdef EO_DEBUG
- if (klass && !ret && (klass->desc->data_size == 0))
- ERR("Tried getting data of class '%s', but it has none.", klass->desc->name);
+ // rare to use goto to keep instruction cache cleaner
+ if (klass && !ret && (klass->desc->data_size == 0)) goto err_ret;
#endif
+err_klass:
EO_OBJ_DONE(ref_obj_id);
}
EO_OBJ_DONE(obj_id);
return ret;
+#ifdef EO_DEBUG
+err_ret:
+ ERR("Tried getting data of class '%s', but it has none.", klass->desc->name);
+ goto err;
+err_mro:
+ ERR("Tried getting data of class '%s' from object of class '%s', but the former is not a direct inheritance of the latter.", klass->desc->name, obj->klass->desc->name);
+err:
+ EO_OBJ_DONE(obj_id);
+ EO_OBJ_DONE(ref_obj_id);
+ return NULL;
+#endif
}
EAPI void
{
EO_OBJ_POINTER_RETURN_VAL(obj_id, obj, EINA_FALSE);
+ // rare to use goto to keep instruction cache cleaner
if (obj->manual_free == EINA_FALSE) goto err_manual_free;
+ // rare to use goto to keep instruction cache cleaner
if (!obj->destructed) goto err_not_destructed;
_eo_free(obj);
EO_OBJ_DONE(obj_id);
EOLIAN static void
_efl_object_parent_set(Eo *obj, Efl_Object_Data *pd, Eo *parent_id)
{
- if (pd->parent == parent_id)
+ if ((pd->parent == parent_id) ||
+ ((parent_id) && (!_eo_id_domain_compatible(parent_id, obj))))
return;
- if (parent_id)
- {
- if (!_eo_id_domain_compatible(parent_id, obj)) return;
- }
EO_OBJ_POINTER(obj, eo_obj);
-
if (pd->parent)
{
- Efl_Object_Data *old_parent_pd;
+ Efl_Object_Data *old_parent_pd = efl_data_scope_get(pd->parent,
+ EFL_OBJECT_CLASS);
- old_parent_pd = efl_data_scope_get(pd->parent, EFL_OBJECT_CLASS);
if (old_parent_pd)
- {
- old_parent_pd->children = eina_inlist_remove(old_parent_pd->children,
- EINA_INLIST_GET(eo_obj));
- }
- else
- {
- ERR("CONTACT DEVS!!! SHOULD NEVER HAPPEN!!! Old parent %p for object %p is not a valid Eo object.",
- pd->parent, obj);
- }
+ old_parent_pd->children = eina_inlist_remove(old_parent_pd->children,
+ EINA_INLIST_GET(eo_obj));
+ // this error is highly unlikely so move it out of the normal
+ // instruction path to avoid l1 cache pollution
+ else goto err_impossible;
/* Only unref if we don't have a new parent instead and we are not at
* the process of deleting the object.*/
- if (!parent_id && !eo_obj->del_triggered)
- {
- efl_unref(obj);
- }
+ if (!parent_id && !eo_obj->del_triggered) efl_unref(obj);
}
/* Set new parent */
if (parent_id)
{
- Efl_Object_Data *parent_pd = NULL;
- parent_pd = efl_data_scope_get(parent_id, EFL_OBJECT_CLASS);
+ Efl_Object_Data *parent_pd = efl_data_scope_get(parent_id,
+ EFL_OBJECT_CLASS);
if (EINA_LIKELY(parent_pd != NULL))
{
pd->parent = parent_id;
parent_pd->children = eina_inlist_append(parent_pd->children,
- EINA_INLIST_GET(eo_obj));
+ EINA_INLIST_GET(eo_obj));
}
else
{
pd->parent = NULL;
- ERR("New parent %p for object %p is not a valid Eo object.",
- parent_id, obj);
+ // unlikely this error happens, so move it out of execution path
+ // to improve l1 cache efficiency
+ goto err_parent;
}
}
- else
- {
- pd->parent = NULL;
- }
+ else pd->parent = NULL;
+
EO_OBJ_DONE(obj);
+ return;
+err_parent:
+ ERR("New parent %p for object %p is not a valid Eo object.",
+ parent_id, obj);
+ return;
+err_impossible:
+ ERR("CONTACT DEVS!!! SHOULD NEVER HAPPEN!!! Old parent %p for object %p is not a valid Eo object.",
+ pd->parent, obj);
}
EOLIAN static Eo *
_efl_object_children_iterator_new(Eo *obj_id, Efl_Object_Data *pd)
{
_Efl_Class *klass;
- Eo_Children_Iterator *it;
+ Eo_Children_Iterator *it = NULL;
EO_OBJ_POINTER_RETURN_VAL(obj_id, obj, NULL);
- if (!pd->children)
- {
- EO_OBJ_DONE(obj_id);
- return NULL;
- }
-
- klass = (_Efl_Class *) obj->klass;
-
- eina_spinlock_take(&klass->iterators.trash_lock);
- it = eina_trash_pop(&klass->iterators.trash);
- if (it)
- {
- klass->iterators.trash_count--;
- memset(it, 0, sizeof (Eo_Children_Iterator));
- }
- else
+ if (pd->children)
{
- it = calloc(1, sizeof (Eo_Children_Iterator));
- }
- eina_spinlock_release(&klass->iterators.trash_lock);
- if (!it) return NULL;
-
- EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
- it->current = pd->children;
- it->obj = _efl_ref(obj);
- it->obj_id = obj_id;
-
- it->iterator.next = FUNC_ITERATOR_NEXT(_efl_children_iterator_next);
- it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_efl_children_iterator_container);
- it->iterator.free = FUNC_ITERATOR_FREE(_efl_children_iterator_free);
+ klass = (_Efl_Class *)obj->klass;
+ eina_spinlock_take(&klass->iterators.trash_lock);
+ it = eina_trash_pop(&klass->iterators.trash);
+ if (it)
+ {
+ klass->iterators.trash_count--;
+ memset(it, 0, sizeof (Eo_Children_Iterator));
+ }
+ else it = calloc(1, sizeof (Eo_Children_Iterator));
+ eina_spinlock_release(&klass->iterators.trash_lock);
+ // very unlikely to not allocate the iterator to move this error
+ // handling out of l1 instruction cache
+ if (!it) goto done;
+
+ EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
+ it->current = pd->children;
+ it->obj = _efl_ref(obj);
+ it->obj_id = obj_id;
+ it->iterator.next = FUNC_ITERATOR_NEXT(_efl_children_iterator_next);
+ it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_efl_children_iterator_container);
+ it->iterator.free = FUNC_ITERATOR_FREE(_efl_children_iterator_free);
+ }
+done:
EO_OBJ_DONE(obj_id);
return (Eina_Iterator *)it;
}
count += 1; /* New wref. */
ext = _efl_object_extension_need(pd);
- if (!ext) return;
-
- tmp = realloc(ext->wrefs, sizeof(*ext->wrefs) * (count + 1));
- if (!tmp) return;
- ext->wrefs = tmp;
-
- ext->wrefs[count - 1] = wref;
- ext->wrefs[count] = NULL;
- *wref = obj;
+ if (ext)
+ {
+ tmp = realloc(ext->wrefs, sizeof(*ext->wrefs) * (count + 1));
+ if (tmp)
+ {
+ ext->wrefs = tmp;
+ ext->wrefs[count - 1] = wref;
+ ext->wrefs[count] = NULL;
+ *wref = obj;
+ }
+ }
}
EOLIAN static void
size_t count;
Efl_Object_Extension *ext = pd->ext;
- if (*wref != obj)
- {
- ERR("Wref is a weak ref to %p, while this function was called on %p.",
- *wref, obj);
- return;
- }
+ // very unlikely so improve l1 instr cache by using goto
+ if (*wref != obj) goto err_wref_not_obj;
- if ((!ext) || (!ext->wrefs))
- {
- ERR("There are no weak refs for object %p", obj);
- *wref = NULL;
- return;
- }
+ // very unlikely so improve l1 instr cache by using goto
+ if ((!ext) || (!ext->wrefs)) goto err_wref_none;
/* Move the last item in the array instead of the current wref. */
count = _wref_count(pd);
break;
}
}
-
- if (!*itr)
- {
- ERR("Wref %p is not associated with object %p", wref, obj);
- *wref = NULL;
- return;
- }
+ // very unlikely so improve l1 instr cache by using goto
+ if (!*itr) goto err_noiter;
}
if (count > 1)
if (!tmp) return;
ext->wrefs = tmp;
ext->wrefs[count - 1] = NULL;
+ *wref = NULL;
+ return;
}
else
{
}
*wref = NULL;
+ return;
+
+err_noiter:
+ ERR("Wref %p is not associated with object %p", wref, obj);
+ goto err_null;
+err_wref_none:
+ ERR("There are no weak refs for object %p", obj);
+err_null:
+ *wref = NULL;
+ return;
+err_wref_not_obj:
+ ERR("Wref is a weak ref to %p, while this function was called on %p.",
+ *wref, obj);
+ return;
}
static inline void
_eo_callback_new(void)
{
Eo_Callback_Description *cb;
- if (!_eo_callback_mempool)
- {
- _eo_callback_mempool = eina_mempool_add
- ("chained_mempool",
- NULL, NULL,
- sizeof(Eo_Callback_Description), 256);
- if (!_eo_callback_mempool) return NULL;
- }
+ // very unlikely that the mempool isnt initted, so take all the init code
+ // and move it out of l1 instruction cache space so we dont pollute the
+ // l1 cache with unused code 99% of the time
+ if (!_eo_callback_mempool) goto init_mempool;
+init_mempool_back:
+
cb = eina_mempool_calloc(_eo_callback_mempool,
sizeof(Eo_Callback_Description));
- if (!cb)
+ if (cb)
{
- if (_eo_callbacks == 0)
- {
- eina_mempool_del(_eo_callback_mempool);
- _eo_callback_mempool = NULL;
- }
- return NULL;
+ _eo_callbacks++;
+ return cb;
}
- _eo_callbacks++;
- return cb;
+ if (_eo_callbacks != 0) return NULL;
+ eina_mempool_del(_eo_callback_mempool);
+ _eo_callback_mempool = NULL;
+ return NULL;
+init_mempool:
+ _eo_callback_mempool = eina_mempool_add
+ ("chained_mempool", NULL, NULL, sizeof(Eo_Callback_Description), 256);
+ if (!_eo_callback_mempool) return NULL;
+ goto init_mempool_back;
}
/* Actually remove, doesn't care about walking list, or delete_me */
_eo_callback_search_sorted_near(const Efl_Object_Data *pd, const Eo_Callback_Description *look)
{
unsigned int start, last, middle;
+ const Eo_Callback_Description *p;
+ int cmp;
- if (pd->callbacks_count == 0)
- {
- return 0;
- }
- else if (pd->callbacks_count == 1)
- {
- return 0;
- }
+ if (pd->callbacks_count == 0) return 0;
+ else if (pd->callbacks_count == 1) return 0;
start = 0;
last = pd->callbacks_count - 1;
do
{
- const Eo_Callback_Description *p;
- int cmp;
-
middle = start + (last - start) / 2;
p = pd->callbacks[middle];
cmp = p->priority - look->priority;
- if (cmp == 0)
- return middle;
- else if (cmp > 0)
- start = middle + 1;
- else if (middle > 0)
- last = middle - 1;
- else
- break ;
+ if (cmp == 0) return middle;
+ else if (cmp > 0) start = middle + 1;
+ else if (middle > 0) last = middle - 1;
+ else break;
}
while (start <= last);
return middle;
EOLIAN static Eina_Bool
_efl_object_event_callback_priority_add(Eo *obj, Efl_Object_Data *pd,
- const Efl_Event_Description *desc,
- Efl_Callback_Priority priority,
- Efl_Event_Cb func,
- const void *user_data)
+ const Efl_Event_Description *desc,
+ Efl_Callback_Priority priority,
+ Efl_Event_Cb func,
+ const void *user_data)
{
const Efl_Callback_Array_Item arr[] = { {desc, func}, {NULL, NULL}};
Eo_Callback_Description *cb = _eo_callback_new();
- if (!cb || !desc || !func)
- {
- ERR("Tried adding callback with invalid values: cb: %p desc: %p func: %p\n", cb, desc, func);
- _eo_callback_free(cb);
- return EINA_FALSE;
- }
+ // very unlikely so improve l1 instr cache by using goto
+ if (!cb || !desc || !func) goto err;
cb->items.item.desc = desc;
cb->items.item.func = func;
cb->func_data = (void *) user_data;
efl_event_callback_call(obj, EFL_EVENT_CALLBACK_ADD, (void *)arr);
return EINA_TRUE;
+
+err:
+ ERR("Tried adding callback with invalid values: cb: %p desc: %p func: %p\n", cb, desc, func);
+ _eo_callback_free(cb);
+ return EINA_FALSE;
}
EOLIAN static Eina_Bool
EOLIAN static Eina_Bool
_efl_object_event_callback_array_priority_add(Eo *obj, Efl_Object_Data *pd,
- const Efl_Callback_Array_Item *array,
- Efl_Callback_Priority priority,
- const void *user_data)
+ const Efl_Callback_Array_Item *array,
+ Efl_Callback_Priority priority,
+ const void *user_data)
{
Eo_Callback_Description *cb = _eo_callback_new();
#ifdef EO_DEBUG
const Efl_Callback_Array_Item *prev;
#endif
- if (!cb || !array)
- {
- ERR("Tried adding array of callbacks with invalid values: cb: %p array: %p.", cb, array);
- _eo_callback_free(cb);
- return EINA_FALSE;
- }
-
+ // very unlikely so improve l1 instr cache by using goto
+ if (!cb || !array) goto err;
#ifdef EO_DEBUG
prev = array;
for (it = prev + 1; prev->func && it->func; it++, prev++)
efl_event_callback_call(obj, EFL_EVENT_CALLBACK_ADD, (void *)array);
return EINA_TRUE;
+
+err:
+ ERR("Tried adding array of callbacks with invalid values: cb: %p array: %p.", cb, array);
+ _eo_callback_free(cb);
+ return EINA_FALSE;
}
EOLIAN static Eina_Bool
_efl_object_event_callback_array_del(Eo *obj, Efl_Object_Data *pd,
- const Efl_Callback_Array_Item *array,
- const void *user_data)
+ const Efl_Callback_Array_Item *array,
+ const void *user_data)
{
Eo_Callback_Description **cb;
unsigned int i;
_cb_desc_match(const Efl_Event_Description *a, const Efl_Event_Description *b, Eina_Bool legacy_compare)
{
/* If one is legacy and the other is not, strcmp. Else, pointer compare. */
- if (EINA_UNLIKELY(legacy_compare && (_legacy_event_desc_is(a) != _legacy_event_desc_is(b))))
- {
- return !strcmp(a->name, b->name);
- }
-
- return (a == b);
+ if (!EINA_UNLIKELY(legacy_compare && (_legacy_event_desc_is(a) != _legacy_event_desc_is(b))))
+ return (a == b);
+ return !strcmp(a->name, b->name);
}
static inline Eina_Bool
_event_callback_call(Eo *obj_id, Efl_Object_Data *pd,
- const Efl_Event_Description *desc,
- void *event_info,
- Eina_Bool legacy_compare)
+ const Efl_Event_Description *desc,
+ void *event_info,
+ Eina_Bool legacy_compare)
{
Eo_Callback_Description **cb;
Eo_Current_Callback_Description *lookup = NULL;
pd->walking_list++;
// Handle event that require to restart where we were in the nested list walking
- if (desc->restart)
- {
- EINA_INLIST_FOREACH(pd->current, lookup)
- if (lookup->desc == desc)
- break;
-
- // This is the first event to trigger it, so register it here
- if (!lookup)
- {
- // This following trick get us a zero allocation list
- saved.desc = desc;
- saved.current = 0;
- lookup = &saved;
- // Ideally there will most of the time be only one item in this list
- // But just to speed up things, prepend so we find it fast at the end
- // of this function
- pd->current = eina_inlist_prepend(pd->current, EINA_INLIST_GET(lookup));
- }
-
- if (!lookup->current) lookup->current = pd->callbacks_count;
- idx = lookup->current;
- }
- else
- {
- idx = pd->callbacks_count;
- }
+ // relatively unlikely so improve l1 instr cache by using goto
+ if (desc->restart) goto restart;
+ else idx = pd->callbacks_count;
+restart_back:
for (; idx > 0; idx--)
{
pd->callback_stopped = callback_already_stopped;
return ret;
+restart:
+ EINA_INLIST_FOREACH(pd->current, lookup)
+ {
+ if (lookup->desc == desc) break;
+ }
+
+ // This is the first event to trigger it, so register it here
+ if (!lookup)
+ {
+ // This following trick get us a zero allocation list
+ saved.desc = desc;
+ saved.current = 0;
+ lookup = &saved;
+ // Ideally there will most of the time be only one item in this list
+ // But just to speed up things, prepend so we find it fast at the end
+ // of this function
+ pd->current = eina_inlist_prepend(pd->current, EINA_INLIST_GET(lookup));
+ }
+
+ if (!lookup->current) lookup->current = pd->callbacks_count;
+ idx = lookup->current;
+ goto restart_back;
}
EOLIAN static Eina_Bool
{
EO_OBJ_POINTER_RETURN_VAL(comp_obj_id, comp_obj, EINA_FALSE);
EO_OBJ_POINTER(parent_id, parent);
- if (!parent)
- {
- EO_OBJ_DONE(comp_obj_id);
- return EINA_FALSE;
- }
- Efl_Object_Data *comp_pd = efl_data_scope_get(comp_obj_id, EFL_OBJECT_CLASS);
+ // very unlikely so improve l1 instr cache by using goto
+ if (!parent) goto err_parent;
+
/* Don't composite if we already have a composite object of this type */
{
Eina_List *itr;
EINA_LIST_FOREACH(parent->composite_objects, itr, emb_obj_id)
{
EO_OBJ_POINTER_RETURN_VAL(emb_obj_id, emb_obj, EINA_FALSE);
- if (emb_obj->klass == comp_obj->klass)
- {
- EO_OBJ_DONE(parent_id);
- EO_OBJ_DONE(comp_obj_id);
- return EINA_FALSE;
- }
+ // unlikely so improve l1 instr cache by using goto
+ if (emb_obj->klass == comp_obj->klass) goto err_klass;
}
}
+ Efl_Object_Data *comp_pd = efl_data_scope_get(comp_obj_id, EFL_OBJECT_CLASS);
+
if (efl_composite_part_is(comp_obj_id))
efl_composite_detach(comp_pd->ext->composite_parent, comp_obj_id);
EO_OBJ_DONE(parent_id);
EO_OBJ_DONE(comp_obj_id);
return EINA_TRUE;
+
+err_klass:
+ EO_OBJ_DONE(parent_id);
+err_parent:
+ EO_OBJ_DONE(comp_obj_id);
+ return EINA_FALSE;
}
EOLIAN static Eina_Bool
{
EO_OBJ_POINTER_RETURN_VAL(comp_obj_id, comp_obj, EINA_FALSE);
EO_OBJ_POINTER(parent_id, parent);
- if (!parent)
- {
- EO_OBJ_DONE(comp_obj_id);
- return EINA_FALSE;
- }
+ // very unlikely so improve l1 instr cache by using goto
+ if (!parent) goto err_parent;
- if (!efl_composite_part_is(comp_obj_id))
- {
- EO_OBJ_DONE(parent_id);
- EO_OBJ_DONE(comp_obj_id);
- return EINA_FALSE;
- }
+ // unlikely so improve l1 instr cache by using goto
+ if (!efl_composite_part_is(comp_obj_id)) goto err_part;
parent->composite_objects = eina_list_remove(parent->composite_objects, comp_obj_id);
/* Clear the comp parent on the child. */
{
Efl_Object_Data *comp_pd = efl_data_scope_get(comp_obj_id, EFL_OBJECT_CLASS);
comp_pd->ext->composite_parent = NULL;
-
_efl_object_extension_noneed(comp_pd);
}
EO_OBJ_DONE(parent_id);
EO_OBJ_DONE(comp_obj_id);
return EINA_TRUE;
+
+err_part:
+ EO_OBJ_DONE(parent_id);
+err_parent:
+ EO_OBJ_DONE(comp_obj_id);
+ return EINA_FALSE;
}
EOLIAN static Eina_Bool
{
Eo *child;
Efl_Object_Extension *ext;
+ _Eo_Object *obj_data2 = NULL;
DBG("%p - %s.", obj, efl_class_name_get(obj));
// special removal - remove from children list by hand after getting
// child handle in case unparent method is overridden and does
// extra things like removes other children too later on in the list
- while (pd->children)
- {
- child = _eo_obj_id_get(EINA_INLIST_CONTAINER_GET(pd->children, _Eo_Object));
- efl_parent_set(child, NULL);
- }
+ // this is a goto because more often than not objects do not have children
+ // so it's unlikely they will need the child cleanup code to so to have
+ // better l1 cache instruction coherency, move this to the end
+ if (pd->children) goto children;
+children_back:
- /* If we are a composite object, detach children */
+ // If we are a composite object, detach children. it is quite unlikely
+ // we are a composite object, so put the core of this handling
+ // at the end out of l1 cache prefetch
{
EO_OBJ_POINTER_RETURN(obj, obj_data);
- Eina_List *itr, *next;
- Eo *emb_obj_id;
- EINA_LIST_FOREACH_SAFE(obj_data->composite_objects, itr, next, emb_obj_id)
- {
- efl_composite_detach(obj, emb_obj_id);
- }
+ obj_data2 = obj_data;
+ if (obj_data->composite_objects) goto composite_obj;
+composite_obj_back:
EO_OBJ_DONE(obj);
}
if (pd->ext && pd->ext->composite_parent)
- {
- efl_composite_detach(pd->ext->composite_parent, obj);
- }
+ efl_composite_detach(pd->ext->composite_parent, obj);
- if (pd->parent)
- {
- ERR("Object '%p' still has a parent at the time of destruction.", obj);
- efl_parent_set(obj, NULL);
- }
+ // parent still being here is unlikely, so move error handling out of the
+ // code execution path
+ if (pd->parent) goto err_parent;
+err_parent_back:
_eo_generic_data_del_all(obj, pd);
_wref_destruct(pd);
_eo_callback_remove_all(pd);
ext = pd->ext;
- if (ext)
+ // it is rather likely we dont have any extension section for most objects
+ // so return immediately here to avoid pulling in more instructions to
+ // the 1l cache if we can
+ if (!ext)
{
- eina_stringshare_del(ext->name);
- ext->name = NULL;
- eina_stringshare_del(ext->comment);
- ext->comment = NULL;
- while (pd->ext && ext->futures)
- efl_future_cancel(eina_list_data_get(ext->futures));
+ _eo_condtor_done(obj);
+ return;
+ }
+ eina_stringshare_del(ext->name);
+ ext->name = NULL;
+ eina_stringshare_del(ext->comment);
+ ext->comment = NULL;
+ while (pd->ext && ext->futures)
+ efl_future_cancel(eina_list_data_get(ext->futures));
+ _efl_object_extension_noneed(pd);
+ _eo_condtor_done(obj);
+ return;
- _efl_object_extension_noneed(pd);
+children:
+ while (pd->children)
+ {
+ child = _eo_obj_id_get(EINA_INLIST_CONTAINER_GET(pd->children, _Eo_Object));
+ efl_parent_set(child, NULL);
}
+ goto children_back;
- _eo_condtor_done(obj);
+composite_obj:
+ {
+ Eina_List *itr, *next;
+ Eo *emb_obj_id;
+ EINA_LIST_FOREACH_SAFE(obj_data2->composite_objects, itr, next, emb_obj_id)
+ {
+ efl_composite_detach(obj, emb_obj_id);
+ }
+ }
+ goto composite_obj_back;
+
+err_parent:
+ ERR("Object '%p' still has a parent at the time of destruction.", obj);
+ efl_parent_set(obj, NULL);
+ goto err_parent_back;
}
EOLIAN static Eo *
do { char buf[256]; sprintf(buf, fmt, ptr); _eo_pointer_error(buf); } while (0)
#define EO_OBJ_POINTER(obj_id, obj) \
- _Eo_Object *obj; \
- do { \
- obj = _eo_obj_pointer_get((Eo_Id)obj_id); \
- } while (0)
+ _Eo_Object *obj; \
+ do { \
+ obj = _eo_obj_pointer_get((Eo_Id)obj_id); \
+ } while (0)
#define EO_OBJ_POINTER_RETURN_VAL(obj_id, obj, ret) \
- _Eo_Object *obj; \
- do { \
- obj = _eo_obj_pointer_get((Eo_Id)obj_id); \
- if (!obj) return (ret); \
- } while (0)
+ _Eo_Object *obj; \
+ do { \
+ obj = _eo_obj_pointer_get((Eo_Id)obj_id); \
+ if (!obj) return (ret); \
+ } while (0)
#define EO_OBJ_POINTER_RETURN(obj_id, obj) \
- _Eo_Object *obj; \
- do { \
- obj = _eo_obj_pointer_get((Eo_Id)obj_id); \
- if (!obj) return; \
- } while (0)
+ _Eo_Object *obj; \
+ do { \
+ obj = _eo_obj_pointer_get((Eo_Id)obj_id); \
+ if (!obj) return; \
+ } while (0)
#define EO_OBJ_POINTER_GOTO(obj_id, obj, label) \
- _Eo_Object *obj; \
- do { \
- obj = _eo_obj_pointer_get((Eo_Id)obj_id); \
- if (!obj) goto label; \
- } while (0)
+ _Eo_Object *obj; \
+ do { \
+ obj = _eo_obj_pointer_get((Eo_Id)obj_id); \
+ if (!obj) goto label; \
+ } while (0)
#define EO_CLASS_POINTER(klass_id, klass) \
_Efl_Class *klass; \
do { \
- klass = _eo_class_pointer_get(klass_id); \
+ klass = _eo_class_pointer_get(klass_id); \
} while (0)
#define EO_CLASS_POINTER_RETURN_VAL(klass_id, klass, ret) \
_Efl_Class *klass; \
do { \
- klass = _eo_class_pointer_get(klass_id); \
- if (!klass) { \
- _EO_POINTER_ERR("Class (%p) is an invalid ref.", klass_id); \
- return ret; \
- } \
+ klass = _eo_class_pointer_get(klass_id); \
+ if (!klass) { \
+ _EO_POINTER_ERR("Class (%p) is an invalid ref.", klass_id); \
+ return ret; \
+ } \
} while (0)
#define EO_CLASS_POINTER_RETURN(klass_id, klass) \
_Efl_Class *klass; \
do { \
- klass = _eo_class_pointer_get(klass_id); \
- if (!klass) { \
- _EO_POINTER_ERR("Class (%p) is an invalid ref.", klass_id); \
- return; \
- } \
+ klass = _eo_class_pointer_get(klass_id); \
+ if (!klass) { \
+ _EO_POINTER_ERR("Class (%p) is an invalid ref.", klass_id); \
+ return; \
+ } \
} while (0)
#define EO_CLASS_POINTER_GOTO(klass_id, klass, label) \
_Efl_Class *klass; \
do { \
- klass = _eo_class_pointer_get(klass_id); \
- if (!klass) goto label; \
+ klass = _eo_class_pointer_get(klass_id); \
+ if (!klass) goto label; \
} while (0)
#define EO_OBJ_DONE(obj_id) \
#else
#define EO_OBJ_POINTER(obj_id, obj) \
- _Eo_Object *obj; \
- do { \
- obj = _eo_obj_pointer_get((Eo_Id)obj_id); \
- if (obj && \
- !EINA_MAGIC_CHECK((Eo_Header *) obj, EO_EINA_MAGIC)) { \
- EINA_MAGIC_FAIL((Eo_Header *) obj, EO_EINA_MAGIC); \
- } \
- } while (0)
+ _Eo_Object *obj; \
+ do { \
+ obj = _eo_obj_pointer_get((Eo_Id)obj_id); \
+ if (obj && \
+ !EINA_MAGIC_CHECK((Eo_Header *) obj, EO_EINA_MAGIC)) { \
+ EINA_MAGIC_FAIL((Eo_Header *) obj, EO_EINA_MAGIC); \
+ } \
+ } while (0)
#define EO_OBJ_POINTER_RETURN_VAL(obj_id, obj, ret) \
_Eo_Object *obj; \
do { \
- obj = _eo_obj_pointer_get((Eo_Id)obj_id); \
- if (!obj) return (ret); \
+ obj = _eo_obj_pointer_get((Eo_Id)obj_id); \
+ if (!obj) return (ret); \
EO_MAGIC_RETURN_VAL((Eo_Header *) obj, EO_EINA_MAGIC, ret); \
} while (0)
#define EO_OBJ_POINTER_RETURN(obj_id, obj) \
_Eo_Object *obj; \
do { \
- obj = _eo_obj_pointer_get((Eo_Id)obj_id); \
- if (!obj) return; \
- EO_MAGIC_RETURN((Eo_Header *) obj, EO_EINA_MAGIC); \
+ obj = _eo_obj_pointer_get((Eo_Id)obj_id); \
+ if (!obj) return; \
+ EO_MAGIC_RETURN((Eo_Header *) obj, EO_EINA_MAGIC); \
} while (0)
#define EO_OBJ_POINTER_GOTO(obj_id, obj, label) \
_Eo_Object *obj; \
do { \
- obj = _eo_obj_pointer_get((Eo_Id)obj_id); \
- if (!obj || \
- !EINA_MAGIC_CHECK((Eo_Header *) obj, EO_EINA_MAGIC)) goto label; \
+ obj = _eo_obj_pointer_get((Eo_Id)obj_id); \
+ if (!obj || \
+ !EINA_MAGIC_CHECK((Eo_Header *) obj, EO_EINA_MAGIC)) goto label; \
} while (0)
#define EO_CLASS_POINTER(klass_id, klass) \
_Efl_Class *klass; \
do { \
- klass = _eo_class_pointer_get(klass_id); \
- if (klass && \
- !EINA_MAGIC_CHECK((Eo_Header *) klas, EO_CLASS_EINA_MAGIC)) { \
- EO_MAGIC_FAIL((Eo_Header *) klass, EO_CLASS_EINA_MAGIC); \
- } \
+ klass = _eo_class_pointer_get(klass_id); \
+ if (klass && \
+ !EINA_MAGIC_CHECK((Eo_Header *) klas, EO_CLASS_EINA_MAGIC)) { \
+ EO_MAGIC_FAIL((Eo_Header *) klass, EO_CLASS_EINA_MAGIC); \
+ } \
} while (0)
#define EO_CLASS_POINTER_RETURN_VAL(klass_id, klass, ret) \
_Efl_Class *klass; \
do { \
- klass = _eo_class_pointer_get(klass_id); \
- if (!klass) return (ret); \
- EO_MAGIC_RETURN_VAL((Eo_Header *) klass, EO_CLASS_EINA_MAGIC, ret); \
+ klass = _eo_class_pointer_get(klass_id); \
+ if (!klass) return (ret); \
+ EO_MAGIC_RETURN_VAL((Eo_Header *) klass, EO_CLASS_EINA_MAGIC, ret); \
} while (0)
#define EO_CLASS_POINTER_RETURN(klass_id, klass) \
_Efl_Class *klass; \
do { \
- klass = _eo_class_pointer_get(klass_id); \
- if (!klass) return; \
- EO_MAGIC_RETURN((Eo_Header *) klass, EO_CLASS_EINA_MAGIC); \
+ klass = _eo_class_pointer_get(klass_id); \
+ if (!klass) return; \
+ EO_MAGIC_RETURN((Eo_Header *) klass, EO_CLASS_EINA_MAGIC); \
} while (0)
#define EO_CLASS_POINTER_GOTO(klass_id, klass, label) \
_Efl_Class *klass; \
do { \
- klass = _eo_class_pointer_get(klass_id); \
- if (!klass) goto label; \
- if (klass && \
- !EINA_MAGIC_CHECK((Eo_Header *) klas, EO_CLASS_EINA_MAGIC)) { \
+ klass = _eo_class_pointer_get(klass_id); \
+ if (!klass) goto label; \
+ if (klass && \
+ !EINA_MAGIC_CHECK((Eo_Header *) klas, EO_CLASS_EINA_MAGIC)) { \
+ goto label;
+ } \
} while (0)
#define EO_OBJ_DONE(obj_id)