inline dj_global_id dj_vm_resolveRuntimeClass(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;
		PRINTF("Comparing with infusion %d having base id %d\n",dj_vm_getInfusionId(dj_exec_getVM(), infusion), 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
	printf("error: class not found: %d\n", id);
    // dead code to make compiler happy
    ret.entity_id=255;
    ret.infusion=NULL;
    return ret;
}
Exemple #2
0
/**
 * Unloads an infusion. Make sure you check whether it's safe to do so using dj_vm_safeToUnload! If you
 * unload an infusion that another infusion depends on you'll leave the VM in an undefined state. Also,
 * a kitten will die.
 * @param vm the virtual machine context
 * @param unloadInfusion the infusion to unload
 */
void dj_vm_unloadInfusion(dj_vm *vm, dj_infusion * unloadInfusion)
{
	dj_thread * thread;
	dj_frame * frame;
	dj_infusion * infusion;
	dj_infusion * prev;
	int index;

	// kill any thread that is currently executing any method in the infusion that we're unloading
	thread = vm->threads;
	while (thread!=NULL)
	{

		// check each frame
		frame = thread->frameStack;
		while (frame!=NULL)
		{
			if (frame->method.infusion==unloadInfusion)
			{
				// kill the thread
				thread->status = THREADSTATUS_FINISHED;

				break;
			}
			frame = frame->parent;
		}

		// next thread
		thread = thread->next;
	}

	// shift runtime IDs
	dj_mem_shiftRuntimeIDs(unloadInfusion->class_base, dj_di_parentElement_getListSize(unloadInfusion->classList));

	// update other infusions
	infusion = vm->infusions;
	while (infusion!=NULL)
	{
		if (infusion->class_base>unloadInfusion->class_base)
			infusion->class_base -= dj_di_parentElement_getListSize(unloadInfusion->classList);

		infusion = infusion->next;
	}

	prev = NULL;

	index = dj_vm_getInfusionId(vm, unloadInfusion);

	// remove the infusion from the list
	if (index==0)
	{
		vm->infusions = unloadInfusion->next;
	} else
	{
		prev = dj_vm_getInfusion(vm, index - 1);
		prev->next = unloadInfusion->next;
	}

}
Exemple #3
0
// 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;
}