Skip to content

Commit

Permalink
core/java/jdwp: Overhaul of the JDWP library.
Browse files Browse the repository at this point in the history
Add a debug mode which prints every send and recv.
Add string helpers for the majority of the message types.
Flesh out thread-reference APIs.
Reimplement the event request API to be more strict about thread suspension.
  • Loading branch information
ben-clayton committed Mar 8, 2018
1 parent 020af71 commit d28080d
Show file tree
Hide file tree
Showing 24 changed files with 649 additions and 201 deletions.
2 changes: 2 additions & 0 deletions core/java/jdwp/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ go_library(
"cmdset_vm.go",
"cmdsets.go",
"coder.go",
"debug.go",
"errors.go",
"event.go",
"event_kind.go",
Expand All @@ -45,6 +46,7 @@ go_library(
"recv.go",
"suspend_policy.go",
"tag.go",
"thread_status.go",
"type_tag.go",
"types.go",
"value.go",
Expand Down
6 changes: 3 additions & 3 deletions core/java/jdwp/cmdset_arrayreference.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ package jdwp
// GetArrayLength returns the length of the specified array.
func (c *Connection) GetArrayLength(id ArrayID) (int, error) {
var res int
err := c.get(cmdSetArrayReference, 1, id, &res)
err := c.get(cmdArrayReferenceLength, id, &res)
return res, err
}

Expand All @@ -29,7 +29,7 @@ func (c *Connection) GetArrayValues(id ArrayID, first, length int) ([]Value, err
Length int
}{id, first, length}
var res []Value
err := c.get(cmdSetArrayReference, 2, req, &res)
err := c.get(cmdArrayReferenceGetValues, req, &res)
return res, err
}

Expand All @@ -40,5 +40,5 @@ func (c *Connection) SetArrayValues(id ArrayID, first int, values interface{}) e
First int
Values interface{}
}{id, first, values}
return c.get(cmdSetArrayReference, 3, req, nil)
return c.get(cmdArrayReferenceSetValues, req, nil)
}
2 changes: 1 addition & 1 deletion core/java/jdwp/cmdset_arraytype.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@ func (c *Connection) NewArray(ty ArrayTypeID, length int) (TaggedObjectID, error
Length int
}{ty, length}
var res TaggedObjectID
err := c.get(cmdSetArrayType, 1, req, &res)
err := c.get(cmdArrayTypeNewInstance, req, &res)
return res, err
}
2 changes: 1 addition & 1 deletion core/java/jdwp/cmdset_classobjectreference.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,6 @@ func (c *Connection) ReflectedType(id ClassObjectID) (ReferenceTypeID, error) {
Kind byte
ID ReferenceTypeID
}
err := c.get(cmdSetClassObjectReference, 1, req, &res)
err := c.get(cmdClassObjectReferenceReflectedType, req, &res)
return res.ID, err
}
6 changes: 3 additions & 3 deletions core/java/jdwp/cmdset_classtype.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ type InvokeResult struct {
// GetSuperClass returns the immediate super class of the specified class.
func (c *Connection) GetSuperClass(class ClassID) (ClassID, error) {
var res ClassID
err := c.get(cmdSetClassType, 1, class, &res)
err := c.get(cmdClassTypeSuperclass, class, &res)
return res, err
}

Expand All @@ -37,7 +37,7 @@ func (c *Connection) InvokeStaticMethod(class ClassID, method MethodID, thread T
Options InvokeOptions
}{class, thread, method, args, options}
var res InvokeResult
err := c.get(cmdSetClassType, 3, req, &res)
err := c.get(cmdClassTypeInvokeMethod, req, &res)
return res, err
}

Expand All @@ -57,6 +57,6 @@ func (c *Connection) NewInstance(class ClassID, constructor MethodID, thread Thr
Options InvokeOptions
}{class, thread, constructor, args, options}
var res NewInstanceResult
err := c.get(cmdSetClassType, 4, req, &res)
err := c.get(cmdClassTypeNewInstance, req, &res)
return res, err
}
112 changes: 101 additions & 11 deletions core/java/jdwp/cmdset_eventrequest.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,28 @@

package jdwp

import (
"context"
"fmt"

"github.com/google/gapid/core/event/task"
)

// EventRequestID is an identifier of an event request.
type EventRequestID int

const cmdCompositeEvent = cmdID(100)

// SetEvent sets an event request.
func (c *Connection) SetEvent(kind EventKind, suspendPolity SuspendPolicy, modifiers ...EventModifier) (EventRequestID, error) {
// WatchEvents sets an event watcher, calling handler for each received event.
// WatchEvents will continue to watch for events until handler returns false or
// the context is cancelled.
func (c *Connection) WatchEvents(
ctx context.Context,
kind EventKind,
suspendPolity SuspendPolicy,
handler func(Event) bool,
modifiers ...EventModifier) error {

req := struct {
Kind EventKind
SuspendPolicy SuspendPolicy
Expand All @@ -30,22 +45,64 @@ func (c *Connection) SetEvent(kind EventKind, suspendPolity SuspendPolicy, modif
SuspendPolicy: suspendPolity,
Modifiers: modifiers,
}
var res EventRequestID
err := c.get(cmdSetEventRequest, 1, req, &res)
return res, err
}

// ClearEvent cancels an event request.
func (c *Connection) ClearEvent(kind EventKind, id EventRequestID) error {
req := struct {
var id EventRequestID
err := c.get(cmdEventRequestSet, req, &id)
if err != nil {
return err
}

events := make(chan Event, 8)
c.Lock()
c.events[id] = events
c.Unlock()

defer func() {
c.Lock()
delete(c.events, id)
c.Unlock()
}()

if err := c.ResumeAll(); err != nil {
return err
}

run: // Consume events until the handler returns false or the context is cancelled.
for {
select {
case event := <-events:
if !handler(event) {
break run
}
case <-task.ShouldStop(ctx):
break run
}
}

// Clear the event.
clear := struct {
Kind EventKind
ID EventRequestID
}{
Kind: kind,
ID: id,
}
err := c.get(cmdSetEventRequest, 2, req, nil)
return err

if err := c.get(cmdEventRequestClear, clear, nil); err != nil {
return err
}

flush: // Consume any remaining events in the pipe.
for {
select {
case event := <-events:
handler(event)
default:
break flush
}
}

return nil
}

// EventModifier is the interface implemented by all event modifier types.
Expand Down Expand Up @@ -126,3 +183,36 @@ func (ExceptionOnlyEventModifier) modKind() uint8 { return 8 }
func (FieldOnlyEventModifier) modKind() uint8 { return 9 }
func (StepEventModifier) modKind() uint8 { return 10 }
func (InstanceOnlyEventModifier) modKind() uint8 { return 11 }

func (m CountEventModifier) String() string {
return fmt.Sprintf("CountEventModifier<%v>", int(m))
}
func (m ThreadOnlyEventModifier) String() string {
return fmt.Sprintf("ThreadOnlyEventModifier<%v>", int(m))
}
func (m ClassOnlyEventModifier) String() string {
return fmt.Sprintf("ClassOnlyEventModifier<%v>", int(m))
}
func (m ClassMatchEventModifier) String() string {
return fmt.Sprintf("ClassMatchEventModifier<%v>", string(m))
}
func (m ClassExcludeEventModifier) String() string {
return fmt.Sprintf("ClassExcludeEventModifier<%v>", string(m))
}
func (m LocationOnlyEventModifier) String() string {
return fmt.Sprintf("LocationOnlyEventModifier<%v>", Location(m))
}
func (m ExceptionOnlyEventModifier) String() string {
return fmt.Sprintf("ExceptionOnlyEventModifier<Exception: %v, Caught: %v, Uncaught: %v>",
m.ExceptionOrNull, m.Caught, m.Uncaught)
}
func (m FieldOnlyEventModifier) String() string {
return fmt.Sprintf("FieldOnlyEventModifier<Type: %v, Field: %v>", m.Type, m.Field)
}
func (m StepEventModifier) String() string {
return fmt.Sprintf("StepEventModifier<Thread: %v, Size: %v, Depth: %v>",
m.Thread, m.Size, m.Depth)
}
func (m InstanceOnlyEventModifier) String() string {
return fmt.Sprintf("InstanceOnlyEventModifier<%v>", ObjectID(m))
}
6 changes: 3 additions & 3 deletions core/java/jdwp/cmdset_method.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@

package jdwp

// VariableTable returns all of the variables that are present
// in the given Method.
// VariableTable returns all of the variables that are present in the given
// Method.
func (c *Connection) VariableTable(classTy ReferenceTypeID, method MethodID) (VariableTable, error) {
req := struct {
Class ReferenceTypeID
Method MethodID
}{classTy, method}
var res VariableTable
err := c.get(cmdSetMethod, 2, req, &res)
err := c.get(cmdMethodTypeVariableTable, req, &res)
return res, err
}
10 changes: 5 additions & 5 deletions core/java/jdwp/cmdset_objectreference.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,14 @@ type ObjectType struct {
// GetObjectType returns the type of the specified object.
func (c *Connection) GetObjectType(object ObjectID) (ObjectType, error) {
var res ObjectType
err := c.get(cmdSetObjectReference, 1, object, &res)
err := c.get(cmdObjectReferenceReferenceType, object, &res)
return res, err
}

// GetFieldValues returns the values of all the instance fields.
func (c *Connection) GetFieldValues(obj ObjectID, fields ...FieldID) ([]Value, error) {
var res []Value
err := c.get(cmdSetObjectReference, 2, struct {
err := c.get(cmdObjectReferenceGetValues, struct {
Obj ObjectID
Fields []FieldID
}{obj, fields}, &res)
Expand All @@ -48,16 +48,16 @@ func (c *Connection) InvokeMethod(object ObjectID, class ClassID, method MethodI
Options InvokeOptions
}{object, thread, class, method, args, options}
var res InvokeResult
err := c.get(cmdSetObjectReference, 6, req, &res)
err := c.get(cmdObjectReferenceInvokeMethod, req, &res)
return res, err
}

// DisableGC disables garbage collection for the specified object.
func (c *Connection) DisableGC(object ObjectID) error {
return c.get(cmdSetObjectReference, 7, object, nil)
return c.get(cmdObjectReferenceDisableCollection, object, nil)
}

// EnableGC enables garbage collection for the specified object.
func (c *Connection) EnableGC(object ObjectID) error {
return c.get(cmdSetObjectReference, 8, object, nil)
return c.get(cmdObjectReferenceEnableCollection, object, nil)
}
10 changes: 5 additions & 5 deletions core/java/jdwp/cmdset_referencetypes.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,28 +17,28 @@ package jdwp
// GetTypeSignature returns the Java type signature for the specified type.
func (c *Connection) GetTypeSignature(ty ReferenceTypeID) (string, error) {
var res string
err := c.get(cmdSetReferenceType, 1, ty, &res)
err := c.get(cmdReferenceTypeSignature, ty, &res)
return res, err
}

// GetFields returns all the fields for the specified type.
func (c *Connection) GetFields(ty ReferenceTypeID) (Fields, error) {
var res Fields
err := c.get(cmdSetReferenceType, 4, ty, &res)
err := c.get(cmdReferenceTypeFields, ty, &res)
return res, err
}

// GetMethods returns all the methods for the specified type.
func (c *Connection) GetMethods(ty ReferenceTypeID) (Methods, error) {
var res Methods
err := c.get(cmdSetReferenceType, 5, ty, &res)
err := c.get(cmdReferenceTypeMethods, ty, &res)
return res, err
}

// GetStaticFieldValues returns the values of all the requests static fields.
func (c *Connection) GetStaticFieldValues(ty ReferenceTypeID, fields ...FieldID) ([]Value, error) {
var res []Value
err := c.get(cmdSetReferenceType, 6, struct {
err := c.get(cmdReferenceTypeGetValues, struct {
Ty ReferenceTypeID
Fields []FieldID
}{ty, fields}, &res)
Expand All @@ -49,6 +49,6 @@ func (c *Connection) GetStaticFieldValues(ty ReferenceTypeID, fields ...FieldID)
// type.
func (c *Connection) GetImplemented(ty ReferenceTypeID) ([]InterfaceID, error) {
var res []InterfaceID
err := c.get(cmdSetReferenceType, 10, ty, &res)
err := c.get(cmdReferenceTypeInterfaces, ty, &res)
return res, err
}
6 changes: 3 additions & 3 deletions core/java/jdwp/cmdset_stackframe.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ func (c *Connection) GetThisObject(thread ThreadID, frame FrameID) (TaggedObject
Frame FrameID
}{thread, frame}
res := TaggedObjectID{}
err := c.get(cmdSetStackFrame, 3, req, &res)
err := c.get(cmdStackFrameThisObject, req, &res)
return res, err
}

Expand All @@ -40,7 +40,7 @@ func (c *Connection) GetValues(thread ThreadID, frame FrameID, slots []VariableR
Slots []VariableRequest
}{thread, frame, slots}
res := ValueSlice{}
err := c.get(cmdSetStackFrame, 1, req, &res)
err := c.get(cmdStackFrameGetValues, req, &res)
return res, err
}

Expand All @@ -57,6 +57,6 @@ func (c *Connection) SetValues(thread ThreadID, frame FrameID, slots []VariableA
Slots []VariableAssignmentRequest
}{thread, frame, slots}

err := c.get(cmdSetStackFrame, 2, req, nil)
err := c.get(cmdStackFrameSetValues, req, nil)
return err
}
2 changes: 1 addition & 1 deletion core/java/jdwp/cmdset_stringreference.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,6 @@ package jdwp
// GetString returns the string text for the given StringID.
func (c *Connection) GetString(id StringID) (string, error) {
var res string
err := c.get(cmdSetStringReference, 1, id, &res)
err := c.get(cmdStringReferenceValue, id, &res)
return res, err
}
Loading

0 comments on commit d28080d

Please sign in to comment.