diff --git a/src/lib/eo/eo.c b/src/lib/eo/eo.c index a80027ae46..6fe2a03100 100644 --- a/src/lib/eo/eo.c +++ b/src/lib/eo/eo.c @@ -316,13 +316,16 @@ static Eina_Spinlock _super_class_lock; 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 @@ -345,8 +348,7 @@ _efl_object_call_resolve(Eo *eo_id, const char *func_name, Efl_Object_Op_Call_Da 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; @@ -420,6 +422,9 @@ ok_klass_back: } #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: @@ -449,6 +454,8 @@ 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: @@ -479,7 +486,8 @@ 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'.", @@ -509,16 +517,14 @@ err: // 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; @@ -526,6 +532,8 @@ ok_klass: } goto ok_klass_back; +err_klass: + _EO_POINTER_ERR("Class (%p) is an invalid ref.", eo_id); return EINA_FALSE; } @@ -539,28 +547,6 @@ _efl_object_call_end(Efl_Object_Op_Call_Data *call) } } -/* -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) { @@ -681,25 +667,16 @@ _eo_class_funcs_set(Eo_Vtable *vtable, const Efl_Object_Ops *ops, const _Efl_Cla 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; @@ -708,22 +685,25 @@ efl_class_functions_set(const Efl_Class *klass_id, const Efl_Object_Ops *object_ _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 * @@ -732,24 +712,18 @@ _efl_add_internal_start(const char *file, int line, const Efl_Class *klass_id, E _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); @@ -783,35 +757,44 @@ _efl_add_internal_start(const char *file, int line, const Efl_Class *klass_id, E /* 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; +ok_nomatch: + { + 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); - if (parent_id) EO_OBJ_DONE(parent_id); - return NULL; - } - else if (eo_id != _eo_obj_id_get(obj)) - { - EO_OBJ_POINTER_RETURN_VAL(eo_id, new_obj, NULL); - /* 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 * @@ -819,15 +802,8 @@ _efl_add_internal_end(Eo *eo_id, Eo *finalized_id) { 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 @@ -845,11 +821,16 @@ _efl_add_internal_end(Eo *eo_id, Eo *finalized_id) } 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); @@ -885,14 +866,19 @@ efl_class_get(const Eo *eo_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 * @@ -902,16 +888,21 @@ efl_class_name_get(const Efl_Class *eo_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); 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 @@ -1407,7 +1398,7 @@ EAPI Eina_Bool 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) @@ -1417,11 +1408,13 @@ efl_object_override(Eo *eo_id, const Efl_Object_Ops *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 @@ -1489,7 +1482,12 @@ efl_isa(const Eo *eo_id, const Efl_Class *klass_id) (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); @@ -1503,7 +1501,6 @@ efl_isa(const Eo *eo_id, const Efl_Class *klass_id) // 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; @@ -1778,24 +1775,29 @@ _efl_data_xunref_internal(_Eo_Object *obj, void *data, const _Eo_Object *ref_obj 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; } @@ -1811,28 +1813,35 @@ efl_data_xref_internal(const char *file, int line, const Eo *obj_id, const Efl_C { 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 @@ -2176,7 +2185,9 @@ efl_manual_free(Eo *obj_id) { 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); diff --git a/src/lib/eo/eo_base_class.c b/src/lib/eo/eo_base_class.c index 8203bde1d5..e05ffa607d 100644 --- a/src/lib/eo/eo_base_class.c +++ b/src/lib/eo/eo_base_class.c @@ -536,63 +536,59 @@ _efl_object_del(const Eo *obj, Efl_Object_Data *pd EINA_UNUSED) 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 * @@ -678,41 +674,36 @@ EOLIAN static Eina_Iterator * _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) + 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 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); } - - 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); - 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); - +done: EO_OBJ_DONE(obj_id); return (Eina_Iterator *)it; } @@ -749,15 +740,17 @@ _efl_object_wref_add(Eo *obj, Efl_Object_Data *pd, Eo **wref) 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 @@ -766,19 +759,11 @@ _efl_object_wref_del(Eo *obj, Efl_Object_Data *pd, Eo **wref) 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); @@ -793,13 +778,8 @@ _efl_object_wref_del(Eo *obj, Efl_Object_Data *pd, Eo **wref) 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) @@ -810,6 +790,8 @@ _efl_object_wref_del(Eo *obj, Efl_Object_Data *pd, Eo **wref) if (!tmp) return; ext->wrefs = tmp; ext->wrefs[count - 1] = NULL; + *wref = NULL; + return; } else { @@ -819,6 +801,20 @@ _efl_object_wref_del(Eo *obj, Efl_Object_Data *pd, Eo **wref) } *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 @@ -913,27 +909,28 @@ static Eo_Callback_Description * _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 */ @@ -991,35 +988,24 @@ static inline unsigned int _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; @@ -1065,20 +1051,16 @@ _eo_callbacks_sorted_insert(Efl_Object_Data *pd, Eo_Callback_Description *cb) 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; @@ -1088,6 +1070,11 @@ _efl_object_event_callback_priority_add(Eo *obj, Efl_Object_Data *pd, 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 @@ -1127,9 +1114,9 @@ _efl_object_event_callback_del(Eo *obj, Efl_Object_Data *pd, 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 @@ -1137,13 +1124,8 @@ _efl_object_event_callback_array_priority_add(Eo *obj, Efl_Object_Data *pd, 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++) @@ -1166,12 +1148,17 @@ _efl_object_event_callback_array_priority_add(Eo *obj, Efl_Object_Data *pd, 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; @@ -1203,19 +1190,16 @@ static Eina_Bool _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; @@ -1234,32 +1218,10 @@ _event_callback_call(Eo *obj_id, Efl_Object_Data *pd, 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--) { @@ -1336,6 +1298,28 @@ end: 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 @@ -1452,12 +1436,9 @@ _efl_object_composite_attach(Eo *parent_id, Efl_Object_Data *pd EINA_UNUSED, Eo { 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; @@ -1465,15 +1446,13 @@ _efl_object_composite_attach(Eo *parent_id, Efl_Object_Data *pd EINA_UNUSED, Eo 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); @@ -1486,6 +1465,12 @@ _efl_object_composite_attach(Eo *parent_id, Efl_Object_Data *pd EINA_UNUSED, Eo 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 @@ -1493,31 +1478,29 @@ _efl_object_composite_detach(Eo *parent_id, Efl_Object_Data *pd EINA_UNUSED, Eo { 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 @@ -1641,59 +1624,84 @@ _efl_object_destructor(Eo *obj, Efl_Object_Data *pd) { 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)); - - _efl_object_extension_noneed(pd); + _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; + +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; + +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 * diff --git a/src/lib/eo/eo_ptr_indirection.h b/src/lib/eo/eo_ptr_indirection.h index 82c29136f5..3df4fb56ea 100644 --- a/src/lib/eo/eo_ptr_indirection.h +++ b/src/lib/eo/eo_ptr_indirection.h @@ -14,63 +14,63 @@ void _eo_pointer_error(const char *msg); 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) \ @@ -79,72 +79,74 @@ void _eo_pointer_error(const char *msg); #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)