Path: blob/master/src/hotspot/share/prims/jvmtiEnvThreadState.cpp
41145 views
/*1* Copyright (c) 2003, 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#include "precompiled.hpp"25#include "interpreter/interpreter.hpp"26#include "jvmtifiles/jvmtiEnv.hpp"27#include "memory/resourceArea.hpp"28#include "prims/jvmtiEnvThreadState.hpp"29#include "prims/jvmtiEventController.inline.hpp"30#include "prims/jvmtiImpl.hpp"31#include "runtime/handles.hpp"32#include "runtime/handles.inline.hpp"33#include "runtime/interfaceSupport.inline.hpp"34#include "runtime/javaCalls.hpp"35#include "runtime/signature.hpp"36#include "runtime/thread.inline.hpp"37#include "runtime/vframe.hpp"38#include "runtime/vmOperations.hpp"394041///////////////////////////////////////////////////////////////42//43// class JvmtiFramePop44//4546#ifndef PRODUCT47void JvmtiFramePop::print() {48tty->print_cr("_frame_number=%d", _frame_number);49}50#endif515253///////////////////////////////////////////////////////////////54//55// class JvmtiFramePops - private methods56//5758void59JvmtiFramePops::set(JvmtiFramePop& fp) {60if (_pops->find(fp.frame_number()) < 0) {61_pops->append(fp.frame_number());62}63}646566void67JvmtiFramePops::clear(JvmtiFramePop& fp) {68assert(_pops->length() > 0, "No more frame pops");6970_pops->remove(fp.frame_number());71}727374int75JvmtiFramePops::clear_to(JvmtiFramePop& fp) {76int cleared = 0;77int index = 0;78while (index < _pops->length()) {79JvmtiFramePop pop = JvmtiFramePop(_pops->at(index));80if (pop.above_on_stack(fp)) {81_pops->remove_at(index);82++cleared;83} else {84++index;85}86}87return cleared;88}899091///////////////////////////////////////////////////////////////92//93// class JvmtiFramePops - public methods94//9596JvmtiFramePops::JvmtiFramePops() {97_pops = new (ResourceObj::C_HEAP, mtServiceability) GrowableArray<int> (2, mtServiceability);98}99100JvmtiFramePops::~JvmtiFramePops() {101// return memory to c_heap.102delete _pops;103}104105106#ifndef PRODUCT107void JvmtiFramePops::print() {108ResourceMark rm;109110int n = _pops->length();111for (int i=0; i<n; i++) {112JvmtiFramePop fp = JvmtiFramePop(_pops->at(i));113tty->print("%d: ", i);114fp.print();115tty->cr();116}117}118#endif119120///////////////////////////////////////////////////////////////121//122// class JvmtiEnvThreadState123//124// Instances of JvmtiEnvThreadState hang off of each JvmtiThreadState,125// one per JvmtiEnv.126//127128JvmtiEnvThreadState::JvmtiEnvThreadState(JavaThread *thread, JvmtiEnvBase *env) :129_event_enable() {130_thread = thread;131_env = (JvmtiEnv*)env;132_next = NULL;133_frame_pops = NULL;134_current_bci = 0;135_current_method_id = NULL;136_breakpoint_posted = false;137_single_stepping_posted = false;138_agent_thread_local_storage_data = NULL;139}140141JvmtiEnvThreadState::~JvmtiEnvThreadState() {142delete _frame_pops;143_frame_pops = NULL;144}145146// Given that a new (potential) event has come in,147// maintain the current JVMTI location on a per-thread per-env basis148// and use it to filter out duplicate events:149// - instruction rewrites150// - breakpoint followed by single step151// - single step at a breakpoint152void JvmtiEnvThreadState::compare_and_set_current_location(Method* new_method,153address new_location, jvmtiEvent event) {154155int new_bci = new_location - new_method->code_base();156157// The method is identified and stored as a jmethodID which is safe in this158// case because the class cannot be unloaded while a method is executing.159jmethodID new_method_id = new_method->jmethod_id();160161// the last breakpoint or single step was at this same location162if (_current_bci == new_bci && _current_method_id == new_method_id) {163switch (event) {164case JVMTI_EVENT_BREAKPOINT:165// Repeat breakpoint is complicated. If we previously posted a breakpoint166// event at this location and if we also single stepped at this location167// then we skip the duplicate breakpoint.168_breakpoint_posted = _breakpoint_posted && _single_stepping_posted;169break;170case JVMTI_EVENT_SINGLE_STEP:171// Repeat single step is easy: just don't post it again.172// If step is pending for popframe then it may not be173// a repeat step. The new_bci and method_id is same as current_bci174// and current method_id after pop and step for recursive calls.175// This has been handled by clearing the location176_single_stepping_posted = true;177break;178default:179assert(false, "invalid event value passed");180break;181}182return;183}184185set_current_location(new_method_id, new_bci);186_breakpoint_posted = false;187_single_stepping_posted = false;188}189190191JvmtiFramePops* JvmtiEnvThreadState::get_frame_pops() {192#ifdef ASSERT193Thread *current = Thread::current();194#endif195assert(get_thread()->is_handshake_safe_for(current),196"frame pop data only accessible from same thread or direct handshake");197if (_frame_pops == NULL) {198_frame_pops = new JvmtiFramePops();199assert(_frame_pops != NULL, "_frame_pops != NULL");200}201return _frame_pops;202}203204205bool JvmtiEnvThreadState::has_frame_pops() {206return _frame_pops == NULL? false : (_frame_pops->length() > 0);207}208209void JvmtiEnvThreadState::set_frame_pop(int frame_number) {210#ifdef ASSERT211Thread *current = Thread::current();212#endif213assert(get_thread()->is_handshake_safe_for(current),214"frame pop data only accessible from same thread or direct handshake");215JvmtiFramePop fpop(frame_number);216JvmtiEventController::set_frame_pop(this, fpop);217}218219220void JvmtiEnvThreadState::clear_frame_pop(int frame_number) {221#ifdef ASSERT222Thread *current = Thread::current();223#endif224assert(get_thread()->is_handshake_safe_for(current),225"frame pop data only accessible from same thread or direct handshake");226JvmtiFramePop fpop(frame_number);227JvmtiEventController::clear_frame_pop(this, fpop);228}229230231bool JvmtiEnvThreadState::is_frame_pop(int cur_frame_number) {232#ifdef ASSERT233Thread *current = Thread::current();234#endif235assert(get_thread()->is_handshake_safe_for(current),236"frame pop data only accessible from same thread or direct handshake");237if (!get_thread()->is_interp_only_mode() || _frame_pops == NULL) {238return false;239}240JvmtiFramePop fp(cur_frame_number);241return get_frame_pops()->contains(fp);242}243244245class GetCurrentLocationClosure : public HandshakeClosure {246private:247jmethodID _method_id;248int _bci;249bool _completed;250public:251GetCurrentLocationClosure()252: HandshakeClosure("GetCurrentLocation"),253_method_id(NULL),254_bci(0),255_completed(false) {}256void do_thread(Thread *target) {257JavaThread *jt = target->as_Java_thread();258ResourceMark rmark; // jt != Thread::current()259RegisterMap rm(jt, false);260// There can be a race condition between a handshake261// and the target thread exiting from Java execution.262// We must recheck that the last Java frame still exists.263if (!jt->is_exiting() && jt->has_last_Java_frame()) {264javaVFrame* vf = jt->last_java_vframe(&rm);265if (vf != NULL) {266Method* method = vf->method();267_method_id = method->jmethod_id();268_bci = vf->bci();269}270}271_completed = true;272}273void get_current_location(jmethodID *method_id, int *bci) {274*method_id = _method_id;275*bci = _bci;276}277bool completed() {278return _completed;279}280};281282void JvmtiEnvThreadState::reset_current_location(jvmtiEvent event_type, bool enabled) {283assert(event_type == JVMTI_EVENT_SINGLE_STEP || event_type == JVMTI_EVENT_BREAKPOINT,284"must be single-step or breakpoint event");285286// Current location is used to detect the following:287// 1) a breakpoint event followed by single-stepping to the same bci288// 2) single-step to a bytecode that will be transformed to a fast version289// We skip to avoid posting the duplicate single-stepping event.290291// If single-stepping is disabled, clear current location so that292// single-stepping to the same method and bcp at a later time will be293// detected if single-stepping is enabled at that time (see 4388912).294295// If single-stepping is enabled, set the current location to the296// current method and bcp. This covers the following type of case,297// e.g., the debugger stepi command:298// - bytecode single stepped299// - SINGLE_STEP event posted and SINGLE_STEP event disabled300// - SINGLE_STEP event reenabled301// - bytecode rewritten to fast version302303// If breakpoint event is disabled, clear current location only if304// single-stepping is not enabled. Otherwise, keep the thread location305// to detect any duplicate events.306307if (enabled) {308// If enabling breakpoint, no need to reset.309// Can't do anything if empty stack.310if (event_type == JVMTI_EVENT_SINGLE_STEP && _thread->has_last_Java_frame()) {311jmethodID method_id;312int bci;313// The java thread stack may not be walkable for a running thread314// so get current location with direct handshake.315GetCurrentLocationClosure op;316Thread *current = Thread::current();317if (_thread->is_handshake_safe_for(current)) {318op.do_thread(_thread);319} else {320Handshake::execute(&op, _thread);321guarantee(op.completed(), "Handshake failed. Target thread is not alive?");322}323op.get_current_location(&method_id, &bci);324set_current_location(method_id, bci);325}326} else if (event_type == JVMTI_EVENT_SINGLE_STEP || !is_enabled(JVMTI_EVENT_SINGLE_STEP)) {327// If this is to disable breakpoint, also check if single-step is not enabled328clear_current_location();329}330}331332333