jvmtiImpl.hpp revision 0:a61af66fc99e
1/*
2 * Copyright 1999-2007 Sun Microsystems, Inc.  All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
20 * CA 95054 USA or visit www.sun.com if you need additional information or
21 * have any questions.
22 *
23 */
24
25//
26// Forward Declarations
27//
28
29class JvmtiRawMonitor;
30class JvmtiBreakpoint;
31class JvmtiBreakpoints;
32
33
34///////////////////////////////////////////////////////////////
35//
36// class GrowableCache, GrowableElement
37// Used by              : JvmtiBreakpointCache
38// Used by JVMTI methods: none directly.
39//
40// GrowableCache is a permanent CHeap growable array of <GrowableElement *>
41//
42// In addition, the GrowableCache maintains a NULL terminated cache array of type address
43// that's created from the element array using the function:
44//     address GrowableElement::getCacheValue().
45//
46// Whenever the GrowableArray changes size, the cache array gets recomputed into a new C_HEAP allocated
47// block of memory. Additionally, every time the cache changes its position in memory, the
48//    void (*_listener_fun)(void *this_obj, address* cache)
49// gets called with the cache's new address. This gives the user of the GrowableCache a callback
50// to update its pointer to the address cache.
51//
52
53class GrowableElement : public CHeapObj {
54public:
55  virtual address getCacheValue()          =0;
56  virtual bool equals(GrowableElement* e)  =0;
57  virtual bool lessThan(GrowableElement *e)=0;
58  virtual GrowableElement *clone()         =0;
59  virtual void oops_do(OopClosure* f)      =0;
60};
61
62class GrowableCache VALUE_OBJ_CLASS_SPEC {
63
64private:
65  // Object pointer passed into cache & listener functions.
66  void *_this_obj;
67
68  // Array of elements in the collection
69  GrowableArray<GrowableElement *> *_elements;
70
71  // Parallel array of cached values
72  address *_cache;
73
74  // Listener for changes to the _cache field.
75  // Called whenever the _cache field has it's value changed
76  // (but NOT when cached elements are recomputed).
77  void (*_listener_fun)(void *, address*);
78
79  static bool equals(void *, GrowableElement *);
80
81  // recache all elements after size change, notify listener
82  void recache();
83
84public:
85   GrowableCache();
86   ~GrowableCache();
87
88  void initialize(void *this_obj, void listener_fun(void *, address*) );
89
90  // number of elements in the collection
91  int length();
92  // get the value of the index element in the collection
93  GrowableElement* at(int index);
94  // find the index of the element, -1 if it doesn't exist
95  int find(GrowableElement* e);
96  // append a copy of the element to the end of the collection, notify listener
97  void append(GrowableElement* e);
98  // insert a copy of the element using lessthan(), notify listener
99  void insert(GrowableElement* e);
100  // remove the element at index, notify listener
101  void remove (int index);
102  // clear out all elements and release all heap space, notify listener
103  void clear();
104  // apply f to every element and update the cache
105  void oops_do(OopClosure* f);
106  void gc_epilogue();
107};
108
109
110///////////////////////////////////////////////////////////////
111//
112// class JvmtiBreakpointCache
113// Used by              : JvmtiBreakpoints
114// Used by JVMTI methods: none directly.
115// Note   : typesafe wrapper for GrowableCache of JvmtiBreakpoint
116//
117
118class JvmtiBreakpointCache : public CHeapObj {
119
120private:
121  GrowableCache _cache;
122
123public:
124  JvmtiBreakpointCache()  {}
125  ~JvmtiBreakpointCache() {}
126
127  void initialize(void *this_obj, void listener_fun(void *, address*) ) {
128    _cache.initialize(this_obj,listener_fun);
129  }
130
131  int length()                          { return _cache.length(); }
132  JvmtiBreakpoint& at(int index)        { return (JvmtiBreakpoint&) *(_cache.at(index)); }
133  int find(JvmtiBreakpoint& e)          { return _cache.find((GrowableElement *) &e); }
134  void append(JvmtiBreakpoint& e)       { _cache.append((GrowableElement *) &e); }
135  void remove (int index)               { _cache.remove(index); }
136  void clear()                          { _cache.clear(); }
137  void oops_do(OopClosure* f)           { _cache.oops_do(f); }
138  void gc_epilogue()                    { _cache.gc_epilogue(); }
139};
140
141
142///////////////////////////////////////////////////////////////
143//
144// class JvmtiBreakpoint
145// Used by              : JvmtiBreakpoints
146// Used by JVMTI methods: SetBreakpoint, ClearBreakpoint, ClearAllBreakpoints
147// Note: Extends GrowableElement for use in a GrowableCache
148//
149// A JvmtiBreakpoint describes a location (class, method, bci) to break at.
150//
151
152typedef void (methodOopDesc::*method_action)(int _bci);
153
154class JvmtiBreakpoint : public GrowableElement {
155private:
156  methodOop             _method;
157  int                   _bci;
158  Bytecodes::Code       _orig_bytecode;
159
160public:
161  JvmtiBreakpoint();
162  JvmtiBreakpoint(methodOop m_method, jlocation location);
163  bool equals(JvmtiBreakpoint& bp);
164  bool lessThan(JvmtiBreakpoint &bp);
165  void copy(JvmtiBreakpoint& bp);
166  bool is_valid();
167  address getBcp();
168  void each_method_version_do(method_action meth_act);
169  void set();
170  void clear();
171  void print();
172
173  methodOop method() { return _method; }
174
175  // GrowableElement implementation
176  address getCacheValue()         { return getBcp(); }
177  bool lessThan(GrowableElement* e) { Unimplemented(); return false; }
178  bool equals(GrowableElement* e) { return equals((JvmtiBreakpoint&) *e); }
179  void oops_do(OopClosure* f)     { f->do_oop((oop *) &_method); }
180  GrowableElement *clone()        {
181    JvmtiBreakpoint *bp = new JvmtiBreakpoint();
182    bp->copy(*this);
183    return bp;
184  }
185};
186
187
188///////////////////////////////////////////////////////////////
189//
190// class VM_ChangeBreakpoints
191// Used by              : JvmtiBreakpoints
192// Used by JVMTI methods: none directly.
193// Note: A Helper class.
194//
195// VM_ChangeBreakpoints implements a VM_Operation for ALL modifications to the JvmtiBreakpoints class.
196//
197
198class VM_ChangeBreakpoints : public VM_Operation {
199private:
200  JvmtiBreakpoints* _breakpoints;
201  int               _operation;
202  JvmtiBreakpoint*  _bp;
203
204public:
205  enum { SET_BREAKPOINT=0, CLEAR_BREAKPOINT=1, CLEAR_ALL_BREAKPOINT=2 };
206
207  VM_ChangeBreakpoints(JvmtiBreakpoints* breakpoints, int operation) {
208    _breakpoints = breakpoints;
209    _bp = NULL;
210    _operation = operation;
211    assert(breakpoints != NULL, "breakpoints != NULL");
212    assert(operation == CLEAR_ALL_BREAKPOINT, "unknown breakpoint operation");
213  }
214  VM_ChangeBreakpoints(JvmtiBreakpoints* breakpoints, int operation, JvmtiBreakpoint *bp) {
215    _breakpoints = breakpoints;
216    _bp = bp;
217    _operation = operation;
218    assert(breakpoints != NULL, "breakpoints != NULL");
219    assert(bp != NULL, "bp != NULL");
220    assert(operation == SET_BREAKPOINT || operation == CLEAR_BREAKPOINT , "unknown breakpoint operation");
221  }
222
223  VMOp_Type type() const { return VMOp_ChangeBreakpoints; }
224  void doit();
225  void oops_do(OopClosure* f);
226};
227
228
229///////////////////////////////////////////////////////////////
230//
231// class JvmtiBreakpoints
232// Used by              : JvmtiCurrentBreakpoints
233// Used by JVMTI methods: none directly
234// Note: A Helper class
235//
236// JvmtiBreakpoints is a GrowableCache of JvmtiBreakpoint.
237// All changes to the GrowableCache occur at a safepoint using VM_ChangeBreakpoints.
238//
239// Because _bps is only modified at safepoints, its possible to always use the
240// cached byte code pointers from _bps without doing any synchronization (see JvmtiCurrentBreakpoints).
241//
242// It would be possible to make JvmtiBreakpoints a static class, but I've made it
243// CHeap allocated to emphasize its similarity to JvmtiFramePops.
244//
245
246class JvmtiBreakpoints : public CHeapObj {
247private:
248
249  JvmtiBreakpointCache _bps;
250
251  // These should only be used by VM_ChangeBreakpoints
252  // to insure they only occur at safepoints.
253  // Todo: add checks for safepoint
254  friend class VM_ChangeBreakpoints;
255  void set_at_safepoint(JvmtiBreakpoint& bp);
256  void clear_at_safepoint(JvmtiBreakpoint& bp);
257  void clearall_at_safepoint();
258
259  static void do_element(GrowableElement *e);
260
261public:
262  JvmtiBreakpoints(void listener_fun(void *, address *));
263  ~JvmtiBreakpoints();
264
265  int length();
266  void oops_do(OopClosure* f);
267  void gc_epilogue();
268  void print();
269
270  int  set(JvmtiBreakpoint& bp);
271  int  clear(JvmtiBreakpoint& bp);
272  void clearall_in_class_at_safepoint(klassOop klass);
273  void clearall();
274};
275
276
277///////////////////////////////////////////////////////////////
278//
279// class JvmtiCurrentBreakpoints
280//
281// A static wrapper class for the JvmtiBreakpoints that provides:
282// 1. a fast inlined function to check if a byte code pointer is a breakpoint (is_breakpoint).
283// 2. a function for lazily creating the JvmtiBreakpoints class (this is not strictly necessary,
284//    but I'm copying the code from JvmtiThreadState which needs to lazily initialize
285//    JvmtiFramePops).
286// 3. An oops_do entry point for GC'ing the breakpoint array.
287//
288
289class JvmtiCurrentBreakpoints : public AllStatic {
290
291private:
292
293  // Current breakpoints, lazily initialized by get_jvmti_breakpoints();
294  static JvmtiBreakpoints *_jvmti_breakpoints;
295
296  // NULL terminated cache of byte-code pointers corresponding to current breakpoints.
297  // Updated only at safepoints (with listener_fun) when the cache is moved.
298  // It exists only to make is_breakpoint fast.
299  static address          *_breakpoint_list;
300  static inline void set_breakpoint_list(address *breakpoint_list) { _breakpoint_list = breakpoint_list; }
301  static inline address *get_breakpoint_list()                     { return _breakpoint_list; }
302
303  // Listener for the GrowableCache in _jvmti_breakpoints, updates _breakpoint_list.
304  static void listener_fun(void *this_obj, address *cache);
305
306public:
307  static void initialize();
308  static void destroy();
309
310  // lazily create _jvmti_breakpoints and _breakpoint_list
311  static JvmtiBreakpoints& get_jvmti_breakpoints();
312
313  // quickly test whether the bcp matches a cached breakpoint in the list
314  static inline bool is_breakpoint(address bcp);
315
316  static void oops_do(OopClosure* f);
317  static void gc_epilogue();
318};
319
320// quickly test whether the bcp matches a cached breakpoint in the list
321bool JvmtiCurrentBreakpoints::is_breakpoint(address bcp) {
322    address *bps = get_breakpoint_list();
323    if (bps == NULL) return false;
324    for ( ; (*bps) != NULL; bps++) {
325      if ((*bps) == bcp) return true;
326    }
327    return false;
328}
329
330
331///////////////////////////////////////////////////////////////
332//
333// class JvmtiRawMonitor
334//
335// Used by JVMTI methods: All RawMonitor methods (CreateRawMonitor, EnterRawMonitor, etc.)
336//
337// Wrapper for ObjectMonitor class that saves the Monitor's name
338//
339
340class JvmtiRawMonitor : public ObjectMonitor  {
341private:
342  int           _magic;
343  char *        _name;
344  // JVMTI_RM_MAGIC is set in contructor and unset in destructor.
345  enum { JVMTI_RM_MAGIC = (int)(('T' << 24) | ('I' << 16) | ('R' << 8) | 'M') };
346
347public:
348  JvmtiRawMonitor(const char *name);
349  ~JvmtiRawMonitor();
350  int            magic()   { return _magic;  }
351  const char *get_name()   { return _name; }
352  bool        is_valid()   { return _magic == JVMTI_RM_MAGIC;  }
353};
354
355// Onload pending raw monitors
356// Class is used to cache onload or onstart monitor enter
357// which will transition into real monitor when
358// VM is fully initialized.
359class JvmtiPendingMonitors : public AllStatic {
360
361private:
362  static GrowableArray<JvmtiRawMonitor*> *_monitors; // Cache raw monitor enter
363
364  inline static GrowableArray<JvmtiRawMonitor*>* monitors() { return _monitors; }
365
366  static void dispose() {
367    delete monitors();
368  }
369
370public:
371  static void enter(JvmtiRawMonitor *monitor) {
372    monitors()->append(monitor);
373  }
374
375  static int count() {
376    return monitors()->length();
377  }
378
379  static void destroy(JvmtiRawMonitor *monitor) {
380    while (monitors()->contains(monitor)) {
381      monitors()->remove(monitor);
382    }
383  }
384
385  // Return false if monitor is not found in the list.
386  static bool exit(JvmtiRawMonitor *monitor) {
387    if (monitors()->contains(monitor)) {
388      monitors()->remove(monitor);
389      return true;
390    } else {
391      return false;
392    }
393  }
394
395  static void transition_raw_monitors();
396};
397
398
399
400///////////////////////////////////////////////////////////////
401// The get/set local operations must only be done by the VM thread
402// because the interpreter version needs to access oop maps, which can
403// only safely be done by the VM thread
404//
405// I'm told that in 1.5 oop maps are now protected by a lock and
406// we could get rid of the VM op
407// However if the VM op is removed then the target thread must
408// be suspended AND a lock will be needed to prevent concurrent
409// setting of locals to the same java thread. This lock is needed
410// to prevent compiledVFrames from trying to add deferred updates
411// to the thread simultaneously.
412//
413class VM_GetOrSetLocal : public VM_Operation {
414private:
415  JavaThread* _thread;
416  JavaThread* _calling_thread;
417  jint        _depth;
418  jint        _index;
419  BasicType   _type;
420  jvalue      _value;
421  javaVFrame* _jvf;
422  bool        _set;
423
424  jvmtiError  _result;
425
426  vframe* get_vframe();
427  javaVFrame* get_java_vframe();
428  bool check_slot_type(javaVFrame* vf);
429
430public:
431  // Constructor for non-object getter
432  VM_GetOrSetLocal(JavaThread* thread, jint depth, jint index, BasicType type);
433
434  // Constructor for object or non-object setter
435  VM_GetOrSetLocal(JavaThread* thread, jint depth, jint index, BasicType type, jvalue value);
436
437  // Constructor for object getter
438  VM_GetOrSetLocal(JavaThread* thread, JavaThread* calling_thread, jint depth,
439                   int index);
440
441  VMOp_Type type() const { return VMOp_GetOrSetLocal; }
442  jvalue value()         { return _value; }
443  jvmtiError result()    { return _result; }
444
445  bool doit_prologue();
446  void doit();
447  bool allow_nested_vm_operations() const;
448  const char* name() const                       { return "get/set locals"; }
449
450  // Check that the klass is assignable to a type with the given signature.
451  static bool is_assignable(const char* ty_sign, Klass* klass, Thread* thread);
452};
453
454
455///////////////////////////////////////////////////////////////
456//
457// class JvmtiSuspendControl
458//
459// Convenience routines for suspending and resuming threads.
460//
461// All attempts by JVMTI to suspend and resume threads must go through the
462// JvmtiSuspendControl interface.
463//
464// methods return true if successful
465//
466class JvmtiSuspendControl : public AllStatic {
467public:
468  // suspend the thread, taking it to a safepoint
469  static bool suspend(JavaThread *java_thread);
470  // resume the thread
471  static bool resume(JavaThread *java_thread);
472
473  static void print();
474};
475
476// Utility macro that checks for NULL pointers:
477#define NULL_CHECK(X, Y) if ((X) == NULL) { return (Y); }
478