boolean dispatch_static_initializer (ClassRecord *aRec, byte *retAddr) { if (is_initialized (aRec)) return false; set_initialized (aRec); if (!has_clinit (aRec)) return false; #if DEBUG_METHODS printf ("dispatch_static_initializer: has clinit: %d, %d\n", (int) aRec, (int) retAddr); #endif dispatch_special (find_method (aRec, _6clinit_7_4_5V), retAddr); return true; }
/** * Calls static initializer if necessary before * dispatching with dispatch_special(). * @param retAddr Return bytecode address. * @param btAddr Backtrack bytecode address (in case * static initializer is executed). */ void dispatch_special_checked (byte classIndex, byte methodIndex, byte *retAddr, byte *btAddr) { ClassRecord *classRecord; #if DEBUG_METHODS printf ("dispatch_special_checked: %d, %d, %d, %d\n", classIndex, methodIndex, (int) retAddr, (int) btAddr); #endif classRecord = get_class_record (classIndex); if (dispatch_static_initializer (classRecord, btAddr)) return; dispatch_special (get_method_record (classRecord, methodIndex), retAddr); }
void dispatch_virtual (Object *ref, int signature, byte *retAddr) { ClassRecord *classRecord; MethodRecord *methodRecord; int classIndex; #if DEBUG_METHODS printf("dispatch_virtual %d\n", signature); #endif if (ref == JNULL) { throw_new_exception (JAVA_LANG_NULLPOINTEREXCEPTION); return; } // When calling methods on arrays, we use the methods for the Object class... classIndex = get_class_index(ref); LABEL_METHODLOOKUP: classRecord = get_class_record (classIndex); methodRecord = find_method (classRecord, signature); if (methodRecord == null) { #if SAFE if (classIndex == JAVA_LANG_OBJECT) { throw_new_exception (JAVA_LANG_NOSUCHMETHODERROR); return; } #endif classIndex = classRecord->parentClass; goto LABEL_METHODLOOKUP; } if (dispatch_special (methodRecord, retAddr)) { if (is_synchronized(methodRecord)) { current_stackframe()->monitor = ref; enter_monitor (currentThread, ref); } } }
void dispatch_virtual (Object *ref, TWOBYTES signature, byte *retAddr) { MethodRecord *auxMethodRecord; byte auxByte; #if DEBUG_METHODS printf("dispatch_virtual %d\n", signature); #endif if (ref == JNULL) { throw_exception (nullPointerException); return; } auxByte = get_class_index(ref); LABEL_METHODLOOKUP: tempClassRecord = get_class_record (auxByte); auxMethodRecord = find_method (tempClassRecord, signature); if (auxMethodRecord == null) { #if SAFE if (auxByte == JAVA_LANG_OBJECT) { throw_exception (noSuchMethodError); return; } #endif auxByte = tempClassRecord->parentClass; goto LABEL_METHODLOOKUP; } if (dispatch_special (auxMethodRecord, retAddr)) { if (is_synchronized(auxMethodRecord)) { current_stackframe()->monitor = ref; enter_monitor (currentThread, ref); } } }
/** * Calls static initializer if necessary before * dispatching with dispatch_special(). * @param retAddr Return bytecode address. * @param btAddr Backtrack bytecode address (in case * static initializer is executed). */ void dispatch_special_checked (byte classIndex, byte methodIndex, byte *retAddr, byte *btAddr) { ClassRecord *classRecord; MethodRecord *methodRecord; #if DEBUG_METHODS printf ("dispatch_special_checked: %d, %d, %d, %d\n", classIndex, methodIndex, (int) retAddr, (int) btAddr); #endif // If we need to run the initializer then the real method will get called // later, when we re-run the current instruction. classRecord = get_class_record (classIndex); if (!is_initialized_idx (classIndex)) if (dispatch_static_initializer (classRecord, btAddr) != EXEC_CONTINUE) return; methodRecord = get_method_record (classRecord, methodIndex); if(dispatch_special (methodRecord, retAddr)) { if (is_synchronized(methodRecord)) { if (!is_static(methodRecord)) { Object *ref = (Object *)curLocalsBase[0]; current_stackframe()->monitor = ref; enter_monitor (currentThread, ref); } else { Object *ref = (Object *)classRecord; current_stackframe()->monitor = ref; enter_monitor (currentThread, ref); } } } }
/** A select_handler_T read_func for itrm_in.sock. A slave process * calls this when the master sends it data to be displayed. The * master process never calls this. */ static void in_sock(struct itrm *itrm) { struct string path; struct string delete_; char ch; int fg; /* enum term_exec */ ssize_t bytes_read, i, p; unsigned char buf[ITRM_OUT_QUEUE_SIZE]; bytes_read = safe_read(itrm->in.sock, buf, ITRM_OUT_QUEUE_SIZE); if (bytes_read <= 0) goto free_and_return; qwerty: for (i = 0; i < bytes_read; i++) if (!buf[i]) goto has_nul_byte; safe_hard_write(itrm->out.std, buf, bytes_read); return; has_nul_byte: if (i) safe_hard_write(itrm->out.std, buf, i); i++; assert(ITRM_OUT_QUEUE_SIZE - i > 0); memmove(buf, buf + i, ITRM_OUT_QUEUE_SIZE - i); bytes_read -= i; p = 0; #define RD(xx) { \ unsigned char cc; \ \ if (p < bytes_read) \ cc = buf[p++]; \ else if ((hard_read(itrm->in.sock, &cc, 1)) <= 0) \ goto free_and_return; \ xx = cc; \ } RD(fg); if (!init_string(&path)) goto free_and_return; while (1) { RD(ch); if (!ch) break; add_char_to_string(&path, ch); } if (!init_string(&delete_)) { done_string(&path); goto free_and_return; } while (1) { RD(ch); if (!ch) break; add_char_to_string(&delete_, ch); } #undef RD if (!*path.source) { dispatch_special(delete_.source); } else { int blockh; unsigned char *param; int path_len, del_len, param_len; /* TODO: Should this be changed to allow TERM_EXEC_NEWWIN * in a blocked terminal? There is similar code in * exec_on_terminal(). --KON, 2007 */ if (is_blocked() && fg != TERM_EXEC_BG) { if (*delete_.source) unlink(delete_.source); goto nasty_thing; } path_len = path.length; del_len = delete_.length; param_len = path_len + del_len + 3; param = mem_alloc(param_len); if (!param) goto nasty_thing; param[0] = fg; memcpy(param + 1, path.source, path_len + 1); memcpy(param + 1 + path_len + 1, delete_.source, del_len + 1); if (fg == TERM_EXEC_FG) block_itrm(); blockh = start_thread((void (*)(void *, int)) exec_thread, param, param_len); mem_free(param); if (blockh == -1) { if (fg == TERM_EXEC_FG) unblock_itrm(); goto nasty_thing; } if (fg == TERM_EXEC_FG) { set_handlers(blockh, (select_handler_T) unblock_itrm_x, NULL, (select_handler_T) unblock_itrm_x, (void *) (long) blockh); } else { set_handlers(blockh, close_handle, NULL, close_handle, (void *) (long) blockh); } } nasty_thing: done_string(&path); done_string(&delete_); assert(ITRM_OUT_QUEUE_SIZE - p > 0); memmove(buf, buf + p, ITRM_OUT_QUEUE_SIZE - p); bytes_read -= p; goto qwerty; free_and_return: free_itrm(itrm); }
/** * Exceute the static initializer if required. Note that the ret address used * here is set such that the current instruction will be re-started when the * initialization completes. * @return An indication of how the VM should proceed */ int dispatch_static_initializer (ClassRecord *aRec, byte *retAddr) { int state = get_init_state(aRec); ClassRecord *init = aRec; ClassRecord *super = get_class_record(init->parentClass); MethodRecord *method; // Are we needed? if (state & C_INITIALIZED) return EXEC_CONTINUE; // We need to initialize all of the super classes first. So we find the // highest one that has not been initialized and deal with that. This code // will then be called again and we will init the next highest and so on // until all of the classes in the chain are done. for(;;) { // find first super class that has not been initialized while (init != super && (get_init_state(super) & C_INITIALIZED) == 0) { init = super; super = get_class_record(init->parentClass); } // Do we have an initilizer if so we have found our class if (has_clinit (init)) break; // no initializer so mark as now initialized set_init_state (init, C_INITIALIZED); // If we are at the start of the list we are done if (init == aRec) return EXEC_CONTINUE; // Otherwise go do it all again init = aRec; } state = get_init_state(init); // are we already initializing ? if (state & C_INITIALIZING) { // Is it this thread that is doing the init? if (get_sync(init)->threadId == currentThread->threadId) return EXEC_CONTINUE; // No so we must retry the current instruction curPc = retAddr; sleep_thread(1); schedule_request(REQUEST_SWITCH_THREAD); return EXEC_RETRY; } #if DEBUG_METHODS printf ("dispatch_static_initializer: has clinit: %d, %d\n", (int) aRec, (int) retAddr); #endif // Static initializer is always the first method method = get_method_table(init); if ((byte *)method == get_binary_base() || method->signatureId != _6clinit_7_4_5V) { throw_new_exception (JAVA_LANG_NOSUCHMETHODERROR); return EXEC_EXCEPTION; } // Can we run it? if (!dispatch_special (method, retAddr)) return EXEC_RETRY; // Mark for next time set_init_state(init, C_INITIALIZING); // and claim the monitor current_stackframe()->monitor = (Object *)init; enter_monitor (currentThread, (Object *)init); return EXEC_RUN; }