Hi,

(skip this mail if you don't care about micro optimization^^)

On Tue, Jan 16, 2018 at 9:13 PM, Carsten Haitzler <ras...@rasterman.com>
wrote:

> On Tue, 16 Jan 2018 20:25:37 +0900 Jean-Philippe André <j...@videolan.org>
> said:
>
> > Oh, another point.
> >
> > I'm pretty sure that the many very ugly goto we have in the code to "not
> > pollute L1 cache" are in fact not useful. I had a look at the ASM
> produced
> > by GCC -O2 and it strictly follows EINA_(UN)LIKELY. If goto is used for
> > error handling, fine, but if it's used with "goto label_back",
> readability
> > is really bad, while apparently not having any meaningful impact on the
> > binary code (for GCC, clang differs a bit). EINA_LIKELY is good enough,
> > IMHO. And hardware branch prediction happens no matter what.
>
> at the time i used EINA_LIKELY/UNLIKELY and also tried goto's and the gotos
> reshuffled the code and ended up with speedups, the likely/unlikely didn't.
> it's not about branch prediction BUT keeping code that might be fetched
> within
> the same cacheline of instructions as linear as possible without skips
> ahead
> skipping error or rare case code.
>


Yeah except it seems not be be true with GCC 7.2.1 and CFLAGS=-O2.
HW branch prediction will not affect L1 code cache but EINA_[UN]LIKELY will.

Let's have a quick look at the ASM produced, I think it's quite interesting
:)


Code A:

  if(EINA_UNLIKELY(!condition)) goto label.
  <hot code>
  label: <cold code>

This will inline hot code after "jne":
  test !condition
  jne label
  hot code
  label: cold code



Code B:

  if (EINA_UNLIKELY(!condition)) { <cold code> }
  <hot code>

This will inline hot code after "jne". The ASM is exactly the same as Code
A except the labelID's may differ a bit (probably depending on how they are
allocated by GCC).

  test !condition
  jne label
  hot code
  label: cold code



Code C:

  if (!condition) goto label
  <hot code>
  label: <cold code>

This will inline <cold code> after "je" (the condition for a jump becomes
inversed, of course), which is the opposite of what we wanted.

  test !condition
  je label2
  (supposedly) cold code
  label2: (supposedly) hot code


Conclusions:
- EINA_LIKELY has a direct impact on what GCC decides to do at ASM level
(at least with -O2 on my x64 system).
- A goto without EINA_LIKELY might even be inlined. GCC probably assumes
the true path (the goto branch) is most likely.

I think goto harms readability and maintenance for dubious performance
gains (which, if the above ASM is correct, are nil).
goto remains useful for exception handling, and should be exclusively
limited to that case, together with EINA_[UN]LIKELY.

Clang/LLVM produces different code in all cases and my lack of knowledge in
ASM doesn't allow me to easily analyse said differences :)

GCC remains a good option for optimization, and follows our hints. :)

Best regards,



ANNEX.


Tested in Eo.h: EFL_FUNC_COMMON_OP / EFL_FUNC_COMMON_OP_END
The following output comes from gcc -S.
Observe the first jump in BB#1 (je or jne).

Snippet for A/B:

# BB#1:
movl efl_key_data_set.___generation(%rip), %eax
movq _efl_object_init_generation@GOTPCREL(%rip), %rdx
cmpl (%rdx), %eax
jne .LBB0_2
.LBB0_3:
leaq .L.str(%rip), %rsi
leaq .L.str.1(%rip), %r8
leaq 8(%rsp), %rdx
movl $302, %r9d              # imm = 0x12E
movq %rbx, %rdi
callq _efl_object_call_resolve@PLT
testb %al, %al
je .LBB0_5
# BB#4:
movq 8(%rsp), %rdi
movq 32(%rsp), %rsi
movq %r15, %rdx
movq %r14, %rcx
callq *24(%rsp)
leaq 8(%rsp), %rdi
callq _efl_object_call_end@PLT
.LBB0_5:
movq %fs:40, %rax
cmpq 72(%rsp), %rax
jne .LBB0_7
# BB#6:
addq $80, %rsp
popq %rbx
popq %r14
popq %r15
retq
.LBB0_2:
leaq efl_key_data_set(%rip), %rdi
leaq .L.str(%rip), %rdx
leaq .L.str.1(%rip), %rcx
movl $302, %r8d              # imm = 0x12E
movq %rbx, %rsi
callq _efl_object_op_api_id_get@PLT
movl %eax, %ecx
movl %ecx, efl_key_data_set.___op(%rip)
movq _efl_object_init_generation@GOTPCREL(%rip), %rax
movl (%rax), %eax
movl %eax, efl_key_data_set.___generation(%rip)
testl %ecx, %ecx
jne .LBB0_3
jmp .LBB0_5


Patch for B:

diff --git a/src/lib/eo/Eo.h b/src/lib/eo/Eo.h
index a26e9fb7a6..2518680765 100644
--- a/src/lib/eo/Eo.h
+++ b/src/lib/eo/Eo.h
@@ -1183,8 +1183,11 @@ typedef struct _Efl_Object_Op_Call_Data
    _Eo_##Name##_func _func_;                                            \
    if (EINA_UNLIKELY((___op == EFL_NOOP) ||                       \
                      (___generation != _efl_object_init_generation))) \
-     goto __##Name##_op_create; /* yes a goto - see below */ \
-   __##Name##_op_create_done: EINA_HOT; \
+     { \
+        ___op = _efl_object_op_api_id_get(EFL_FUNC_COMMON_OP_FUNC(Name),
Obj, #Name, __FILE__, __LINE__); \
+        ___generation = _efl_object_init_generation; \
+        if (EINA_UNLIKELY(___op == EFL_NOOP)) goto __##Name##_failed; \
+     } \
    if (EINA_UNLIKELY(!_efl_object_call_resolve( \
       (Eo *) Obj, #Name, &___call, ___op, __FILE__, __LINE__))) \
       goto __##Name##_failed; \
@@ -1199,14 +1202,10 @@ typedef struct _Efl_Object_Op_Call_Data
 // of the cacheline that was already fetched should yield better cache
 // hits.
 #define EFL_FUNC_COMMON_OP_END(Obj, Name, DefRet, ErrorCase) \
-__##Name##_op_create: EINA_COLD; \
-   ___op = _efl_object_op_api_id_get(EFL_FUNC_COMMON_OP_FUNC(Name), Obj,
#Name, __FILE__, __LINE__); \
-   ___generation = _efl_object_init_generation; \
-   if (EINA_UNLIKELY(___op == EFL_NOOP)) goto __##Name##_failed; \
-   goto __##Name##_op_create_done; \
 __##Name##_failed: EINA_COLD; \
    ErrorCase \
    return DefRet;
+
 #define _EFL_OBJECT_API_BEFORE_HOOK
 #define _EFL_OBJECT_API_AFTER_HOOK
 #define _EFL_OBJECT_API_CALL_HOOK(x) x



Snippet C:

# BB#1:
movl efl_key_data_set.___generation(%rip), %eax
movq _efl_object_init_generation@GOTPCREL(%rip), %rdx
cmpl (%rdx), %eax
je .LBB0_2
.LBB0_4:
leaq efl_key_data_set(%rip), %rdi
leaq .L.str(%rip), %rdx
leaq .L.str.1(%rip), %rcx
movl $302, %r8d              # imm = 0x12E
movq %rbx, %rsi
callq _efl_object_op_api_id_get@PLT
movl %eax, %ecx
movl %ecx, efl_key_data_set.___op(%rip)
movq _efl_object_init_generation@GOTPCREL(%rip), %rax
movl (%rax), %eax
movl %eax, efl_key_data_set.___generation(%rip)
testl %ecx, %ecx
je .LBB0_5
.LBB0_2:
leaq .L.str(%rip), %rsi
leaq .L.str.1(%rip), %r8
leaq 8(%rsp), %rdx
movl $302, %r9d              # imm = 0x12E
movq %rbx, %rdi
callq _efl_object_call_resolve@PLT
testb %al, %al
je .LBB0_5
# BB#3:
movq 8(%rsp), %rdi
movq 32(%rsp), %rsi
movq %r15, %rdx
movq %r14, %rcx
callq *24(%rsp)
leaq 8(%rsp), %rdi
callq _efl_object_call_end@PLT
.LBB0_5:
movq %fs:40, %rax
cmpq 72(%rsp), %rax
jne .LBB0_7
# BB#6:
addq $80, %rsp
popq %rbx
popq %r14
popq %r15
retq


Patch for C:

diff --git a/src/lib/eo/Eo.h b/src/lib/eo/Eo.h
index a26e9fb7a6..84173fdd81 100644
--- a/src/lib/eo/Eo.h
+++ b/src/lib/eo/Eo.h
@@ -1181,7 +1181,7 @@ typedef struct _Efl_Object_Op_Call_Data
    static unsigned int ___generation = 0; \
    Efl_Object_Op_Call_Data ___call; \
    _Eo_##Name##_func _func_;                                            \
-   if (EINA_UNLIKELY((___op == EFL_NOOP) ||                       \
+   if (((___op == EFL_NOOP) ||                       \
                      (___generation != _efl_object_init_generation))) \
      goto __##Name##_op_create; /* yes a goto - see below */ \
    __##Name##_op_create_done: EINA_HOT; \




> > So, for at least Eo.h I think it would be very good to remove the goto.
> >
> > On Tue, Jan 16, 2018 at 7:53 PM, Jean-Philippe André <j...@videolan.org>
> > wrote:
> >
> > > Hi,
> > >
> > > This broke make check (I fixed it now).
> > >
> > > Note that this patch probably should not have been merged as a single
> > > commit, as the Phab Diff contains multiple patches.
> > >
> > > Best regards,
> > >
> > > On Tue, Jan 16, 2018 at 5:50 PM, Jean Guyomarc'h <j...@guyomarch.bzh>
> > > wrote:
> > >
> > >> raster pushed a commit to branch master.
> > >>
> > >> http://git.enlightenment.org/core/efl.git/commit/?id=34d9f20
> > >> 70696027199a56cb621c0526ea1430e8f
> > >>
> > >> commit 34d9f2070696027199a56cb621c0526ea1430e8f
> > >> Author: Jean Guyomarc'h <j...@guyomarch.bzh>
> > >> Date:   Tue Jan 16 14:58:38 2018 +0900
> > >>
> > >>     eina: remove usless newline
> > >>
> > >>     Summary:
> > >>     ecore_evas: remove debug
> > >>
> > >>     eina: unregister log level when done with
> > >>
> > >>     Fixes a constant memory leak.
> > >>
> > >>     eina: introduce EINA_HOT and EINA_COLD
> > >>
> > >>     These attributes respectivelly expand to __attribute__ ((hot)) and
> > >>     __attribute__ ((cold)) when available. They allow to mark
> functions
> > >> are
> > >>     being hot/cold (frequently used or not) as well as to qualify
> labels
> > >>     within a function (likely/unlikely branches).
> > >>
> > >>     eo: speed-up generated calls by removing call cache
> > >>
> > >>     The call cache needed to by thread-local, to avoid concurrency
> issues.
> > >>     Problem with TLS is that is adds an extra overhead, which appears
> to
> > >> be
> > >>     greater than the optimization the cache provides.
> > >>
> > >>     Op is naturally atomic, because it is an unsigned integer. As
> such, it
> > >>     cannot be tempered with while another thread is reading it. When
> > >>     entering the generated function, the first operation done is
> reading
> > >>     'op'. If we have concurrency, we will have access sequences
> returning
> > >>     either EFL_NOOP or a VALID op, because 'op' is not set until the
> very
> > >>     end of the function, when everything has been computed. As such,
> we
> > >> now
> > >>     use the 'op' atomic integer to instore a lock-free/wait-free
> > >> mechanism,
> > >>     which allows to drop the TLS nature of the cache, speeding up the
> > >> access
> > >>     to the cache, and therefore making functions execute faster.
> > >>
> > >>     We don't test anymore the generation count. This can be put as a
> > >>     limitation. If means that if you call efl_object_shutdown() and
> > >>     re-initialize it later with different data, opcodes will be
> invalid.
> > >>     I am not sure there is any usecase for this to ever happen.
> > >>     We could move all the caches in a dedicated section, that can be
> > >>     overwritten after a call to efl_object_shutdown(), but I am not
> sure
> > >> it
> > >>     will be very portable.
> > >>
> > >>     Benchmark: mean over 3 executions of
> > >>        ELM_TEST_AUTOBOUNCE=100 time elementary_test -to genlist
> > >>
> > >>     ```
> > >>                          BEFORE               AFTER
> > >>     ------------------------------------------------------------
> > >>     time (ns)            11114111647.0        9147676220.0
> > >>     frames               2872.3333333333335   2904.6666666666665
> > >>     time per frame (ns)  3869364.6666666665   3149535.3333333335
> > >>     user time (s)        11.096666666666666   9.22
> > >>     cpu (%)              22.666666666666668   18.333333333333332
> > >>     ```
> > >>
> > >>     Ref T6580
> > >>
> > >>     Reviewers: raster, cedric
> > >>
> > >>     Subscribers: cedric, jpeg
> > >>
> > >>     Maniphest Tasks: T6580
> > >>
> > >>     Differential Revision: https://phab.enlightenment.org/D5738
> > >> ---
> > >>  src/lib/ecore_evas/ecore_evas_private.h |  2 +-
> > >>  src/lib/eina/eina_cow.c                 |  1 +
> > >>  src/lib/eina/eina_safepointer.c         |  2 +-
> > >>  src/lib/eina/eina_types.h               |  8 +++++
> > >>  src/lib/eo/Eo.h                         | 56
> > >> +++++++----------------------
> > >>  src/lib/eo/eo.c                         | 64
> > >> ++++++---------------------------
> > >>  6 files changed, 33 insertions(+), 100 deletions(-)
> > >>
> > >> diff --git a/src/lib/ecore_evas/ecore_evas_private.h
> > >> b/src/lib/ecore_evas/ecore_evas_private.h
> > >> index 7b83589347..13002402a4 100644
> > >> --- a/src/lib/ecore_evas/ecore_evas_private.h
> > >> +++ b/src/lib/ecore_evas/ecore_evas_private.h
> > >> @@ -347,7 +347,7 @@ struct _Ecore_Evas
> > >>     } delayed;
> > >>
> > >>     int refcount;
> > >> -#define ECORE_EVAS_ASYNC_RENDER_DEBUG 1 /* TODO: remove me */
> > >> +//#define ECORE_EVAS_ASYNC_RENDER_DEBUG 1 /* TODO: remove me */
> > >>  #ifdef ECORE_EVAS_ASYNC_RENDER_DEBUG
> > >>     double async_render_start;
> > >>  #endif
> > >> diff --git a/src/lib/eina/eina_cow.c b/src/lib/eina/eina_cow.c
> > >> index 73a65e5f30..8ec86cfd79 100644
> > >> --- a/src/lib/eina/eina_cow.c
> > >> +++ b/src/lib/eina/eina_cow.c
> > >> @@ -320,6 +320,7 @@ eina_cow_init(void)
> > >>  Eina_Bool
> > >>  eina_cow_shutdown(void)
> > >>  {
> > >> +   eina_log_domain_unregister(_eina_cow_log_dom);
> > >>     eina_mempool_del(gc_pool);
> > >>     return EINA_TRUE;
> > >>  }
> > >> diff --git a/src/lib/eina/eina_safepointer.c
> > >> b/src/lib/eina/eina_safepointer.c
> > >> index 1a19f851c7..8f9d4b62a9 100644
> > >> --- a/src/lib/eina/eina_safepointer.c
> > >> +++ b/src/lib/eina/eina_safepointer.c
> > >> @@ -370,7 +370,7 @@ eina_safepointer_init(void)
> > >>
> > >>     DBG("entry[Size, Align] = { %zu, %u }",
> > >>         sizeof (Eina_Memory_Entry), eina_mempool_alignof(sizeof
> > >> (Eina_Memory_Entry)));
> > >> -   DBG("table[Size, Align] = { %zu, %u }\n",
> > >> +   DBG("table[Size, Align] = { %zu, %u }",
> > >>         sizeof (Eina_Memory_Table), eina_mempool_alignof(sizeof
> > >> (Eina_Memory_Table)));
> > >>
> > >>     return EINA_TRUE;
> > >> diff --git a/src/lib/eina/eina_types.h b/src/lib/eina/eina_types.h
> > >> index 94e6ebc6f3..3d15a3f42d 100644
> > >> --- a/src/lib/eina/eina_types.h
> > >> +++ b/src/lib/eina/eina_types.h
> > >> @@ -184,6 +184,14 @@
> > >>  #  define EINA_PURE
> > >>  # endif
> > >>
> > >> +# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
> > >> +#  define EINA_HOT __attribute__ ((hot))
> > >> +#  define EINA_COLD __attribute__ ((cold))
> > >> +# else
> > >> +#  define EINA_HOT
> > >> +#  define EINA_COLD
> > >> +# endif
> > >> +
> > >>  # if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4)
> > >>  #  if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 3)
> > >>  #   define EINA_PRINTF(fmt, arg) __attribute__((__format__
> > >> (__gnu_printf__, fmt, arg)))
> > >> diff --git a/src/lib/eo/Eo.h b/src/lib/eo/Eo.h
> > >> index 3ea20ec2ff..8b489ab72a 100644
> > >> --- a/src/lib/eo/Eo.h
> > >> +++ b/src/lib/eo/Eo.h
> > >> @@ -1159,37 +1159,6 @@ typedef struct _Efl_Object_Op_Call_Data
> > >>     void         *extn4; // for future use to avoid ABI issues
> > >>  } Efl_Object_Op_Call_Data;
> > >>
> > >> -#define EFL_OBJECT_CALL_CACHE_SIZE 1
> > >> -
> > >> -typedef struct _Efl_Object_Call_Cache_Index
> > >> -{
> > >> -   const void       *klass;
> > >> -} Efl_Object_Call_Cache_Index;
> > >> -
> > >> -typedef struct _Efl_Object_Call_Cache_Entry
> > >> -{
> > >> -   const void       *func;
> > >> -} Efl_Object_Call_Cache_Entry;
> > >> -
> > >> -typedef struct _Efl_Object_Call_Cache_Off
> > >> -{
> > >> -   int               off;
> > >> -} Efl_Object_Call_Cache_Off;
> > >> -
> > >> -typedef struct _Efl_Object_Call_Cache
> > >> -{
> > >> -#if EFL_OBJECT_CALL_CACHE_SIZE > 0
> > >> -   Efl_Object_Call_Cache_Index index[EFL_OBJECT_CALL_CACHE_SIZE];
> > >> -   Efl_Object_Call_Cache_Entry entry[EFL_OBJECT_CALL_CACHE_SIZE];
> > >> -   Efl_Object_Call_Cache_Off   off  [EFL_OBJECT_CALL_CACHE_SIZE];
> > >> -# if EFL_OBJECT_CALL_CACHE_SIZE > 1
> > >> -   int                 next_slot;
> > >> -# endif
> > >> -#endif
> > >> -   Efl_Object_Op               op;
> > >> -   unsigned int        generation;
> > >> -} Efl_Object_Call_Cache;
> > >> -
> > >>  // to pass the internal function call to EFL_FUNC_BODY (as Func
> > >> parameter)
> > >>  #define EFL_FUNC_CALL(...) __VA_ARGS__
> > >>
> > >> @@ -1205,17 +1174,18 @@ typedef struct _Efl_Object_Call_Cache
> > >>  # define EFL_FUNC_TLS __thread
> > >>  #endif
> > >>
> > >> +
> > >>  // cache OP id, get real fct and object data then do the call
> > >>  #define EFL_FUNC_COMMON_OP(Obj, Name, DefRet) \
> > >> -   static EFL_FUNC_TLS Efl_Object_Call_Cache ___cache; /* static 0 by
> > >> default */ \
> > >> +   static Efl_Object_Op ___op; /* static 0 by default */ \
> > >>     Efl_Object_Op_Call_Data ___call; \
> > >>     _Eo_##Name##_func _func_;
>     \
> > >> -   if (EINA_UNLIKELY((___cache.op == EFL_NOOP) ||
>    \
> > >> -                     (___cache.generation !=
> > >> _efl_object_init_generation))) \
> > >> +   if (EINA_UNLIKELY(___op == EFL_NOOP)) \
> > >>       goto __##Name##_op_create; /* yes a goto - see below */ \
> > >> -   __##Name##_op_create_done: \
> > >> -   if (!_efl_object_call_resolve((Eo *) Obj, #Name, &___call,
> &___cache,
> > >> \
> > >> -                                 __FILE__, __LINE__)) goto
> > >> __##Name##_failed; \
> > >> +   __##Name##_op_create_done: EINA_HOT; \
> > >> +   if (EINA_UNLIKELY(!_efl_object_call_resolve( \
> > >> +      (Eo *) Obj, #Name, &___call, ___op, __FILE__, __LINE__))) \
> > >> +      goto __##Name##_failed; \
> > >>     _func_ = (_Eo_##Name##_func) ___call.func;
> > >>
> > >>  // This looks ugly with gotos BUT it moves rare "init" handling code
> > >> @@ -1227,13 +1197,11 @@ typedef struct _Efl_Object_Call_Cache
> > >>  // of the cacheline that was already fetched should yield better
> cache
> > >>  // hits.
> > >>  #define EFL_FUNC_COMMON_OP_END(Obj, Name, DefRet, ErrorCase) \
> > >> -__##Name##_op_create: \
> > >> -   if (EINA_UNLIKELY(___cache.op != EFL_NOOP)) memset(&___cache, 0,
> > >> sizeof(___cache)); \
> > >> -   ___cache.op = _efl_object_op_api_id_get(EFL_
> FUNC_COMMON_OP_FUNC(Name),
> > >> Obj, #Name, __FILE__, __LINE__); \
> > >> -   if (___cache.op == EFL_NOOP) goto __##Name##_failed; \
> > >> -   ___cache.generation = _efl_object_init_generation; \
> > >> +__##Name##_op_create: EINA_COLD; \
> > >> +   ___op = _efl_object_op_api_id_get(EFL_FUNC_COMMON_OP_FUNC(Name),
> > >> Obj, #Name, __FILE__, __LINE__); \
> > >> +   if (EINA_UNLIKELY(___op == EFL_NOOP)) goto __##Name##_failed; \
> > >>     goto __##Name##_op_create_done; \
> > >> -__##Name##_failed: \
> > >> +__##Name##_failed: EINA_COLD; \
> > >>     ErrorCase \
> > >>     return DefRet;
> > >>  #define _EFL_OBJECT_API_BEFORE_HOOK
> > >> @@ -1335,7 +1303,7 @@ EAPI Efl_Object_Op _efl_object_api_op_id_get(
> const
> > >> void *api_func) EINA_DEPRECAT
> > >>  EAPI Efl_Object_Op _efl_object_op_api_id_get(const void *api_func,
> > >> const Eo *obj, const char *api_func_name, const char *file, int line)
> > >> EINA_ARG_NONNULL(1, 2, 3, 4) EINA_WARN_UNUSED_RESULT;
> > >>
> > >>  // gets the real function pointer and the object data
> > >> -EAPI Eina_Bool _efl_object_call_resolve(Eo *obj, const char
> *func_name,
> > >> Efl_Object_Op_Call_Data *call, Efl_Object_Call_Cache *callcache,
> const char
> > >> *file, int line);
> > >> +EAPI Eina_Bool _efl_object_call_resolve(Eo *obj, const char
> *func_name,
> > >> Efl_Object_Op_Call_Data *call, Efl_Object_Op op, const char *file, int
> > >> line);
> > >>
> > >>  // end of the eo call barrier, unref the obj
> > >>  EAPI void _efl_object_call_end(Efl_Object_Op_Call_Data *call);
> > >> diff --git a/src/lib/eo/eo.c b/src/lib/eo/eo.c
> > >> index 50df250acf..0db34fc35c 100644
> > >> --- a/src/lib/eo/eo.c
> > >> +++ b/src/lib/eo/eo.c
> > >> @@ -439,15 +439,14 @@ efl_cast(const Eo *eo_id, const Efl_Class
> > >> *cur_klass)
> > >>  }
> > >>
> > >>  EAPI Eina_Bool
> > >> -_efl_object_call_resolve(Eo *eo_id, const char *func_name,
> > >> Efl_Object_Op_Call_Data *call, Efl_Object_Call_Cache *cache, const
> char
> > >> *file, int line)
> > >> +_efl_object_call_resolve(Eo *eo_id, const char *func_name,
> > >> Efl_Object_Op_Call_Data *call, Efl_Object_Op op, const char *file, int
> > >> line) {
> > >> -   const _Efl_Class *klass, *inputklass, *main_klass;
> > >> +   const _Efl_Class *klass, *main_klass;
> > >>     const _Efl_Class *cur_klass = NULL;
> > >>     _Eo_Object *obj = NULL;
> > >>     const Eo_Vtable *vtable = NULL;
> > >>     const op_type_funcs *func;
> > >>     Eina_Bool is_obj;
> > >> -   Eina_Bool is_override = EINA_FALSE;
> > >>     Eina_Bool super = EINA_TRUE;
> > >>
> > >>     if (EINA_UNLIKELY(!eo_id)) return EINA_FALSE;
> > >> @@ -456,14 +455,13 @@ _efl_object_call_resolve(Eo *eo_id, const char
> > >> *func_name, Efl_Object_Op_Call_Da
> > >>
> > >>     is_obj = _eo_is_a_obj(eo_id);
> > >>
> > >> -   if (is_obj)
> > >> +   if (EINA_LIKELY(is_obj == EINA_TRUE))
> > >>       {
> > >>          EO_OBJ_POINTER_RETURN_VAL_PROXY(eo_id, _obj, EINA_FALSE);
> > >>
> > >>          obj = _obj;
> > >>          klass = _obj->klass;
> > >>          vtable = EO_VTABLE(obj);
> > >> -        is_override = _obj_is_override(obj);
> > >>          if (EINA_UNLIKELY(_obj->cur_klass != NULL))
> > >>            {
> > >>               // YES this is a goto with a label to return. this is a
> > >> @@ -485,9 +483,7 @@ obj_super_back:
> > >>       }
> > >>  ok_klass_back:
> > >>
> > >> -   inputklass = main_klass =  klass;
> > >> -
> > >> -   if (!cache->op) goto err_cache_op;
> > >> +   main_klass =  klass;
> > >>
> > >>     /* If we have a current class, we need to itr to the next. */
> > >>     if (cur_klass)
> > >> @@ -499,30 +495,7 @@ ok_klass_back:
> > >>       }
> > >>     else
> > >>       {
> > >> -# if EFL_OBJECT_CALL_CACHE_SIZE > 0
> > >> -        if (!is_override)
> > >> -          {
> > >> -# if EFL_OBJECT_CALL_CACHE_SIZE > 1
> > >> -             int i;
> > >> -
> > >> -             for (i = 0; i < EFL_OBJECT_CALL_CACHE_SIZE; i++)
> > >> -# else
> > >> -                const int i = 0;
> > >> -# endif
> > >> -               {
> > >> -                  if ((const void *)inputklass ==
> cache->index[i].klass)
> > >> -                    {
> > >> -                       func = (const op_type_funcs
> > >> *)cache->entry[i].func;
> > >> -                       call->func = func->func;
> > >> -                       if (is_obj)
> > >> -                         call->data = (char *)obj +
> cache->off[i].off;
> > >> -                       if (EINA_UNLIKELY(!call->func)) goto
> err_cache_op;
> > >> -                       return EINA_TRUE;
> > >> -                    }
> > >> -               }
> > >> -          }
> > >> -#endif
> > >> -        func = _vtable_func_get(vtable, cache->op);
> > >> +        func = _vtable_func_get(vtable, 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
> > >> @@ -536,22 +509,6 @@ ok_cur_klass_back:
> > >>
> > >>          if (is_obj) call->data = _efl_data_scope_get(obj, func->src);
> > >>
> > >> -# if EFL_OBJECT_CALL_CACHE_SIZE > 0
> > >> -        if (!cur_klass && !is_override)
> > >> -          {
> > >> -# if EFL_OBJECT_CALL_CACHE_SIZE > 1
> > >> -             const int slot = cache->next_slot;
> > >> -# else
> > >> -             const int slot = 0;
> > >> -# endif
> > >> -             cache->index[slot].klass = (const void *)inputklass;
> > >> -             cache->entry[slot].func = (const void *)func;
> > >> -             cache->off[slot].off = (int)((long)((char *)call->data -
> > >> (char *)obj));
> > >> -# if EFL_OBJECT_CALL_CACHE_SIZE > 1
> > >> -             cache->next_slot = (slot + 1) %
> EFL_OBJECT_CALL_CACHE_SIZE;
> > >> -# endif
> > >> -          }
> > >> -#endif
> > >>          return EINA_TRUE;
> > >>       }
> > >>
> > >> @@ -570,7 +527,7 @@ end:
> > >>               EO_OBJ_POINTER_PROXY(emb_obj_id, emb_obj);
> > >>               if (EINA_UNLIKELY(!emb_obj)) continue;
> > >>
> > >> -             func = _vtable_func_get(EO_VTABLE(emb_obj), cache->op);
> > >> +             func = _vtable_func_get(EO_VTABLE(emb_obj), op);
> > >>               if (func == NULL) goto composite_continue;
> > >>
> > >>               if (EINA_LIKELY(func->func && func->src))
> > >> @@ -594,7 +551,7 @@ composite_continue:
> > >>     if (cur_klass)
> > >>       {
> > >>          ERR("in %s:%d: func '%s' (%d) could not be resolved for class
> > >> '%s' for super of '%s'.",
> > >> -            file, line, func_name, cache->op, main_klass->desc->name,
> > >> +            file, line, func_name, op, main_klass->desc->name,
> > >>              cur_klass->desc->name);
> > >>          goto err;
> > >>       }
> > >> @@ -602,7 +559,7 @@ composite_continue:
> > >>       {
> > >>          /* we should not be able to take this branch */
> > >>          ERR("in %s:%d: func '%s' (%d) could not be resolved for class
> > >> '%s'.",
> > >> -            file, line, func_name, cache->op,
> main_klass->desc->name);
> > >> +            file, line, func_name, op, main_klass->desc->name);
> > >>          goto err;
> > >>       }
> > >>  err_cache_op:
> > >> @@ -612,7 +569,7 @@ err_cache_op:
> > >>     goto err;
> > >>  err_func_src:
> > >>     ERR("in %s:%d: you called a pure virtual func '%s' (%d) of class
> > >> '%s'.",
> > >> -       file, line, func_name, cache->op, klass->desc->name);
> > >> +       file, line, func_name, op, klass->desc->name);
> > >>  err:
> > >>     if (is_obj)
> > >>       {
> > >> @@ -629,7 +586,7 @@ 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, super);
> > >> +   func = _eo_kls_itr_next(klass, cur_klass, op, super);
> > >>     if (!func) goto end;
> > >>     klass = func->src;
> > >>     goto ok_cur_klass_back;
> > >> @@ -661,7 +618,6 @@ obj_super:
> > >>             cur_klass = NULL;
> > >>          }
> > >>
> > >> -      is_override = _obj_is_override(obj) && (cur_klass == NULL);
> > >>     }
> > >>     goto obj_super_back;
> > >>
> > >>
> > >> --
> > >>
> > >> --
> > >> Jean-Philippe André
> > >>
> > >>
> >
> >
> > --
> > Jean-Philippe André
> > ------------------------------------------------------------
> ------------------
> > Check out the vibrant tech community on one of the world's most
> > engaging tech sites, Slashdot.org! http://sdm.link/slashdot
> > _______________________________________________
> > enlightenment-devel mailing list
> > enlightenment-devel@lists.sourceforge.net
> > https://lists.sourceforge.net/lists/listinfo/enlightenment-devel
>
>
> --
> ------------- Codito, ergo sum - "I code, therefore I am" --------------
> Carsten Haitzler - ras...@rasterman.com
>
>


-- 
Jean-Philippe André
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
enlightenment-devel mailing list
enlightenment-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/enlightenment-devel

Reply via email to