Пример #1
0
void DaoCallServer_AddCall( DaoProcess *caller )
{
	DaoProcess *callee = DaoVmSpace_AcquireProcess( caller->vmSpace );
	DaoStackFrame *frame = caller->topFrame;
	DaoTaskEvent *event = DaoCallServer_MakeEvent();
	DaoType *type = (DaoType*) frame->routine->routType->aux;
	DaoFuture *future = DaoFuture_New( type, 1 );
	DaoValue **params = caller->stackValues + caller->topFrame->stackBase;
	int i, count = caller->topFrame->parCount;

	future->state = DAO_CALL_PAUSED;
	future->actor = caller->topFrame->object;
	GC_IncRC( future->actor );

	GC_ShiftRC( future, callee->future );
	callee->future = future;
	future->process = callee;
	GC_IncRC( future->process );

	callee->parCount = count;
	for(i=0; i<count; ++i) DaoValue_Copy( params[i], & callee->paramValues[i] );
	DaoProcess_PushRoutine( callee, caller->topFrame->routine, future->actor );

	DaoTaskEvent_Init( event, DAO_EVENT_RESUME_TASKLET, DAO_EVENT_RESUME, future, NULL );

	DaoProcess_PopFrame( caller );
	DaoProcess_PutValue( caller, (DaoValue*) future );

	DaoCallServer_Add( event );
}
Пример #2
0
static void DaoMT_InitProcess( DaoProcess *proto, DaoProcess *clone )
{
	DaoProcess_PushRoutine( clone, proto->activeRoutine, proto->activeObject );
	clone->activeCode = proto->activeCode;
	DaoProcess_PushFunction( clone, proto->topFrame->routine );
	DaoProcess_SetActiveFrame( clone, clone->topFrame );
	DaoProcess_PushSectionFrame( clone );
	clone->topFrame->outer = proto;
	clone->topFrame->sect = proto->topFrame->prev;
	clone->topFrame->returning = -1;
}
Пример #3
0
static void DaoMT_InitProcess( DaoProcess *proto, DaoProcess *clone, int argcount )
{
	DaoProcess_PushRoutine( clone, proto->activeRoutine, proto->activeObject );
	clone->activeCode = proto->activeCode;
	DaoProcess_PushFunction( clone, proto->topFrame->routine );
	DaoProcess_InitCodeSection( clone, argcount );
	clone->topFrame->outer = proto;
	clone->topFrame->host = proto->topFrame->prev;
	clone->topFrame->retmode = DVM_RET_PROCESS;
	clone->topFrame->returning = 0;
}
Пример #4
0
static void COROUT_Start( DaoProcess *proc, DaoValue *par[], int N )
{
	DaoxCoroutine *self = (DaoxCoroutine*) par[0];
	DaoValue *params[DAO_MAX_PARAM];
	DaoValue *val = par[1];
	DaoProcess *vmProc;
	DaoRoutine *rout;
	int i, passed = 0;
	if( val == NULL || val->type != DAO_ROUTINE ){
		DaoProcess_RaiseError( proc, "Type", NULL );
		return;
	}
	params[0] = par[0];
	memcpy( params + 1, par + 2, (N-2)*sizeof(DaoValue*) );
	rout = DaoRoutine_Resolve( (DaoRoutine*)val, NULL, NULL, params, NULL, N-1, DVM_CALL );
	if( rout ) rout = DaoProcess_PassParams( proc, rout, NULL, NULL, params, NULL, N-1, DVM_CALL );
	if( rout == NULL || rout->body == NULL ){
		DaoProcess_RaiseError( proc, "Param", "not matched" );
		return;
	}
	if( self->process == NULL ){
		self->process = DaoProcess_New( proc->vmSpace );
		GC_IncRC( self->process );
	}
	vmProc = self->process;
	DaoProcess_PushRoutine( vmProc, rout, NULL );
	vmProc->activeValues = vmProc->stackValues + vmProc->topFrame->stackBase;
	for(i=0; i<rout->parCount; i++){
		vmProc->activeValues[i] = proc->paramValues[i];
		GC_IncRC( vmProc->activeValues[i] );
	}
	vmProc->status = DAO_PROCESS_SUSPENDED;
	vmProc->pauseType = DAO_PAUSE_COROUTINE_YIELD;
	DaoProcess_Start( vmProc );
	DaoProcess_PutValue( proc, vmProc->stackValues[0] );
	if( vmProc->status == DAO_PROCESS_ABORTED )
		DaoProcess_RaiseError( proc, NULL, "coroutine execution is aborted." );
}
Пример #5
0
void DaoCallServer_AddCall( DaoProcess *caller )
{
	DaoFuture *future;
	DaoTaskEvent *event;
	DaoProcess *callee = DaoVmSpace_AcquireProcess( caller->vmSpace );
	DaoStackFrame *frame = caller->topFrame;
	DaoRoutine *routine = frame->routine;
	DaoType *type = (DaoType*) routine->routType->aux;
	DaoValue **params = caller->stackValues + caller->topFrame->stackBase;
	int i, count = caller->topFrame->parCount;

	if( caller->activeCode->b & DAO_CALL_BLOCK ){
		DaoValue **calleeValues, **callerValues = caller->activeValues;
		DaoStackFrame *sectFrame = DaoProcess_FindSectionFrame( caller );
		DaoStackFrame *callerFrame = caller->topFrame->prev;
		DaoVmCode *vmc, *end, *sect;
		if( sectFrame != callerFrame ){
			DaoVmSpace_ReleaseProcess( caller->vmSpace, callee );
			DaoProcess_RaiseError( caller, NULL, "Invalid code section" );
			return;
		}
		if( routine->body ){
			DaoProcess_PushRoutine( callee, callerFrame->routine, callerFrame->object );
			callerValues = caller->stackValues + callerFrame->stackBase;
		}else{
			DaoProcess_PushRoutine( callee, caller->activeRoutine, caller->activeObject );
		}
		DaoProcess_SetActiveFrame( callee, callee->topFrame );
		calleeValues = callee->stackValues + callee->topFrame->stackBase;
		callee->activeCode = caller->activeCode;
		vmc = callerFrame->routine->body->vmCodes->data.codes + callerFrame->entry;
		end = callerFrame->routine->body->vmCodes->data.codes + vmc->b;
		sect = vmc + 1;
		for(vmc=sect; vmc!=end; vmc++){
			int i = -1, code = vmc->code;
			if( code == DVM_GETVH || (code >= DVM_GETVH_I && code <= DVM_GETVH_C) ){
				i = vmc->b;
			}else if( code == DVM_SETVH || (code >= DVM_SETVH_II && code <= DVM_SETVH_CC) ){
				i = vmc->b;
			}
			if( i >= 0 ) DaoValue_Move( callerValues[i], & calleeValues[i], NULL );
		}
	}

	future = DaoFuture_New( type, 1 );
	future->state = DAO_CALL_PAUSED;
	future->actor = caller->topFrame->object;
	GC_IncRC( future->actor );

	GC_Assign( & future->process, callee );
 	GC_Assign( & callee->future, future );

	callee->parCount = count;
	/* Use routine->parCount instead of caller->topFrame->parCount, for default parameters: */
	for(i=0; i<routine->parCount; ++i) DaoValue_Copy( params[i], & callee->paramValues[i] );
	if( routine->body ){
		DaoProcess_PushRoutine( callee, routine, future->actor );
	}else{
		DaoProcess_PushFunction( callee, routine );
		callee->activeNamespace = caller->activeNamespace;
	}
	if( caller->activeCode->b & DAO_CALL_BLOCK ){
		callee->topFrame->host = callee->topFrame;
		callee->topFrame->retmode = DVM_RET_PROCESS;
		callee->topFrame->returning = 0;
	}

#ifdef DAO_WITH_CONCURRENT
	DaoCallServer_TryInit( mainVmSpace );
	event = DaoCallServer_MakeEvent();
	DaoTaskEvent_Init( event, DAO_EVENT_RESUME_TASKLET, DAO_EVENT_RESUME, future, NULL );

	DaoProcess_PopFrame( caller );
	DaoProcess_PutValue( caller, (DaoValue*) future );

	DaoCallServer_Add( event );
#else
	DaoProcess_PopFrame( caller );
	DaoProcess_PutValue( caller, (DaoValue*) future );
	DaoProcess_InterceptReturnValue( callee );
	DaoProcess_Execute( callee );
	DaoProcess_ReturnFutureValue( callee, future );
	DaoVmSpace_ReleaseProcess( caller->vmSpace, callee );
#endif
}