hotspot/src/share/vm/prims/jvmtiEnvThreadState.cpp
changeset 1 489c9b5090e2
child 5547 f4b087cbb361
equal deleted inserted replaced
0:fd16c54261b3 1:489c9b5090e2
       
     1 /*
       
     2  * Copyright 2003-2006 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 # include "incls/_precompiled.incl"
       
    26 # include "incls/_jvmtiEnvThreadState.cpp.incl"
       
    27 
       
    28 
       
    29 ///////////////////////////////////////////////////////////////
       
    30 //
       
    31 // class JvmtiFramePop
       
    32 //
       
    33 
       
    34 #ifndef PRODUCT
       
    35 void JvmtiFramePop::print() {
       
    36   tty->print_cr("_frame_number=%d", _frame_number);
       
    37 }
       
    38 #endif
       
    39 
       
    40 
       
    41 ///////////////////////////////////////////////////////////////
       
    42 //
       
    43 // class JvmtiFramePops - private methods
       
    44 //
       
    45 
       
    46 void
       
    47 JvmtiFramePops::set(JvmtiFramePop& fp) {
       
    48   if (_pops->find(fp.frame_number()) < 0) {
       
    49     _pops->append(fp.frame_number());
       
    50   }
       
    51 }
       
    52 
       
    53 
       
    54 void
       
    55 JvmtiFramePops::clear(JvmtiFramePop& fp) {
       
    56   assert(_pops->length() > 0, "No more frame pops");
       
    57 
       
    58   _pops->remove(fp.frame_number());
       
    59 }
       
    60 
       
    61 
       
    62 int
       
    63 JvmtiFramePops::clear_to(JvmtiFramePop& fp) {
       
    64   int cleared = 0;
       
    65   int index = 0;
       
    66   while (index < _pops->length()) {
       
    67     JvmtiFramePop pop = JvmtiFramePop(_pops->at(index));
       
    68     if (pop.above_on_stack(fp)) {
       
    69       _pops->remove_at(index);
       
    70       ++cleared;
       
    71     } else {
       
    72       ++index;
       
    73     }
       
    74   }
       
    75   return cleared;
       
    76 }
       
    77 
       
    78 
       
    79 ///////////////////////////////////////////////////////////////
       
    80 //
       
    81 // class JvmtiFramePops - public methods
       
    82 //
       
    83 
       
    84 JvmtiFramePops::JvmtiFramePops() {
       
    85   _pops = new (ResourceObj::C_HEAP) GrowableArray<int> (2, true);
       
    86 }
       
    87 
       
    88 JvmtiFramePops::~JvmtiFramePops() {
       
    89   // return memory to c_heap.
       
    90   delete _pops;
       
    91 }
       
    92 
       
    93 
       
    94 #ifndef PRODUCT
       
    95 void JvmtiFramePops::print() {
       
    96   ResourceMark rm;
       
    97 
       
    98   int n = _pops->length();
       
    99   for (int i=0; i<n; i++) {
       
   100     JvmtiFramePop fp = JvmtiFramePop(_pops->at(i));
       
   101     tty->print("%d: ", i);
       
   102     fp.print();
       
   103     tty->print_cr("");
       
   104   }
       
   105 }
       
   106 #endif
       
   107 
       
   108 ///////////////////////////////////////////////////////////////
       
   109 //
       
   110 // class JvmtiEnvThreadState
       
   111 //
       
   112 // Instances of JvmtiEnvThreadState hang off of each JvmtiThreadState,
       
   113 // one per JvmtiEnv.
       
   114 //
       
   115 
       
   116 JvmtiEnvThreadState::JvmtiEnvThreadState(JavaThread *thread, JvmtiEnvBase *env) :
       
   117   _event_enable() {
       
   118   _thread                 = thread;
       
   119   _env                    = (JvmtiEnv*)env;
       
   120   _next                   = NULL;
       
   121   _frame_pops             = NULL;
       
   122   _current_bci            = 0;
       
   123   _current_method_id      = NULL;
       
   124   _breakpoint_posted      = false;
       
   125   _single_stepping_posted = false;
       
   126   _agent_thread_local_storage_data = NULL;
       
   127 }
       
   128 
       
   129 JvmtiEnvThreadState::~JvmtiEnvThreadState()   {
       
   130   delete _frame_pops;
       
   131   _frame_pops = NULL;
       
   132 }
       
   133 
       
   134 // Given that a new (potential) event has come in,
       
   135 // maintain the current JVMTI location on a per-thread per-env basis
       
   136 // and use it to filter out duplicate events:
       
   137 // - instruction rewrites
       
   138 // - breakpoint followed by single step
       
   139 // - single step at a breakpoint
       
   140 void JvmtiEnvThreadState::compare_and_set_current_location(methodOop new_method,
       
   141                                                            address new_location, jvmtiEvent event) {
       
   142 
       
   143   int new_bci = new_location - new_method->code_base();
       
   144 
       
   145   // The method is identified and stored as a jmethodID which is safe in this
       
   146   // case because the class cannot be unloaded while a method is executing.
       
   147   jmethodID new_method_id = new_method->jmethod_id();
       
   148 
       
   149   // the last breakpoint or single step was at this same location
       
   150   if (_current_bci == new_bci && _current_method_id == new_method_id) {
       
   151     switch (event) {
       
   152     case JVMTI_EVENT_BREAKPOINT:
       
   153       // Repeat breakpoint is complicated. If we previously posted a breakpoint
       
   154       // event at this location and if we also single stepped at this location
       
   155       // then we skip the duplicate breakpoint.
       
   156       _breakpoint_posted = _breakpoint_posted && _single_stepping_posted;
       
   157       break;
       
   158     case JVMTI_EVENT_SINGLE_STEP:
       
   159       // Repeat single step is easy: just don't post it again.
       
   160       // If step is pending for popframe then it may not be
       
   161       // a repeat step. The new_bci and method_id is same as current_bci
       
   162       // and current method_id after pop and step for recursive calls.
       
   163       // This has been handled by clearing the location
       
   164       _single_stepping_posted = true;
       
   165       break;
       
   166     default:
       
   167       assert(false, "invalid event value passed");
       
   168       break;
       
   169     }
       
   170     return;
       
   171   }
       
   172 
       
   173   set_current_location(new_method_id, new_bci);
       
   174   _breakpoint_posted = false;
       
   175   _single_stepping_posted = false;
       
   176 }
       
   177 
       
   178 
       
   179 JvmtiFramePops* JvmtiEnvThreadState::get_frame_pops() {
       
   180 #ifdef ASSERT
       
   181   uint32_t debug_bits = 0;
       
   182 #endif
       
   183   assert(get_thread() == Thread::current() || JvmtiEnv::is_thread_fully_suspended(get_thread(), false, &debug_bits),
       
   184          "frame pop data only accessible from same thread or while suspended");
       
   185 
       
   186   if (_frame_pops == NULL) {
       
   187     _frame_pops = new JvmtiFramePops();
       
   188     assert(_frame_pops != NULL, "_frame_pops != NULL");
       
   189   }
       
   190   return _frame_pops;
       
   191 }
       
   192 
       
   193 
       
   194 bool JvmtiEnvThreadState::has_frame_pops() {
       
   195   return _frame_pops == NULL? false : (_frame_pops->length() > 0);
       
   196 }
       
   197 
       
   198 void JvmtiEnvThreadState::set_frame_pop(int frame_number) {
       
   199 #ifdef ASSERT
       
   200   uint32_t debug_bits = 0;
       
   201 #endif
       
   202   assert(get_thread() == Thread::current() || JvmtiEnv::is_thread_fully_suspended(get_thread(), false, &debug_bits),
       
   203          "frame pop data only accessible from same thread or while suspended");
       
   204   JvmtiFramePop fpop(frame_number);
       
   205   JvmtiEventController::set_frame_pop(this, fpop);
       
   206 }
       
   207 
       
   208 
       
   209 void JvmtiEnvThreadState::clear_frame_pop(int frame_number) {
       
   210 #ifdef ASSERT
       
   211   uint32_t debug_bits = 0;
       
   212 #endif
       
   213   assert(get_thread() == Thread::current() || JvmtiEnv::is_thread_fully_suspended(get_thread(), false, &debug_bits),
       
   214          "frame pop data only accessible from same thread or while suspended");
       
   215   JvmtiFramePop fpop(frame_number);
       
   216   JvmtiEventController::clear_frame_pop(this, fpop);
       
   217 }
       
   218 
       
   219 
       
   220 void JvmtiEnvThreadState::clear_to_frame_pop(int frame_number)  {
       
   221 #ifdef ASSERT
       
   222   uint32_t debug_bits = 0;
       
   223 #endif
       
   224   assert(get_thread() == Thread::current() || JvmtiEnv::is_thread_fully_suspended(get_thread(), false, &debug_bits),
       
   225          "frame pop data only accessible from same thread or while suspended");
       
   226   JvmtiFramePop fpop(frame_number);
       
   227   JvmtiEventController::clear_to_frame_pop(this, fpop);
       
   228 }
       
   229 
       
   230 
       
   231 bool JvmtiEnvThreadState::is_frame_pop(int cur_frame_number) {
       
   232 #ifdef ASSERT
       
   233   uint32_t debug_bits = 0;
       
   234 #endif
       
   235   assert(get_thread() == Thread::current() || JvmtiEnv::is_thread_fully_suspended(get_thread(), false, &debug_bits),
       
   236          "frame pop data only accessible from same thread or while suspended");
       
   237   if (!get_thread()->is_interp_only_mode() || _frame_pops == NULL) {
       
   238     return false;
       
   239   }
       
   240   JvmtiFramePop fp(cur_frame_number);
       
   241   return get_frame_pops()->contains(fp);
       
   242 }
       
   243 
       
   244 
       
   245 class VM_GetCurrentLocation : public VM_Operation {
       
   246  private:
       
   247    JavaThread *_thread;
       
   248    jmethodID _method_id;
       
   249    int _bci;
       
   250 
       
   251  public:
       
   252   VM_GetCurrentLocation(JavaThread *thread) {
       
   253      _thread = thread;
       
   254    }
       
   255   VMOp_Type type() const { return VMOp_GetCurrentLocation; }
       
   256   void doit() {
       
   257     ResourceMark rmark; // _thread != Thread::current()
       
   258     RegisterMap rm(_thread, false);
       
   259     javaVFrame* vf = _thread->last_java_vframe(&rm);
       
   260     assert(vf != NULL, "must have last java frame");
       
   261     methodOop method = vf->method();
       
   262     _method_id = method->jmethod_id();
       
   263     _bci = vf->bci();
       
   264   }
       
   265   void get_current_location(jmethodID *method_id, int *bci) {
       
   266     *method_id = _method_id;
       
   267     *bci = _bci;
       
   268   }
       
   269 };
       
   270 
       
   271 void JvmtiEnvThreadState::reset_current_location(jvmtiEvent event_type, bool enabled) {
       
   272   assert(event_type == JVMTI_EVENT_SINGLE_STEP || event_type == JVMTI_EVENT_BREAKPOINT,
       
   273          "must be single-step or breakpoint event");
       
   274 
       
   275   // Current location is used to detect the following:
       
   276   // 1) a breakpoint event followed by single-stepping to the same bci
       
   277   // 2) single-step to a bytecode that will be transformed to a fast version
       
   278   // We skip to avoid posting the duplicate single-stepping event.
       
   279 
       
   280   // If single-stepping is disabled, clear current location so that
       
   281   // single-stepping to the same method and bcp at a later time will be
       
   282   // detected if single-stepping is enabled at that time (see 4388912).
       
   283 
       
   284   // If single-stepping is enabled, set the current location to the
       
   285   // current method and bcp. This covers the following type of case,
       
   286   // e.g., the debugger stepi command:
       
   287   // - bytecode single stepped
       
   288   // - SINGLE_STEP event posted and SINGLE_STEP event disabled
       
   289   // - SINGLE_STEP event reenabled
       
   290   // - bytecode rewritten to fast version
       
   291 
       
   292   // If breakpoint event is disabled, clear current location only if
       
   293   // single-stepping is not enabled.  Otherwise, keep the thread location
       
   294   // to detect any duplicate events.
       
   295 
       
   296   if (enabled) {
       
   297     // If enabling breakpoint, no need to reset.
       
   298     // Can't do anything if empty stack.
       
   299     if (event_type == JVMTI_EVENT_SINGLE_STEP && _thread->has_last_Java_frame()) {
       
   300       jmethodID method_id;
       
   301       int bci;
       
   302       // The java thread stack may not be walkable for a running thread
       
   303       // so get current location at safepoint.
       
   304       VM_GetCurrentLocation op(_thread);
       
   305       VMThread::execute(&op);
       
   306       op.get_current_location(&method_id, &bci);
       
   307       set_current_location(method_id, bci);
       
   308     }
       
   309   } else if (event_type == JVMTI_EVENT_SINGLE_STEP || !is_enabled(JVMTI_EVENT_SINGLE_STEP)) {
       
   310     // If this is to disable breakpoint, also check if single-step is not enabled
       
   311     clear_current_location();
       
   312   }
       
   313 }