Path: blob/master/src/hotspot/share/prims/jvmtiImpl.hpp
41144 views
/*1* Copyright (c) 1999, 2021, 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_PRIMS_JVMTIIMPL_HPP25#define SHARE_PRIMS_JVMTIIMPL_HPP2627#include "jvmtifiles/jvmti.h"28#include "oops/objArrayOop.hpp"29#include "prims/jvmtiEnvThreadState.hpp"30#include "prims/jvmtiEventController.hpp"31#include "prims/jvmtiTrace.hpp"32#include "prims/jvmtiUtil.hpp"33#include "runtime/escapeBarrier.hpp"34#include "runtime/stackValueCollection.hpp"35#include "runtime/vmOperations.hpp"36#include "utilities/ostream.hpp"3738//39// Forward Declarations40//4142class JvmtiBreakpoint;43class JvmtiBreakpoints;444546///////////////////////////////////////////////////////////////47//48// class GrowableCache, GrowableElement49// Used by : JvmtiBreakpointCache50// Used by JVMTI methods: none directly.51//52// GrowableCache is a permanent CHeap growable array of <GrowableElement *>53//54// In addition, the GrowableCache maintains a NULL terminated cache array of type address55// that's created from the element array using the function:56// address GrowableElement::getCacheValue().57//58// Whenever the GrowableArray changes size, the cache array gets recomputed into a new C_HEAP allocated59// block of memory. Additionally, every time the cache changes its position in memory, the60// void (*_listener_fun)(void *this_obj, address* cache)61// gets called with the cache's new address. This gives the user of the GrowableCache a callback62// to update its pointer to the address cache.63//6465class GrowableElement : public CHeapObj<mtInternal> {66public:67virtual ~GrowableElement() {}68virtual address getCacheValue() =0;69virtual bool equals(GrowableElement* e) =0;70virtual GrowableElement *clone() =0;71};7273class GrowableCache {7475private:76// Object pointer passed into cache & listener functions.77void *_this_obj;7879// Array of elements in the collection80GrowableArray<GrowableElement *> *_elements;8182// Parallel array of cached values83address *_cache;8485// Listener for changes to the _cache field.86// Called whenever the _cache field has it's value changed87// (but NOT when cached elements are recomputed).88void (*_listener_fun)(void *, address*);8990static bool equals(void *, GrowableElement *);9192// recache all elements after size change, notify listener93void recache();9495public:96GrowableCache();97~GrowableCache();9899void initialize(void *this_obj, void listener_fun(void *, address*) );100101// number of elements in the collection102int length();103// get the value of the index element in the collection104GrowableElement* at(int index);105// find the index of the element, -1 if it doesn't exist106int find(GrowableElement* e);107// append a copy of the element to the end of the collection, notify listener108void append(GrowableElement* e);109// remove the element at index, notify listener110void remove (int index);111// clear out all elements and release all heap space, notify listener112void clear();113};114115116///////////////////////////////////////////////////////////////117//118// class JvmtiBreakpointCache119// Used by : JvmtiBreakpoints120// Used by JVMTI methods: none directly.121// Note : typesafe wrapper for GrowableCache of JvmtiBreakpoint122//123124class JvmtiBreakpointCache : public CHeapObj<mtInternal> {125126private:127GrowableCache _cache;128129public:130JvmtiBreakpointCache() {}131~JvmtiBreakpointCache() {}132133void initialize(void *this_obj, void listener_fun(void *, address*) ) {134_cache.initialize(this_obj, listener_fun);135}136137int length() { return _cache.length(); }138JvmtiBreakpoint& at(int index) { return (JvmtiBreakpoint&) *(_cache.at(index)); }139int find(JvmtiBreakpoint& e) { return _cache.find((GrowableElement *) &e); }140void append(JvmtiBreakpoint& e) { _cache.append((GrowableElement *) &e); }141void remove (int index) { _cache.remove(index); }142};143144145///////////////////////////////////////////////////////////////146//147// class JvmtiBreakpoint148// Used by : JvmtiBreakpoints149// Used by JVMTI methods: SetBreakpoint, ClearBreakpoint, ClearAllBreakpoints150// Note: Extends GrowableElement for use in a GrowableCache151//152// A JvmtiBreakpoint describes a location (class, method, bci) to break at.153//154155typedef void (Method::*method_action)(int _bci);156157class JvmtiBreakpoint : public GrowableElement {158private:159Method* _method;160int _bci;161OopHandle _class_holder; // keeps _method memory from being deallocated162163public:164JvmtiBreakpoint() : _method(NULL), _bci(0) {}165JvmtiBreakpoint(Method* m_method, jlocation location);166virtual ~JvmtiBreakpoint();167bool equals(JvmtiBreakpoint& bp);168void copy(JvmtiBreakpoint& bp);169address getBcp() const;170void each_method_version_do(method_action meth_act);171void set();172void clear();173void print_on(outputStream* out) const;174175Method* method() { return _method; }176177// GrowableElement implementation178address getCacheValue() { return getBcp(); }179bool equals(GrowableElement* e) { return equals((JvmtiBreakpoint&) *e); }180181GrowableElement *clone() {182JvmtiBreakpoint *bp = new JvmtiBreakpoint();183bp->copy(*this);184return bp;185}186};187188189///////////////////////////////////////////////////////////////190//191// class JvmtiBreakpoints192// Used by : JvmtiCurrentBreakpoints193// Used by JVMTI methods: none directly194// Note: A Helper class195//196// JvmtiBreakpoints is a GrowableCache of JvmtiBreakpoint.197// All changes to the GrowableCache occur at a safepoint using VM_ChangeBreakpoints.198//199// Because _bps is only modified at safepoints, its possible to always use the200// cached byte code pointers from _bps without doing any synchronization (see JvmtiCurrentBreakpoints).201//202// It would be possible to make JvmtiBreakpoints a static class, but I've made it203// CHeap allocated to emphasize its similarity to JvmtiFramePops.204//205206class JvmtiBreakpoints : public CHeapObj<mtInternal> {207private:208209JvmtiBreakpointCache _bps;210211// These should only be used by VM_ChangeBreakpoints212// to insure they only occur at safepoints.213// Todo: add checks for safepoint214friend class VM_ChangeBreakpoints;215void set_at_safepoint(JvmtiBreakpoint& bp);216void clear_at_safepoint(JvmtiBreakpoint& bp);217218public:219JvmtiBreakpoints(void listener_fun(void *, address *));220~JvmtiBreakpoints();221222int length();223void print();224225int set(JvmtiBreakpoint& bp);226int clear(JvmtiBreakpoint& bp);227void clearall_in_class_at_safepoint(Klass* klass);228};229230231///////////////////////////////////////////////////////////////232//233// class JvmtiCurrentBreakpoints234//235// A static wrapper class for the JvmtiBreakpoints that provides:236// 1. a fast inlined function to check if a byte code pointer is a breakpoint (is_breakpoint).237// 2. a function for lazily creating the JvmtiBreakpoints class (this is not strictly necessary,238// but I'm copying the code from JvmtiThreadState which needs to lazily initialize239// JvmtiFramePops).240// 3. An oops_do entry point for GC'ing the breakpoint array.241//242243class JvmtiCurrentBreakpoints : public AllStatic {244245private:246247// Current breakpoints, lazily initialized by get_jvmti_breakpoints();248static JvmtiBreakpoints *_jvmti_breakpoints;249250// NULL terminated cache of byte-code pointers corresponding to current breakpoints.251// Updated only at safepoints (with listener_fun) when the cache is moved.252// It exists only to make is_breakpoint fast.253static address *_breakpoint_list;254static inline void set_breakpoint_list(address *breakpoint_list) { _breakpoint_list = breakpoint_list; }255256// Listener for the GrowableCache in _jvmti_breakpoints, updates _breakpoint_list.257static void listener_fun(void *this_obj, address *cache);258259public:260static void initialize();261static void destroy();262263// lazily create _jvmti_breakpoints and _breakpoint_list264static JvmtiBreakpoints& get_jvmti_breakpoints();265};266267///////////////////////////////////////////////////////////////268//269// class VM_ChangeBreakpoints270// Used by : JvmtiBreakpoints271// Used by JVMTI methods: none directly.272// Note: A Helper class.273//274// VM_ChangeBreakpoints implements a VM_Operation for ALL modifications to the JvmtiBreakpoints class.275//276277class VM_ChangeBreakpoints : public VM_Operation {278private:279JvmtiBreakpoints* _breakpoints;280int _operation;281JvmtiBreakpoint* _bp;282283public:284enum { SET_BREAKPOINT=0, CLEAR_BREAKPOINT=1 };285286VM_ChangeBreakpoints(int operation, JvmtiBreakpoint *bp) {287JvmtiBreakpoints& current_bps = JvmtiCurrentBreakpoints::get_jvmti_breakpoints();288_breakpoints = ¤t_bps;289_bp = bp;290_operation = operation;291assert(bp != NULL, "bp != NULL");292}293294VMOp_Type type() const { return VMOp_ChangeBreakpoints; }295void doit();296};297298299///////////////////////////////////////////////////////////////300// The get/set local operations must only be done by the VM thread301// because the interpreter version needs to access oop maps, which can302// only safely be done by the VM thread303//304// I'm told that in 1.5 oop maps are now protected by a lock and305// we could get rid of the VM op306// However if the VM op is removed then the target thread must307// be suspended AND a lock will be needed to prevent concurrent308// setting of locals to the same java thread. This lock is needed309// to prevent compiledVFrames from trying to add deferred updates310// to the thread simultaneously.311//312class VM_GetOrSetLocal : public VM_Operation {313protected:314JavaThread* _thread;315JavaThread* _calling_thread;316jint _depth;317jint _index;318BasicType _type;319jvalue _value;320javaVFrame* _jvf;321bool _set;322323EscapeBarrier _eb;324325// It is possible to get the receiver out of a non-static native wrapper326// frame. Use VM_GetReceiver to do this.327virtual bool getting_receiver() const { return false; }328329jvmtiError _result;330331vframe* get_vframe();332javaVFrame* get_java_vframe();333bool check_slot_type_lvt(javaVFrame* vf);334bool check_slot_type_no_lvt(javaVFrame* vf);335336public:337// Constructor for non-object getter338VM_GetOrSetLocal(JavaThread* thread, jint depth, jint index, BasicType type);339340// Constructor for object or non-object setter341VM_GetOrSetLocal(JavaThread* thread, jint depth, jint index, BasicType type, jvalue value);342343// Constructor for object getter344VM_GetOrSetLocal(JavaThread* thread, JavaThread* calling_thread, jint depth,345int index);346347VMOp_Type type() const { return VMOp_GetOrSetLocal; }348jvalue value() { return _value; }349jvmtiError result() { return _result; }350351bool doit_prologue();352void doit();353bool allow_nested_vm_operations() const;354const char* name() const { return "get/set locals"; }355356// Check that the klass is assignable to a type with the given signature.357static bool is_assignable(const char* ty_sign, Klass* klass, Thread* thread);358};359360class VM_GetReceiver : public VM_GetOrSetLocal {361protected:362virtual bool getting_receiver() const { return true; }363364public:365VM_GetReceiver(JavaThread* thread, JavaThread* calling_thread, jint depth);366const char* name() const { return "get receiver"; }367};368369370///////////////////////////////////////////////////////////////371//372// class JvmtiSuspendControl373//374// Convenience routines for suspending and resuming threads.375//376// All attempts by JVMTI to suspend and resume threads must go through the377// JvmtiSuspendControl interface.378//379// methods return true if successful380//381class JvmtiSuspendControl : public AllStatic {382public:383// suspend the thread, taking it to a safepoint384static bool suspend(JavaThread *java_thread);385// resume the thread386static bool resume(JavaThread *java_thread);387388static void print();389};390391392/**393* When a thread (such as the compiler thread or VM thread) cannot post a394* JVMTI event itself because the event needs to be posted from a Java395* thread, then it can defer the event to the Service thread for posting.396* The information needed to post the event is encapsulated into this class397* and then enqueued onto the JvmtiDeferredEventQueue, where the Service398* thread will pick it up and post it.399*400* This is currently only used for posting compiled-method-load and unload401* events, which we don't want posted from the compiler thread.402*/403class JvmtiDeferredEvent {404friend class JvmtiDeferredEventQueue;405private:406typedef enum {407TYPE_NONE,408TYPE_COMPILED_METHOD_LOAD,409TYPE_COMPILED_METHOD_UNLOAD,410TYPE_DYNAMIC_CODE_GENERATED,411TYPE_CLASS_UNLOAD412} Type;413414Type _type;415union {416nmethod* compiled_method_load;417struct {418jmethodID method_id;419const void* code_begin;420} compiled_method_unload;421struct {422const char* name;423const void* code_begin;424const void* code_end;425} dynamic_code_generated;426struct {427const char* name;428} class_unload;429} _event_data;430431JvmtiDeferredEvent(Type t) : _type(t) {}432433public:434435JvmtiDeferredEvent() : _type(TYPE_NONE) {}436437// Factory methods438static JvmtiDeferredEvent compiled_method_load_event(nmethod* nm)439NOT_JVMTI_RETURN_(JvmtiDeferredEvent());440static JvmtiDeferredEvent compiled_method_unload_event(441jmethodID id, const void* code) NOT_JVMTI_RETURN_(JvmtiDeferredEvent());442static JvmtiDeferredEvent dynamic_code_generated_event(443const char* name, const void* begin, const void* end)444NOT_JVMTI_RETURN_(JvmtiDeferredEvent());445static JvmtiDeferredEvent class_unload_event(446const char* name) NOT_JVMTI_RETURN_(JvmtiDeferredEvent());447448// Actually posts the event.449void post() NOT_JVMTI_RETURN;450void post_compiled_method_load_event(JvmtiEnv* env) NOT_JVMTI_RETURN;451void run_nmethod_entry_barriers() NOT_JVMTI_RETURN;452// Sweeper support to keep nmethods from being zombied while in the queue.453void nmethods_do(CodeBlobClosure* cf) NOT_JVMTI_RETURN;454// GC support to keep nmethod from being unloaded while in the queue.455void oops_do(OopClosure* f, CodeBlobClosure* cf) NOT_JVMTI_RETURN;456};457458/**459* Events enqueued on this queue wake up the Service thread which dequeues460* and posts the events. The Service_lock is required to be held461* when operating on the queue.462*/463class JvmtiDeferredEventQueue : public CHeapObj<mtInternal> {464friend class JvmtiDeferredEvent;465private:466class QueueNode : public CHeapObj<mtInternal> {467private:468JvmtiDeferredEvent _event;469QueueNode* _next;470471public:472QueueNode(const JvmtiDeferredEvent& event)473: _event(event), _next(NULL) {}474475JvmtiDeferredEvent& event() { return _event; }476QueueNode* next() const { return _next; }477478void set_next(QueueNode* next) { _next = next; }479};480481QueueNode* _queue_head;482QueueNode* _queue_tail;483484public:485JvmtiDeferredEventQueue() : _queue_head(NULL), _queue_tail(NULL) {}486487bool has_events() NOT_JVMTI_RETURN_(false);488JvmtiDeferredEvent dequeue() NOT_JVMTI_RETURN_(JvmtiDeferredEvent());489490// Post all events in the queue for the current Jvmti environment491void post(JvmtiEnv* env) NOT_JVMTI_RETURN;492void enqueue(JvmtiDeferredEvent event) NOT_JVMTI_RETURN;493void run_nmethod_entry_barriers();494495// Sweeper support to keep nmethods from being zombied while in the queue.496void nmethods_do(CodeBlobClosure* cf) NOT_JVMTI_RETURN;497// GC support to keep nmethod from being unloaded while in the queue.498void oops_do(OopClosure* f, CodeBlobClosure* cf) NOT_JVMTI_RETURN;499};500501// Utility macro that checks for NULL pointers:502#define NULL_CHECK(X, Y) if ((X) == NULL) { return (Y); }503504#endif // SHARE_PRIMS_JVMTIIMPL_HPP505506507