From: Cedric Bail Date: Wed, 16 Oct 2019 00:04:32 +0000 (-0700) Subject: eo: prevent unecessary callback call walk. X-Git-Tag: submit/tizen/20191111.023126~97 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=b916c4003eecd1664eed869fd8f52df41c361df5;p=platform%2Fupstream%2Fefl.git eo: prevent unecessary callback call walk. This patch introduce a small hash (64 or 32bits) that cache all existing Efl_Event_Description callback handler registered on an object. It slightly reduce the time needed to do an unecessary call and cost just a few bytes per object. Reviewed-by: Marcel Hollerbach Differential Revision: https://phab.enlightenment.org/D10475 --- diff --git a/src/lib/eo/eo_base_class.c b/src/lib/eo/eo_base_class.c index 67deec8..b3cd4a6 100644 --- a/src/lib/eo/eo_base_class.c +++ b/src/lib/eo/eo_base_class.c @@ -53,6 +53,11 @@ struct _Efl_Object_Data Efl_Event_Callback_Frame *event_frame; Eo_Callback_Description **callbacks; +#ifdef EFL64 + uint64_t callbacks_mask; +#else + uint32_t callbacks_mask; +#endif Eina_Inlist *pending_futures; unsigned int callbacks_count; @@ -1209,9 +1214,26 @@ _efl_pending_future_new(void) #define CB_COUNT_INC(cnt) do { if ((cnt) != 0xffff) (cnt)++; } while(0) #define CB_COUNT_DEC(cnt) do { if ((cnt) != 0xffff) (cnt)--; } while(0) +static inline unsigned char +_pointer_hash(const uintptr_t val) +{ + static const unsigned char shift = (unsigned char) log2(1 + sizeof (Efl_Event_Description)); +#ifdef EFL64 + return (unsigned char)(((val) >> shift) & 0x3F); +#else + return (unsigned char)(((val) >> shift) & 0x1F); +#endif +} + static inline void _special_event_count_inc(Eo *obj_id, Efl_Object_Data *pd, const Efl_Callback_Array_Item *it) { + int event_hash; + + event_hash = _pointer_hash((uintptr_t) it->desc); + + pd->callbacks_mask |= 1 << event_hash; + if (it->desc == EFL_EVENT_CALLBACK_ADD) CB_COUNT_INC(pd->event_cb_efl_event_callback_add_count); else if (it->desc == EFL_EVENT_CALLBACK_DEL) @@ -1682,6 +1704,7 @@ _event_callback_call(Eo *obj_id, Efl_Object_Data *pd, .inserted_before = 0, .generation = 1, }; + int event_hash; if (pd->callbacks_count == 0) return EINA_FALSE; else if ((desc == EFL_EVENT_CALLBACK_ADD) && @@ -1695,6 +1718,13 @@ _event_callback_call(Eo *obj_id, Efl_Object_Data *pd, else if ((desc == EFL_EVENT_NOREF) && (pd->event_cb_efl_event_noref_count == 0)) return EINA_FALSE; + if (!legacy_compare) + { + event_hash = _pointer_hash((uintptr_t) desc); + if (!(pd->callbacks_mask & (1 << event_hash))) + return EINA_FALSE; + } + if (pd->event_frame) frame.generation = ((Efl_Event_Callback_Frame*)pd->event_frame)->generation + 1; diff --git a/src/tests/eo/suite/eo_test_general.c b/src/tests/eo/suite/eo_test_general.c index 1494f46..61bf10b 100644 --- a/src/tests/eo/suite/eo_test_general.c +++ b/src/tests/eo/suite/eo_test_general.c @@ -1808,9 +1808,9 @@ EFL_START_TEST(efl_object_size) // Update this number only if you modified the class size on purpose #ifdef EO_DEBUG - ck_assert_int_le(efl_class_memory_size_get(SIMPLE_CLASS), 164); + ck_assert_int_le(efl_class_memory_size_get(SIMPLE_CLASS), 180); #else - ck_assert_int_le(efl_class_memory_size_get(SIMPLE_CLASS), 148); + ck_assert_int_le(efl_class_memory_size_get(SIMPLE_CLASS), 164); #endif } EFL_END_TEST