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;
}
Beispiel #3
0
/*
 * 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 = &current();
    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(&current);
  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);
  }
}
Beispiel #4
0
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);
}