This is the mail archive of the
java-patches@gcc.gnu.org
mailing list for the Java project.
[RFA] [Un]Register single step
- From: Keith Seitz <keiths at redhat dot com>
- To: Java Patch List <java-patches at gcc dot gnu dot org>
- Date: Thu, 08 Feb 2007 11:19:59 -0800
- Subject: [RFA] [Un]Register single step
Hi,
The attached patch implements the JDWP side of single step event
registration (and "unregistration"). Most of what it does is simply
massaging data received from the JDWP backend (in classpath) and store
it in a more useful form (along with some new data) to facilitate
decision making during single stepping. [You get to see how that's done
when I submit the related callback function.]
Comments/questions/concerns?
Keith
ChangeLog
2007-02-08 Keith Seitz <keiths@redhat.com>
* gnu/classpath/jdwp/VMVirtualMachine.java
(_stepping_threads): New member.
* gnu/classpath/jdwp/VMVirtualMachine.class:
Regenerated.
* gnu/classpath/jdwp/VMVirtualMachine.h:
Regenerated.
* gnu/claspath/jdwp/natVMVirtualMachine.cc
(get_request_step_filter): New function.
(DISABLE_EVENT): New macro.
(initialize): Initialize _stepping_threads.
(registerEvent): Implement EVENT_SINGLE_STEP.
(unregisterEvent): Likewise.
Index: gnu/classpath/jdwp/VMVirtualMachine.java
===================================================================
--- gnu/classpath/jdwp/VMVirtualMachine.java (revision 121716)
+++ gnu/classpath/jdwp/VMVirtualMachine.java (working copy)
@@ -1,7 +1,7 @@
/* VMVirtualMachine.java -- A reference implementation of a JDWP virtual
machine
- Copyright (C) 2005, 2006 Free Software Foundation
+ Copyright (C) 2005, 2006, 2007 Free Software Foundation
This file is part of GNU Classpath.
@@ -61,6 +61,9 @@
// Thread suspension table. Maps Thread to suspend count (Integer)
private static Hashtable _jdwp_suspend_counts;
+ // List of stepping threads: maps Thread -> stepping info
+ static Hashtable _stepping_threads;
+
public static native void initialize ();
/**
Index: gnu/classpath/jdwp/natVMVirtualMachine.cc
===================================================================
--- gnu/classpath/jdwp/natVMVirtualMachine.cc (revision 121716)
+++ gnu/classpath/jdwp/natVMVirtualMachine.cc (working copy)
@@ -11,6 +11,7 @@
#include <config.h>
#include <gcj/cni.h>
#include <java-assert.h>
+#include <java-interp.h>
#include <jvm.h>
#include <jvmti.h>
@@ -39,9 +40,11 @@
#include <gnu/classpath/jdwp/event/VmInitEvent.h>
#include <gnu/classpath/jdwp/event/filters/IEventFilter.h>
#include <gnu/classpath/jdwp/event/filters/LocationOnlyFilter.h>
+#include <gnu/classpath/jdwp/event/filters/StepFilter.h>
#include <gnu/classpath/jdwp/exception/InvalidLocationException.h>
#include <gnu/classpath/jdwp/exception/InvalidMethodException.h>
#include <gnu/classpath/jdwp/exception/JdwpInternalErrorException.h>
+#include <gnu/classpath/jdwp/id/ThreadId.h>
#include <gnu/classpath/jdwp/util/Location.h>
#include <gnu/classpath/jdwp/util/MethodResult.h>
#include <gnu/gcj/jvmti/Breakpoint.h>
@@ -51,8 +54,19 @@
using namespace gnu::classpath::jdwp::event;
using namespace gnu::classpath::jdwp::util;
+// Stepping information
+struct step_info
+{
+ jint size; // See gnu.classpath.jdwp.JdwpConstants.StepSize
+ jint depth; // See gnu.classpath.jdwp.JdwpConstants.StepDepth
+ int stack_depth; // stack depth at start of stepping
+ jmethodID method; // method in which we are stepping
+};
+
// Forward declarations
static Location *get_request_location (EventRequest *);
+static gnu::classpath::jdwp::event::filters::StepFilter *
+get_request_step_filter (EventRequest *);
static void JNICALL jdwpClassPrepareCB (jvmtiEnv *, JNIEnv *, jthread, jclass);
static void JNICALL jdwpThreadEndCB (jvmtiEnv *, JNIEnv *, jthread);
static void JNICALL jdwpThreadStartCB (jvmtiEnv *, JNIEnv *, jthread);
@@ -61,6 +75,9 @@
static void throw_jvmti_error (jvmtiError);
#define DEFINE_CALLBACK(Cb,Event) Cb.Event = jdwp ## Event ## CB
+#define DISABLE_EVENT(Event,Thread) \
+ _jdwp_jvmtiEnv->SetEventNotificationMode (JVMTI_DISABLE, \
+ JVMTI_EVENT_ ## Event, Thread)
#define ENABLE_EVENT(Event,Thread) \
_jdwp_jvmtiEnv->SetEventNotificationMode (JVMTI_ENABLE, \
JVMTI_EVENT_ ## Event, Thread)
@@ -77,6 +94,8 @@
gnu::classpath::jdwp::VMVirtualMachine::initialize ()
{
_jdwp_suspend_counts = new ::java::util::Hashtable ();
+ _stepping_threads = new ::java::util::Hashtable ();
+
JavaVM *vm = _Jv_GetJavaVM ();
vm->GetEnv (reinterpret_cast<void **> (&_jdwp_jvmtiEnv), JVMTI_VERSION_1_0);
@@ -196,6 +215,32 @@
switch (request->getEventKind ())
{
case EventRequest::EVENT_SINGLE_STEP:
+ {
+ Thread *thread;
+ filters::StepFilter *filter = get_request_step_filter (request);
+ if (filter == NULL)
+ {
+ // No filter specified: report every step in every
+ // thread.
+ thread = NULL;
+ }
+ else
+ {
+ // Add stepping information to list of stepping threads
+ thread = filter->getThread ()->getThread ();
+ _Jv_InterpFrame *frame
+ = reinterpret_cast<_Jv_InterpFrame *> (thread->interp_frame);
+ struct step_info *sinfo
+ = (struct step_info *) JvAllocBytes (sizeof (struct step_info));
+ sinfo->size = filter->getSize ();
+ sinfo->depth = filter->getDepth ();
+ sinfo->stack_depth = frame->depth ();
+ sinfo->method = frame->self->get_method ();
+ _stepping_threads->put (thread, (jobject) sinfo);
+ }
+
+ ENABLE_EVENT (SINGLE_STEP, thread);
+ }
break;
case EventRequest::EVENT_BREAKPOINT:
@@ -273,6 +318,19 @@
switch (request->getEventKind ())
{
case EventRequest::EVENT_SINGLE_STEP:
+ {
+ Thread *thread;
+ filters::StepFilter *filter = get_request_step_filter (request);
+ if (filter == NULL)
+ thread = NULL;
+ else
+ {
+ thread = filter->getThread ()->getThread ();
+ _stepping_threads->remove (thread);
+ }
+
+ DISABLE_EVENT (SINGLE_STEP, thread);
+ }
break;
case EventRequest::EVENT_BREAKPOINT:
@@ -482,6 +540,26 @@
return NULL;
}
+static gnu::classpath::jdwp::event::filters::StepFilter *
+get_request_step_filter (EventRequest *request)
+{
+ ::java::util::Collection *filters = request->getFilters ();
+ ::java::util::Iterator *iter = filters->iterator ();
+ filters::StepFilter *filter = NULL;
+ while (iter->hasNext ())
+ {
+ using namespace gnu::classpath::jdwp::event::filters;
+ IEventFilter *next = (IEventFilter *) iter->next ();
+ if (next->getClass () == &StepFilter::class$)
+ {
+ filter = reinterpret_cast<StepFilter *> (next);
+ break;
+ }
+ }
+
+ return filter;
+}
+
static Location *
get_request_location (EventRequest *request)
{