eo2: call stack Proof Of Concept

no grow/shrink or thread local storage
This commit is contained in:
Jérémy Zurcher 2013-12-25 15:16:34 +01:00 committed by Tom Hacohen
parent a645076979
commit 6a16edc888
4 changed files with 110 additions and 59 deletions

View File

@ -614,48 +614,40 @@ EAPI Eina_Bool eo_shutdown(void);
EAPI void
eo2_class_funcs_set(Eo_Class *klass_id);
// opaque type used to pass object pointer to EAPI calls
typedef struct _Eo_Internal _Eo;
// to fetch internal function and object data at once
typedef struct _Eo2_Op_Call_Data
{
void *func;
void *data;
Eo *obj_id;
void *func;
void *data;
} Eo2_Op_Call_Data;
// EAPI function declaration first argument
#define eo2_a _Eo *obj, Eo *objid
// EAPI function call first argument
#define eo2_o _obj_, _objid_
// to pass the internal function call to EO2_FUNC_BODY (as Func parameter)
#define EO2_FUNC_CALL(...) _func_(objid, call.data, __VA_ARGS__)
#define EO2_FUNC_CALL(...) _func_(call.obj_id, call.data, __VA_ARGS__)
// cache OP id, get real fct and object data then do the call
#define _EO2_FUNC_COMMON(Name, Ret, Func, DefRet) \
static Eo_Op op = EO_NOOP; \
if ( op == EO_NOOP ) op = eo2_get_op_id(obj, (void*)Name); \
if ( op == EO_NOOP ) op = eo2_get_op_id((void*)Name); \
Eo2_Op_Call_Data call; \
if (!eo2_call_resolve(obj, op, &call)) return DefRet; \
if (!eo2_call_resolve(op, &call)) return DefRet; \
__##Name##_func _func_ = (__##Name##_func) call.func; \
return Func; \
/* XXX: Essential, because we need to adjust objid for comp objects. */
// to define an EAPI function
#define EO2_FUNC_BODY(Name, Ret, DefRet) \
Ret \
Name(_Eo *obj, Eo *objid) \
Name() \
{ \
typedef Ret (*__##Name##_func)(Eo *, void *obj_data); \
_EO2_FUNC_COMMON(Name, Ret, _func_(objid, call.data), DefRet) \
_EO2_FUNC_COMMON(Name, Ret, _func_(call.obj_id, call.data), DefRet)\
}
#define EO2_VOID_FUNC_BODY(Name) EO2_FUNC_BODY(Name, void, )
#define EO2_FUNC_BODYV(Name, Ret, Func, DefRet, ...) \
Ret \
Name(_Eo *obj, Eo *objid, __VA_ARGS__) \
Name(__VA_ARGS__) \
{ \
typedef Ret (*__##Name##_func)(Eo *, void *obj_data, __VA_ARGS__); \
_EO2_FUNC_COMMON(Name, Ret, Func, DefRet) \
@ -670,21 +662,17 @@ typedef struct _Eo2_Op_Call_Data
#define EO2_OP_SENTINEL { NULL, NULL, 0, EO_OP_TYPE_INVALID, NULL}
// returns the OP id corresponding to the given api_func
EAPI Eo_Op eo2_get_op_id(_Eo *obj, void *api_func);
EAPI Eo_Op eo2_get_op_id(void *api_func);
// gets the real function pointer and the object data
#define eo2_call_resolve(obj_id, op, call) eo2_call_resolve_internal(obj_id, NULL, op, call)
EAPI Eina_Bool eo2_call_resolve_internal(_Eo *obj, const Eo_Class *klass, Eo_Op op, Eo2_Op_Call_Data *call);
#define eo2_call_resolve(op, call) eo2_call_resolve_internal(NULL, op, call)
EAPI Eina_Bool eo2_call_resolve_internal(const Eo_Class *klass, Eo_Op op, Eo2_Op_Call_Data *call);
// start of eo2_do barrier, gets the object pointer and ref it
EAPI _Eo * eo2_do_start(Eo *obj_id);
// start of eo2_do barrier, gets the object pointer and ref it, put it on the stask
EAPI Eina_Bool eo2_do_start(Eo *obj_id);
// end of the eo2_do barrier, unref the obj
EAPI void eo2_do_end(_Eo *obj);
// optional helper
#define eo2_call(api_func) api_func(eo2_o)
#define eo2_callv(api_func, ...) api_func(eo2_o, __VA_ARGS__)
// end of the eo2_do barrier, unref the obj, move the stack pointer
EAPI void eo2_do_end();
// eo object method calls batch,
// DO NOT use return statement in it, use break if necessary
@ -692,11 +680,9 @@ EAPI void eo2_do_end(_Eo *obj);
do \
{ \
Eo *_objid_ = objid; \
_Eo *_obj_ = eo2_do_start(_objid_); \
if (!_obj_) break; \
if (!eo2_do_start(_objid_)) break; \
do { __VA_ARGS__ ; } while (0); \
eo2_do_end(_obj_); \
_obj_ = NULL; \
eo2_do_end(); \
} while (0)
// FIXME

View File

@ -257,25 +257,77 @@ _eo_kls_itr_func_get(const _Eo_Class *cur_klass, Eo_Op op)
/************************************ EO2 ************************************/
EAPI _Eo *
// FIXME: per thread stack, grow/shrink
#define EO2_INVALID_DATA (void *) -1
#define EO2_CALL_STACK_SIZE 5
typedef struct _Eo2_Stack_Frame
{
Eo *obj_id;
_Eo *obj;
void *obj_data;
} Eo2_Stack_Frame;
typedef struct _Eo2_Call_Stack {
Eo2_Stack_Frame stack[EO2_CALL_STACK_SIZE];
Eo2_Stack_Frame *frame_ptr;
} Eo2_Call_Stack;
static Eo2_Call_Stack eo2_call_stack = {
{
{ NULL, NULL, EO2_INVALID_DATA },
{ NULL, NULL, EO2_INVALID_DATA },
{ NULL, NULL, EO2_INVALID_DATA },
{ NULL, NULL, EO2_INVALID_DATA },
{ NULL, NULL, EO2_INVALID_DATA },
},
NULL };
EAPI Eina_Bool
eo2_do_start(Eo *obj_id)
{
EO_OBJ_POINTER_RETURN_VAL(obj_id, obj, NULL);
EO_OBJ_POINTER_RETURN_VAL(obj_id, obj, EINA_FALSE);
_eo_ref(obj);
return obj;
if (eo2_call_stack.frame_ptr == NULL)
eo2_call_stack.frame_ptr = &eo2_call_stack.stack[0];
else
eo2_call_stack.frame_ptr++;
if (eo2_call_stack.frame_ptr->obj_id != NULL)
ERR("eo2 call stack is not clear, you must have used a return statement in a eo2_do macro");
if ((eo2_call_stack.frame_ptr - eo2_call_stack.stack) >= EO2_CALL_STACK_SIZE)
ERR("eo2 call stack overflow !!!");
eo2_call_stack.frame_ptr->obj = obj;
eo2_call_stack.frame_ptr->obj_id = obj_id;
eo2_call_stack.frame_ptr->obj_data = EO2_INVALID_DATA;
return EINA_TRUE;
}
EAPI void
eo2_do_end(_Eo *obj)
eo2_do_end()
{
_eo_unref(obj);
_eo_unref(eo2_call_stack.frame_ptr->obj);
eo2_call_stack.frame_ptr->obj = NULL;
eo2_call_stack.frame_ptr->obj_id = NULL;
eo2_call_stack.frame_ptr->obj_data = EO2_INVALID_DATA;
if (eo2_call_stack.frame_ptr == &eo2_call_stack.stack[0])
eo2_call_stack.frame_ptr = NULL;
else
eo2_call_stack.frame_ptr--;
}
EAPI Eina_Bool
eo2_call_resolve_internal(_Eo *obj, const Eo_Class *klass_id, Eo_Op op, Eo2_Op_Call_Data *call)
eo2_call_resolve_internal(const Eo_Class *klass_id, Eo_Op op, Eo2_Op_Call_Data *call)
{
const _Eo_Class *klass;
const op_type_funcs *func;
const _Eo * obj = eo2_call_stack.frame_ptr->obj;
if (klass_id)
klass = _eo_class_pointer_get(klass_id);
@ -285,8 +337,19 @@ eo2_call_resolve_internal(_Eo *obj, const Eo_Class *klass_id, Eo_Op op, Eo2_Op_C
func = _eo_kls_itr_func_get(klass, op);
if (EINA_LIKELY(func != NULL))
{
call->obj_id = eo2_call_stack.frame_ptr->obj_id;
call->func = func->func;
call->data = _eo_data_scope_get(obj, func->src);
if (func->src == obj->klass)
{
if (eo2_call_stack.frame_ptr->obj_data == EO2_INVALID_DATA)
eo2_call_stack.frame_ptr->obj_data = _eo_data_scope_get(obj, func->src);
call->data = eo2_call_stack.frame_ptr->obj_data;
}
else
call->data = _eo_data_scope_get(obj, func->src);
return EINA_TRUE;
}
@ -297,11 +360,12 @@ eo2_call_resolve_internal(_Eo *obj, const Eo_Class *klass_id, Eo_Op op, Eo2_Op_C
EAPI Eo_Op
eo2_get_op_id(_Eo *obj, void *api_func)
eo2_get_op_id(void *api_func)
{
int imin, imax, imid;
Eo2_Op_Description *op_desc;
Eo2_Op_Description *op_descs;
const _Eo * obj = eo2_call_stack.frame_ptr->obj;
imin = 0;
imax = obj->klass->desc->ops.count - 1;

View File

@ -10,66 +10,66 @@
/* #include "eo_private.h" */
EAPI void
data_set(eo2_a, const char *key, const void *data, eo_base_data_free_func free_func);
data_set(const char *key, const void *data, eo_base_data_free_func free_func);
EAPI void
data_get(eo2_a, const char *key);
data_get(const char *key);
EAPI void
data_del(eo2_a, const char *key);
data_del(const char *key);
EAPI void
wref_add(eo2_a, Eo **wref);
wref_add(Eo **wref);
EAPI void
wref_del(eo2_a, Eo **wref);
wref_del(Eo **wref);
EAPI void
ev_cb_priority_add(eo2_a, const Eo_Event_Description *desc,
ev_cb_priority_add(const Eo_Event_Description *desc,
Eo_Callback_Priority priority, Eo_Event_Cb func,
const void *user_data);
EAPI void
ev_cb_del(eo2_a, const Eo_Event_Description *desc, Eo_Event_Cb func,
ev_cb_del(const Eo_Event_Description *desc, Eo_Event_Cb func,
const void *user_data);
EAPI void
ev_cb_array_priority_add(eo2_a, const Eo_Callback_Array_Item *array,
ev_cb_array_priority_add(const Eo_Callback_Array_Item *array,
Eo_Callback_Priority priority, const void *user_data);
EAPI void
ev_cb_array_del(eo2_a, const Eo_Callback_Array_Item *array,
ev_cb_array_del(const Eo_Callback_Array_Item *array,
const void *user_data);
EAPI Eina_Bool
ev_cb_call(eo2_a, const Eo_Event_Description *desc, void *event_info);
ev_cb_call(const Eo_Event_Description *desc, void *event_info);
EAPI void
ev_cb_forwarder_add(eo2_a, const Eo_Event_Description *desc, Eo *new_obj);
ev_cb_forwarder_add(const Eo_Event_Description *desc, Eo *new_obj);
EAPI void
ev_cb_forwarder_del(eo2_a, const Eo_Event_Description *desc, Eo *new_obj);
ev_cb_forwarder_del(const Eo_Event_Description *desc, Eo *new_obj);
EAPI void
ev_freeze(eo2_a);
ev_freeze();
EAPI void
ev_thaw(eo2_a);
ev_thaw();
EAPI int
ev_freeze_get(eo2_a);
ev_freeze_get();
EAPI void
ev_global_freeze(eo2_a);
ev_global_freeze();
EAPI void
ev_global_thaw(eo2_a);
ev_global_thaw();
EAPI int
ev_global_freeze_get(eo2_a);
ev_global_freeze_get();
EAPI void
dbg_info_get(eo2_a);
dbg_info_get();
EAPI void
eo2_dbg_info_free(Eo_Dbg_Info *info);

View File

@ -60,6 +60,7 @@ typedef uintptr_t Eo_Id;
typedef struct _Eo_Class _Eo_Class;
typedef struct _Eo_Object _Eo_Object;
typedef struct _Eo_Base Eo_Base;
typedef struct _Eo_Internal _Eo;
/* Retrieves the pointer to the object from the id */
static inline _Eo_Object *_eo_obj_pointer_get(const Eo_Id obj_id);