static void DaoMT_Critical( DaoProcess *proc, DaoValue *p[], int n ) { void *key; DNode *it; DMap *cache = (DMap*) DaoProcess_GetAuxData( proc, DaoMT_ProcMutexCache ); DaoVmCode *sect = DaoProcess_InitCodeSection( proc, 0 ); DaoRoutine *routine = proc->activeRoutine; if( sect == NULL ) return; /* Get the original routine, if this one is a specialized copy: */ while( routine->original ) routine = routine->original; /* // Use "routine + sect->c" instead of "sect" as the key for mutex, // as "sect" may be different for different copy of specialized routine. // But "sect->c" won't change after being set during compiling. */ key = routine + sect->c; if( cache == NULL ){ cache = DHash_New(0,0); /* Local cache is used to avoid extra locking; */ DaoProcess_SetAuxData( proc, DaoMT_ProcMutexCache, cache ); } it = DMap_Find( cache, key ); /* Check local cache first; */ if( it == NULL ) it = DMap_Insert( cache, key, DaoMT_GetMutex( routine, key ) ); DMutex_Lock( (DMutex*) it->value.pVoid ); DaoProcess_Execute( proc ); DMutex_Unlock( (DMutex*) it->value.pVoid ); DaoProcess_PopFrame( proc ); }
static void DaoIO_WriteLines( DaoProcess *proc, DaoValue *p[], int N ) { DString *string; DaoInteger idint = {DAO_INTEGER,0,0,0,0,0}; DaoValue *res, *index = (DaoValue*)(void*)&idint; DaoVmCode *sect = DaoGetSectionCode( proc->activeCode ); daoint i, entry, lines = p[1]->xInteger.value; FILE *fout = stdout; if( p[0]->type == DAO_STRING ){ fout = DaoIO_OpenFile( proc, p[0]->xString.data, "w+", 0 ); if( fout == NULL ) return; }else{ if( p[0]->xStream.file ) fout = p[0]->xStream.file; } if( sect == NULL || DaoProcess_PushSectionFrame( proc ) == NULL ) return; entry = proc->topFrame->entry; for(i=0; i<lines; i++){ idint.value = i; if( sect->b >0 ) DaoProcess_SetValue( proc, sect->a, index ); proc->topFrame->entry = entry; DaoProcess_Execute( proc ); if( proc->status == DAO_PROCESS_ABORTED ) break; string = proc->stackValues[0]->xString.data; if( string->mbs ){ fprintf( fout, "%s", string->mbs ); }else{ fprintf( fout, "%ls", string->wcs ); } } DaoProcess_PopFrame( proc ); }
static void STD_List( DaoProcess *proc, DaoValue *p[], int N ) { DaoInteger idint = {DAO_INTEGER,0,0,0,0,0}; DaoValue *res = p[N==2], *index = (DaoValue*)(void*)&idint; DaoVmCode *sect = DaoGetSectionCode( proc->activeCode ); DaoList *list = DaoProcess_PutList( proc ); daoint i, entry, size = p[0]->xInteger.value; daoint fold = N == 2; if( fold ) DaoList_Append( list, res ); if( sect == NULL || size < 0 ) return; // TODO exception if( DaoProcess_PushSectionFrame( proc ) == NULL ) return; entry = proc->topFrame->entry; DaoProcess_AcquireCV( proc ); for(i=fold; i<size; i++){ idint.value = i; if( sect->b >0 ) DaoProcess_SetValue( proc, sect->a, index ); if( sect->b >1 && N ==2 ) DaoProcess_SetValue( proc, sect->a+1, res ); proc->topFrame->entry = entry; DaoProcess_Execute( proc ); if( proc->status == DAO_PROCESS_ABORTED ) break; res = proc->stackValues[0]; DaoList_Append( list, res ); } DaoProcess_ReleaseCV( proc ); DaoProcess_PopFrame( proc ); }
static void STD_Map( DaoProcess *proc, DaoValue *p[], int N ) { DaoInteger idint = {DAO_INTEGER,0,0,0,0,0}; DaoValue *res, *index = (DaoValue*)(void*)&idint; DaoVmCode *sect = DaoGetSectionCode( proc->activeCode ); DaoMap *map = DaoProcess_PutMap( proc, p[1]->xInteger.value ); daoint i, entry, size = p[0]->xInteger.value; if( sect == NULL || size < 0 ) return; // TODO exception if( DaoProcess_PushSectionFrame( proc ) == NULL ) return; entry = proc->topFrame->entry; DaoProcess_AcquireCV( proc ); for(i=0; i<size; i++){ idint.value = i; if( sect->b >0 ) DaoProcess_SetValue( proc, sect->a, index ); proc->topFrame->entry = entry; DaoProcess_Execute( proc ); if( proc->status == DAO_PROCESS_ABORTED ) break; res = proc->stackValues[0]; if( res->type == DAO_TUPLE && res->xTuple.size == 2 ) DaoMap_Insert( map, res->xTuple.items[0], res->xTuple.items[1] ); } DaoProcess_ReleaseCV( proc ); DaoProcess_PopFrame( proc ); }
static void TEST_AssertError( DaoProcess *proc, DaoValue* p[], int N ) { DString *expected = p[0]->xString.value; DString *actual = NULL; DList *errors = proc->exceptions; DaoVmCode *sect = DaoProcess_InitCodeSection( proc, 0 ); int catched = 0; int size = errors->size; if( sect == NULL ) return; DaoProcess_Execute( proc ); if ( proc->status == DAO_PROCESS_ABORTED && errors->size > size ){ DaoException *e = (DaoException*)&errors->items.pValue[errors->size - 1]->xCdata; if ( DString_Compare( expected, e->ctype->name ) != 0 ) actual = DString_Copy( e->ctype->name ); else catched = 1; DList_Clear( errors ); } DaoProcess_PopFrame( proc ); if ( !catched ){ char buf[512]; if ( actual ){ snprintf( buf, sizeof(buf), "expected %s error, intercepted %s", expected->chars, actual->chars ); DString_Delete( actual ); } else snprintf( buf, sizeof(buf), "expected %s error, intercepted nothing", expected->chars ); DaoProcess_RaiseError( proc, "Test::AssertError", buf ); } }
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 ); }
static void DaoStream_ReadLines( DaoStream *self, DaoList *list, DaoProcess *proc, int count, int chop ) { DaoValue *res; DaoString *line; DaoVmCode *sect = DaoProcess_InitCodeSection( proc, 1 ); daoint i = 0; if( sect == NULL ){ line = DaoString_New(); while( (count == 0 || (i++) < count) && DaoStream_ReadLine( self, line->value ) ){ if( line->value->size == 0 && self->AtEnd != NULL && self->AtEnd( self ) ) break; if( chop ) DString_Chop( line->value, 0 ); DaoList_Append( list, (DaoValue*) line ); } DaoString_Delete( line ); }else{ ushort_t entry = proc->topFrame->entry; if( sect->b ){ DaoString tmp = {DAO_STRING,0,0,0,1,NULL}; DString tmp2 = DString_WrapChars( "" ); tmp.value = & tmp2; line = (DaoString*) DaoProcess_SetValue( proc, sect->a, (DaoValue*)(void*) &tmp ); } while( (count == 0 || (i++) < count) && DaoStream_ReadLine( self, line->value ) ){ if( line->value->size == 0 && self->AtEnd != NULL && self->AtEnd( self ) ) break; if( chop ) DString_Chop( line->value, 0 ); proc->topFrame->entry = entry; DaoProcess_Execute( proc ); if( proc->status == DAO_PROCESS_ABORTED ) break; res = proc->stackValues[0]; if( res && res->type != DAO_NONE ) DaoList_Append( list, res ); } DaoProcess_PopFrame( proc ); } }
static void DaoMT_Critical( DaoProcess *proc, DaoValue *p[], int n ) { DaoVmCode *sect = DaoGetSectionCode( proc->activeCode ); if( sect == NULL || DaoMT_PushSectionFrame( proc ) == 0 ) return; if( proc->mutex ) DMutex_Lock( proc->mutex ); DaoProcess_Execute( proc ); if( proc->mutex ) DMutex_Unlock( proc->mutex ); DaoProcess_PopFrame( proc ); }
static void DaoSema_Lib_Protect( DaoProcess *proc, DaoValue *p[], int n ) { DaoSema *self = (DaoSema*) p[0]; DaoVmCode *sect = DaoGetSectionCode( proc->activeCode ); if( sect == NULL || DaoMT_PushSectionFrame( proc ) == 0 ) return; DSema_Wait( & self->mySema ); DaoProcess_Execute( proc ); DSema_Post( & self->mySema ); DaoProcess_PopFrame( proc ); }
static void DaoMutex_Lib_Protect( DaoProcess *proc, DaoValue *p[], int n ) { DaoMutex *self = (DaoMutex*) p[0]; DaoVmCode *sect = DaoGetSectionCode( proc->activeCode ); if( sect == NULL || DaoMT_PushSectionFrame( proc ) == 0 ) return; DaoMutex_Lock( self ); DaoProcess_Execute( proc ); DaoMutex_Unlock( self ); DaoProcess_PopFrame( proc ); }
static void NODE_Search( DaoProcess *proc, DaoValue *p[], int N ) { DList *nodes; DaoList *list = DaoProcess_PutList( proc ); DaoxNode *self = (DaoxNode*) p[0]; DaoVmCode *sect = DaoProcess_InitCodeSection( proc, 1 ); daoint method = p[1]->xEnum.value; daoint which = p[2]->xEnum.value; daoint i, j, entry; if( sect == NULL ) return; for(i=0; i<self->graph->nodes->size; i++){ DaoxNode *node = (DaoxNode*) self->graph->nodes->items.pVoid[i]; node->state = 0; } nodes = DList_New(0); DList_PushBack( nodes, self ); entry = proc->topFrame->entry; while( nodes->size ){ DaoxNode *node = NULL; if( method ){ node = (DaoxNode*) DList_Front( nodes ); DList_PopFront( nodes ); }else{ node = (DaoxNode*) DList_Back( nodes ); DList_PopBack( nodes ); } if( node->state ) continue; node->state = 1; if( sect->b >0 ) DaoProcess_SetValue( proc, sect->a, (DaoValue*) node ); proc->topFrame->entry = entry; DaoProcess_Execute( proc ); if( proc->status == DAO_PROCESS_ABORTED ) break; if( proc->stackValues[0]->xInteger.value ){ DaoList_PushBack( list, (DaoValue*) node ); if( which == 0 ) break; } for(j=0; j<node->outs->size; j++){ DaoxEdge *edge = (DaoxEdge*) node->outs->items.pVoid[j]; DaoxNode *node2 = node == edge->first ? edge->second : edge->first; DList_PushBack( nodes, node2 ); } } DaoProcess_PopFrame( proc ); DList_Delete( nodes ); }
static void DaoSTD_Exec( DaoProcess *proc, DaoValue *p[], int n ) { DaoVmCode *sect = DaoProcess_InitCodeSection( proc, 0 ); int ecount = proc->exceptions->size; if( sect == NULL ) return; DaoProcess_Execute( proc ); DaoProcess_PopFrame( proc ); if( proc->exceptions->size > ecount ){ if( n > 0 ){ DaoProcess_PutValue( proc, p[0] ); DList_Erase( proc->exceptions, ecount, -1 ); } }else{ DaoProcess_PutValue( proc, proc->stackValues[0] ); } }
static void DaoMT_Start( DaoProcess *proc, DaoValue *p[], int n ) { DaoProcess *clone; DaoVmCode *vmc, *end; DaoVmCode *sect = DaoGetSectionCode( proc->activeCode ); DaoType *type = DaoProcess_GetReturnType( proc ); DaoFuture *future = DaoFuture_New( type, 0 ); int entry, nop = proc->activeCode[1].code == DVM_NOP; DaoProcess_PutValue( proc, (DaoValue*) future ); if( sect == NULL || DaoMT_PushSectionFrame( proc ) == 0 ) return; entry = proc->topFrame->entry; end = proc->activeRoutine->body->vmCodes->data.codes + proc->activeCode[nop+1].b; clone = DaoVmSpace_AcquireProcess( proc->vmSpace ); DaoProcess_PopFrame( proc ); DaoProcess_SetActiveFrame( proc, proc->topFrame ); DaoMT_InitProcess( proc, clone ); clone->topFrame->entry = entry; /* // Use the cloned process instead of the parent process, in case that // the cloned process will not be joined by the parent process: */ clone->topFrame->outer = clone; future->process = clone; GC_IncRC( clone ); GC_ShiftRC( future, clone->future ); clone->future = future; future->state = DAO_CALL_RUNNING; 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 ){ /* These values should be shared with the parent thread: */ GC_ShiftRC( proc->activeValues[i], clone->activeValues[i] ); clone->activeValues[i] = proc->activeValues[i]; } } DaoCallServer_AddTask( DaoMT_Start0, clone, p[0]->xEnum.value ); }
static void FRAME_ScanCells( DaoProcess *proc, DaoValue *p[], int npar ) { DaoxDataFrame *self = (DaoxDataFrame*) p[0]; DaoVmCode *sect = DaoGetSectionCode( proc->activeCode ); DaoInteger integer1 = {DAO_INTEGER,0,0,0,0,0}; DaoInteger integer2 = {DAO_INTEGER,0,0,0,0,0}; DaoInteger integer3 = {DAO_INTEGER,0,0,0,0,0}; DaoInteger *rowidx = & integer1; DaoInteger *colidx = & integer2; DaoInteger *depidx = & integer3; DaoValue value; daoint N = self->dims[0]; daoint M = self->dims[1]; daoint K = self->dims[2]; daoint NK = N * K; daoint entry, i, j; value.xInteger = integer1; if( sect == NULL ) return; if( DaoProcess_PushSectionFrame( proc ) == NULL ) return; entry = proc->topFrame->entry; DaoProcess_AcquireCV( proc ); for(j=0; j<M; ++j){ DaoxDataColumn *column = (DaoxDataColumn*) self->columns->items.pVoid[j]; colidx->value = j; for(i=0; i<NK; ++i){ rowidx->value = i % N; depidx->value = i / N; if( sect->b >0 ){ DaoValue *cell = DaoxDataColumn_GetCell( column, i, & value ); DaoProcess_SetValue( proc, sect->a, cell ); } if( sect->b >1 ) DaoProcess_SetValue( proc, sect->a+1, (DaoValue*) rowidx ); if( sect->b >2 ) DaoProcess_SetValue( proc, sect->a+2, (DaoValue*) colidx ); if( sect->b >3 ) DaoProcess_SetValue( proc, sect->a+3, (DaoValue*) depidx ); proc->topFrame->entry = entry; DaoProcess_Execute( proc ); if( proc->status == DAO_PROCESS_ABORTED ) break; } } DaoProcess_ReleaseCV( proc ); DaoProcess_PopFrame( proc ); }
static void DaoIO_ReadLines( DaoProcess *proc, DaoValue *p[], int N ) { DString *fname; DaoValue *res; DaoString *line; DaoVmCode *sect = DaoGetSectionCode( proc->activeCode ); DaoList *list = DaoProcess_PutList( proc ); int chop = p[1]->xInteger.value; char buf[IO_BUF_SIZE]; FILE *fin; if( proc->vmSpace->options & DAO_OPTION_SAFE ){ DaoProcess_RaiseException( proc, DAO_ERROR, "not permitted" ); return; } fin = DaoIO_OpenFile( proc, p[0]->xString.data, "r", 0 ); if( fin == NULL ) return; if( sect == NULL || DaoProcess_PushSectionFrame( proc ) == NULL ){ line = DaoString_New(1); while( DaoFile_ReadLine( fin, line->data ) ){ if( chop ) DString_Chop( line->data ); DaoList_Append( list, (DaoValue*) line ); } DaoString_Delete( line ); }else{ ushort_t entry = proc->topFrame->entry; DaoString tmp = {DAO_STRING,0,0,0,1,NULL}; tmp.data = p[0]->xString.data; line = (DaoString*) DaoProcess_SetValue( proc, sect->a, (DaoValue*)(void*) &tmp ); DaoProcess_AcquireCV( proc ); while( DaoFile_ReadLine( fin, line->data ) ){ if( chop ) DString_Chop( line->data ); proc->topFrame->entry = entry; DaoProcess_Execute( proc ); if( proc->status == DAO_PROCESS_ABORTED ) break; res = proc->stackValues[0]; if( res && res->type != DAO_NONE ) DaoList_Append( list, res ); } DaoProcess_ReleaseCV( proc ); DaoProcess_PopFrame( proc ); } fclose( fin ); }
static void DaoSTD_Try( DaoProcess *proc, DaoValue *p[], int n ) { DaoVmCode *sect = DaoProcess_InitCodeSection( proc, 0 ); int i, ecount = proc->exceptions->size; if( sect == NULL ) return; DaoProcess_Execute( proc ); DaoProcess_PopFrame( proc ); if( proc->exceptions->size > (ecount+1) ){ DaoList *list = DaoProcess_PutList( proc ); for(i=ecount; i<proc->exceptions->size; ++i){ DaoList_Append( list, proc->exceptions->items.pValue[i] ); } DList_Erase( proc->exceptions, ecount, -1 ); }else if( proc->exceptions->size > ecount ){ DaoProcess_PutValue( proc, proc->exceptions->items.pValue[proc->exceptions->size-1] ); DList_PopBack( proc->exceptions ); }else{ DaoProcess_PutValue( proc, proc->stackValues[0] ); } }
static void STD_Iterate( DaoProcess *proc, DaoValue *p[], int N ) { DaoInteger idint = {DAO_INTEGER,0,0,0,0,0}; DaoValue *index = (DaoValue*)(void*)&idint; DaoVmCode *sect = DaoGetSectionCode( proc->activeCode ); daoint i, entry, times = p[0]->xInteger.value; if( sect == NULL || times < 0 ) return; // TODO exception if( DaoProcess_PushSectionFrame( proc ) == NULL ) return; entry = proc->topFrame->entry; DaoProcess_AcquireCV( proc ); for(i=0; i<times; i++){ idint.value = i; if( sect->b >0 ) DaoProcess_SetValue( proc, sect->a, index ); proc->topFrame->entry = entry; DaoProcess_Execute( proc ); if( proc->status == DAO_PROCESS_ABORTED ) break; } DaoProcess_ReleaseCV( proc ); DaoProcess_PopFrame( proc ); }
static void DaoMT_Start( DaoProcess *proc, DaoValue *p[], int n ) { DaoProcess *clone; DaoVmCode *vmc, *end, *sect; DaoType *type = DaoProcess_GetReturnType( proc ); DaoFuture *future = DaoFuture_New( type, 0 ); int entry, nop = proc->activeCode[1].code == DVM_NOP; DaoProcess_PutValue( proc, (DaoValue*) future ); sect = DaoProcess_InitCodeSection( proc, 0 ); if( sect == NULL ) return; entry = proc->topFrame->entry; end = proc->activeRoutine->body->vmCodes->data.codes + proc->activeCode[nop+1].b; clone = DaoVmSpace_AcquireProcess( proc->vmSpace ); DaoProcess_PopFrame( proc ); DaoMT_InitProcess( proc, clone, 0 ); clone->topFrame->entry = entry; /* // Use the cloned process instead of the parent process, in case that // the cloned process will not be joined by the parent process: */ clone->topFrame->outer = clone; future->process = clone; GC_IncRC( clone ); GC_Assign( & clone->future, future ); future->state = DAO_CALL_RUNNING; 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( proc->activeValues[i], & clone->activeValues[i], NULL ); } DaoCallServer_AddTask( DaoMT_Start0, clone, p[0]->xEnum.value ? clone : NULL ); }
static void GRAPH_FindEdges( DaoProcess *proc, DaoValue *p[], int N ) { DaoxGraph *self = (DaoxGraph*) p[0]; DaoList *list = DaoProcess_PutList( proc ); DaoVmCode *sect = DaoProcess_InitCodeSection( proc, 1 ); daoint which = p[1]->xEnum.value; daoint i, j, entry; if( sect == NULL ) return; entry = proc->topFrame->entry; for(i=0; i<self->edges->size; i++){ DaoxEdge *edge = (DaoxEdge*) self->edges->items.pVoid[i]; if( sect->b >0 ) DaoProcess_SetValue( proc, sect->a, (DaoValue*) edge ); proc->topFrame->entry = entry; DaoProcess_Execute( proc ); if( proc->status == DAO_PROCESS_ABORTED ) break; if( proc->stackValues[0]->xInteger.value ){ DaoList_PushBack( list, (DaoValue*) edge ); if( which == 0 ) break; } } DaoProcess_PopFrame( proc ); }
static void DaoIO_ReadLines2( DaoProcess *proc, DaoValue *p[], int N ) { DaoValue *res; DaoString *line; DaoVmCode *sect = DaoGetSectionCode( proc->activeCode ); DaoList *list = DaoProcess_PutList( proc ); DaoStream *self = & p[0]->xStream; daoint i = 0, count = p[1]->xInteger.value; int chop = p[2]->xInteger.value; if( sect == NULL || DaoProcess_PushSectionFrame( proc ) == NULL ){ line = DaoString_New(1); while( (i++) < count && DaoStream_ReadLine( self, line->data ) ){ if( chop ) DString_Chop( line->data ); DaoList_Append( list, (DaoValue*) line ); } DaoString_Delete( line ); }else{ ushort_t entry = proc->topFrame->entry; DaoString tmp = {DAO_STRING,0,0,0,1,NULL}; DString tmp2 = DString_WrapMBS( "" ); tmp.data = & tmp2; line = (DaoString*) DaoProcess_SetValue( proc, sect->a, (DaoValue*)(void*) &tmp ); DaoProcess_AcquireCV( proc ); while( (i++) < count && DaoStream_ReadLine( self, line->data ) ){ if( chop ) DString_Chop( line->data ); proc->topFrame->entry = entry; DaoProcess_Execute( proc ); if( proc->status == DAO_PROCESS_ABORTED ) break; res = proc->stackValues[0]; if( res && res->type != DAO_NONE ) DaoList_Append( list, res ); } DaoProcess_ReleaseCV( proc ); DaoProcess_PopFrame( proc ); } }
static void STD_String( DaoProcess *proc, DaoValue *p[], int N ) { DaoInteger idint = {DAO_INTEGER,0,0,0,0,0}; DaoValue *index = (DaoValue*)(void*)&idint; DaoVmCode *sect = DaoGetSectionCode( proc->activeCode ); DString *string = DaoProcess_PutMBString( proc, "" ); daoint i, entry, size = p[0]->xInteger.value; if( p[1]->xEnum.value ) DString_ToWCS( string ); if( sect == NULL || size < 0 ) return; // TODO exception if( DaoProcess_PushSectionFrame( proc ) == NULL ) return; entry = proc->topFrame->entry; DaoProcess_AcquireCV( proc ); for(i=0; i<size; i++){ idint.value = i; if( sect->b >0 ) DaoProcess_SetValue( proc, sect->a, index ); proc->topFrame->entry = entry; DaoProcess_Execute( proc ); if( proc->status == DAO_PROCESS_ABORTED ) break; DString_AppendWChar( string, proc->stackValues[0]->xInteger.value ); } DaoProcess_ReleaseCV( proc ); DaoProcess_PopFrame( proc ); }
static void STD_Array( DaoProcess *proc, DaoValue *p[], int N ) { DaoInteger idint = {DAO_INTEGER,0,0,0,0,0}; DaoValue *res, *index = (DaoValue*)(void*)&idint; DaoVmCode *sect = DaoGetSectionCode( proc->activeCode ); DaoArray *array = DaoProcess_PutArray( proc ); DaoArray *first = NULL; DaoArray *sub = NULL; daoint i, j, k, entry, size = 1; /* if multi-dimensional array is disabled, DaoProcess_PutArray() will raise exception. */ #ifdef DAO_WITH_NUMARRAY for(i=0; i<N; i++){ daoint d = p[i]->xInteger.value; if( d < 0 ){ DaoProcess_RaiseException( proc, DAO_ERROR_PARAM, NULL ); break; } size *= d; } if( size == 0 ) return; if( sect == NULL ) return; // TODO exception if( DaoProcess_PushSectionFrame( proc ) == NULL ) return; entry = proc->topFrame->entry; DaoProcess_AcquireCV( proc ); for(i=0; i<size; i++){ idint.value = i; if( sect->b >0 ) DaoProcess_SetValue( proc, sect->a, index ); proc->topFrame->entry = entry; DaoProcess_Execute( proc ); if( proc->status == DAO_PROCESS_ABORTED ) break; res = proc->stackValues[0]; if( i == 0 ){ int D = N; DaoArray_SetDimCount( array, N + (res->type == DAO_ARRAY ? res->xArray.ndim : 0) ); for(j=0; j<N; j++) array->dims[j] = p[j]->xInteger.value; if( res->type == DAO_ARRAY ){ first = DaoArray_Copy( (DaoArray*) res ); if( first->ndim == 2 && (first->dims[0] == 1 || first->dims[1] == 1) ){ D += 1; array->dims[N] = first->dims[ first->dims[0] == 1 ]; }else{ D += first->ndim; memmove( array->dims + N, first->dims, first->ndim*sizeof(daoint) ); } } DaoArray_ResizeArray( array, array->dims, D ); } if( res->type == DAO_ARRAY ){ sub = (DaoArray*) res; if( first == NULL || DaoArray_AlignShape( sub, NULL, first->dims, first->ndim ) ==0 ){ DaoProcess_RaiseException( proc, DAO_ERROR, "inconsistent elements or subarrays" ); break; } k = i * sub->size; for(j=0; j<sub->size; j++){ switch( array->etype ){ case DAO_INTEGER : array->data.i[k+j] = DaoArray_GetInteger( sub, j ); break; case DAO_FLOAT : array->data.f[k+j] = DaoArray_GetFloat( sub, j ); break; case DAO_DOUBLE : array->data.d[k+j] = DaoArray_GetDouble( sub, j ); break; case DAO_COMPLEX : array->data.c[k+j] = DaoArray_GetComplex( sub, j ); break; } } }else{ switch( array->etype ){ case DAO_INTEGER : array->data.i[i] = DaoValue_GetInteger( res ); break; case DAO_FLOAT : array->data.f[i] = DaoValue_GetFloat( res ); break; case DAO_DOUBLE : array->data.d[i] = DaoValue_GetDouble( res ); break; case DAO_COMPLEX : array->data.c[i] = DaoValue_GetComplex( res ); break; } } } DaoProcess_ReleaseCV( proc ); DaoProcess_PopFrame( proc ); if( first ) DaoArray_Delete( first ); #endif }
bool DaoxDebugger::EditContinue ( DaoProcess *process, int newEntryLine, QList<int> & lineMap, QStringList & newCodes, QStringList & routCodes ) { DaoRoutine *oldrout = process->activeRoutine; int i, j, k, dest = 0; //printf( "=======%s\n", routCodes.join("\n").toLocal8Bit().data() ); //printf( "=======%s\n", newCodes.join("\n").toLocal8Bit().data() ); if( routCodes.size() == newCodes.size() ){ DaoLexer *lexer = DaoLexer_New(); bool eq = true; for(i=0; i<routCodes.size(); i++){ QString s1 = NormalizeCodes( routCodes[i], lexer ); QString s2 = NormalizeCodes( newCodes[i], lexer ); if( s1 != s2 ){ eq = false; break; } } DaoLexer_Delete( lexer ); if( eq ) return true; } QString codes = newCodes.join( "\n" ); DaoParser *parser = DaoParser_New(); DaoRoutine *routine = DaoRoutine_New( oldrout->nameSpace, oldrout->routHost, 1 ); routine->routType = oldrout->routType; routine->parCount = oldrout->parCount; routine->attribs = oldrout->attribs; routine->defLine = oldrout->defLine; parser->routine = routine; parser->nameSpace = routine->nameSpace = oldrout->nameSpace; parser->vmSpace = oldrout->nameSpace->vmSpace; DString_Assign( parser->fileName, oldrout->nameSpace->name ); routine->body->codeStart = oldrout->body->codeStart; routine->body->codeEnd = oldrout->body->codeStart + newCodes.size() + 1; parser->regCount = routine->parCount; parser->levelBase = oldrout->defLine != 0; bool res = DaoParser_LexCode( parser, codes.toLocal8Bit().data(), 1 ); for(i=0; i<(int)parser->tokens->size; i++){ parser->tokens->items.pToken[i]->line += routine->body->codeStart; } for(i=0; i<(int)oldrout->body->defLocals->size; i++){ DaoToken *tok = oldrout->body->defLocals->items.pToken[i]; if( tok->index >= oldrout->parCount || tok->type ==0 ) break; MAP_Insert( DList_Top( parser->lookupTables ), & tok->string, i ); DList_Append( routine->body->defLocals, tok ); } res = res && DaoParser_ParseRoutine( parser ); DaoParser_Delete( parser ); if( res == false ){ DaoRoutine_Delete( routine ); return false; } if( (process->stackSize - process->stackTop) < (routine->body->regCount + DAO_MAX_PARAM) ){ DaoProcess_PushFrame( process, routine->body->regCount ); DaoProcess_PopFrame( process ); } DaoType **regTypes = routine->body->regType->items.pType; DaoValue **newValues = process->activeValues; DaoValue **oldValues = (DaoValue**)calloc( oldrout->body->regCount, sizeof(DaoValue*) ); memcpy( oldValues, newValues, oldrout->body->regCount * sizeof(DaoValue*) ); memset( newValues, 0, oldrout->body->regCount * sizeof(DaoValue*) ); DaoProcess_InitTopFrame( process, routine, process->activeObject ); #if 0 DaoStream *stream = DaoStream_New(); DaoRoutine_PrintCode( oldrout, stream ); DaoRoutine_PrintCode( routine, stream ); #endif regmap.clear(); for(i=0; i<oldrout->parCount; i++) regmap[i] = i; DaoVmCode *oldVMC = oldrout->body->vmCodes->data.codes; DaoVmCode *newVMC = routine->body->vmCodes->data.codes; DaoVmCodeX **oldAnnot = oldrout->body->annotCodes->items.pVmc; DaoVmCodeX **newAnnot = routine->body->annotCodes->items.pVmc; int M = oldrout->body->vmCodes->size; int N = routine->body->vmCodes->size; j = k = 0; for(i=0; i<lineMap.size(); i++){ QList<DaoVmCode> oldLineCodes; QList<DaoVmCode> newLineCodes; if( lineMap[i] <0 ) continue; int old = lineMap[i] + oldrout->body->codeStart + 1; int niu = i + routine->body->codeStart + 1; //printf( "%3i %3i: %3i %3i; %3i %3i\n", j, k, i, niu, lineMap[i], old ); while( j<M && oldAnnot[j]->line < old ) ++j; while( k<N && newAnnot[k]->line < niu ) ++k; while( j<M && oldAnnot[j]->line == old ){ oldLineCodes.append( oldVMC[j] ); ++j; } while( k<N && newAnnot[k]->line == niu ){ newLineCodes.append( newVMC[k] ); ++k; } Matching( oldLineCodes, newLineCodes ); } QMap<int,int>::iterator it, end = regmap.end(); for(it=regmap.begin(); it != end; ++it){ j = it.key(); i = it.value(); DaoValue_Move( oldValues[j], & newValues[i], regTypes[i] ); } int offset = 0; if( newEntryLine <0 ){ DaoVmCodeX **annotCodes = oldrout->body->annotCodes->items.pVmc; int entry = (process->activeCode - process->topFrame->codes) + 1; int entryline = oldrout->body->annotCodes->items.pVmc[entry]->line; /* if the entry line is NOT modified, use it */ entryline -= oldrout->body->codeStart + 1; for(i=0; i<lineMap.size(); i++) if( lineMap[i] == entryline ) break; int newEntryLine = i < lineMap.size() ? i : -1; if( newEntryLine >=0 ){ entryline += oldrout->body->codeStart + 1; while( (--entry) >=0 && annotCodes[entry]->line == entryline ) offset ++; } /* if the entry line IS modified, set the entry line to the first modified line */ if( newEntryLine <0 ){ for(i=0; i<lineMap.size(); i++) if( lineMap[i] <0 ) break; newEntryLine = i; } /* if the entry line is manually set: */ newEntryLine += routine->body->codeStart + 1; } //XXX GC_ShiftRC( routine, oldrout ); GC_IncRC( routine ); oldrout->body->revised = routine; process->activeRoutine = routine; process->activeTypes = regTypes; process->topFrame->codes = routine->body->vmCodes->data.codes; ResetExecution( process, newEntryLine, offset ); i = newCodes.size() - routCodes.size(); DaoNS_UpdateLineInfo( routine->nameSpace, routine->body->codeStart, i ); return true; }
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 }
static void DaoMT_Functional( DaoProcess *proc, DaoValue *P[], int N, int F ) { DMutex mutex; DCondVar condv; DaoTaskData *tasks; DaoValue *param = P[0]; DaoValue *result = NULL; DaoList *list = NULL; DaoArray *array = NULL; DaoVmCode *sect = DaoGetSectionCode( proc->activeCode ); int i, entry, threads = P[1]->xInteger.value; daoint index = -1, status = 0, joined = 0; DNode *node = NULL; switch( F ){ case DVM_FUNCT_MAP : if( param->type == DAO_ARRAY ){ array = DaoProcess_PutArray( proc ); result = (DaoValue*) array; }else{ list = DaoProcess_PutList( proc ); result = (DaoValue*) list; } break; case DVM_FUNCT_APPLY : DaoProcess_PutValue( proc, param ); break; case DVM_FUNCT_FIND : DaoProcess_PutValue( proc, dao_none_value ); break; } if( threads <= 0 ) threads = 2; if( sect == NULL || DaoMT_PushSectionFrame( proc ) == 0 ) return; if( list ){ DArray_Clear( & list->items ); if( param->type == DAO_LIST ) DArray_Resize( & list->items, param->xList.items.size, NULL ); if( param->type == DAO_MAP ) DArray_Resize( & list->items, param->xMap.items->size, NULL ); #ifdef DAO_WITH_NUMARRAY }else if( array && F == DVM_FUNCT_MAP ){ DaoArray_GetSliceShape( (DaoArray*) param, & array->dims, & array->ndim ); DaoArray_ResizeArray( array, array->dims, array->ndim ); #endif } DMutex_Init( & mutex ); DCondVar_Init( & condv ); entry = proc->topFrame->entry; tasks = (DaoTaskData*) dao_calloc( threads, sizeof(DaoTaskData) ); DaoProcess_PopFrame( proc ); for(i=0; i<threads; i++){ DaoTaskData *task = tasks + i; task->param = param; task->result = result; task->proto = proc; task->sect = sect; task->funct = F; task->entry = entry; task->first = i; task->step = threads; task->index = & index; task->node = & node; task->joined = & joined; task->condv = & condv; task->mutex = & mutex; task->clone = DaoVmSpace_AcquireProcess( proc->vmSpace ); task->clone->mutex = & mutex; if( i ) DaoCallServer_AddTask( DaoMT_RunFunctional, task, 1 ); } DaoMT_RunFunctional( tasks ); DMutex_Lock( & mutex ); while( joined < threads ) DCondVar_TimedWait( & condv, & mutex, 0.01 ); DMutex_Unlock( & mutex ); for(i=0; i<threads; i++){ DaoTaskData *task = tasks + i; DaoVmSpace_ReleaseProcess( proc->vmSpace, task->clone ); status |= task->status; } if( F == DVM_FUNCT_FIND ){ DaoTuple *tuple = DaoProcess_PutTuple( proc, 0 ); if( param->type == DAO_LIST && index != -1 ){ DaoValue **items = param->xList.items.items.pValue; GC_ShiftRC( items[index], tuple->items[1] ); tuple->items[1] = items[index]; tuple->items[0]->xInteger.value = index; }else if( param->type == DAO_MAP && node ){ GC_ShiftRC( node->key.pValue, tuple->items[0] ); GC_ShiftRC( node->value.pValue, tuple->items[1] ); tuple->items[0] = node->key.pValue; tuple->items[1] = node->value.pValue; } } if( status ) DaoProcess_RaiseException( proc, DAO_ERROR, "code section execution failed!" ); DMutex_Destroy( & mutex ); DCondVar_Destroy( & condv ); dao_free( tasks ); }