/** * Adds an infusion to a virtual machine. * @param vm the virtual machine to add the infusion to * @param infusion the infusion to add */ void dj_vm_addInfusion(dj_vm *vm, dj_infusion *infusion) { dj_infusion *tail = vm->infusions; if (tail!=NULL) while (tail->next!=NULL) tail = tail->next; if (tail==NULL) { // list is empty, add as first element vm->infusions = infusion; infusion->class_base = CHUNKID_JAVA_START; } else { // add to the end of the list tail->next = infusion; infusion->class_base = tail->class_base + dj_di_parentElement_getListSize(tail->classList); } // the new infusion is the last element, // so its next should be NULL infusion->next = NULL; }
inline dj_global_id dj_vm_getRuntimeClass(dj_vm *vm, runtime_id_t id) { dj_global_id ret; dj_infusion *infusion = vm->infusions; runtime_id_t base = 0; // TODO: optimize this! (binary search?) // TODO: test for multiple loaded infusions while (infusion!=NULL) { base = infusion->class_base; if ((id>=base)&&(id<base + dj_di_parentElement_getListSize(infusion->classList))) { ret.infusion = infusion; ret.entity_id = id - base; return ret; } infusion = infusion->next; } // TODO raise error, class not found DEBUG_LOG("error: class not found: %d\n", id); DARJEELING_PRINTF("error: class not found: %d\n", id); #ifdef DARJEELING_DEBUG_FRAME dj_exec_debugCurrentFrame(); #endif dj_panic(DJ_PANIC_ILLEGAL_INTERNAL_STATE); // dead code to make compiler happy ret.entity_id=255; ret.infusion=NULL; return ret; }
// TODO niels clean up this function dj_infusion* dj_vm_runClassInitialisers(dj_vm *vm, dj_infusion *infusion) { int i, threadId; dj_thread * thread; dj_frame * frame; dj_global_id methodImplId; uint8_t infusionId; // store infusion ID so that we can get an up-to-date infusion pointer later infusionId = dj_vm_getInfusionId(vm, infusion); // create a new thread object to run the <CLINIT> methods in thread = dj_thread_create(); infusion = dj_vm_getInfusion(vm, infusionId); if (thread == NULL) { DARJEELING_PRINTF("Not enough space for class initializer in infusion %s\n", (char *) dj_di_header_getInfusionName(infusion->header)); dj_panic(DJ_PANIC_OUT_OF_MEMORY); } dj_vm_addThread(dj_exec_getVM(), thread); threadId = thread->id; // iterate over the class list and execute any class initialisers that are encountered int size = dj_di_parentElement_getListSize(infusion->classList); for (i=0; i<size; i++) { infusion = dj_vm_getInfusion(dj_exec_getVM(), infusionId); dj_di_pointer classDef = dj_di_parentElement_getChild(infusion->classList, i); methodImplId.entity_id = dj_di_classDefinition_getCLInit(classDef); methodImplId.infusion = infusion; if (methodImplId.entity_id!=255) { // create a frame to run the initialiser in methodImplId.infusion = infusion; frame = dj_frame_create(methodImplId); // if we're out of memory, panic if (frame==NULL) { DEBUG_LOG(DBG_DARJEELING, "dj_vm_runClassInitialisers: could not create frame. Panicking\n"); DARJEELING_PRINTF("Not enough space to create a frame\n"); dj_panic(DJ_PANIC_OUT_OF_MEMORY); } // the thread we're running the class initialisers in. thread = dj_vm_getThreadById(dj_exec_getVM(), threadId); thread->frameStack = frame; thread->status = THREADSTATUS_RUNNING; dj_exec_activate_thread(thread); // execute the method while (dj_vm_getThreadById(dj_exec_getVM(), threadId)->status!=THREADSTATUS_FINISHED) { // running the CLINIT method may trigger garbage collection dj_exec_run(RUNSIZE); } } } // clean up the thread thread = dj_vm_getThreadById(dj_exec_getVM(), threadId); dj_vm_removeThread(vm, thread); dj_thread_destroy(thread); vm->currentThread = NULL; return infusion; }