| File: | jdk/src/hotspot/share/prims/jvmtiImpl.cpp | 
| Warning: | line 231, column 11 Value stored to 'thread' during its initialization is never read | 
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* | 
| 2 | * Copyright (c) 2003, 2021, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | 
| 20 | * or visit www.oracle.com if you need additional information or have any | 
| 21 | * questions. | 
| 22 | * | 
| 23 | */ | 
| 24 | |
| 25 | #include "precompiled.hpp" | 
| 26 | #include "classfile/javaClasses.hpp" | 
| 27 | #include "classfile/symbolTable.hpp" | 
| 28 | #include "code/nmethod.hpp" | 
| 29 | #include "interpreter/interpreter.hpp" | 
| 30 | #include "interpreter/oopMapCache.hpp" | 
| 31 | #include "jvmtifiles/jvmtiEnv.hpp" | 
| 32 | #include "logging/log.hpp" | 
| 33 | #include "logging/logStream.hpp" | 
| 34 | #include "memory/allocation.inline.hpp" | 
| 35 | #include "memory/resourceArea.hpp" | 
| 36 | #include "oops/instanceKlass.hpp" | 
| 37 | #include "oops/klass.inline.hpp" | 
| 38 | #include "oops/oop.inline.hpp" | 
| 39 | #include "oops/oopHandle.inline.hpp" | 
| 40 | #include "prims/jvmtiAgentThread.hpp" | 
| 41 | #include "prims/jvmtiEventController.inline.hpp" | 
| 42 | #include "prims/jvmtiImpl.hpp" | 
| 43 | #include "prims/jvmtiRedefineClasses.hpp" | 
| 44 | #include "runtime/deoptimization.hpp" | 
| 45 | #include "runtime/frame.inline.hpp" | 
| 46 | #include "runtime/handles.inline.hpp" | 
| 47 | #include "runtime/interfaceSupport.inline.hpp" | 
| 48 | #include "runtime/javaCalls.hpp" | 
| 49 | #include "runtime/jniHandles.hpp" | 
| 50 | #include "runtime/os.hpp" | 
| 51 | #include "runtime/serviceThread.hpp" | 
| 52 | #include "runtime/signature.hpp" | 
| 53 | #include "runtime/thread.inline.hpp" | 
| 54 | #include "runtime/threadSMR.hpp" | 
| 55 | #include "runtime/vframe.hpp" | 
| 56 | #include "runtime/vframe_hp.hpp" | 
| 57 | #include "runtime/vmOperations.hpp" | 
| 58 | #include "utilities/exceptions.hpp" | 
| 59 | |
| 60 | // | 
| 61 | // class JvmtiAgentThread | 
| 62 | // | 
| 63 | // JavaThread used to wrap a thread started by an agent | 
| 64 | // using the JVMTI method RunAgentThread. | 
| 65 | // | 
| 66 | |
| 67 | JvmtiAgentThread::JvmtiAgentThread(JvmtiEnv* env, jvmtiStartFunction start_fn, const void *start_arg) | 
| 68 | : JavaThread(start_function_wrapper) { | 
| 69 | _env = env; | 
| 70 | _start_fn = start_fn; | 
| 71 | _start_arg = start_arg; | 
| 72 | } | 
| 73 | |
| 74 | void | 
| 75 | JvmtiAgentThread::start_function_wrapper(JavaThread *thread, TRAPSJavaThread* __the_thread__) { | 
| 76 | // It is expected that any Agent threads will be created as | 
| 77 | // Java Threads. If this is the case, notification of the creation | 
| 78 | // of the thread is given in JavaThread::thread_main(). | 
| 79 | assert(thread == JavaThread::current(), "sanity check")do { if (!(thread == JavaThread::current())) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiImpl.cpp" , 79, "assert(" "thread == JavaThread::current()" ") failed", "sanity check"); ::breakpoint(); } } while (0); | 
| 80 | |
| 81 | JvmtiAgentThread *dthread = (JvmtiAgentThread *)thread; | 
| 82 | dthread->call_start_function(); | 
| 83 | } | 
| 84 | |
| 85 | void | 
| 86 | JvmtiAgentThread::call_start_function() { | 
| 87 | ThreadToNativeFromVM transition(this); | 
| 88 | _start_fn(_env->jvmti_external(), jni_environment(), (void*)_start_arg); | 
| 89 | } | 
| 90 | |
| 91 | |
| 92 | // | 
| 93 | // class GrowableCache - private methods | 
| 94 | // | 
| 95 | |
| 96 | void GrowableCache::recache() { | 
| 97 | int len = _elements->length(); | 
| 98 | |
| 99 | FREE_C_HEAP_ARRAY(address, _cache)FreeHeap((char*)(_cache)); | 
| 100 | _cache = NEW_C_HEAP_ARRAY(address,len+1, mtInternal)(address*) (AllocateHeap((len+1) * sizeof(address), mtInternal )); | 
| 101 | |
| 102 | for (int i=0; i<len; i++) { | 
| 103 | _cache[i] = _elements->at(i)->getCacheValue(); | 
| 104 | // | 
| 105 | // The cache entry has gone bad. Without a valid frame pointer | 
| 106 | // value, the entry is useless so we simply delete it in product | 
| 107 | // mode. The call to remove() will rebuild the cache again | 
| 108 | // without the bad entry. | 
| 109 | // | 
| 110 | if (_cache[i] == NULL__null) { | 
| 111 | assert(false, "cannot recache NULL elements")do { if (!(false)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiImpl.cpp" , 111, "assert(" "false" ") failed", "cannot recache NULL elements" ); ::breakpoint(); } } while (0); | 
| 112 | remove(i); | 
| 113 | return; | 
| 114 | } | 
| 115 | } | 
| 116 | _cache[len] = NULL__null; | 
| 117 | |
| 118 | _listener_fun(_this_obj,_cache); | 
| 119 | } | 
| 120 | |
| 121 | bool GrowableCache::equals(void* v, GrowableElement *e2) { | 
| 122 | GrowableElement *e1 = (GrowableElement *) v; | 
| 123 | assert(e1 != NULL, "e1 != NULL")do { if (!(e1 != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiImpl.cpp" , 123, "assert(" "e1 != __null" ") failed", "e1 != NULL"); :: breakpoint(); } } while (0); | 
| 124 | assert(e2 != NULL, "e2 != NULL")do { if (!(e2 != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiImpl.cpp" , 124, "assert(" "e2 != __null" ") failed", "e2 != NULL"); :: breakpoint(); } } while (0); | 
| 125 | |
| 126 | return e1->equals(e2); | 
| 127 | } | 
| 128 | |
| 129 | // | 
| 130 | // class GrowableCache - public methods | 
| 131 | // | 
| 132 | |
| 133 | GrowableCache::GrowableCache() { | 
| 134 | _this_obj = NULL__null; | 
| 135 | _listener_fun = NULL__null; | 
| 136 | _elements = NULL__null; | 
| 137 | _cache = NULL__null; | 
| 138 | } | 
| 139 | |
| 140 | GrowableCache::~GrowableCache() { | 
| 141 | clear(); | 
| 142 | delete _elements; | 
| 143 | FREE_C_HEAP_ARRAY(address, _cache)FreeHeap((char*)(_cache)); | 
| 144 | } | 
| 145 | |
| 146 | void GrowableCache::initialize(void *this_obj, void listener_fun(void *, address*) ) { | 
| 147 | _this_obj = this_obj; | 
| 148 | _listener_fun = listener_fun; | 
| 149 | _elements = new (ResourceObj::C_HEAP, mtServiceability) GrowableArray<GrowableElement*>(5, mtServiceability); | 
| 150 | recache(); | 
| 151 | } | 
| 152 | |
| 153 | // number of elements in the collection | 
| 154 | int GrowableCache::length() { | 
| 155 | return _elements->length(); | 
| 156 | } | 
| 157 | |
| 158 | // get the value of the index element in the collection | 
| 159 | GrowableElement* GrowableCache::at(int index) { | 
| 160 | GrowableElement *e = (GrowableElement *) _elements->at(index); | 
| 161 | assert(e != NULL, "e != NULL")do { if (!(e != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiImpl.cpp" , 161, "assert(" "e != __null" ") failed", "e != NULL"); ::breakpoint (); } } while (0); | 
| 162 | return e; | 
| 163 | } | 
| 164 | |
| 165 | int GrowableCache::find(GrowableElement* e) { | 
| 166 | return _elements->find(e, GrowableCache::equals); | 
| 167 | } | 
| 168 | |
| 169 | // append a copy of the element to the end of the collection | 
| 170 | void GrowableCache::append(GrowableElement* e) { | 
| 171 | GrowableElement *new_e = e->clone(); | 
| 172 | _elements->append(new_e); | 
| 173 | recache(); | 
| 174 | } | 
| 175 | |
| 176 | // remove the element at index | 
| 177 | void GrowableCache::remove (int index) { | 
| 178 | GrowableElement *e = _elements->at(index); | 
| 179 | assert(e != NULL, "e != NULL")do { if (!(e != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiImpl.cpp" , 179, "assert(" "e != __null" ") failed", "e != NULL"); ::breakpoint (); } } while (0); | 
| 180 | _elements->remove(e); | 
| 181 | delete e; | 
| 182 | recache(); | 
| 183 | } | 
| 184 | |
| 185 | // clear out all elements, release all heap space and | 
| 186 | // let our listener know that things have changed. | 
| 187 | void GrowableCache::clear() { | 
| 188 | int len = _elements->length(); | 
| 189 | for (int i=0; i<len; i++) { | 
| 190 | delete _elements->at(i); | 
| 191 | } | 
| 192 | _elements->clear(); | 
| 193 | recache(); | 
| 194 | } | 
| 195 | |
| 196 | // | 
| 197 | // class JvmtiBreakpoint | 
| 198 | // | 
| 199 | |
| 200 | JvmtiBreakpoint::JvmtiBreakpoint(Method* m_method, jlocation location) | 
| 201 | : _method(m_method), _bci((int)location) { | 
| 202 | assert(_method != NULL, "No method for breakpoint.")do { if (!(_method != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiImpl.cpp" , 202, "assert(" "_method != __null" ") failed", "No method for breakpoint." ); ::breakpoint(); } } while (0); | 
| 203 | assert(_bci >= 0, "Negative bci for breakpoint.")do { if (!(_bci >= 0)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiImpl.cpp" , 203, "assert(" "_bci >= 0" ") failed", "Negative bci for breakpoint." ); ::breakpoint(); } } while (0); | 
| 204 | oop class_holder_oop = _method->method_holder()->klass_holder(); | 
| 205 | _class_holder = OopHandle(JvmtiExport::jvmti_oop_storage(), class_holder_oop); | 
| 206 | } | 
| 207 | |
| 208 | JvmtiBreakpoint::~JvmtiBreakpoint() { | 
| 209 | _class_holder.release(JvmtiExport::jvmti_oop_storage()); | 
| 210 | } | 
| 211 | |
| 212 | void JvmtiBreakpoint::copy(JvmtiBreakpoint& bp) { | 
| 213 | _method = bp._method; | 
| 214 | _bci = bp._bci; | 
| 215 | _class_holder = OopHandle(JvmtiExport::jvmti_oop_storage(), bp._class_holder.resolve()); | 
| 216 | } | 
| 217 | |
| 218 | bool JvmtiBreakpoint::equals(JvmtiBreakpoint& bp) { | 
| 219 | return _method == bp._method | 
| 220 | && _bci == bp._bci; | 
| 221 | } | 
| 222 | |
| 223 | address JvmtiBreakpoint::getBcp() const { | 
| 224 | return _method->bcp_from(_bci); | 
| 225 | } | 
| 226 | |
| 227 | void JvmtiBreakpoint::each_method_version_do(method_action meth_act) { | 
| 228 | ((Method*)_method->*meth_act)(_bci); | 
| 229 | |
| 230 | // add/remove breakpoint to/from versions of the method that are EMCP. | 
| 231 | Thread *thread = Thread::current(); | 
| Value stored to 'thread' during its initialization is never read | |
| 232 | InstanceKlass* ik = _method->method_holder(); | 
| 233 | Symbol* m_name = _method->name(); | 
| 234 | Symbol* m_signature = _method->signature(); | 
| 235 | |
| 236 | // search previous versions if they exist | 
| 237 | for (InstanceKlass* pv_node = ik->previous_versions(); | 
| 238 | pv_node != NULL__null; | 
| 239 | pv_node = pv_node->previous_versions()) { | 
| 240 | Array<Method*>* methods = pv_node->methods(); | 
| 241 | |
| 242 | for (int i = methods->length() - 1; i >= 0; i--) { | 
| 243 | Method* method = methods->at(i); | 
| 244 | // Only set breakpoints in EMCP methods. | 
| 245 | // EMCP methods are old but not obsolete. Equivalent | 
| 246 | // Modulo Constant Pool means the method is equivalent except | 
| 247 | // the constant pool and instructions that access the constant | 
| 248 | // pool might be different. | 
| 249 | // If a breakpoint is set in a redefined method, its EMCP methods | 
| 250 | // must have a breakpoint also. | 
| 251 | // None of the methods are deleted until none are running. | 
| 252 | // This code could set a breakpoint in a method that | 
| 253 | // is never reached, but this won't be noticeable to the programmer. | 
| 254 | if (!method->is_obsolete() && | 
| 255 | method->name() == m_name && | 
| 256 | method->signature() == m_signature) { | 
| 257 | ResourceMark rm; | 
| 258 | log_debug(redefine, class, breakpoint)(!(LogImpl<(LogTag::_redefine), (LogTag::_class), (LogTag:: _breakpoint), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag ::__NO_TAG)>::is_level(LogLevel::Debug))) ? (void)0 : LogImpl <(LogTag::_redefine), (LogTag::_class), (LogTag::_breakpoint ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::write<LogLevel::Debug> | 
| 259 | ("%sing breakpoint in %s(%s)", meth_act == &Method::set_breakpoint ? "sett" : "clear", | 
| 260 | method->name()->as_C_string(), method->signature()->as_C_string()); | 
| 261 | (method->*meth_act)(_bci); | 
| 262 | break; | 
| 263 | } | 
| 264 | } | 
| 265 | } | 
| 266 | } | 
| 267 | |
| 268 | void JvmtiBreakpoint::set() { | 
| 269 | each_method_version_do(&Method::set_breakpoint); | 
| 270 | } | 
| 271 | |
| 272 | void JvmtiBreakpoint::clear() { | 
| 273 | each_method_version_do(&Method::clear_breakpoint); | 
| 274 | } | 
| 275 | |
| 276 | void JvmtiBreakpoint::print_on(outputStream* out) const { | 
| 277 | #ifndef PRODUCT | 
| 278 | ResourceMark rm; | 
| 279 | const char *class_name = (_method == NULL__null) ? "NULL" : _method->klass_name()->as_C_string(); | 
| 280 | const char *method_name = (_method == NULL__null) ? "NULL" : _method->name()->as_C_string(); | 
| 281 | out->print("Breakpoint(%s,%s,%d,%p)", class_name, method_name, _bci, getBcp()); | 
| 282 | #endif | 
| 283 | } | 
| 284 | |
| 285 | |
| 286 | // | 
| 287 | // class VM_ChangeBreakpoints | 
| 288 | // | 
| 289 | // Modify the Breakpoints data structure at a safepoint | 
| 290 | // | 
| 291 | |
| 292 | void VM_ChangeBreakpoints::doit() { | 
| 293 | switch (_operation) { | 
| 294 | case SET_BREAKPOINT: | 
| 295 | _breakpoints->set_at_safepoint(*_bp); | 
| 296 | break; | 
| 297 | case CLEAR_BREAKPOINT: | 
| 298 | _breakpoints->clear_at_safepoint(*_bp); | 
| 299 | break; | 
| 300 | default: | 
| 301 | assert(false, "Unknown operation")do { if (!(false)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiImpl.cpp" , 301, "assert(" "false" ") failed", "Unknown operation"); :: breakpoint(); } } while (0); | 
| 302 | } | 
| 303 | } | 
| 304 | |
| 305 | // | 
| 306 | // class JvmtiBreakpoints | 
| 307 | // | 
| 308 | // a JVMTI internal collection of JvmtiBreakpoint | 
| 309 | // | 
| 310 | |
| 311 | JvmtiBreakpoints::JvmtiBreakpoints(void listener_fun(void *,address *)) { | 
| 312 | _bps.initialize(this,listener_fun); | 
| 313 | } | 
| 314 | |
| 315 | JvmtiBreakpoints:: ~JvmtiBreakpoints() {} | 
| 316 | |
| 317 | void JvmtiBreakpoints::print() { | 
| 318 | #ifndef PRODUCT | 
| 319 | LogTarget(Trace, jvmti)LogTargetImpl<LogLevel::Trace, (LogTag::_jvmti), (LogTag:: __NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG)> log; | 
| 320 | LogStream log_stream(log); | 
| 321 | |
| 322 | int n = _bps.length(); | 
| 323 | for (int i=0; i<n; i++) { | 
| 324 | JvmtiBreakpoint& bp = _bps.at(i); | 
| 325 | log_stream.print("%d: ", i); | 
| 326 | bp.print_on(&log_stream); | 
| 327 | log_stream.cr(); | 
| 328 | } | 
| 329 | #endif | 
| 330 | } | 
| 331 | |
| 332 | |
| 333 | void JvmtiBreakpoints::set_at_safepoint(JvmtiBreakpoint& bp) { | 
| 334 | assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint")do { if (!(SafepointSynchronize::is_at_safepoint())) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiImpl.cpp" , 334, "assert(" "SafepointSynchronize::is_at_safepoint()" ") failed" , "must be at safepoint"); ::breakpoint(); } } while (0); | 
| 335 | |
| 336 | int i = _bps.find(bp); | 
| 337 | if (i == -1) { | 
| 338 | _bps.append(bp); | 
| 339 | bp.set(); | 
| 340 | } | 
| 341 | } | 
| 342 | |
| 343 | void JvmtiBreakpoints::clear_at_safepoint(JvmtiBreakpoint& bp) { | 
| 344 | assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint")do { if (!(SafepointSynchronize::is_at_safepoint())) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiImpl.cpp" , 344, "assert(" "SafepointSynchronize::is_at_safepoint()" ") failed" , "must be at safepoint"); ::breakpoint(); } } while (0); | 
| 345 | |
| 346 | int i = _bps.find(bp); | 
| 347 | if (i != -1) { | 
| 348 | _bps.remove(i); | 
| 349 | bp.clear(); | 
| 350 | } | 
| 351 | } | 
| 352 | |
| 353 | int JvmtiBreakpoints::length() { return _bps.length(); } | 
| 354 | |
| 355 | int JvmtiBreakpoints::set(JvmtiBreakpoint& bp) { | 
| 356 | if ( _bps.find(bp) != -1) { | 
| 357 | return JVMTI_ERROR_DUPLICATE; | 
| 358 | } | 
| 359 | VM_ChangeBreakpoints set_breakpoint(VM_ChangeBreakpoints::SET_BREAKPOINT, &bp); | 
| 360 | VMThread::execute(&set_breakpoint); | 
| 361 | return JVMTI_ERROR_NONE; | 
| 362 | } | 
| 363 | |
| 364 | int JvmtiBreakpoints::clear(JvmtiBreakpoint& bp) { | 
| 365 | if ( _bps.find(bp) == -1) { | 
| 366 | return JVMTI_ERROR_NOT_FOUND; | 
| 367 | } | 
| 368 | |
| 369 | VM_ChangeBreakpoints clear_breakpoint(VM_ChangeBreakpoints::CLEAR_BREAKPOINT, &bp); | 
| 370 | VMThread::execute(&clear_breakpoint); | 
| 371 | return JVMTI_ERROR_NONE; | 
| 372 | } | 
| 373 | |
| 374 | void JvmtiBreakpoints::clearall_in_class_at_safepoint(Klass* klass) { | 
| 375 | bool changed = true; | 
| 376 | // We are going to run thru the list of bkpts | 
| 377 | // and delete some. This deletion probably alters | 
| 378 | // the list in some implementation defined way such | 
| 379 | // that when we delete entry i, the next entry might | 
| 380 | // no longer be at i+1. To be safe, each time we delete | 
| 381 | // an entry, we'll just start again from the beginning. | 
| 382 | // We'll stop when we make a pass thru the whole list without | 
| 383 | // deleting anything. | 
| 384 | while (changed) { | 
| 385 | int len = _bps.length(); | 
| 386 | changed = false; | 
| 387 | for (int i = 0; i < len; i++) { | 
| 388 | JvmtiBreakpoint& bp = _bps.at(i); | 
| 389 | if (bp.method()->method_holder() == klass) { | 
| 390 | bp.clear(); | 
| 391 | _bps.remove(i); | 
| 392 | // This changed 'i' so we have to start over. | 
| 393 | changed = true; | 
| 394 | break; | 
| 395 | } | 
| 396 | } | 
| 397 | } | 
| 398 | } | 
| 399 | |
| 400 | // | 
| 401 | // class JvmtiCurrentBreakpoints | 
| 402 | // | 
| 403 | |
| 404 | JvmtiBreakpoints *JvmtiCurrentBreakpoints::_jvmti_breakpoints = NULL__null; | 
| 405 | address * JvmtiCurrentBreakpoints::_breakpoint_list = NULL__null; | 
| 406 | |
| 407 | |
| 408 | JvmtiBreakpoints& JvmtiCurrentBreakpoints::get_jvmti_breakpoints() { | 
| 409 | if (_jvmti_breakpoints != NULL__null) return (*_jvmti_breakpoints); | 
| 410 | _jvmti_breakpoints = new JvmtiBreakpoints(listener_fun); | 
| 411 | assert(_jvmti_breakpoints != NULL, "_jvmti_breakpoints != NULL")do { if (!(_jvmti_breakpoints != __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiImpl.cpp" , 411, "assert(" "_jvmti_breakpoints != __null" ") failed", "_jvmti_breakpoints != NULL" ); ::breakpoint(); } } while (0); | 
| 412 | return (*_jvmti_breakpoints); | 
| 413 | } | 
| 414 | |
| 415 | void JvmtiCurrentBreakpoints::listener_fun(void *this_obj, address *cache) { | 
| 416 | JvmtiBreakpoints *this_jvmti = (JvmtiBreakpoints *) this_obj; | 
| 417 | assert(this_jvmti != NULL, "this_jvmti != NULL")do { if (!(this_jvmti != __null)) { (*g_assert_poison) = 'X'; ; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiImpl.cpp" , 417, "assert(" "this_jvmti != __null" ") failed", "this_jvmti != NULL" ); ::breakpoint(); } } while (0); | 
| 418 | |
| 419 | debug_only(int n = this_jvmti->length();)int n = this_jvmti->length();; | 
| 420 | assert(cache[n] == NULL, "cache must be NULL terminated")do { if (!(cache[n] == __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiImpl.cpp" , 420, "assert(" "cache[n] == __null" ") failed", "cache must be NULL terminated" ); ::breakpoint(); } } while (0); | 
| 421 | |
| 422 | set_breakpoint_list(cache); | 
| 423 | } | 
| 424 | |
| 425 | /////////////////////////////////////////////////////////////// | 
| 426 | // | 
| 427 | // class VM_GetOrSetLocal | 
| 428 | // | 
| 429 | |
| 430 | // Constructor for non-object getter | 
| 431 | VM_GetOrSetLocal::VM_GetOrSetLocal(JavaThread* thread, jint depth, jint index, BasicType type) | 
| 432 | : _thread(thread) | 
| 433 | , _calling_thread(NULL__null) | 
| 434 | , _depth(depth) | 
| 435 | , _index(index) | 
| 436 | , _type(type) | 
| 437 | , _jvf(NULL__null) | 
| 438 | , _set(false) | 
| 439 | , _eb(false, NULL__null, NULL__null) | 
| 440 | , _result(JVMTI_ERROR_NONE) | 
| 441 | { | 
| 442 | } | 
| 443 | |
| 444 | // Constructor for object or non-object setter | 
| 445 | VM_GetOrSetLocal::VM_GetOrSetLocal(JavaThread* thread, jint depth, jint index, BasicType type, jvalue value) | 
| 446 | : _thread(thread) | 
| 447 | , _calling_thread(NULL__null) | 
| 448 | , _depth(depth) | 
| 449 | , _index(index) | 
| 450 | , _type(type) | 
| 451 | , _value(value) | 
| 452 | , _jvf(NULL__null) | 
| 453 | , _set(true) | 
| 454 | , _eb(type == T_OBJECT, JavaThread::current(), thread) | 
| 455 | , _result(JVMTI_ERROR_NONE) | 
| 456 | { | 
| 457 | } | 
| 458 | |
| 459 | // Constructor for object getter | 
| 460 | VM_GetOrSetLocal::VM_GetOrSetLocal(JavaThread* thread, JavaThread* calling_thread, jint depth, int index) | 
| 461 | : _thread(thread) | 
| 462 | , _calling_thread(calling_thread) | 
| 463 | , _depth(depth) | 
| 464 | , _index(index) | 
| 465 | , _type(T_OBJECT) | 
| 466 | , _jvf(NULL__null) | 
| 467 | , _set(false) | 
| 468 | , _eb(true, calling_thread, thread) | 
| 469 | , _result(JVMTI_ERROR_NONE) | 
| 470 | { | 
| 471 | } | 
| 472 | |
| 473 | vframe *VM_GetOrSetLocal::get_vframe() { | 
| 474 | if (!_thread->has_last_Java_frame()) { | 
| 475 | return NULL__null; | 
| 476 | } | 
| 477 | RegisterMap reg_map(_thread); | 
| 478 | vframe *vf = _thread->last_java_vframe(®_map); | 
| 479 | int d = 0; | 
| 480 | while ((vf != NULL__null) && (d < _depth)) { | 
| 481 | vf = vf->java_sender(); | 
| 482 | d++; | 
| 483 | } | 
| 484 | return vf; | 
| 485 | } | 
| 486 | |
| 487 | javaVFrame *VM_GetOrSetLocal::get_java_vframe() { | 
| 488 | vframe* vf = get_vframe(); | 
| 489 | if (vf == NULL__null) { | 
| 490 | _result = JVMTI_ERROR_NO_MORE_FRAMES; | 
| 491 | return NULL__null; | 
| 492 | } | 
| 493 | javaVFrame *jvf = (javaVFrame*)vf; | 
| 494 | |
| 495 | if (!vf->is_java_frame()) { | 
| 496 | _result = JVMTI_ERROR_OPAQUE_FRAME; | 
| 497 | return NULL__null; | 
| 498 | } | 
| 499 | return jvf; | 
| 500 | } | 
| 501 | |
| 502 | // Check that the klass is assignable to a type with the given signature. | 
| 503 | // Another solution could be to use the function Klass::is_subtype_of(type). | 
| 504 | // But the type class can be forced to load/initialize eagerly in such a case. | 
| 505 | // This may cause unexpected consequences like CFLH or class-init JVMTI events. | 
| 506 | // It is better to avoid such a behavior. | 
| 507 | bool VM_GetOrSetLocal::is_assignable(const char* ty_sign, Klass* klass, Thread* thread) { | 
| 508 | assert(ty_sign != NULL, "type signature must not be NULL")do { if (!(ty_sign != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiImpl.cpp" , 508, "assert(" "ty_sign != __null" ") failed", "type signature must not be NULL" ); ::breakpoint(); } } while (0); | 
| 509 | assert(thread != NULL, "thread must not be NULL")do { if (!(thread != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiImpl.cpp" , 509, "assert(" "thread != __null" ") failed", "thread must not be NULL" ); ::breakpoint(); } } while (0); | 
| 510 | assert(klass != NULL, "klass must not be NULL")do { if (!(klass != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiImpl.cpp" , 510, "assert(" "klass != __null" ") failed", "klass must not be NULL" ); ::breakpoint(); } } while (0); | 
| 511 | |
| 512 | int len = (int) strlen(ty_sign); | 
| 513 | if (ty_sign[0] == JVM_SIGNATURE_CLASS && | 
| 514 | ty_sign[len-1] == JVM_SIGNATURE_ENDCLASS) { // Need pure class/interface name | 
| 515 | ty_sign++; | 
| 516 | len -= 2; | 
| 517 | } | 
| 518 | TempNewSymbol ty_sym = SymbolTable::new_symbol(ty_sign, len); | 
| 519 | if (klass->name() == ty_sym) { | 
| 520 | return true; | 
| 521 | } | 
| 522 | // Compare primary supers | 
| 523 | int super_depth = klass->super_depth(); | 
| 524 | int idx; | 
| 525 | for (idx = 0; idx < super_depth; idx++) { | 
| 526 | if (klass->primary_super_of_depth(idx)->name() == ty_sym) { | 
| 527 | return true; | 
| 528 | } | 
| 529 | } | 
| 530 | // Compare secondary supers | 
| 531 | const Array<Klass*>* sec_supers = klass->secondary_supers(); | 
| 532 | for (idx = 0; idx < sec_supers->length(); idx++) { | 
| 533 | if (((Klass*) sec_supers->at(idx))->name() == ty_sym) { | 
| 534 | return true; | 
| 535 | } | 
| 536 | } | 
| 537 | return false; | 
| 538 | } | 
| 539 | |
| 540 | // Checks error conditions: | 
| 541 | // JVMTI_ERROR_INVALID_SLOT | 
| 542 | // JVMTI_ERROR_TYPE_MISMATCH | 
| 543 | // Returns: 'true' - everything is Ok, 'false' - error code | 
| 544 | |
| 545 | bool VM_GetOrSetLocal::check_slot_type_lvt(javaVFrame* jvf) { | 
| 546 | Method* method = jvf->method(); | 
| 547 | jint num_entries = method->localvariable_table_length(); | 
| 548 | if (num_entries == 0) { | 
| 549 | _result = JVMTI_ERROR_INVALID_SLOT; | 
| 550 | return false; // There are no slots | 
| 551 | } | 
| 552 | int signature_idx = -1; | 
| 553 | int vf_bci = jvf->bci(); | 
| 554 | LocalVariableTableElement* table = method->localvariable_table_start(); | 
| 555 | for (int i = 0; i < num_entries; i++) { | 
| 556 | int start_bci = table[i].start_bci; | 
| 557 | int end_bci = start_bci + table[i].length; | 
| 558 | |
| 559 | // Here we assume that locations of LVT entries | 
| 560 | // with the same slot number cannot be overlapped | 
| 561 | if (_index == (jint) table[i].slot && start_bci <= vf_bci && vf_bci <= end_bci) { | 
| 562 | signature_idx = (int) table[i].descriptor_cp_index; | 
| 563 | break; | 
| 564 | } | 
| 565 | } | 
| 566 | if (signature_idx == -1) { | 
| 567 | _result = JVMTI_ERROR_INVALID_SLOT; | 
| 568 | return false; // Incorrect slot index | 
| 569 | } | 
| 570 | Symbol* sign_sym = method->constants()->symbol_at(signature_idx); | 
| 571 | BasicType slot_type = Signature::basic_type(sign_sym); | 
| 572 | |
| 573 | switch (slot_type) { | 
| 574 | case T_BYTE: | 
| 575 | case T_SHORT: | 
| 576 | case T_CHAR: | 
| 577 | case T_BOOLEAN: | 
| 578 | slot_type = T_INT; | 
| 579 | break; | 
| 580 | case T_ARRAY: | 
| 581 | slot_type = T_OBJECT; | 
| 582 | break; | 
| 583 | default: | 
| 584 | break; | 
| 585 | }; | 
| 586 | if (_type != slot_type) { | 
| 587 | _result = JVMTI_ERROR_TYPE_MISMATCH; | 
| 588 | return false; | 
| 589 | } | 
| 590 | |
| 591 | jobject jobj = _value.l; | 
| 592 | if (_set && slot_type == T_OBJECT && jobj != NULL__null) { // NULL reference is allowed | 
| 593 | // Check that the jobject class matches the return type signature. | 
| 594 | oop obj = JNIHandles::resolve_external_guard(jobj); | 
| 595 | NULL_CHECK(obj, (_result = JVMTI_ERROR_INVALID_OBJECT, false))if ((obj) == __null) { return ((_result = JVMTI_ERROR_INVALID_OBJECT , false)); }; | 
| 596 | Klass* ob_k = obj->klass(); | 
| 597 | NULL_CHECK(ob_k, (_result = JVMTI_ERROR_INVALID_OBJECT, false))if ((ob_k) == __null) { return ((_result = JVMTI_ERROR_INVALID_OBJECT , false)); }; | 
| 598 | |
| 599 | const char* signature = (const char *) sign_sym->as_utf8(); | 
| 600 | if (!is_assignable(signature, ob_k, VMThread::vm_thread())) { | 
| 601 | _result = JVMTI_ERROR_TYPE_MISMATCH; | 
| 602 | return false; | 
| 603 | } | 
| 604 | } | 
| 605 | return true; | 
| 606 | } | 
| 607 | |
| 608 | bool VM_GetOrSetLocal::check_slot_type_no_lvt(javaVFrame* jvf) { | 
| 609 | Method* method = jvf->method(); | 
| 610 | jint extra_slot = (_type == T_LONG || _type == T_DOUBLE) ? 1 : 0; | 
| 611 | |
| 612 | if (_index < 0 || _index + extra_slot >= method->max_locals()) { | 
| 613 | _result = JVMTI_ERROR_INVALID_SLOT; | 
| 614 | return false; | 
| 615 | } | 
| 616 | StackValueCollection *locals = _jvf->locals(); | 
| 617 | BasicType slot_type = locals->at(_index)->type(); | 
| 618 | |
| 619 | if (slot_type == T_CONFLICT) { | 
| 620 | _result = JVMTI_ERROR_INVALID_SLOT; | 
| 621 | return false; | 
| 622 | } | 
| 623 | if (extra_slot) { | 
| 624 | BasicType extra_slot_type = locals->at(_index + 1)->type(); | 
| 625 | if (extra_slot_type != T_INT) { | 
| 626 | _result = JVMTI_ERROR_INVALID_SLOT; | 
| 627 | return false; | 
| 628 | } | 
| 629 | } | 
| 630 | if (_type != slot_type && (_type == T_OBJECT || slot_type != T_INT)) { | 
| 631 | _result = JVMTI_ERROR_TYPE_MISMATCH; | 
| 632 | return false; | 
| 633 | } | 
| 634 | return true; | 
| 635 | } | 
| 636 | |
| 637 | static bool can_be_deoptimized(vframe* vf) { | 
| 638 | return (vf->is_compiled_frame() && vf->fr().can_be_deoptimized()); | 
| 639 | } | 
| 640 | |
| 641 | bool VM_GetOrSetLocal::doit_prologue() { | 
| 642 | if (!_eb.deoptimize_objects(_depth, _depth)) { | 
| 643 | // The target frame is affected by a reallocation failure. | 
| 644 | _result = JVMTI_ERROR_OUT_OF_MEMORY; | 
| 645 | return false; | 
| 646 | } | 
| 647 | |
| 648 | return true; | 
| 649 | } | 
| 650 | |
| 651 | void VM_GetOrSetLocal::doit() { | 
| 652 | _jvf = _jvf == NULL__null ? get_java_vframe() : _jvf; | 
| 653 | if (_jvf == NULL__null) { | 
| 654 | return; | 
| 655 | }; | 
| 656 | |
| 657 | Method* method = _jvf->method(); | 
| 658 | if (getting_receiver()) { | 
| 659 | if (method->is_static()) { | 
| 660 | _result = JVMTI_ERROR_INVALID_SLOT; | 
| 661 | return; | 
| 662 | } | 
| 663 | } else { | 
| 664 | if (method->is_native()) { | 
| 665 | _result = JVMTI_ERROR_OPAQUE_FRAME; | 
| 666 | return; | 
| 667 | } | 
| 668 | |
| 669 | if (!check_slot_type_no_lvt(_jvf)) { | 
| 670 | return; | 
| 671 | } | 
| 672 | if (method->has_localvariable_table() && | 
| 673 | !check_slot_type_lvt(_jvf)) { | 
| 674 | return; | 
| 675 | } | 
| 676 | } | 
| 677 | |
| 678 | InterpreterOopMap oop_mask; | 
| 679 | _jvf->method()->mask_for(_jvf->bci(), &oop_mask); | 
| 680 | if (oop_mask.is_dead(_index)) { | 
| 681 | // The local can be invalid and uninitialized in the scope of current bci | 
| 682 | _result = JVMTI_ERROR_INVALID_SLOT; | 
| 683 | return; | 
| 684 | } | 
| 685 | if (_set) { | 
| 686 | // Force deoptimization of frame if compiled because it's | 
| 687 | // possible the compiler emitted some locals as constant values, | 
| 688 | // meaning they are not mutable. | 
| 689 | if (can_be_deoptimized(_jvf)) { | 
| 690 | |
| 691 | // Schedule deoptimization so that eventually the local | 
| 692 | // update will be written to an interpreter frame. | 
| 693 | Deoptimization::deoptimize_frame(_jvf->thread(), _jvf->fr().id()); | 
| 694 | |
| 695 | // Now store a new value for the local which will be applied | 
| 696 | // once deoptimization occurs. Note however that while this | 
| 697 | // write is deferred until deoptimization actually happens | 
| 698 | // can vframe created after this point will have its locals | 
| 699 | // reflecting this update so as far as anyone can see the | 
| 700 | // write has already taken place. | 
| 701 | |
| 702 | // If we are updating an oop then get the oop from the handle | 
| 703 | // since the handle will be long gone by the time the deopt | 
| 704 | // happens. The oop stored in the deferred local will be | 
| 705 | // gc'd on its own. | 
| 706 | if (_type == T_OBJECT) { | 
| 707 | _value.l = cast_from_oop<jobject>(JNIHandles::resolve_external_guard(_value.l)); | 
| 708 | } | 
| 709 | // Re-read the vframe so we can see that it is deoptimized | 
| 710 | // [ Only need because of assert in update_local() ] | 
| 711 | _jvf = get_java_vframe(); | 
| 712 | ((compiledVFrame*)_jvf)->update_local(_type, _index, _value); | 
| 713 | return; | 
| 714 | } | 
| 715 | StackValueCollection *locals = _jvf->locals(); | 
| 716 | Thread* current_thread = VMThread::vm_thread(); | 
| 717 | HandleMark hm(current_thread); | 
| 718 | |
| 719 | switch (_type) { | 
| 720 | case T_INT: locals->set_int_at (_index, _value.i); break; | 
| 721 | case T_LONG: locals->set_long_at (_index, _value.j); break; | 
| 722 | case T_FLOAT: locals->set_float_at (_index, _value.f); break; | 
| 723 | case T_DOUBLE: locals->set_double_at(_index, _value.d); break; | 
| 724 | case T_OBJECT: { | 
| 725 | Handle ob_h(current_thread, JNIHandles::resolve_external_guard(_value.l)); | 
| 726 | locals->set_obj_at (_index, ob_h); | 
| 727 | break; | 
| 728 | } | 
| 729 | default: ShouldNotReachHere()do { (*g_assert_poison) = 'X';; report_should_not_reach_here( "/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiImpl.cpp" , 729); ::breakpoint(); } while (0); | 
| 730 | } | 
| 731 | _jvf->set_locals(locals); | 
| 732 | } else { | 
| 733 | if (_jvf->method()->is_native() && _jvf->is_compiled_frame()) { | 
| 734 | assert(getting_receiver(), "Can only get here when getting receiver")do { if (!(getting_receiver())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiImpl.cpp" , 734, "assert(" "getting_receiver()" ") failed", "Can only get here when getting receiver" ); ::breakpoint(); } } while (0); | 
| 735 | oop receiver = _jvf->fr().get_native_receiver(); | 
| 736 | _value.l = JNIHandles::make_local(_calling_thread, receiver); | 
| 737 | } else { | 
| 738 | StackValueCollection *locals = _jvf->locals(); | 
| 739 | |
| 740 | switch (_type) { | 
| 741 | case T_INT: _value.i = locals->int_at (_index); break; | 
| 742 | case T_LONG: _value.j = locals->long_at (_index); break; | 
| 743 | case T_FLOAT: _value.f = locals->float_at (_index); break; | 
| 744 | case T_DOUBLE: _value.d = locals->double_at(_index); break; | 
| 745 | case T_OBJECT: { | 
| 746 | // Wrap the oop to be returned in a local JNI handle since | 
| 747 | // oops_do() no longer applies after doit() is finished. | 
| 748 | oop obj = locals->obj_at(_index)(); | 
| 749 | _value.l = JNIHandles::make_local(_calling_thread, obj); | 
| 750 | break; | 
| 751 | } | 
| 752 | default: ShouldNotReachHere()do { (*g_assert_poison) = 'X';; report_should_not_reach_here( "/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiImpl.cpp" , 752); ::breakpoint(); } while (0); | 
| 753 | } | 
| 754 | } | 
| 755 | } | 
| 756 | } | 
| 757 | |
| 758 | |
| 759 | bool VM_GetOrSetLocal::allow_nested_vm_operations() const { | 
| 760 | return true; // May need to deoptimize | 
| 761 | } | 
| 762 | |
| 763 | |
| 764 | VM_GetReceiver::VM_GetReceiver( | 
| 765 | JavaThread* thread, JavaThread* caller_thread, jint depth) | 
| 766 | : VM_GetOrSetLocal(thread, caller_thread, depth, 0) {} | 
| 767 | |
| 768 | ///////////////////////////////////////////////////////////////////////////////////////// | 
| 769 | |
| 770 | // | 
| 771 | // class JvmtiSuspendControl - see comments in jvmtiImpl.hpp | 
| 772 | // | 
| 773 | |
| 774 | bool JvmtiSuspendControl::suspend(JavaThread *java_thread) { | 
| 775 | return java_thread->java_suspend(); | 
| 776 | } | 
| 777 | |
| 778 | bool JvmtiSuspendControl::resume(JavaThread *java_thread) { | 
| 779 | return java_thread->java_resume(); | 
| 780 | } | 
| 781 | |
| 782 | void JvmtiSuspendControl::print() { | 
| 783 | #ifndef PRODUCT | 
| 784 | ResourceMark rm; | 
| 785 | LogStreamHandle(Trace, jvmti)LogStreamTemplate<LogLevel::Trace, (LogTag::_jvmti), (LogTag ::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag:: __NO_TAG), (LogTag::__NO_TAG)> log_stream; | 
| 786 | log_stream.print("Suspended Threads: ["); | 
| 787 | for (JavaThreadIteratorWithHandle jtiwh; JavaThread *thread = jtiwh.next(); ) { | 
| 788 | #ifdef JVMTI_TRACE | 
| 789 | const char *name = JvmtiTrace::safe_get_thread_name(thread); | 
| 790 | #else | 
| 791 | const char *name = ""; | 
| 792 | #endif /*JVMTI_TRACE */ | 
| 793 | log_stream.print("%s(%c ", name, thread->is_suspended() ? 'S' : '_'); | 
| 794 | if (!thread->has_last_Java_frame()) { | 
| 795 | log_stream.print("no stack"); | 
| 796 | } | 
| 797 | log_stream.print(") "); | 
| 798 | } | 
| 799 | log_stream.print_cr("]"); | 
| 800 | #endif | 
| 801 | } | 
| 802 | |
| 803 | JvmtiDeferredEvent JvmtiDeferredEvent::compiled_method_load_event( | 
| 804 | nmethod* nm) { | 
| 805 | JvmtiDeferredEvent event = JvmtiDeferredEvent(TYPE_COMPILED_METHOD_LOAD); | 
| 806 | event._event_data.compiled_method_load = nm; | 
| 807 | return event; | 
| 808 | } | 
| 809 | |
| 810 | JvmtiDeferredEvent JvmtiDeferredEvent::compiled_method_unload_event( | 
| 811 | jmethodID id, const void* code) { | 
| 812 | JvmtiDeferredEvent event = JvmtiDeferredEvent(TYPE_COMPILED_METHOD_UNLOAD); | 
| 813 | event._event_data.compiled_method_unload.method_id = id; | 
| 814 | event._event_data.compiled_method_unload.code_begin = code; | 
| 815 | return event; | 
| 816 | } | 
| 817 | |
| 818 | JvmtiDeferredEvent JvmtiDeferredEvent::dynamic_code_generated_event( | 
| 819 | const char* name, const void* code_begin, const void* code_end) { | 
| 820 | JvmtiDeferredEvent event = JvmtiDeferredEvent(TYPE_DYNAMIC_CODE_GENERATED); | 
| 821 | // Need to make a copy of the name since we don't know how long | 
| 822 | // the event poster will keep it around after we enqueue the | 
| 823 | // deferred event and return. strdup() failure is handled in | 
| 824 | // the post() routine below. | 
| 825 | event._event_data.dynamic_code_generated.name = os::strdup(name); | 
| 826 | event._event_data.dynamic_code_generated.code_begin = code_begin; | 
| 827 | event._event_data.dynamic_code_generated.code_end = code_end; | 
| 828 | return event; | 
| 829 | } | 
| 830 | |
| 831 | JvmtiDeferredEvent JvmtiDeferredEvent::class_unload_event(const char* name) { | 
| 832 | JvmtiDeferredEvent event = JvmtiDeferredEvent(TYPE_CLASS_UNLOAD); | 
| 833 | // Need to make a copy of the name since we don't know how long | 
| 834 | // the event poster will keep it around after we enqueue the | 
| 835 | // deferred event and return. strdup() failure is handled in | 
| 836 | // the post() routine below. | 
| 837 | event._event_data.class_unload.name = os::strdup(name); | 
| 838 | return event; | 
| 839 | } | 
| 840 | |
| 841 | void JvmtiDeferredEvent::post() { | 
| 842 | assert(Thread::current()->is_service_thread(),do { if (!(Thread::current()->is_service_thread())) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiImpl.cpp" , 843, "assert(" "Thread::current()->is_service_thread()" ") failed" , "Service thread must post enqueued events"); ::breakpoint() ; } } while (0) | 
| 843 | "Service thread must post enqueued events")do { if (!(Thread::current()->is_service_thread())) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiImpl.cpp" , 843, "assert(" "Thread::current()->is_service_thread()" ") failed" , "Service thread must post enqueued events"); ::breakpoint() ; } } while (0); | 
| 844 | switch(_type) { | 
| 845 | case TYPE_COMPILED_METHOD_LOAD: { | 
| 846 | nmethod* nm = _event_data.compiled_method_load; | 
| 847 | JvmtiExport::post_compiled_method_load(nm); | 
| 848 | break; | 
| 849 | } | 
| 850 | case TYPE_COMPILED_METHOD_UNLOAD: { | 
| 851 | JvmtiExport::post_compiled_method_unload( | 
| 852 | _event_data.compiled_method_unload.method_id, | 
| 853 | _event_data.compiled_method_unload.code_begin); | 
| 854 | break; | 
| 855 | } | 
| 856 | case TYPE_DYNAMIC_CODE_GENERATED: { | 
| 857 | JvmtiExport::post_dynamic_code_generated_internal( | 
| 858 | // if strdup failed give the event a default name | 
| 859 | (_event_data.dynamic_code_generated.name == NULL__null) | 
| 860 | ? "unknown_code" : _event_data.dynamic_code_generated.name, | 
| 861 | _event_data.dynamic_code_generated.code_begin, | 
| 862 | _event_data.dynamic_code_generated.code_end); | 
| 863 | if (_event_data.dynamic_code_generated.name != NULL__null) { | 
| 864 | // release our copy | 
| 865 | os::free((void *)_event_data.dynamic_code_generated.name); | 
| 866 | } | 
| 867 | break; | 
| 868 | } | 
| 869 | case TYPE_CLASS_UNLOAD: { | 
| 870 | JvmtiExport::post_class_unload_internal( | 
| 871 | // if strdup failed give the event a default name | 
| 872 | (_event_data.class_unload.name == NULL__null) | 
| 873 | ? "unknown_class" : _event_data.class_unload.name); | 
| 874 | if (_event_data.class_unload.name != NULL__null) { | 
| 875 | // release our copy | 
| 876 | os::free((void *)_event_data.class_unload.name); | 
| 877 | } | 
| 878 | break; | 
| 879 | } | 
| 880 | default: | 
| 881 | ShouldNotReachHere()do { (*g_assert_poison) = 'X';; report_should_not_reach_here( "/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiImpl.cpp" , 881); ::breakpoint(); } while (0); | 
| 882 | } | 
| 883 | } | 
| 884 | |
| 885 | void JvmtiDeferredEvent::post_compiled_method_load_event(JvmtiEnv* env) { | 
| 886 | assert(_type == TYPE_COMPILED_METHOD_LOAD, "only user of this method")do { if (!(_type == TYPE_COMPILED_METHOD_LOAD)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiImpl.cpp" , 886, "assert(" "_type == TYPE_COMPILED_METHOD_LOAD" ") failed" , "only user of this method"); ::breakpoint(); } } while (0); | 
| 887 | nmethod* nm = _event_data.compiled_method_load; | 
| 888 | JvmtiExport::post_compiled_method_load(env, nm); | 
| 889 | } | 
| 890 | |
| 891 | void JvmtiDeferredEvent::run_nmethod_entry_barriers() { | 
| 892 | if (_type == TYPE_COMPILED_METHOD_LOAD) { | 
| 893 | _event_data.compiled_method_load->run_nmethod_entry_barrier(); | 
| 894 | } | 
| 895 | } | 
| 896 | |
| 897 | |
| 898 | // Keep the nmethod for compiled_method_load from being unloaded. | 
| 899 | void JvmtiDeferredEvent::oops_do(OopClosure* f, CodeBlobClosure* cf) { | 
| 900 | if (cf != NULL__null && _type == TYPE_COMPILED_METHOD_LOAD) { | 
| 901 | cf->do_code_blob(_event_data.compiled_method_load); | 
| 902 | } | 
| 903 | } | 
| 904 | |
| 905 | // The sweeper calls this and marks the nmethods here on the stack so that | 
| 906 | // they cannot be turned into zombies while in the queue. | 
| 907 | void JvmtiDeferredEvent::nmethods_do(CodeBlobClosure* cf) { | 
| 908 | if (cf != NULL__null && _type == TYPE_COMPILED_METHOD_LOAD) { | 
| 909 | cf->do_code_blob(_event_data.compiled_method_load); | 
| 910 | } | 
| 911 | } | 
| 912 | |
| 913 | |
| 914 | bool JvmtiDeferredEventQueue::has_events() { | 
| 915 | // We save the queued events before the live phase and post them when it starts. | 
| 916 | // This code could skip saving the events on the queue before the live | 
| 917 | // phase and ignore them, but this would change how we do things now. | 
| 918 | // Starting the service thread earlier causes this to be called before the live phase begins. | 
| 919 | // The events on the queue should all be posted after the live phase so this is an | 
| 920 | // ok check. Before the live phase, DynamicCodeGenerated events are posted directly. | 
| 921 | // If we add other types of events to the deferred queue, this could get ugly. | 
| 922 | return JvmtiEnvBase::get_phase() == JVMTI_PHASE_LIVE && _queue_head != NULL__null; | 
| 923 | } | 
| 924 | |
| 925 | void JvmtiDeferredEventQueue::enqueue(JvmtiDeferredEvent event) { | 
| 926 | // Events get added to the end of the queue (and are pulled off the front). | 
| 927 | QueueNode* node = new QueueNode(event); | 
| 928 | if (_queue_tail == NULL__null) { | 
| 929 | _queue_tail = _queue_head = node; | 
| 930 | } else { | 
| 931 | assert(_queue_tail->next() == NULL, "Must be the last element in the list")do { if (!(_queue_tail->next() == __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiImpl.cpp" , 931, "assert(" "_queue_tail->next() == __null" ") failed" , "Must be the last element in the list"); ::breakpoint(); } } while (0); | 
| 932 | _queue_tail->set_next(node); | 
| 933 | _queue_tail = node; | 
| 934 | } | 
| 935 | |
| 936 | assert((_queue_head == NULL) == (_queue_tail == NULL),do { if (!((_queue_head == __null) == (_queue_tail == __null) )) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiImpl.cpp" , 937, "assert(" "(_queue_head == __null) == (_queue_tail == __null)" ") failed", "Inconsistent queue markers"); ::breakpoint(); } } while (0) | 
| 937 | "Inconsistent queue markers")do { if (!((_queue_head == __null) == (_queue_tail == __null) )) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiImpl.cpp" , 937, "assert(" "(_queue_head == __null) == (_queue_tail == __null)" ") failed", "Inconsistent queue markers"); ::breakpoint(); } } while (0); | 
| 938 | } | 
| 939 | |
| 940 | JvmtiDeferredEvent JvmtiDeferredEventQueue::dequeue() { | 
| 941 | assert(_queue_head != NULL, "Nothing to dequeue")do { if (!(_queue_head != __null)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiImpl.cpp" , 941, "assert(" "_queue_head != __null" ") failed", "Nothing to dequeue" ); ::breakpoint(); } } while (0); | 
| 942 | |
| 943 | if (_queue_head == NULL__null) { | 
| 944 | // Just in case this happens in product; it shouldn't but let's not crash | 
| 945 | return JvmtiDeferredEvent(); | 
| 946 | } | 
| 947 | |
| 948 | QueueNode* node = _queue_head; | 
| 949 | _queue_head = _queue_head->next(); | 
| 950 | if (_queue_head == NULL__null) { | 
| 951 | _queue_tail = NULL__null; | 
| 952 | } | 
| 953 | |
| 954 | assert((_queue_head == NULL) == (_queue_tail == NULL),do { if (!((_queue_head == __null) == (_queue_tail == __null) )) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiImpl.cpp" , 955, "assert(" "(_queue_head == __null) == (_queue_tail == __null)" ") failed", "Inconsistent queue markers"); ::breakpoint(); } } while (0) | 
| 955 | "Inconsistent queue markers")do { if (!((_queue_head == __null) == (_queue_tail == __null) )) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiImpl.cpp" , 955, "assert(" "(_queue_head == __null) == (_queue_tail == __null)" ") failed", "Inconsistent queue markers"); ::breakpoint(); } } while (0); | 
| 956 | |
| 957 | JvmtiDeferredEvent event = node->event(); | 
| 958 | delete node; | 
| 959 | return event; | 
| 960 | } | 
| 961 | |
| 962 | void JvmtiDeferredEventQueue::post(JvmtiEnv* env) { | 
| 963 | // Post events while nmethods are still in the queue and can't be unloaded or made zombie | 
| 964 | while (_queue_head != NULL__null) { | 
| 965 | _queue_head->event().post_compiled_method_load_event(env); | 
| 966 | dequeue(); | 
| 967 | } | 
| 968 | } | 
| 969 | |
| 970 | void JvmtiDeferredEventQueue::run_nmethod_entry_barriers() { | 
| 971 | for(QueueNode* node = _queue_head; node != NULL__null; node = node->next()) { | 
| 972 | node->event().run_nmethod_entry_barriers(); | 
| 973 | } | 
| 974 | } | 
| 975 | |
| 976 | |
| 977 | void JvmtiDeferredEventQueue::oops_do(OopClosure* f, CodeBlobClosure* cf) { | 
| 978 | for(QueueNode* node = _queue_head; node != NULL__null; node = node->next()) { | 
| 979 | node->event().oops_do(f, cf); | 
| 980 | } | 
| 981 | } | 
| 982 | |
| 983 | void JvmtiDeferredEventQueue::nmethods_do(CodeBlobClosure* cf) { | 
| 984 | for(QueueNode* node = _queue_head; node != NULL__null; node = node->next()) { | 
| 985 | node->event().nmethods_do(cf); | 
| 986 | } | 
| 987 | } |