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(DBG_DARJEELING, "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; }
void dj_vm_loadInfusionArchive(dj_vm * vm, dj_di_pointer archive, dj_named_native_handler native_handlers[], unsigned char numHandlers) { for (uint8_t i=0; i<dj_archive_number_of_files(archive); i++) { dj_di_pointer file = dj_archive_get_file(archive, i); if (dj_archive_filetype(file) == FILETYPE_LIB_INFUSION) { dj_infusion * infusion = dj_vm_loadInfusion(vm, file, native_handlers, numHandlers); if (infusion == NULL) { DARJEELING_PRINTF("Not enough space to create the infusion nr %d in archive.\n", i); dj_panic(DJ_PANIC_OUT_OF_MEMORY); } } } }
void javax_wukong_wkpf_WKPF_void__init() { wkpf_markRootSetHook.function = wkpf_markRootSet; dj_hook_add(&dj_vm_markRootSetHook, &wkpf_markRootSetHook); wkpf_updatePointersHook.function = wkpf_updatePointers; dj_hook_add(&dj_mem_updateReferenceHook, &wkpf_updatePointersHook); wkpf_comm_handleMessageHook.function = wkpf_comm_handle_message; dj_hook_add(&wkcomm_handle_message_hook, &wkpf_comm_handleMessageHook); if (wkpf_native_wuclasses_init() != WKPF_OK) dj_panic(DJ_PANIC_OUT_OF_MEMORY); }
void dj_init() { //before anything starts, define global variables struct tossim_global_variables* global_variables = malloc(sizeof(struct tossim_global_variables)); struct tossim_UGLY_global_variables* UGLY_global_variables = malloc(sizeof(struct tossim_UGLY_global_variables)); setGlobalVariables(global_variables); setUglyGlobalVariables(UGLY_global_variables); dj_vm *vm; unsigned char *mem = malloc(HEAPSIZE); // initialise memory manager dj_mem_init(mem, HEAPSIZE); _global_ref_t_base_address = (char*)mem - 42; // initialise timer dj_timer_init(); // create a new VM vm = dj_vm_create(); if (vm == nullref) { //fail with a unknown type exception dj_panic(-1); } // tell the execution engine to use the newly created VM instance dj_exec_setVM(vm); // load the embedded infusions dj_named_native_handler handlers[] = { { "base", &base_native_handler }, { "darjeeling", &darjeeling_native_handler } #ifdef WITH_RADIO ,{ "radio", &radio_native_handler } #endif }; int length = sizeof(handlers)/ sizeof(handlers[0]); archive.start = (dj_di_pointer)di_archive_data; archive.end = (dj_di_pointer)(di_archive_data + di_archive_size); dj_vm_loadInfusionArchive(vm, &archive, handlers, length); // load the embedded infusions DARJEELING_PRINTF("%d infusions loaded\n", dj_vm_countInfusions(dj_exec_getVM())); // pre-allocate an OutOfMemoryError object dj_object *obj = dj_vm_createSysLibObject(dj_exec_getVM(), BASE_CDEF_java_lang_OutOfMemoryError); dj_mem_setPanicExceptionObject(obj); }
// void javax.darjeeling.Darjeeling.assertTrue(int, boolean) void javax_darjeeling_Darjeeling_void_assertTrue_int_boolean() { // pop argument from the stack int32_t value = dj_exec_stackPopShort(); int32_t id = dj_exec_stackPopInt(); char tempStr[35]; if (tempStr != NULL){ if (value==0) snprintf(tempStr, 35, "%c[31mASSERT[%3d] FAILED%c[0m\n", 0x1b, (int)id, 0x1b); else snprintf(tempStr, 35, "%c[32mASSERT[%3d] PASSED%c[0m\n", 0x1b, (int)id, 0x1b); tossim_printf(tempStr); dj_mem_free (tempStr); if (value ==0) dj_panic(DJ_PANIC_ASSERTION_FAILURE); } }
uint8_t radio_xbee_send(radio_xbee_address_t dest, uint8_t *payload, uint8_t length) { dj_panic(DJ_PANIC_UNIMPLEMENTED_FEATURE); return 1; // To keep the compiler happy. }
void radio_xbee_poll(void) { dj_panic(DJ_PANIC_UNIMPLEMENTED_FEATURE); }
radio_xbee_address_t radio_xbee_get_node_id() { dj_panic(DJ_PANIC_UNIMPLEMENTED_FEATURE); return 1; // To keep the compiler happy. }
/** * Loads an infusion into the virtual machine. * @param vm the virtual machine object to load the infusion into * @param di a di pointer to the infusion file in program space * @return a newly loaded infusion, or NULL in case of fail */ dj_infusion *dj_vm_loadInfusion(dj_vm *vm, dj_di_pointer di, dj_named_native_handler native_handlers[], unsigned char numHandlers) { int i; dj_infusion *infusion; dj_di_pointer element; dj_di_pointer staticFieldInfo = DJ_DI_NOT_SET; dj_di_pointer infusionList = DJ_DI_NOT_SET; dj_thread * thread; dj_global_id entryPoint; // iterate over the child elements, and find the static // field size info block. We need this info to allocate // the memory to hold the static fields for this // infusion for (i=0; i<dj_di_getListSize(di); i++) { element = dj_di_getListElement(di, i); switch (dj_di_element_getId(element)) { case STATICFIELDINFO: staticFieldInfo = element; break; case INFUSIONLIST: infusionList = element; break; } } // Check if each of the required elements were found if (staticFieldInfo==DJ_DI_NOT_SET||infusionList==DJ_DI_NOT_SET) dj_panic(DJ_PANIC_MALFORMED_INFUSION); // allocate the Infusion struct infusion = dj_infusion_create(staticFieldInfo, dj_di_infusionList_getSize(infusionList)); // if we're out of memory, let the caller handle it if (infusion==NULL) return NULL; // iterate over the child elements and get references // to the class list and method implementation list, // and get the header for (i=0; i<dj_di_getListSize(di); i++) { element = dj_di_getListElement(di, i); switch (dj_di_element_getId(element)) { case HEADER: infusion->header = element; break; case CLASSLIST: infusion->classList = element; break; case METHODIMPLLIST: infusion->methodImplementationList = element; break; case STRINGTABLE: infusion->stringTable = element; break; } } // Check if each of the required elements was found if (infusion->stringTable==DJ_DI_NOT_SET||infusion->classList==DJ_DI_NOT_SET||infusion->methodImplementationList==DJ_DI_NOT_SET||infusion->header==DJ_DI_NOT_SET) dj_panic(DJ_PANIC_MALFORMED_INFUSION); // iterate over the referenced infusion list and set the appropriate pointers for (i=0; i<dj_di_infusionList_getSize(infusionList); i++) { dj_di_pointer name = dj_di_infusionList_getChild(infusionList, i); dj_infusion *referenced_infusion = dj_vm_lookupInfusion(vm, name); if (infusion==NULL) dj_panic(DJ_PANIC_UNSATISFIED_LINK); infusion->referencedInfusions[i] = referenced_infusion; } // add the new infusion to the VM dj_vm_addInfusion(vm, infusion); // We're assuming here that base.di is the first file in the archive if (vm->systemInfusion == NULL) vm->systemInfusion = infusion; // This code was originally in load dj_vm_loadInfusionArchive. // Moved here because the application is not in an archive, but needs // some of the same code (not native_handlers, but class initialisers // and creating a thread) #ifdef DARJEELING_DEBUG char name[64]; dj_infusion_getName(infusion, name, 64); DEBUG_LOG(DBG_DARJEELING, "Loaded infusion %s.", name); #endif for (i=0; i<numHandlers; i++) { if (dj_di_strEqualsDirectStr(dj_di_header_getInfusionName(infusion->header), native_handlers[i].name)) { infusion->native_handler = native_handlers[i].handler; #ifdef DARJEELING_DEBUG DEBUG_LOG(DBG_DARJEELING, "Attached native handler to infusion %s.", name); #endif } } // run class initialisers for this infusion infusion = dj_vm_runClassInitialisers(vm, infusion); // find the entry point for the infusion if ((entryPoint.entity_id=dj_di_header_getEntryPoint(infusion->header))!=255) { // create a new thread and add it to the VM entryPoint.infusion = infusion; thread = dj_thread_create_and_run(entryPoint); if (thread==NULL) dj_panic(DJ_PANIC_OUT_OF_MEMORY); dj_vm_addThread(vm, thread); } return infusion; }
// 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; }
void dj_vm_loadInfusionArchive(dj_vm * vm, dj_archive* archive, dj_named_native_handler native_handlers[], unsigned char numHandlers) { dj_thread * thread; dj_infusion * infusion = NULL; dj_di_pointer archive_start = archive->start; dj_di_pointer archive_end = archive->end; unsigned char digit, i; dj_global_id entryPoint; unsigned long size, pos; bool first = true; // skip header, we'll just assume you're not passing something silly into this method archive_start += 8; while (archive_start<archive_end-1) { // read size size = 0; pos = AR_EHEADER_SIZE_START; while (((digit=dj_di_getU8(archive_start+pos))!=' ')&&(pos<AR_EHEADER_SIZE_END)) { size *= 10; size += digit - '0'; pos++; } // if filename starts with '/' skip this entry, since it's part of a // GNU extension on the common AR format if (dj_di_getU8(archive_start)!='/') { // Read infusion file. We're assuming here that base.di is the first file in the archive if (first) infusion = dj_vm_loadSystemInfusion(vm, archive_start + AR_EHEADER_SIZE); else infusion = dj_vm_loadInfusion(vm, archive_start + AR_EHEADER_SIZE); // If infusion is not loaded a critical error has occured if (infusion == NULL){ DARJEELING_PRINTF("Not enough space to create the infusion : %c%c%c%c%c%c%c%c\n", dj_di_getU8(archive_start+0), dj_di_getU8(archive_start+1), dj_di_getU8(archive_start+2), dj_di_getU8(archive_start+3), dj_di_getU8(archive_start+4), dj_di_getU8(archive_start+5), dj_di_getU8(archive_start+6), dj_di_getU8(archive_start+7) ); dj_panic(DJ_PANIC_OUT_OF_MEMORY); } /* else DARJEELING_PRINTF("[%s.di] %ld\n", (char *) dj_di_header_getInfusionName(infusion->header), size ); */ #ifdef DARJEELING_DEBUG char name[64]; dj_infusion_getName(infusion, name, 64); DEBUG_LOG("Loaded infusion %s.", name); #endif for (i=0; i<numHandlers; i++) { if (dj_di_strEqualsDirectStr(dj_di_header_getInfusionName(infusion->header), native_handlers[i].name)) { infusion->native_handler = native_handlers[i].handler; #ifdef DARJEELING_DEBUG DEBUG_LOG("Attached native handler to infusion %s.", name); #endif } } // run class initialisers for this infusion infusion = dj_vm_runClassInitialisers(vm, infusion); // find the entry point for the infusion if ((entryPoint.entity_id=dj_di_header_getEntryPoint(infusion->header))!=255) { // create a new thread and add it to the VM entryPoint.infusion = infusion; thread = dj_thread_create_and_run(entryPoint); if (thread==NULL) dj_panic(DJ_PANIC_OUT_OF_MEMORY); dj_vm_addThread(vm, thread); } first = false; } // files are 2-byte aligned if (size&1) size++; archive_start += size + AR_EHEADER_SIZE; } }
/** * Loads an infusion into the virtual machine. * @param vm the virtual machine object to load the infusion into * @param di a di pointer to the infusion file in program space * @return a newly loaded infusion, or NULL in case of fail */ dj_infusion *dj_vm_loadInfusion(dj_vm *vm, dj_di_pointer di) { int i; dj_infusion *ret; dj_di_pointer element; dj_di_pointer staticFieldInfo = DJ_DI_NOT_SET; dj_di_pointer infusionList = DJ_DI_NOT_SET; // iterate over the child elements, and find the static // field size info block. We need this info to allocate // the memory to hold the static fields for this // infusion for (i=0; i<dj_di_getListSize(di); i++) { element = dj_di_getListElement(di, i); switch (dj_di_element_getId(element)) { case STATICFIELDINFO: staticFieldInfo = element; break; case INFUSIONLIST: infusionList = element; break; } } // Check if each of the required elements were found if (staticFieldInfo==DJ_DI_NOT_SET||infusionList==DJ_DI_NOT_SET) dj_panic(DJ_PANIC_MALFORMED_INFUSION); // allocate the Infusion struct ret = dj_infusion_create(staticFieldInfo, dj_di_infusionList_getSize(infusionList)); // if we're out of memory, let the caller handle it if (ret==NULL) return NULL; // iterate over the child elements and get references // to the class list and method implementation list, // and get the header for (i=0; i<dj_di_getListSize(di); i++) { element = dj_di_getListElement(di, i); switch (dj_di_element_getId(element)) { case HEADER: ret->header = element; break; case CLASSLIST: ret->classList = element; break; case METHODIMPLLIST: ret->methodImplementationList = element; break; case STRINGTABLE: ret->stringTable = element; break; } } // Check if each of the required elements was found if (ret->stringTable==DJ_DI_NOT_SET||ret->classList==DJ_DI_NOT_SET||ret->methodImplementationList==DJ_DI_NOT_SET||ret->header==DJ_DI_NOT_SET) dj_panic(DJ_PANIC_MALFORMED_INFUSION); // iterate over the referenced infusion list and set the appropriate pointers for (i=0; i<dj_di_infusionList_getSize(infusionList); i++) { dj_di_pointer name = dj_di_infusionList_getChild(infusionList, i); dj_infusion *infusion = dj_vm_lookupInfusion(vm, name); if (infusion==NULL) dj_panic(DJ_PANIC_UNSATISFIED_LINK); ret->referencedInfusions[i] = infusion; } // add the new infusion to the VM dj_vm_addInfusion(vm, ret); return ret; }