Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/share/vm/prims/jvmtiImpl.hpp
32285 views
/*1* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#ifndef SHARE_VM_PRIMS_JVMTIIMPL_HPP25#define SHARE_VM_PRIMS_JVMTIIMPL_HPP2627#include "classfile/systemDictionary.hpp"28#include "jvmtifiles/jvmti.h"29#include "oops/objArrayOop.hpp"30#include "prims/jvmtiEnvThreadState.hpp"31#include "prims/jvmtiEventController.hpp"32#include "prims/jvmtiTrace.hpp"33#include "prims/jvmtiUtil.hpp"34#include "runtime/stackValueCollection.hpp"35#include "runtime/vm_operations.hpp"3637//38// Forward Declarations39//4041class JvmtiBreakpoint;42class JvmtiBreakpoints;434445///////////////////////////////////////////////////////////////46//47// class GrowableCache, GrowableElement48// Used by : JvmtiBreakpointCache49// Used by JVMTI methods: none directly.50//51// GrowableCache is a permanent CHeap growable array of <GrowableElement *>52//53// In addition, the GrowableCache maintains a NULL terminated cache array of type address54// that's created from the element array using the function:55// address GrowableElement::getCacheValue().56//57// Whenever the GrowableArray changes size, the cache array gets recomputed into a new C_HEAP allocated58// block of memory. Additionally, every time the cache changes its position in memory, the59// void (*_listener_fun)(void *this_obj, address* cache)60// gets called with the cache's new address. This gives the user of the GrowableCache a callback61// to update its pointer to the address cache.62//6364class GrowableElement : public CHeapObj<mtInternal> {65public:66virtual address getCacheValue() =0;67virtual bool equals(GrowableElement* e) =0;68virtual bool lessThan(GrowableElement *e)=0;69virtual GrowableElement *clone() =0;70virtual void oops_do(OopClosure* f) =0;71virtual void metadata_do(void f(Metadata*)) =0;72};7374class GrowableCache VALUE_OBJ_CLASS_SPEC {7576private:77// Object pointer passed into cache & listener functions.78void *_this_obj;7980// Array of elements in the collection81GrowableArray<GrowableElement *> *_elements;8283// Parallel array of cached values84address *_cache;8586// Listener for changes to the _cache field.87// Called whenever the _cache field has it's value changed88// (but NOT when cached elements are recomputed).89void (*_listener_fun)(void *, address*);9091static bool equals(void *, GrowableElement *);9293// recache all elements after size change, notify listener94void recache();9596public:97GrowableCache();98~GrowableCache();99100void initialize(void *this_obj, void listener_fun(void *, address*) );101102// number of elements in the collection103int length();104// get the value of the index element in the collection105GrowableElement* at(int index);106// find the index of the element, -1 if it doesn't exist107int find(GrowableElement* e);108// append a copy of the element to the end of the collection, notify listener109void append(GrowableElement* e);110// insert a copy of the element using lessthan(), notify listener111void insert(GrowableElement* e);112// remove the element at index, notify listener113void remove (int index);114// clear out all elements and release all heap space, notify listener115void clear();116// apply f to every element and update the cache117void oops_do(OopClosure* f);118// walk metadata to preserve for RedefineClasses119void metadata_do(void f(Metadata*));120// update the cache after a full gc121void gc_epilogue();122};123124125///////////////////////////////////////////////////////////////126//127// class JvmtiBreakpointCache128// Used by : JvmtiBreakpoints129// Used by JVMTI methods: none directly.130// Note : typesafe wrapper for GrowableCache of JvmtiBreakpoint131//132133class JvmtiBreakpointCache : public CHeapObj<mtInternal> {134135private:136GrowableCache _cache;137138public:139JvmtiBreakpointCache() {}140~JvmtiBreakpointCache() {}141142void initialize(void *this_obj, void listener_fun(void *, address*) ) {143_cache.initialize(this_obj,listener_fun);144}145146int length() { return _cache.length(); }147JvmtiBreakpoint& at(int index) { return (JvmtiBreakpoint&) *(_cache.at(index)); }148int find(JvmtiBreakpoint& e) { return _cache.find((GrowableElement *) &e); }149void append(JvmtiBreakpoint& e) { _cache.append((GrowableElement *) &e); }150void remove (int index) { _cache.remove(index); }151void clear() { _cache.clear(); }152void oops_do(OopClosure* f) { _cache.oops_do(f); }153void metadata_do(void f(Metadata*)) { _cache.metadata_do(f); }154void gc_epilogue() { _cache.gc_epilogue(); }155};156157158///////////////////////////////////////////////////////////////159//160// class JvmtiBreakpoint161// Used by : JvmtiBreakpoints162// Used by JVMTI methods: SetBreakpoint, ClearBreakpoint, ClearAllBreakpoints163// Note: Extends GrowableElement for use in a GrowableCache164//165// A JvmtiBreakpoint describes a location (class, method, bci) to break at.166//167168typedef void (Method::*method_action)(int _bci);169170class JvmtiBreakpoint : public GrowableElement {171private:172Method* _method;173int _bci;174Bytecodes::Code _orig_bytecode;175oop _class_holder; // keeps _method memory from being deallocated176177public:178JvmtiBreakpoint();179JvmtiBreakpoint(Method* m_method, jlocation location);180bool equals(JvmtiBreakpoint& bp);181bool lessThan(JvmtiBreakpoint &bp);182void copy(JvmtiBreakpoint& bp);183bool is_valid();184address getBcp();185void each_method_version_do(method_action meth_act);186void set();187void clear();188void print();189190Method* method() { return _method; }191192// GrowableElement implementation193address getCacheValue() { return getBcp(); }194bool lessThan(GrowableElement* e) { Unimplemented(); return false; }195bool equals(GrowableElement* e) { return equals((JvmtiBreakpoint&) *e); }196void oops_do(OopClosure* f) {197// Mark the method loader as live so the Method* class loader doesn't get198// unloaded and Method* memory reclaimed.199f->do_oop(&_class_holder);200}201void metadata_do(void f(Metadata*)) {202// walk metadata to preserve for RedefineClasses203f(_method);204}205206GrowableElement *clone() {207JvmtiBreakpoint *bp = new JvmtiBreakpoint();208bp->copy(*this);209return bp;210}211};212213214///////////////////////////////////////////////////////////////215//216// class JvmtiBreakpoints217// Used by : JvmtiCurrentBreakpoints218// Used by JVMTI methods: none directly219// Note: A Helper class220//221// JvmtiBreakpoints is a GrowableCache of JvmtiBreakpoint.222// All changes to the GrowableCache occur at a safepoint using VM_ChangeBreakpoints.223//224// Because _bps is only modified at safepoints, its possible to always use the225// cached byte code pointers from _bps without doing any synchronization (see JvmtiCurrentBreakpoints).226//227// It would be possible to make JvmtiBreakpoints a static class, but I've made it228// CHeap allocated to emphasize its similarity to JvmtiFramePops.229//230231class JvmtiBreakpoints : public CHeapObj<mtInternal> {232private:233234JvmtiBreakpointCache _bps;235236// These should only be used by VM_ChangeBreakpoints237// to insure they only occur at safepoints.238// Todo: add checks for safepoint239friend class VM_ChangeBreakpoints;240void set_at_safepoint(JvmtiBreakpoint& bp);241void clear_at_safepoint(JvmtiBreakpoint& bp);242243static void do_element(GrowableElement *e);244245public:246JvmtiBreakpoints(void listener_fun(void *, address *));247~JvmtiBreakpoints();248249int length();250void oops_do(OopClosure* f);251void metadata_do(void f(Metadata*));252void print();253254int set(JvmtiBreakpoint& bp);255int clear(JvmtiBreakpoint& bp);256void clearall_in_class_at_safepoint(Klass* klass);257void gc_epilogue();258};259260261///////////////////////////////////////////////////////////////262//263// class JvmtiCurrentBreakpoints264//265// A static wrapper class for the JvmtiBreakpoints that provides:266// 1. a fast inlined function to check if a byte code pointer is a breakpoint (is_breakpoint).267// 2. a function for lazily creating the JvmtiBreakpoints class (this is not strictly necessary,268// but I'm copying the code from JvmtiThreadState which needs to lazily initialize269// JvmtiFramePops).270// 3. An oops_do entry point for GC'ing the breakpoint array.271//272273class JvmtiCurrentBreakpoints : public AllStatic {274275private:276277// Current breakpoints, lazily initialized by get_jvmti_breakpoints();278static JvmtiBreakpoints *_jvmti_breakpoints;279280// NULL terminated cache of byte-code pointers corresponding to current breakpoints.281// Updated only at safepoints (with listener_fun) when the cache is moved.282// It exists only to make is_breakpoint fast.283static address *_breakpoint_list;284static inline void set_breakpoint_list(address *breakpoint_list) { _breakpoint_list = breakpoint_list; }285static inline address *get_breakpoint_list() { return _breakpoint_list; }286287// Listener for the GrowableCache in _jvmti_breakpoints, updates _breakpoint_list.288static void listener_fun(void *this_obj, address *cache);289290public:291static void initialize();292static void destroy();293294// lazily create _jvmti_breakpoints and _breakpoint_list295static JvmtiBreakpoints& get_jvmti_breakpoints();296297// quickly test whether the bcp matches a cached breakpoint in the list298static inline bool is_breakpoint(address bcp);299300static void oops_do(OopClosure* f);301static void metadata_do(void f(Metadata*)) NOT_JVMTI_RETURN;302static void gc_epilogue();303};304305// quickly test whether the bcp matches a cached breakpoint in the list306bool JvmtiCurrentBreakpoints::is_breakpoint(address bcp) {307address *bps = get_breakpoint_list();308if (bps == NULL) return false;309for ( ; (*bps) != NULL; bps++) {310if ((*bps) == bcp) return true;311}312return false;313}314315316///////////////////////////////////////////////////////////////317//318// class VM_ChangeBreakpoints319// Used by : JvmtiBreakpoints320// Used by JVMTI methods: none directly.321// Note: A Helper class.322//323// VM_ChangeBreakpoints implements a VM_Operation for ALL modifications to the JvmtiBreakpoints class.324//325326class VM_ChangeBreakpoints : public VM_Operation {327private:328JvmtiBreakpoints* _breakpoints;329int _operation;330JvmtiBreakpoint* _bp;331332public:333enum { SET_BREAKPOINT=0, CLEAR_BREAKPOINT=1 };334335VM_ChangeBreakpoints(int operation, JvmtiBreakpoint *bp) {336JvmtiBreakpoints& current_bps = JvmtiCurrentBreakpoints::get_jvmti_breakpoints();337_breakpoints = ¤t_bps;338_bp = bp;339_operation = operation;340assert(bp != NULL, "bp != NULL");341}342343VMOp_Type type() const { return VMOp_ChangeBreakpoints; }344void doit();345void oops_do(OopClosure* f);346void metadata_do(void f(Metadata*));347};348349350///////////////////////////////////////////////////////////////351// The get/set local operations must only be done by the VM thread352// because the interpreter version needs to access oop maps, which can353// only safely be done by the VM thread354//355// I'm told that in 1.5 oop maps are now protected by a lock and356// we could get rid of the VM op357// However if the VM op is removed then the target thread must358// be suspended AND a lock will be needed to prevent concurrent359// setting of locals to the same java thread. This lock is needed360// to prevent compiledVFrames from trying to add deferred updates361// to the thread simultaneously.362//363class VM_GetOrSetLocal : public VM_Operation {364protected:365JavaThread* _thread;366JavaThread* _calling_thread;367jint _depth;368jint _index;369BasicType _type;370jvalue _value;371javaVFrame* _jvf;372bool _set;373374// It is possible to get the receiver out of a non-static native wrapper375// frame. Use VM_GetReceiver to do this.376virtual bool getting_receiver() const { return false; }377378jvmtiError _result;379380vframe* get_vframe();381javaVFrame* get_java_vframe();382bool check_slot_type(javaVFrame* vf);383384public:385// Constructor for non-object getter386VM_GetOrSetLocal(JavaThread* thread, jint depth, jint index, BasicType type);387388// Constructor for object or non-object setter389VM_GetOrSetLocal(JavaThread* thread, jint depth, jint index, BasicType type, jvalue value);390391// Constructor for object getter392VM_GetOrSetLocal(JavaThread* thread, JavaThread* calling_thread, jint depth,393int index);394395VMOp_Type type() const { return VMOp_GetOrSetLocal; }396jvalue value() { return _value; }397jvmtiError result() { return _result; }398399bool doit_prologue();400void doit();401bool allow_nested_vm_operations() const;402const char* name() const { return "get/set locals"; }403404// Check that the klass is assignable to a type with the given signature.405static bool is_assignable(const char* ty_sign, Klass* klass, Thread* thread);406};407408class VM_GetReceiver : public VM_GetOrSetLocal {409protected:410virtual bool getting_receiver() const { return true; }411412public:413VM_GetReceiver(JavaThread* thread, JavaThread* calling_thread, jint depth);414const char* name() const { return "get receiver"; }415};416417418///////////////////////////////////////////////////////////////419//420// class JvmtiSuspendControl421//422// Convenience routines for suspending and resuming threads.423//424// All attempts by JVMTI to suspend and resume threads must go through the425// JvmtiSuspendControl interface.426//427// methods return true if successful428//429class JvmtiSuspendControl : public AllStatic {430public:431// suspend the thread, taking it to a safepoint432static bool suspend(JavaThread *java_thread);433// resume the thread434static bool resume(JavaThread *java_thread);435436static void print();437};438439440/**441* When a thread (such as the compiler thread or VM thread) cannot post a442* JVMTI event itself because the event needs to be posted from a Java443* thread, then it can defer the event to the Service thread for posting.444* The information needed to post the event is encapsulated into this class445* and then enqueued onto the JvmtiDeferredEventQueue, where the Service446* thread will pick it up and post it.447*448* This is currently only used for posting compiled-method-load and unload449* events, which we don't want posted from the compiler thread.450*/451class JvmtiDeferredEvent VALUE_OBJ_CLASS_SPEC {452friend class JvmtiDeferredEventQueue;453private:454typedef enum {455TYPE_NONE,456TYPE_COMPILED_METHOD_LOAD,457TYPE_COMPILED_METHOD_UNLOAD,458TYPE_DYNAMIC_CODE_GENERATED459} Type;460461Type _type;462union {463nmethod* compiled_method_load;464struct {465nmethod* nm;466jmethodID method_id;467const void* code_begin;468} compiled_method_unload;469struct {470const char* name;471const void* code_begin;472const void* code_end;473} dynamic_code_generated;474} _event_data;475476JvmtiDeferredEvent(Type t) : _type(t) {}477478public:479480JvmtiDeferredEvent() : _type(TYPE_NONE) {}481482// Factory methods483static JvmtiDeferredEvent compiled_method_load_event(nmethod* nm)484NOT_JVMTI_RETURN_(JvmtiDeferredEvent());485static JvmtiDeferredEvent compiled_method_unload_event(nmethod* nm,486jmethodID id, const void* code) NOT_JVMTI_RETURN_(JvmtiDeferredEvent());487static JvmtiDeferredEvent dynamic_code_generated_event(488const char* name, const void* begin, const void* end)489NOT_JVMTI_RETURN_(JvmtiDeferredEvent());490491// Actually posts the event.492void post() NOT_JVMTI_RETURN;493};494495/**496* Events enqueued on this queue wake up the Service thread which dequeues497* and posts the events. The Service_lock is required to be held498* when operating on the queue (except for the "pending" events).499*/500class JvmtiDeferredEventQueue : AllStatic {501friend class JvmtiDeferredEvent;502private:503class QueueNode : public CHeapObj<mtInternal> {504private:505JvmtiDeferredEvent _event;506QueueNode* _next;507508public:509QueueNode(const JvmtiDeferredEvent& event)510: _event(event), _next(NULL) {}511512const JvmtiDeferredEvent& event() const { return _event; }513QueueNode* next() const { return _next; }514515void set_next(QueueNode* next) { _next = next; }516};517518static QueueNode* _queue_head; // Hold Service_lock to access519static QueueNode* _queue_tail; // Hold Service_lock to access520static volatile QueueNode* _pending_list; // Uses CAS for read/update521522// Transfers events from the _pending_list to the _queue.523static void process_pending_events() NOT_JVMTI_RETURN;524525public:526// Must be holding Service_lock when calling these527static bool has_events() NOT_JVMTI_RETURN_(false);528static void enqueue(const JvmtiDeferredEvent& event) NOT_JVMTI_RETURN;529static JvmtiDeferredEvent dequeue() NOT_JVMTI_RETURN_(JvmtiDeferredEvent());530531// Used to enqueue events without using a lock, for times (such as during532// safepoint) when we can't or don't want to lock the Service_lock.533//534// Events will be held off to the side until there's a call to535// dequeue(), enqueue(), or process_pending_events() (all of which require536// the holding of the Service_lock), and will be enqueued at that time.537static void add_pending_event(const JvmtiDeferredEvent&) NOT_JVMTI_RETURN;538};539540// Utility macro that checks for NULL pointers:541#define NULL_CHECK(X, Y) if ((X) == NULL) { return (Y); }542543#endif // SHARE_VM_PRIMS_JVMTIIMPL_HPP544545546