view runtime/func.h @ 141:f2cb85c53ced

Fix Pause/Resume and rewrite Call Async in Rhope rather than C
author Mike Pavone <pavone@retrodev.com>
date Sat, 20 Nov 2010 17:48:22 -0500
parents c14698c512f1
children 7bbdc034e347
line wrap: on
line source

#ifndef _FUNC_H_
#define _FUNC_H_

typedef struct object object;
typedef struct calldata calldata;

typedef enum {
	NORMAL_RETURN=0,
	EXCEPTION_RETURN,
	TAIL_RETURN,
	NO_CONVERSION,
	STACK_UNWIND
} returntype;


typedef returntype (*rhope_func)(calldata *);
typedef void (*special_func) (object *);

#ifdef MULTI_SWITCH
#define DispatchEntry(name) case FUNC_##name: goto f_##name;
#define ResumeEntry(num,name) case RES_##num##_##name: goto r##num##_##name;
#define DispatchVar
#define DISPATCH switch(func) { DispatchEntries }
#define EndEntry case END: goto DO_END;
#define EndThreadEntry case END_THREAD: goto DO_END_THREAD;
#else
#define DispatchEntry(name) &&f_##name,
#define ResumeEntry(num,name) &&r##num##_##name,
#define DispatchVar void * funcs[] = { DispatchEntries };
#define DISPATCH goto *funcs[func];
#define EndEntry &&DO_END,
#define EndThreadEntry &&DO_END_THREAD
#endif


#define MethodName(name,type) f_ ## name ## AT_ ## type

#ifdef ENABLE_PROFILING

#define START_PROFILE \
		gettimeofday(&time, NULL);\
		cdata->accum = cdata->self_accum = 0;\
		cdata->self_start = cdata->start = ((uint64_t)time.tv_sec) * 1000000ULL + ((uint64_t)time.tv_usec);

#define PAUSE_SELF \
		gettimeofday(&time, NULL);\
		my_cdata->self_accum += ((uint64_t)time.tv_sec) * 1000000ULL + ((uint64_t)time.tv_usec) - my_cdata->self_start;
		
#define AND_TOTAL \
		*(my_cdata->myactivationlevel)--;\
		my_cdata->accum += ((uint64_t)time.tv_sec) * 1000000ULL + ((uint64_t)time.tv_usec) - my_cdata->start;

#define RESUME_SELF \
		gettimeofday(&time, NULL);\
		my_cdata->self_start = ((uint64_t)time.tv_sec) * 1000000ULL + ((uint64_t)time.tv_usec);
		
#define AND_RESUME_TOTAL \
		*(my_cdata->myactivationlevel)++;\
		my_cdata->start = my_cdata->self_start;
		
#define EndFunc(name)	\
		free_stack(ct, lv_ ## name);\
		func = cdata->func;\
		profile_activationlevel[FUNC_ ## name]--;\
		gettimeofday(&time, NULL);\
		if(profile_activationlevel[FUNC_ ## name])\
		{\
			profile_nestedcounts[FUNC_ ## name]++;\
		} else {\
			profile_counts[FUNC_ ## name]++;\
			profile_totals[FUNC_ ## name] += ((uint64_t)time.tv_sec) * 1000000ULL + ((uint64_t)time.tv_usec) - cdata->start + cdata->accum;\
		}\
		profile_selftotals[FUNC_ ## name] +=  ((uint64_t)time.tv_sec) * 1000000ULL + ((uint64_t)time.tv_usec) - cdata->self_start + cdata->self_accum;
		
#define Func(name,numparams) \
f_ ## name:\
		for(idx = numparams; idx < cdata->num_params; ++idx)\
			release_ref(cdata->params[idx]); cdata->num_params = numparams;\
sf_ ## name:\
		profile_activationlevel[FUNC_ ## name]++;\
		cdata->myactivationlevel = &profile_activationlevel[FUNC_ ## name];\
		START_PROFILE\
		lv_ ## name = alloc_stack(ct, sizeof(lt_ ## name));\
		my_cdata = cdata;

#define MethodImpl(name,type_name,mytype_id,numparams) \
f_ ## name ## AT_ ## type_name:\
sf_ ## name ## AT_ ## type_name:\
		if (cdata->num_params < 1)\
		{\
			cdata = alloc_cdata(ct, cdata, 0);\
			cdata->func = FUNC_ ## name ## AT_ ## type_name;\
			goto _exception;\
		}\
		if(get_blueprint(cdata->params[0])->type_id != mytype_id)\
		{\
			puts("uh oh, need conversion and that's not implemented yet!");\
			exit(1);\
		}\
m_ ## name ## AT_ ## type_name:\
		profile_activationlevel[FUNC_ ## name ## AT_ ## type_name]++;\
		cdata->myactivationlevel = &profile_activationlevel[FUNC_ ## name ## AT_ ## type_name];\
		START_PROFILE\
		for(idx = numparams; idx < cdata->num_params; ++idx)\
			release_ref(cdata->params[idx]); cdata->num_params = numparams;\
		lv_ ## name ## AT_ ## type_name = alloc_stack(ct, sizeof(lt_ ## name ## AT_ ## type_name));\
		my_cdata = cdata;

#else

#define START_PROFILE
#define PAUSE_SELF
#define RESUME_SELF
#define AND_TOTAL
#define AND_RESUME_TOTAL

#define EndFunc(name)	\
		free_stack(ct, lv_ ## name);\
		func = cdata->func;
		
#define Func(name,numparams) \
f_ ## name:\
		for(idx = numparams; idx < cdata->num_params; ++idx)\
			release_ref(cdata->params[idx]); cdata->num_params = numparams;\
sf_ ## name:\
		lv_ ## name = alloc_stack(ct, sizeof(lt_ ## name));\
		my_cdata = cdata;

#define MethodImpl(name,type_name,mytype_id,numparams) \
f_ ## name ## AT_ ## type_name:\
sf_ ## name ## AT_ ## type_name:\
		if (cdata->num_params < 1)\
		{\
			cdata = alloc_cdata(ct, cdata, 0);\
			cdata->func = FUNC_ ## name ## AT_ ## type_name;\
			goto _exception;\
		}\
		if(get_blueprint(cdata->params[0])->type_id != mytype_id)\
		{\
			puts("uh oh, need conversion and that's not implemented yet!");\
			exit(1);\
		}\
m_ ## name ## AT_ ## type_name:\
		for(idx = numparams; idx < cdata->num_params; ++idx)\
			release_ref(cdata->params[idx]); cdata->num_params = numparams;\
		lv_ ## name ## AT_ ## type_name = alloc_stack(ct, sizeof(lt_ ## name ## AT_ ## type_name));\
		my_cdata = cdata;

#endif

#define EndFuncNoLocals	\
		func = cdata->func;


#define FuncNoLocals(name,numparams) \
f_ ## name:\
		for(idx = numparams; idx < cdata->num_params; ++idx)\
			release_ref(cdata->params[idx]); cdata->num_params = numparams;\
sf_ ## name:\
		my_cdata = cdata;
			
				
#define MethodImplNoLocals(name,type_name,mytype_id,numparams) \
f_ ## name ## AT_ ## type_name:\
sf_ ## name ## AT_ ## type_name:\
		if (cdata->num_params < 1)\
			cdata = alloc_cdata(ct, cdata, 0);\
			cdata->func = FUNC_ ## name ## AT_ ## type_name;\
			goto _exception;\
		if(get_blueprint(cdata->params[0])->type_id != mytype_id)\
		{\
			puts("uh oh, need conversion and that's not implemented yet!");\
			exit(1);\
		}\
m_ ## name ## AT_ ## type_name:\
		for(idx = numparams; idx < cdata->num_params; ++idx)\
			release_ref(cdata->params[idx]); cdata->num_params = numparams;\
		my_cdata = cdata;

		
#define Method(name) \
f_ ## name:\
sf_ ## name:\
		switch(get_blueprint(cdata->params[0])->type_id)\
		{
			
#define EndMethod(mname) \
		default:\
			printf("Type ");\
			fwrite( ((t_Array *)((t_String *)get_blueprint(cdata->params[0])->name)->payload.Buffer)+1, 1, ((t_Array *)((t_String *)get_blueprint(cdata->params[0])->name)->payload.Buffer)->payload.Length, stdout);\
			printf("(%d) does not implement method %s\n", get_blueprint(cdata->params[0])->type_id, #mname);\
			cdata = alloc_cdata(ct, cdata, 0);\
			cdata->func = FUNC_ ## mname;\
			goto _exception;\
		}
			
			
#define MethodDispatch(type_id,name,type_name) \
		case type_id:\
			goto m_ ## name ## AT_ ## type_name;
			
#define NumParams
#define CallSpace

#define Param(num,convtypeid) \
	if(get_blueprint(cdata->params[num])->type_id != convtypeid)\
	{\
		printf("uh oh, need conversion from type %d to type %d for param %d and that's not implemented yet!", get_blueprint(cdata->params[num])->type_id, convtypeid, num);\
		goto _exception;\
	}

#define CopiedParam(num,convtypeid) Param(num,convtypeid) cdata->params[num] = copy_object(cdata->params[num]);
#define Ret(num,val) cdata->params[num] = (object *)(val);
#define NumRet(num) cdata->num_params = num;\
	if (num == 1 && !cdata->params[0])\
	{\
		puts("Worker with only one output failed to produce data for that output!");\
		goto _exception;\
	}
#define Exception
#define FuncDef(name) lt_ ## name * lv_ ## name;
#define MethodDef(name) lt_ ## name ## AT_ ## type_name * lv_ ## name ## AT_ ## type_name;


#define PrepCall(callspace) cdata = alloc_cdata(ct, cdata, callspace);

#define SetParam(num,value) cdata->params[num] = value;


#define VCRePrepCall(func,numparams,lastnumparams) \
	if(numparams + ((t_Worker *)func)->payload.Count > lastnumparams)\
	{\
		temp_cdata = cdata->lastframe;\
		free_stack(ct, cdata);\
		cdata = alloc_cdata(ct, temp_cdata, numparams + ((t_Worker *)func)->payload.Count);\
	}\
	vcparam_offset = 0;

#define VCPrepCall(func,numparams) \
	cdata = alloc_cdata(ct, cdata, numparams + ((t_Worker *)func)->payload.Count);\
	vcparam_offset = 0;

#define VCSetParam(func,num,value) \
	while((num+vcparam_offset) < ((t_Worker *)func)->payload.Size && ((object **)(((t_Worker *)func)+1))[num+vcparam_offset])\
	{\
		cdata->params[num+vcparam_offset] = add_ref(((object **)(((t_Worker *)func)+1))[num+vcparam_offset]);\
		++vcparam_offset;\
	}\
	cdata->params[num+vcparam_offset] = value;\
	last_vcparam = num+vcparam_offset;

#define ValCall(tocall,numparams,resumeto,myname)\
	last_vcparam++;\
	while(last_vcparam < ((t_Worker *)tocall)->payload.Size)\
	{\
		if (((object **)(((t_Worker *)tocall)+1))[last_vcparam]) \
			cdata->params[last_vcparam] = add_ref(((object **)(((t_Worker *)tocall)+1))[last_vcparam]);\
		++last_vcparam;\
	}\
	cdata->func = RES_  ## resumeto ## _ ## myname;\
	cdata->num_params = numparams + ((t_Worker *)tocall)->payload.Count;\
	cdata->vars = lv_ ## myname;\
	func = ((t_Worker *)tocall)->payload.Index;\
	PAUSE_SELF

#define ValCallPostlude(resumeto,myname)\
r ## resumeto ## _ ## myname:\
	my_cdata = cdata->lastframe;\
	RESUME_SELF\
	lv_ ## myname = cdata->vars;
	
#define ValCallNoLocals(tocall,numparams,resumeto,myname)\
	last_vcparam++;\
	while(last_vcparam < ((t_Worker *)tocall)->payload.Size)\
	{\
		if (((object **)(((t_Worker *)tocall)+1))[last_vcparam]) \
			cdata->params[last_vcparam] = add_ref(((object **)(((t_Worker *)tocall)+1))[last_vcparam]);\
		++last_vcparam;\
	}\
	cdata->func = RES_  ## resumeto ## _ ## myname;\
	cdata->num_params = numparams + ((t_Worker *)tocall)->payload.Count;\
	func = ((t_Worker *)tocall)->payload.Index;\
	PAUSE_SELF

#define ValCallNoLocalsPostlude(resumeto,myname)\
r ## resumeto ## _ ## myname:\
	my_cdata = cdata->lastframe;\
	RESUME_SELF


#define Call(tocall, numparams, resumeto, myname)\
			cdata->func = RES_  ## resumeto ## _ ## myname;\
			cdata->num_params = numparams;\
			cdata->vars = lv_ ## myname;\
			if(FUNC_ ## tocall == FUNC_ ## myname) {\
				PAUSE_SELF\
				AND_TOTAL\
			} else if (FUNC_ ## tocall != FUNC_PL_ && FUNC_ ## tocall != FUNC_MN_ && FUNC_ ## tocall != FUNC_TM_ && FUNC_ ## tocall != FUNC_DV_ && FUNC_ ## tocall != FUNC_If) {\
				PAUSE_SELF\
			}\
			goto sf_ ## tocall;\
r ## resumeto ## _ ## myname:\
			my_cdata = cdata->lastframe;\
			if(FUNC_ ## tocall == FUNC_ ## myname) {\
				RESUME_SELF\
				AND_RESUME_TOTAL\
			} else if (FUNC_ ## tocall != FUNC_PL_ && FUNC_ ## tocall != FUNC_MN_ && FUNC_ ## tocall != FUNC_TM_ && FUNC_ ## tocall != FUNC_DV_ && FUNC_ ## tocall != FUNC_If) {\
				RESUME_SELF\
			}\
			lv_ ## myname = cdata->vars;
			
	
#define FreeCall\
			temp_cdata = cdata->lastframe;\
			free_stack(ct, cdata);\
			cdata = temp_cdata;

#define FreeCallMethod(myname,mytype)\
			temp_cdata = cdata->lastframe;\
			free_stack(ct, cdata);\
			cdata = temp_cdata;\
			lv_ ## myname ## AT_ ## type_name = (lt_ ## myname ## AT_ ## type_name *)(cdata+1);
			
#define TPrepCall(callspace) \
			func = cdata->lastframe->func;\
			temp_cdata = cdata->lastframe->lastframe;\
			free_stack(ct, cdata->lastframe);\
			cdata = alloc_cdata(ct, temp_cdata, callspace);\
			cdata->func = func;
			
#define TCall(tocall, numparams)\
			cdata->num_params = numparams;\
			goto sf_ ## tocall;
	
	
#endif //_FUNC_H_