1/*
2 * Copyright (c) 2012, 2019, 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
27#include <new>
28
29#include "classfile/classLoaderDataGraph.hpp"
30#include "classfile/modules.hpp"
31#include "classfile/protectionDomainCache.hpp"
32#include "classfile/stringTable.hpp"
33#include "classfile/symbolTable.hpp"
34#include "code/codeCache.hpp"
35#include "compiler/methodMatcher.hpp"
36#include "compiler/directivesParser.hpp"
37#include "gc/shared/gcConfig.hpp"
38#include "gc/shared/genArguments.hpp"
39#include "gc/shared/genCollectedHeap.hpp"
40#include "jvmtifiles/jvmtiEnv.hpp"
41#include "memory/filemap.hpp"
42#include "memory/heapShared.inline.hpp"
43#include "memory/metaspaceShared.hpp"
44#include "memory/metadataFactory.hpp"
45#include "memory/iterator.hpp"
46#include "memory/resourceArea.hpp"
47#include "memory/universe.hpp"
48#include "memory/oopFactory.hpp"
49#include "oops/array.hpp"
50#include "oops/compressedOops.hpp"
51#include "oops/constantPool.inline.hpp"
52#include "oops/method.inline.hpp"
53#include "oops/objArrayKlass.hpp"
54#include "oops/objArrayOop.inline.hpp"
55#include "oops/oop.inline.hpp"
56#include "oops/typeArrayOop.inline.hpp"
57#include "prims/resolvedMethodTable.hpp"
58#include "prims/wbtestmethods/parserTests.hpp"
59#include "prims/whitebox.inline.hpp"
60#include "runtime/arguments.hpp"
61#include "runtime/compilationPolicy.hpp"
62#include "runtime/deoptimization.hpp"
63#include "runtime/fieldDescriptor.inline.hpp"
64#include "runtime/flags/jvmFlag.hpp"
65#include "runtime/frame.inline.hpp"
66#include "runtime/handles.inline.hpp"
67#include "runtime/handshake.hpp"
68#include "runtime/interfaceSupport.inline.hpp"
69#include "runtime/javaCalls.hpp"
70#include "runtime/jniHandles.inline.hpp"
71#include "runtime/os.hpp"
72#include "runtime/sweeper.hpp"
73#include "runtime/thread.hpp"
74#include "runtime/threadSMR.hpp"
75#include "runtime/vm_version.hpp"
76#include "services/memoryService.hpp"
77#include "utilities/align.hpp"
78#include "utilities/debug.hpp"
79#include "utilities/elfFile.hpp"
80#include "utilities/exceptions.hpp"
81#include "utilities/macros.hpp"
82#if INCLUDE_CDS
83#include "prims/cdsoffsets.hpp"
84#endif // INCLUDE_CDS
85#if INCLUDE_G1GC
86#include "gc/g1/g1Arguments.hpp"
87#include "gc/g1/g1CollectedHeap.inline.hpp"
88#include "gc/g1/g1ConcurrentMark.hpp"
89#include "gc/g1/g1ConcurrentMarkThread.hpp"
90#include "gc/g1/heapRegionRemSet.hpp"
91#include "gc/g1/heterogeneousHeapRegionManager.hpp"
92#endif // INCLUDE_G1GC
93#if INCLUDE_PARALLELGC
94#include "gc/parallel/parallelScavengeHeap.inline.hpp"
95#include "gc/parallel/adjoiningGenerations.hpp"
96#endif // INCLUDE_PARALLELGC
97#if INCLUDE_NMT
98#include "services/mallocSiteTable.hpp"
99#include "services/memTracker.hpp"
100#include "utilities/nativeCallStack.hpp"
101#endif // INCLUDE_NMT
102#if INCLUDE_AOT
103#include "aot/aotLoader.hpp"
104#endif // INCLUDE_AOT
105
106#ifdef LINUX
107#include "osContainer_linux.hpp"
108#endif
109
110#define SIZE_T_MAX_VALUE ((size_t) -1)
111
112#define CHECK_JNI_EXCEPTION_(env, value) \
113 do { \
114 JavaThread* THREAD = JavaThread::thread_from_jni_environment(env); \
115 THREAD->clear_pending_jni_exception_check(); \
116 if (HAS_PENDING_EXCEPTION) { \
117 return(value); \
118 } \
119 } while (0)
120
121#define CHECK_JNI_EXCEPTION(env) \
122 do { \
123 JavaThread* THREAD = JavaThread::thread_from_jni_environment(env); \
124 THREAD->clear_pending_jni_exception_check(); \
125 if (HAS_PENDING_EXCEPTION) { \
126 return; \
127 } \
128 } while (0)
129
130bool WhiteBox::_used = false;
131volatile bool WhiteBox::compilation_locked = false;
132
133class VM_WhiteBoxOperation : public VM_Operation {
134 public:
135 VM_WhiteBoxOperation() { }
136 VMOp_Type type() const { return VMOp_WhiteBoxOperation; }
137 bool allow_nested_vm_operations() const { return true; }
138};
139
140
141WB_ENTRY(jlong, WB_GetObjectAddress(JNIEnv* env, jobject o, jobject obj))
142 return (jlong)(void*)JNIHandles::resolve(obj);
143WB_END
144
145WB_ENTRY(jint, WB_GetHeapOopSize(JNIEnv* env, jobject o))
146 return heapOopSize;
147WB_END
148
149WB_ENTRY(jint, WB_GetVMPageSize(JNIEnv* env, jobject o))
150 return os::vm_page_size();
151WB_END
152
153WB_ENTRY(jlong, WB_GetVMAllocationGranularity(JNIEnv* env, jobject o))
154 return os::vm_allocation_granularity();
155WB_END
156
157WB_ENTRY(jlong, WB_GetVMLargePageSize(JNIEnv* env, jobject o))
158 return os::large_page_size();
159WB_END
160
161class WBIsKlassAliveClosure : public LockedClassesDo {
162 Symbol* _name;
163 bool _found;
164public:
165 WBIsKlassAliveClosure(Symbol* name) : _name(name), _found(false) {}
166
167 void do_klass(Klass* k) {
168 if (_found) return;
169 Symbol* ksym = k->name();
170 if (ksym->fast_compare(_name) == 0) {
171 _found = true;
172 }
173 }
174
175 bool found() const {
176 return _found;
177 }
178};
179
180WB_ENTRY(jboolean, WB_IsClassAlive(JNIEnv* env, jobject target, jstring name))
181 oop h_name = JNIHandles::resolve(name);
182 if (h_name == NULL) return false;
183 Symbol* sym = java_lang_String::as_symbol(h_name);
184 TempNewSymbol tsym(sym); // Make sure to decrement reference count on sym on return
185
186 WBIsKlassAliveClosure closure(sym);
187 ClassLoaderDataGraph::classes_do(&closure);
188
189 return closure.found();
190WB_END
191
192WB_ENTRY(jint, WB_GetSymbolRefcount(JNIEnv* env, jobject unused, jstring name))
193 oop h_name = JNIHandles::resolve(name);
194 if (h_name == NULL) return false;
195 Symbol* sym = java_lang_String::as_symbol(h_name);
196 TempNewSymbol tsym(sym); // Make sure to decrement reference count on sym on return
197 return (jint)sym->refcount();
198WB_END
199
200
201WB_ENTRY(void, WB_AddToBootstrapClassLoaderSearch(JNIEnv* env, jobject o, jstring segment)) {
202#if INCLUDE_JVMTI
203 ResourceMark rm;
204 const char* seg = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(segment));
205 JvmtiEnv* jvmti_env = JvmtiEnv::create_a_jvmti(JVMTI_VERSION);
206 jvmtiError err = jvmti_env->AddToBootstrapClassLoaderSearch(seg);
207 assert(err == JVMTI_ERROR_NONE, "must not fail");
208#endif
209}
210WB_END
211
212WB_ENTRY(void, WB_AddToSystemClassLoaderSearch(JNIEnv* env, jobject o, jstring segment)) {
213#if INCLUDE_JVMTI
214 ResourceMark rm;
215 const char* seg = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(segment));
216 JvmtiEnv* jvmti_env = JvmtiEnv::create_a_jvmti(JVMTI_VERSION);
217 jvmtiError err = jvmti_env->AddToSystemClassLoaderSearch(seg);
218 assert(err == JVMTI_ERROR_NONE, "must not fail");
219#endif
220}
221WB_END
222
223
224WB_ENTRY(jlong, WB_GetCompressedOopsMaxHeapSize(JNIEnv* env, jobject o)) {
225 return (jlong)Arguments::max_heap_for_compressed_oops();
226}
227WB_END
228
229WB_ENTRY(void, WB_PrintHeapSizes(JNIEnv* env, jobject o)) {
230 tty->print_cr("Minimum heap " SIZE_FORMAT " Initial heap " SIZE_FORMAT " "
231 "Maximum heap " SIZE_FORMAT " Space alignment " SIZE_FORMAT " Heap alignment " SIZE_FORMAT,
232 MinHeapSize,
233 InitialHeapSize,
234 MaxHeapSize,
235 SpaceAlignment,
236 HeapAlignment);
237}
238WB_END
239
240#ifndef PRODUCT
241// Forward declaration
242void TestReservedSpace_test();
243void TestReserveMemorySpecial_test();
244void TestVirtualSpace_test();
245void TestMetaspaceUtils_test();
246#endif
247
248WB_ENTRY(void, WB_RunMemoryUnitTests(JNIEnv* env, jobject o))
249#ifndef PRODUCT
250 TestReservedSpace_test();
251 TestReserveMemorySpecial_test();
252 TestVirtualSpace_test();
253 TestMetaspaceUtils_test();
254#endif
255WB_END
256
257WB_ENTRY(void, WB_ReadFromNoaccessArea(JNIEnv* env, jobject o))
258 size_t granularity = os::vm_allocation_granularity();
259 ReservedHeapSpace rhs(100 * granularity, granularity, false);
260 VirtualSpace vs;
261 vs.initialize(rhs, 50 * granularity);
262
263 // Check if constraints are complied
264 if (!( UseCompressedOops && rhs.base() != NULL &&
265 CompressedOops::base() != NULL &&
266 CompressedOops::use_implicit_null_checks() )) {
267 tty->print_cr("WB_ReadFromNoaccessArea method is useless:\n "
268 "\tUseCompressedOops is %d\n"
269 "\trhs.base() is " PTR_FORMAT "\n"
270 "\tCompressedOops::base() is " PTR_FORMAT "\n"
271 "\tCompressedOops::use_implicit_null_checks() is %d",
272 UseCompressedOops,
273 p2i(rhs.base()),
274 p2i(CompressedOops::base()),
275 CompressedOops::use_implicit_null_checks());
276 return;
277 }
278 tty->print_cr("Reading from no access area... ");
279 tty->print_cr("*(vs.low_boundary() - rhs.noaccess_prefix() / 2 ) = %c",
280 *(vs.low_boundary() - rhs.noaccess_prefix() / 2 ));
281WB_END
282
283static jint wb_stress_virtual_space_resize(size_t reserved_space_size,
284 size_t magnitude, size_t iterations) {
285 size_t granularity = os::vm_allocation_granularity();
286 ReservedHeapSpace rhs(reserved_space_size * granularity, granularity, false);
287 VirtualSpace vs;
288 if (!vs.initialize(rhs, 0)) {
289 tty->print_cr("Failed to initialize VirtualSpace. Can't proceed.");
290 return 3;
291 }
292
293 int seed = os::random();
294 tty->print_cr("Random seed is %d", seed);
295 os::init_random(seed);
296
297 for (size_t i = 0; i < iterations; i++) {
298
299 // Whether we will shrink or grow
300 bool shrink = os::random() % 2L == 0;
301
302 // Get random delta to resize virtual space
303 size_t delta = (size_t)os::random() % magnitude;
304
305 // If we are about to shrink virtual space below zero, then expand instead
306 if (shrink && vs.committed_size() < delta) {
307 shrink = false;
308 }
309
310 // Resizing by delta
311 if (shrink) {
312 vs.shrink_by(delta);
313 } else {
314 // If expanding fails expand_by will silently return false
315 vs.expand_by(delta, true);
316 }
317 }
318 return 0;
319}
320
321WB_ENTRY(jint, WB_StressVirtualSpaceResize(JNIEnv* env, jobject o,
322 jlong reserved_space_size, jlong magnitude, jlong iterations))
323 tty->print_cr("reservedSpaceSize=" JLONG_FORMAT ", magnitude=" JLONG_FORMAT ", "
324 "iterations=" JLONG_FORMAT "\n", reserved_space_size, magnitude,
325 iterations);
326 if (reserved_space_size < 0 || magnitude < 0 || iterations < 0) {
327 tty->print_cr("One of variables printed above is negative. Can't proceed.\n");
328 return 1;
329 }
330
331 // sizeof(size_t) depends on whether OS is 32bit or 64bit. sizeof(jlong) is
332 // always 8 byte. That's why we should avoid overflow in case of 32bit platform.
333 if (sizeof(size_t) < sizeof(jlong)) {
334 jlong size_t_max_value = (jlong) SIZE_T_MAX_VALUE;
335 if (reserved_space_size > size_t_max_value || magnitude > size_t_max_value
336 || iterations > size_t_max_value) {
337 tty->print_cr("One of variables printed above overflows size_t. Can't proceed.\n");
338 return 2;
339 }
340 }
341
342 return wb_stress_virtual_space_resize((size_t) reserved_space_size,
343 (size_t) magnitude, (size_t) iterations);
344WB_END
345
346WB_ENTRY(jboolean, WB_IsGCSupported(JNIEnv* env, jobject o, jint name))
347 return GCConfig::is_gc_supported((CollectedHeap::Name)name);
348WB_END
349
350WB_ENTRY(jboolean, WB_IsGCSelected(JNIEnv* env, jobject o, jint name))
351 return GCConfig::is_gc_selected((CollectedHeap::Name)name);
352WB_END
353
354WB_ENTRY(jboolean, WB_IsGCSelectedErgonomically(JNIEnv* env, jobject o))
355 return GCConfig::is_gc_selected_ergonomically();
356WB_END
357
358WB_ENTRY(jboolean, WB_isObjectInOldGen(JNIEnv* env, jobject o, jobject obj))
359 oop p = JNIHandles::resolve(obj);
360#if INCLUDE_G1GC
361 if (UseG1GC) {
362 G1CollectedHeap* g1h = G1CollectedHeap::heap();
363 const HeapRegion* hr = g1h->heap_region_containing(p);
364 if (hr == NULL) {
365 return false;
366 }
367 return !(hr->is_young());
368 }
369#endif
370#if INCLUDE_PARALLELGC
371 if (UseParallelGC) {
372 ParallelScavengeHeap* psh = ParallelScavengeHeap::heap();
373 return !psh->is_in_young(p);
374 }
375#endif
376#if INCLUDE_ZGC
377 if (UseZGC) {
378 return Universe::heap()->is_in(p);
379 }
380#endif
381 GenCollectedHeap* gch = GenCollectedHeap::heap();
382 return !gch->is_in_young(p);
383WB_END
384
385WB_ENTRY(jlong, WB_GetObjectSize(JNIEnv* env, jobject o, jobject obj))
386 oop p = JNIHandles::resolve(obj);
387 return Universe::heap()->obj_size(p) * HeapWordSize;
388WB_END
389
390WB_ENTRY(jlong, WB_GetHeapSpaceAlignment(JNIEnv* env, jobject o))
391 return (jlong)SpaceAlignment;
392WB_END
393
394WB_ENTRY(jlong, WB_GetHeapAlignment(JNIEnv* env, jobject o))
395 return (jlong)HeapAlignment;
396WB_END
397
398WB_ENTRY(jboolean, WB_SupportsConcurrentGCPhaseControl(JNIEnv* env, jobject o))
399 return Universe::heap()->supports_concurrent_phase_control();
400WB_END
401
402WB_ENTRY(jboolean, WB_RequestConcurrentGCPhase(JNIEnv* env, jobject o, jstring name))
403 Handle h_name(THREAD, JNIHandles::resolve(name));
404 ResourceMark rm;
405 const char* c_name = java_lang_String::as_utf8_string(h_name());
406 return Universe::heap()->request_concurrent_phase(c_name);
407WB_END
408
409#if INCLUDE_G1GC
410
411WB_ENTRY(jboolean, WB_G1IsHumongous(JNIEnv* env, jobject o, jobject obj))
412 if (UseG1GC) {
413 G1CollectedHeap* g1h = G1CollectedHeap::heap();
414 oop result = JNIHandles::resolve(obj);
415 const HeapRegion* hr = g1h->heap_region_containing(result);
416 return hr->is_humongous();
417 }
418 THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_G1IsHumongous: G1 GC is not enabled");
419WB_END
420
421WB_ENTRY(jboolean, WB_G1BelongsToHumongousRegion(JNIEnv* env, jobject o, jlong addr))
422 if (UseG1GC) {
423 G1CollectedHeap* g1h = G1CollectedHeap::heap();
424 const HeapRegion* hr = g1h->heap_region_containing((void*) addr);
425 return hr->is_humongous();
426 }
427 THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_G1BelongsToHumongousRegion: G1 GC is not enabled");
428WB_END
429
430WB_ENTRY(jboolean, WB_G1BelongsToFreeRegion(JNIEnv* env, jobject o, jlong addr))
431 if (UseG1GC) {
432 G1CollectedHeap* g1h = G1CollectedHeap::heap();
433 const HeapRegion* hr = g1h->heap_region_containing((void*) addr);
434 return hr->is_free();
435 }
436 THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_G1BelongsToFreeRegion: G1 GC is not enabled");
437WB_END
438
439WB_ENTRY(jlong, WB_G1NumMaxRegions(JNIEnv* env, jobject o))
440 if (UseG1GC) {
441 G1CollectedHeap* g1h = G1CollectedHeap::heap();
442 size_t nr = g1h->max_regions();
443 return (jlong)nr;
444 }
445 THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_G1NumMaxRegions: G1 GC is not enabled");
446WB_END
447
448WB_ENTRY(jlong, WB_G1NumFreeRegions(JNIEnv* env, jobject o))
449 if (UseG1GC) {
450 G1CollectedHeap* g1h = G1CollectedHeap::heap();
451 size_t nr = g1h->num_free_regions();
452 return (jlong)nr;
453 }
454 THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_G1NumFreeRegions: G1 GC is not enabled");
455WB_END
456
457WB_ENTRY(jboolean, WB_G1InConcurrentMark(JNIEnv* env, jobject o))
458 if (UseG1GC) {
459 G1CollectedHeap* g1h = G1CollectedHeap::heap();
460 return g1h->concurrent_mark()->cm_thread()->during_cycle();
461 }
462 THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_G1InConcurrentMark: G1 GC is not enabled");
463WB_END
464
465WB_ENTRY(jboolean, WB_G1StartMarkCycle(JNIEnv* env, jobject o))
466 if (UseG1GC) {
467 G1CollectedHeap* g1h = G1CollectedHeap::heap();
468 if (!g1h->concurrent_mark()->cm_thread()->during_cycle()) {
469 g1h->collect(GCCause::_wb_conc_mark);
470 return true;
471 }
472 return false;
473 }
474 THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_G1StartMarkCycle: G1 GC is not enabled");
475WB_END
476
477WB_ENTRY(jint, WB_G1RegionSize(JNIEnv* env, jobject o))
478 if (UseG1GC) {
479 return (jint)HeapRegion::GrainBytes;
480 }
481 THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_G1RegionSize: G1 GC is not enabled");
482WB_END
483
484#endif // INCLUDE_G1GC
485
486#if INCLUDE_G1GC || INCLUDE_PARALLELGC
487WB_ENTRY(jlong, WB_DramReservedStart(JNIEnv* env, jobject o))
488#if INCLUDE_G1GC
489 if (UseG1GC) {
490 G1CollectedHeap* g1h = G1CollectedHeap::heap();
491 if (g1h->is_heterogeneous_heap()) {
492 uint start_region = HeterogeneousHeapRegionManager::manager()->start_index_of_dram();
493 return (jlong)(g1h->base() + start_region * HeapRegion::GrainBytes);
494 } else {
495 return (jlong)g1h->base();
496 }
497 }
498#endif // INCLUDE_G1GC
499#if INCLUDE_PARALLELGC
500 if (UseParallelGC) {
501 ParallelScavengeHeap* ps_heap = ParallelScavengeHeap::heap();
502 if (AllocateOldGenAt != NULL) {
503 MemRegion reserved = ps_heap->young_gen()->reserved();
504 return (jlong)reserved.start();
505 } else {
506 return (jlong)ps_heap->base();
507 }
508 }
509#endif // INCLUDE_PARALLELGC
510 THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_DramReservedStart: enabled only for G1 and Parallel GC");
511WB_END
512
513WB_ENTRY(jlong, WB_DramReservedEnd(JNIEnv* env, jobject o))
514#if INCLUDE_G1GC
515 if (UseG1GC) {
516 G1CollectedHeap* g1h = G1CollectedHeap::heap();
517 if (g1h->is_heterogeneous_heap()) {
518 uint end_region = HeterogeneousHeapRegionManager::manager()->end_index_of_dram();
519 return (jlong)(g1h->base() + (end_region + 1) * HeapRegion::GrainBytes - 1);
520 } else {
521 return (jlong)g1h->base() + G1Arguments::heap_max_size_bytes();
522 }
523 }
524#endif // INCLUDE_G1GC
525#if INCLUDE_PARALLELGC
526 if (UseParallelGC) {
527 ParallelScavengeHeap* ps_heap = ParallelScavengeHeap::heap();
528 if (AllocateOldGenAt != NULL) {
529 MemRegion reserved = ps_heap->young_gen()->reserved();
530 return (jlong)reserved.end();
531 } else {
532 return (jlong)ps_heap->reserved_region().end();
533 }
534 }
535#endif // INCLUDE_PARALLELGC
536 THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_DramReservedEnd: enabled only for G1 and Parallel GC");
537WB_END
538
539WB_ENTRY(jlong, WB_NvdimmReservedStart(JNIEnv* env, jobject o))
540#if INCLUDE_G1GC
541 if (UseG1GC) {
542 G1CollectedHeap* g1h = G1CollectedHeap::heap();
543 if (g1h->is_heterogeneous_heap()) {
544 uint start_region = HeterogeneousHeapRegionManager::manager()->start_index_of_nvdimm();
545 return (jlong)(g1h->base() + start_region * HeapRegion::GrainBytes);
546 } else {
547 THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_NvdimmReservedStart: Old gen is not allocated on NV-DIMM using AllocateOldGenAt flag");
548 }
549 }
550#endif // INCLUDE_G1GC
551#if INCLUDE_PARALLELGC
552 if (UseParallelGC) {
553 ParallelScavengeHeap* ps_heap = ParallelScavengeHeap::heap();
554 if (AllocateOldGenAt != NULL) {
555 MemRegion reserved = ps_heap->old_gen()->reserved();
556 return (jlong)reserved.start();
557 } else {
558 THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_NvdimmReservedStart: Old gen is not allocated on NV-DIMM using AllocateOldGenAt flag");
559 }
560 }
561#endif // INCLUDE_PARALLELGC
562 THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_NvdimmReservedStart: enabled only for G1 and Parallel GC");
563WB_END
564
565WB_ENTRY(jlong, WB_NvdimmReservedEnd(JNIEnv* env, jobject o))
566#if INCLUDE_G1GC
567 if (UseG1GC) {
568 G1CollectedHeap* g1h = G1CollectedHeap::heap();
569 if (g1h->is_heterogeneous_heap()) {
570 uint end_region = HeterogeneousHeapRegionManager::manager()->start_index_of_nvdimm();
571 return (jlong)(g1h->base() + (end_region + 1) * HeapRegion::GrainBytes - 1);
572 } else {
573 THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_NvdimmReservedEnd: Old gen is not allocated on NV-DIMM using AllocateOldGenAt flag");
574 }
575 }
576#endif // INCLUDE_G1GC
577#if INCLUDE_PARALLELGC
578 if (UseParallelGC) {
579 ParallelScavengeHeap* ps_heap = ParallelScavengeHeap::heap();
580 if (AllocateOldGenAt != NULL) {
581 MemRegion reserved = ps_heap->old_gen()->reserved();
582 return (jlong)reserved.end();
583 } else {
584 THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_NvdimmReservedEnd: Old gen is not allocated on NV-DIMM using AllocateOldGenAt flag");
585 }
586 }
587#endif // INCLUDE_PARALLELGC
588 THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_NvdimmReservedEnd: enabled only for G1 and Parallel GC");
589WB_END
590
591#endif // INCLUDE_G1GC || INCLUDE_PARALLELGC
592
593#if INCLUDE_PARALLELGC
594
595WB_ENTRY(jlong, WB_PSVirtualSpaceAlignment(JNIEnv* env, jobject o))
596 if (UseParallelGC) {
597 return ParallelScavengeHeap::heap()->gens()->virtual_spaces()->alignment();
598 }
599 THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_PSVirtualSpaceAlignment: Parallel GC is not enabled");
600WB_END
601
602WB_ENTRY(jlong, WB_PSHeapGenerationAlignment(JNIEnv* env, jobject o))
603 if (UseParallelGC) {
604 return GenAlignment;
605 }
606 THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_PSHeapGenerationAlignment: Parallel GC is not enabled");
607WB_END
608
609#endif // INCLUDE_PARALLELGC
610
611#if INCLUDE_G1GC
612
613WB_ENTRY(jobject, WB_G1AuxiliaryMemoryUsage(JNIEnv* env))
614 if (UseG1GC) {
615 ResourceMark rm(THREAD);
616 G1CollectedHeap* g1h = G1CollectedHeap::heap();
617 MemoryUsage usage = g1h->get_auxiliary_data_memory_usage();
618 Handle h = MemoryService::create_MemoryUsage_obj(usage, CHECK_NULL);
619 return JNIHandles::make_local(env, h());
620 }
621 THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_G1AuxiliaryMemoryUsage: G1 GC is not enabled");
622WB_END
623
624class OldRegionsLivenessClosure: public HeapRegionClosure {
625
626 private:
627 const int _liveness;
628 size_t _total_count;
629 size_t _total_memory;
630 size_t _total_memory_to_free;
631
632 public:
633 OldRegionsLivenessClosure(int liveness) :
634 _liveness(liveness),
635 _total_count(0),
636 _total_memory(0),
637 _total_memory_to_free(0) { }
638
639 size_t total_count() { return _total_count; }
640 size_t total_memory() { return _total_memory; }
641 size_t total_memory_to_free() { return _total_memory_to_free; }
642
643 bool do_heap_region(HeapRegion* r) {
644 if (r->is_old()) {
645 size_t prev_live = r->marked_bytes();
646 size_t live = r->live_bytes();
647 size_t size = r->used();
648 size_t reg_size = HeapRegion::GrainBytes;
649 if (size > 0 && ((int)(live * 100 / size) < _liveness)) {
650 _total_memory += size;
651 ++_total_count;
652 if (size == reg_size) {
653 // we don't include non-full regions since they are unlikely included in mixed gc
654 // for testing purposes it's enough to have lowest estimation of total memory that is expected to be freed
655 _total_memory_to_free += size - prev_live;
656 }
657 }
658 }
659 return false;
660 }
661};
662
663
664WB_ENTRY(jlongArray, WB_G1GetMixedGCInfo(JNIEnv* env, jobject o, jint liveness))
665 if (!UseG1GC) {
666 THROW_MSG_NULL(vmSymbols::java_lang_UnsupportedOperationException(), "WB_G1GetMixedGCInfo: G1 GC is not enabled");
667 }
668 if (liveness < 0) {
669 THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), "liveness value should be non-negative");
670 }
671
672 G1CollectedHeap* g1h = G1CollectedHeap::heap();
673 OldRegionsLivenessClosure rli(liveness);
674 g1h->heap_region_iterate(&rli);
675
676 typeArrayOop result = oopFactory::new_longArray(3, CHECK_NULL);
677 result->long_at_put(0, rli.total_count());
678 result->long_at_put(1, rli.total_memory());
679 result->long_at_put(2, rli.total_memory_to_free());
680 return (jlongArray) JNIHandles::make_local(env, result);
681WB_END
682
683#endif // INCLUDE_G1GC
684
685#if INCLUDE_NMT
686// Alloc memory using the test memory type so that we can use that to see if
687// NMT picks it up correctly
688WB_ENTRY(jlong, WB_NMTMalloc(JNIEnv* env, jobject o, jlong size))
689 jlong addr = 0;
690 addr = (jlong)(uintptr_t)os::malloc(size, mtTest);
691 return addr;
692WB_END
693
694// Alloc memory with pseudo call stack. The test can create psudo malloc
695// allocation site to stress the malloc tracking.
696WB_ENTRY(jlong, WB_NMTMallocWithPseudoStack(JNIEnv* env, jobject o, jlong size, jint pseudo_stack))
697 address pc = (address)(size_t)pseudo_stack;
698 NativeCallStack stack(&pc, 1);
699 return (jlong)(uintptr_t)os::malloc(size, mtTest, stack);
700WB_END
701
702// Alloc memory with pseudo call stack and specific memory type.
703WB_ENTRY(jlong, WB_NMTMallocWithPseudoStackAndType(JNIEnv* env, jobject o, jlong size, jint pseudo_stack, jint type))
704 address pc = (address)(size_t)pseudo_stack;
705 NativeCallStack stack(&pc, 1);
706 return (jlong)(uintptr_t)os::malloc(size, (MEMFLAGS)type, stack);
707WB_END
708
709// Free the memory allocated by NMTAllocTest
710WB_ENTRY(void, WB_NMTFree(JNIEnv* env, jobject o, jlong mem))
711 os::free((void*)(uintptr_t)mem);
712WB_END
713
714WB_ENTRY(jlong, WB_NMTReserveMemory(JNIEnv* env, jobject o, jlong size))
715 jlong addr = 0;
716
717 addr = (jlong)(uintptr_t)os::reserve_memory(size);
718 MemTracker::record_virtual_memory_type((address)addr, mtTest);
719
720 return addr;
721WB_END
722
723WB_ENTRY(jlong, WB_NMTAttemptReserveMemoryAt(JNIEnv* env, jobject o, jlong addr, jlong size))
724 addr = (jlong)(uintptr_t)os::attempt_reserve_memory_at((size_t)size, (char*)(uintptr_t)addr);
725 MemTracker::record_virtual_memory_type((address)addr, mtTest);
726
727 return addr;
728WB_END
729
730WB_ENTRY(void, WB_NMTCommitMemory(JNIEnv* env, jobject o, jlong addr, jlong size))
731 os::commit_memory((char *)(uintptr_t)addr, size, !ExecMem);
732 MemTracker::record_virtual_memory_type((address)(uintptr_t)addr, mtTest);
733WB_END
734
735WB_ENTRY(void, WB_NMTUncommitMemory(JNIEnv* env, jobject o, jlong addr, jlong size))
736 os::uncommit_memory((char *)(uintptr_t)addr, size);
737WB_END
738
739WB_ENTRY(void, WB_NMTReleaseMemory(JNIEnv* env, jobject o, jlong addr, jlong size))
740 os::release_memory((char *)(uintptr_t)addr, size);
741WB_END
742
743WB_ENTRY(jboolean, WB_NMTChangeTrackingLevel(JNIEnv* env))
744 // Test that we can downgrade NMT levels but not upgrade them.
745 if (MemTracker::tracking_level() == NMT_off) {
746 MemTracker::transition_to(NMT_off);
747 return MemTracker::tracking_level() == NMT_off;
748 } else {
749 assert(MemTracker::tracking_level() == NMT_detail, "Should start out as detail tracking");
750 MemTracker::transition_to(NMT_summary);
751 assert(MemTracker::tracking_level() == NMT_summary, "Should be summary now");
752
753 // Can't go to detail once NMT is set to summary.
754 MemTracker::transition_to(NMT_detail);
755 assert(MemTracker::tracking_level() == NMT_summary, "Should still be summary now");
756
757 // Shutdown sets tracking level to minimal.
758 MemTracker::shutdown();
759 assert(MemTracker::tracking_level() == NMT_minimal, "Should be minimal now");
760
761 // Once the tracking level is minimal, we cannot increase to summary.
762 // The code ignores this request instead of asserting because if the malloc site
763 // table overflows in another thread, it tries to change the code to summary.
764 MemTracker::transition_to(NMT_summary);
765 assert(MemTracker::tracking_level() == NMT_minimal, "Should still be minimal now");
766
767 // Really can never go up to detail, verify that the code would never do this.
768 MemTracker::transition_to(NMT_detail);
769 assert(MemTracker::tracking_level() == NMT_minimal, "Should still be minimal now");
770 return MemTracker::tracking_level() == NMT_minimal;
771 }
772WB_END
773
774WB_ENTRY(jint, WB_NMTGetHashSize(JNIEnv* env, jobject o))
775 int hash_size = MallocSiteTable::hash_buckets();
776 assert(hash_size > 0, "NMT hash_size should be > 0");
777 return (jint)hash_size;
778WB_END
779#endif // INCLUDE_NMT
780
781static jmethodID reflected_method_to_jmid(JavaThread* thread, JNIEnv* env, jobject method) {
782 assert(method != NULL, "method should not be null");
783 ThreadToNativeFromVM ttn(thread);
784 return env->FromReflectedMethod(method);
785}
786
787// Deoptimizes all compiled frames and makes nmethods not entrant if it's requested
788class VM_WhiteBoxDeoptimizeFrames : public VM_WhiteBoxOperation {
789 private:
790 int _result;
791 const bool _make_not_entrant;
792 public:
793 VM_WhiteBoxDeoptimizeFrames(bool make_not_entrant) :
794 _result(0), _make_not_entrant(make_not_entrant) { }
795 int result() const { return _result; }
796
797 void doit() {
798 for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) {
799 if (t->has_last_Java_frame()) {
800 for (StackFrameStream fst(t, UseBiasedLocking); !fst.is_done(); fst.next()) {
801 frame* f = fst.current();
802 if (f->can_be_deoptimized() && !f->is_deoptimized_frame()) {
803 RegisterMap* reg_map = fst.register_map();
804 Deoptimization::deoptimize(t, *f, reg_map);
805 if (_make_not_entrant) {
806 CompiledMethod* cm = CodeCache::find_compiled(f->pc());
807 assert(cm != NULL, "sanity check");
808 cm->make_not_entrant();
809 }
810 ++_result;
811 }
812 }
813 }
814 }
815 }
816};
817
818WB_ENTRY(jint, WB_DeoptimizeFrames(JNIEnv* env, jobject o, jboolean make_not_entrant))
819 VM_WhiteBoxDeoptimizeFrames op(make_not_entrant == JNI_TRUE);
820 VMThread::execute(&op);
821 return op.result();
822WB_END
823
824WB_ENTRY(void, WB_DeoptimizeAll(JNIEnv* env, jobject o))
825 MutexLocker mu(Compile_lock);
826 CodeCache::mark_all_nmethods_for_deoptimization();
827 VM_Deoptimize op;
828 VMThread::execute(&op);
829WB_END
830
831WB_ENTRY(jint, WB_DeoptimizeMethod(JNIEnv* env, jobject o, jobject method, jboolean is_osr))
832 jmethodID jmid = reflected_method_to_jmid(thread, env, method);
833 int result = 0;
834 CHECK_JNI_EXCEPTION_(env, result);
835 MutexLocker mu(Compile_lock);
836 methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
837 if (is_osr) {
838 result += mh->mark_osr_nmethods();
839 } else if (mh->code() != NULL) {
840 mh->code()->mark_for_deoptimization();
841 ++result;
842 }
843 result += CodeCache::mark_for_deoptimization(mh());
844 if (result > 0) {
845 VM_Deoptimize op;
846 VMThread::execute(&op);
847 }
848 return result;
849WB_END
850
851WB_ENTRY(jboolean, WB_IsMethodCompiled(JNIEnv* env, jobject o, jobject method, jboolean is_osr))
852 jmethodID jmid = reflected_method_to_jmid(thread, env, method);
853 CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
854 MutexLocker mu(Compile_lock);
855 methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
856 CompiledMethod* code = is_osr ? mh->lookup_osr_nmethod_for(InvocationEntryBci, CompLevel_none, false) : mh->code();
857 if (code == NULL) {
858 return JNI_FALSE;
859 }
860 return (code->is_alive() && !code->is_marked_for_deoptimization());
861WB_END
862
863WB_ENTRY(jboolean, WB_IsMethodCompilable(JNIEnv* env, jobject o, jobject method, jint comp_level, jboolean is_osr))
864 if (method == NULL || comp_level > MIN2((CompLevel) TieredStopAtLevel, CompLevel_highest_tier)) {
865 return false;
866 }
867 jmethodID jmid = reflected_method_to_jmid(thread, env, method);
868 CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
869 MutexLocker mu(Compile_lock);
870 methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
871 if (is_osr) {
872 return CompilationPolicy::can_be_osr_compiled(mh, comp_level);
873 } else {
874 return CompilationPolicy::can_be_compiled(mh, comp_level);
875 }
876WB_END
877
878WB_ENTRY(jboolean, WB_IsMethodQueuedForCompilation(JNIEnv* env, jobject o, jobject method))
879 jmethodID jmid = reflected_method_to_jmid(thread, env, method);
880 CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
881 MutexLocker mu(Compile_lock);
882 methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
883 return mh->queued_for_compilation();
884WB_END
885
886WB_ENTRY(jboolean, WB_IsIntrinsicAvailable(JNIEnv* env, jobject o, jobject method, jobject compilation_context, jint compLevel))
887 if (compLevel < CompLevel_none || compLevel > MIN2((CompLevel) TieredStopAtLevel, CompLevel_highest_tier)) {
888 return false; // Intrinsic is not available on a non-existent compilation level.
889 }
890 jmethodID method_id, compilation_context_id;
891 method_id = reflected_method_to_jmid(thread, env, method);
892 CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
893 methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(method_id));
894
895 DirectiveSet* directive;
896 AbstractCompiler* comp = CompileBroker::compiler((int)compLevel);
897 assert(comp != NULL, "compiler not available");
898 if (compilation_context != NULL) {
899 compilation_context_id = reflected_method_to_jmid(thread, env, compilation_context);
900 CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
901 methodHandle cch(THREAD, Method::checked_resolve_jmethod_id(compilation_context_id));
902 directive = DirectivesStack::getMatchingDirective(cch, comp);
903 } else {
904 // Calling with NULL matches default directive
905 directive = DirectivesStack::getDefaultDirective(comp);
906 }
907 bool result = comp->is_intrinsic_available(mh, directive);
908 DirectivesStack::release(directive);
909 return result;
910WB_END
911
912WB_ENTRY(jint, WB_GetMethodCompilationLevel(JNIEnv* env, jobject o, jobject method, jboolean is_osr))
913 jmethodID jmid = reflected_method_to_jmid(thread, env, method);
914 CHECK_JNI_EXCEPTION_(env, CompLevel_none);
915 methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
916 CompiledMethod* code = is_osr ? mh->lookup_osr_nmethod_for(InvocationEntryBci, CompLevel_none, false) : mh->code();
917 return (code != NULL ? code->comp_level() : CompLevel_none);
918WB_END
919
920WB_ENTRY(void, WB_MakeMethodNotCompilable(JNIEnv* env, jobject o, jobject method, jint comp_level, jboolean is_osr))
921 jmethodID jmid = reflected_method_to_jmid(thread, env, method);
922 CHECK_JNI_EXCEPTION(env);
923 methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
924 if (is_osr) {
925 mh->set_not_osr_compilable("WhiteBox", comp_level);
926 } else {
927 mh->set_not_compilable("WhiteBox", comp_level);
928 }
929WB_END
930
931WB_ENTRY(jint, WB_GetMethodEntryBci(JNIEnv* env, jobject o, jobject method))
932 jmethodID jmid = reflected_method_to_jmid(thread, env, method);
933 CHECK_JNI_EXCEPTION_(env, InvocationEntryBci);
934 methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
935 CompiledMethod* code = mh->lookup_osr_nmethod_for(InvocationEntryBci, CompLevel_none, false);
936 return (code != NULL && code->is_osr_method() ? code->osr_entry_bci() : InvocationEntryBci);
937WB_END
938
939WB_ENTRY(jboolean, WB_TestSetDontInlineMethod(JNIEnv* env, jobject o, jobject method, jboolean value))
940 jmethodID jmid = reflected_method_to_jmid(thread, env, method);
941 CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
942 methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
943 bool result = mh->dont_inline();
944 mh->set_dont_inline(value == JNI_TRUE);
945 return result;
946WB_END
947
948WB_ENTRY(jint, WB_GetCompileQueueSize(JNIEnv* env, jobject o, jint comp_level))
949 if (comp_level == CompLevel_any) {
950 return CompileBroker::queue_size(CompLevel_full_optimization) /* C2 */ +
951 CompileBroker::queue_size(CompLevel_full_profile) /* C1 */;
952 } else {
953 return CompileBroker::queue_size(comp_level);
954 }
955WB_END
956
957WB_ENTRY(jboolean, WB_TestSetForceInlineMethod(JNIEnv* env, jobject o, jobject method, jboolean value))
958 jmethodID jmid = reflected_method_to_jmid(thread, env, method);
959 CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
960 methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
961 bool result = mh->force_inline();
962 mh->set_force_inline(value == JNI_TRUE);
963 return result;
964WB_END
965
966bool WhiteBox::compile_method(Method* method, int comp_level, int bci, Thread* THREAD) {
967 // Screen for unavailable/bad comp level or null method
968 AbstractCompiler* comp = CompileBroker::compiler(comp_level);
969 if (method == NULL) {
970 tty->print_cr("WB error: request to compile NULL method");
971 return false;
972 }
973 if (comp_level > MIN2((CompLevel) TieredStopAtLevel, CompLevel_highest_tier)) {
974 tty->print_cr("WB error: invalid compilation level %d", comp_level);
975 return false;
976 }
977 if (comp == NULL) {
978 tty->print_cr("WB error: no compiler for requested compilation level %d", comp_level);
979 return false;
980 }
981
982 // Check if compilation is blocking
983 methodHandle mh(THREAD, method);
984 DirectiveSet* directive = DirectivesStack::getMatchingDirective(mh, comp);
985 bool is_blocking = !directive->BackgroundCompilationOption;
986 DirectivesStack::release(directive);
987
988 // Compile method and check result
989 nmethod* nm = CompileBroker::compile_method(mh, bci, comp_level, mh, mh->invocation_count(), CompileTask::Reason_Whitebox, THREAD);
990 MutexLocker mu(Compile_lock);
991 bool is_queued = mh->queued_for_compilation();
992 if ((!is_blocking && is_queued) || nm != NULL) {
993 return true;
994 }
995 tty->print("WB error: failed to %s compile at level %d method ", is_blocking ? "blocking" : "", comp_level);
996 mh->print_short_name(tty);
997 tty->cr();
998 if (is_blocking && is_queued) {
999 tty->print_cr("WB error: blocking compilation is still in queue!");
1000 }
1001 return false;
1002}
1003
1004WB_ENTRY(jboolean, WB_EnqueueMethodForCompilation(JNIEnv* env, jobject o, jobject method, jint comp_level, jint bci))
1005 jmethodID jmid = reflected_method_to_jmid(thread, env, method);
1006 CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
1007 return WhiteBox::compile_method(Method::checked_resolve_jmethod_id(jmid), comp_level, bci, THREAD);
1008WB_END
1009
1010WB_ENTRY(jboolean, WB_EnqueueInitializerForCompilation(JNIEnv* env, jobject o, jclass klass, jint comp_level))
1011 InstanceKlass* ik = InstanceKlass::cast(java_lang_Class::as_Klass(JNIHandles::resolve(klass)));
1012 Method* clinit = ik->class_initializer();
1013 if (clinit == NULL) {
1014 return false;
1015 }
1016 return WhiteBox::compile_method(clinit, comp_level, InvocationEntryBci, THREAD);
1017WB_END
1018
1019WB_ENTRY(jboolean, WB_ShouldPrintAssembly(JNIEnv* env, jobject o, jobject method, jint comp_level))
1020 jmethodID jmid = reflected_method_to_jmid(thread, env, method);
1021 CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
1022
1023 methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
1024 DirectiveSet* directive = DirectivesStack::getMatchingDirective(mh, CompileBroker::compiler(comp_level));
1025 bool result = directive->PrintAssemblyOption;
1026 DirectivesStack::release(directive);
1027
1028 return result;
1029WB_END
1030
1031WB_ENTRY(jint, WB_MatchesInline(JNIEnv* env, jobject o, jobject method, jstring pattern))
1032 jmethodID jmid = reflected_method_to_jmid(thread, env, method);
1033 CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
1034
1035 methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
1036
1037 ResourceMark rm;
1038 const char* error_msg = NULL;
1039 char* method_str = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(pattern));
1040 InlineMatcher* m = InlineMatcher::parse_inline_pattern(method_str, error_msg);
1041
1042 if (m == NULL) {
1043 assert(error_msg != NULL, "Always have an error message");
1044 tty->print_cr("Got error: %s", error_msg);
1045 return -1; // Pattern failed
1046 }
1047
1048 // Pattern works - now check if it matches
1049 int result;
1050 if (m->match(mh, InlineMatcher::force_inline)) {
1051 result = 2; // Force inline match
1052 } else if (m->match(mh, InlineMatcher::dont_inline)) {
1053 result = 1; // Dont inline match
1054 } else {
1055 result = 0; // No match
1056 }
1057 delete m;
1058 return result;
1059WB_END
1060
1061WB_ENTRY(jint, WB_MatchesMethod(JNIEnv* env, jobject o, jobject method, jstring pattern))
1062 jmethodID jmid = reflected_method_to_jmid(thread, env, method);
1063 CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
1064
1065 methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
1066
1067 ResourceMark rm;
1068 char* method_str = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(pattern));
1069
1070 const char* error_msg = NULL;
1071
1072 BasicMatcher* m = BasicMatcher::parse_method_pattern(method_str, error_msg);
1073 if (m == NULL) {
1074 assert(error_msg != NULL, "Must have error_msg");
1075 tty->print_cr("Got error: %s", error_msg);
1076 return -1;
1077 }
1078
1079 // Pattern works - now check if it matches
1080 int result = m->matches(mh);
1081 delete m;
1082 assert(result == 0 || result == 1, "Result out of range");
1083 return result;
1084WB_END
1085
1086WB_ENTRY(void, WB_MarkMethodProfiled(JNIEnv* env, jobject o, jobject method))
1087 jmethodID jmid = reflected_method_to_jmid(thread, env, method);
1088 CHECK_JNI_EXCEPTION(env);
1089 methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
1090
1091 MethodData* mdo = mh->method_data();
1092 if (mdo == NULL) {
1093 Method::build_interpreter_method_data(mh, CHECK_AND_CLEAR);
1094 mdo = mh->method_data();
1095 }
1096 mdo->init();
1097 InvocationCounter* icnt = mdo->invocation_counter();
1098 InvocationCounter* bcnt = mdo->backedge_counter();
1099 // set i-counter according to TieredThresholdPolicy::is_method_profiled
1100 icnt->set(InvocationCounter::wait_for_compile, Tier4MinInvocationThreshold);
1101 bcnt->set(InvocationCounter::wait_for_compile, Tier4CompileThreshold);
1102WB_END
1103
1104WB_ENTRY(void, WB_ClearMethodState(JNIEnv* env, jobject o, jobject method))
1105 jmethodID jmid = reflected_method_to_jmid(thread, env, method);
1106 CHECK_JNI_EXCEPTION(env);
1107 methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
1108 MutexLocker mu(Compile_lock);
1109 MethodData* mdo = mh->method_data();
1110 MethodCounters* mcs = mh->method_counters();
1111
1112 if (mdo != NULL) {
1113 mdo->init();
1114 ResourceMark rm;
1115 int arg_count = mdo->method()->size_of_parameters();
1116 for (int i = 0; i < arg_count; i++) {
1117 mdo->set_arg_modified(i, 0);
1118 }
1119 MutexLocker mu(mdo->extra_data_lock());
1120 mdo->clean_method_data(/*always_clean*/true);
1121 }
1122
1123 mh->clear_not_c1_compilable();
1124 mh->clear_not_c2_compilable();
1125 mh->clear_not_c2_osr_compilable();
1126 NOT_PRODUCT(mh->set_compiled_invocation_count(0));
1127 if (mcs != NULL) {
1128 mcs->backedge_counter()->init();
1129 mcs->invocation_counter()->init();
1130 mcs->set_interpreter_invocation_count(0);
1131 mcs->set_interpreter_throwout_count(0);
1132
1133#ifdef TIERED
1134 mcs->set_rate(0.0F);
1135 mh->set_prev_event_count(0);
1136 mh->set_prev_time(0);
1137#endif
1138 }
1139WB_END
1140
1141template <typename T>
1142static bool GetVMFlag(JavaThread* thread, JNIEnv* env, jstring name, T* value, JVMFlag::Error (*TAt)(const char*, T*, bool, bool)) {
1143 if (name == NULL) {
1144 return false;
1145 }
1146 ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
1147 const char* flag_name = env->GetStringUTFChars(name, NULL);
1148 CHECK_JNI_EXCEPTION_(env, false);
1149 JVMFlag::Error result = (*TAt)(flag_name, value, true, true);
1150 env->ReleaseStringUTFChars(name, flag_name);
1151 return (result == JVMFlag::SUCCESS);
1152}
1153
1154template <typename T>
1155static bool SetVMFlag(JavaThread* thread, JNIEnv* env, jstring name, T* value, JVMFlag::Error (*TAtPut)(const char*, T*, JVMFlag::Flags)) {
1156 if (name == NULL) {
1157 return false;
1158 }
1159 ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
1160 const char* flag_name = env->GetStringUTFChars(name, NULL);
1161 CHECK_JNI_EXCEPTION_(env, false);
1162 JVMFlag::Error result = (*TAtPut)(flag_name, value, JVMFlag::INTERNAL);
1163 env->ReleaseStringUTFChars(name, flag_name);
1164 return (result == JVMFlag::SUCCESS);
1165}
1166
1167template <typename T>
1168static jobject box(JavaThread* thread, JNIEnv* env, Symbol* name, Symbol* sig, T value) {
1169 ResourceMark rm(thread);
1170 jclass clazz = env->FindClass(name->as_C_string());
1171 CHECK_JNI_EXCEPTION_(env, NULL);
1172 jmethodID methodID = env->GetStaticMethodID(clazz,
1173 vmSymbols::valueOf_name()->as_C_string(),
1174 sig->as_C_string());
1175 CHECK_JNI_EXCEPTION_(env, NULL);
1176 jobject result = env->CallStaticObjectMethod(clazz, methodID, value);
1177 CHECK_JNI_EXCEPTION_(env, NULL);
1178 return result;
1179}
1180
1181static jobject booleanBox(JavaThread* thread, JNIEnv* env, jboolean value) {
1182 return box(thread, env, vmSymbols::java_lang_Boolean(), vmSymbols::Boolean_valueOf_signature(), value);
1183}
1184static jobject integerBox(JavaThread* thread, JNIEnv* env, jint value) {
1185 return box(thread, env, vmSymbols::java_lang_Integer(), vmSymbols::Integer_valueOf_signature(), value);
1186}
1187static jobject longBox(JavaThread* thread, JNIEnv* env, jlong value) {
1188 return box(thread, env, vmSymbols::java_lang_Long(), vmSymbols::Long_valueOf_signature(), value);
1189}
1190/* static jobject floatBox(JavaThread* thread, JNIEnv* env, jfloat value) {
1191 return box(thread, env, vmSymbols::java_lang_Float(), vmSymbols::Float_valueOf_signature(), value);
1192}*/
1193static jobject doubleBox(JavaThread* thread, JNIEnv* env, jdouble value) {
1194 return box(thread, env, vmSymbols::java_lang_Double(), vmSymbols::Double_valueOf_signature(), value);
1195}
1196
1197static JVMFlag* getVMFlag(JavaThread* thread, JNIEnv* env, jstring name) {
1198 ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
1199 const char* flag_name = env->GetStringUTFChars(name, NULL);
1200 CHECK_JNI_EXCEPTION_(env, NULL);
1201 JVMFlag* result = JVMFlag::find_flag(flag_name, strlen(flag_name), true, true);
1202 env->ReleaseStringUTFChars(name, flag_name);
1203 return result;
1204}
1205
1206WB_ENTRY(jboolean, WB_IsConstantVMFlag(JNIEnv* env, jobject o, jstring name))
1207 JVMFlag* flag = getVMFlag(thread, env, name);
1208 return (flag != NULL) && flag->is_constant_in_binary();
1209WB_END
1210
1211WB_ENTRY(jboolean, WB_IsLockedVMFlag(JNIEnv* env, jobject o, jstring name))
1212 JVMFlag* flag = getVMFlag(thread, env, name);
1213 return (flag != NULL) && !(flag->is_unlocked() || flag->is_unlocker());
1214WB_END
1215
1216WB_ENTRY(jobject, WB_GetBooleanVMFlag(JNIEnv* env, jobject o, jstring name))
1217 bool result;
1218 if (GetVMFlag <bool> (thread, env, name, &result, &JVMFlag::boolAt)) {
1219 ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
1220 return booleanBox(thread, env, result);
1221 }
1222 return NULL;
1223WB_END
1224
1225WB_ENTRY(jobject, WB_GetIntVMFlag(JNIEnv* env, jobject o, jstring name))
1226 int result;
1227 if (GetVMFlag <int> (thread, env, name, &result, &JVMFlag::intAt)) {
1228 ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
1229 return longBox(thread, env, result);
1230 }
1231 return NULL;
1232WB_END
1233
1234WB_ENTRY(jobject, WB_GetUintVMFlag(JNIEnv* env, jobject o, jstring name))
1235 uint result;
1236 if (GetVMFlag <uint> (thread, env, name, &result, &JVMFlag::uintAt)) {
1237 ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
1238 return longBox(thread, env, result);
1239 }
1240 return NULL;
1241WB_END
1242
1243WB_ENTRY(jobject, WB_GetIntxVMFlag(JNIEnv* env, jobject o, jstring name))
1244 intx result;
1245 if (GetVMFlag <intx> (thread, env, name, &result, &JVMFlag::intxAt)) {
1246 ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
1247 return longBox(thread, env, result);
1248 }
1249 return NULL;
1250WB_END
1251
1252WB_ENTRY(jobject, WB_GetUintxVMFlag(JNIEnv* env, jobject o, jstring name))
1253 uintx result;
1254 if (GetVMFlag <uintx> (thread, env, name, &result, &JVMFlag::uintxAt)) {
1255 ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
1256 return longBox(thread, env, result);
1257 }
1258 return NULL;
1259WB_END
1260
1261WB_ENTRY(jobject, WB_GetUint64VMFlag(JNIEnv* env, jobject o, jstring name))
1262 uint64_t result;
1263 if (GetVMFlag <uint64_t> (thread, env, name, &result, &JVMFlag::uint64_tAt)) {
1264 ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
1265 return longBox(thread, env, result);
1266 }
1267 return NULL;
1268WB_END
1269
1270WB_ENTRY(jobject, WB_GetSizeTVMFlag(JNIEnv* env, jobject o, jstring name))
1271 size_t result;
1272 if (GetVMFlag <size_t> (thread, env, name, &result, &JVMFlag::size_tAt)) {
1273 ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
1274 return longBox(thread, env, result);
1275 }
1276 return NULL;
1277WB_END
1278
1279WB_ENTRY(jobject, WB_GetDoubleVMFlag(JNIEnv* env, jobject o, jstring name))
1280 double result;
1281 if (GetVMFlag <double> (thread, env, name, &result, &JVMFlag::doubleAt)) {
1282 ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
1283 return doubleBox(thread, env, result);
1284 }
1285 return NULL;
1286WB_END
1287
1288WB_ENTRY(jstring, WB_GetStringVMFlag(JNIEnv* env, jobject o, jstring name))
1289 ccstr ccstrResult;
1290 if (GetVMFlag <ccstr> (thread, env, name, &ccstrResult, &JVMFlag::ccstrAt)) {
1291 ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
1292 jstring result = env->NewStringUTF(ccstrResult);
1293 CHECK_JNI_EXCEPTION_(env, NULL);
1294 return result;
1295 }
1296 return NULL;
1297WB_END
1298
1299WB_ENTRY(void, WB_SetBooleanVMFlag(JNIEnv* env, jobject o, jstring name, jboolean value))
1300 bool result = value == JNI_TRUE ? true : false;
1301 SetVMFlag <bool> (thread, env, name, &result, &JVMFlag::boolAtPut);
1302WB_END
1303
1304WB_ENTRY(void, WB_SetIntVMFlag(JNIEnv* env, jobject o, jstring name, jlong value))
1305 int result = value;
1306 SetVMFlag <int> (thread, env, name, &result, &JVMFlag::intAtPut);
1307WB_END
1308
1309WB_ENTRY(void, WB_SetUintVMFlag(JNIEnv* env, jobject o, jstring name, jlong value))
1310 uint result = value;
1311 SetVMFlag <uint> (thread, env, name, &result, &JVMFlag::uintAtPut);
1312WB_END
1313
1314WB_ENTRY(void, WB_SetIntxVMFlag(JNIEnv* env, jobject o, jstring name, jlong value))
1315 intx result = value;
1316 SetVMFlag <intx> (thread, env, name, &result, &JVMFlag::intxAtPut);
1317WB_END
1318
1319WB_ENTRY(void, WB_SetUintxVMFlag(JNIEnv* env, jobject o, jstring name, jlong value))
1320 uintx result = value;
1321 SetVMFlag <uintx> (thread, env, name, &result, &JVMFlag::uintxAtPut);
1322WB_END
1323
1324WB_ENTRY(void, WB_SetUint64VMFlag(JNIEnv* env, jobject o, jstring name, jlong value))
1325 uint64_t result = value;
1326 SetVMFlag <uint64_t> (thread, env, name, &result, &JVMFlag::uint64_tAtPut);
1327WB_END
1328
1329WB_ENTRY(void, WB_SetSizeTVMFlag(JNIEnv* env, jobject o, jstring name, jlong value))
1330 size_t result = value;
1331 SetVMFlag <size_t> (thread, env, name, &result, &JVMFlag::size_tAtPut);
1332WB_END
1333
1334WB_ENTRY(void, WB_SetDoubleVMFlag(JNIEnv* env, jobject o, jstring name, jdouble value))
1335 double result = value;
1336 SetVMFlag <double> (thread, env, name, &result, &JVMFlag::doubleAtPut);
1337WB_END
1338
1339WB_ENTRY(void, WB_SetStringVMFlag(JNIEnv* env, jobject o, jstring name, jstring value))
1340 ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
1341 const char* ccstrValue;
1342 if (value == NULL) {
1343 ccstrValue = NULL;
1344 }
1345 else {
1346 ccstrValue = env->GetStringUTFChars(value, NULL);
1347 CHECK_JNI_EXCEPTION(env);
1348 }
1349 ccstr ccstrResult = ccstrValue;
1350 bool needFree;
1351 {
1352 ThreadInVMfromNative ttvfn(thread); // back to VM
1353 needFree = SetVMFlag <ccstr> (thread, env, name, &ccstrResult, &JVMFlag::ccstrAtPut);
1354 }
1355 if (value != NULL) {
1356 env->ReleaseStringUTFChars(value, ccstrValue);
1357 }
1358 if (needFree) {
1359 FREE_C_HEAP_ARRAY(char, ccstrResult);
1360 }
1361WB_END
1362
1363WB_ENTRY(void, WB_LockCompilation(JNIEnv* env, jobject o, jlong timeout))
1364 WhiteBox::compilation_locked = true;
1365WB_END
1366
1367WB_ENTRY(void, WB_UnlockCompilation(JNIEnv* env, jobject o))
1368 MonitorLocker mo(Compilation_lock, Mutex::_no_safepoint_check_flag);
1369 WhiteBox::compilation_locked = false;
1370 mo.notify_all();
1371WB_END
1372
1373WB_ENTRY(void, WB_ForceNMethodSweep(JNIEnv* env, jobject o))
1374 // Force a code cache sweep and block until it finished
1375 NMethodSweeper::force_sweep();
1376WB_END
1377
1378WB_ENTRY(jboolean, WB_IsInStringTable(JNIEnv* env, jobject o, jstring javaString))
1379 ResourceMark rm(THREAD);
1380 int len;
1381 jchar* name = java_lang_String::as_unicode_string(JNIHandles::resolve(javaString), len, CHECK_false);
1382 return (StringTable::lookup(name, len) != NULL);
1383WB_END
1384
1385WB_ENTRY(void, WB_FullGC(JNIEnv* env, jobject o))
1386 Universe::heap()->soft_ref_policy()->set_should_clear_all_soft_refs(true);
1387 Universe::heap()->collect(GCCause::_wb_full_gc);
1388#if INCLUDE_G1GC
1389 if (UseG1GC) {
1390 // Needs to be cleared explicitly for G1
1391 Universe::heap()->soft_ref_policy()->set_should_clear_all_soft_refs(false);
1392 }
1393#endif // INCLUDE_G1GC
1394WB_END
1395
1396WB_ENTRY(void, WB_YoungGC(JNIEnv* env, jobject o))
1397 Universe::heap()->collect(GCCause::_wb_young_gc);
1398WB_END
1399
1400WB_ENTRY(void, WB_ReadReservedMemory(JNIEnv* env, jobject o))
1401 // static+volatile in order to force the read to happen
1402 // (not be eliminated by the compiler)
1403 static char c;
1404 static volatile char* p;
1405
1406 p = os::reserve_memory(os::vm_allocation_granularity(), NULL, 0);
1407 if (p == NULL) {
1408 THROW_MSG(vmSymbols::java_lang_OutOfMemoryError(), "Failed to reserve memory");
1409 }
1410
1411 c = *p;
1412WB_END
1413
1414WB_ENTRY(jstring, WB_GetCPUFeatures(JNIEnv* env, jobject o))
1415 const char* features = VM_Version::features_string();
1416 ThreadToNativeFromVM ttn(thread);
1417 jstring features_string = env->NewStringUTF(features);
1418
1419 CHECK_JNI_EXCEPTION_(env, NULL);
1420
1421 return features_string;
1422WB_END
1423
1424int WhiteBox::get_blob_type(const CodeBlob* code) {
1425 guarantee(WhiteBoxAPI, "internal testing API :: WhiteBox has to be enabled");
1426 if (code->is_aot()) {
1427 return -1;
1428 }
1429 return CodeCache::get_code_heap(code)->code_blob_type();
1430}
1431
1432CodeHeap* WhiteBox::get_code_heap(int blob_type) {
1433 guarantee(WhiteBoxAPI, "internal testing API :: WhiteBox has to be enabled");
1434 return CodeCache::get_code_heap(blob_type);
1435}
1436
1437struct CodeBlobStub {
1438 CodeBlobStub(const CodeBlob* blob) :
1439 name(os::strdup(blob->name())),
1440 size(blob->size()),
1441 blob_type(WhiteBox::get_blob_type(blob)),
1442 address((jlong) blob) { }
1443 ~CodeBlobStub() { os::free((void*) name); }
1444 const char* const name;
1445 const jint size;
1446 const jint blob_type;
1447 const jlong address;
1448};
1449
1450static jobjectArray codeBlob2objectArray(JavaThread* thread, JNIEnv* env, CodeBlobStub* cb) {
1451 jclass clazz = env->FindClass(vmSymbols::java_lang_Object()->as_C_string());
1452 CHECK_JNI_EXCEPTION_(env, NULL);
1453 jobjectArray result = env->NewObjectArray(4, clazz, NULL);
1454
1455 jstring name = env->NewStringUTF(cb->name);
1456 CHECK_JNI_EXCEPTION_(env, NULL);
1457 env->SetObjectArrayElement(result, 0, name);
1458
1459 jobject obj = integerBox(thread, env, cb->size);
1460 CHECK_JNI_EXCEPTION_(env, NULL);
1461 env->SetObjectArrayElement(result, 1, obj);
1462
1463 obj = integerBox(thread, env, cb->blob_type);
1464 CHECK_JNI_EXCEPTION_(env, NULL);
1465 env->SetObjectArrayElement(result, 2, obj);
1466
1467 obj = longBox(thread, env, cb->address);
1468 CHECK_JNI_EXCEPTION_(env, NULL);
1469 env->SetObjectArrayElement(result, 3, obj);
1470
1471 return result;
1472}
1473
1474WB_ENTRY(jobjectArray, WB_GetNMethod(JNIEnv* env, jobject o, jobject method, jboolean is_osr))
1475 ResourceMark rm(THREAD);
1476 jmethodID jmid = reflected_method_to_jmid(thread, env, method);
1477 CHECK_JNI_EXCEPTION_(env, NULL);
1478 methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
1479 CompiledMethod* code = is_osr ? mh->lookup_osr_nmethod_for(InvocationEntryBci, CompLevel_none, false) : mh->code();
1480 jobjectArray result = NULL;
1481 if (code == NULL) {
1482 return result;
1483 }
1484 int comp_level = code->comp_level();
1485 int insts_size = comp_level == CompLevel_aot ? code->code_end() - code->code_begin() : code->insts_size();
1486
1487 ThreadToNativeFromVM ttn(thread);
1488 jclass clazz = env->FindClass(vmSymbols::java_lang_Object()->as_C_string());
1489 CHECK_JNI_EXCEPTION_(env, NULL);
1490 result = env->NewObjectArray(5, clazz, NULL);
1491 if (result == NULL) {
1492 return result;
1493 }
1494
1495 CodeBlobStub stub(code);
1496 jobjectArray codeBlob = codeBlob2objectArray(thread, env, &stub);
1497 CHECK_JNI_EXCEPTION_(env, NULL);
1498 env->SetObjectArrayElement(result, 0, codeBlob);
1499
1500 jobject level = integerBox(thread, env, comp_level);
1501 CHECK_JNI_EXCEPTION_(env, NULL);
1502 env->SetObjectArrayElement(result, 1, level);
1503
1504 jbyteArray insts = env->NewByteArray(insts_size);
1505 CHECK_JNI_EXCEPTION_(env, NULL);
1506 env->SetByteArrayRegion(insts, 0, insts_size, (jbyte*) code->insts_begin());
1507 env->SetObjectArrayElement(result, 2, insts);
1508
1509 jobject id = integerBox(thread, env, code->compile_id());
1510 CHECK_JNI_EXCEPTION_(env, NULL);
1511 env->SetObjectArrayElement(result, 3, id);
1512
1513 jobject entry_point = longBox(thread, env, (jlong) code->entry_point());
1514 CHECK_JNI_EXCEPTION_(env, NULL);
1515 env->SetObjectArrayElement(result, 4, entry_point);
1516
1517 return result;
1518WB_END
1519
1520CodeBlob* WhiteBox::allocate_code_blob(int size, int blob_type) {
1521 guarantee(WhiteBoxAPI, "internal testing API :: WhiteBox has to be enabled");
1522 BufferBlob* blob;
1523 int full_size = CodeBlob::align_code_offset(sizeof(BufferBlob));
1524 if (full_size < size) {
1525 full_size += align_up(size - full_size, oopSize);
1526 }
1527 {
1528 MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
1529 blob = (BufferBlob*) CodeCache::allocate(full_size, blob_type);
1530 if (blob != NULL) {
1531 ::new (blob) BufferBlob("WB::DummyBlob", full_size);
1532 }
1533 }
1534 // Track memory usage statistic after releasing CodeCache_lock
1535 MemoryService::track_code_cache_memory_usage();
1536 return blob;
1537}
1538
1539WB_ENTRY(jlong, WB_AllocateCodeBlob(JNIEnv* env, jobject o, jint size, jint blob_type))
1540 if (size < 0) {
1541 THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
1542 err_msg("WB_AllocateCodeBlob: size is negative: " INT32_FORMAT, size));
1543 }
1544 return (jlong) WhiteBox::allocate_code_blob(size, blob_type);
1545WB_END
1546
1547WB_ENTRY(void, WB_FreeCodeBlob(JNIEnv* env, jobject o, jlong addr))
1548 if (addr == 0) {
1549 return;
1550 }
1551 BufferBlob::free((BufferBlob*) addr);
1552WB_END
1553
1554WB_ENTRY(jobjectArray, WB_GetCodeHeapEntries(JNIEnv* env, jobject o, jint blob_type))
1555 ResourceMark rm;
1556 GrowableArray<CodeBlobStub*> blobs;
1557 {
1558 MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
1559 CodeHeap* heap = WhiteBox::get_code_heap(blob_type);
1560 if (heap == NULL) {
1561 return NULL;
1562 }
1563 for (CodeBlob* cb = (CodeBlob*) heap->first();
1564 cb != NULL; cb = (CodeBlob*) heap->next(cb)) {
1565 CodeBlobStub* stub = NEW_RESOURCE_OBJ(CodeBlobStub);
1566 new (stub) CodeBlobStub(cb);
1567 blobs.append(stub);
1568 }
1569 }
1570 ThreadToNativeFromVM ttn(thread);
1571 jobjectArray result = NULL;
1572 jclass clazz = env->FindClass(vmSymbols::java_lang_Object()->as_C_string());
1573 CHECK_JNI_EXCEPTION_(env, NULL);
1574 result = env->NewObjectArray(blobs.length(), clazz, NULL);
1575 CHECK_JNI_EXCEPTION_(env, NULL);
1576 if (result == NULL) {
1577 return result;
1578 }
1579 int i = 0;
1580 for (GrowableArrayIterator<CodeBlobStub*> it = blobs.begin();
1581 it != blobs.end(); ++it) {
1582 jobjectArray obj = codeBlob2objectArray(thread, env, *it);
1583 CHECK_JNI_EXCEPTION_(env, NULL);
1584 env->SetObjectArrayElement(result, i, obj);
1585 CHECK_JNI_EXCEPTION_(env, NULL);
1586 ++i;
1587 }
1588 return result;
1589WB_END
1590
1591WB_ENTRY(jint, WB_GetCompilationActivityMode(JNIEnv* env, jobject o))
1592 return CompileBroker::get_compilation_activity_mode();
1593WB_END
1594
1595WB_ENTRY(jobjectArray, WB_GetCodeBlob(JNIEnv* env, jobject o, jlong addr))
1596 if (addr == 0) {
1597 THROW_MSG_NULL(vmSymbols::java_lang_NullPointerException(),
1598 "WB_GetCodeBlob: addr is null");
1599 }
1600 ThreadToNativeFromVM ttn(thread);
1601 CodeBlobStub stub((CodeBlob*) addr);
1602 return codeBlob2objectArray(thread, env, &stub);
1603WB_END
1604
1605WB_ENTRY(jlong, WB_GetMethodData(JNIEnv* env, jobject wv, jobject method))
1606 jmethodID jmid = reflected_method_to_jmid(thread, env, method);
1607 CHECK_JNI_EXCEPTION_(env, 0);
1608 methodHandle mh(thread, Method::checked_resolve_jmethod_id(jmid));
1609 return (jlong) mh->method_data();
1610WB_END
1611
1612WB_ENTRY(jlong, WB_GetThreadStackSize(JNIEnv* env, jobject o))
1613 return (jlong) Thread::current()->stack_size();
1614WB_END
1615
1616WB_ENTRY(jlong, WB_GetThreadRemainingStackSize(JNIEnv* env, jobject o))
1617 JavaThread* t = JavaThread::current();
1618 return (jlong) t->stack_available(os::current_stack_pointer()) - (jlong)JavaThread::stack_shadow_zone_size();
1619WB_END
1620
1621
1622int WhiteBox::array_bytes_to_length(size_t bytes) {
1623 return Array<u1>::bytes_to_length(bytes);
1624}
1625
1626WB_ENTRY(jlong, WB_AllocateMetaspace(JNIEnv* env, jobject wb, jobject class_loader, jlong size))
1627 if (size < 0) {
1628 THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
1629 err_msg("WB_AllocateMetaspace: size is negative: " JLONG_FORMAT, size));
1630 }
1631
1632 oop class_loader_oop = JNIHandles::resolve(class_loader);
1633 ClassLoaderData* cld = class_loader_oop != NULL
1634 ? java_lang_ClassLoader::loader_data_acquire(class_loader_oop)
1635 : ClassLoaderData::the_null_class_loader_data();
1636
1637 void* metadata = MetadataFactory::new_array<u1>(cld, WhiteBox::array_bytes_to_length((size_t)size), thread);
1638
1639 return (jlong)(uintptr_t)metadata;
1640WB_END
1641
1642WB_ENTRY(void, WB_FreeMetaspace(JNIEnv* env, jobject wb, jobject class_loader, jlong addr, jlong size))
1643 oop class_loader_oop = JNIHandles::resolve(class_loader);
1644 ClassLoaderData* cld = class_loader_oop != NULL
1645 ? java_lang_ClassLoader::loader_data_acquire(class_loader_oop)
1646 : ClassLoaderData::the_null_class_loader_data();
1647
1648 MetadataFactory::free_array(cld, (Array<u1>*)(uintptr_t)addr);
1649WB_END
1650
1651WB_ENTRY(void, WB_DefineModule(JNIEnv* env, jobject o, jobject module, jboolean is_open,
1652 jstring version, jstring location, jobjectArray packages))
1653 ResourceMark rm(THREAD);
1654
1655 objArrayOop packages_oop = objArrayOop(JNIHandles::resolve(packages));
1656 objArrayHandle packages_h(THREAD, packages_oop);
1657 int num_packages = (packages_h == NULL ? 0 : packages_h->length());
1658
1659 char** pkgs = NULL;
1660 if (num_packages > 0) {
1661 pkgs = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char*, num_packages);
1662 for (int x = 0; x < num_packages; x++) {
1663 oop pkg_str = packages_h->obj_at(x);
1664 if (pkg_str == NULL || !pkg_str->is_a(SystemDictionary::String_klass())) {
1665 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
1666 err_msg("Bad package name"));
1667 }
1668 pkgs[x] = java_lang_String::as_utf8_string(pkg_str);
1669 }
1670 }
1671 Modules::define_module(module, is_open, version, location, (const char* const*)pkgs, num_packages, CHECK);
1672WB_END
1673
1674WB_ENTRY(void, WB_AddModuleExports(JNIEnv* env, jobject o, jobject from_module, jstring package, jobject to_module))
1675 ResourceMark rm(THREAD);
1676 char* package_name = NULL;
1677 if (package != NULL) {
1678 package_name = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(package));
1679 }
1680 Modules::add_module_exports_qualified(from_module, package_name, to_module, CHECK);
1681WB_END
1682
1683WB_ENTRY(void, WB_AddModuleExportsToAllUnnamed(JNIEnv* env, jobject o, jclass module, jstring package))
1684 ResourceMark rm(THREAD);
1685 char* package_name = NULL;
1686 if (package != NULL) {
1687 package_name = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(package));
1688 }
1689 Modules::add_module_exports_to_all_unnamed(module, package_name, CHECK);
1690WB_END
1691
1692WB_ENTRY(void, WB_AddModuleExportsToAll(JNIEnv* env, jobject o, jclass module, jstring package))
1693 ResourceMark rm(THREAD);
1694 char* package_name = NULL;
1695 if (package != NULL) {
1696 package_name = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(package));
1697 }
1698 Modules::add_module_exports(module, package_name, NULL, CHECK);
1699WB_END
1700
1701WB_ENTRY(void, WB_AddReadsModule(JNIEnv* env, jobject o, jobject from_module, jobject source_module))
1702 Modules::add_reads_module(from_module, source_module, CHECK);
1703WB_END
1704
1705WB_ENTRY(jlong, WB_IncMetaspaceCapacityUntilGC(JNIEnv* env, jobject wb, jlong inc))
1706 if (inc < 0) {
1707 THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
1708 err_msg("WB_IncMetaspaceCapacityUntilGC: inc is negative: " JLONG_FORMAT, inc));
1709 }
1710
1711 jlong max_size_t = (jlong) ((size_t) -1);
1712 if (inc > max_size_t) {
1713 THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
1714 err_msg("WB_IncMetaspaceCapacityUntilGC: inc does not fit in size_t: " JLONG_FORMAT, inc));
1715 }
1716
1717 size_t new_cap_until_GC = 0;
1718 size_t aligned_inc = align_down((size_t) inc, Metaspace::commit_alignment());
1719 bool success = MetaspaceGC::inc_capacity_until_GC(aligned_inc, &new_cap_until_GC);
1720 if (!success) {
1721 THROW_MSG_0(vmSymbols::java_lang_IllegalStateException(),
1722 "WB_IncMetaspaceCapacityUntilGC: could not increase capacity until GC "
1723 "due to contention with another thread");
1724 }
1725 return (jlong) new_cap_until_GC;
1726WB_END
1727
1728WB_ENTRY(jlong, WB_MetaspaceCapacityUntilGC(JNIEnv* env, jobject wb))
1729 return (jlong) MetaspaceGC::capacity_until_GC();
1730WB_END
1731
1732WB_ENTRY(jboolean, WB_MetaspaceShouldConcurrentCollect(JNIEnv* env, jobject wb))
1733 return MetaspaceGC::should_concurrent_collect();
1734WB_END
1735
1736WB_ENTRY(jlong, WB_MetaspaceReserveAlignment(JNIEnv* env, jobject wb))
1737 return (jlong)Metaspace::reserve_alignment();
1738WB_END
1739
1740WB_ENTRY(void, WB_AssertMatchingSafepointCalls(JNIEnv* env, jobject o, jboolean mutexSafepointValue, jboolean attemptedNoSafepointValue))
1741 Monitor::SafepointCheckRequired sfpt_check_required = mutexSafepointValue ?
1742 Monitor::_safepoint_check_always :
1743 Monitor::_safepoint_check_never;
1744 Monitor::SafepointCheckFlag sfpt_check_attempted = attemptedNoSafepointValue ?
1745 Monitor::_no_safepoint_check_flag :
1746 Monitor::_safepoint_check_flag;
1747 MutexLocker ml(new Mutex(Mutex::leaf, "SFPT_Test_lock", true, sfpt_check_required),
1748 sfpt_check_attempted);
1749WB_END
1750
1751WB_ENTRY(jboolean, WB_IsMonitorInflated(JNIEnv* env, jobject wb, jobject obj))
1752 oop obj_oop = JNIHandles::resolve(obj);
1753 return (jboolean) obj_oop->mark()->has_monitor();
1754WB_END
1755
1756WB_ENTRY(void, WB_ForceSafepoint(JNIEnv* env, jobject wb))
1757 VM_ForceSafepoint force_safepoint_op;
1758 VMThread::execute(&force_safepoint_op);
1759WB_END
1760
1761WB_ENTRY(jlong, WB_GetConstantPool(JNIEnv* env, jobject wb, jclass klass))
1762 InstanceKlass* ik = InstanceKlass::cast(java_lang_Class::as_Klass(JNIHandles::resolve(klass)));
1763 return (jlong) ik->constants();
1764WB_END
1765
1766WB_ENTRY(jint, WB_GetConstantPoolCacheIndexTag(JNIEnv* env, jobject wb))
1767 return ConstantPool::CPCACHE_INDEX_TAG;
1768WB_END
1769
1770WB_ENTRY(jint, WB_GetConstantPoolCacheLength(JNIEnv* env, jobject wb, jclass klass))
1771 InstanceKlass* ik = InstanceKlass::cast(java_lang_Class::as_Klass(JNIHandles::resolve(klass)));
1772 ConstantPool* cp = ik->constants();
1773 if (cp->cache() == NULL) {
1774 return -1;
1775 }
1776 return cp->cache()->length();
1777WB_END
1778
1779WB_ENTRY(jint, WB_ConstantPoolRemapInstructionOperandFromCache(JNIEnv* env, jobject wb, jclass klass, jint index))
1780 InstanceKlass* ik = InstanceKlass::cast(java_lang_Class::as_Klass(JNIHandles::resolve(klass)));
1781 ConstantPool* cp = ik->constants();
1782 if (cp->cache() == NULL) {
1783 THROW_MSG_0(vmSymbols::java_lang_IllegalStateException(), "Constant pool does not have a cache");
1784 }
1785 jint cpci = index;
1786 jint cpciTag = ConstantPool::CPCACHE_INDEX_TAG;
1787 if (cpciTag > cpci || cpci >= cp->cache()->length() + cpciTag) {
1788 THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Constant pool cache index is out of range");
1789 }
1790 jint cpi = cp->remap_instruction_operand_from_cache(cpci);
1791 return cpi;
1792WB_END
1793
1794WB_ENTRY(jint, WB_ConstantPoolEncodeIndyIndex(JNIEnv* env, jobject wb, jint index))
1795 return ConstantPool::encode_invokedynamic_index(index);
1796WB_END
1797
1798WB_ENTRY(void, WB_ClearInlineCaches(JNIEnv* env, jobject wb, jboolean preserve_static_stubs))
1799 VM_ClearICs clear_ics(preserve_static_stubs == JNI_TRUE);
1800 VMThread::execute(&clear_ics);
1801WB_END
1802
1803template <typename T>
1804static bool GetMethodOption(JavaThread* thread, JNIEnv* env, jobject method, jstring name, T* value) {
1805 assert(value != NULL, "sanity");
1806 if (method == NULL || name == NULL) {
1807 return false;
1808 }
1809 jmethodID jmid = reflected_method_to_jmid(thread, env, method);
1810 CHECK_JNI_EXCEPTION_(env, false);
1811 methodHandle mh(thread, Method::checked_resolve_jmethod_id(jmid));
1812 // can't be in VM when we call JNI
1813 ThreadToNativeFromVM ttnfv(thread);
1814 const char* flag_name = env->GetStringUTFChars(name, NULL);
1815 CHECK_JNI_EXCEPTION_(env, false);
1816 bool result = CompilerOracle::has_option_value(mh, flag_name, *value);
1817 env->ReleaseStringUTFChars(name, flag_name);
1818 return result;
1819}
1820
1821WB_ENTRY(jobject, WB_GetMethodBooleaneOption(JNIEnv* env, jobject wb, jobject method, jstring name))
1822 bool result;
1823 if (GetMethodOption<bool> (thread, env, method, name, &result)) {
1824 // can't be in VM when we call JNI
1825 ThreadToNativeFromVM ttnfv(thread);
1826 return booleanBox(thread, env, result);
1827 }
1828 return NULL;
1829WB_END
1830
1831WB_ENTRY(jobject, WB_GetMethodIntxOption(JNIEnv* env, jobject wb, jobject method, jstring name))
1832 intx result;
1833 if (GetMethodOption <intx> (thread, env, method, name, &result)) {
1834 // can't be in VM when we call JNI
1835 ThreadToNativeFromVM ttnfv(thread);
1836 return longBox(thread, env, result);
1837 }
1838 return NULL;
1839WB_END
1840
1841WB_ENTRY(jobject, WB_GetMethodUintxOption(JNIEnv* env, jobject wb, jobject method, jstring name))
1842 uintx result;
1843 if (GetMethodOption <uintx> (thread, env, method, name, &result)) {
1844 // can't be in VM when we call JNI
1845 ThreadToNativeFromVM ttnfv(thread);
1846 return longBox(thread, env, result);
1847 }
1848 return NULL;
1849WB_END
1850
1851WB_ENTRY(jobject, WB_GetMethodDoubleOption(JNIEnv* env, jobject wb, jobject method, jstring name))
1852 double result;
1853 if (GetMethodOption <double> (thread, env, method, name, &result)) {
1854 // can't be in VM when we call JNI
1855 ThreadToNativeFromVM ttnfv(thread);
1856 return doubleBox(thread, env, result);
1857 }
1858 return NULL;
1859WB_END
1860
1861WB_ENTRY(jobject, WB_GetMethodStringOption(JNIEnv* env, jobject wb, jobject method, jstring name))
1862 ccstr ccstrResult;
1863 if (GetMethodOption <ccstr> (thread, env, method, name, &ccstrResult)) {
1864 // can't be in VM when we call JNI
1865 ThreadToNativeFromVM ttnfv(thread);
1866 jstring result = env->NewStringUTF(ccstrResult);
1867 CHECK_JNI_EXCEPTION_(env, NULL);
1868 return result;
1869 }
1870 return NULL;
1871WB_END
1872
1873WB_ENTRY(jobject, WB_GetDefaultArchivePath(JNIEnv* env, jobject wb))
1874 const char* p = Arguments::get_default_shared_archive_path();
1875 ThreadToNativeFromVM ttn(thread);
1876 jstring path_string = env->NewStringUTF(p);
1877
1878 CHECK_JNI_EXCEPTION_(env, NULL);
1879
1880 return path_string;
1881WB_END
1882
1883WB_ENTRY(jboolean, WB_IsSharingEnabled(JNIEnv* env, jobject wb))
1884 return UseSharedSpaces;
1885WB_END
1886
1887WB_ENTRY(jboolean, WB_CDSMemoryMappingFailed(JNIEnv* env, jobject wb))
1888 return FileMapInfo::memory_mapping_failed();
1889WB_END
1890
1891WB_ENTRY(jboolean, WB_IsShared(JNIEnv* env, jobject wb, jobject obj))
1892 oop obj_oop = JNIHandles::resolve(obj);
1893 return HeapShared::is_archived_object(obj_oop);
1894WB_END
1895
1896WB_ENTRY(jboolean, WB_IsSharedClass(JNIEnv* env, jobject wb, jclass clazz))
1897 return (jboolean)MetaspaceShared::is_in_shared_metaspace(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz)));
1898WB_END
1899
1900WB_ENTRY(jboolean, WB_AreSharedStringsIgnored(JNIEnv* env))
1901 return !HeapShared::closed_archive_heap_region_mapped();
1902WB_END
1903
1904WB_ENTRY(jobject, WB_GetResolvedReferences(JNIEnv* env, jobject wb, jclass clazz))
1905 Klass *k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz));
1906 if (k->is_instance_klass()) {
1907 InstanceKlass *ik = InstanceKlass::cast(k);
1908 ConstantPool *cp = ik->constants();
1909 objArrayOop refs = cp->resolved_references();
1910 return (jobject)JNIHandles::make_local(env, refs);
1911 } else {
1912 return NULL;
1913 }
1914WB_END
1915
1916WB_ENTRY(void, WB_LinkClass(JNIEnv* env, jobject wb, jclass clazz))
1917 Klass *k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz));
1918 if (!k->is_instance_klass()) {
1919 return;
1920 }
1921 InstanceKlass *ik = InstanceKlass::cast(k);
1922 ik->link_class(THREAD); // may throw verification error
1923WB_END
1924
1925WB_ENTRY(jboolean, WB_AreOpenArchiveHeapObjectsMapped(JNIEnv* env))
1926 return HeapShared::open_archive_heap_region_mapped();
1927WB_END
1928
1929WB_ENTRY(jboolean, WB_IsCDSIncludedInVmBuild(JNIEnv* env))
1930#if INCLUDE_CDS
1931# ifdef _LP64
1932 if (!UseCompressedOops || !UseCompressedClassPointers) {
1933 // On 64-bit VMs, CDS is supported only with compressed oops/pointers
1934 return false;
1935 }
1936# endif // _LP64
1937 return true;
1938#else
1939 return false;
1940#endif // INCLUDE_CDS
1941WB_END
1942
1943WB_ENTRY(jboolean, WB_IsJavaHeapArchiveSupported(JNIEnv* env))
1944 return HeapShared::is_heap_object_archiving_allowed();
1945WB_END
1946
1947
1948WB_ENTRY(jboolean, WB_IsJFRIncludedInVmBuild(JNIEnv* env))
1949#if INCLUDE_JFR
1950 return true;
1951#else
1952 return false;
1953#endif // INCLUDE_JFR
1954WB_END
1955
1956#if INCLUDE_CDS
1957
1958WB_ENTRY(jint, WB_GetOffsetForName(JNIEnv* env, jobject o, jstring name))
1959 ResourceMark rm;
1960 char* c_name = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(name));
1961 int result = CDSOffsets::find_offset(c_name);
1962 return (jint)result;
1963WB_END
1964
1965#endif // INCLUDE_CDS
1966
1967WB_ENTRY(jint, WB_HandshakeWalkStack(JNIEnv* env, jobject wb, jobject thread_handle, jboolean all_threads))
1968 class TraceSelfClosure : public ThreadClosure {
1969 jint _num_threads_completed;
1970
1971 void do_thread(Thread* th) {
1972 assert(th->is_Java_thread(), "sanity");
1973 JavaThread* jt = (JavaThread*)th;
1974 ResourceMark rm;
1975
1976 jt->print_on(tty);
1977 jt->print_stack_on(tty);
1978 tty->cr();
1979 Atomic::inc(&_num_threads_completed);
1980 }
1981
1982 public:
1983 TraceSelfClosure() : _num_threads_completed(0) {}
1984
1985 jint num_threads_completed() const { return _num_threads_completed; }
1986 };
1987 TraceSelfClosure tsc;
1988
1989 if (all_threads) {
1990 Handshake::execute(&tsc);
1991 } else {
1992 oop thread_oop = JNIHandles::resolve(thread_handle);
1993 if (thread_oop != NULL) {
1994 JavaThread* target = java_lang_Thread::thread(thread_oop);
1995 Handshake::execute(&tsc, target);
1996 }
1997 }
1998 return tsc.num_threads_completed();
1999WB_END
2000
2001//Some convenience methods to deal with objects from java
2002int WhiteBox::offset_for_field(const char* field_name, oop object,
2003 Symbol* signature_symbol) {
2004 assert(field_name != NULL && strlen(field_name) > 0, "Field name not valid");
2005 Thread* THREAD = Thread::current();
2006
2007 //Get the class of our object
2008 Klass* arg_klass = object->klass();
2009 //Turn it into an instance-klass
2010 InstanceKlass* ik = InstanceKlass::cast(arg_klass);
2011
2012 //Create symbols to look for in the class
2013 TempNewSymbol name_symbol = SymbolTable::new_symbol(field_name);
2014
2015 //To be filled in with an offset of the field we're looking for
2016 fieldDescriptor fd;
2017
2018 Klass* res = ik->find_field(name_symbol, signature_symbol, &fd);
2019 if (res == NULL) {
2020 tty->print_cr("Invalid layout of %s at %s", ik->external_name(),
2021 name_symbol->as_C_string());
2022 vm_exit_during_initialization("Invalid layout of preloaded class: use -Xlog:class+load=info to see the origin of the problem class");
2023 }
2024
2025 //fetch the field at the offset we've found
2026 int dest_offset = fd.offset();
2027
2028 return dest_offset;
2029}
2030
2031
2032const char* WhiteBox::lookup_jstring(const char* field_name, oop object) {
2033 int offset = offset_for_field(field_name, object,
2034 vmSymbols::string_signature());
2035 oop string = object->obj_field(offset);
2036 if (string == NULL) {
2037 return NULL;
2038 }
2039 const char* ret = java_lang_String::as_utf8_string(string);
2040 return ret;
2041}
2042
2043bool WhiteBox::lookup_bool(const char* field_name, oop object) {
2044 int offset =
2045 offset_for_field(field_name, object, vmSymbols::bool_signature());
2046 bool ret = (object->bool_field(offset) == JNI_TRUE);
2047 return ret;
2048}
2049
2050void WhiteBox::register_methods(JNIEnv* env, jclass wbclass, JavaThread* thread, JNINativeMethod* method_array, int method_count) {
2051 ResourceMark rm;
2052 ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
2053
2054 // one by one registration natives for exception catching
2055 jclass no_such_method_error_klass = env->FindClass(vmSymbols::java_lang_NoSuchMethodError()->as_C_string());
2056 CHECK_JNI_EXCEPTION(env);
2057 for (int i = 0, n = method_count; i < n; ++i) {
2058 // Skip dummy entries
2059 if (method_array[i].fnPtr == NULL) continue;
2060 if (env->RegisterNatives(wbclass, &method_array[i], 1) != 0) {
2061 jthrowable throwable_obj = env->ExceptionOccurred();
2062 if (throwable_obj != NULL) {
2063 env->ExceptionClear();
2064 if (env->IsInstanceOf(throwable_obj, no_such_method_error_klass)) {
2065 // NoSuchMethodError is thrown when a method can't be found or a method is not native.
2066 // Ignoring the exception since it is not preventing use of other WhiteBox methods.
2067 tty->print_cr("Warning: 'NoSuchMethodError' on register of sun.hotspot.WhiteBox::%s%s",
2068 method_array[i].name, method_array[i].signature);
2069 }
2070 } else {
2071 // Registration failed unexpectedly.
2072 tty->print_cr("Warning: unexpected error on register of sun.hotspot.WhiteBox::%s%s. All methods will be unregistered",
2073 method_array[i].name, method_array[i].signature);
2074 env->UnregisterNatives(wbclass);
2075 break;
2076 }
2077 }
2078 }
2079}
2080
2081WB_ENTRY(jint, WB_AddCompilerDirective(JNIEnv* env, jobject o, jstring compDirect))
2082 // can't be in VM when we call JNI
2083 ThreadToNativeFromVM ttnfv(thread);
2084 const char* dir = env->GetStringUTFChars(compDirect, NULL);
2085 CHECK_JNI_EXCEPTION_(env, 0);
2086 int ret;
2087 {
2088 ThreadInVMfromNative ttvfn(thread); // back to VM
2089 ret = DirectivesParser::parse_string(dir, tty);
2090 }
2091 env->ReleaseStringUTFChars(compDirect, dir);
2092 // -1 for error parsing directive. Return 0 as number of directives added.
2093 if (ret == -1) {
2094 ret = 0;
2095 }
2096 return (jint) ret;
2097WB_END
2098
2099WB_ENTRY(void, WB_RemoveCompilerDirective(JNIEnv* env, jobject o, jint count))
2100 DirectivesStack::pop(count);
2101WB_END
2102
2103// Checks that the library libfile has the noexecstack bit set.
2104WB_ENTRY(jboolean, WB_CheckLibSpecifiesNoexecstack(JNIEnv* env, jobject o, jstring libfile))
2105 jboolean ret = false;
2106#ifdef LINUX
2107 // Can't be in VM when we call JNI.
2108 ThreadToNativeFromVM ttnfv(thread);
2109 const char* lf = env->GetStringUTFChars(libfile, NULL);
2110 CHECK_JNI_EXCEPTION_(env, 0);
2111 ret = (jboolean) ElfFile::specifies_noexecstack(lf);
2112 env->ReleaseStringUTFChars(libfile, lf);
2113#endif
2114 return ret;
2115WB_END
2116
2117WB_ENTRY(jboolean, WB_IsContainerized(JNIEnv* env, jobject o))
2118 LINUX_ONLY(return OSContainer::is_containerized();)
2119 return false;
2120WB_END
2121
2122WB_ENTRY(void, WB_PrintOsInfo(JNIEnv* env, jobject o))
2123 os::print_os_info(tty);
2124WB_END
2125
2126// Elf decoder
2127WB_ENTRY(void, WB_DisableElfSectionCache(JNIEnv* env))
2128#if !defined(_WINDOWS) && !defined(__APPLE__) && !defined(_AIX)
2129 ElfFile::_do_not_cache_elf_section = true;
2130#endif
2131WB_END
2132
2133WB_ENTRY(jlong, WB_ResolvedMethodItemsCount(JNIEnv* env, jobject o))
2134 return (jlong) ResolvedMethodTable::items_count();
2135WB_END
2136
2137WB_ENTRY(jint, WB_ProtectionDomainRemovedCount(JNIEnv* env, jobject o))
2138 return (jint) SystemDictionary::pd_cache_table()->removed_entries_count();
2139WB_END
2140
2141WB_ENTRY(jint, WB_AotLibrariesCount(JNIEnv* env, jobject o))
2142 jint result = 0;
2143#if INCLUDE_AOT
2144 result = (jint) AOTLoader::heaps_count();
2145#endif
2146 return result;
2147WB_END
2148
2149#define CC (char*)
2150
2151static JNINativeMethod methods[] = {
2152 {CC"getObjectAddress0", CC"(Ljava/lang/Object;)J", (void*)&WB_GetObjectAddress },
2153 {CC"getObjectSize0", CC"(Ljava/lang/Object;)J", (void*)&WB_GetObjectSize },
2154 {CC"isObjectInOldGen0", CC"(Ljava/lang/Object;)Z", (void*)&WB_isObjectInOldGen },
2155 {CC"getHeapOopSize", CC"()I", (void*)&WB_GetHeapOopSize },
2156 {CC"getVMPageSize", CC"()I", (void*)&WB_GetVMPageSize },
2157 {CC"getVMAllocationGranularity", CC"()J", (void*)&WB_GetVMAllocationGranularity },
2158 {CC"getVMLargePageSize", CC"()J", (void*)&WB_GetVMLargePageSize},
2159 {CC"getHeapSpaceAlignment", CC"()J", (void*)&WB_GetHeapSpaceAlignment},
2160 {CC"getHeapAlignment", CC"()J", (void*)&WB_GetHeapAlignment},
2161 {CC"isClassAlive0", CC"(Ljava/lang/String;)Z", (void*)&WB_IsClassAlive },
2162 {CC"getSymbolRefcount", CC"(Ljava/lang/String;)I", (void*)&WB_GetSymbolRefcount },
2163 {CC"parseCommandLine0",
2164 CC"(Ljava/lang/String;C[Lsun/hotspot/parser/DiagnosticCommand;)[Ljava/lang/Object;",
2165 (void*) &WB_ParseCommandLine
2166 },
2167 {CC"addToBootstrapClassLoaderSearch0", CC"(Ljava/lang/String;)V",
2168 (void*)&WB_AddToBootstrapClassLoaderSearch},
2169 {CC"addToSystemClassLoaderSearch0", CC"(Ljava/lang/String;)V",
2170 (void*)&WB_AddToSystemClassLoaderSearch},
2171 {CC"getCompressedOopsMaxHeapSize", CC"()J",
2172 (void*)&WB_GetCompressedOopsMaxHeapSize},
2173 {CC"printHeapSizes", CC"()V", (void*)&WB_PrintHeapSizes },
2174 {CC"runMemoryUnitTests", CC"()V", (void*)&WB_RunMemoryUnitTests},
2175 {CC"readFromNoaccessArea",CC"()V", (void*)&WB_ReadFromNoaccessArea},
2176 {CC"stressVirtualSpaceResize",CC"(JJJ)I", (void*)&WB_StressVirtualSpaceResize},
2177#if INCLUDE_CDS
2178 {CC"getOffsetForName0", CC"(Ljava/lang/String;)I", (void*)&WB_GetOffsetForName},
2179#endif
2180#if INCLUDE_G1GC
2181 {CC"g1InConcurrentMark", CC"()Z", (void*)&WB_G1InConcurrentMark},
2182 {CC"g1IsHumongous0", CC"(Ljava/lang/Object;)Z", (void*)&WB_G1IsHumongous },
2183 {CC"g1BelongsToHumongousRegion0", CC"(J)Z", (void*)&WB_G1BelongsToHumongousRegion},
2184 {CC"g1BelongsToFreeRegion0", CC"(J)Z", (void*)&WB_G1BelongsToFreeRegion},
2185 {CC"g1NumMaxRegions", CC"()J", (void*)&WB_G1NumMaxRegions },
2186 {CC"g1NumFreeRegions", CC"()J", (void*)&WB_G1NumFreeRegions },
2187 {CC"g1RegionSize", CC"()I", (void*)&WB_G1RegionSize },
2188 {CC"g1StartConcMarkCycle", CC"()Z", (void*)&WB_G1StartMarkCycle },
2189 {CC"g1AuxiliaryMemoryUsage", CC"()Ljava/lang/management/MemoryUsage;",
2190 (void*)&WB_G1AuxiliaryMemoryUsage },
2191 {CC"g1GetMixedGCInfo", CC"(I)[J", (void*)&WB_G1GetMixedGCInfo },
2192#endif // INCLUDE_G1GC
2193#if INCLUDE_G1GC || INCLUDE_PARALLELGC
2194 {CC"dramReservedStart", CC"()J", (void*)&WB_DramReservedStart },
2195 {CC"dramReservedEnd", CC"()J", (void*)&WB_DramReservedEnd },
2196 {CC"nvdimmReservedStart", CC"()J", (void*)&WB_NvdimmReservedStart },
2197 {CC"nvdimmReservedEnd", CC"()J", (void*)&WB_NvdimmReservedEnd },
2198#endif // INCLUDE_G1GC || INCLUDE_PARALLELGC
2199#if INCLUDE_PARALLELGC
2200 {CC"psVirtualSpaceAlignment",CC"()J", (void*)&WB_PSVirtualSpaceAlignment},
2201 {CC"psHeapGenerationAlignment",CC"()J", (void*)&WB_PSHeapGenerationAlignment},
2202#endif
2203#if INCLUDE_NMT
2204 {CC"NMTMalloc", CC"(J)J", (void*)&WB_NMTMalloc },
2205 {CC"NMTMallocWithPseudoStack", CC"(JI)J", (void*)&WB_NMTMallocWithPseudoStack},
2206 {CC"NMTMallocWithPseudoStackAndType", CC"(JII)J", (void*)&WB_NMTMallocWithPseudoStackAndType},
2207 {CC"NMTFree", CC"(J)V", (void*)&WB_NMTFree },
2208 {CC"NMTReserveMemory", CC"(J)J", (void*)&WB_NMTReserveMemory },
2209 {CC"NMTAttemptReserveMemoryAt", CC"(JJ)J", (void*)&WB_NMTAttemptReserveMemoryAt },
2210 {CC"NMTCommitMemory", CC"(JJ)V", (void*)&WB_NMTCommitMemory },
2211 {CC"NMTUncommitMemory", CC"(JJ)V", (void*)&WB_NMTUncommitMemory },
2212 {CC"NMTReleaseMemory", CC"(JJ)V", (void*)&WB_NMTReleaseMemory },
2213 {CC"NMTChangeTrackingLevel", CC"()Z", (void*)&WB_NMTChangeTrackingLevel},
2214 {CC"NMTGetHashSize", CC"()I", (void*)&WB_NMTGetHashSize },
2215#endif // INCLUDE_NMT
2216 {CC"deoptimizeFrames", CC"(Z)I", (void*)&WB_DeoptimizeFrames },
2217 {CC"deoptimizeAll", CC"()V", (void*)&WB_DeoptimizeAll },
2218 {CC"deoptimizeMethod0", CC"(Ljava/lang/reflect/Executable;Z)I",
2219 (void*)&WB_DeoptimizeMethod },
2220 {CC"isMethodCompiled0", CC"(Ljava/lang/reflect/Executable;Z)Z",
2221 (void*)&WB_IsMethodCompiled },
2222 {CC"isMethodCompilable0", CC"(Ljava/lang/reflect/Executable;IZ)Z",
2223 (void*)&WB_IsMethodCompilable},
2224 {CC"isMethodQueuedForCompilation0",
2225 CC"(Ljava/lang/reflect/Executable;)Z", (void*)&WB_IsMethodQueuedForCompilation},
2226 {CC"isIntrinsicAvailable0",
2227 CC"(Ljava/lang/reflect/Executable;Ljava/lang/reflect/Executable;I)Z",
2228 (void*)&WB_IsIntrinsicAvailable},
2229 {CC"makeMethodNotCompilable0",
2230 CC"(Ljava/lang/reflect/Executable;IZ)V", (void*)&WB_MakeMethodNotCompilable},
2231 {CC"testSetDontInlineMethod0",
2232 CC"(Ljava/lang/reflect/Executable;Z)Z", (void*)&WB_TestSetDontInlineMethod},
2233 {CC"getMethodCompilationLevel0",
2234 CC"(Ljava/lang/reflect/Executable;Z)I", (void*)&WB_GetMethodCompilationLevel},
2235 {CC"getMethodEntryBci0",
2236 CC"(Ljava/lang/reflect/Executable;)I", (void*)&WB_GetMethodEntryBci},
2237 {CC"getCompileQueueSize",
2238 CC"(I)I", (void*)&WB_GetCompileQueueSize},
2239 {CC"testSetForceInlineMethod0",
2240 CC"(Ljava/lang/reflect/Executable;Z)Z", (void*)&WB_TestSetForceInlineMethod},
2241 {CC"enqueueMethodForCompilation0",
2242 CC"(Ljava/lang/reflect/Executable;II)Z", (void*)&WB_EnqueueMethodForCompilation},
2243 {CC"enqueueInitializerForCompilation0",
2244 CC"(Ljava/lang/Class;I)Z", (void*)&WB_EnqueueInitializerForCompilation},
2245 {CC"markMethodProfiled",
2246 CC"(Ljava/lang/reflect/Executable;)V", (void*)&WB_MarkMethodProfiled},
2247 {CC"clearMethodState0",
2248 CC"(Ljava/lang/reflect/Executable;)V", (void*)&WB_ClearMethodState},
2249 {CC"lockCompilation", CC"()V", (void*)&WB_LockCompilation},
2250 {CC"unlockCompilation", CC"()V", (void*)&WB_UnlockCompilation},
2251 {CC"matchesMethod",
2252 CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)I",
2253 (void*)&WB_MatchesMethod},
2254 {CC"matchesInline",
2255 CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)I",
2256 (void*)&WB_MatchesInline},
2257 {CC"shouldPrintAssembly",
2258 CC"(Ljava/lang/reflect/Executable;I)Z",
2259 (void*)&WB_ShouldPrintAssembly},
2260
2261 {CC"isConstantVMFlag", CC"(Ljava/lang/String;)Z", (void*)&WB_IsConstantVMFlag},
2262 {CC"isLockedVMFlag", CC"(Ljava/lang/String;)Z", (void*)&WB_IsLockedVMFlag},
2263 {CC"setBooleanVMFlag", CC"(Ljava/lang/String;Z)V",(void*)&WB_SetBooleanVMFlag},
2264 {CC"setIntVMFlag", CC"(Ljava/lang/String;J)V",(void*)&WB_SetIntVMFlag},
2265 {CC"setUintVMFlag", CC"(Ljava/lang/String;J)V",(void*)&WB_SetUintVMFlag},
2266 {CC"setIntxVMFlag", CC"(Ljava/lang/String;J)V",(void*)&WB_SetIntxVMFlag},
2267 {CC"setUintxVMFlag", CC"(Ljava/lang/String;J)V",(void*)&WB_SetUintxVMFlag},
2268 {CC"setUint64VMFlag", CC"(Ljava/lang/String;J)V",(void*)&WB_SetUint64VMFlag},
2269 {CC"setSizeTVMFlag", CC"(Ljava/lang/String;J)V",(void*)&WB_SetSizeTVMFlag},
2270 {CC"setDoubleVMFlag", CC"(Ljava/lang/String;D)V",(void*)&WB_SetDoubleVMFlag},
2271 {CC"setStringVMFlag", CC"(Ljava/lang/String;Ljava/lang/String;)V",
2272 (void*)&WB_SetStringVMFlag},
2273 {CC"getBooleanVMFlag", CC"(Ljava/lang/String;)Ljava/lang/Boolean;",
2274 (void*)&WB_GetBooleanVMFlag},
2275 {CC"getIntVMFlag", CC"(Ljava/lang/String;)Ljava/lang/Long;",
2276 (void*)&WB_GetIntVMFlag},
2277 {CC"getUintVMFlag", CC"(Ljava/lang/String;)Ljava/lang/Long;",
2278 (void*)&WB_GetUintVMFlag},
2279 {CC"getIntxVMFlag", CC"(Ljava/lang/String;)Ljava/lang/Long;",
2280 (void*)&WB_GetIntxVMFlag},
2281 {CC"getUintxVMFlag", CC"(Ljava/lang/String;)Ljava/lang/Long;",
2282 (void*)&WB_GetUintxVMFlag},
2283 {CC"getUint64VMFlag", CC"(Ljava/lang/String;)Ljava/lang/Long;",
2284 (void*)&WB_GetUint64VMFlag},
2285 {CC"getSizeTVMFlag", CC"(Ljava/lang/String;)Ljava/lang/Long;",
2286 (void*)&WB_GetSizeTVMFlag},
2287 {CC"getDoubleVMFlag", CC"(Ljava/lang/String;)Ljava/lang/Double;",
2288 (void*)&WB_GetDoubleVMFlag},
2289 {CC"getStringVMFlag", CC"(Ljava/lang/String;)Ljava/lang/String;",
2290 (void*)&WB_GetStringVMFlag},
2291 {CC"isInStringTable", CC"(Ljava/lang/String;)Z", (void*)&WB_IsInStringTable },
2292 {CC"fullGC", CC"()V", (void*)&WB_FullGC },
2293 {CC"youngGC", CC"()V", (void*)&WB_YoungGC },
2294 {CC"readReservedMemory", CC"()V", (void*)&WB_ReadReservedMemory },
2295 {CC"allocateMetaspace",
2296 CC"(Ljava/lang/ClassLoader;J)J", (void*)&WB_AllocateMetaspace },
2297 {CC"freeMetaspace",
2298 CC"(Ljava/lang/ClassLoader;JJ)V", (void*)&WB_FreeMetaspace },
2299 {CC"incMetaspaceCapacityUntilGC", CC"(J)J", (void*)&WB_IncMetaspaceCapacityUntilGC },
2300 {CC"metaspaceCapacityUntilGC", CC"()J", (void*)&WB_MetaspaceCapacityUntilGC },
2301 {CC"metaspaceShouldConcurrentCollect", CC"()Z", (void*)&WB_MetaspaceShouldConcurrentCollect },
2302 {CC"metaspaceReserveAlignment", CC"()J", (void*)&WB_MetaspaceReserveAlignment },
2303 {CC"getCPUFeatures", CC"()Ljava/lang/String;", (void*)&WB_GetCPUFeatures },
2304 {CC"getNMethod0", CC"(Ljava/lang/reflect/Executable;Z)[Ljava/lang/Object;",
2305 (void*)&WB_GetNMethod },
2306 {CC"forceNMethodSweep", CC"()V", (void*)&WB_ForceNMethodSweep },
2307 {CC"allocateCodeBlob", CC"(II)J", (void*)&WB_AllocateCodeBlob },
2308 {CC"freeCodeBlob", CC"(J)V", (void*)&WB_FreeCodeBlob },
2309 {CC"getCodeHeapEntries", CC"(I)[Ljava/lang/Object;",(void*)&WB_GetCodeHeapEntries },
2310 {CC"getCompilationActivityMode",
2311 CC"()I", (void*)&WB_GetCompilationActivityMode},
2312 {CC"getMethodData0", CC"(Ljava/lang/reflect/Executable;)J",
2313 (void*)&WB_GetMethodData },
2314 {CC"getCodeBlob", CC"(J)[Ljava/lang/Object;",(void*)&WB_GetCodeBlob },
2315 {CC"getThreadStackSize", CC"()J", (void*)&WB_GetThreadStackSize },
2316 {CC"getThreadRemainingStackSize", CC"()J", (void*)&WB_GetThreadRemainingStackSize },
2317 {CC"DefineModule", CC"(Ljava/lang/Object;ZLjava/lang/String;Ljava/lang/String;[Ljava/lang/Object;)V",
2318 (void*)&WB_DefineModule },
2319 {CC"AddModuleExports", CC"(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)V",
2320 (void*)&WB_AddModuleExports },
2321 {CC"AddReadsModule", CC"(Ljava/lang/Object;Ljava/lang/Object;)V",
2322 (void*)&WB_AddReadsModule },
2323 {CC"AddModuleExportsToAllUnnamed", CC"(Ljava/lang/Object;Ljava/lang/String;)V",
2324 (void*)&WB_AddModuleExportsToAllUnnamed },
2325 {CC"AddModuleExportsToAll", CC"(Ljava/lang/Object;Ljava/lang/String;)V",
2326 (void*)&WB_AddModuleExportsToAll },
2327 {CC"assertMatchingSafepointCalls", CC"(ZZ)V", (void*)&WB_AssertMatchingSafepointCalls },
2328 {CC"isMonitorInflated0", CC"(Ljava/lang/Object;)Z", (void*)&WB_IsMonitorInflated },
2329 {CC"forceSafepoint", CC"()V", (void*)&WB_ForceSafepoint },
2330 {CC"getConstantPool0", CC"(Ljava/lang/Class;)J", (void*)&WB_GetConstantPool },
2331 {CC"getConstantPoolCacheIndexTag0", CC"()I", (void*)&WB_GetConstantPoolCacheIndexTag},
2332 {CC"getConstantPoolCacheLength0", CC"(Ljava/lang/Class;)I", (void*)&WB_GetConstantPoolCacheLength},
2333 {CC"remapInstructionOperandFromCPCache0",
2334 CC"(Ljava/lang/Class;I)I", (void*)&WB_ConstantPoolRemapInstructionOperandFromCache},
2335 {CC"encodeConstantPoolIndyIndex0",
2336 CC"(I)I", (void*)&WB_ConstantPoolEncodeIndyIndex},
2337 {CC"getMethodBooleanOption",
2338 CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)Ljava/lang/Boolean;",
2339 (void*)&WB_GetMethodBooleaneOption},
2340 {CC"getMethodIntxOption",
2341 CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)Ljava/lang/Long;",
2342 (void*)&WB_GetMethodIntxOption},
2343 {CC"getMethodUintxOption",
2344 CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)Ljava/lang/Long;",
2345 (void*)&WB_GetMethodUintxOption},
2346 {CC"getMethodDoubleOption",
2347 CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)Ljava/lang/Double;",
2348 (void*)&WB_GetMethodDoubleOption},
2349 {CC"getMethodStringOption",
2350 CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)Ljava/lang/String;",
2351 (void*)&WB_GetMethodStringOption},
2352 {CC"getDefaultArchivePath", CC"()Ljava/lang/String;",
2353 (void*)&WB_GetDefaultArchivePath},
2354 {CC"isSharingEnabled", CC"()Z", (void*)&WB_IsSharingEnabled},
2355 {CC"isShared", CC"(Ljava/lang/Object;)Z", (void*)&WB_IsShared },
2356 {CC"isSharedClass", CC"(Ljava/lang/Class;)Z", (void*)&WB_IsSharedClass },
2357 {CC"areSharedStringsIgnored", CC"()Z", (void*)&WB_AreSharedStringsIgnored },
2358 {CC"getResolvedReferences", CC"(Ljava/lang/Class;)Ljava/lang/Object;", (void*)&WB_GetResolvedReferences},
2359 {CC"linkClass", CC"(Ljava/lang/Class;)V", (void*)&WB_LinkClass},
2360 {CC"areOpenArchiveHeapObjectsMapped", CC"()Z", (void*)&WB_AreOpenArchiveHeapObjectsMapped},
2361 {CC"isCDSIncludedInVmBuild", CC"()Z", (void*)&WB_IsCDSIncludedInVmBuild },
2362 {CC"isJFRIncludedInVmBuild", CC"()Z", (void*)&WB_IsJFRIncludedInVmBuild },
2363 {CC"isJavaHeapArchiveSupported", CC"()Z", (void*)&WB_IsJavaHeapArchiveSupported },
2364 {CC"cdsMemoryMappingFailed", CC"()Z", (void*)&WB_CDSMemoryMappingFailed },
2365
2366 {CC"clearInlineCaches0", CC"(Z)V", (void*)&WB_ClearInlineCaches },
2367 {CC"handshakeWalkStack", CC"(Ljava/lang/Thread;Z)I", (void*)&WB_HandshakeWalkStack },
2368 {CC"addCompilerDirective", CC"(Ljava/lang/String;)I",
2369 (void*)&WB_AddCompilerDirective },
2370 {CC"removeCompilerDirective", CC"(I)V", (void*)&WB_RemoveCompilerDirective },
2371 {CC"isGCSupported", CC"(I)Z", (void*)&WB_IsGCSupported},
2372 {CC"isGCSelected", CC"(I)Z", (void*)&WB_IsGCSelected},
2373 {CC"isGCSelectedErgonomically", CC"()Z", (void*)&WB_IsGCSelectedErgonomically},
2374 {CC"supportsConcurrentGCPhaseControl", CC"()Z", (void*)&WB_SupportsConcurrentGCPhaseControl},
2375 {CC"requestConcurrentGCPhase0", CC"(Ljava/lang/String;)Z",
2376 (void*)&WB_RequestConcurrentGCPhase},
2377 {CC"checkLibSpecifiesNoexecstack", CC"(Ljava/lang/String;)Z",
2378 (void*)&WB_CheckLibSpecifiesNoexecstack},
2379 {CC"isContainerized", CC"()Z", (void*)&WB_IsContainerized },
2380 {CC"printOsInfo", CC"()V", (void*)&WB_PrintOsInfo },
2381 {CC"disableElfSectionCache", CC"()V", (void*)&WB_DisableElfSectionCache },
2382 {CC"resolvedMethodItemsCount", CC"()J", (void*)&WB_ResolvedMethodItemsCount },
2383 {CC"protectionDomainRemovedCount", CC"()I", (void*)&WB_ProtectionDomainRemovedCount },
2384 {CC"aotLibrariesCount", CC"()I", (void*)&WB_AotLibrariesCount },
2385};
2386
2387
2388#undef CC
2389
2390JVM_ENTRY(void, JVM_RegisterWhiteBoxMethods(JNIEnv* env, jclass wbclass))
2391 {
2392 if (WhiteBoxAPI) {
2393 // Make sure that wbclass is loaded by the null classloader
2394 InstanceKlass* ik = InstanceKlass::cast(JNIHandles::resolve(wbclass)->klass());
2395 Handle loader(THREAD, ik->class_loader());
2396 if (loader.is_null()) {
2397 WhiteBox::register_methods(env, wbclass, thread, methods, sizeof(methods) / sizeof(methods[0]));
2398 WhiteBox::set_used();
2399 }
2400 }
2401 }
2402JVM_END
2403