Mercurial > repos > rhope
view interp.c @ 121:1af91ceaaf49
Fixed memory leak when an output is only attached to a single null input
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Thu, 28 Oct 2010 21:04:12 -0400 |
parents | 6202b866d72c |
children |
line wrap: on
line source
#ifdef WIN32 #include <windows.h> #include <winsock.h> #include <crtdbg.h> #else #ifdef SYLLABLE #include <unistd.h> #include <atheos/threads.h> #else #ifdef NINTENDO_DS #include <nds.h> #else #include <unistd.h> #include <pthread.h> #endif #endif #endif #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include "mt19937ar.h" #include "interp.h" #include "vis_threading.h" #include "datum.h" #include "parser.h" #include "saveload.h" #ifdef TEXT_FILE_DEBUG FILE * debugfile; #endif char debugbuffer[1024]; //extern HWND hWnd; extern char new_name_buf[256]; extern int buf_size; int lock_fail_counter; int lock_counter; VIS_CRITICAL_SECTION(data_lock) VIS_CRITICAL_SECTION(worker_queue_lock) VIS_CRITICAL_SECTION(randlock) VIS_Event(queue_add_event) int program_count=1; VIS_CRITICAL_SECTION(program_count_lock) //#define ENABLE_PROFILING 1 #ifdef ENABLE_PROFILING __int64 vis_profile_start_times[NUM_PROFS]; __int64 vis_profile_running_total[NUM_PROFS]; int vis_profile_counts[NUM_PROFS]; __declspec(naked) unsigned __int64 __cdecl rdtsc(void) { __asm { rdtsc ret ; return value at EDX:EAX } } #define PROF_INIT_CUSTOM 0 #define PROF_WORKER_THREAD 1 #define PROF_PROCESS_WORKER 2 #define PROF_CLEANUP_CUSTOM 3 #define PROF_SUB_CALLBACK 4 #define PROF_CLEANUP_RELEASE_REFS 5 #define PROF_CLEANUP_CHECK 6 #define PROF_CLEANUP_FREELISTS 7 #define PROF_PROCESS_OUTPUTS 8 #define PROF_OPT_PREP_INPUT 9 #define PROF_RUN_OPT 10 #define PROF_ADDQUEUE 11 #define PROF_ADDQUEUE_MALLOC 12 #define PROF_OPT_LOOP 13 #define PROF_EXECUTE_WORKER 14 #define PROF_EXECUTE_OTHER 15 #define PROF_PREP_MAGIC 16 #define PROF_CONVERT_INPUTS 17 #define PROF_EXECUTE_CUSTOM 18 #define PROF_EXECUTE_BUILTIN 19 #define PROF_EMPTYFUNC 20 #define PROF_NOCODE 21 #define PROF_LESSERWHOLE 22 #define PROF_EQUALWHOLE 23 #define PROF_PARTIAL_EXEC 24 #define PROF_ADDWHOLE 25 #define PROF_FULL_EXEC 26 #define PROF_OPT_EXEC_USER 27 #define PROF_OPT_EXEC_BUILT 28 #define PROF_VIRTUAL_DECODE 27 #define PROF_VIRTUAL_EXECUTE 28 /*#define VIS_PROFILE_START(index) vis_profile_start_times[index] = rdtsc() #define VIS_PROFILE_END(index) vis_profile_running_total[index] += (rdtsc()-vis_profile_start_times[index]); ++vis_profile_counts[index] #else #define VIS_PROFILE_START(index) #define VIS_PROFILE_END(index)*/ #endif queue_entry * worker_queue; queue_section first_section; queue_section * current_section; int queue_start; int queue_len; BOOL execute_active=FALSE; char text_buf[256]; int text_buf_size; VIS_CRITICAL_SECTION(text_buf_lock) #ifdef WIN32 WSADATA wsa_data; #ifdef GUI_LIB char errorbuffer[1024]; #endif #endif worker_instance * main_instance; //company companylist[40]; //int num_companies=0; datum * global_store_dict; VIS_CRITICAL_SECTION(global_store_lock); int empty_func(datum ** a, queue_entry * worker_entry) { return 0; } worker_impl empty_test = empty_func; /* void set_in_child(worker_def * parent, int worker_num, BOOL * in_child, BOOL value, int exclude_worker) { int j,i = parent->workerlist[worker_num].wire_down_lookup; if(exclude_worker >= 0 && exclude_worker == worker_num) return; in_child[worker_num] = value; while(parent->wirelist[j=parent->workers_to_wires_down[i]].start_worker == worker_num && j >= 0) set_in_child(parent, parent->wirelist[j].end_worker, in_child, value); } void build_child_worker(worker_def * parent, int worker_num, int output_num) { int i,j, num_child_workers, num_child_wires, child_def; BOOL * in_child = malloc(sizeof(BOOL)* parent->num_workers); int * child_offsets = malloc(sizeof(int) * parent->num_workers); for(i = 0; i < parent->num_workers; ++i) { in_child[i] = FALSE; child_offsets[i] = -1; } i = parent->workerlist[worker_num].wire_down_lookup; while(parent->wirelist[j=parent->workers_to_wires_down[i]].start_worker == worker_num && j >= 0) { if(parent->wirelist[j].output_num == output_num) set_in_child(parent, parent->wirelist[j].end_worker, in_child, TRUE,-1); } i = parent->workerlist[worker_num].wire_down_lookup; while(parent->wirelist[j=parent->workers_to_wires_down[i]].start_worker == worker_num && j >= 0) { if(parent->wirelist[j].output_num != output_num) set_in_child(parent, parent->wirelist[j].end_worker, in_child, FALSE,-1); } for(i = 0; i < parent->num_workers; ++i) { if(i != worker_num && (parent->workerlist[i].type == 4 || (parent->workerlist[i].type == 2 && !in_child[i]))) set_in_child(parent, i, in_child, FALSE); } for(i = 0; i < parent->num_workers; ++i) { if(in_child[i]) child_offests[i] = num_child_workers++; } for(i = 0; i < parent->num_wires; ++i) { if(in_child[parent->wirelist[i].start_worker] || in_child[parent->wirelist[i].end_worker]) ++num_child_wires; } child_def = num_defs++;//needs lock or atomic incrememnt deflist[child_def].workerlist = malloc(sizeof(worker)*num_child_workers); deflist[child_def].wirelist = malloc(sizeof(wire)*num_child_wires); for(i = 0; i < parent->num_workers; ++i) { if(in_child[i]) deflist[child_def].workerlist[child_offests[i]] = parent->workerlist[i]; } } */ #define MAX_TRACE_DEPTH 40 void print_stack_trace(worker_instance * stack_instance) { int i = 0; ERRORPUTS("Stack trace:\n"); while(stack_instance && i < MAX_TRACE_DEPTH) { ERRORPRINTF("%s\n", stack_instance->def->name); stack_instance = stack_instance->caller_instance; ++i; } if(stack_instance) { ERRORPUTS("Stack trace aborted after 40 entries\n"); } } void check_tail(worker_def * def) { custom_worker * worker = def->implement_func; int i,j,k,endworker; BOOL can_tail, outputs_handled[32]; for(i = 0; i < worker->num_workers; ++i) { if(worker->workerlist[i].type == WORKER) { can_tail = TRUE; for(j = 0; j < def->num_outputs; ++j) outputs_handled[j] = FALSE; j = worker->workerlist[i].wire_down_lookup; while((k=worker->workers_to_wires_down[j]) >= 0 && worker->wirelist[k].start_worker == i) { endworker = worker->wirelist[k].end_worker; if(worker->workerlist[endworker].type != OUTPUT || worker->workerlist[endworker].io_num != worker->wirelist[k].output_num) { can_tail = FALSE; break; } else outputs_handled[worker->wirelist[k].output_num] = TRUE; ++j; } if(can_tail) { for(j = 0; j < def->num_outputs; ++j) if(!outputs_handled[j]) { can_tail = FALSE; break; } if(can_tail) if(worker->workerlist[i].value_index == def) worker->workerlist[i].type = TAIL_RECURSE; else if(!def->num_stores) worker->workerlist[i].type = TAIL_CALL; } } } } BOOL method_match(char * name, char * method_name) { int i = 0; while(name[i] != '\0' && method_name[i] != '@' && method_name[i] != '\0') { if(name[i] != method_name[i]) return FALSE; ++i; } if(name[i] != '\0' || method_name[i] != '@') return FALSE; return TRUE; } worker_def * find_method(int type, char * name, int num_inputs, program * prog) { int i; worker_def * output = NULL; company * companylist = prog->companylist; VIS_EnterCriticalSection(companylist[type].lock); for(i = 0; i < companylist[type].num_methods; ++i) { //DEBUGPRINTF( "Checking method %s(%d,%d)\n", companylist[type].methodlist[i]->name, companylist[type].methodlist[i]->num_inputs, companylist[type].methodlist[i]->num_outputs); if(companylist[type].methodlist[i]->num_inputs == num_inputs && method_match(name, companylist[type].methodlist[i]->name)) { DEBUGPRINTF( "Found method: %s\n", companylist[type].methodlist[i]->name); output = companylist[type].methodlist[i]; break; } } VIS_LeaveCriticalSection(companylist[type].lock); return output; } worker_def * find_method_noinputcheck(int type, char * name, program * prog) { int i; worker_def * output = NULL; company * companylist = prog->companylist; VIS_EnterCriticalSection(companylist[type].lock); for(i = 0; i < companylist[type].num_methods; ++i) { //DEBUGPRINTF( "Checking method %s(%d,%d)\n", companylist[type].methodlist[i]->name, companylist[type].methodlist[i]->num_inputs, companylist[type].methodlist[i]->num_outputs); if(method_match(name, companylist[type].methodlist[i]->name)) { DEBUGPRINTF( "Found method: %s\n", companylist[type].methodlist[i]->name); output = companylist[type].methodlist[i]; break; } } VIS_LeaveCriticalSection(companylist[type].lock); return output; } worker_def * find_converter_method(int totype, int fromtype, program * prog) { int i; company * companylist = prog->companylist; DEBUGPRINTF( "Finding converter from %s to %s\n", companylist[fromtype].name, companylist[totype].name); //DEBUGPRINTF( "Num methods %d\n", companylist[totype].num_methods); for(i = 0; i < companylist[totype].num_methods; ++i) { //DEBUGPRINTF("methodlist[i]: %X\n", companylist[totype].methodlist[i]); DEBUGPRINTF( "Checking method %s\n", companylist[totype].methodlist[i]->name); if(companylist[totype].methodlist[i]->name[0] == '<' && method_match(companylist[fromtype].name, companylist[totype].methodlist[i]->name+1)) { DEBUGPRINTF( "Found Method %s\n", companylist[totype].methodlist[i]->name); return companylist[totype].methodlist[i]; } } return NULL; } worker_instance * init_custom_worker_type(int aworker, worker_instance * caller, worker_def * def, instance_callback callback, void * callback_data, datum ** params, int type) { int i, workerlist_size, j, add_index_count=0; int add_index[32]; datum * work_params[32]; datum * temp_params[3]; global_store * store; worker_instance * instance; BOOL release_params = TRUE; def_make_lookup(def); workerlist_size = sizeof(worker_instance_data)*(def->implement_func->num_workers); //DEBUGPRINTF("workerlist_size: %d * %d = %d, wirelist_size: %d * %d = %d.\n", sizeof(worker_instance_data), def->implement_func->num_workers, workerlist_size, sizeof(wire_instance_data), def->implement_func->num_wires, sizeof(wire_instance_data)*(def->implement_func->num_wires)); //DEBUGPRINTF("Before malloc(%d)\n",sizeof(worker_instance) + workerlist_size + sizeof(wire_instance_data)*(def->implement_func->num_wires)); if(type == TAIL_RECURSE || type == TAIL_CALL) { VIS_EnterCriticalSection(caller->counter_lock); if(caller->in_progress_count <= 1 && !caller->in_queue_count) { VIS_LeaveCriticalSection(caller->counter_lock); instance = caller; for(i = 0; i < instance->num_workers; ++i) { if(instance->def->implement_func->workerlist[i].type != WORKER && instance->def->implement_func->workerlist[i].type != TAIL_RECURSE && instance->def->implement_func->workerlist[i].type != TAIL_CALL && instance->workerlist[i].value) release_ref(instance->workerlist[i].value); if(instance->workerlist[i].ready_count && instance->workerlist[i].ready_count < (instance->def->implement_func->workerlist[i].num_inputs + (instance->def->implement_func->workerlist[i].null_input ? 1 : 0))) { DEBUGPRINTF("Freeing params for worker number %d, ready_count: %d, num_inputs: %d, null_input: %d, instance: %X\n", i, instance->workerlist[i].ready_count,instance->def->implement_func->workerlist[i].num_inputs, instance->def->implement_func->workerlist[i].null_input, instance); for(j = 0; j <= instance->def->implement_func->workerlist[i].num_inputs; ++j) { DEBUGPRINTF("Releasing param %d of worker %d\n", j, i); release_ref(instance->workerlist[i].params[j]); } } } for(i = 0; i < def->num_inputs; ++i) work_params[i] = params[i]; params = work_params; if(type == TAIL_RECURSE) { instance->in_progress_count = 0; //TODO: adjust profile counter? goto init_workerlist; } else { aworker = instance->worker_in_caller; callback = instance->callback; callback_data = instance->callback_data; caller = instance->caller_instance; VIS_DeleteCriticalSection(instance->counter_lock); free(instance); } } else { VIS_LeaveCriticalSection(caller->counter_lock); } } instance = MALLOC(sizeof(worker_instance) + workerlist_size/* + sizeof(wire_instance_data)*(def->implement_func->num_wires) */,"instance"); //DEBUGPRINTF("malloc returned %X.\n", instance); VIS_PROFILE_START(PROF_INIT_CUSTOM); //DEBUGPRINTF("init_custom_worker, instance: %X\n", instance); #ifdef USER_PROFILE QueryPerformanceCounter(&(instance->start)); #endif instance->def = def; instance->num_workers = def->implement_func->num_workers; instance->workerlist = (worker_instance_data *)(((char *)instance) + sizeof(worker_instance));//malloc(sizeof(worker_instance_data)*(def->implement_func->num_workers)); //DEBUGPRINTF("workerlist at %X\n", instance->workerlist); /*instance->num_wires = def->implement_func->num_wires; instance->wirelist = (wire_instance_data *)(((char *)(instance->workerlist)) + workerlist_size);//malloc(sizeof(wire_instance_data)*(def->implement_func->num_wires)); DEBUGPRINTF("wirelist at %X\n", instance->wirelist);*/ instance->callback = callback; instance->worker_in_caller = aworker; instance->callback_data = callback_data; instance->caller_instance = caller; VIS_InitializeCriticalSection(instance->counter_lock); instance->in_progress_count = 0; instance->in_queue_count = 0; if(def->num_stores) { instance->trans = MALLOC(sizeof(transaction) + sizeof(global_store_use) *(def->num_stores - 1),"transaction"); VIS_EnterCriticalSection(global_store_lock); for(i = 0; i < def->num_stores; ++i) { temp_params[0] = add_ref(global_store_dict); temp_params[1] = make_string(def->uses_stores[i], -1, def->program); vis_dict_index(temp_params, NULL); if(!temp_params[0]) { printf("Error: Global store %s is not initialized\n", def->uses_stores[i]); DEBUGPRINTF("Error: Global store %s is not initialized\n", def->uses_stores[i]); VIS_LeaveCriticalSection(global_store_lock); return NULL; } instance->trans->stores[i].store = temp_params[0]->c.generic.data; instance->trans->stores[i].instance_data = instance->trans->stores[i].begin_data = add_ref(instance->trans->stores[i].store->data); VIS_InitializeCriticalSection(instance->trans->stores[i].lock); //Is this really necessary? release_ref(temp_params[0]); } VIS_LeaveCriticalSection(global_store_lock); instance->trans->num_stores = def->num_stores; if((def->transaction_flags & TRANSACTION_WRITE) && (def->transaction_flags & TRANSACTION_TYPE_MASK) == TRANSACTION_RETRY) { release_params = FALSE; for(i = 0; i < def->num_inputs; ++i) instance->trans->params[i] = params[i]; } } else { instance->trans = NULL; } init_workerlist: //DEBUGPUTS("init worker values\n"); for(i = 0; i < instance->num_workers; ++i) { // DEBUGPRINTF("InitializeCriticalSection on workerlist[%d].worker_lock (%X)\n", i, &(instance->workerlist[i].worker_lock)); VIS_InitializeCriticalSection(instance->workerlist[i].worker_lock); //DEBUGPUTS("ready_count = 0\n"); instance->workerlist[i].ready_count = 0; if(def->implement_func->workerlist[i].type == INPUT && params) instance->workerlist[i].value = add_ref(params[def->implement_func->workerlist[i].io_num]); else //if(def->implement_func->workerlist[i].type != 2) instance->workerlist[i].value = NULL; //DEBUGPRINTF("instance->workerlist[%d].value = %X\n", i, instance->workerlist[i].value); for(j = 0; j <= def->implement_func->workerlist[i].num_inputs; ++j) instance->workerlist[i].params[j] = NULL; //DEBUGPRINTF("num_inputs: %d, null_input: %d\n", def->implement_func->workerlist[i].num_inputs, def->implement_func->workerlist[i].null_input); //There's still a potential race condition here, but it's unlikely to occur except on a system with an insane number of cores/processors //and only on custom workers that have more than 32 items that will be initially ready if(!def->implement_func->workerlist[i].num_inputs && !def->implement_func->workerlist[i].null_input) { DEBUGPRINTF("adding worker %s(%d) to queue\n", def->implement_func->workerlist[i].name, i); add_index[add_index_count++] = i; if(add_index_count == 32) { add_multiple(add_index, add_index_count, instance); add_index_count = 0; } //add_queue(i,instance); } } if(params) { if(release_params) { //DEBUGPUTS("release params\n"); for(i = 0; i < def->num_inputs; ++i) release_ref(params[i]); } } if(add_index_count > 0) add_multiple(add_index, add_index_count, instance); VIS_PROFILE_END(PROF_INIT_CUSTOM); return instance; } worker_instance * init_custom_worker(int aworker, worker_instance * caller, worker_def * def, instance_callback callback, void * callback_data, datum ** params) { return init_custom_worker_type(aworker, caller, def, callback, callback_data, params, WORKER); } void cleanup_check(queue_entry aworker) { char msg[256]; VIS_EnterCriticalSection(aworker.instance->counter_lock); --(aworker.instance->in_progress_count); DEBUGPRINTF( "Cleanup Check on %s<%d>:%X, in_progress: %d, in_queue: %d\n", aworker.instance->def->name, aworker.instance->worker_in_caller, aworker.instance, aworker.instance->in_progress_count,aworker.instance->in_queue_count); if(aworker.instance->in_progress_count == 0 && aworker.instance->in_queue_count == 0) { VIS_LeaveCriticalSection(aworker.instance->counter_lock); cleanup_custom_worker(aworker.instance, aworker.worker_num); } else { VIS_LeaveCriticalSection(aworker.instance->counter_lock); } } void cleanup_custom_worker(worker_instance * instance, int worker_num) { BOOL do_commit = TRUE; int i,j; queue_entry incaller; global_store * store; #ifdef USER_PROFILE LARGE_INTEGER end; LARGE_INTEGER duration; #endif if(instance->trans) { if(instance->def->transaction_flags & TRANSACTION_WRITE) { VIS_EnterCriticalSection(global_store_lock); if((instance->def->transaction_flags & TRANSACTION_TYPE_MASK) != TRANSACTION_FORCE) { for(i = 0; i < instance->trans->num_stores; ++i) { if(instance->trans->stores[i].begin_data != instance->trans->stores[i].store->data) { do_commit = FALSE; break; } } } if(do_commit) { for(i = 0; i < instance->trans->num_stores; ++i) { release_ref(instance->trans->stores[i].store->data); instance->trans->stores[i].store->data = instance->trans->stores[i].instance_data; } } VIS_LeaveCriticalSection(global_store_lock); if(!do_commit)//retry transaction { for(i = 0; i < instance->trans->num_stores; ++i) release_ref(instance->trans->stores[i].instance_data); puts("retrying transaction"); init_custom_worker(instance->worker_in_caller, instance->caller_instance, instance->def, instance->callback, instance->callback_data, instance->trans->params); } else if((instance->def->transaction_flags & TRANSACTION_TYPE_MASK) == TRANSACTION_RETRY) for(i = 0; i < instance->def->num_inputs; ++i) release_ref(instance->trans->params[i]); } else { for(i = 0; i < instance->trans->num_stores; ++i) release_ref(instance->trans->stores[i].instance_data); } VIS_FREE(instance->trans, "transaction"); } VIS_PROFILE_START(PROF_CLEANUP_CUSTOM); DEBUGPRINTF("Cleaning up custom worker: %s:%X\n", instance->def->name, instance); VIS_PROFILE_START(PROF_SUB_CALLBACK); if(instance->callback && do_commit) instance->callback(instance->caller_instance, instance->worker_in_caller, instance, instance->callback_data); //DEBUGPUTS("About to release refs\n"); VIS_PROFILE_END(PROF_SUB_CALLBACK); VIS_PROFILE_START(PROF_CLEANUP_RELEASE_REFS); /*for(i = 0; i < instance->def->implement_func->num_wires; ++i) { if(instance->wirelist[i].data) { DEBUGPRINTF("release_ref on wire %d\n", i); release_ref(instance->wirelist[i].data); } }*/ for(i = 0; i < instance->num_workers; ++i) { if(instance->def->implement_func->workerlist[i].type != WORKER && instance->def->implement_func->workerlist[i].type != TAIL_RECURSE && instance->def->implement_func->workerlist[i].type != TAIL_CALL && instance->workerlist[i].value) { DEBUGPRINTF( "release_ref on worker %d in instance %X\n", i, instance); release_ref(instance->workerlist[i].value); } if(instance->workerlist[i].ready_count && instance->workerlist[i].ready_count < (instance->def->implement_func->workerlist[i].num_inputs + (instance->def->implement_func->workerlist[i].null_input ? 1 : 0))) { DEBUGPRINTF("Freeing params for worker number %d, ready_count: %d, num_inputs: %d, null_input: %d, instance: %X\n", i, instance->workerlist[i].ready_count,instance->def->implement_func->workerlist[i].num_inputs, instance->def->implement_func->workerlist[i].null_input, instance); for(j = 0; j <= instance->def->implement_func->workerlist[i].num_inputs; ++j) { DEBUGPRINTF("Releasing param %d of worker %d\n", j, i); release_ref(instance->workerlist[i].params[j]); } } VIS_DeleteCriticalSection(instance->workerlist[i].worker_lock); } VIS_PROFILE_END(PROF_CLEANUP_RELEASE_REFS); VIS_DeleteCriticalSection(instance->counter_lock); //DEBUGPUTS("freeing lists\n"); #ifdef USER_PROFILE if(do_commit) { QueryPerformanceCounter(&end); duration.QuadPart = end.QuadPart - instance->start.QuadPart; VIS_EnterCriticalSection(instance->def->lock); instance->def->total.QuadPart += duration.QuadPart; ++instance->def->count; if(duration.QuadPart > instance->def->worst.QuadPart) instance->def->worst.QuadPart = duration.QuadPart; VIS_LeaveCriticalSection(instance->def->lock); } #endif /*VIS_PROFILE_START(PROF_CLEANUP_FREELISTS); free(instance->workerlist); free(instance->wirelist); VIS_PROFILE_END(PROF_CLEANUP_FREELISTS);*/ VIS_PROFILE_START(PROF_CLEANUP_CHECK); if(instance->caller_instance && do_commit) { incaller.worker_num = instance->worker_in_caller; incaller.instance = instance->caller_instance; DEBUGPUTS("Calling cleanup_check on parent\n"); cleanup_check(incaller); } if(do_commit && instance->callback == main_callback) release_program_ref(instance->def->program); VIS_PROFILE_END(PROF_CLEANUP_CHECK); VIS_PROFILE_START(PROF_CLEANUP_FREELISTS); VIS_FREE(instance, "worker instance"); VIS_PROFILE_END(PROF_CLEANUP_FREELISTS); VIS_PROFILE_END(PROF_CLEANUP_CUSTOM); } /* void worker_complete(queue_entry aworker) { int i,j; wire * wirelist; int * workers_to_wires_down; VIS_PROFILE_START(PROF_WORKER_COMPLETE); DEBUGPUTS("worker_complete()\n"); i = aworker.instance->def->implement_func->workerlist[aworker.worker_num].wire_down_lookup; wirelist = aworker.instance->def->implement_func->wirelist; workers_to_wires_down = aworker.instance->def->implement_func->workers_to_wires_down; while(wirelist[j=workers_to_wires_down[i]].start_worker == aworker.worker_num && j >= 0) { if(aworker.instance->wirelist[j].data) { DEBUGPRINTF("end_worker: %d, wirelist[%d].data = %X\n", wirelist[j].end_worker, j, aworker.instance->wirelist[j].data); add_if_ready(wirelist[j].end_worker, aworker.instance); } ++i; } DEBUGPUTS("worker_complete done\n"); VIS_PROFILE_END(PROF_WORKER_COMPLETE); }*/ void process_outputs(datum ** params, int aworker, worker_instance * instance) { BOOL flag=FALSE; int i,j; worker_def * def = instance->def; //custom_worker *implement_func = def->implement_func; wire * def_wires = def->implement_func->wirelist; worker * def_workers = def->implement_func->workerlist; VIS_PROFILE_START(PROF_PROCESS_OUTPUTS); DEBUGPRINTF("Process outputs for worker %d in instance %X\n", aworker, instance); DEBUGPRINTF("Num_inputs: %d, num_outputs: %d\n", def_workers[aworker].num_inputs, def_workers[aworker].num_outputs); if(def_workers[aworker].num_outputs && instance->workerlist) { //DEBUGPRINTF("num_outputs: %d\n", def_workers[aworker].num_outputs); i = def_workers[aworker].wire_down_lookup; while((j=def->implement_func->workers_to_wires_down[i]) >= 0 && def_wires[j].start_worker == aworker) { //DEBUGPRINTF("Checking output: %d\n", def_wires[j].output_num); DEBUGPRINTF("output[%d] = %X\n", def_wires[j].output_num, params[def_wires[j].output_num]); DEBUGPRINTF("wire leads to worker %d, instance->workerlist: %X\n", def_wires[j].end_worker, instance->workerlist); VIS_EnterCriticalSection(instance->workerlist[def_wires[j].end_worker].worker_lock); if(params[def_wires[j].output_num] && !instance->workerlist[def_wires[j].end_worker].params[def_wires[j].input_num+1]) { //DEBUGPRINTF( "add_ref on output %d\n", def_wires[j].output_num); instance->workerlist[def_wires[j].end_worker].params[def_wires[j].input_num+1]=add_ref(params[def_wires[j].output_num]); //DEBUGPRINTF("Ready count was: %d, ", instance->workerlist[def_wires[j].end_worker].ready_count); ++instance->workerlist[def_wires[j].end_worker].ready_count; DEBUGPRINTF("Ready count is now: %d\n", instance->workerlist[def_wires[j].end_worker].ready_count); DEBUGPRINTF("num inputs: %d, null input: %d\n", instance->def->implement_func->workerlist[def_wires[j].end_worker].num_inputs, instance->def->implement_func->workerlist[def_wires[j].end_worker].null_input); if(instance->workerlist[def_wires[j].end_worker].ready_count >= (instance->def->implement_func->workerlist[def_wires[j].end_worker].num_inputs + (instance->def->implement_func->workerlist[def_wires[j].end_worker].null_input ? 1 : 0))) { //DEBUGPUTS("flag = true\n"); flag = TRUE; instance->workerlist[def_wires[j].end_worker].ready_count=0; } } VIS_LeaveCriticalSection(instance->workerlist[def_wires[j].end_worker].worker_lock); if(flag) { DEBUGPUTS("add_queue\n"); add_queue(def_wires[j].end_worker, instance); //add_if_ready(def_wires[j].end_worker, instance); flag = FALSE; } ++i; } //DEBUGPUTS("releasing refs\n"); for(i = 0; i < def_workers[aworker].num_outputs; ++i) release_ref(params[i]); } VIS_PROFILE_END(PROF_PROCESS_OUTPUTS); } void main_callback(worker_instance * junkinst, int junk, worker_instance * main_instance, void * data) { //MessageBox(NULL, "Main Callback", "Visuality Debug", MB_OK); VIS_EnterCriticalSection(program_count_lock); --program_count; if(program_count <= 0) { execute_active = FALSE; VIS_SetEvent(queue_add_event); } VIS_LeaveCriticalSection(program_count_lock); if(data) release_ref((datum *)data); } void sub_callback(worker_instance * caller_instance, int caller_workernum, worker_instance * done_instance, void * data) { int i; queue_entry incaller; datum * params[32]; worker_def * def = done_instance->def; custom_worker * implement_func = def->implement_func; incaller.worker_num = caller_workernum; incaller.instance = caller_instance; for(i = 0; i < def->num_outputs; ++i) params[i] = NULL; for(i = 0; i < implement_func->num_workers; ++i) { if(implement_func->workerlist[i].type == 4) { if(!params[implement_func->workerlist[i].io_num]) { params[implement_func->workerlist[i].io_num] = done_instance->workerlist[i].value; DEBUGPRINTF("Output[%d] = %X\n", implement_func->workerlist[i].io_num, done_instance->workerlist[i].value); done_instance->workerlist[i].value = NULL; } } } process_outputs(params, caller_workernum, caller_instance); //worker_complete(incaller); } void pack_list_sub_callback(worker_instance * caller_instance, int caller_workernum, worker_instance * done_instance, void * data) { int i; queue_entry incaller; datum * params[32]; datum * workparams[2]; incaller.worker_num = caller_workernum; incaller.instance = caller_instance; for(i = 0; i < done_instance->def->num_outputs; ++i) params[i] = NULL; for(i = 0; i < done_instance->def->implement_func->num_workers; ++i) { if(done_instance->def->implement_func->workerlist[i].type == 4) { if(!params[done_instance->def->implement_func->workerlist[i].io_num]) { params[done_instance->def->implement_func->workerlist[i].io_num] = done_instance->workerlist[i].value; done_instance->workerlist[i].value = NULL; } } } workparams[0] = create_list(done_instance->def->program); for(i = 0; i < done_instance->def->num_outputs; ++i) { workparams[1] = params[i]; vis_list_append(workparams, NULL); } process_outputs(workparams, caller_workernum, caller_instance); //worker_complete(incaller); } void transaction_sub_callback(worker_instance * caller_instance, int caller_workernum, worker_instance * done_instance, void * data) { int i; pack_list_sub_callback(caller_instance, caller_workernum, done_instance, NULL); } int global_argc; char ** global_argv; int spin_counter; void prep_program(program * prog) { defchunk * current; int i,j; make_lookup_arrays(prog); current = prog->defs; while(current) { for(i = 0; i < current->num_defs; ++i) { #ifdef USER_PROFILE current->deflist[i].count = 0; current->deflist[i].total.QuadPart = 0; current->deflist[i].worst.QuadPart = 0; VIS_InitializeCriticalSection(current->deflist[i].lock); #endif // USER_PROFILE //DEBUGPRINTF("Checking worker %s with type %X\n", current->deflist[i].name, current->deflist[i].type); if(current->deflist[i].type & USER_FLAG && (current->deflist[i].type & TYPE_MASK) == WORKER_TYPE) { //DEBUGPRINTF("Checking for constants in worker %s\n", current->deflist[i].name); for(j = 0; j < current->deflist[i].implement_func->num_workers; ++j) if(current->deflist[i].implement_func->workerlist[j].type == CONSTANT) { //current->deflist[i].implement_func->workerlist[j].value_index = (int)(get_constant(current->deflist[i].implement_func->workerlist[j].name,-1, initial_prog)); //DEBUGPRINTF("Set value_index for constant to %X in worker %s at index %d\n", current->deflist[i].implement_func->workerlist[j].value_index, current->deflist[i].name, j); } else if(current->deflist[i].implement_func->workerlist[j].type == WORKER || current->deflist[i].implement_func->workerlist[j].type == TAIL_CALL || current->deflist[i].implement_func->workerlist[j].type == TAIL_RECURSE) { current->deflist[i].implement_func->workerlist[j].num_inputs = ((worker_def *)current->deflist[i].implement_func->workerlist[j].value_index)->num_inputs; current->deflist[i].implement_func->workerlist[j].num_outputs = ((worker_def *)current->deflist[i].implement_func->workerlist[j].value_index)->num_outputs; } else current->deflist[i].implement_func->workerlist[j].value_index = 0; //DEBUGPRINTF("optimize %d\n", i); #ifdef ENABLE_OPT optimize(current->deflist + i); #endif } } current = current->next; } } void interp_start(int num_threads, BOOL use_this_thread, int argc, char ** argv, program * initial_prog) { defchunk * current; datum * params[2]; int i, junk,create_threads,j; #ifdef USER_PROFILE LARGE_INTEGER frequency; #endif lock_fail_counter = 0; lock_counter = 0; spin_counter = 0; #ifdef WIN32 //_CrtSetDbgFlag(_CRTDBG_CHECK_ALWAYS_DF | _CRTDBG_CHECK_CRT_DF | _CRTDBG_ALLOC_MEM_DF); WSAStartup(MAKEWORD(1, 1), &wsa_data); #endif VIS_InitializeCriticalSection(randlock); DEBUGPUTS("interp_start\n"); #ifdef ENABLE_PROFILING for(i = 0; i < NUM_PROFS; ++i) { vis_profile_running_total[i] = 0; vis_profile_counts[i] = 0; } VIS_PROFILE_START(PROF_EMPTYFUNC); empty_test(NULL,NULL); VIS_PROFILE_END(PROF_EMPTYFUNC); VIS_PROFILE_START(PROF_NOCODE); VIS_PROFILE_END(PROF_NOCODE); #endif global_argc = argc; global_argv = argv; init_sync_primitives(); init_datum_storage(); init_global_storage(initial_prog); //init queue current_section = &first_section; DEBUGPRINTF("current_section = %X, ¤t_section = %X\n", current_section, ¤t_section); worker_queue = current_section->entries; current_section->last = NULL; current_section->next = NULL; queue_start = queue_len = 0; // deflist[0].num_workers = num_workers; // deflist[0].num_wires = num_wires; prep_program(initial_prog); //MessageBox(NULL, "Before fopen", "visdbg", MB_OK); init_genrand(time(NULL)); execute_active = TRUE; DEBUGPUTS("Before init_custom_worker on Main\n"); params[0] = create_list(initial_prog); for(i = 0; i < argc; ++i) { params[1] = make_string(argv[i], -1, initial_prog); vis_list_append(params, NULL); } main_instance = init_custom_worker(-1, NULL, initial_prog->defs->deflist, main_callback, NULL, params); //num_datum = 0; #if COMPILE_THREADS > 0 create_threads = COMPILE_THREADS; if(num_threads > 0) create_threads = num_threads; if(use_this_thread) --create_threads; for(i = 0; i < create_threads; ++i) { #ifdef WIN32 CreateThread(NULL, 0, worker_thread, NULL, 0, &junk); #else #ifdef SYLLABLE resume_thread(spawn_thread("vis_worker", worker_thread, 1, 0, NULL)); #else pthread_t pid; pthread_create(&pid, NULL, worker_thread, NULL); #endif #endif } if(use_this_thread) worker_thread(NULL); #else worker_thread(NULL); #endif #ifdef ENABLE_PROFILING for(i = 0; i < NUM_PROFS; ++i) printf("%d:\t%f,\tcount: %d,\taverage: %f\n", i, (double)vis_profile_running_total[i], vis_profile_counts[i], ((double)vis_profile_running_total[i])/((double)vis_profile_counts[i])); #endif #ifdef USER_PROFILE printf("%-33s%12s%7s%15s%12s\n\n", "Worker", "Total", "Count", "Average", "Worst"); current = initial_prog->defs; while(current) { for(i = 0; i < current->num_defs; ++i) { if(current->deflist[i].count > 0) { printf("%-33s%12.0f%7d%15.2f%12.0f\n", current->deflist[i].name, (double)current->deflist[i].total.QuadPart, current->deflist[i].count, (double)current->deflist[i].total.QuadPart / (double)current->deflist[i].count, (double)current->deflist[i].worst.QuadPart); } } current = current->next; } QueryPerformanceFrequency(&frequency); printf("%.0f ticks per second\n", (double)frequency.QuadPart); #endif interp_stop(); } void interp_stop() { int i; execute_active = FALSE; close_sync_primitives(); // Doesn't make sense in the context of multiple programs // cleanup_custom_worker(main_instance); #ifdef WIN32 WSACleanup(); #endif #ifdef TEXT_FILE_DEBUG fclose(debugfile); #endif } extern void init_sync_primitives() { int i; DEBUGPUTS("Initializing data_lock\n"); VIS_InitializeCriticalSection(data_lock); DEBUGPUTS("Initializing worker_queue_lock\n"); VIS_InitializeCriticalSection(worker_queue_lock); DEBUGPUTS("Initializing text_buf_lock\n"); VIS_InitializeCriticalSection(text_buf_lock); #ifdef GUI_LIB #ifdef SYLLABLE DEBUGPUTS("vis_window_init\n"); vis_window_init(); #endif #endif //GUI_LIB VIS_CreateEvent(queue_add_event);//No security parameter, auto reset, starts signaled, no name } void close_sync_primitives() { int i; VIS_DeleteCriticalSection(data_lock); VIS_DeleteCriticalSection(worker_queue_lock); VIS_DestroyEvent(queue_add_event); } void init_global_storage(program * prog) { VIS_InitializeCriticalSection(global_store_lock); global_store_dict = create_dict(prog); } void add_multiple(int * data, int num, worker_instance * instance) { int i, index; queue_section * temp; DEBUGPRINTF( "Adding %d workers\n", num); VIS_EnterCriticalSection(instance->counter_lock); instance->in_queue_count += num; VIS_LeaveCriticalSection(instance->counter_lock); VIS_EnterCriticalSection(worker_queue_lock); for(i = 0; i < num; ++i) { if(queue_len >= QUEUE_SIZE) { if(current_section->next) { //DEBUGPUTS("Moving to next queue_section\n"); current_section = current_section->next; } else { //DEBUGPUTS("Allocating new queue_section\n"); VIS_PROFILE_START(PROF_ADDQUEUE_MALLOC); temp = MALLOC(sizeof(queue_section),"queue section"); VIS_PROFILE_END(PROF_ADDQUEUE_MALLOC); temp->last = current_section; temp->next = NULL; current_section->next = temp; current_section = temp; } worker_queue = current_section->entries; queue_start = queue_len = 0; } if(queue_start+queue_len < QUEUE_SIZE) index = queue_start+queue_len; else index = queue_start+queue_len-QUEUE_SIZE; worker_queue[index].worker_num=data[i]; worker_queue[index].instance = instance; ++queue_len; } VIS_LeaveCriticalSection(worker_queue_lock); //DEBUGPUTS("SetEvent\n"); VIS_SetEvent(queue_add_event); } void requeue(int data, worker_instance * instance) { add_queue(data, instance); VIS_EnterCriticalSection(instance->counter_lock); --(instance->in_progress_count); VIS_LeaveCriticalSection(instance->counter_lock); } void add_queue(int data, worker_instance * instance) { int index; queue_section * temp; VIS_PROFILE_START(PROF_ADDQUEUE); VIS_EnterCriticalSection(instance->counter_lock); ++(instance->in_queue_count); VIS_LeaveCriticalSection(instance->counter_lock); VIS_EnterCriticalSection(worker_queue_lock); if(queue_len >= QUEUE_SIZE) { if(current_section->next) { //DEBUGPUTS("Moving to next queue_section\n"); current_section = current_section->next; } else { //DEBUGPUTS("Allocating new queue_section\n"); VIS_PROFILE_START(PROF_ADDQUEUE_MALLOC); temp = MALLOC(sizeof(queue_section),"queue section"); VIS_PROFILE_END(PROF_ADDQUEUE_MALLOC); temp->last = current_section; temp->next = NULL; current_section->next = temp; current_section = temp; } worker_queue = current_section->entries; queue_start = queue_len = 0; } else if(queue_len == 0) { VIS_SetEvent(queue_add_event); //DEBUGPUTS("SetEvent\n"); } if(queue_start+queue_len < QUEUE_SIZE) index = queue_start+queue_len; else index = queue_start+queue_len-QUEUE_SIZE; worker_queue[index].worker_num=data; worker_queue[index].instance = instance; ++queue_len; VIS_LeaveCriticalSection(worker_queue_lock); VIS_PROFILE_END(PROF_ADDQUEUE); } /** * Retrieves a ready worker from the queue */ queue_entry get_queue() { queue_entry data; queue_section * temp; //DEBUGPUTS("Begin get_queue()\n"); VIS_EnterCriticalSection(worker_queue_lock); while(!queue_len && execute_active) { //DEBUGPUTS("Queue empty, resetting event\n"); VIS_ResetEvent(queue_add_event); VIS_LeaveCriticalSection(worker_queue_lock); //DEBUGPUTS("Waiting for queue_add_event\n"); VIS_WaitEvent(queue_add_event); #ifdef NINTENDO_DS //TODO make the processor sleep while waiting for IRQs if(irq_queue_count > 0) run_queued_irqs(); #endif VIS_EnterCriticalSection(worker_queue_lock); } if(queue_len > 0) { data = worker_queue[queue_start]; //DEBUGPRINTF( "Next worker in queue: %d\n", data.worker_num); //DEBUGPRINTF("data.instance: %X, data.instance->workerlist: %X\n", data.instance, data.instance->workerlist); /*VIS_EnterCriticalSection(data.instance->workerlist[data.worker_num].worker_lock); DEBUGPUTS("Adjusting ready_count"); data.instance->workerlist[data.worker_num].ready_count=0; VIS_LeaveCriticalSection(data.instance->workerlist[data.worker_num].worker_lock);*/ ++queue_start; --queue_len; //DEBUGPUTS("Adjusted ready count.\n"); //DEBUGPRINTF("current_section: %X\n", current_section); if(queue_len == 0 && current_section->last) { if(current_section->next != NULL) { //DEBUGPUTS("Freeing current_section->next.\n"); VIS_FREE(current_section->next, "ready queue node"); current_section->next = NULL; } current_section = current_section->last; worker_queue = current_section->entries; queue_start = 0; queue_len = QUEUE_SIZE; } else if(queue_start == QUEUE_SIZE) queue_start = 0; } else { //DEBUGPUTS("Queue empty\n"); data.worker_num = -2; } VIS_LeaveCriticalSection(worker_queue_lock); //DEBUGPUTS("Left worker_queue_lock\n"); //MessageBox(NULL,"AfterLeave","visdbg",MB_OK); if(data.worker_num >= 0) { VIS_EnterCriticalSection(data.instance->counter_lock); //DEBUGPUTS("Adjusting in_queue/in_progress counts.\n"); --(data.instance->in_queue_count); ++(data.instance->in_progress_count); DEBUGPRINTF( "Counts for %s<%d> Instance:%X after get_queue: in_queue: %d in_progress: %d\n",data.instance->def->name, data.instance->worker_in_caller, data.instance, data.instance->in_queue_count, data.instance->in_progress_count); VIS_LeaveCriticalSection(data.instance->counter_lock); } //DEBUGPUTS("End get_queue()\n"); return data; } void def_make_lookup(worker_def * def) { int i, j, upoffset, offset; VIS_EnterCriticalSection(def->implement_func->lock); if(def->implement_func->dirty) { upoffset = offset = 0; for(i = 0; i < def->implement_func->num_workers; ++i) { def->implement_func->workerlist[i].wire_down_lookup=offset; def->implement_func->workerlist[i].wire_up_lookup=upoffset; for(j = 0; j < def->implement_func->num_wires; ++j) { if(def->implement_func->wirelist[j].start_worker == i) def->implement_func->workers_to_wires_down[offset++]=j; if(def->implement_func->wirelist[j].end_worker == i) def->implement_func->workers_to_wires_up[upoffset++]=j; } //Clear tail call info if(def->implement_func->workerlist[i].type == TAIL_CALL || def->implement_func->workerlist[i].type == TAIL_RECURSE) def->implement_func->workerlist[i].type = WORKER; } def->implement_func->workers_to_wires_down[offset]=-1; def->implement_func->workers_to_wires_up[upoffset]=-1; check_tail(def); def->implement_func->dirty = FALSE; } VIS_LeaveCriticalSection(def->implement_func->lock); } /** * Generates lookup array to ease navigation between workers */ void make_lookup_arrays(program * prog) { int i,j,k, offset, upoffset; worker_def * deflist; defchunk * current = prog->defs; while(current) { deflist = current->deflist; for(k = 0; k < current->num_defs; ++k) { if(deflist[k].type & USER_FLAG && (deflist[k].type & TYPE_MASK) == WORKER_TYPE) def_make_lookup(deflist + k); } current = current->next; } } extern char _end_bss[]; void initpredefworkers(program * prog) { int current_def = 1; int current_company = 0; int current_method; int comp_room; company * this_comp; worker_def * aworker; create_company(prog, "Any Type", 0, 0, FALSE); create_company(prog, "Yes No", 0, 0, FALSE); aworker = create_worker(prog, "Print", 1, 1, WORKER_TYPE); aworker->implement_func = (custom_worker *)vis_print; aworker->input_types[0] = BUILTIN_TYPE_STRING; aworker = create_worker(prog, "Random", 0, 1, WORKER_TYPE); aworker->implement_func = (custom_worker *)vis_random; aworker = create_worker(prog, "Build", 1, 1, WORKER_TYPE); aworker->implement_func = (custom_worker *)vis_build; aworker->input_types[0] = BUILTIN_TYPE_STRING; aworker = create_worker(prog, "End", 1, 0, WORKER_TYPE); aworker->implement_func = (custom_worker *)vis_end; aworker->input_types[0] = ANY_TYPE; create_worker(prog, "Append", 2, 1, MAGIC_TYPE); create_worker(prog, "+", 2, 1, MAGIC_TYPE); create_worker(prog, "-", 2, 1, MAGIC_TYPE); create_worker(prog, "*", 2, 1, MAGIC_TYPE); create_worker(prog, "/", 2, 1, MAGIC_TYPE); create_worker(prog, ">", 2, 1, MAGIC_TYPE); create_worker(prog, "<", 2, 1, MAGIC_TYPE); create_worker(prog, "=", 2, 1, MAGIC_TYPE); aworker = create_worker(prog, "Get Input", 0, 1, WORKER_TYPE); aworker->implement_func = (custom_worker *)vis_getinput; aworker = create_worker(prog, "If",1, 2, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_if; aworker->input_types[0] = BUILTIN_TYPE_YESNO; aworker = create_worker(prog, "Type Of",1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_type_of; aworker->input_types[0] = ANY_TYPE; aworker = create_worker(prog, "Init Store",1, 0, WORKER_TYPE); aworker->implement_func=(custom_worker *)init_global_store; aworker->input_types[0] = BUILTIN_TYPE_STRING; aworker = create_worker(prog, "Wait Forever", 0, 0, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_wait_forever; #ifdef NINTENDO_DS aworker = create_worker(prog, "Register Handler", 2, 1, WORKER_TYPE); aworker->implement_func = (custom_worker *)vis_register_handler; aworker->input_types[0] = BUILTIN_TYPE_WHOLE; aworker->input_types[1] = BUILTIN_TYPE_WORKER; aworker = create_worker(prog, "Clear Handler", 1, 1, WORKER_TYPE); aworker->implement_func = (custom_worker *)vis_clear_handler; aworker->input_types[0] = BUILTIN_TYPE_WHOLE; aworker = create_worker(prog, "Held Keys", 0, 1, WORKER_TYPE); aworker->implement_func = (custom_worker *)vis_held_keys; aworker = create_worker(prog, "Touch Position", 0, 2, WORKER_TYPE); aworker->implement_func = (custom_worker *)vis_touch_position; #endif current_method = 0; //strcpy(companylist[current_company].name, "String"); #ifdef SEGA this_comp = create_company(prog, "String", 6, 0, FALSE); #else this_comp = create_company(prog, "String", 7, 0, FALSE); #endif aworker = create_worker(prog, "<Whole Number@String",1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_inttostring; aworker->input_types[0] = BUILTIN_TYPE_WHOLE; //add_method(this_comp, aworker); #ifndef SEGA aworker = create_worker(prog, "<Real Number@String",1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_realtostring; aworker->input_types[0] = BUILTIN_TYPE_REAL; //add_method(this_comp, aworker); #endif aworker = create_worker(prog, "=@String",2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_stringequal; aworker->input_types[0] = BUILTIN_TYPE_STRING; aworker->input_types[1] = BUILTIN_TYPE_STRING; //add_method(this_comp, aworker); aworker = create_worker(prog, "<Yes No@String",1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_yesnotostring; aworker->input_types[0] = BUILTIN_TYPE_YESNO; //add_method(this_comp, aworker); aworker = create_worker(prog, ">@String",2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_greaterstring; aworker->input_types[0] = BUILTIN_TYPE_STRING; aworker->input_types[1] = BUILTIN_TYPE_STRING; //add_method(this_comp, aworker); aworker = create_worker(prog, "<@String",2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_lesserstring; aworker->input_types[0] = BUILTIN_TYPE_STRING; aworker->input_types[1] = BUILTIN_TYPE_STRING; //add_method(this_comp, aworker); aworker = create_worker(prog, "Append@String",2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_append; aworker->input_types[0] = BUILTIN_TYPE_STRING; aworker->input_types[1] = BUILTIN_TYPE_STRING; //add_method(this_comp, aworker); aworker = create_worker(prog, "Split@String",2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_string_split; aworker->input_types[0] = BUILTIN_TYPE_STRING; aworker->input_types[1] = BUILTIN_TYPE_STRING; aworker = create_worker(prog, "Get Raw@String",2, 2, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_string_get_raw; aworker->input_types[0] = BUILTIN_TYPE_STRING; aworker->input_types[1] = ANY_TYPE; aworker = create_worker(prog, "Put Raw@String",2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_string_put_raw; aworker->input_types[0] = BUILTIN_TYPE_STRING; aworker->input_types[1] = ANY_TYPE; aworker = create_worker(prog, "Slice@String",2, 2, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_string_slice; aworker->input_types[0] = BUILTIN_TYPE_STRING; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; aworker = create_worker(prog, "Reverse@String",1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_string_reverse; aworker->input_types[0] = BUILTIN_TYPE_STRING; aworker = create_worker(prog, "Length@String",1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_string_length; aworker->input_types[0] = BUILTIN_TYPE_STRING; aworker = create_worker(prog, "Put Byte@String",2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_string_put_byte; aworker->input_types[0] = BUILTIN_TYPE_STRING; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; aworker = create_worker(prog, "Get DString@String",2, 4, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_string_get_dstring; aworker->input_types[0] = BUILTIN_TYPE_STRING; aworker->input_types[1] = ANY_TYPE; current_method = 0; this_comp = create_company(prog, "Whole Number", 6, 0, FALSE); aworker = create_worker(prog, "<String@Whole Number",1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_stringtoint; aworker->input_types[0] = BUILTIN_TYPE_STRING; aworker = create_worker(prog, "From Hex@Whole Number",1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_whole_fromhex; aworker->input_types[0] = BUILTIN_TYPE_STRING; //add_method(this_comp, aworker); aworker = create_worker(prog, "=@Whole Number",2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_wholeequal; aworker->input_types[0] = BUILTIN_TYPE_WHOLE; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; //add_method(this_comp, aworker); aworker = create_worker(prog, ">@Whole Number",2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_greaterint; aworker->input_types[0] = BUILTIN_TYPE_WHOLE; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; //add_method(this_comp, aworker); aworker = create_worker(prog, "<@Whole Number",2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_lesserint; aworker->input_types[0] = BUILTIN_TYPE_WHOLE; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; //add_method(this_comp, aworker); aworker = create_worker(prog, "+@Whole Number", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_whole_add; aworker->input_types[0] = BUILTIN_TYPE_WHOLE; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; //add_method(this_comp, aworker); aworker = create_worker(prog, "-@Whole Number", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_whole_subtract; aworker->input_types[0] = BUILTIN_TYPE_WHOLE; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; aworker = create_worker(prog, "*@Whole Number", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_whole_mult; aworker->input_types[0] = BUILTIN_TYPE_WHOLE; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; //add_method(this_comp, aworker); aworker = create_worker(prog, "/@Whole Number", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_whole_div; aworker->input_types[0] = BUILTIN_TYPE_WHOLE; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; aworker = create_worker(prog, "&@Whole Number", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_whole_and; aworker->input_types[0] = BUILTIN_TYPE_WHOLE; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; aworker = create_worker(prog, "|@Whole Number", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_whole_or; aworker->input_types[0] = BUILTIN_TYPE_WHOLE; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; aworker = create_worker(prog, "LShift@Whole Number", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_whole_lsh; aworker->input_types[0] = BUILTIN_TYPE_WHOLE; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; aworker = create_worker(prog, "RShift@Whole Number", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_whole_rsh; aworker->input_types[0] = BUILTIN_TYPE_WHOLE; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; aworker = create_worker(prog, "%@Whole Number", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_whole_modulus; aworker->input_types[0] = BUILTIN_TYPE_WHOLE; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; //add_method(this_comp, aworker); current_method = 0; this_comp = create_company(prog, "Real Number", 6, 0, FALSE);//<string, =, >, <, +, - aworker = create_worker(prog, "<String@Real Number", 1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_stringtoreal; aworker->input_types[0] = BUILTIN_TYPE_STRING; //add_method(this_comp, aworker); aworker = create_worker(prog, "=@Real Number", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_realequal; aworker->input_types[0] = BUILTIN_TYPE_REAL; aworker->input_types[1] = BUILTIN_TYPE_REAL; //add_method(this_comp, aworker); aworker = create_worker(prog, ">@Real Number", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_greaterreal; aworker->input_types[0] = BUILTIN_TYPE_REAL; aworker->input_types[1] = BUILTIN_TYPE_REAL; //add_method(this_comp, aworker); aworker = create_worker(prog, "<@Real Number", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_lesserreal; aworker->input_types[0] = BUILTIN_TYPE_REAL; aworker->input_types[1] = BUILTIN_TYPE_REAL; //add_method(this_comp, aworker); aworker = create_worker(prog, "+@Real Number", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_real_add; aworker->input_types[0] = BUILTIN_TYPE_REAL; aworker->input_types[1] = BUILTIN_TYPE_REAL; //add_method(this_comp, aworker); aworker = create_worker(prog, "-@Real Number", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_real_subtract; aworker->input_types[0] = BUILTIN_TYPE_REAL; aworker->input_types[1] = BUILTIN_TYPE_REAL; aworker = create_worker(prog, "/@Real Number", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_real_div; aworker->input_types[0] = BUILTIN_TYPE_REAL; aworker->input_types[1] = BUILTIN_TYPE_REAL; aworker = create_worker(prog, "*@Real Number", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_real_mult; aworker->input_types[0] = BUILTIN_TYPE_REAL; aworker->input_types[1] = BUILTIN_TYPE_REAL; aworker = create_worker(prog, "Cosine@Real Number", 1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_real_cos; aworker->input_types[0] = BUILTIN_TYPE_REAL; aworker = create_worker(prog, "Sine@Real Number", 1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_real_sin; aworker->input_types[0] = BUILTIN_TYPE_REAL; aworker = create_worker(prog, "Tangent@Real Number", 1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_real_tan; aworker->input_types[0] = BUILTIN_TYPE_REAL; aworker = create_worker(prog, "Arc Cosine@Real Number", 1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_real_arccos; aworker->input_types[0] = BUILTIN_TYPE_REAL; aworker = create_worker(prog, "Arc Sine@Real Number", 1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_real_arcsin; aworker->input_types[0] = BUILTIN_TYPE_REAL; aworker = create_worker(prog, "Arc Tangent@Real Number", 1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_real_arctan; aworker->input_types[0] = BUILTIN_TYPE_REAL; aworker = create_worker(prog, "^@Real Number", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_real_exp; aworker->input_types[0] = BUILTIN_TYPE_REAL; aworker->input_types[1] = BUILTIN_TYPE_REAL; aworker = create_worker(prog, "Square Root@Real Number", 1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_real_sqrt; aworker->input_types[0] = BUILTIN_TYPE_REAL; aworker = create_worker(prog, "Truncate to Whole@Real Number", 1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_whole_fromreal; aworker->input_types[0] = BUILTIN_TYPE_REAL; aworker = create_worker(prog, "<Whole Number@Real Number", 1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_real_fromwhole; aworker->input_types[0] = BUILTIN_TYPE_WHOLE; //add_method(this_comp, aworker); current_method = 0; this_comp = create_company(prog, "List", 7, 1, FALSE);//Index, Append, Swap, Insert, Remove, Set, Length, New comp_room = add_comp_room(this_comp, "Length", 0, 0, ROOM_NO_ACCESS, ROOM_LONG); aworker = create_worker(prog, "Index@List", 2, 2, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_list_index; aworker->input_types[0] = BUILTIN_TYPE_LIST; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; //add_method(this_comp, aworker); aworker = create_worker(prog, "Append@List", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_list_append; aworker->input_types[0] = BUILTIN_TYPE_LIST; aworker->input_types[1] = ANY_TYPE; //add_method(this_comp, aworker); aworker = create_worker(prog, "Swap@List",3, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_list_swap; aworker->input_types[0] = BUILTIN_TYPE_LIST; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; aworker->input_types[2] = BUILTIN_TYPE_WHOLE; //add_method(this_comp, aworker); aworker = create_worker(prog, "Insert@List",3, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_list_insert; aworker->input_types[0] = BUILTIN_TYPE_LIST; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; aworker->input_types[2] = ANY_TYPE; //add_method(this_comp, aworker); aworker = create_worker(prog, "Remove@List", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_list_remove; aworker->input_types[0] = BUILTIN_TYPE_LIST; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; //add_method(this_comp, aworker); aworker = create_worker(prog, "Set@List",3, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_list_set; aworker->input_types[0] = BUILTIN_TYPE_LIST; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; aworker->input_types[2] = ANY_TYPE; //add_method(this_comp, aworker); aworker = create_worker(prog, "Length@List", 1, 1, WORKER_TYPE); aworker->implement_func = (custom_worker *)vis_list_length; aworker->input_types[0] = BUILTIN_TYPE_LIST; //add_method(this_comp, aworker); aworker = create_worker(prog, "List",0, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_list_new; //add_method(this_comp, aworker); aworker = create_worker(prog, "First@List", 1, 2, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_list_first; aworker->input_types[0] = BUILTIN_TYPE_LIST; aworker = create_worker(prog, "Next@List", 2, 2, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_list_next; aworker->input_types[0] = BUILTIN_TYPE_LIST; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; current_method = 0; this_comp = create_company(prog, "Dictionary", 5, 0, FALSE);//Index, Swap, Remove, Set, Length, New aworker = create_worker(prog, "Index@Dictionary", 2, 2, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_dict_index; aworker->input_types[0] = BUILTIN_TYPE_DICT; aworker->input_types[1] = BUILTIN_TYPE_STRING; //add_method(this_comp, aworker); aworker = create_worker(prog, "Swap@Dictionary",3, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_dict_swap; aworker->input_types[0] = BUILTIN_TYPE_DICT; aworker->input_types[1] = BUILTIN_TYPE_STRING; aworker->input_types[2] = BUILTIN_TYPE_STRING; //add_method(this_comp, aworker); aworker = create_worker(prog, "Remove@Dictionary", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_dict_remove; aworker->input_types[0] = BUILTIN_TYPE_DICT; aworker->input_types[1] = BUILTIN_TYPE_STRING; //add_method(this_comp, aworker); aworker = create_worker(prog, "Set@Dictionary",3, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_dict_set; aworker->input_types[0] = BUILTIN_TYPE_DICT; aworker->input_types[1] = BUILTIN_TYPE_STRING; aworker->input_types[2] = ANY_TYPE; aworker = create_worker(prog, "Length@Dictionary", 1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_dict_length; aworker->input_types[0] = BUILTIN_TYPE_DICT; //add_method(this_comp, aworker); aworker = create_worker(prog, "Dictionary",0, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_dict_new; //add_method(this_comp, aworker); aworker = create_worker(prog, "First@Dictionary", 1, 2, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_dict_first; aworker->input_types[0] = BUILTIN_TYPE_DICT; aworker = create_worker(prog, "Next@Dictionary", 2, 2, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_dict_next; aworker->input_types[0] = BUILTIN_TYPE_DICT; aworker->input_types[1] = BUILTIN_TYPE_STRING; current_method = 0; #ifdef SEGA this_comp = create_company(prog, "File", 0, 0, FALSE); #else this_comp = create_company(prog, "File", 7, 0, FALSE);//<String, Get FString, Get DString, Get Byte, Get Word, Get Long, Put String aworker = create_worker(prog, "<String@File", 1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_file_from_string; aworker->input_types[0] = BUILTIN_TYPE_STRING; //add_method(this_comp, aworker); aworker = create_worker(prog, "Get FString@File", 2, 2, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_file_get_fstring; aworker->input_types[0] = BUILTIN_TYPE_FILE; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; //add_method(this_comp, aworker); aworker = create_worker(prog, "Get DString@File", 2, 4, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_file_get_dstring; aworker->input_types[0] = BUILTIN_TYPE_FILE; aworker->input_types[1] = ANY_TYPE; //add_method(this_comp, aworker); aworker = create_worker(prog, "Get Byte@File", 1, 3, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_file_get_byte; aworker->input_types[0] = BUILTIN_TYPE_FILE; //add_method(this_comp, aworker); aworker = create_worker(prog, "Get Word@File", 1, 3, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_file_get_word; aworker->input_types[0] = BUILTIN_TYPE_FILE; //add_method(this_comp, aworker); aworker = create_worker(prog, "Get Long@File", 1, 3, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_file_get_long; aworker->input_types[0] = BUILTIN_TYPE_FILE; //add_method(this_comp, aworker); aworker = create_worker(prog, "Get Double@File", 1, 3, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_file_get_double; aworker->input_types[0] = BUILTIN_TYPE_FILE; aworker = create_worker(prog, "Put String@File", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_file_put_string; aworker->input_types[0] = BUILTIN_TYPE_FILE; aworker->input_types[1] = BUILTIN_TYPE_STRING; aworker = create_worker(prog, "Length@File", 1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_file_length; aworker->input_types[0] = BUILTIN_TYPE_FILE; //add_method(this_comp, aworker); #endif current_method = 0; this_comp = create_company(prog, "Worker", 3, 0, FALSE);//<String, Do, Later: methods for manipulating aworker = create_worker(prog, "<String@Worker", 1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_worker_from_string; aworker->input_types[0] = BUILTIN_TYPE_STRING; //add_method(this_comp, aworker); aworker = create_worker(prog, "Do@Worker", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_worker_do; aworker->input_types[0] = BUILTIN_TYPE_WORKER; aworker->input_types[1] = BUILTIN_TYPE_LIST; aworker = create_worker(prog, "Set Input@Worker", 3, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_worker_setinput; aworker->input_types[0] = BUILTIN_TYPE_WORKER; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; aworker->input_types[2] = ANY_TYPE; //add_method(this_comp, aworker); aworker = create_worker(prog, "Add Worker Call@Worker", 2, 2, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_worker_add_worker_call; aworker->input_types[0] = BUILTIN_TYPE_WORKER; aworker->input_types[1] = BUILTIN_TYPE_WORKER; aworker = create_worker(prog, "Add Wire@Worker", 5, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_worker_add_wire; aworker->input_types[0] = BUILTIN_TYPE_WORKER; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; aworker->input_types[2] = BUILTIN_TYPE_WHOLE; aworker->input_types[3] = BUILTIN_TYPE_WHOLE; aworker->input_types[4] = BUILTIN_TYPE_WHOLE; aworker = create_worker(prog, "Add Constant@Worker", 2, 2, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_worker_add_constant; aworker->input_types[0] = BUILTIN_TYPE_WORKER; aworker->input_types[1] = ANY_TYPE; aworker = create_worker(prog, "Add Input@Worker", 3, 2, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_worker_add_input; aworker->input_types[0] = BUILTIN_TYPE_WORKER; aworker->input_types[1] = BUILTIN_TYPE_STRING; aworker->input_types[2] = BUILTIN_TYPE_WHOLE; aworker = create_worker(prog, "Add Output@Worker", 3, 2, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_worker_add_output; aworker->input_types[0] = BUILTIN_TYPE_WORKER; aworker->input_types[1] = BUILTIN_TYPE_STRING; aworker->input_types[2] = BUILTIN_TYPE_WHOLE; aworker = create_worker(prog, "Add Object Get@Worker", 2, 2, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_worker_add_objectget; aworker->input_types[0] = BUILTIN_TYPE_WORKER; aworker->input_types[1] = BUILTIN_TYPE_STRING; aworker = create_worker(prog, "Add Object Set@Worker", 2, 2, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_worker_add_objectset; aworker->input_types[0] = BUILTIN_TYPE_WORKER; aworker->input_types[1] = BUILTIN_TYPE_STRING; aworker = create_worker(prog, "Add Global Get@Worker", 3, 2, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_worker_add_globalget; aworker->input_types[0] = BUILTIN_TYPE_WORKER; aworker->input_types[1] = BUILTIN_TYPE_STRING; aworker->input_types[2] = BUILTIN_TYPE_STRING; aworker = create_worker(prog, "Add Global Set@Worker", 3, 2, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_worker_add_globalset; aworker->input_types[0] = BUILTIN_TYPE_WORKER; aworker->input_types[1] = BUILTIN_TYPE_STRING; aworker->input_types[2] = BUILTIN_TYPE_STRING; aworker = create_worker(prog, "Clear@Worker", 1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_worker_clear; aworker->input_types[0] = BUILTIN_TYPE_WORKER; aworker = create_worker(prog, "Uses@Worker", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_worker_uses; aworker->input_types[0] = BUILTIN_TYPE_WORKER; aworker->input_types[1] = BUILTIN_TYPE_LIST; aworker = create_worker(prog, "Set IO Counts@Worker", 3, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_worker_setio_counts; aworker->input_types[0] = BUILTIN_TYPE_WORKER; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; aworker->input_types[2] = BUILTIN_TYPE_WHOLE; aworker = create_worker(prog, "Worker", 1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_worker_new; aworker->input_types[0] = BUILTIN_TYPE_STRING; #ifdef GUI_LIB current_method = 0; this_comp = create_company(prog, "Window", 3, 0, FALSE); aworker = create_worker(prog, "Window", 3, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_window_new; aworker->input_types[0] = BUILTIN_TYPE_STRING; aworker->input_types[1] = BUILTIN_TYPE_REAL; aworker->input_types[2] = BUILTIN_TYPE_REAL; //add_method(this_comp, aworker); aworker = create_worker(prog, "Add Widget@Window", 5, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_window_add_widget; aworker->input_types[0] = BUILTIN_TYPE_WINDOW; aworker->input_types[1] = BUILTIN_TYPE_STRING; aworker->input_types[2] = ANY_TYPE; aworker->input_types[3] = BUILTIN_TYPE_REAL; aworker->input_types[4] = BUILTIN_TYPE_REAL; //add_method(this_comp, aworker); aworker = create_worker(prog, "Show@Window", 3, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_window_show; aworker->input_types[0] = BUILTIN_TYPE_WINDOW; aworker->input_types[1] = BUILTIN_TYPE_REAL; aworker->input_types[2] = BUILTIN_TYPE_REAL; //add_method(this_comp, aworker); current_method = 0; this_comp = create_company(prog, "Screen Window", 3, 0, FALSE); aworker = create_worker(prog, "Get Value@Screen Window", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_window_get_value; aworker->input_types[0] = BUILTIN_TYPE_WINDOW_SHOWN; aworker->input_types[1] = BUILTIN_TYPE_STRING; //add_method(this_comp, aworker); aworker = create_worker(prog, "Set Value@Screen Window", 3, 0, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_window_set_value; aworker->input_types[0] = BUILTIN_TYPE_WINDOW_SHOWN; aworker->input_types[1] = BUILTIN_TYPE_STRING; #ifdef SYLLABLE aworker->input_types[2] = ANY_TYPE; #else aworker->input_types[2] = BUILTIN_TYPE_STRING; #endif //add_method(this_comp, aworker); aworker = create_worker(prog, "Wait Close@Screen Window", 1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_window_wait_close; aworker->input_types[0] = BUILTIN_TYPE_WINDOW_SHOWN; //add_method(this_comp, aworker); #ifdef SYLLABLE aworker = create_worker(prog, "Add Widget@Screen Window", 5, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_window_shown_addwidget; aworker->input_types[0] = BUILTIN_TYPE_WINDOW_SHOWN; aworker->input_types[1] = BUILTIN_TYPE_STRING; aworker->input_types[2] = ANY_TYPE; aworker->input_types[3] = BUILTIN_TYPE_REAL; aworker->input_types[4] = BUILTIN_TYPE_REAL; #endif current_method = 0; create_company(prog, "Button", 2, 0, FALSE); aworker = create_worker(prog, "Button", 3, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_button_new; aworker->input_types[0] = BUILTIN_TYPE_STRING; aworker->input_types[1] = BUILTIN_TYPE_REAL; aworker->input_types[2] = BUILTIN_TYPE_REAL; //add_method(this_comp, aworker); aworker = create_worker(prog, "Set Handler@Button", 3, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_button_set_handler; aworker->input_types[0] = BUILTIN_TYPE_BUTTON; aworker->input_types[1] = BUILTIN_TYPE_STRING; aworker->input_types[2] = BUILTIN_TYPE_WORKER; //add_method(this_comp, aworker); current_method = 0; create_company(prog, "Input Box", 2, 0, FALSE); aworker = create_worker(prog, "Input Box", 3, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_inputbox_new; aworker->input_types[0] = BUILTIN_TYPE_STRING; aworker->input_types[1] = BUILTIN_TYPE_REAL; aworker->input_types[2] = BUILTIN_TYPE_REAL; //add_method(this_comp, aworker); aworker = create_worker(prog, "Set Type@Input Box", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_inputbox_settype; aworker->input_types[0] = BUILTIN_TYPE_INPUTBOX; aworker->input_types[1] = BUILTIN_TYPE_STRING; //add_method(this_comp, aworker); #endif #ifndef NO_NET this_comp = create_company(prog, "Net Client", 3, 0, FALSE); aworker = create_worker(prog, "Net Client", 2, 1, WORKER_TYPE); aworker->implement_func =(custom_worker *)net_client_new; aworker->input_types[0] = BUILTIN_TYPE_STRING; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; aworker = create_worker(prog, "Put String@Net Client", 2, 2, WORKER_TYPE); aworker->implement_func = (custom_worker *)net_client_put_string; aworker->input_types[0] = BUILTIN_TYPE_NETCLIENT; aworker->input_types[1] = BUILTIN_TYPE_STRING; aworker = create_worker(prog, "Get FString@Net Client", 2, 3, WORKER_TYPE); aworker->implement_func = (custom_worker *)net_client_get_fstring; aworker->input_types[0] = BUILTIN_TYPE_NETCLIENT; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; aworker = create_worker(prog, "Get DString@Net Client", 2, 4, WORKER_TYPE); aworker->implement_func = (custom_worker *)net_client_get_dstring; aworker->input_types[0] = BUILTIN_TYPE_NETCLIENT; aworker->input_types[1] = ANY_TYPE; aworker = create_worker(prog, "Put Raw@Net Client", 2, 2, WORKER_TYPE); aworker->implement_func = (custom_worker *)net_client_put_raw; aworker->input_types[0] = BUILTIN_TYPE_NETCLIENT; aworker->input_types[1] = ANY_TYPE; aworker = create_worker(prog, "Get Raw@Net Client", 2, 3, WORKER_TYPE); aworker->implement_func = (custom_worker *)net_client_get_raw; aworker->input_types[0] = BUILTIN_TYPE_NETCLIENT; aworker->input_types[1] = ANY_TYPE; aworker = create_worker(prog, "Listen on Port", 2, 0, WORKER_TYPE); aworker->implement_func = (custom_worker *)vis_net_listenport; aworker->input_types[0] = BUILTIN_TYPE_WHOLE; aworker->input_types[1] = BUILTIN_TYPE_WORKER; #endif create_company(prog, "Global Store", 0, 0, FALSE); create_company(prog, "Program", 5, 0, FALSE); aworker = create_worker(prog, "Program", 0, 1, WORKER_TYPE); aworker->implement_func = (custom_worker *)vis_program_new; aworker = create_worker(prog, "New Worker@Program", 2, 2, WORKER_TYPE); aworker->implement_func = (custom_worker *)vis_program_new_worker; aworker->input_types[0] = BUILTIN_TYPE_PROGRAM; aworker->input_types[1] = BUILTIN_TYPE_STRING; aworker = create_worker(prog, "Add Worker@Program", 2, 2, WORKER_TYPE); aworker->implement_func = (custom_worker *)vis_program_add_worker; aworker->input_types[0] = BUILTIN_TYPE_PROGRAM; aworker->input_types[1] = BUILTIN_TYPE_WORKER; aworker = create_worker(prog, "Add Builtins@Program", 1, 1, WORKER_TYPE); aworker->implement_func = (custom_worker *)vis_program_add_builtins; aworker->input_types[0] = BUILTIN_TYPE_PROGRAM; aworker = create_worker(prog, "Run@Program", 2, 1, WORKER_TYPE); aworker->implement_func = (custom_worker *)vis_program_run; aworker->input_types[0] = BUILTIN_TYPE_PROGRAM; aworker->input_types[1] = ANY_TYPE; aworker = create_worker(prog, "Find Worker@Program", 2, 2, WORKER_TYPE); aworker->implement_func = (custom_worker *)vis_program_find_worker; aworker->input_types[0] = BUILTIN_TYPE_PROGRAM; aworker->input_types[1] = BUILTIN_TYPE_STRING; #ifdef GUI_LIB #ifdef SYLLABLE create_company(prog, "Custom Widget", 2, 0, FALSE); aworker = create_worker(prog, "Custom Widget", 3, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_customwidget_new; aworker->input_types[0] = BUILTIN_TYPE_STRING; aworker->input_types[1] = BUILTIN_TYPE_REAL; aworker->input_types[2] = BUILTIN_TYPE_REAL; //add_method(this_comp, aworker); aworker = create_worker(prog, "Set Handler@Custom Widget", 3, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_button_set_handler; aworker->input_types[0] = BUILTIN_TYPE_CUSTOM_WIDGET; aworker->input_types[1] = BUILTIN_TYPE_STRING; aworker->input_types[2] = BUILTIN_TYPE_WORKER; //add_method(this_comp, aworker); create_company(prog, "Screen Custom Widget", 3, 0, FALSE); aworker = create_worker(prog, "Default Draw@Screen Custom Widget", 1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_screen_custom_defaultpaint; aworker->input_types[0] = BUILTIN_TYPE_SCREEN_CUSTOM; //add_method(this_comp, aworker); aworker = create_worker(prog, "Draw Line@Screen Custom Widget", 5, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_screen_custom_drawline; aworker->input_types[0] = BUILTIN_TYPE_SCREEN_CUSTOM; aworker->input_types[1] = BUILTIN_TYPE_REAL; aworker->input_types[2] = BUILTIN_TYPE_REAL; aworker->input_types[3] = BUILTIN_TYPE_REAL; aworker->input_types[4] = BUILTIN_TYPE_REAL; //add_method(this_comp, aworker); aworker = create_worker(prog, "Draw String@Screen Custom Widget", 4, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_screen_custom_drawstring; aworker->input_types[0] = BUILTIN_TYPE_SCREEN_CUSTOM; aworker->input_types[1] = BUILTIN_TYPE_STRING; aworker->input_types[2] = BUILTIN_TYPE_REAL; aworker->input_types[3] = BUILTIN_TYPE_REAL; aworker = create_worker(prog, "Set Draw Color@Screen Custom Widget", 5, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_screen_custom_setdrawcolor; aworker->input_types[0] = BUILTIN_TYPE_SCREEN_CUSTOM; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; aworker->input_types[2] = BUILTIN_TYPE_WHOLE; aworker->input_types[3] = BUILTIN_TYPE_WHOLE; aworker->input_types[4] = BUILTIN_TYPE_WHOLE; aworker = create_worker(prog, "Move By@Screen Custom Widget", 3, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_screen_custom_moveby; aworker->input_types[0] = BUILTIN_TYPE_SCREEN_CUSTOM; aworker->input_types[1] = BUILTIN_TYPE_REAL; aworker->input_types[2] = BUILTIN_TYPE_REAL; aworker = create_worker(prog, "Set Handler@Screen Custom Widget", 3, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_screen_custom_sethandler; aworker->input_types[0] = BUILTIN_TYPE_SCREEN_CUSTOM; aworker->input_types[1] = BUILTIN_TYPE_STRING; aworker->input_types[2] = BUILTIN_TYPE_WORKER; aworker = create_worker(prog, "Remove Handler@Screen Custom Widget", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_screen_custom_removehandler; aworker->input_types[0] = BUILTIN_TYPE_SCREEN_CUSTOM; aworker->input_types[1] = BUILTIN_TYPE_STRING; aworker = create_worker(prog, "Give Focus@Screen Custom Widget", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_screen_custom_givefocus; aworker->input_types[0] = BUILTIN_TYPE_SCREEN_CUSTOM; aworker->input_types[1] = BUILTIN_TYPE_YESNO; aworker = create_worker(prog, "Add Widget@Screen Custom Widget", 5, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_screen_custom_addwidget; aworker->input_types[0] = BUILTIN_TYPE_SCREEN_CUSTOM; aworker->input_types[1] = BUILTIN_TYPE_STRING; aworker->input_types[2] = ANY_TYPE; aworker->input_types[3] = BUILTIN_TYPE_REAL; aworker->input_types[4] = BUILTIN_TYPE_REAL; #endif #endif create_company(prog, "Buffer", 7, 0, FALSE); aworker = create_worker(prog, "Buffer", 1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_buffer_new; aworker->input_types[0] = BUILTIN_TYPE_WHOLE; aworker = create_worker(prog, "Lock@Buffer", 1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_buffer_lock; aworker->input_types[0] = BUILTIN_TYPE_BUFFER; aworker = create_worker(prog, "Unlock@Buffer", 1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_buffer_unlock; aworker->input_types[0] = BUILTIN_TYPE_BUFFER; aworker = create_worker(prog, "Put Byte@Buffer", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_buffer_putbyte; aworker->input_types[0] = BUILTIN_TYPE_BUFFER; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; aworker = create_worker(prog, "Write Byte@Buffer", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_buffer_writebyte; aworker->input_types[0] = BUILTIN_TYPE_BUFFER; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; aworker = create_worker(prog, "Put Word@Buffer", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_buffer_putshort; aworker->input_types[0] = BUILTIN_TYPE_BUFFER; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; aworker = create_worker(prog, "Write Word@Buffer", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_buffer_writeshort; aworker->input_types[0] = BUILTIN_TYPE_BUFFER; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; aworker = create_worker(prog, "Put Long@Buffer", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_buffer_putlong; aworker->input_types[0] = BUILTIN_TYPE_BUFFER; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; aworker = create_worker(prog, "Write Long@Buffer", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_buffer_writelong; aworker->input_types[0] = BUILTIN_TYPE_BUFFER; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; aworker = create_worker(prog, "Reset@Buffer", 1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_buffer_reset; aworker->input_types[0] = BUILTIN_TYPE_BUFFER; #if defined(SEGA) || defined(NINTENDO_DS) aworker = create_worker(prog, "From Address@Buffer", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_buffer_fromaddress; aworker->input_types[0] = BUILTIN_TYPE_WHOLE; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; #endif //SEGA create_company(prog, "Blueprint", 4, 0, FALSE); aworker = create_worker(prog, "Blueprint", 1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_blueprint_new; aworker->input_types[0] = BUILTIN_TYPE_STRING; aworker = create_worker(prog, "Add Field@Blueprint", 3, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_blueprint_addfield; aworker->input_types[0] = BUILTIN_TYPE_BLUEPRINT; aworker->input_types[1] = BUILTIN_TYPE_STRING; aworker->input_types[2] = BUILTIN_TYPE_STRING; aworker = create_worker(prog, "Name@Blueprint", 1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_blueprint_name; aworker->input_types[0] = BUILTIN_TYPE_BLUEPRINT; aworker = create_worker(prog, "Get Fields@Blueprint", 1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_blueprint_getfields; aworker->input_types[0] = BUILTIN_TYPE_BLUEPRINT; aworker = create_worker(prog, "Blueprint Of", 1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_get_blueprint; aworker->input_types[0] = ANY_TYPE; aworker = create_worker(prog, "Get Field", 2, 2, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_get_field; aworker->input_types[0] = ANY_TYPE; aworker->input_types[1] = BUILTIN_TYPE_STRING; aworker = create_worker(prog, "Set Field", 3, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_set_field; aworker->input_types[0] = ANY_TYPE; aworker->input_types[1] = BUILTIN_TYPE_STRING; aworker->input_types[2] = ANY_TYPE; aworker = create_worker(prog, "New Blueprint@Program", 2, 2, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_program_newblueprint; aworker->input_types[0] = BUILTIN_TYPE_PROGRAM; aworker->input_types[1] = BUILTIN_TYPE_STRING; #ifdef GUI_LIB #ifdef SYLLABLE create_company(prog, "Checkbox", 2, 0, FALSE); aworker = create_worker(prog, "Checkbox", 4, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_checkbox_new; aworker->input_types[0] = BUILTIN_TYPE_STRING; aworker->input_types[1] = BUILTIN_TYPE_REAL; aworker->input_types[2] = BUILTIN_TYPE_REAL; aworker->input_types[3] = BUILTIN_TYPE_YESNO; aworker = create_worker(prog, "Set Handler@Checkbox", 3, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_button_set_handler; aworker->input_types[0] = BUILTIN_TYPE_CHECKBOX; aworker->input_types[1] = BUILTIN_TYPE_STRING; aworker->input_types[2] = BUILTIN_TYPE_WORKER; create_company(prog, "Dropdown", 4, 0, FALSE); aworker = create_worker(prog, "Dropdown", 3, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_dropdown_new; aworker->input_types[0] = BUILTIN_TYPE_LIST; aworker->input_types[1] = BUILTIN_TYPE_REAL; aworker->input_types[2] = BUILTIN_TYPE_REAL; aworker = create_worker(prog, "Set Handler@Dropdown", 3, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_button_set_handler; aworker->input_types[0] = BUILTIN_TYPE_DROPDOWN; aworker->input_types[1] = BUILTIN_TYPE_STRING; aworker->input_types[2] = BUILTIN_TYPE_WORKER; aworker = create_worker(prog, "Set Text@Dropdown", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_dropdown_settext; aworker->input_types[0] = BUILTIN_TYPE_DROPDOWN; aworker->input_types[1] = BUILTIN_TYPE_STRING; aworker = create_worker(prog, "Select@Dropdown", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_dropdown_select; aworker->input_types[0] = BUILTIN_TYPE_DROPDOWN; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; #endif #endif aworker = create_worker(prog, "Unix Time", 0, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)unix_time; /*if(current_def > num_defs) num_defs = current_def; if(current_company > num_companies) num_companies = current_company;*/ } void initworkers(program * prog) { //num_defs=0; //num_companies=0; create_worker(prog, "Main", 0, 0, USER_FLAG | WORKER_TYPE); initpredefworkers(prog); } /* void add_if_ready(int workerNum, worker_instance * instance) { //int i, j, n, old_ready_count; BOOL ready=FALSE; //int paramstore[32]; //int * params = paramstore; DEBUGPUTS("add_if_ready\n"); if(!instance || !instance->def) return; VIS_PROFILE_START(PROF_ADDREADY); DEBUGPRINTF( "add_if_ready on %s\n", instance->def->implement_func->workerlist[workerNum].name); VIS_EnterCriticalSection(instance->workerlist[workerNum].worker_lock); ++instance->workerlist[workerNum].ready_count; if(instance->workerlist[workerNum].ready_count >= (instance->def->implement_func->workerlist[workerNum].num_inputs + (instance->def->implement_func->workerlist[workerNum].null_input ? 1 : 0))) { ready = TRUE; instance->workerlist[workerNum].ready_count = 0; } VIS_LeaveCriticalSection(instance->workerlist[workerNum].worker_lock); if(ready) { DEBUGPRINTF("add_queue on %s\n", instance->def->implement_func->workerlist[workerNum].name); add_queue(workerNum, instance); } VIS_PROFILE_END(PROF_ADDREADY); }*/ #define RETURN_CODE_EXIT 0xABCE1234 #define RETURN_CODE_IDLE 0x00BADFAD #define RETURN_CODE_NORMAL 0xABBAABBA #define RETURN_CODE_PARALLEL 0xC001D00D #define GET_OP1(opcode) ((opcode & 0xF0000000) >> 28) #define GET_OP2(opcode) ((opcode & 0x0F000000) >> 24) #define GET_INST(opcode) ((opcode & 0x00FF0000) >> 16) #define MOVE_INST 0x00 #define ADDREF_INST 0x01 #define RELEASE_INST 0x02 #define LOAD_INST 0x03 #define CALL_INST 0x04 #define CALLB_INST 0x05 #define CALLP_INST 0x06 #define CALLBP_INST 0x07 #define RETURN_INST 0x08 #define BRANCH_INST 0x09 #define BRANCHT_INST 0x0A #define BRANCHF_INST 0x0B #define WAIT_INST 0x0C #define ADD_INST 0x0D #define SUB_INST 0x0E #define SUBR_INST 0x0F #define GREATER_INST 0x10 #define LESSER_INST 0x11 #define REGISTER_BIT 0x8 #define NO_OPERAND 0x7 #define OP_REG_MASK 0x7 #define GET_REGNUM1(opcode) ((opcode & 0x0000FF00) >> 8) #define GET_REGNUM2(opcode) (opcode & 0x000000FF) #define REG_DIRECT 0 #define REG_INDIRECT 1 #define IMMED_8 2 #define IMMED_32 3 #define STACK_8 4 #define REG_REL_32 5 #define PC_REL_8 6 #define STACK_REG 31 #define PC_REG 30 #define OPC(inst, op1, reg1, op2, reg2) ((op1 << 28) | (op2 << 24) | (inst << 16) | ((reg1 & 0xff) << 8) | (reg2 & 0xFF)) //unsigned long test_program[] = //{ // OPC(LOAD_INST, PC_REL_8, 8 /* Hi */, REG_DIRECT, 0), // OPC(CALLB_INST, IMMED_8, 1/* Print */, NO_OPERAND, 0), // OPC(RETURN_INST, NO_OPERAND, 0, NO_OPERAND, 0), // 26952//Hi //}; unsigned long test_program[] = { //Main: OPC(LOAD_INST, PC_REL_8, 20/* 10 */, REG_DIRECT, 0), OPC(LOAD_INST, PC_REL_8, 20/* 2 */, PC_REL_8, 28), OPC(LOAD_INST, PC_REL_8, 20/* 1 */, PC_REL_8, 28), OPC(CALL_INST, PC_REL_8, 28/* Fib: */, NO_OPERAND, 0), OPC(CALLB_INST, IMMED_8, 1/* Print */, NO_OPERAND, 0), OPC(RETURN_INST, NO_OPERAND, 0, NO_OPERAND, 0), 0x3033,//'30' 0x32,//'2' 0x31,//'1' 0,//2 storage 0,//1 storage //Fib: OPC(ADD_INST, IMMED_8, 8, REG_DIRECT, STACK_REG), OPC(MOVE_INST, REG_DIRECT, 0, STACK_8, -4), OPC(ADDREF_INST, REG_INDIRECT, 0, NO_OPERAND, 0), OPC(ADDREF_INST, REG_INDIRECT, 0, NO_OPERAND, 0), OPC(MOVE_INST, PC_REL_8, -28/* 2 */, REG_DIRECT, 1), OPC(ADDREF_INST, REG_INDIRECT, 1, NO_OPERAND, 0), OPC(CALLB_INST, IMMED_8, 8/* < */, NO_OPERAND, 0), OPC(CALLB_INST, IMMED_8, 11/* If */, NO_OPERAND, 0), OPC(BRANCHT_INST, PC_REL_8, 64/* _Base */, REG_DIRECT, 0), OPC(RELEASE_INST, REG_INDIRECT, 1, NO_OPERAND, 0), OPC(MOVE_INST, STACK_8, -4, REG_DIRECT, 0), OPC(MOVE_INST, PC_REL_8, -56/* 2 */, REG_DIRECT, 1), OPC(ADDREF_INST, REG_INDIRECT, 1, NO_OPERAND, 0), OPC(CALLB_INST, IMMED_8, 6/* - */, NO_OPERAND, 0), OPC(CALL_INST, PC_REL_8, -60/* Fib */, NO_OPERAND, 0), OPC(MOVE_INST, REG_DIRECT, 0, STACK_8, -8), OPC(MOVE_INST, STACK_8, -4, REG_DIRECT, 0), OPC(MOVE_INST, PC_REL_8, -76/* 1 */, REG_DIRECT, 1), OPC(ADDREF_INST, REG_INDIRECT, 1, NO_OPERAND, 0), OPC(CALLB_INST, IMMED_8, 6/* - */, NO_OPERAND, 0), OPC(CALL_INST, PC_REL_8, -84/* Fib */, NO_OPERAND, 0), OPC(MOVE_INST, STACK_8, -8, REG_DIRECT, 1), OPC(CALLB_INST, IMMED_8, 5/* + */, NO_OPERAND, 0), OPC(SUBR_INST, IMMED_8, 8, REG_DIRECT, STACK_REG), OPC(RETURN_INST, NO_OPERAND, 0, NO_OPERAND, 0), //_Base: OPC(RELEASE_INST, REG_INDIRECT, 0, NO_OPERAND, 0), OPC(MOVE_INST, PC_REL_8, -112/* 1 */, REG_DIRECT, 0), OPC(ADDREF_INST, REG_INDIRECT, 0, NO_OPERAND, 0), OPC(SUBR_INST, IMMED_8, 8, REG_DIRECT, STACK_REG), OPC(RETURN_INST, NO_OPERAND, 0, NO_OPERAND, 0), }; unsigned long * get_effective_address(char op, unsigned short regnum, unsigned long ** pc, unsigned long * registers, unsigned long * immed) { unsigned long * add = NULL; unsigned long work; if(op != NO_OPERAND) { if(op & REGISTER_BIT) add = (unsigned long *)(registers[regnum] + registers[op & OP_REG_MASK]); else { switch(op) { case REG_DIRECT: add = registers + regnum; break; case REG_INDIRECT: add = (unsigned long *) registers[regnum]; break; case IMMED_8: *immed = (char)regnum; add = (unsigned long *)immed; break; case IMMED_32: *immed = *((*pc)++); add = (unsigned long *)immed; break; case STACK_8: work = (char)regnum; add = (unsigned long *)(registers[STACK_REG] + work); break; case REG_REL_32: work = *((*pc)++); add = (unsigned long *)(registers[regnum] + work); break; case PC_REL_8: work = (char)regnum; add = (unsigned long *)(registers[PC_REG] + work); break; default: break; } } } return add; } DWORD WINAPI virtual_processor(unsigned long * program, BOOL main) { int i; unsigned long **pc; unsigned long **stack; unsigned long registers[32]; unsigned long opcode; unsigned long extra, extra2; queue_entry entry; stack_segment initial_stack; stack_segment * current = &initial_stack; char slot_usage[7]; char op1, op2; char inst; unsigned long *add1, *add2; long immed1, immed2; initial_stack.size = MIN_STACK_SIZE; initial_stack.parent = initial_stack.child = NULL; initial_stack.data[0] = main ? RETURN_CODE_EXIT : RETURN_CODE_IDLE; pc = (unsigned long **)(&(registers[PC_REG])); stack = (unsigned long **)(&(registers[STACK_REG])); *pc = program; *stack = (unsigned long *)(initial_stack.data + 1); entry.instance = NULL; entry.worker_num = 0; DEBUGPRINTF("Virtual processor, Program start: %X\n", program); #ifdef ENABLE_PROFILING for(i = 0; i < NUM_PROFS; ++i) { vis_profile_running_total[i] = 0; vis_profile_counts[i] = 0; } VIS_PROFILE_START(PROF_EMPTYFUNC); empty_test(NULL,NULL); VIS_PROFILE_END(PROF_EMPTYFUNC); VIS_PROFILE_START(PROF_NOCODE); VIS_PROFILE_END(PROF_NOCODE); #endif while(execute_active) { VIS_PROFILE_START(PROF_VIRTUAL_DECODE); DEBUGPRINTF("PC: %X\n", *pc); opcode = *((*pc)++); op1 = GET_OP1(opcode); op2 = GET_OP2(opcode); add1 = get_effective_address(op1, GET_REGNUM1(opcode), pc, registers, &immed1); add2 = get_effective_address(op2, GET_REGNUM2(opcode), pc, registers, &immed2); DEBUGPRINTF("Opcode: %X, Instruction: %X, op1 %X, op2 %X\n", opcode, GET_INST(opcode), op1, op2); inst = GET_INST(opcode); VIS_PROFILE_END(PROF_VIRTUAL_DECODE); VIS_PROFILE_START(PROF_VIRTUAL_EXECUTE); switch(inst) { case MOVE_INST: *add2 = *add1; break; case ADDREF_INST: add_ref((datum *)add1); break; case RELEASE_INST: release_ref((datum *)add1); break; /* Temporarily commented out until multiple program support is finished case LOAD_INST: *add2 = (long)get_constant((char *)add1, -1); break; */ case CALL_INST: *((*stack)++) = (unsigned long)*pc; *((*stack)++) = RETURN_CODE_NORMAL; *pc = add1; break; /* Temporarily commented out until multiple program support is finished case CALLB_INST: //TODO: Needs to be made 100% correct DEBUGPRINTF("Calling builtin: %s\n", deflist[*add1].name); execute_def(deflist + *add1, entry, (datum **)registers, NULL); break;*/ case CALLP_INST: //TODO Implement me break; case CALLBP_INST: //TODO Implement me break; case RETURN_INST: switch(*(--(*stack))) { case RETURN_CODE_EXIT: execute_active = FALSE; break; case RETURN_CODE_IDLE: //TODO: Implement me break; case RETURN_CODE_NORMAL: *pc = (unsigned long *)*(--(*stack)); break; default: break; } break; case BRANCH_INST: *pc = add1; break; case BRANCHT_INST: if(*add2) *pc = add1; break; case BRANCHF_INST: if(!*add2) *pc = add1; break; case WAIT_INST: //TODO: Implement Me break; case ADD_INST: *add2 = *add1 + *add2; break; case SUB_INST: *add2 = *add1 - *add2; break; case SUBR_INST: *add2 = *add2 - *add1; break; case GREATER_INST: *add2 = *add1 > *add2; break; case LESSER_INST: *add2 = *add1 < *add2; break; default: break; } VIS_PROFILE_END(PROF_VIRTUAL_EXECUTE); } #ifdef ENABLE_PROFILING for(i = 0; i < NUM_PROFS; ++i) printf("%d:\t%f,\tcount: %d,\taverage: %f\n", i, (double)vis_profile_running_total[i], vis_profile_counts[i], ((double)vis_profile_running_total[i])/((double)vis_profile_counts[i])); #endif return 0; } void test_virtual() { // int i,j,k; program * prog = new_program(START_DEF_STORAGE, START_COMP_STORAGE); initpredefworkers(prog); init_sync_primitives(); init_datum_storage(); //TODO Uncomment me // init_global_storage(); execute_active = TRUE; /* for(i = MOVE_INST; i <= LESSER_INST; ++i) { for(j = 0; j < 0x10; ++j) { for(k = 0; k < 0x10; ++k) { DEBUGPRINTF("i: %X, j: %X, k: %X, OPC: %X\n", i, j, k, OPC(i, j, j, k, k)); } } }*/ virtual_processor(test_program, TRUE); } DWORD WINAPI worker_thread(LPVOID param) { queue_entry aworker; int temp_queue_len; while(execute_active) { VIS_PROFILE_START(PROF_WORKER_THREAD); #ifdef NINTENDO_DS if(irq_queue_count > 0) run_queued_irqs(); #endif //DEBUGPUTS("Before WaitForSingleObect\n"); /*VIS_EnterCriticalSection(worker_queue_lock); temp_queue_len = queue_len; VIS_LeaveCriticalSection(worker_queue_lock);*/ //DEBUGPUTS("After WaitForSingleObject\n"); aworker = get_queue(); //DEBUGPUTS("After get_queue()\n"); //while(execute_active && aworker.worker_num < 0)//temp_queue_len == 0 && execute_active) //{ // VIS_WaitEvent(queue_add_event); // aworker = get_queue(); /*#if COMPILE_THREADS > 0 #ifdef WIN32 Sleep(0); #else sleep(0); #endif #endif VIS_EnterCriticalSection(worker_queue_lock); temp_queue_len = queue_len; VIS_LeaveCriticalSection(worker_queue_lock);*/ //} if(aworker.worker_num >= 0) { //DEBUGPUTS("Before EnterCriticalSection\n"); /* VIS_EnterCriticalSection(worker_queue_lock); if(queue_len > 0) { DEBUGPUTS("SetEvent\n"); VIS_SetEvent(queue_add_event); } VIS_LeaveCriticalSection(worker_queue_lock);*/ DEBUGPRINTF( "\nExecuting: %s<%d>, Instance: %X\n", aworker.instance->def->implement_func->workerlist[aworker.worker_num].name,aworker.worker_num,aworker.instance); if(process_worker(aworker) == 0) { //worker_complete(aworker); cleanup_check(aworker); //DEBUGPUTS("After cleanup_check\n"); } } VIS_PROFILE_END(PROF_WORKER_THREAD); } VIS_SetEvent(queue_add_event); return 0; } int set_comp_room(datum ** params, int room_index, queue_entry * entry, program * prog) { int i; char * data; //DEBUGPRINTF("params[0]->ref_count: %d\n", params[0]->ref_count); params[0] = copy_datum(params[0], 0); data = ((char *)(params[0]->c.generic.data) + (int)params[0]->company->room_list[room_index].set_func); DEBUGPRINTF("Set comp room: c.generic.data = %X, +get_func = %X\n", params[0]->c.generic.data, data); //TODO: input conversion switch(params[0]->company->room_list[room_index].get_func_type) { case ROOM_BYTE: *data = params[1]->c.integers.num_a; release_ref(params[1]); break; case ROOM_SHORT: *((short *)data) = params[1]->c.integers.num_a; release_ref(params[1]); break; case ROOM_LONG: *((long *)data) = params[1]->c.integers.num_a; release_ref(params[1]); break; case ROOM_SINGLE: *((float *)data) = params[1]->c.real; release_ref(params[1]); break; case ROOM_DOUBLE: *((double *)data) = params[1]->c.real; release_ref(params[1]); break; case ROOM_VIS_REF: release_ref(*((datum **)data)); *((datum **)data) = params[1]; break; case ROOM_CSTRING: //not implemented case ROOM_CSTRING_STRUCT: case ROOM_PSTRING: case ROOM_PSTRING_STRUCT: case ROOM_WORKER://not implemented case ROOM_VIS_OBJECT://not implemented default: release_ref(params[0]); release_ref(params[1]); params[0] = params[1] = NULL; puts("unimplemented company room type\n"); break; } return 0; } int set_comp_room_by_name(datum ** company, char * name, int * room_index_ret, queue_entry * entry, program * prog) { int i; for (i = 0; i < company[0]->company->num_rooms; ++i) if(!strcmp(name,company[0]->company->room_list[i].name)) { if(room_index_ret) *room_index_ret = i; return set_comp_room(company, i, entry, prog); } if(room_index_ret) *room_index_ret = -1; printf("Error: Can't set field %s on object with blueprint %s\n", name, company[0]->company); return -1; } int get_comp_room(datum ** company, int room_index, queue_entry * entry, program * prog) { int i; datum * out; queue_entry empty; char * data = ((char *)(company[0]->c.generic.data) + (int)company[0]->company->room_list[room_index].get_func); company[1] = NULL; DEBUGPRINTF("Get comp room: c.generic.data = %X, +get_func = %X\n", company[0]->c.generic.data, data); switch(company[0]->company->room_list[room_index].get_func_type) { case ROOM_BYTE: out = new_datum(BUILTIN_TYPE_WHOLE, 2, 0, prog); out->c.integers.num_a = *data; break; case ROOM_SHORT: out = new_datum(BUILTIN_TYPE_WHOLE, 2, 0, prog); out->c.integers.num_a = *((short *)data); break; case ROOM_LONG: out = new_datum(BUILTIN_TYPE_WHOLE, 2, 0, prog); out->c.integers.num_a = *((long *)data); break; case ROOM_SINGLE: out = new_datum(BUILTIN_TYPE_REAL, 3, 0, prog); out->c.real = *((float *)data); break; case ROOM_DOUBLE: out = new_datum(BUILTIN_TYPE_REAL, 3, 0, prog); out->c.real = *((double *)data); break; case ROOM_CSTRING: data = *((char **)data); case ROOM_CSTRING_STRUCT: out = new_datum(BUILTIN_TYPE_STRING, 1, strlen(data)+1, prog); strcpy(out->c.generic.data, data); break; case ROOM_PSTRING: data = *((char **)data); case ROOM_PSTRING_STRUCT: out = new_datum(BUILTIN_TYPE_STRING, 1, *((unsigned char *)data), prog); memcpy(out->c.generic.data, data, *((unsigned char *)data)); ((char *)out->c.generic.data)[*((unsigned char *)data)] = '\0'; break; case ROOM_VIS_REF: out = add_ref(*((datum **)data)); if(!out) { company[1] = company[0]; company[0] = NULL; } break; case ROOM_WORKER: if(entry) return execute_def((worker_def *)(company[0]->company->room_list[room_index].get_func), *entry, company, sub_callback); else { empty.instance = NULL; empty.worker_num = -1; return execute_def((worker_def *)(company[0]->company->room_list[room_index].get_func), empty, company, sub_callback); } case ROOM_VIS_OBJECT://not implemented default: out = NULL; puts("unimplemented company room type\n"); break; } release_ref(company[0]); company[0] = out; return 0; } int get_comp_room_by_name(datum ** company, char * name, int * room_index_ret, queue_entry * entry, program * prog) { int i; for (i = 0; i < company[0]->company->num_rooms; ++i) if(!strcmp(name,company[0]->company->room_list[i].name)) { if(room_index_ret) *room_index_ret = i; return get_comp_room(company, i, entry, prog); } if(room_index_ret) *room_index_ret = -1; printf("Error: Can't get field %s from object with blueprint %s\n", name, company[0]->company); print_stack_trace(entry->instance); return -1; } datum * literal_string(char * value, int len, program * prog) { char literalchar; BOOL literal; int i, bufpos, lenstr; datum * returnval; if(len < 0) { len = strlen(value); } literal = FALSE; lenstr = 0; for(i = 0; i < len; ++i) if(literal) literal = FALSE; else { ++lenstr; if(value[i] == '\\') literal = TRUE; } //DEBUGPRINTF("Allocating %d bytes for string constant\n", lenstr+1); returnval = new_datum(BUILTIN_TYPE_STRING, 1, lenstr+1, prog); bufpos = 0; for(i = 0; i < len; ++i) { if(literal) { literal = FALSE; switch(value[i]) { case 'n': //newline literalchar = '\n'; break; case 'r': //carriage return literalchar = '\r'; break; case 't': // tab literalchar = '\t'; break; case '0': //NULL literalchar = '\0'; break; default: literalchar = value[i]; break; } ((char *)returnval->c.generic.data)[bufpos++] = literalchar; } else { if(value[i] == '\\') literal = TRUE; else { ((char *)returnval->c.generic.data)[bufpos++] = value[i]; } } } //DEBUGPRINTF("bufpos: %d\n", bufpos); ((char *)returnval->c.generic.data)[bufpos] = '\0'; DEBUGPUTS("Constant Type: String\n"); return returnval; } datum * get_constant(char * value, int len, program * prog) { datum * params[2]; datum * returnval; int i = 0,bufpos; int start; int lenstr; int leftcurly; int dotcount = 0; char literalchar; unsigned short const_type = ANY_TYPE; BOOL literal; if((len == 3 && memcmp(value, "Yes", len) == 0) || (len < 0 && strcmp(value, "Yes") == 0)) { DEBUGPUTS("Constnat: Yes\n"); returnval = new_datum(BUILTIN_TYPE_YESNO, 2, 0, prog); returnval->c.integers.num_a = 1; DEBUGPRINTF("Company: %s, integers.num_a: %d\n", returnval->company->name, returnval->c.integers.num_a); return returnval; } else if((len == 2 && memcmp(value, "No", len) == 0) || (len < 0 && strcmp(value, "No") == 0)) { DEBUGPUTS("Constant: No\n"); returnval = new_datum(BUILTIN_TYPE_YESNO, 2, 0, prog); returnval->c.integers.num_a = 0; DEBUGPRINTF("Company: %s, integers.num_a: %d\n", returnval->company->name, returnval->c.integers.num_a); return returnval; } if(value[0] == '{') { DEBUGPUTS("Constant type: List"); params[0] = create_list(prog); i = start = 1; literal = FALSE; leftcurly = 0; for(;value[i] != 0 && (len < 0 || i < len); ++i) { if(literal) literal = FALSE; else { if(value[i] == '\\') literal = TRUE; else if(value[i] == '}') if(leftcurly) --leftcurly; else break; else if(value[i] == '{') ++leftcurly; else if(value[i] == ',' && !leftcurly) { params[1] = get_constant(value+start, i-start, prog); vis_list_append(params, NULL); start = i+1; } } } params[1]= get_constant(value+start, i-start, prog); vis_list_append(params, NULL); returnval = params[0]; } else if(value[0] == '"') { if(len < 0) { len = strlen(value); } len -= 2; returnval = literal_string(value+1, len, prog); } else { while(value[i] != 0 && (len < 0 || i < len)) { if(value[i] >= '0' && value[i] <= '9') { if(const_type == ANY_TYPE) const_type = BUILTIN_TYPE_WHOLE; } else if(value[i] == '.') { if(dotcount) { const_type = BUILTIN_TYPE_STRING; } else { ++dotcount; if(const_type == BUILTIN_TYPE_WHOLE) const_type = BUILTIN_TYPE_REAL; } } else { //DEBUGPRINTF("Current character: %c resulted in String\n", value[i]); const_type = BUILTIN_TYPE_STRING; break; } ++i; } if(const_type == BUILTIN_TYPE_WHOLE) { returnval = new_datum(const_type, 2, 0, prog); returnval->c.integers.num_a = atol(value); DEBUGPUTS("Constant Type: Whole Number\n"); } else if(const_type == BUILTIN_TYPE_REAL) { returnval = new_datum(const_type, 3, 0, prog); returnval->c.real = atof(value); DEBUGPUTS("Constant Type: Real Number\n"); } else { /* literal = FALSE; lenstr = 0; for(i = 0; (i < len || len < 0) && value[i] != 0; ++i) if(literal) literal = FALSE; else { ++lenstr; if(value[i] == '\\') literal = TRUE; } DEBUGPRINTF("Allocating %d bytes for string constant\n", lenstr+1); returnval = new_datum(BUILTIN_TYPE_STRING, 1, lenstr+1, prog); bufpos = 0; for(i = 0; (i < len || len < 0) && value[i] != 0; ++i) { DEBUGPRINTF("bufpos: %d\n", bufpos); if(literal) { literal = FALSE; switch(value[i]) { case 'n': //newline literalchar = '\n'; break; case 'r': //carriage return literalchar = '\r'; break; case 't': // tab literalchar = '\t'; break; case '0': //NULL literalchar = '\0'; break; default: literalchar = value[i]; break; } ((char *)returnval->c.generic.data)[bufpos++] = literalchar; } else { if(value[i] == '\\') literal = TRUE; else { ((char *)returnval->c.generic.data)[bufpos++] = value[i]; } } } DEBUGPRINTF("bufpos: %d\n", bufpos); ((char *)returnval->c.generic.data)[bufpos] = '\0'; DEBUGPUTS("Constant Type: String\n"); */ returnval = literal_string(value, len, prog); } } return returnval; } int execute_def(worker_def * process_def, queue_entry worker_entry, datum ** params, instance_callback callback) { return execute_def_type(process_def, worker_entry, params, callback, NULL, WORKER); } int execute_def_data(worker_def * process_def, queue_entry worker_entry, datum ** params, instance_callback callback, void * data) { return execute_def_type(process_def, worker_entry, params, callback, data, WORKER); } int execute_def_type(worker_def * process_def, queue_entry worker_entry, datum ** params, instance_callback callback, void * data, int type) { int returnval, i; worker_instance * stack_instance; worker_def *temp_def, *converter; worker_def *parent_def = worker_entry.instance->def; unsigned short magic_cache_type; #ifdef USER_PROFILE LARGE_INTEGER start, end, duration; #endif VIS_PROFILE_START(PROF_PREP_MAGIC); if((process_def->type & TYPE_MASK) == MAGIC_TYPE) { DEBUGPRINTF( "Magic method: %s\n", process_def->name); if(!params || !params[0]) { ERRORPRINTF("Error: null first parmeter or null parameter array for worker %s, params: %X, params[0]: %X\n", process_def->name, params, params[0]); print_stack_trace(worker_entry.instance); execute_active = FALSE; return -1; } VIS_EnterCriticalSection(parent_def->implement_func->workerlist[worker_entry.worker_num].lock); temp_def = parent_def->implement_func->workerlist[worker_entry.worker_num].magic_cache_implement; magic_cache_type = parent_def->implement_func->workerlist[worker_entry.worker_num].magic_cache_type; VIS_LeaveCriticalSection(parent_def->implement_func->workerlist[worker_entry.worker_num].lock); if(!temp_def || magic_cache_type != params[0]->company->type_id) { DEBUGPRINTF("Finding method %s with %d inputs for type %s(%d)\n", process_def->name, process_def->num_inputs, params[0]->company->name, params[0]->company->type_id); temp_def = find_method(params[0]->company->type_id,process_def->name, process_def->num_inputs, process_def->program); if(!temp_def) { for(i = 1; i < process_def->program->num_companies; ++i) { temp_def = find_method(i,process_def->name, process_def->num_inputs, process_def->program); if(temp_def) { converter = find_converter_method(temp_def->input_types[0], params[0]->company->type_id, process_def->program); if(converter) { ((worker_impl)converter->implement_func)(params, &worker_entry); break; } else { //DEBUGPRINTF("Error: Needed conversion from %s to %s for input %d of %s\n", params[0]->company->name, process_def->program->companylist[temp_def->input_types[0]].name, 0, temp_def->name); //printf("Warning: Needed conversion from %s to %s for input %d of %s for loose method call\n", params[0]->company->name, process_def->program->companylist[temp_def->input_types[0]].name, 0, temp_def->name); temp_def = NULL; } } } } if(temp_def) { VIS_EnterCriticalSection(parent_def->implement_func->workerlist[worker_entry.worker_num].lock); parent_def->implement_func->workerlist[worker_entry.worker_num].magic_cache_implement = temp_def; parent_def->implement_func->workerlist[worker_entry.worker_num].magic_cache_type = temp_def->input_types[0]; VIS_LeaveCriticalSection(parent_def->implement_func->workerlist[worker_entry.worker_num].lock); } else { ERRORPRINTF("Error: Company %s doesn't implement worker %s. It implements the following:\n", params[0]->company->name, process_def->name); for(i = 0; i < params[0]->company->num_methods; ++i) { ERRORPRINTF("%s\n", params[0]->company->methodlist[i]->name); } print_stack_trace(worker_entry.instance); } } process_def = temp_def; } VIS_PROFILE_END(PROF_PREP_MAGIC); if(!process_def) { //DEBUGPUTS("Invalid def\n"); VIS_PROFILE_END(PROF_EXECUTE_WORKER); execute_active = FALSE; return -2; } VIS_PROFILE_START(PROF_CONVERT_INPUTS); for(i = 0; i < process_def->num_inputs; ++i) { DEBUGPRINTF("params[%d] = %X\n", i, params[i]); if(process_def->input_types[i] != ANY_TYPE && process_def->input_types[i] != params[i]->company->type_id) { DEBUGPRINTF("Input %d needs conversion from %d to %d\n", i, params[i]->company->type_id, process_def->input_types[i]); converter = find_converter_method(process_def->input_types[i], params[i]->company->type_id, process_def->program); if(!converter) { if(worker_entry.instance) { ERRORPRINTF("Error: Needed conversion from %s to %s for input %d of %s in worker %s\n", params[i]->company->name, process_def->program->companylist[process_def->input_types[i]].name, i, process_def->name, worker_entry.instance->def->name); print_stack_trace(worker_entry.instance); } else { DEBUGPRINTF("Error: Needed conversion from %s to %s for input %d of %s\n", params[i]->company->name, process_def->program->companylist[process_def->input_types[i]].name, i, process_def->name); printf("Error: Needed conversion from %s to %s for input %d of %s", params[i]->company->name, process_def->program->companylist[process_def->input_types[i]].name, i, process_def->name); } execute_active = FALSE; VIS_PROFILE_END(PROF_PROCESS_WORKER); return -3; } ((worker_impl)(converter->implement_func))(params+i, &worker_entry); } } VIS_PROFILE_END(PROF_CONVERT_INPUTS); if(process_def->type & USER_FLAG) { VIS_PROFILE_START(PROF_EXECUTE_CUSTOM); // init_custom_worker_type(worker_entry.worker_num, worker_entry.instance, process_def, callback, data, params, type); VIS_PROFILE_END(PROF_EXECUTE_CUSTOM); VIS_PROFILE_END(PROF_PROCESS_WORKER); VIS_PROFILE_END(PROF_EXECUTE_WORKER); return 1; } else { VIS_PROFILE_START(PROF_EXECUTE_BUILTIN); //DEBUGPRINTF("%s: before deflist[%d].implement_func: %X. vis_append: %X vis_print: %X\n",def->implement_func->workerlist[aworker].name, def->implement_func->workerlist[aworker].value_index, (int)deflist[def->implement_func->workerlist[aworker].value_index].implement_func, (int)vis_append, (int)vis_print); #ifdef USER_PROFILE QueryPerformanceCounter(&start); #endif returnval = ((worker_impl)(process_def->implement_func))(params, &worker_entry); #ifdef USER_PROFILE if(!returnval) { QueryPerformanceCounter(&end); duration.QuadPart = end.QuadPart - start.QuadPart; VIS_EnterCriticalSection(process_def->lock); process_def->total.QuadPart += duration.QuadPart; ++process_def->count; if(duration.QuadPart > process_def->worst.QuadPart) process_def->worst.QuadPart = duration.QuadPart; VIS_LeaveCriticalSection(process_def->lock); } #endif //DEBUGPUTS("Builtin worker returned\n"); VIS_PROFILE_END(PROF_EXECUTE_BUILTIN); return returnval; } } void wait_callback(worker_instance * caller_instance, int caller_workerenum, worker_instance * done_instance, void * data) { int i; def_done * done = (def_done *)data; //DEBUGPUTS("begin wait_callback\n"); for(i = 0; i < done_instance->def->num_outputs; ++i) done->params[i] = NULL; for(i = 0; i < done_instance->def->implement_func->num_workers; ++i) { if(done_instance->def->implement_func->workerlist[i].type == 4) { if(!(done->params[done_instance->def->implement_func->workerlist[i].io_num])) { done->params[done_instance->def->implement_func->workerlist[i].io_num] = done_instance->workerlist[i].value; done_instance->workerlist[i].value = NULL; } } } //DEBUGPUTS("Before EnterCritical\n"); VIS_EnterCriticalSection(done->lock); done->done_flag = TRUE; VIS_LeaveCriticalSection(done->lock); //DEBUGPUTS("After EnterCritical\n"); } BOOL execute_def_wait(worker_def * def, datum ** params) { int val; def_done done; queue_entry entry; entry.worker_num = 0; entry.instance = NULL; VIS_InitializeCriticalSection(done.lock); done.done_flag = FALSE; done.params = params; val = execute_def_data(def, entry, params, wait_callback, &done); if(val == 0) return TRUE; else if (val < 0) return FALSE; while(1) { VIS_EnterCriticalSection(done.lock); if(done.done_flag) { VIS_DeleteCriticalSection(done.lock); break; } VIS_LeaveCriticalSection(done.lock); #if COMPILE_THREADS > 1 #ifdef WIN32 Sleep(0); #else sleep(0); #endif #endif } return TRUE; } int process_worker(queue_entry worker_entry) { //datum * paramstore[32]; datum ** params;// = paramstore; int i, j, start=0; global_store * store; char * varname; datum * varname_dat; datum * tempvalindex, *todelete; int got_params=0; int aworker = worker_entry.worker_num; worker_instance * instance = worker_entry.instance; worker_def * def = instance->def; worker_def * process_def; worker_def * temp_def; worker_def * converter; int returnval = 0; short const_type; char * last; VIS_PROFILE_START(PROF_PROCESS_WORKER); DEBUGPRINTF( "Processing worker %d with %d inputs and %d outputs\n", aworker,def->implement_func->workerlist[aworker].num_inputs, def->implement_func->workerlist[aworker].num_outputs); /*VIS_EnterCriticalSection(instance->workerlist[aworker].worker_lock); for(i = 0; i < def->implement_func->workerlist[aworker].num_inputs; ++i) { params[i] = instance->workerlist[aworker].params[i+1]; DEBUGPRINTF("params[%d] = %X\n", i, params[i]); instance->workerlist[aworker].params[i+1] = NULL; }*/ if(def->implement_func->workerlist[aworker].null_input) { //DEBUGPUTS("About to call release_ref\n"); release_ref(instance->workerlist[aworker].params[0]); instance->workerlist[aworker].params[0] = NULL; } //VIS_LeaveCriticalSection(instance->workerlist[aworker].worker_lock); //DEBUGPRINTF("Param check complete. returnval: %d, start: %d\n", returnval, start); params = instance->workerlist[aworker].params+1; if(def->implement_func->workerlist[aworker].type == WORKER || def->implement_func->workerlist[aworker].type == TAIL_RECURSE || def->implement_func->workerlist[aworker].type == TAIL_CALL)//Worker { VIS_PROFILE_START(PROF_EXECUTE_WORKER); //DEBUGPUTS("Worker\n"); process_def = (worker_def *)(def->implement_func->workerlist[aworker].value_index); //DEBUGPUTS("Got process_def\n"); DEBUGPRINTF("process_def->type: %X, type & TYPE_MASK: %X\n", process_def->type, (process_def->type & TYPE_MASK)); returnval = execute_def_type(process_def, worker_entry, params, sub_callback, NULL, def->implement_func->workerlist[aworker].type); DEBUGPRINTF("execute_def returned %d\n", returnval); if(returnval != 0) { VIS_PROFILE_END(PROF_PROCESS_WORKER); VIS_PROFILE_END(PROF_EXECUTE_WORKER); return returnval; } //DEBUGPRINTF("params[0] after execute_def: %X\n", params[0]); //DEBUGPUTS("Before process_outputs\n"); process_outputs(params, aworker, instance); //DEBUGPUTS("After process_outputs\n"); VIS_PROFILE_END(PROF_EXECUTE_WORKER); } else if(def->implement_func->workerlist[aworker].type == GET_GLOBAL) { varname = def->implement_func->workerlist[aworker].name + def->implement_func->workerlist[aworker].io_num; varname_dat = make_string(varname, -1, def->program); if(def->implement_func->workerlist[aworker].value_index < 0) { for(i = 0; i < instance->trans->num_stores; ++i) { VIS_EnterCriticalSection(instance->trans->stores[i].lock); params[0] = add_ref(instance->trans->stores[i].instance_data); VIS_LeaveCriticalSection(instance->trans->stores[i].lock); params[1] = add_ref(varname_dat); vis_dict_index(params, NULL); if(params[0]) { def->implement_func->workerlist[aworker].value_index = i; break; } } if(def->implement_func->workerlist[aworker].value_index < 0) { printf("Error: Variable %s not found in any global stores used by worker %s\n", varname, def->name); DEBUGPRINTF("Error: Variable %s not found in any global stores used by worker %s\n", varname, def->name); execute_active = FALSE; return -1; } } else { VIS_EnterCriticalSection(instance->trans->stores[(int)def->implement_func->workerlist[aworker].value_index].lock); params[0] = add_ref(instance->trans->stores[(int)def->implement_func->workerlist[aworker].value_index].instance_data); VIS_LeaveCriticalSection(instance->trans->stores[(int)def->implement_func->workerlist[aworker].value_index].lock); params[1] = varname_dat; vis_dict_index(params, NULL); if(!params[0]) { printf("Error: Global variable %s not found in worker %s\n", def->implement_func->workerlist[aworker].name, def->name); DEBUGPRINTF("Error: Global variable %s not found in worker %s\n", def->implement_func->workerlist[aworker].name, def->name); execute_active = FALSE; return -1; } } process_outputs(params, aworker, instance); } else if(def->implement_func->workerlist[aworker].type == SET_GLOBAL) { varname = def->implement_func->workerlist[aworker].name + def->implement_func->workerlist[aworker].io_num; varname_dat = make_string(varname, -1, def->program); params[2] = params[0]; params[1] = varname_dat; VIS_EnterCriticalSection(instance->trans->stores[(int)def->implement_func->workerlist[aworker].value_index].lock); //no add_ref here because we'll be replacing instance_data with the result of vis_dict set params[0] = instance->trans->stores[(int)def->implement_func->workerlist[aworker].value_index].instance_data; vis_dict_set(params, NULL); instance->trans->stores[(int)def->implement_func->workerlist[aworker].value_index].instance_data = params[0]; VIS_LeaveCriticalSection(instance->trans->stores[(int)def->implement_func->workerlist[aworker].value_index].lock); //no outputs to process } else if(def->implement_func->workerlist[aworker].type == GET_COMP) { returnval = get_comp_room_by_name(params, def->implement_func->workerlist[aworker].name, NULL, &worker_entry, def->program); if(returnval) return returnval; process_outputs(params, aworker, instance); } else if(def->implement_func->workerlist[aworker].type == SET_COMP) { returnval = set_comp_room_by_name(params, def->implement_func->workerlist[aworker].name, NULL, &worker_entry, def->program); if(returnval) return returnval; process_outputs(params, aworker, instance); } else//Variable { VIS_PROFILE_START(PROF_EXECUTE_OTHER); if(def->implement_func->workerlist[aworker].num_inputs > 0 || def->implement_func->workerlist[aworker].type == INPUT) //Is this a Room or a constant? { todelete = NULL; VIS_EnterCriticalSection(instance->workerlist[aworker].worker_lock); if(def->implement_func->workerlist[aworker].type == OUTPUT) { todelete = instance->workerlist[aworker].value; instance->workerlist[aworker].value = params[0]; DEBUGPRINTF("Setting room/output at pos %d to %X in instance %X\n", aworker, params[0], instance); } //tempvalindex = instance->workerlist[aworker].value; VIS_LeaveCriticalSection(instance->workerlist[aworker].worker_lock); if(def->implement_func->workerlist[aworker].type == INPUT) { params[0] = instance->workerlist[aworker].value; instance->workerlist[aworker].value = NULL; } if(todelete) release_ref(todelete); if(def->implement_func->workerlist[aworker].num_outputs) { //add_ref(tempvalindex); process_outputs(params/*&tempvalindex*/, aworker, instance); } } else { //Hmm, do I potentially need another lock here? /*if(!(instance->def->implement_func->workerlist[aworker].value_index)) { instance->def->implement_func->workerlist[aworker].value_index = (int)(tempvalindex=get_constant(def->implement_func->workerlist[aworker].name,-1));//(int)tempvalindex; } else*/ tempvalindex = (datum *)instance->def->implement_func->workerlist[aworker].value_index; add_ref(tempvalindex); process_outputs(&tempvalindex, aworker, instance); } VIS_PROFILE_END(PROF_EXECUTE_OTHER); } VIS_PROFILE_END(PROF_PROCESS_WORKER); return returnval; } #define OPT_RESULT 0 #define OPT_CUST_RESULT 0x10000000 #define OPT_CONST 0x20000000 #define OPT_INPUT 0x30000000 int find_input_worker(custom_worker * cust, int aworker, int input, int *ret_output) { int o, p, wire_count; int out_worker; o = cust->workerlist[aworker].wire_up_lookup; wire_count = 0; while(cust->wirelist[p=cust->workers_to_wires_up[o]].end_worker == aworker && p >= 0) { if(cust->wirelist[p].input_num == input) { ++wire_count; out_worker = cust->wirelist[p].start_worker; DEBUGPRINTF("Input %d attached to %s(%d)\n", input, cust->workerlist[out_worker].name, out_worker); if(ret_output) *ret_output = cust->wirelist[p].output_num; } ++o; } DEBUGPRINTF("wire_count: %d\n", wire_count); if(wire_count == 1) return out_worker; return -1; } int make_input_code(custom_worker * cust, BOOL * in_opt, int * pos_in_opt, int source_worker, int output_num, int index, opt_entry * opts, int * branch_flags, opt_entry ** branch_refs, int input_num, program * prog) { /*if(in_opt[source_worker]) { if(prog->deflist[cust->workerlist[source_worker].value_index].type & USER_FLAG) { return OPT_CUST_RESULT | ((pos_in_opt[source_worker] & 0xFFFF) << 8) | (output_num & 0xFF); } else { if(strcmp(prog->deflist[cust->workerlist[source_worker].value_index].name, "If") == 0) { if(output_num == 0) { branch_flags[index] = 1; if(opts[pos_in_opt[source_worker]].branch1 <= index) opts[pos_in_opt[source_worker]].branch1 = index+1; } else { branch_flags[index] = 2; if(opts[pos_in_opt[source_worker]].branch2 <= index) opts[pos_in_opt[source_worker]].branch2 = index+1; } branch_refs[index] = opts + pos_in_opt[source_worker]; } else if(branch_flags[pos_in_opt[source_worker]]) { if(branch_flags[pos_in_opt[source_worker]] == 1) { branch_refs[pos_in_opt[source_worker]]->branch1 = index + 1; branch_flags[index] = 1; } else { branch_refs[pos_in_opt[source_worker]]->branch1 = index + 2; branch_flags[index] = 2; } branch_refs[index] = branch_refs[pos_in_opt[source_worker]]; } else branch_flags[index] = 0; if(input_num >= 0) ++opts[pos_in_opt[source_worker]].output_refs[output_num]; DEBUGPRINTF("OPT_RESULT: opt_num: %d, output_num: %d\n", pos_in_opt[source_worker], output_num); return OPT_RESULT | ((pos_in_opt[source_worker] & 0xFFFF) << 8) | (output_num & 0xFF); } } else if(cust->workerlist[source_worker].type == CONSTANT) { branch_flags[index] = 0; DEBUGPRINTF("OPT_CONST: %d\n", source_worker); return OPT_CONST | source_worker; } else if(cust->workerlist[source_worker].type == INPUT) { branch_flags[index] = 0; DEBUGPRINTF("OPT_INPUT: %d\n", cust->workerlist[source_worker].io_num); return OPT_INPUT | cust->workerlist[source_worker].io_num; }*/ return -1; } void optimize(worker_def * def) { /* int i,j,k,m,o,p; int * const_in; int num_entries = 0; int aworker; int adjust; int source_worker; int source_output; int source_null; int null_output; int wire_count; int * input_data; int current_null; int cust_result_count; int new_start; custom_worker * cust = def->implement_func; int start_current, end_current, new_current; worker_def * deflist = def->program->deflist; opt_entry * output = malloc(sizeof(opt_entry) * def->implement_func->num_workers); BOOL * in_opt = malloc(sizeof(BOOL) * cust->num_workers); int * branch_flags = malloc(sizeof(int) * cust->num_workers); opt_entry ** branch_refs = malloc(sizeof(int) * cust->num_workers); //BOOL * real_in_opt = malloc(sizeof(BOOL) * cust->num_workers); int * pos_in_opt = malloc(sizeof(int) * cust->num_workers); DEBUGPRINTF("deflist: %X\n", deflist); for(i = 0; i < cust->num_workers; ++i) { branch_flags[i] = 0; DEBUGPRINTF("%d: No input pass\n", i); DEBUGPRINTF("Examining: %s\n", cust->workerlist[i].name); if(cust->workerlist[i].num_inputs == 0 && !cust->workerlist[i].null_input && cust->workerlist[i].type == WORKER) { output[num_entries].def = deflist + cust->workerlist[i].value_index; DEBUGPRINTF("Set output[%d].def = %X\n", num_entries, output[num_entries].def); DEBUGPRINTF("opt: %d is %s\n\n", num_entries, cust->workerlist[i].name); output[num_entries].original_pos = i; output[num_entries].input_data = NULL; if(cust->workerlist[i].num_outputs) { output[num_entries].output_refs = malloc(sizeof(int)*cust->workerlist[i].num_outputs); for(j = 0; j < cust->workerlist[i].num_outputs; ++j) output[num_entries].output_refs[j] = 0; } else output[num_entries].output_refs = NULL; output[num_entries].branch1 = output[num_entries].branch2 = -1; //if(!(deflist[cust->workerlist[i].value_index].type & USER_FLAG)) //{ in_opt[i] = TRUE; pos_in_opt[i] = num_entries; //} //real_in_opt[i] = TRUE; ++num_entries; } else { //real_in_opt[i] = FALSE; in_opt[i] = FALSE; } } start_current = num_entries; for(i = 0; i < cust->num_workers; ++i) { DEBUGPRINTF("%d: Second pass\n", i); if(cust->workerlist[i].num_inputs == 0 && !cust->workerlist[i].null_input) { j = cust->workerlist[i].wire_down_lookup; while(cust->wirelist[k=cust->workers_to_wires_down[j]].start_worker == i && k >= 0) { aworker = cust->wirelist[k].end_worker; if(!in_opt[aworker]) { DEBUGPRINTF("Examining: %s(%d)\n", cust->workerlist[aworker].name, aworker); if(cust->workerlist[i].null_input) adjust = 1; else adjust = 0; input_data = malloc(sizeof(int)* (cust->workerlist[aworker].num_inputs+adjust)); for(m = (0-adjust); m < cust->workerlist[aworker].num_inputs; ++m) { DEBUGPRINTF("Input: %d\n", m); source_worker = find_input_worker(cust, aworker, m, &source_output); DEBUGPRINTF("source_worker: %d\n", source_worker); if(source_worker == -1) break; source_worker = make_input_code(cust, in_opt, pos_in_opt, source_worker, source_output, num_entries, output, branch_flags, branch_refs, m, def->program); DEBUGPRINTF("input code: %X\n", source_worker); if(source_worker == -1) break; input_data[m+adjust] = source_worker; if(source_worker == -1) break; } if(source_worker == -1) free(input_data); else { if(cust->workerlist[aworker].type == OUTPUT) output[num_entries].def = NULL; else output[num_entries].def = deflist + cust->workerlist[aworker].value_index; DEBUGPRINTF("Set output[%d].def = %X\n", num_entries, output[num_entries].def); DEBUGPRINTF("opt: %d is %s\n\n", num_entries, cust->workerlist[aworker].name); output[num_entries].original_pos = aworker; output[num_entries].input_data = input_data; output[num_entries].null_inputs = adjust; output[num_entries].branch1 = output[num_entries].branch2 = -1; if(cust->workerlist[aworker].num_outputs) { output[num_entries].output_refs = malloc(sizeof(int)*cust->workerlist[aworker].num_outputs); for(m = 0; m < cust->workerlist[aworker].num_outputs; ++m) output[num_entries].output_refs[m] = 0; } else output[num_entries].output_refs = NULL; //if(cust->workerlist[aworker].type != OUTPUT && !(deflist[cust->workerlist[aworker].value_index].type & USER_FLAG)) //{ in_opt[aworker] = TRUE; pos_in_opt[aworker] = num_entries; //} //real_in_opt[aworker] = TRUE; ++num_entries; } } ++j; } } } DEBUGPUTS("Before While\n"); end_current = num_entries; while(start_current != end_current) { DEBUGPRINTF("start_current: %d, end_current: %d\n", start_current, end_current); new_start = num_entries; for(i = start_current; i < end_current; ++i) { DEBUGPRINTF("opt: %d, def: %X, name: %s\n", i, output[i].def, cust->workerlist[output[i].original_pos].name); j = cust->workerlist[output[i].original_pos].wire_down_lookup; DEBUGPRINTF("wire_down_lookup: %d\n", j); while(cust->wirelist[k=cust->workers_to_wires_down[j]].start_worker == output[i].original_pos && k >= 0) { DEBUGPRINTF("Wire %d is attached to worker %d output %d and worker %d input %d\n", k, cust->wirelist[k].start_worker, cust->wirelist[k].output_num, cust->wirelist[k].end_worker, cust->wirelist[k].input_num); aworker = cust->wirelist[k].end_worker; //FIXME: Only works if constant/input attached to only one destination if(cust->workerlist[aworker].type == CONSTANT || cust->workerlist[aworker].type == INPUT) { DEBUGPRINTF("Worker is of type %d, ", cust->workerlist[aworker].type); aworker = cust->wirelist[cust->workers_to_wires_down[cust->workerlist[aworker].wire_down_lookup]].end_worker; DEBUGPRINTF("reruting to worker %d\n", aworker); } if(!in_opt[aworker]) { DEBUGPRINTF("Examining: %s(%d)\n", cust->workerlist[aworker].name, aworker); if(cust->workerlist[i].null_input) adjust = 1; else adjust = 0; for(m = (0-adjust); m < cust->workerlist[aworker].num_inputs; ++m) { source_worker = find_input_worker(cust, aworker, m, &source_output); if(source_worker == -1) break; if(cust->workerlist[source_worker].null_input && cust->workerlist[source_worker].type != WORKER) ++adjust; } if(source_worker != -1) { current_null = 0; input_data = malloc(sizeof(int)* (cust->workerlist[aworker].num_inputs+adjust)); cust_result_count = 0; for(m = (cust->workerlist[i].null_input ? -1 : 0); m < cust->workerlist[aworker].num_inputs; ++m) { DEBUGPRINTF("Input: %d\n", m); source_worker = find_input_worker(cust, aworker, m, &source_output); if(cust->workerlist[source_worker].null_input && cust->workerlist[source_worker].type != WORKER) { source_null = find_input_worker(cust, source_worker, -1, &null_output); if(source_null == -1) { source_worker = -1; break; } source_null = make_input_code(cust, in_opt, pos_in_opt, source_null, null_output, num_entries, output, branch_flags, branch_refs,-2, def->program); if((source_null & 0xF0000000) == OPT_CUST_RESULT) ++cust_result_count; if(source_null == -1) { source_worker = -1; break; } input_data[current_null++] = source_null; } DEBUGPRINTF("source_worker: %d\n", source_worker); source_worker = make_input_code(cust, in_opt, pos_in_opt, source_worker, source_output, num_entries, output, branch_flags, branch_refs, m, def->program); if((source_worker & 0xF0000000) == OPT_CUST_RESULT) ++cust_result_count; DEBUGPRINTF("input code: %d\n", source_worker); if(cust_result_count >= (cust->workerlist[aworker].num_inputs + adjust)) source_worker = -1; if(source_worker == -1) break; input_data[m+adjust] = source_worker; } if(source_worker == -1) free(input_data); else { if(cust->workerlist[aworker].type == OUTPUT) output[num_entries].def = NULL; else output[num_entries].def = deflist + cust->workerlist[aworker].value_index; DEBUGPRINTF("Set output[%d].def = %X\n", num_entries, output[num_entries].def); DEBUGPRINTF("opt: %d is %s\n\n", num_entries, cust->workerlist[aworker].name); output[num_entries].original_pos = aworker; output[num_entries].input_data = input_data; output[num_entries].null_inputs = adjust; output[num_entries].branch1 = output[num_entries].branch2 = -1; if(cust->workerlist[aworker].num_outputs) { output[num_entries].output_refs = malloc(sizeof(int)*cust->workerlist[aworker].num_outputs); for(m = 0; m < cust->workerlist[aworker].num_outputs; ++m) output[num_entries].output_refs[m] = 0; } else output[num_entries].output_refs = NULL; //if(cust->workerlist[aworker].type != OUTPUT && !(deflist[cust->workerlist[aworker].value_index].type & USER_FLAG)) //{ in_opt[aworker] = TRUE; pos_in_opt[aworker] = num_entries; //} //real_in_opt[aworker] = TRUE; ++num_entries; } } } ++j; } } start_current = new_start; end_current = num_entries; } def->optimized = output; def->opt_count = num_entries; DEBUGPUTS("optimize done\n\n\n"); */ } void run_optimized(worker_instance * instance, datum ** params) { int i = 0,j,k; unsigned short output, opt_num; datum * this_params[32]; queue_entry entry; datum * val; BOOL skip; BOOL partial_flag; BOOL continue_flag; int count; int ready; int jump_from = -1; int jump_to = -1; int tmp, addnum; opt_entry * exec_list = instance->def->optimized; datum ** results = instance->opt_results;//malloc(sizeof(datum *) * instance->def->opt_count * 32); VIS_PROFILE_START(PROF_RUN_OPT); entry.instance = instance; for(i = 0; i < instance->def->opt_count; ++i) { VIS_PROFILE_START(PROF_OPT_LOOP); skip = FALSE; partial_flag = FALSE; continue_flag = FALSE; DEBUGPRINTF("\nPeparing exec_list[%d]\n", i); if(exec_list[i].def) { DEBUGPRINTF("Name: %s\n", exec_list[i].def->name); count = exec_list[i].def->num_inputs; } else count = 1; count += exec_list[i].null_inputs; //DEBUGPRINTF("Input count: %d\n", count); if(count && !exec_list[i].input_data) puts("Runtime Error: input data is NULL\n"); //DEBUGPRINTF("input_data: %X\n", exec_list[i].input_data); VIS_PROFILE_START(PROF_OPT_PREP_INPUT); for(j = 0; j < count; ++j) { val = NULL; continue_flag = FALSE; switch(exec_list[i].input_data[j] & 0xF0000000) { case OPT_RESULT: output = exec_list[i].input_data[j] & 0xFF; opt_num = (exec_list[i].input_data[j] >> 8)& 0xFFFF; DEBUGPRINTF("OPT_RESULT for input %d, opt_num: %d, output: %d\n", j, opt_num, output); val = results[(opt_num * 32) | output]; break; case OPT_CUST_RESULT: val = NULL; partial_flag = TRUE; continue_flag = TRUE; break; case OPT_INPUT: DEBUGPRINTF("OPT_INPUT for input %d\n", j); val = add_ref(params[exec_list[i].input_data[j] & 0xFF]); break; case OPT_CONST: DEBUGPRINTF("OPT_CONST for input %d\n", j); val = add_ref((datum *)(instance->def->implement_func->workerlist[exec_list[i].input_data[j] & 0xFFFFFF].value_index)); break; default: puts("Runtime Error: Invalid bytecode\n"); val = NULL; break; } if(!val && !continue_flag) { for(k = exec_list[i].null_inputs; k < j; ++k) release_ref(this_params[k]); skip = TRUE; break; } DEBUGPRINTF("this_params[%d] = %X\n", j, val); if(j >= exec_list[i].null_inputs) if(val) this_params[j] = /*add_ref(*/val/*)*/; else this_params[j] = NULL; } VIS_PROFILE_END(PROF_OPT_PREP_INPUT); if(!skip) { if(partial_flag) { VIS_PROFILE_START(PROF_PARTIAL_EXEC); ready = 0; for(j = exec_list[i].null_inputs; j < count; ++j) if(this_params[j]) { instance->workerlist[exec_list[i].original_pos].params[j-exec_list[i].null_inputs+1] = this_params[j]; ++ready; } if(instance->def->implement_func->workerlist[exec_list[i].original_pos].null_input && this_params[exec_list[i].null_inputs-1]) ++ready; DEBUGPRINTF("ready: %d\n", ready); skip = TRUE; VIS_EnterCriticalSection(instance->workerlist[exec_list[i].original_pos].worker_lock); instance->workerlist[exec_list[i].original_pos].ready_count += ready; if(instance->workerlist[exec_list[i].original_pos].ready_count >= (exec_list[i].def->num_inputs + (instance->def->implement_func->workerlist[exec_list[i].original_pos].null_input ? 1 : 0))) { skip = FALSE; instance->workerlist[exec_list[i].original_pos].ready_count = 0; } DEBUGPRINTF("ready_count: %d\n", instance->workerlist[exec_list[i].original_pos].ready_count); VIS_LeaveCriticalSection(instance->workerlist[exec_list[i].original_pos].worker_lock); if(!skip) add_queue(exec_list[i].original_pos, instance); VIS_PROFILE_END(PROF_PARTIAL_EXEC); } else if(exec_list[i].def) { VIS_PROFILE_START(PROF_FULL_EXEC); DEBUGPRINTF("opt_exec: %s(%d)\n", exec_list[i].def->name, exec_list[i].original_pos); entry.worker_num = exec_list[i].original_pos; if(exec_list[i].def->type & USER_FLAG) { VIS_PROFILE_START(PROF_OPT_EXEC_USER); instance->workerlist[exec_list[i].original_pos].params[0] = NULL; memcpy(instance->workerlist[exec_list[i].original_pos].params+1, this_params + exec_list[i].null_inputs, sizeof(datum *) * exec_list[i].def->num_inputs); add_queue(exec_list[i].original_pos, instance); VIS_PROFILE_END(PROF_OPT_EXEC_USER); } else { VIS_PROFILE_START(PROF_OPT_EXEC_BUILT); if(execute_def(exec_list[i].def, entry, this_params + exec_list[i].null_inputs, sub_callback) == 0) { DEBUGPUTS("Exectuted with reslts\n"); if(exec_list[i].output_refs) { for(j = exec_list[i].null_inputs; j < (exec_list[i].def->num_outputs+exec_list[i].null_inputs); ++j) { DEBUGPRINTF("output_refs[%d] = %d\n", j-exec_list[i].null_inputs, exec_list[i].output_refs[j-exec_list[i].null_inputs]); if(!exec_list[i].output_refs[j-exec_list[i].null_inputs]) release_ref(this_params[j]); else if(exec_list[i].output_refs[j-exec_list[i].null_inputs] > 1) { /*DEBUGPRINTF("multi_add_ref(%X): %d\n", this_params[j], exec_list[i].output_refs[j-exec_list[i].null_inputs]-1); tmp = (int)(&(this_params[j]->ref_count)); addnum = exec_list[i].output_refs[j-exec_list[i].null_inputs]-1; __asm { mov ebx, tmp mov eax, addnum lock xadd dword ptr [ebx], eax }*/ VIS_EnterCriticalSection(this_params[j]->lock); this_params[j]->ref_count += exec_list[i].output_refs[j-exec_list[i].null_inputs]-1; VIS_LeaveCriticalSection(this_params[j]->lock); } } memcpy(results + i*32, this_params + exec_list[i].null_inputs, sizeof(datum *) * exec_list[i].def->num_outputs); if(exec_list[i].branch1 >= 0) { if(this_params[exec_list[i].null_inputs]) { jump_from = exec_list[i].branch1; jump_to = exec_list[i].branch2; } else { i = exec_list[i].branch1-1; } } } } /*else { for(j = exec_list[i].null_inputs; j < (exec_list[i].def->num_outputs + exec_list[i].null_inputs); ++j) results[(i*32)|j] = NULL; }*/ VIS_PROFILE_END(PROF_OPT_EXEC_BUILT); } VIS_PROFILE_END(PROF_FULL_EXEC); DEBUGPUTS("Executed\n"); } else instance->workerlist[exec_list[i].original_pos].value = this_params[exec_list[i].null_inputs]; } else { DEBUGPUTS("Skipped\n"); if(exec_list[i].def) { for(j = 0; j < exec_list[i].def->num_outputs; ++j) results[(i*32)|j] = NULL; } } if(jump_from >= 0 && (i+1) == jump_from) { i = jump_to-1; jump_from = -1; } VIS_PROFILE_END(PROF_OPT_LOOP); } DEBUGPUTS("run_optimized calling cleanup_check\n"); for(i = 0; i < instance->def->num_inputs; ++i) release_ref(params[i]); cleanup_check(entry); VIS_PROFILE_END(PROF_RUN_OPT); } int vis_print(datum ** inputlist, queue_entry * worker_entry) { int result; #ifdef CONSOLE puts((char *)inputlist[0]->c.generic.data); #else MessageBox(NULL, (char *)inputlist[0]->c.generic.data, "Visuality Output", MB_OK); #endif result = 1; release_ref(inputlist[0]); inputlist[0] = new_datum(BUILTIN_TYPE_YESNO, 2, 0, worker_entry->instance->def->program); //No one else knows about this new datum yet so we can skip getting a lock datum_set_yesno(inputlist[0], result); return 0; } int unix_time(datum ** inputlist, queue_entry * worker_entry) { inputlist[0] = new_datum(BUILTIN_TYPE_WHOLE, 2, 0, worker_entry->instance->def->program); inputlist[0]->c.integers.num_a = time(NULL); return 0; } int vis_end(datum ** inputlist, queue_entry * worker_entry) { // fprintf(outfile, "End worker reached.\n"); execute_active=FALSE; release_ref(inputlist[0]); //interp_stop(); return 0; } #ifdef NINTENDO_DS const char keyLetters[15] = "ABESRLUD><XYMC"; #define MAX_KEY_BITS 14 #endif int vis_getinput(datum ** inputlist, queue_entry * worker_entry) { #ifdef NINTENDO_DS int held,i,pos; char tempstring[14]; scanKeys(); held = keysHeld(); if(held) { pos = 0; for(i = 0; i < MAX_KEY_BITS; ++i) if(held & (1 << i)) tempstring[pos++] = keyLetters[i]; inputlist[0] = new_datum(BUILTIN_TYPE_STRING, 1, pos+1, worker_entry->instance->def->program); memcpy(inputlist[0]->c.generic.data, tempstring, pos); ((char *)inputlist[0]->c.generic.data)[pos]='\0'; return 0; } else { requeue(worker_entry->worker_num, worker_entry->instance); return 1; } #else #ifdef CONSOLE gets(text_buf); text_buf_size = strlen(text_buf); //Nasty hack for testing until I get around to supporting command line args propery //text_buf_size = strlen(global_argv[1]); #else while(text_buf_size <= 0) { Sleep(30); //TODO: replace with I/O queue mechanism } #endif // VIS_EnterCriticalSection(text_buf_lock); DEBUGPRINTF("Allocating %d bytes\n", text_buf_size+1); inputlist[0] = new_datum(BUILTIN_TYPE_STRING, 1, text_buf_size+1, worker_entry->instance->def->program); DEBUGPUTS("Allocated datum.\n"); memcpy(inputlist[0]->c.generic.data, text_buf, text_buf_size); DEBUGPUTS("Copied string.\n"); ((char *)inputlist[0]->c.generic.data)[text_buf_size]='\0'; DEBUGPRINTF("Input is %s\n", inputlist[0]->c.generic.data); text_buf_size = 0; // VIS_LeaveCriticalSection(text_buf_lock); return 0; #endif } int vis_if(datum ** inputlist, queue_entry * worker_entry) { if(!(inputlist[0]->c.integers.num_a)) { inputlist[1] = inputlist[0]; inputlist[0] = NULL; } else inputlist[1] = NULL; return 0; } int vis_build(datum ** inputlist, queue_entry * worker_entry) { int i,j; company * companylist = worker_entry->instance->def->program->companylist; int num_companies = worker_entry->instance->def->program->num_companies; DEBUGPRINTF("Looking for company named %s\n", inputlist[0]->c.generic.data); for(i = 0; i < num_companies; ++i) { DEBUGPRINTF("Checking company %d:%s\n", i, companylist[i].name); if(!strcmp(inputlist[0]->c.generic.data, companylist[i].name)) break; } release_ref(inputlist[0]); if(i < num_companies && companylist[i].build_size > 0) { DEBUGPRINTF("Building company with size %d\n", companylist[i].build_size); inputlist[0] = new_datum(i, 1, companylist[i].build_size, worker_entry->instance->def->program); for(j = 0; j < companylist[i].build_size; ++j) ((char*)(inputlist[0]->c.generic.data))[j] = 0; } else { DEBUGPUTS("Could not find company\n"); inputlist[0] = NULL; } return 0; } int vis_wait_forever(datum ** inputlist, queue_entry * worker_entry) { return 1; } int init_global_store(datum ** inputlist, queue_entry * worker_entry) { datum * params[3]; global_store * store; datum * store_dat = new_datum(BUILTIN_TYPE_GLOBAL_STORE, 1, sizeof(global_store), worker_entry->instance->def->program); store = store_dat->c.generic.data; store->name = add_ref(inputlist[0]); store->data = create_dict(worker_entry->instance->def->program); VIS_EnterCriticalSection(global_store_lock); params[0] = global_store_dict; params[1] = inputlist[0]; params[2] = store_dat; vis_dict_set(params, NULL); global_store_dict = params[0]; DEBUGPUTS("Global store init complete\n"); VIS_LeaveCriticalSection(global_store_lock); DEBUGPUTS("Released global_store_lock\n"); inputlist[0] = NULL; return 0; } int vis_type_of(datum ** inputlist, queue_entry * worker_entry) { datum * output = make_string(inputlist[0]->company->name, -1, worker_entry->instance->def->program); release_ref(inputlist[0]); inputlist[0] = output; return 0; } int vis_random(datum ** inputlist, queue_entry * worker_entry) { inputlist[0] = new_datum(BUILTIN_TYPE_WHOLE, 2, 0, worker_entry->instance->def->program); VIS_EnterCriticalSection(randlock); inputlist[0]->c.integers.num_a = genrand_int32(); VIS_LeaveCriticalSection(randlock); return 0; }