aoqi@0: /* aoqi@0: * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. aoqi@0: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. aoqi@0: * aoqi@0: * This code is free software; you can redistribute it and/or modify it aoqi@0: * under the terms of the GNU General Public License version 2 only, as aoqi@0: * published by the Free Software Foundation. aoqi@0: * aoqi@0: * This code is distributed in the hope that it will be useful, but WITHOUT aoqi@0: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or aoqi@0: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License aoqi@0: * version 2 for more details (a copy is included in the LICENSE file that aoqi@0: * accompanied this code). aoqi@0: * aoqi@0: * You should have received a copy of the GNU General Public License version aoqi@0: * 2 along with this work; if not, write to the Free Software Foundation, aoqi@0: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. aoqi@0: * aoqi@0: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA aoqi@0: * or visit www.oracle.com if you need additional information or have any aoqi@0: * questions. aoqi@0: * aoqi@0: */ aoqi@0: aoqi@0: #include "precompiled.hpp" aoqi@0: #include "jvmtifiles/jvmtiEnv.hpp" aoqi@0: #include "memory/gcLocker.hpp" aoqi@0: #include "memory/resourceArea.hpp" aoqi@0: #include "prims/jvmtiEventController.inline.hpp" aoqi@0: #include "prims/jvmtiImpl.hpp" aoqi@0: #include "prims/jvmtiThreadState.inline.hpp" aoqi@0: #include "runtime/vframe.hpp" aoqi@0: aoqi@0: // marker for when the stack depth has been reset and is now unknown. aoqi@0: // any negative number would work but small ones might obscure an aoqi@0: // underrun error. aoqi@0: static const int UNKNOWN_STACK_DEPTH = -99; aoqi@0: aoqi@0: /////////////////////////////////////////////////////////////// aoqi@0: // aoqi@0: // class JvmtiThreadState aoqi@0: // aoqi@0: // Instances of JvmtiThreadState hang off of each thread. aoqi@0: // Thread local storage for JVMTI. aoqi@0: // aoqi@0: aoqi@0: JvmtiThreadState *JvmtiThreadState::_head = NULL; aoqi@0: aoqi@0: JvmtiThreadState::JvmtiThreadState(JavaThread* thread) aoqi@0: : _thread_event_enable() { aoqi@0: assert(JvmtiThreadState_lock->is_locked(), "sanity check"); aoqi@0: _thread = thread; aoqi@0: _exception_detected = false; aoqi@0: _exception_caught = false; aoqi@0: _debuggable = true; aoqi@0: _hide_single_stepping = false; aoqi@0: _hide_level = 0; aoqi@0: _pending_step_for_popframe = false; aoqi@0: _class_being_redefined = NULL; aoqi@0: _class_load_kind = jvmti_class_load_kind_load; aoqi@0: _head_env_thread_state = NULL; aoqi@0: _dynamic_code_event_collector = NULL; aoqi@0: _vm_object_alloc_event_collector = NULL; aoqi@0: _the_class_for_redefinition_verification = NULL; aoqi@0: _scratch_class_for_redefinition_verification = NULL; aoqi@0: aoqi@0: // JVMTI ForceEarlyReturn support aoqi@0: _pending_step_for_earlyret = false; aoqi@0: _earlyret_state = earlyret_inactive; aoqi@0: _earlyret_tos = ilgl; aoqi@0: _earlyret_value.j = 0L; aoqi@0: _earlyret_oop = NULL; aoqi@0: aoqi@0: // add all the JvmtiEnvThreadState to the new JvmtiThreadState aoqi@0: { aoqi@0: JvmtiEnvIterator it; aoqi@0: for (JvmtiEnvBase* env = it.first(); env != NULL; env = it.next(env)) { aoqi@0: if (env->is_valid()) { aoqi@0: add_env(env); aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: // link us into the list aoqi@0: { aoqi@0: // The thread state list manipulation code must not have safepoints. aoqi@0: // See periodic_clean_up(). aoqi@0: debug_only(No_Safepoint_Verifier nosafepoint;) aoqi@0: aoqi@0: _prev = NULL; aoqi@0: _next = _head; aoqi@0: if (_head != NULL) { aoqi@0: _head->_prev = this; aoqi@0: } aoqi@0: _head = this; aoqi@0: } aoqi@0: aoqi@0: // set this as the state for the thread aoqi@0: thread->set_jvmti_thread_state(this); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: JvmtiThreadState::~JvmtiThreadState() { aoqi@0: assert(JvmtiThreadState_lock->is_locked(), "sanity check"); aoqi@0: aoqi@0: // clear this as the state for the thread aoqi@0: get_thread()->set_jvmti_thread_state(NULL); aoqi@0: aoqi@0: // zap our env thread states aoqi@0: { aoqi@0: JvmtiEnvBase::entering_dying_thread_env_iteration(); aoqi@0: JvmtiEnvThreadStateIterator it(this); aoqi@0: for (JvmtiEnvThreadState* ets = it.first(); ets != NULL; ) { aoqi@0: JvmtiEnvThreadState* zap = ets; aoqi@0: ets = it.next(ets); aoqi@0: delete zap; aoqi@0: } aoqi@0: JvmtiEnvBase::leaving_dying_thread_env_iteration(); aoqi@0: } aoqi@0: aoqi@0: // remove us from the list aoqi@0: { aoqi@0: // The thread state list manipulation code must not have safepoints. aoqi@0: // See periodic_clean_up(). aoqi@0: debug_only(No_Safepoint_Verifier nosafepoint;) aoqi@0: aoqi@0: if (_prev == NULL) { aoqi@0: assert(_head == this, "sanity check"); aoqi@0: _head = _next; aoqi@0: } else { aoqi@0: assert(_head != this, "sanity check"); aoqi@0: _prev->_next = _next; aoqi@0: } aoqi@0: if (_next != NULL) { aoqi@0: _next->_prev = _prev; aoqi@0: } aoqi@0: _next = NULL; aoqi@0: _prev = NULL; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: aoqi@0: void aoqi@0: JvmtiThreadState::periodic_clean_up() { aoqi@0: assert(SafepointSynchronize::is_at_safepoint(), "at safepoint"); aoqi@0: aoqi@0: // This iteration is initialized with "_head" instead of "JvmtiThreadState::first()" aoqi@0: // because the latter requires the JvmtiThreadState_lock. aoqi@0: // This iteration is safe at a safepoint as well, see the No_Safepoint_Verifier aoqi@0: // asserts at all list manipulation sites. aoqi@0: for (JvmtiThreadState *state = _head; state != NULL; state = state->next()) { aoqi@0: // For each environment thread state corresponding to an invalid environment aoqi@0: // unlink it from the list and deallocate it. aoqi@0: JvmtiEnvThreadStateIterator it(state); aoqi@0: JvmtiEnvThreadState* previous_ets = NULL; aoqi@0: JvmtiEnvThreadState* ets = it.first(); aoqi@0: while (ets != NULL) { aoqi@0: if (ets->get_env()->is_valid()) { aoqi@0: previous_ets = ets; aoqi@0: ets = it.next(ets); aoqi@0: } else { aoqi@0: // This one isn't valid, remove it from the list and deallocate it aoqi@0: JvmtiEnvThreadState* defunct_ets = ets; aoqi@0: ets = ets->next(); aoqi@0: if (previous_ets == NULL) { aoqi@0: assert(state->head_env_thread_state() == defunct_ets, "sanity check"); aoqi@0: state->set_head_env_thread_state(ets); aoqi@0: } else { aoqi@0: previous_ets->set_next(ets); aoqi@0: } aoqi@0: delete defunct_ets; aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: void JvmtiThreadState::add_env(JvmtiEnvBase *env) { aoqi@0: assert(JvmtiThreadState_lock->is_locked(), "sanity check"); aoqi@0: aoqi@0: JvmtiEnvThreadState *new_ets = new JvmtiEnvThreadState(_thread, env); aoqi@0: // add this environment thread state to the end of the list (order is important) aoqi@0: { aoqi@0: // list deallocation (which occurs at a safepoint) cannot occur simultaneously aoqi@0: debug_only(No_Safepoint_Verifier nosafepoint;) aoqi@0: aoqi@0: JvmtiEnvThreadStateIterator it(this); aoqi@0: JvmtiEnvThreadState* previous_ets = NULL; aoqi@0: for (JvmtiEnvThreadState* ets = it.first(); ets != NULL; ets = it.next(ets)) { aoqi@0: previous_ets = ets; aoqi@0: } aoqi@0: if (previous_ets == NULL) { aoqi@0: set_head_env_thread_state(new_ets); aoqi@0: } else { aoqi@0: previous_ets->set_next(new_ets); aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: aoqi@0: aoqi@0: aoqi@0: void JvmtiThreadState::enter_interp_only_mode() { aoqi@0: assert(_thread->get_interp_only_mode() == 0, "entering interp only when mode not zero"); aoqi@0: _thread->increment_interp_only_mode(); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: void JvmtiThreadState::leave_interp_only_mode() { aoqi@0: assert(_thread->get_interp_only_mode() == 1, "leaving interp only when mode not one"); aoqi@0: _thread->decrement_interp_only_mode(); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: // Helper routine used in several places aoqi@0: int JvmtiThreadState::count_frames() { aoqi@0: #ifdef ASSERT aoqi@0: uint32_t debug_bits = 0; aoqi@0: #endif aoqi@0: assert(SafepointSynchronize::is_at_safepoint() || aoqi@0: JvmtiEnv::is_thread_fully_suspended(get_thread(), false, &debug_bits), aoqi@0: "at safepoint or must be suspended"); aoqi@0: aoqi@0: if (!get_thread()->has_last_Java_frame()) return 0; // no Java frames aoqi@0: aoqi@0: ResourceMark rm; aoqi@0: RegisterMap reg_map(get_thread()); aoqi@0: javaVFrame *jvf = get_thread()->last_java_vframe(®_map); aoqi@0: int n = 0; aoqi@0: // tty->print_cr("CSD: counting frames on %s ...", aoqi@0: // JvmtiTrace::safe_get_thread_name(get_thread())); aoqi@0: while (jvf != NULL) { aoqi@0: Method* method = jvf->method(); aoqi@0: // tty->print_cr("CSD: frame - method %s.%s - loc %d", aoqi@0: // method->klass_name()->as_C_string(), aoqi@0: // method->name()->as_C_string(), aoqi@0: // jvf->bci() ); aoqi@0: jvf = jvf->java_sender(); aoqi@0: n++; aoqi@0: } aoqi@0: // tty->print_cr("CSD: frame count: %d", n); aoqi@0: return n; aoqi@0: } aoqi@0: aoqi@0: aoqi@0: void JvmtiThreadState::invalidate_cur_stack_depth() { aoqi@0: Thread *cur = Thread::current(); aoqi@0: uint32_t debug_bits = 0; aoqi@0: aoqi@0: // The caller can be the VMThread at a safepoint, the current thread aoqi@0: // or the target thread must be suspended. aoqi@0: guarantee((cur->is_VM_thread() && SafepointSynchronize::is_at_safepoint()) || aoqi@0: (JavaThread *)cur == get_thread() || aoqi@0: JvmtiEnv::is_thread_fully_suspended(get_thread(), false, &debug_bits), aoqi@0: "sanity check"); aoqi@0: aoqi@0: _cur_stack_depth = UNKNOWN_STACK_DEPTH; aoqi@0: } aoqi@0: aoqi@0: void JvmtiThreadState::incr_cur_stack_depth() { aoqi@0: guarantee(JavaThread::current() == get_thread(), "must be current thread"); aoqi@0: aoqi@0: if (!is_interp_only_mode()) { aoqi@0: _cur_stack_depth = UNKNOWN_STACK_DEPTH; aoqi@0: } aoqi@0: if (_cur_stack_depth != UNKNOWN_STACK_DEPTH) { aoqi@0: ++_cur_stack_depth; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: void JvmtiThreadState::decr_cur_stack_depth() { aoqi@0: guarantee(JavaThread::current() == get_thread(), "must be current thread"); aoqi@0: aoqi@0: if (!is_interp_only_mode()) { aoqi@0: _cur_stack_depth = UNKNOWN_STACK_DEPTH; aoqi@0: } aoqi@0: if (_cur_stack_depth != UNKNOWN_STACK_DEPTH) { aoqi@0: --_cur_stack_depth; aoqi@0: assert(_cur_stack_depth >= 0, "incr/decr_cur_stack_depth mismatch"); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: int JvmtiThreadState::cur_stack_depth() { aoqi@0: uint32_t debug_bits = 0; aoqi@0: guarantee(JavaThread::current() == get_thread() || aoqi@0: JvmtiEnv::is_thread_fully_suspended(get_thread(), false, &debug_bits), aoqi@0: "must be current thread or suspended"); aoqi@0: aoqi@0: if (!is_interp_only_mode() || _cur_stack_depth == UNKNOWN_STACK_DEPTH) { aoqi@0: _cur_stack_depth = count_frames(); aoqi@0: } else { aoqi@0: // heavy weight assert aoqi@0: assert(_cur_stack_depth == count_frames(), aoqi@0: "cur_stack_depth out of sync"); aoqi@0: } aoqi@0: return _cur_stack_depth; aoqi@0: } aoqi@0: aoqi@0: bool JvmtiThreadState::may_be_walked() { aoqi@0: return (get_thread()->is_being_ext_suspended() || (JavaThread::current() == get_thread())); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: void JvmtiThreadState::process_pending_step_for_popframe() { aoqi@0: // We are single stepping as the last part of the PopFrame() dance aoqi@0: // so we have some house keeping to do. aoqi@0: aoqi@0: JavaThread *thr = get_thread(); aoqi@0: if (thr->popframe_condition() != JavaThread::popframe_inactive) { aoqi@0: // If the popframe_condition field is not popframe_inactive, then aoqi@0: // we missed all of the popframe_field cleanup points: aoqi@0: // aoqi@0: // - unpack_frames() was not called (nothing to deopt) aoqi@0: // - remove_activation_preserving_args_entry() was not called aoqi@0: // (did not get suspended in a call_vm() family call and did aoqi@0: // not complete a call_vm() family call on the way here) aoqi@0: thr->clear_popframe_condition(); aoqi@0: } aoqi@0: aoqi@0: // clearing the flag indicates we are done with the PopFrame() dance aoqi@0: clr_pending_step_for_popframe(); aoqi@0: aoqi@0: // If exception was thrown in this frame, need to reset jvmti thread state. aoqi@0: // Single stepping may not get enabled correctly by the agent since aoqi@0: // exception state is passed in MethodExit event which may be sent at some aoqi@0: // time in the future. JDWP agent ignores MethodExit events if caused by aoqi@0: // an exception. aoqi@0: // aoqi@0: if (is_exception_detected()) { aoqi@0: clear_exception_detected(); aoqi@0: } aoqi@0: // If step is pending for popframe then it may not be aoqi@0: // a repeat step. The new_bci and method_id is same as current_bci aoqi@0: // and current method_id after pop and step for recursive calls. aoqi@0: // Force the step by clearing the last location. aoqi@0: JvmtiEnvThreadStateIterator it(this); aoqi@0: for (JvmtiEnvThreadState* ets = it.first(); ets != NULL; ets = it.next(ets)) { aoqi@0: ets->clear_current_location(); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: aoqi@0: // Class: JvmtiThreadState aoqi@0: // Function: update_for_pop_top_frame aoqi@0: // Description: aoqi@0: // This function removes any frame pop notification request for aoqi@0: // the top frame and invalidates both the current stack depth and aoqi@0: // all cached frameIDs. aoqi@0: // aoqi@0: // Called by: PopFrame aoqi@0: // aoqi@0: void JvmtiThreadState::update_for_pop_top_frame() { aoqi@0: if (is_interp_only_mode()) { aoqi@0: // remove any frame pop notification request for the top frame aoqi@0: // in any environment aoqi@0: int popframe_number = cur_stack_depth(); aoqi@0: { aoqi@0: JvmtiEnvThreadStateIterator it(this); aoqi@0: for (JvmtiEnvThreadState* ets = it.first(); ets != NULL; ets = it.next(ets)) { aoqi@0: if (ets->is_frame_pop(popframe_number)) { aoqi@0: ets->clear_frame_pop(popframe_number); aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: // force stack depth to be recalculated aoqi@0: invalidate_cur_stack_depth(); aoqi@0: } else { aoqi@0: assert(!is_enabled(JVMTI_EVENT_FRAME_POP), "Must have no framepops set"); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: aoqi@0: void JvmtiThreadState::process_pending_step_for_earlyret() { aoqi@0: // We are single stepping as the last part of the ForceEarlyReturn aoqi@0: // dance so we have some house keeping to do. aoqi@0: aoqi@0: if (is_earlyret_pending()) { aoqi@0: // If the earlyret_state field is not earlyret_inactive, then aoqi@0: // we missed all of the earlyret_field cleanup points: aoqi@0: // aoqi@0: // - remove_activation() was not called aoqi@0: // (did not get suspended in a call_vm() family call and did aoqi@0: // not complete a call_vm() family call on the way here) aoqi@0: // aoqi@0: // One legitimate way for us to miss all the cleanup points is aoqi@0: // if we got here right after handling a compiled return. If that aoqi@0: // is the case, then we consider our return from compiled code to aoqi@0: // complete the ForceEarlyReturn request and we clear the condition. aoqi@0: clr_earlyret_pending(); aoqi@0: set_earlyret_oop(NULL); aoqi@0: clr_earlyret_value(); aoqi@0: } aoqi@0: aoqi@0: // clearing the flag indicates we are done with aoqi@0: // the ForceEarlyReturn() dance aoqi@0: clr_pending_step_for_earlyret(); aoqi@0: aoqi@0: // If exception was thrown in this frame, need to reset jvmti thread state. aoqi@0: // Single stepping may not get enabled correctly by the agent since aoqi@0: // exception state is passed in MethodExit event which may be sent at some aoqi@0: // time in the future. JDWP agent ignores MethodExit events if caused by aoqi@0: // an exception. aoqi@0: // aoqi@0: if (is_exception_detected()) { aoqi@0: clear_exception_detected(); aoqi@0: } aoqi@0: // If step is pending for earlyret then it may not be a repeat step. aoqi@0: // The new_bci and method_id is same as current_bci and current aoqi@0: // method_id after earlyret and step for recursive calls. aoqi@0: // Force the step by clearing the last location. aoqi@0: JvmtiEnvThreadStateIterator it(this); aoqi@0: for (JvmtiEnvThreadState* ets = it.first(); ets != NULL; ets = it.next(ets)) { aoqi@0: ets->clear_current_location(); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: void JvmtiThreadState::oops_do(OopClosure* f) { aoqi@0: f->do_oop((oop*) &_earlyret_oop); aoqi@0: }