char classlibInitJavaThread(Thread *thread, Object *jlthread, Object *name, Object *group, char is_daemon, int priority) { INST_DATA(jlthread, Thread*, eetop_offset) = thread; INST_DATA(jlthread, int, daemon_offset) = is_daemon; INST_DATA(jlthread, int, priority_offset) = priority; if(name == NULL) executeMethod(jlthread, init_mb_no_name, group, NULL); else executeMethod(jlthread, init_mb_with_name, group, name); return !exceptionOccurred(); }
Object *classlibThreadPreInit(Class *thread_class, Class *thrdGrp_class) { MethodBlock *system_init_mb, *main_init_mb; FieldBlock *thread_status_fb, *eetop_fb; Object *system, *main, *main_name; init_mb_with_name = findMethod(thread_class, SYMBOL(object_init), SYMBOL(_java_lang_ThreadGroup_java_lang_String__V)); init_mb_no_name = findMethod(thread_class, SYMBOL(object_init), SYMBOL(_java_lang_ThreadGroup_java_lang_Runnable__V)); thread_status_fb = findField(thread_class, SYMBOL(threadStatus), SYMBOL(I)); eetop_fb = findField(thread_class, SYMBOL(eetop), SYMBOL(J)); system_init_mb = findMethod(thrdGrp_class, SYMBOL(object_init), SYMBOL(___V)); main_init_mb = findMethod(thrdGrp_class, SYMBOL(object_init), SYMBOL(_java_lang_ThreadGroup_java_lang_String__V)); if(init_mb_with_name == NULL || init_mb_no_name == NULL || system_init_mb == NULL || main_init_mb == NULL || thread_status_fb == NULL || eetop_fb == NULL) return NULL; CLASS_CB(thread_class)->flags |= JTHREAD; thread_status_offset = thread_status_fb->u.offset; eetop_offset = eetop_fb->u.offset; if((system = allocObject(thrdGrp_class)) == NULL) return NULL; executeMethod(system, system_init_mb); if(exceptionOccurred()) return NULL; if((main = allocObject(thrdGrp_class)) == NULL || (main_name = Cstr2String("main")) == NULL) return NULL; executeMethod(main, main_init_mb, system, main_name); if(exceptionOccurred()) return NULL; return main; }
Object *initJavaThread(Thread *thread, char is_daemon, const char *name) { Object *vmthread, *jlthread, *thread_name = NULL; /* Create the java.lang.Thread object and the VMThread */ if((vmthread = allocObject(vmthread_class)) == NULL || (jlthread = allocObject(thread_class)) == NULL) return NULL; //thread->ee->thread = jlthread; thread->thread = jlthread; INST_DATA(vmthread)[vmData_offset] = (uintptr_t)thread; INST_DATA(vmthread)[thread_offset] = (uintptr_t)jlthread; /* Create the string for the thread name. If null is specified the initialiser method will generate a name of the form Thread-X */ if(name != NULL && (thread_name = Cstr2String(name)) == NULL) return NULL; /* Call the initialiser method -- this is for use by threads created or attached by the VM "outside" of Java */ DummyFrame dummy; executeMethod(&dummy, jlthread, init_mb, vmthread, thread_name, NORM_PRIORITY, is_daemon); /* Add thread to thread ID map hash table. */ addThreadToHash(thread); return jlthread; }
/* * Execute the ANEWARRAY instruction */ void op_anewarray() { Ref type = resolve(u16(1), ID_TYPE); if (type == NULL) { return; } // rollback, gc done Ref arrayType = getRef(type, TYPE_ARRAY_TYPE); // resolve array type if (arrayType == NULL) { Ref target = getRef(core, OBJECT_TYPE); Ref method = getRef(core, CORE_RESOLVE_METHOD); executeMethod(target, method, 0); return; // rollback } // allocate space int length = peekInt(); // don't pop yet in case gc runs int numWords = ARRAY_DATA + length; Ref array = allocate(numWords, HEADER_OBJECT_ARRAY); if (array == NULL) { return; } // rollback, gc done popInt(); // pop length // initialise array object and push on stack int hash = (char*) array - (char*) core; setInt(array, OBJECT_HASHCODE, hash); setRef(array, OBJECT_TYPE, arrayType); setInt(array, ARRAY_LENGTH, length); pushRef(array); pc += 3; }
void *threadStart(void *arg) { Thread *thread = (Thread *)arg; //Object *jThread = thread->ee->thread; Object *jThread = thread->thread; /* Parent thread created thread with suspension disabled. This is inherited so we need to enable */ enableSuspend(thread); /* Complete initialisation of the thread structure, create the thread stack and add the thread to the thread list */ initThread(thread, INST_DATA(jThread)[daemon_offset], &thread); /* Add thread to thread ID map hash table. */ addThreadToHash(thread); /* Execute the thread's run method */ DummyFrame dummy; executeMethod(&dummy, jThread, CLASS_CB(jThread->classobj)->method_table[run_mtbl_idx]); /* Run has completed. Detach the thread from the VM and exit */ detachThread(thread); TRACE("Thread 0x%x id: %d exited\n", thread, thread->id); return NULL; }
Thread *attachThread(char *name, char is_daemon, void *stack_base, Thread *thread, Object *group) { Object *java_thread; /* Create the ExecEnv for the thread */ // ExecEnv *ee = (ExecEnv*)sysMalloc(sizeof(ExecEnv)); // memset(ee, 0, sizeof(ExecEnv)); thread->tid = pthread_self(); //thread->ee = ee; /* Complete initialisation of the thread structure, create the thread stack and add the thread to the thread list */ initThread(thread, is_daemon, stack_base); /* Initialise the Java-level thread objects representing this thread */ if((java_thread = initJavaThread(thread, is_daemon, name)) == NULL) return NULL; /* Initialiser doesn't handle the thread group */ INST_DATA(java_thread)[group_offset] = (uintptr_t)group; DummyFrame dummy; executeMethod(&dummy, group, addThread_mb, java_thread); /* We're now attached to the VM...*/ TRACE("Thread 0x%x id: %d attached\n", thread, thread->id); return thread; }
// função classInitialization void classInitialization(CLASS_DATA * cd, JVM * jvm, THREAD * thread){ /* A IMPLEMENTAR Initialization of a class consists of two steps: Initializing the class's direct superclass (if any), if the direct superclass hasn't already been initialized Executing the class's class initialization method, if it has one */ if((cd->classfile)->super_class){ cp_info * cp_aux = (cd->classfile)->constant_pool + (cd->classfile)->super_class - 1; cp_aux = (cd->classfile)->constant_pool + cp_aux->u.Class.name_index - 1; char * super_class_name = cp_aux->u.Utf8.bytes; /* super_class_name[cp_aux->u.Utf8.length] = '\0';*/ /* printf("Super class:\t");*/ /* PrintConstantUtf8(cp_aux, stdout);*/ /* puts("");*/ /* if(strcmp(super_class_name, "java/lang/Object")){*/ CLASS_DATA * cd_super; /* if(!(cd_super = getSuperClass(cd->classfile, jvm))){*/ if(!(cd_super = getClass(cp_aux, jvm))){ classLoading(strcat(super_class_name, ".class"), &cd_super, cd, jvm); } classLinking(cd_super, jvm); classInitialization(cd_super, jvm, thread); /* }*/ } /* executeMethod("<init>", cd, jvm, thread, cd);*/ executeMethod("<clinit>", cd, jvm, thread, cd); }// fim da função classInitialization
// Method ID = 8 void EMLiveMonitor::pushMetric( Report::ptr_t report ) { EXEParamList paramsList; paramsList.push_back( report ); executeMethod( 8, paramsList ); }
void signalChainedExceptionClass(Class *exception, char *message, Object *cause) { Object *exp = allocObject(exception); Object *str = message == NULL ? NULL : Cstr2String(message); MethodBlock *init = lookupMethod(exception, SYMBOL(object_init), SYMBOL(_java_lang_String__V)); if(exp && init) { executeMethod(exp, init, str); if(cause && !exceptionOccurred()) { MethodBlock *mb = lookupMethod(exception, SYMBOL(initCause), SYMBOL(_java_lang_Throwable__java_lang_Throwable)); if(mb) executeMethod(exp, mb, cause); } setException(exp); } }
TestResult TestRef::debug() { TestResult result; setUp(); executeMethod(); tearDown(); return result; }
/* * Retrieve the constant pool entry at the given index. If the id of the * entry does not match the given id call the resolve method of the core * object and return null. The code in the core object will replace * the placeholder entry with the resolved object. */ Ref resolve(int index, int id) { Ref entry = getPoolEntry(index); if (getInt(entry, ENTRY_ID) != id) { Ref type = getRef(core, OBJECT_TYPE); Ref method = getRef(core, CORE_RESOLVE_METHOD); executeMethod(type, method, 0); return NULL; } return entry; }
/* * Execute the INVOKESPECIAL instruction */ void op_invokespecial() { Ref method = resolve(u16(1), ID_METHOD); if (method == NULL) { return; } // rollback, gc done // check the target object Int argcount = getInt(method, METHOD_ARG_COUNT); Ref target = stack[argcount - 1].value.r; if (target == NULL) { throwException(CORE_THROW_NULL_POINTER); } // execute the method else { executeMethod(target, method, 3); } }
Object *classlibNewDirectByteBuffer(void *addr, long long capacity) { Object *buff, *rawdata; if((buff = allocObject(buffImpl_class)) != NULL && (rawdata = allocObject(rawdata_class)) != NULL) { INST_DATA(rawdata, void*, rawdata_offset) = addr; executeMethod(buff, buffImpl_init_mb, NULL, rawdata, (int)capacity, (int)capacity, 0); } return buff; }
//invokespecial int op_invokespecial( unsigned char **opCode, StackFrame *stack, SimpleConstantPool *p ) { u2 method_index ; unsigned char tmp[2]; tmp[0] = opCode[0][1]; tmp[1] = opCode[0][2]; method_index = tmp[0] << 8 | tmp[1]; #if SIMPLE_JVM_DEBUG printf("call method_index %d\n", method_index); #endif *opCode = *opCode + 3; if ( method_index < simpleMethodPool.method_used ) { MethodInfo *method = &simpleMethodPool.method[method_index]; executeMethod( method, &stackFrame, &simpleConstantPool ); } return 0; }
/* * Execute the INVOKEVIRTUAL instruction */ void op_invokevirtual() { Ref entry = resolve(u16(1), ID_METHOD); if (entry == NULL) { return; } // rollback, gc done // check the target object int argcount = getInt(entry, METHOD_ARG_COUNT); Ref target = stack[argcount - 1].value.r; if (target == NULL) { throwException(CORE_THROW_NULL_POINTER); } // resolve and execute the method else { Ref type = getRef(target, OBJECT_TYPE); Ref name = getRef(entry, ENTRY_NAME); Ref desc = getRef(entry, ENTRY_DESCRIPTOR); Ref resolved = resolveMethod(type, name, desc); executeMethod(target, resolved, 3); } }
void printException() { ExecEnv *ee = getExecEnv(); Object *exception = ee->exception; if(exception != NULL) { MethodBlock *mb = lookupMethod(exception->class, SYMBOL(printStackTrace), SYMBOL(___V)); clearException(); executeMethod(exception, mb); /* If we're really low on memory we might have been able to throw * OutOfMemory, but then been unable to print any part of it! In * this case the VM just seems to stop... */ if(ee->exception) { jam_fprintf(stderr, "Exception occurred while printing exception (%s)...\n", CLASS_CB(ee->exception->class)->name); jam_fprintf(stderr, "Original exception was %s\n", CLASS_CB(exception->class)->name); }
/* * Execute the INVOKEINTERFACE instruction */ void op_invokeinterface() { Ref entry = resolve(u16(1), ID_METHOD); if (entry == NULL) { return; } // rollback, gc done // check for null pointer Int argcount = getInt(entry, METHOD_ARG_COUNT); Ref object = stack[argcount - 1].value.r; if (object == NULL) { throwException(CORE_THROW_NULL_POINTER); return; } // resolve and execute Ref desc = getRef(entry, ENTRY_DESCRIPTOR); Ref name = getRef(entry, ENTRY_NAME); Ref type = getRef(object, OBJECT_TYPE); Ref method = resolveMethod(type, name, desc); executeMethod(object, method, 5); }
TestResult TestRef::run() { TestResult result; setUp(); try { executeMethod(); } catch (TestResult &r) { result = r; } catch (std::exception &e) { result = TestResult(e); } catch (...) { result = TestResult(false, "", 0, "", "unknown exception"); } result.expectedFailure = getExpectFailure(); tearDown(); return result; }
// função jvmStart void jvmStart(char * class_filename, int num_args, char * args[]){ /* https://docs.oracle.com/javase/specs/jvms/se6/html/Concepts.doc.html#16491 https://docs.oracle.com/javase/specs/jvms/se6/html/Concepts.doc.html#19042 */ JVM * jvm; jvm = (JVM *) malloc(sizeof(JVM)); jvm->method_area = NULL; jvm->threads = NULL; jvm->heap = (HEAP_AREA *) malloc(sizeof(HEAP_AREA)); CLASS_DATA * main_class_data; /* puts("DEBUG:\tCLASS LOADING\n");*/ classLoading(class_filename, &main_class_data, NULL, jvm); /* puts("DEBUG:\tCLASS LINKING\n");*/ classLinking(main_class_data, jvm); // INICIA THREAD PRINCIPAL THREAD * main_thread = (THREAD *) malloc(sizeof(THREAD)); main_thread->program_counter = NULL; main_thread->jvm_stack = NULL; main_thread->prox = NULL; jvm->threads = main_thread; /* puts("DEBUG:\tCLASS INITIALIZATION\n");*/ classInitialization(main_class_data, jvm, main_thread); if(main_class_data->modifiers & ACC_ABSTRACT){ puts("ERROR: method 'main' not find."); exit(EXIT_FAILURE); } executeMethod("main", main_class_data, jvm, main_thread, main_class_data); classUnloading(main_class_data, jvm); jvmExit(jvm); }// fim da função jvmStart
// User methods -------------------------------------------------------------- // Method ID = 7 void EMLiveMonitor::notifyReadyToPush() { EXEParamList emptyParams; executeMethod( 7, emptyParams ); }
/* * Execute the specified native method. Return true if the method * is executed, false if it is rolled back for garbage collection. */ int executeNativeMethod(Ref target, Ref method, int offset) { int magic = getInt(method, METHOD_MAGIC); if (magic == 0) { printf("Native method not supported\n"); debugTrace(); exit(1); } switch (magic) { // print a debug message case MAGIC_RUNTIME_CORE_DEBUG: debugLine(popRef()); pc += offset; break; // execute the given static method case MAGIC_RUNTIME_CORE_EXECUTE_STATIC: { Ref staticMethod = popRef(); if (staticMethod == NULL) { throwException(CORE_THROW_NULL_POINTER); return; } Ref owner = getRef(staticMethod, ENTRY_OWNER); if (!executeMethod(owner, staticMethod, offset)) { // restore stack if rolled back for gc pushRef(staticMethod); } } break; // return the current frame case MAGIC_RUNTIME_FRAME_CURRENT: pushRef(frame); pc += offset; break; // return the core object case MAGIC_RUNTIME_CORE_GET: pushRef(core); pc += offset; break; // create a statics object case MAGIC_RUNTIME_STATICS_CREATE: { // allocate space for statics object Ref type = popRef(); Int numStaticFields = getInt(type, TYPE_STATIC_FIELD_COUNT); Int numWords = STATICS_FIELDS + numStaticFields; Ref statics = allocate(numWords, HEADER_STATIC_FIELDS); if (statics == NULL) { pushRef(type); // restore stack return; // rollback, gc done } // initialise statics object and set in type object int hash = (char*) statics - (char*) core; setInt(statics, OBJECT_HASHCODE, hash); Ref staticsType = getRef(core, CORE_STATICS_TYPE); setRef(statics, OBJECT_TYPE, staticsType); Ref map = getRef(type, TYPE_STATIC_MAP); setRef(statics, STATICS_MAP, map); setRef(type, TYPE_STATICS, statics); } pc += offset; break; // read the type from a class case MAGIC_RUNTIME_CORE_GET_TYPE: { Ref class = popRef(); // type is first field in class... Ref type = getRef(class, OBJECT_FIELDS); pushRef(type); } pc += offset; break; // put system to sleep to avoid wasting processor time while idle case MAGIC_RUNTIME_IDLE_SLEEP: idleSleep(); pc += offset; break; // return the currently executing thread case MAGIC_RUNTIME_THREAD_CURRENT: pushRef(thread); pc += offset; break; // start a new thread case MAGIC_RUNTIME_THREAD_START_HOOK: startNewThread(offset); break; // return an object's class case MAGIC_JAVA_OBJECT_GET_CLASS: { Ref obj = popRef(); Ref type = getRef(obj, OBJECT_TYPE); Ref peer = getRef(type, TYPE_PEER); pushRef(peer); } pc += offset; break; // set system output stream case MAGIC_JAVA_SYSTEM_SET_OUT: { Ref arg = popRef(); Ref type = getRef(method, ENTRY_OWNER); Ref statics = getRef(type, TYPE_STATICS); setRef(statics, STATICS_FIELDS + SYSTEM_OUT, arg); } pc += offset; break; // set system error stream case MAGIC_JAVA_SYSTEM_SET_ERR: { Ref arg = popRef(); Ref type = getRef(method, ENTRY_OWNER); Ref statics = getRef(type, TYPE_STATICS); setRef(statics, STATICS_FIELDS + SYSTEM_ERR, arg); } pc += offset; break; // set system input stream case MAGIC_JAVA_SYSTEM_SET_IN: { Ref arg = popRef(); Ref type = getRef(method, ENTRY_OWNER); Ref statics = getRef(type, TYPE_STATICS); setRef(statics, STATICS_FIELDS + SYSTEM_IN, arg); } pc += offset; break; // read an ascii character from the console case MAGIC_TEST_READ_FROM_CONSOLE: { char c = readFromConsole(); pushInt(c); } pc += offset; break; // write an ascii character to the console case MAGIC_TEST_WRITE_TO_CONSOLE: { char c = popInt() & 0xFF; printf("%c", c); } pc += offset; break; // read a byte from the floppy drive case MAGIC_TEST_READ_FROM_FLOPPY: { Int pos = popInt(); pushInt(readFromFloppy(pos)); } pc += offset; break; // magic id not recognised default: printf("Invalid magic method id: %d\n", magic); exit(1); break; } }
/* * This method is used whenever the system needs to throw an exception * while trying to execute a java bytecode instruction. The given method * offset indicates a field of the core object referring to a static * method which throws the desired exception. A new frame is created on * top of the existing stack and this method is executed. */ void throwException(int offset) { Ref method = getRef(core, offset); Ref coreType = getRef(core, OBJECT_TYPE); executeMethod(coreType, method, 0); }
// Method ID = 10 void EMLiveMonitor::notifyReadyForPull() { EXEParamList emptyParams; executeMethod( 10, emptyParams ); }
/* * Execute the INVOKESTATIC instruction */ void op_invokestatic() { Ref entry = resolve(u16(1), ID_METHOD); if (entry == NULL) { return; } // rollback, gc done Ref owner = getRef(entry, ENTRY_OWNER); executeMethod(owner, entry, 3); }
void detachThread(Thread *thread) { Object *group, *excep; //ExecEnv *ee = thread->ee; //Object *jThread = ee->thread; Object *jThread = thread->thread; Object *vmthread = (Object*)INST_DATA(jThread)[vmthread_offset]; /* Get the thread's group */ group = (Object *)INST_DATA(jThread)[group_offset]; /* If there's an uncaught exception, call uncaughtException on the thread's exception handler, or the thread's group if this is unset */ if((excep = exceptionOccurred())) { FieldBlock *fb = findField(thread_class, SYMBOL(exceptionHandler), SYMBOL(sig_java_lang_Thread_UncaughtExceptionHandler)); Object *thread_handler = fb == NULL ? NULL : (Object *)INST_DATA(jThread)[fb->offset]; Object *handler = thread_handler == NULL ? group : thread_handler; MethodBlock *uncaught_exp = lookupMethod(handler->classobj, SYMBOL(uncaughtException), SYMBOL(_java_lang_Thread_java_lang_Throwable__V)); if(uncaught_exp) { clearException(); DummyFrame dummy; executeMethod(&dummy, handler, uncaught_exp, jThread, excep); } else printException(); } /* remove thread from thread group */ DummyFrame dummy; executeMethod(&dummy, group, (CLASS_CB(group->classobj))->method_table[rmveThrd_mtbl_idx], jThread); /* set VMThread ref in Thread object to null - operations after this point will result in an IllegalThreadStateException */ INST_DATA(jThread)[vmthread_offset] = 0; /* Remove thread from the ID map hash table */ deleteThreadFromHash(thread); /* Disable suspend to protect lock operation */ disableSuspend(thread); /* Grab global lock, and update thread structures protected by it (thread list, thread ID and number of daemon threads) */ pthread_mutex_lock(&lock); /* remove from thread list... */ if((thread->prev->next = thread->next)) thread->next->prev = thread->prev; /* One less live thread */ threads_count--; /* Recycle the thread's thread ID */ freeThreadID(thread->id); /* Handle daemon thread status */ if(!INST_DATA(jThread)[daemon_offset]) non_daemon_thrds--; pthread_mutex_unlock(&lock); /* notify any threads waiting on VMThread object - these are joining this thread */ objectLock(vmthread); objectNotifyAll(vmthread); objectUnlock(vmthread); /* It is safe to free the thread's ExecEnv and stack now as these are only used within the thread. It is _not_ safe to free the native thread structure as another thread may be concurrently accessing it. However, they must have a reference to the VMThread -- therefore, it is safe to free during GC when the VMThread is determined to be no longer reachable. */ // sysFree(ee->stack); //sysFree(ee); /* If no more daemon threads notify the main thread (which may be waiting to exit VM). Note, this is not protected by lock, but main thread checks again */ if(non_daemon_thrds == 0) { /* No need to bother with disabling suspension * around lock, as we're no longer on thread list */ pthread_mutex_lock(&exit_lock); pthread_cond_signal(&exit_cv); pthread_mutex_unlock(&exit_lock); } TRACE("Thread 0x%x id: %d detached from VM\n", thread, thread->id); }
// Method ID = 9 void EMLiveMonitor::notifyPushingCompleted() { EXEParamList emptyParams; executeMethod( 9, emptyParams ); }
HOT void sendSuperMessage(VMGlobals *g, PyrSymbol *selector, long numArgsPushed) { PyrMethod *meth = NULL; PyrMethodRaw *methraw; PyrSlot *recvrSlot, *sp; PyrClass *classobj; long index; PyrObject *obj; //postfl("->sendMessage\n"); #ifdef GC_SANITYCHECK g->gc->SanityCheck(); CallStackSanity(g, "sendSuperMessage"); #endif recvrSlot = g->sp - numArgsPushed + 1; classobj = slotRawSymbol(&slotRawClass(&g->method->ownerclass)->superclass)->u.classobj; //assert(isKindOfSlot(recvrSlot, classobj)); lookup_again: index = slotRawInt(&classobj->classIndex) + selector->u.index; meth = gRowTable[index]; if (slotRawSymbol(&meth->name) != selector) { doesNotUnderstand(g, selector, numArgsPushed); } else { methraw = METHRAW(meth); //postfl("methraw->methType %d\n", methraw->methType); switch (methraw->methType) { case methNormal : /* normal msg send */ executeMethod(g, meth, numArgsPushed); break; case methReturnSelf : /* return self */ g->sp -= numArgsPushed - 1; break; case methReturnLiteral : /* return literal */ sp = g->sp -= numArgsPushed - 1; slotCopy(sp, &meth->selectors); /* in this case selectors is just a single value */ break; case methReturnArg : /* return an argument */ sp = g->sp -= numArgsPushed - 1; index = methraw->specialIndex; // zero is index of the first argument if (index < numArgsPushed) { slotCopy(sp, sp + index); } else { slotCopy(sp, &slotRawObject(&meth->prototypeFrame)->slots[index]); } break; case methReturnInstVar : /* return inst var */ sp = g->sp -= numArgsPushed - 1; index = methraw->specialIndex; slotCopy(sp, &slotRawObject(recvrSlot)->slots[index]); break; case methAssignInstVar : /* assign inst var */ sp = g->sp -= numArgsPushed - 1; index = methraw->specialIndex; obj = slotRawObject(recvrSlot); if (obj->IsImmutable()) { StoreToImmutableB(g, sp, g->ip); } else { if (numArgsPushed >= 2) { slotCopy(&obj->slots[index], sp + 1); g->gc->GCWrite(obj, sp + 1); } else { SetNil(&obj->slots[index]); } slotCopy(sp, recvrSlot); } break; case methReturnClassVar : /* return class var */ sp = g->sp -= numArgsPushed - 1; slotCopy(sp, &g->classvars->slots[methraw->specialIndex]); break; case methAssignClassVar : /* assign class var */ sp = g->sp -= numArgsPushed - 1; if (numArgsPushed >= 2) { slotCopy(&g->classvars->slots[methraw->specialIndex], sp + 1); g->gc->GCWrite(g->classvars, sp + 1); } else { SetNil(&g->classvars->slots[methraw->specialIndex]); } slotCopy(sp, recvrSlot); break; case methRedirect : /* send a different selector to self, e.g. this.subclassResponsibility */ if (numArgsPushed < methraw->numargs) { // not enough args pushed /* push default arg values */ PyrSlot *pslot, *qslot; long m, mmax; pslot = g->sp; qslot = slotRawObject(&meth->prototypeFrame)->slots + numArgsPushed - 1; for (m=0, mmax=methraw->numargs - numArgsPushed; m<mmax; ++m) slotCopy(++pslot, ++qslot); numArgsPushed = methraw->numargs; g->sp += mmax; } selector = slotRawSymbol(&meth->selectors); goto lookup_again; case methRedirectSuper : /* send a different selector to self, e.g. this.subclassResponsibility */ if (numArgsPushed < methraw->numargs) { // not enough args pushed /* push default arg values */ PyrSlot *pslot, *qslot; long m, mmax; pslot = g->sp; qslot = slotRawObject(&meth->prototypeFrame)->slots + numArgsPushed - 1; for (m=0, mmax=methraw->numargs - numArgsPushed; m<mmax; ++m) slotCopy(++pslot, ++qslot); numArgsPushed = methraw->numargs; g->sp += mmax; } selector = slotRawSymbol(&meth->selectors); classobj = slotRawSymbol(&slotRawClass(&meth->ownerclass)->superclass)->u.classobj; goto lookup_again; case methForwardInstVar : /* forward to an instance variable */ if (numArgsPushed < methraw->numargs) { // not enough args pushed /* push default arg values */ PyrSlot *pslot, *qslot; long m, mmax; pslot = g->sp; qslot = slotRawObject(&meth->prototypeFrame)->slots + numArgsPushed - 1; for (m=0, mmax=methraw->numargs - numArgsPushed; m<mmax; ++m) slotCopy(++pslot, ++qslot); numArgsPushed = methraw->numargs; g->sp += mmax; } selector = slotRawSymbol(&meth->selectors); index = methraw->specialIndex; slotCopy(recvrSlot, &slotRawObject(recvrSlot)->slots[index]); classobj = classOfSlot(recvrSlot); goto lookup_again; case methForwardClassVar : /* forward to a class variable */ if (numArgsPushed < methraw->numargs) { // not enough args pushed /* push default arg values */ PyrSlot *pslot, *qslot; long m, mmax; pslot = g->sp; qslot = slotRawObject(&meth->prototypeFrame)->slots + numArgsPushed - 1; for (m=0, mmax=methraw->numargs - numArgsPushed; m<mmax; ++m) slotCopy(++pslot, ++qslot); numArgsPushed = methraw->numargs; g->sp += mmax; } selector = slotRawSymbol(&meth->selectors); slotCopy(recvrSlot, &g->classvars->slots[methraw->specialIndex]); classobj = classOfSlot(recvrSlot); goto lookup_again; case methPrimitive : /* primitive */ doPrimitive(g, meth, (int)numArgsPushed); #ifdef GC_SANITYCHECK g->gc->SanityCheck(); #endif break; /* case methMultDispatchByClass : { index = methraw->specialIndex; if (index < numArgsPushed) { classobj = slotRawObject(sp + index)->classptr; selector = slotRawSymbol(&meth->selectors); goto lookup_again; } else { doesNotUnderstand(g, selector, numArgsPushed); } } break; case methMultDispatchByValue : { index = methraw->specialIndex; if (index < numArgsPushed) { index = arrayAtIdentityHashInPairs(array, b); meth = slotRawObject(&meth->selectors)->slots[index + 1].uom; goto meth_select_again; } else { doesNotUnderstand(g, selector, numArgsPushed); } } break; */ } } #if TAILCALLOPTIMIZE g->tailCall = 0; #endif #ifdef GC_SANITYCHECK g->gc->SanityCheck(); CallStackSanity(g, "<sendSuperMessage"); #endif //postfl("<-sendMessage\n"); }
void initialiseThreadStage2(InitArgs *args) { Object *java_thread; Class *thrdGrp_class; MethodBlock *run, *remove_thread; FieldBlock *group, *priority, *root, *threadId; FieldBlock *vmThread = NULL, *thread = NULL; FieldBlock *vmData, *daemon, *name; /* Load thread class and register reference for compaction threading */ thread_class = findSystemClass0(SYMBOL(java_lang_Thread)); registerStaticClassRef(&thread_class); if(thread_class != NULL) { vmThread = findField(thread_class, SYMBOL(vmThread), SYMBOL(sig_java_lang_VMThread)); daemon = findField(thread_class, SYMBOL(daemon), SYMBOL(Z)); name = findField(thread_class, SYMBOL(name), SYMBOL(sig_java_lang_String)); group = findField(thread_class, SYMBOL(group), SYMBOL(sig_java_lang_ThreadGroup)); priority = findField(thread_class, SYMBOL(priority), SYMBOL(I)); threadId = findField(thread_class, SYMBOL(threadId), SYMBOL(J)); init_mb = findMethod(thread_class, SYMBOL(object_init), SYMBOL(_java_lang_VMThread_java_lang_String_I_Z__V)); run = findMethod(thread_class, SYMBOL(run), SYMBOL(___V)); vmthread_class = findSystemClass0(SYMBOL(java_lang_VMThread)); CLASS_CB(vmthread_class)->flags |= VMTHREAD; /* Register class reference for compaction threading */ registerStaticClassRef(&vmthread_class); if(vmthread_class != NULL) { thread = findField(vmthread_class, SYMBOL(thread), SYMBOL(sig_java_lang_Thread)); vmData = findField(vmthread_class, SYMBOL(vmData), SYMBOL(I)); } } /* findField and findMethod do not throw an exception... */ if((init_mb == NULL) || (vmData == NULL) || (run == NULL) || (daemon == NULL) || (name == NULL) || (group == NULL) || (priority == NULL) || (vmThread == NULL) || (thread == NULL) || (threadId == NULL)) goto error; vmthread_offset = vmThread->offset; thread_offset = thread->offset; vmData_offset = vmData->offset; daemon_offset = daemon->offset; group_offset = group->offset; priority_offset = priority->offset; threadId_offset = threadId->offset; name_offset = name->offset; run_mtbl_idx = run->method_table_index; /* Initialise the Java-level thread objects for the main thread */ java_thread = initJavaThread(&main_thread, FALSE, "main"); /* Main thread is now sufficiently setup to be able to run the thread group initialiser. This is essential to create the root thread group */ thrdGrp_class = findSystemClass(SYMBOL(java_lang_ThreadGroup)); root = findField(thrdGrp_class, SYMBOL(root), SYMBOL(sig_java_lang_ThreadGroup)); addThread_mb = findMethod(thrdGrp_class, SYMBOL(addThread), SYMBOL(_java_lang_Thread_args__void)); remove_thread = findMethod(thrdGrp_class, SYMBOL(removeThread), SYMBOL(_java_lang_Thread_args__void)); /* findField and findMethod do not throw an exception... */ if((root == NULL) || (addThread_mb == NULL) || (remove_thread == NULL)) goto error; rmveThrd_mtbl_idx = remove_thread->method_table_index; /* Add the main thread to the root thread group */ INST_DATA(java_thread)[group_offset] = root->static_value; { DummyFrame dummy; executeMethod(&dummy, ((Object*)root->static_value), addThread_mb, java_thread); } // dyn INST_DATA(java_thread)[vmthread_offset] = 0; /* Setup signal handling. This will be inherited by all threads created within Java */ initialiseSignals(); /* Create the signal handler thread. It is responsible for catching and handling SIGQUIT (thread dump) and SIGINT (user-termination of the VM, e.g. via Ctrl-C). Note it must be a valid Java-level thread as it needs to run the shutdown hooks in the event of user-termination */ createVMThread("Signal Handler", dumpThreadsLoop); return; error: jam_fprintf(stderr, "Error initialising VM (initialiseMainThread)\nCheck " "the README for compatible versions of GNU Classpath\n"); printException(); exitVM(1); }
void doesNotUnderstand(VMGlobals *g, PyrSymbol *selector, long numArgsPushed) { PyrSlot *qslot, *pslot, *pend; long i, index; PyrSlot *uniqueMethodSlot, *arraySlot, *recvrSlot, *selSlot, *slot; PyrClass *classobj; PyrMethod *meth; PyrObject *array; #ifdef GC_SANITYCHECK g->gc->SanityCheck(); #endif // move args up by one to make room for selector qslot = g->sp + 1; pslot = g->sp + 2; pend = pslot - numArgsPushed + 1; while (pslot > pend) *--pslot = *--qslot; selSlot = g->sp - numArgsPushed + 2; SetSymbol(selSlot, selector); g->sp++; recvrSlot = selSlot - 1; classobj = classOfSlot(recvrSlot); index = slotRawInt(&classobj->classIndex) + s_nocomprendo->u.index; meth = gRowTable[index]; if (slotRawClass(&meth->ownerclass) == class_object) { // lookup instance specific method uniqueMethodSlot = &g->classvars->slots[cvxUniqueMethods]; if (isKindOfSlot(uniqueMethodSlot, class_identdict)) { arraySlot = slotRawObject(uniqueMethodSlot)->slots + ivxIdentDict_array; if ((IsObj(arraySlot) && (array = slotRawObject(arraySlot))->classptr == class_array)) { i = arrayAtIdentityHashInPairs(array, recvrSlot); if (i >= 0) { slot = array->slots + i; if (NotNil(slot)) { ++slot; if (isKindOfSlot(slot, class_identdict)) { arraySlot = slotRawObject(slot)->slots + ivxIdentDict_array; if ((IsObj(arraySlot) && (array = slotRawObject(arraySlot))->classptr == class_array)) { i = arrayAtIdentityHashInPairs(array, selSlot); if (i >= 0) { slot = array->slots + i; if (NotNil(slot)) { ++slot; slotCopy(selSlot, recvrSlot); slotCopy(recvrSlot, slot); blockValue(g, (int)numArgsPushed+1); return; } } } } } } } } } executeMethod(g, meth, numArgsPushed+1); #ifdef GC_SANITYCHECK g->gc->SanityCheck(); #endif }