void VMEventModifier::deoptimize_method(Method *m) { #if ENABLE_COMPILER // If we insert a breakpoint into a method, that method may be compiled // and there may be countless frames in the system that reference // that method. We must find all these frames and deoptimized them so that // we hit this breakpoint. UsingFastOops fast_oops; Thread::Fast thread = Universe::global_threadlist(); while (thread.not_null() && thread().last_java_fp() != NULL) { JavaFrame fr(&thread); bool top_frame = true; while(true) { if (fr.is_entry_frame()) { if (fr.as_EntryFrame().is_first_frame()) { break; } top_frame = false; fr.as_EntryFrame().caller_is(fr); } else { UsingFastOops fast_oops2; GUARANTEE(fr.is_java_frame(), "Neither JavaFrame or EntryFrame"); Method::Fast method = fr.method(); if (method.equals(*m)) { // found a reference to this method on some frame, deoptimize it if (fr.is_compiled_frame()) { // deoptimize essentially restarts the current instruction in this // frame when we return to interpreter_deoptimize_entry. // However, in our case we can't restart the instruction // since all the stack (with args etc) is popped off. We really // want to continue in the interpreter at the following instruction // Hence we bump up the bci by 3 (after checking to make sure // it's an invoke we are pointing at). fr.deoptimize_and_continue(!top_frame); } } top_frame = false; fr.caller_is(fr); } } thread = thread().global_next(); } #endif }
ReturnOop VMEventModifier::new_modifier(PacketInputStream *in, PacketOutputStream *out, bool& error) { UsingFastOops fast_oops; jbyte mod_kind = in->read_byte(); VMEventModifier::Fast newMod; Thread::Fast thread; newMod = allocate_modifier(); if (newMod.is_null()) { error = true; out->set_error(JDWP_Error_OUT_OF_MEMORY); return NULL; } newMod().set_mod_kind(mod_kind); #ifdef AZZERT if (TraceDebugger) { tty->print_cr("Modifier: modkind = %d", mod_kind); } #endif switch(mod_kind) { case JDWP_EventRequest_Set_Out_modifiers_Modifier_FieldOnly: // unsupported in->read_class_id(); in->read_class_id(); in->read_int(); return NULL; case JDWP_EventRequest_Set_Out_modifiers_Modifier_Conditional: // unsupported in->read_int(); return NULL; case JDWP_EventRequest_Set_Out_modifiers_Modifier_ClassExclude: // unsupported in->read_string(); return NULL; case JDWP_EventRequest_Set_Out_modifiers_Modifier_ThreadOnly: newMod().set_thread_id(in->read_thread_id()); return newMod; case JDWP_EventRequest_Set_Out_modifiers_Modifier_Count: newMod().set_count(in->read_int()); return newMod; case JDWP_EventRequest_Set_Out_modifiers_Modifier_ClassOnly: { newMod().set_clazz_id(in->read_class_id()); #ifdef AZZERT if (TraceDebugger) { tty->print_cr("Modifier: class_id = %d", newMod().clazz_id()); } #endif return newMod; } case JDWP_EventRequest_Set_Out_modifiers_Modifier_ClassMatch: { UsingFastOops fast_oops_2; int length; SETUP_ERROR_CHECKER_ARG; TypeArray::Fast ta = in->read_raw_string(length JVM_NO_CHECK); if (ta.is_null()) { // Out of memory?? Things will fall apart soon enough, // We just punt on this modifier return newMod; } for (int i = length - 1; i >= 0; i--) { if (ta().byte_at(i) == '.') { ta().byte_at_put(i, '/'); } } Symbol::Fast tmpName = Universe::new_symbol(&ta, (utf8)(ta().base_address()), length JVM_NO_CHECK); if (tmpName.is_null()) { error = true; out->set_error(JDWP_Error_OUT_OF_MEMORY); return NULL; } #ifdef AZZERT if (TraceDebugger) { tty->print("Modifier: class match = "); tmpName().print_symbol_on(tty); tty->cr(); } #endif ClassMatchModifier::Fast class_match_modifier = newMod().obj(); class_match_modifier().set_class_match_name(&tmpName); return newMod; } case JDWP_EventRequest_Set_Out_modifiers_Modifier_LocationOnly: { UsingFastOops fast_oops_3; jbyte tag = in->read_byte(); (void)tag; LocationModifier::Fast lmod = newMod.obj(); lmod().set_clazz_id(in->read_class_id()); if (lmod().clazz_id() == 0) { return NULL; /* Class ID == 0 is invalid */ } lmod().set_method_id(in->read_method_id()); lmod().set_offset(in->read_long()); #ifdef AZZERT if (TraceDebugger) { tty->print_cr("Loc: class: 0x%x, method: 0x%x, off: 0x%x", lmod().clazz_id(), (int)(lmod().method_id() & 0xFFFFFFFF), lmod().offset()); } #endif return lmod; } case JDWP_EventRequest_Set_Out_modifiers_Modifier_ExceptionOnly: { UsingFastOops fast_oops_4; ExceptionModifier::Fast emod = newMod.obj(); emod().set_clazz_id(in->read_class_id()); emod().set_sig_caught(in->read_boolean()); emod().set_sig_uncaught(in->read_boolean()); return emod; } case JDWP_EventRequest_Set_Out_modifiers_Modifier_Step: { UsingFastOops fast_oops_5; int thread_id = in->read_thread_id(); thread = JavaDebugger::get_thread_by_id(thread_id); if (!JavaDebugger::is_valid_thread(&thread) || !thread().last_java_frame_exists()) { error = true; out->set_error(JDWP_Error_INVALID_THREAD); return NULL; } Frame fr(&thread); GUARANTEE(fr.is_java_frame(), "Single step must start at JavaFrame"); JavaFrame jf = fr.as_JavaFrame(); LocationModifier::Fast loc = LocationModifier::new_location(&jf); if (loc.is_null()) { error = true; out->set_error(JDWP_Error_OUT_OF_MEMORY); return NULL; } #ifdef AZZERT if (TraceDebugger) { tty->print_cr("StepLoc: thread: 0x%x, class: 0x%x, method: 0x%x, off: 0x%x", thread_id, loc().clazz_id(), (int)(loc().method_id() & 0xFFFFFFFF), loc().offset()); } #endif loc().set_mod_kind(mod_kind); StepModifier::Fast smod = loc.obj(); smod().set_thread_id(thread_id); if (thread.is_null() /* || (thread.state() & THREAD_DEAD) */) { /* * If you try to single step after suspending because * of an uncaught exception event we'll get sent the * thread id of the thread that had the exception. * That thread is dead though. */ error = true; out->set_error(JDWP_Error_INVALID_THREAD); return NULL; } smod().set_step_size(in->read_int()); smod().set_step_depth(in->read_int()); /* query the _proxy_ for next line location */ { UsingFastOops fast_oops_6; DebuggerEvent d_event; d_event.set_event_kind((jbyte)VM_STEPINFO_EVENT); VMEvent::stepping_info_request(&d_event, in->transport(), &smod); /* * At this point, the proxy has made sure no more commands * from the debugger get sent until we get our line number * info from the proxy */ JavaDebugger::set_loop_count(1); JavaDebugger::process_command_loop(); /* * Once we get back here, then we know we've gotten the * command from the proxy with the line number info put into * the StepModifier object in the step_info_event above. */ /* setup the relevant info */ thread().set_is_stepping(true); // set the _debugger_active flag for the interpreter loop JavaDebugger::set_stepping(true); // smod = step_info_event().mods(); // smod().set_step_target_offset(stepData().step_target_offset()); smod().unlink_method(); if (smod().step_depth() == JDWP_StepDepth_OUT) { // if stepping out to the caller, we really should unlink any // compiled code from here to the caller frame, for now assume // one frame up. It could be re-compiled but we may luck out. Method::Fast m; Frame caller(jf); jf.caller_is(caller); if (!caller.is_entry_frame()) { m = caller.as_JavaFrame().method(); #if ENABLE_COMPILER if (m().has_compiled_code()) { m().unlink_compiled_code(); } #endif } } smod().set_step_starting_fp(DISTANCE(thread().stack_base(), jf.fp())); smod().set_step_starting_offset(jf.bci()); // smod().set_dup_current_line_offset(stepData().dup_current_line_offset()); // smod().set_post_dup_line_offset(stepData().post_dup_line_offset()); thread().set_step_info(&smod); } return smod; } } error = true; out->set_error(JDWP_Error_NOT_IMPLEMENTED); return NULL; }
/* * void nativeStart(Object [] startupState) * where startupState contains the following: * String classname * String [] args * String [][] context * * Note: all objects passed in parameters belongs to the new isolate * and no copy are necessary. See comments in com.sun.cldc.isolate.Isolate. */ void Java_com_sun_cldc_isolate_Isolate_nativeStart(JVM_SINGLE_ARG_TRAPS) { Thread::Raw saved; bool has_exception = false; const int id = Task::allocate_task_id(JVM_SINGLE_ARG_CHECK); { UsingFastOops fast_oops; IsolateObj::Fast isolate = GET_PARAMETER_AS_OOP(0); ObjectHeap::set_task_memory_quota(id, isolate().memory_reserve(), isolate().memory_limit() JVM_CHECK); const int prev = ObjectHeap::on_task_switch( id ); saved = Task::create_task(id, &isolate JVM_NO_CHECK); ObjectHeap::on_task_switch( prev ); if( saved.is_null() ) { ObjectHeap::reset_task_memory_usage(id); Task::cleanup_unstarted_task(id); isolate().terminate(-1 JVM_NO_CHECK_AT_BOTTOM); return; } } // save current thread pointer, no non-raw handles please! Thread::Raw current = Thread::current(); Thread::set_current(&saved); { // handles ok now UsingFastOops fast_oops; Thread::Fast orig = ¤t(); Thread::Fast t = &saved(); // IMPL_NOTE: SHOULDN'T WE DO SOMETHING HERE IF THERE IS SOME EXCEPTION // RELATED TO STARTUP FAILURE (i.e., reclaim the task's id and // proceed to task termination cleanup, including sending of // isolate events) Task::start_task(&t JVM_NO_CHECK); has_exception = (CURRENT_HAS_PENDING_EXCEPTION != NULL); current = orig; // GC may have happened. Reload. saved = t; // GC may have happened. Reload. } // we set the current thread back to the original so that the C interpreter // will switch threads correctly. The new thread/task is set to be the // next thread/task to run when switch_thread is called a few instructions // from now. Thread::set_current(¤t); if (has_exception) { UsingFastOops fast_oops; // new isolate got an exception somewhere during start_task(). The isolate // may not be able to handle the exception since we don't know at which // point it got the exception. Some classes may not be initialized, // task mirrors may not be setup etc. We just tear down the new isolate // and return an exception to the parent. Task::Fast task = Task::get_task(id); IsolateObj::Fast isolate = GET_PARAMETER_AS_OOP(0); Thread::Fast thrd = &saved(); GUARANTEE(!task.is_null(), "Task should not be null at this point"); task().set_status(Task::TASK_STOPPED); task().set_thread_count(0); isolate().terminate(-1 JVM_NO_CHECK); saved = thrd; // GC may have happened. Reload. } if (has_exception) { // Convoluted dance here. Child isolate failed to start // We check the type of exception // if (exception == oome) // throw oome to parent // else if (exception == isolateresourceerror) // throw IsolateResourceError to parent // else // throw java.lang.Error to parent // Make sure we don't have any handles to child objects before // calling Task::cleanup_terminated_task() // UsingFastOops fast_oops; Thread::Fast thrd = &saved(); JavaOop::Fast exception = thrd().noncurrent_pending_exception(); String::Fast str; { ThreadObj::Raw thread_obj = thrd().thread_obj(); // Mark thread as terminated even though it never really started if (!thread_obj.is_null()) { thread_obj().set_terminated(); } } Scheduler::terminate(&thrd JVM_NO_CHECK); thrd.set_null(); // thrd handle has to be disposed here JavaOop::Fast new_exception = Universe::out_of_memory_error_instance(); JavaClass::Fast exception_class = exception().blueprint(); // oome class *must* be loaded in parent, how can it not be? InstanceClass::Fast oome_class = SystemDictionary::resolve(Symbols::java_lang_OutOfMemoryError(), ErrorOnFailure JVM_NO_CHECK); InstanceClass::Fast ire_class = SystemDictionary::resolve(Symbols::com_sun_cldc_isolate_IsolateResourceError(), ErrorOnFailure JVM_NO_CHECK); if( oome_class.not_null() && !oome_class.equals(&exception_class) && ire_class.not_null() ) { new_exception = Throw::allocate_exception( ire_class.equals(&exception_class) ? Symbols::com_sun_cldc_isolate_IsolateResourceError() : Symbols::java_lang_Error(), &str JVM_NO_CHECK); } exception_class.set_null(); // cleared handles to child objects exception.set_null(); // Task::cleanup_terminated_task(id JVM_NO_CHECK); Thread::set_current_pending_exception(&new_exception); } }
void VMEvent::send_event(DebuggerEvent *d_event) { check_notify_wanted(JDWP_eventkind_to_dbg_eventkind(d_event->event_kind())); UsingFastOops fast_oops; VMEvent::Fast ep, ep_2; JavaClass::Fast jc; int event_count = 0; jbyte suspend_policy = JDWP_SuspendPolicy_NONE; int data_len = JDWP_EVENT_LEN; ep = ep_2 = get_event_request(d_event, event_count, suspend_policy); if (ep.is_null()) { return; } // Flush any packets waiting in the queue. This helps avoid a race // condition where we may have a resume command in the queue for a // previous event, we send this event, process the resume command // out of order JavaDebugger::dispatch(0); // Calculate packet length while (ep_2.not_null()) { switch(ep_2().event_kind()) { case JDWP_EventKind_SINGLE_STEP: case JDWP_EventKind_BREAKPOINT: data_len += JDWP_EVENT_BREAK_LEN; break; case JDWP_EventKind_THREAD_START: case JDWP_EventKind_THREAD_DEATH: data_len += JDWP_EVENT_THREAD_LEN; break; case JDWP_EventKind_CLASS_PREPARE: case JDWP_EventKind_CLASS_LOAD: jc = JavaDebugger::get_object_by_id(d_event->clazz_id()); data_len += (9 + class_prepare_info_length(&jc)); break; case JDWP_EventKind_CLASS_UNLOAD: jc = JavaDebugger::get_object_by_id(d_event->clazz_id()); data_len += (5 + PacketOutputStream::get_class_name_length(&jc)); break; } ep_2 = ep_2().send_next(); } Transport::Fast transport = ep().transport(); PacketOutputStream out(&transport, data_len, JDWP_COMMAND_SET(Event), JDWP_COMMAND(Event, Composite)); UsingFastOops fast_oops_2; Thread::Fast thread = JavaDebugger::get_thread_by_id(d_event->thread_id()); if (thread.is_null()) { // Some events were created before any threads were ready, so just // use the current thread thread = Thread::current(); } DEBUGGER_EVENT(("VM Event xprt=0x%x, thrd=0x%x, id=0x%x, kind=0x%x, susp.=0x%x", transport.obj(), d_event->thread_id(), ep().event_id(), ep().event_kind(), suspend_policy)); out.write_byte(suspend_policy); out.write_int(event_count); while (ep.not_null()) { // transport = ep().transport(); // out.set_transport(&transport); out.write_byte(ep().event_kind()); out.write_int(ep().event_id()); switch(ep().event_kind()) { case JDWP_EventKind_SINGLE_STEP: case JDWP_EventKind_BREAKPOINT: { UsingFastOops fast_oops_3; out.write_int(d_event->thread_id()); DEBUGGER_EVENT(("Event clss=0x%x, mthd=0x%x, off=0x%x", d_event->clazz_id(), (int)(d_event->method_id() & 0xFFFFFFFF), d_event->offset())); #ifdef AZZERT if (TraceDebugger) { InstanceClass::Raw ic = JavaDebugger::get_object_by_id(d_event->clazz_id()); Method::Raw m = JavaDebugger::get_method_by_id(&ic, d_event->method_id()); m().print_name_on(tty); tty->cr(); } #endif d_event->write_as_location(&out); // IMPL_NOTE: I don't think we can ever get here with a compiled frame VMEventModifier::deoptimize_frame(&thread); break; } case JDWP_EventKind_THREAD_START: case JDWP_EventKind_THREAD_DEATH: out.write_int(d_event->thread_id()); break; case JDWP_EventKind_CLASS_PREPARE: case JDWP_EventKind_CLASS_LOAD: { out.write_int(d_event->thread_id()); DEBUGGER_EVENT(("Event clss=0x%x", d_event->clazz_id())); jc = JavaDebugger::get_object_by_id(d_event->clazz_id()); #ifdef AZZERT if (TraceDebugger) { jc().print_name_on(tty); tty->cr(); } #endif out.write_class_prepare_info(&jc); break; } case JDWP_EventKind_CLASS_UNLOAD: { jc = JavaDebugger::get_object_by_id(d_event->clazz_id()); out.write_class_name(&jc); break; } } ep = ep().send_next(); } out.send_packet(); JavaDebugger::process_suspend_policy(suspend_policy, &thread, false); }