Bug Summary

File:jdk/src/hotspot/share/prims/jvmtiImpl.cpp
Warning:line 231, column 11
Value stored to 'thread' during its initialization is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name jvmtiImpl.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mthread-model posix -fno-delete-null-pointer-checks -mframe-pointer=all -relaxed-aliasing -fmath-errno -fno-rounding-math -masm-verbose -mconstructor-aliases -munwind-tables -target-cpu x86-64 -dwarf-column-info -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib/llvm-10/lib/clang/10.0.0 -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/hotspot/variant-server/libjvm/objs/precompiled -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -D __STDC_CONSTANT_MACROS -D _GNU_SOURCE -D _REENTRANT -D LIBC=gnu -D LINUX -D VM_LITTLE_ENDIAN -D _LP64=1 -D ASSERT -D CHECK_UNHANDLED_OOPS -D TARGET_ARCH_x86 -D INCLUDE_SUFFIX_OS=_linux -D INCLUDE_SUFFIX_CPU=_x86 -D INCLUDE_SUFFIX_COMPILER=_gcc -D TARGET_COMPILER_gcc -D AMD64 -D HOTSPOT_LIB_ARCH="amd64" -D COMPILER1 -D COMPILER2 -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/hotspot/variant-server/gensrc/adfiles -I /home/daniel/Projects/java/jdk/src/hotspot/share -I /home/daniel/Projects/java/jdk/src/hotspot/os/linux -I /home/daniel/Projects/java/jdk/src/hotspot/os/posix -I /home/daniel/Projects/java/jdk/src/hotspot/cpu/x86 -I /home/daniel/Projects/java/jdk/src/hotspot/os_cpu/linux_x86 -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/hotspot/variant-server/gensrc -I /home/daniel/Projects/java/jdk/src/hotspot/share/precompiled -I /home/daniel/Projects/java/jdk/src/hotspot/share/include -I /home/daniel/Projects/java/jdk/src/hotspot/os/posix/include -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/support/modules_include/java.base -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/support/modules_include/java.base/linux -I /home/daniel/Projects/java/jdk/src/java.base/share/native/libjimage -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/hotspot/variant-server/gensrc/adfiles -I /home/daniel/Projects/java/jdk/src/hotspot/share -I /home/daniel/Projects/java/jdk/src/hotspot/os/linux -I /home/daniel/Projects/java/jdk/src/hotspot/os/posix -I /home/daniel/Projects/java/jdk/src/hotspot/cpu/x86 -I /home/daniel/Projects/java/jdk/src/hotspot/os_cpu/linux_x86 -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/hotspot/variant-server/gensrc -D _FORTIFY_SOURCE=2 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../../include/c++/7.5.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../../include/x86_64-linux-gnu/c++/7.5.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../../include/x86_64-linux-gnu/c++/7.5.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../../include/c++/7.5.0/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-10/lib/clang/10.0.0/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O3 -Wno-format-zero-length -Wno-unused-parameter -Wno-unused -Wno-parentheses -Wno-comment -Wno-unknown-pragmas -Wno-address -Wno-delete-non-virtual-dtor -Wno-char-subscripts -Wno-array-bounds -Wno-int-in-bool-context -Wno-ignored-qualifiers -Wno-missing-field-initializers -Wno-implicit-fallthrough -Wno-empty-body -Wno-strict-overflow -Wno-sequence-point -Wno-maybe-uninitialized -Wno-misleading-indentation -Wno-cast-function-type -Wno-shift-negative-value -std=c++14 -fdeprecated-macro -fdebug-compilation-dir /home/daniel/Projects/java/jdk/make/hotspot -ferror-limit 19 -fmessage-length 0 -fvisibility hidden -stack-protector 1 -fno-rtti -fgnuc-version=4.2.1 -fobjc-runtime=gcc -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -o /home/daniel/Projects/java/scan/2021-12-21-193737-8510-1 -x c++ /home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiImpl.cpp
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
67JvmtiAgentThread::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
74void
75JvmtiAgentThread::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
85void
86JvmtiAgentThread::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
96void 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
121bool 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
133GrowableCache::GrowableCache() {
134 _this_obj = NULL__null;
135 _listener_fun = NULL__null;
136 _elements = NULL__null;
137 _cache = NULL__null;
138}
139
140GrowableCache::~GrowableCache() {
141 clear();
142 delete _elements;
143 FREE_C_HEAP_ARRAY(address, _cache)FreeHeap((char*)(_cache));
144}
145
146void 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
154int GrowableCache::length() {
155 return _elements->length();
156}
157
158// get the value of the index element in the collection
159GrowableElement* 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
165int 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
170void 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
177void 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.
187void 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
200JvmtiBreakpoint::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
208JvmtiBreakpoint::~JvmtiBreakpoint() {
209 _class_holder.release(JvmtiExport::jvmti_oop_storage());
210}
211
212void 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
218bool JvmtiBreakpoint::equals(JvmtiBreakpoint& bp) {
219 return _method == bp._method
220 && _bci == bp._bci;
221}
222
223address JvmtiBreakpoint::getBcp() const {
224 return _method->bcp_from(_bci);
225}
226
227void 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
268void JvmtiBreakpoint::set() {
269 each_method_version_do(&Method::set_breakpoint);
270}
271
272void JvmtiBreakpoint::clear() {
273 each_method_version_do(&Method::clear_breakpoint);
274}
275
276void 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
292void 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
311JvmtiBreakpoints::JvmtiBreakpoints(void listener_fun(void *,address *)) {
312 _bps.initialize(this,listener_fun);
313}
314
315JvmtiBreakpoints:: ~JvmtiBreakpoints() {}
316
317void 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
333void 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
343void 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
353int JvmtiBreakpoints::length() { return _bps.length(); }
354
355int 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
364int 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
374void 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
404JvmtiBreakpoints *JvmtiCurrentBreakpoints::_jvmti_breakpoints = NULL__null;
405address * JvmtiCurrentBreakpoints::_breakpoint_list = NULL__null;
406
407
408JvmtiBreakpoints& 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
415void 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
431VM_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
445VM_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
460VM_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
473vframe *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(&reg_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
487javaVFrame *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.
507bool 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
545bool 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
608bool 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
637static bool can_be_deoptimized(vframe* vf) {
638 return (vf->is_compiled_frame() && vf->fr().can_be_deoptimized());
639}
640
641bool 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
651void 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
759bool VM_GetOrSetLocal::allow_nested_vm_operations() const {
760 return true; // May need to deoptimize
761}
762
763
764VM_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
774bool JvmtiSuspendControl::suspend(JavaThread *java_thread) {
775 return java_thread->java_suspend();
776}
777
778bool JvmtiSuspendControl::resume(JavaThread *java_thread) {
779 return java_thread->java_resume();
780}
781
782void 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
803JvmtiDeferredEvent 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
810JvmtiDeferredEvent 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
818JvmtiDeferredEvent 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
831JvmtiDeferredEvent 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
841void 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
885void 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
891void 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.
899void 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.
907void 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
914bool 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
925void 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
940JvmtiDeferredEvent 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
962void 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
970void 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
977void 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
983void 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}