This is the mail archive of the
java-patches@gcc.gnu.org
mailing list for the Java project.
Re: [RFA/JDWP] [Un]Register breakpoint events
- From: Keith Seitz <keiths at redhat dot com>
- To: Java Patch List <java-patches at gcc dot gnu dot org>
- Date: Thu, 01 Feb 2007 17:56:14 -0800
- Subject: Re: [RFA/JDWP] [Un]Register breakpoint events
- References: <45C2839B.2080507@uglyboxes.com>
[cough] I meant the attached patch. Really. I did.
Keith
Keith Seitz wrote:
Hi,
The attach patch adds support for registering and unregistering
breakpoint events. With this patch, it should now be possible to set and
clear breakpoints in the interpreter. This is one of two remaining
patches which remains to fully implement breakpoints for JDWP. A
follow-on patch implementing the JVMTI breakpoint callback is all that
remains.
Keith
ChangeLog
2007-02-01 Keith Seitz <keiths@redhat.com>
* gnu/classpath/jdwp/natVMVirtualMachine.cc
(registerEvent): Implement EVENT_BREAKPOINT.
(unregisterEvent): Likewise.
(get_request_location): New function.
Index: gnu/classpath/jdwp/natVMVirtualMachine.cc
===================================================================
--- gnu/classpath/jdwp/natVMVirtualMachine.cc (revision 121341)
+++ gnu/classpath/jdwp/natVMVirtualMachine.cc (working copy)
@@ -10,6 +10,7 @@
#include <config.h>
#include <gcj/cni.h>
+#include <java-assert.h>
#include <jvm.h>
#include <jvmti.h>
@@ -21,6 +22,7 @@
#include <java/lang/Thread.h>
#include <java/nio/ByteBuffer.h>
#include <java/util/ArrayList.h>
+#include <java/util/Collection.h>
#include <java/util/Hashtable.h>
#include <java/util/Iterator.h>
@@ -29,20 +31,28 @@
#include <gnu/classpath/jdwp/VMMethod.h>
#include <gnu/classpath/jdwp/VMVirtualMachine.h>
#include <gnu/classpath/jdwp/event/ClassPrepareEvent.h>
+#include <gnu/classpath/jdwp/event/EventManager.h>
#include <gnu/classpath/jdwp/event/EventRequest.h>
#include <gnu/classpath/jdwp/event/ThreadEndEvent.h>
#include <gnu/classpath/jdwp/event/ThreadStartEvent.h>
#include <gnu/classpath/jdwp/event/VmDeathEvent.h>
#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/exception/InvalidLocationException.h>
#include <gnu/classpath/jdwp/exception/InvalidMethodException.h>
#include <gnu/classpath/jdwp/exception/JdwpInternalErrorException.h>
+#include <gnu/classpath/jdwp/util/Location.h>
#include <gnu/classpath/jdwp/util/MethodResult.h>
+#include <gnu/gcj/jvmti/Breakpoint.h>
+#include <gnu/gcj/jvmti/BreakpointManager.h>
using namespace java::lang;
using namespace gnu::classpath::jdwp::event;
using namespace gnu::classpath::jdwp::util;
// Forward declarations
+static Location *get_request_location (EventRequest *);
static void JNICALL jdwpClassPrepareCB (jvmtiEnv *, JNIEnv *, jthread, jclass);
static void JNICALL jdwpThreadEndCB (jvmtiEnv *, JNIEnv *, jthread);
static void JNICALL jdwpThreadStartCB (jvmtiEnv *, JNIEnv *, jthread);
@@ -189,8 +199,30 @@
break;
case EventRequest::EVENT_BREAKPOINT:
- break;
+ {
+ using namespace ::gnu::gcj::jvmti;
+ Location *loc = get_request_location (request);
+ if (loc == NULL)
+ {
+ using namespace gnu::classpath::jdwp::exception;
+ throw new InvalidLocationException ();
+ }
+ jlong method = loc->getMethod ()->getId ();
+ jlocation index = loc->getIndex ();
+ Breakpoint *bp = BreakpointManager::getBreakpoint (method, index);
+ if (bp == NULL)
+ {
+ // Breakpoint not in interpreter yet
+ bp = BreakpointManager::newBreakpoint (method, index);
+ }
+ else
+ {
+ // Ignore the duplicate
+ }
+ }
+ break;
+
case EventRequest::EVENT_FRAME_POP:
break;
@@ -244,6 +276,46 @@
break;
case EventRequest::EVENT_BREAKPOINT:
+ {
+ using namespace gnu::gcj::jvmti;
+ ::java::util::Collection *breakpoints;
+ EventManager *em = EventManager::getDefault ();
+ breakpoints = em->getRequests (EventRequest::EVENT_BREAKPOINT);
+
+ // Check for duplicates
+ int matches = 0;
+ Location *the_location = get_request_location (request);
+
+ // This should not be possible: we REQUIRE a Location
+ // to install a breakpoint
+ JvAssert (the_location != NULL);
+
+ ::java::util::Iterator *iter = breakpoints->iterator ();
+ while (iter->hasNext ())
+ {
+ EventRequest *er
+ = reinterpret_cast<EventRequest *> (iter->next ());
+ Location *loc = get_request_location (er);
+ JvAssert (loc != NULL);
+ if (loc->equals (the_location) && ++matches == 2)
+ {
+ // Short-circuit: already more than one breakpoint
+ return;
+ }
+ }
+
+ if (matches == 0)
+ {
+ using namespace gnu::classpath::jdwp::exception;
+ jstring msg
+ = JvNewStringLatin1 ("attempt to remove unknown breakpoint");
+ throw new JdwpInternalErrorException (msg);
+ }
+
+ jlong methodId = the_location->getMethod ()->getId ();
+ BreakpointManager::deleteBreakpoint (methodId,
+ the_location->getIndex ());
+ }
break;
case EventRequest::EVENT_FRAME_POP:
@@ -403,6 +475,27 @@
return NULL;
}
+static Location *
+get_request_location (EventRequest *request)
+{
+ Location *loc = NULL;
+ ::java::util::Collection *filters = request->getFilters ();
+ ::java::util::Iterator *iter = filters->iterator ();
+ while (iter->hasNext ())
+ {
+ using namespace gnu::classpath::jdwp::event::filters;
+ IEventFilter *filter = (IEventFilter *) iter->next ();
+ if (filter->getClass () == &LocationOnlyFilter::class$)
+ {
+ LocationOnlyFilter *lof
+ = reinterpret_cast<LocationOnlyFilter *> (filter);
+ loc = lof->getLocation ();
+ }
+ }
+
+ return loc;
+}
+
static void
throw_jvmti_error (jvmtiError err)
{