rev 8048 : 8058354: SPECjvm2008-Derby -2.7% performance regression on Solaris-X64 starting with 9-b29
Summary: Allow partial use of large pages for auxiliary data structures in G1.
Reviewed-by: jmasa
1 /*
2 * Copyright (c) 2012, 2015, 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/classLoaderData.hpp"
30 #include "classfile/stringTable.hpp"
31 #include "code/codeCache.hpp"
32 #include "jvmtifiles/jvmtiEnv.hpp"
33 #include "memory/metadataFactory.hpp"
34 #include "memory/universe.hpp"
35 #include "oops/oop.inline.hpp"
36 #include "prims/wbtestmethods/parserTests.hpp"
37 #include "prims/whitebox.hpp"
38 #include "runtime/arguments.hpp"
39 #include "runtime/compilationPolicy.hpp"
40 #include "runtime/deoptimization.hpp"
41 #include "runtime/interfaceSupport.hpp"
42 #include "runtime/os.hpp"
43 #include "runtime/sweeper.hpp"
44 #include "runtime/javaCalls.hpp"
45 #include "runtime/thread.hpp"
46 #include "runtime/vm_version.hpp"
47 #include "utilities/array.hpp"
48 #include "utilities/debug.hpp"
49 #include "utilities/exceptions.hpp"
50 #include "utilities/macros.hpp"
51 #if INCLUDE_ALL_GCS
52 #include "gc_implementation/parallelScavenge/parallelScavengeHeap.inline.hpp"
53 #include "gc_implementation/g1/concurrentMark.hpp"
54 #include "gc_implementation/g1/concurrentMarkThread.hpp"
55 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
56 #include "gc_implementation/g1/heapRegionRemSet.hpp"
57 #endif // INCLUDE_ALL_GCS
58 #if INCLUDE_NMT
59 #include "services/mallocSiteTable.hpp"
60 #include "services/memTracker.hpp"
61 #include "utilities/nativeCallStack.hpp"
62 #endif // INCLUDE_NMT
63
64
65 PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
66
67 #define SIZE_T_MAX_VALUE ((size_t) -1)
68
69 bool WhiteBox::_used = false;
70 volatile bool WhiteBox::compilation_locked = false;
71
72 class VM_WhiteBoxOperation : public VM_Operation {
73 public:
74 VM_WhiteBoxOperation() { }
75 VMOp_Type type() const { return VMOp_WhiteBoxOperation; }
76 bool allow_nested_vm_operations() const { return true; }
77 };
78
79
80 WB_ENTRY(jlong, WB_GetObjectAddress(JNIEnv* env, jobject o, jobject obj))
81 return (jlong)(void*)JNIHandles::resolve(obj);
82 WB_END
83
84 WB_ENTRY(jint, WB_GetHeapOopSize(JNIEnv* env, jobject o))
85 return heapOopSize;
86 WB_END
87
88 WB_ENTRY(jint, WB_GetVMPageSize(JNIEnv* env, jobject o))
89 return os::vm_page_size();
90 WB_END
91
92 class WBIsKlassAliveClosure : public KlassClosure {
93 Symbol* _name;
94 bool _found;
95 public:
96 WBIsKlassAliveClosure(Symbol* name) : _name(name), _found(false) {}
97
98 void do_klass(Klass* k) {
99 if (_found) return;
100 Symbol* ksym = k->name();
101 if (ksym->fast_compare(_name) == 0) {
102 _found = true;
103 }
104 }
105
106 bool found() const {
107 return _found;
108 }
109 };
110
111 WB_ENTRY(jboolean, WB_IsClassAlive(JNIEnv* env, jobject target, jstring name))
112 Handle h_name = JNIHandles::resolve(name);
113 if (h_name.is_null()) return false;
114 Symbol* sym = java_lang_String::as_symbol(h_name, CHECK_false);
115 TempNewSymbol tsym(sym); // Make sure to decrement reference count on sym on return
116
117 WBIsKlassAliveClosure closure(sym);
118 ClassLoaderDataGraph::classes_do(&closure);
119
120 return closure.found();
121 WB_END
122
123 WB_ENTRY(void, WB_AddToBootstrapClassLoaderSearch(JNIEnv* env, jobject o, jstring segment)) {
124 #if INCLUDE_JVMTI
125 ResourceMark rm;
126 const char* seg = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(segment));
127 JvmtiEnv* jvmti_env = JvmtiEnv::create_a_jvmti(JVMTI_VERSION);
128 jvmtiError err = jvmti_env->AddToBootstrapClassLoaderSearch(seg);
129 assert(err == JVMTI_ERROR_NONE, "must not fail");
130 #endif
131 }
132 WB_END
133
134 WB_ENTRY(void, WB_AddToSystemClassLoaderSearch(JNIEnv* env, jobject o, jstring segment)) {
135 #if INCLUDE_JVMTI
136 ResourceMark rm;
137 const char* seg = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(segment));
138 JvmtiEnv* jvmti_env = JvmtiEnv::create_a_jvmti(JVMTI_VERSION);
139 jvmtiError err = jvmti_env->AddToSystemClassLoaderSearch(seg);
140 assert(err == JVMTI_ERROR_NONE, "must not fail");
141 #endif
142 }
143 WB_END
144
145
146 WB_ENTRY(jlong, WB_GetCompressedOopsMaxHeapSize(JNIEnv* env, jobject o)) {
147 return (jlong)Arguments::max_heap_for_compressed_oops();
148 }
149 WB_END
150
151 WB_ENTRY(void, WB_PrintHeapSizes(JNIEnv* env, jobject o)) {
152 CollectorPolicy * p = Universe::heap()->collector_policy();
153 gclog_or_tty->print_cr("Minimum heap "SIZE_FORMAT" Initial heap "
154 SIZE_FORMAT" Maximum heap "SIZE_FORMAT" Space alignment "SIZE_FORMAT" Heap alignment "SIZE_FORMAT,
155 p->min_heap_byte_size(), p->initial_heap_byte_size(), p->max_heap_byte_size(),
156 p->space_alignment(), p->heap_alignment());
157 }
158 WB_END
159
160 #ifndef PRODUCT
161 // Forward declaration
162 void TestReservedSpace_test();
163 void TestReserveMemorySpecial_test();
164 void TestVirtualSpace_test();
165 void TestMetaspaceAux_test();
166 #endif
167
168 WB_ENTRY(void, WB_RunMemoryUnitTests(JNIEnv* env, jobject o))
169 #ifndef PRODUCT
170 TestReservedSpace_test();
171 TestReserveMemorySpecial_test();
172 TestVirtualSpace_test();
173 TestMetaspaceAux_test();
174 #endif
175 WB_END
176
177 WB_ENTRY(void, WB_ReadFromNoaccessArea(JNIEnv* env, jobject o))
178 size_t granularity = os::vm_allocation_granularity();
179 ReservedHeapSpace rhs(100 * granularity, granularity, false);
180 VirtualSpace vs;
181 vs.initialize(rhs, 50 * granularity);
182
183 // Check if constraints are complied
184 if (!( UseCompressedOops && rhs.base() != NULL &&
185 Universe::narrow_oop_base() != NULL &&
186 Universe::narrow_oop_use_implicit_null_checks() )) {
187 tty->print_cr("WB_ReadFromNoaccessArea method is useless:\n "
188 "\tUseCompressedOops is %d\n"
189 "\trhs.base() is "PTR_FORMAT"\n"
190 "\tUniverse::narrow_oop_base() is "PTR_FORMAT"\n"
191 "\tUniverse::narrow_oop_use_implicit_null_checks() is %d",
192 UseCompressedOops,
193 rhs.base(),
194 Universe::narrow_oop_base(),
195 Universe::narrow_oop_use_implicit_null_checks());
196 return;
197 }
198 tty->print_cr("Reading from no access area... ");
199 tty->print_cr("*(vs.low_boundary() - rhs.noaccess_prefix() / 2 ) = %c",
200 *(vs.low_boundary() - rhs.noaccess_prefix() / 2 ));
201 WB_END
202
203 static jint wb_stress_virtual_space_resize(size_t reserved_space_size,
204 size_t magnitude, size_t iterations) {
205 size_t granularity = os::vm_allocation_granularity();
206 ReservedHeapSpace rhs(reserved_space_size * granularity, granularity, false);
207 VirtualSpace vs;
208 if (!vs.initialize(rhs, 0)) {
209 tty->print_cr("Failed to initialize VirtualSpace. Can't proceed.");
210 return 3;
211 }
212
213 long seed = os::random();
214 tty->print_cr("Random seed is %ld", seed);
215 os::init_random(seed);
216
217 for (size_t i = 0; i < iterations; i++) {
218
219 // Whether we will shrink or grow
220 bool shrink = os::random() % 2L == 0;
221
222 // Get random delta to resize virtual space
223 size_t delta = (size_t)os::random() % magnitude;
224
225 // If we are about to shrink virtual space below zero, then expand instead
226 if (shrink && vs.committed_size() < delta) {
227 shrink = false;
228 }
229
230 // Resizing by delta
231 if (shrink) {
232 vs.shrink_by(delta);
233 } else {
234 // If expanding fails expand_by will silently return false
235 vs.expand_by(delta, true);
236 }
237 }
238 return 0;
239 }
240
241 WB_ENTRY(jint, WB_StressVirtualSpaceResize(JNIEnv* env, jobject o,
242 jlong reserved_space_size, jlong magnitude, jlong iterations))
243 tty->print_cr("reservedSpaceSize="JLONG_FORMAT", magnitude="JLONG_FORMAT", "
244 "iterations="JLONG_FORMAT"\n", reserved_space_size, magnitude,
245 iterations);
246 if (reserved_space_size < 0 || magnitude < 0 || iterations < 0) {
247 tty->print_cr("One of variables printed above is negative. Can't proceed.\n");
248 return 1;
249 }
250
251 // sizeof(size_t) depends on whether OS is 32bit or 64bit. sizeof(jlong) is
252 // always 8 byte. That's why we should avoid overflow in case of 32bit platform.
253 if (sizeof(size_t) < sizeof(jlong)) {
254 jlong size_t_max_value = (jlong) SIZE_T_MAX_VALUE;
255 if (reserved_space_size > size_t_max_value || magnitude > size_t_max_value
256 || iterations > size_t_max_value) {
257 tty->print_cr("One of variables printed above overflows size_t. Can't proceed.\n");
258 return 2;
259 }
260 }
261
262 return wb_stress_virtual_space_resize((size_t) reserved_space_size,
263 (size_t) magnitude, (size_t) iterations);
264 WB_END
265
266 WB_ENTRY(jboolean, WB_isObjectInOldGen(JNIEnv* env, jobject o, jobject obj))
267 oop p = JNIHandles::resolve(obj);
268 #if INCLUDE_ALL_GCS
269 if (UseG1GC) {
270 G1CollectedHeap* g1 = G1CollectedHeap::heap();
271 const HeapRegion* hr = g1->heap_region_containing(p);
272 if (hr == NULL) {
273 return false;
274 }
275 return !(hr->is_young());
276 } else if (UseParallelGC) {
277 ParallelScavengeHeap* psh = ParallelScavengeHeap::heap();
278 return !psh->is_in_young(p);
279 }
280 #endif // INCLUDE_ALL_GCS
281 GenCollectedHeap* gch = GenCollectedHeap::heap();
282 return !gch->is_in_young(p);
283 WB_END
284
285 WB_ENTRY(jlong, WB_GetObjectSize(JNIEnv* env, jobject o, jobject obj))
286 oop p = JNIHandles::resolve(obj);
287 return p->size() * HeapWordSize;
288 WB_END
289
290 #if INCLUDE_ALL_GCS
291 WB_ENTRY(jboolean, WB_G1IsHumongous(JNIEnv* env, jobject o, jobject obj))
292 G1CollectedHeap* g1 = G1CollectedHeap::heap();
293 oop result = JNIHandles::resolve(obj);
294 const HeapRegion* hr = g1->heap_region_containing(result);
295 return hr->is_humongous();
296 WB_END
297
298 WB_ENTRY(jlong, WB_G1NumMaxRegions(JNIEnv* env, jobject o))
299 G1CollectedHeap* g1 = G1CollectedHeap::heap();
300 size_t nr = g1->max_regions();
301 return (jlong)nr;
302 WB_END
303
304 WB_ENTRY(jlong, WB_G1NumFreeRegions(JNIEnv* env, jobject o))
305 G1CollectedHeap* g1 = G1CollectedHeap::heap();
306 size_t nr = g1->num_free_regions();
307 return (jlong)nr;
308 WB_END
309
310 WB_ENTRY(jboolean, WB_G1InConcurrentMark(JNIEnv* env, jobject o))
311 G1CollectedHeap* g1 = G1CollectedHeap::heap();
312 return g1->concurrent_mark()->cmThread()->during_cycle();
313 WB_END
314
315 WB_ENTRY(jboolean, WB_G1StartMarkCycle(JNIEnv* env, jobject o))
316 G1CollectedHeap* g1h = G1CollectedHeap::heap();
317 if (!g1h->concurrent_mark()->cmThread()->during_cycle()) {
318 g1h->collect(GCCause::_wb_conc_mark);
319 return true;
320 }
321 return false;
322 WB_END
323
324 WB_ENTRY(jint, WB_G1RegionSize(JNIEnv* env, jobject o))
325 return (jint)HeapRegion::GrainBytes;
326 WB_END
327
328 WB_ENTRY(jobject, WB_G1AuxiliaryMemoryUsage(JNIEnv* env))
329 ResourceMark rm(THREAD);
330 G1CollectedHeap* g1h = G1CollectedHeap::heap();
331 MemoryUsage usage = g1h->get_auxiliary_data_memory_usage();
332 Handle h = MemoryService::create_MemoryUsage_obj(usage, CHECK_NULL);
333 return JNIHandles::make_local(env, h());
334 WB_END
335 #endif // INCLUDE_ALL_GCS
336
337 #if INCLUDE_NMT
338 // Alloc memory using the test memory type so that we can use that to see if
339 // NMT picks it up correctly
340 WB_ENTRY(jlong, WB_NMTMalloc(JNIEnv* env, jobject o, jlong size))
341 jlong addr = 0;
342 addr = (jlong)(uintptr_t)os::malloc(size, mtTest);
343 return addr;
344 WB_END
345
346 // Alloc memory with pseudo call stack. The test can create psudo malloc
347 // allocation site to stress the malloc tracking.
348 WB_ENTRY(jlong, WB_NMTMallocWithPseudoStack(JNIEnv* env, jobject o, jlong size, jint pseudo_stack))
349 address pc = (address)(size_t)pseudo_stack;
350 NativeCallStack stack(&pc, 1);
351 return (jlong)(uintptr_t)os::malloc(size, mtTest, stack);
352 WB_END
353
354 // Free the memory allocated by NMTAllocTest
355 WB_ENTRY(void, WB_NMTFree(JNIEnv* env, jobject o, jlong mem))
356 os::free((void*)(uintptr_t)mem);
357 WB_END
358
359 WB_ENTRY(jlong, WB_NMTReserveMemory(JNIEnv* env, jobject o, jlong size))
360 jlong addr = 0;
361
362 addr = (jlong)(uintptr_t)os::reserve_memory(size);
363 MemTracker::record_virtual_memory_type((address)addr, mtTest);
364
365 return addr;
366 WB_END
367
368 WB_ENTRY(void, WB_NMTCommitMemory(JNIEnv* env, jobject o, jlong addr, jlong size))
369 os::commit_memory((char *)(uintptr_t)addr, size, !ExecMem);
370 MemTracker::record_virtual_memory_type((address)(uintptr_t)addr, mtTest);
371 WB_END
372
373 WB_ENTRY(void, WB_NMTUncommitMemory(JNIEnv* env, jobject o, jlong addr, jlong size))
374 os::uncommit_memory((char *)(uintptr_t)addr, size);
375 WB_END
376
377 WB_ENTRY(void, WB_NMTReleaseMemory(JNIEnv* env, jobject o, jlong addr, jlong size))
378 os::release_memory((char *)(uintptr_t)addr, size);
379 WB_END
380
381 WB_ENTRY(jboolean, WB_NMTChangeTrackingLevel(JNIEnv* env))
382 // Test that we can downgrade NMT levels but not upgrade them.
383 if (MemTracker::tracking_level() == NMT_off) {
384 MemTracker::transition_to(NMT_off);
385 return MemTracker::tracking_level() == NMT_off;
386 } else {
387 assert(MemTracker::tracking_level() == NMT_detail, "Should start out as detail tracking");
388 MemTracker::transition_to(NMT_summary);
389 assert(MemTracker::tracking_level() == NMT_summary, "Should be summary now");
390
391 // Can't go to detail once NMT is set to summary.
392 MemTracker::transition_to(NMT_detail);
393 assert(MemTracker::tracking_level() == NMT_summary, "Should still be summary now");
394
395 // Shutdown sets tracking level to minimal.
396 MemTracker::shutdown();
397 assert(MemTracker::tracking_level() == NMT_minimal, "Should be minimal now");
398
399 // Once the tracking level is minimal, we cannot increase to summary.
400 // The code ignores this request instead of asserting because if the malloc site
401 // table overflows in another thread, it tries to change the code to summary.
402 MemTracker::transition_to(NMT_summary);
403 assert(MemTracker::tracking_level() == NMT_minimal, "Should still be minimal now");
404
405 // Really can never go up to detail, verify that the code would never do this.
406 MemTracker::transition_to(NMT_detail);
407 assert(MemTracker::tracking_level() == NMT_minimal, "Should still be minimal now");
408 return MemTracker::tracking_level() == NMT_minimal;
409 }
410 WB_END
411
412 WB_ENTRY(jint, WB_NMTGetHashSize(JNIEnv* env, jobject o))
413 int hash_size = MallocSiteTable::hash_buckets();
414 assert(hash_size > 0, "NMT hash_size should be > 0");
415 return (jint)hash_size;
416 WB_END
417 #endif // INCLUDE_NMT
418
419 static jmethodID reflected_method_to_jmid(JavaThread* thread, JNIEnv* env, jobject method) {
420 assert(method != NULL, "method should not be null");
421 ThreadToNativeFromVM ttn(thread);
422 return env->FromReflectedMethod(method);
423 }
424
425 // Deoptimizes all compiled frames and makes nmethods not entrant if it's requested
426 class VM_WhiteBoxDeoptimizeFrames : public VM_WhiteBoxOperation {
427 private:
428 int _result;
429 const bool _make_not_entrant;
430 public:
431 VM_WhiteBoxDeoptimizeFrames(bool make_not_entrant) :
432 _result(0), _make_not_entrant(make_not_entrant) { }
433 int result() const { return _result; }
434
435 void doit() {
436 for (JavaThread* t = Threads::first(); t != NULL; t = t->next()) {
437 if (t->has_last_Java_frame()) {
438 for (StackFrameStream fst(t, UseBiasedLocking); !fst.is_done(); fst.next()) {
439 frame* f = fst.current();
440 if (f->can_be_deoptimized() && !f->is_deoptimized_frame()) {
441 RegisterMap* reg_map = fst.register_map();
442 Deoptimization::deoptimize(t, *f, reg_map);
443 if (_make_not_entrant) {
444 nmethod* nm = CodeCache::find_nmethod(f->pc());
445 assert(nm != NULL, "sanity check");
446 nm->make_not_entrant();
447 }
448 ++_result;
449 }
450 }
451 }
452 }
453 }
454 };
455
456 WB_ENTRY(jint, WB_DeoptimizeFrames(JNIEnv* env, jobject o, jboolean make_not_entrant))
457 VM_WhiteBoxDeoptimizeFrames op(make_not_entrant == JNI_TRUE);
458 VMThread::execute(&op);
459 return op.result();
460 WB_END
461
462 WB_ENTRY(void, WB_DeoptimizeAll(JNIEnv* env, jobject o))
463 MutexLockerEx mu(Compile_lock);
464 CodeCache::mark_all_nmethods_for_deoptimization();
465 VM_Deoptimize op;
466 VMThread::execute(&op);
467 WB_END
468
469 WB_ENTRY(jint, WB_DeoptimizeMethod(JNIEnv* env, jobject o, jobject method, jboolean is_osr))
470 jmethodID jmid = reflected_method_to_jmid(thread, env, method);
471 int result = 0;
472 CHECK_JNI_EXCEPTION_(env, result);
473 MutexLockerEx mu(Compile_lock);
474 methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
475 if (is_osr) {
476 result += mh->mark_osr_nmethods();
477 } else if (mh->code() != NULL) {
478 mh->code()->mark_for_deoptimization();
479 ++result;
480 }
481 result += CodeCache::mark_for_deoptimization(mh());
482 if (result > 0) {
483 VM_Deoptimize op;
484 VMThread::execute(&op);
485 }
486 return result;
487 WB_END
488
489 WB_ENTRY(jboolean, WB_IsMethodCompiled(JNIEnv* env, jobject o, jobject method, jboolean is_osr))
490 jmethodID jmid = reflected_method_to_jmid(thread, env, method);
491 CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
492 MutexLockerEx mu(Compile_lock);
493 methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
494 nmethod* code = is_osr ? mh->lookup_osr_nmethod_for(InvocationEntryBci, CompLevel_none, false) : mh->code();
495 if (code == NULL) {
496 return JNI_FALSE;
497 }
498 return (code->is_alive() && !code->is_marked_for_deoptimization());
499 WB_END
500
501 WB_ENTRY(jboolean, WB_IsMethodCompilable(JNIEnv* env, jobject o, jobject method, jint comp_level, jboolean is_osr))
502 jmethodID jmid = reflected_method_to_jmid(thread, env, method);
503 CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
504 MutexLockerEx mu(Compile_lock);
505 methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
506 if (is_osr) {
507 return CompilationPolicy::can_be_osr_compiled(mh, comp_level);
508 } else {
509 return CompilationPolicy::can_be_compiled(mh, comp_level);
510 }
511 WB_END
512
513 WB_ENTRY(jboolean, WB_IsMethodQueuedForCompilation(JNIEnv* env, jobject o, jobject method))
514 jmethodID jmid = reflected_method_to_jmid(thread, env, method);
515 CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
516 MutexLockerEx mu(Compile_lock);
517 methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
518 return mh->queued_for_compilation();
519 WB_END
520
521 WB_ENTRY(jint, WB_GetMethodCompilationLevel(JNIEnv* env, jobject o, jobject method, jboolean is_osr))
522 jmethodID jmid = reflected_method_to_jmid(thread, env, method);
523 CHECK_JNI_EXCEPTION_(env, CompLevel_none);
524 methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
525 nmethod* code = is_osr ? mh->lookup_osr_nmethod_for(InvocationEntryBci, CompLevel_none, false) : mh->code();
526 return (code != NULL ? code->comp_level() : CompLevel_none);
527 WB_END
528
529 WB_ENTRY(void, WB_MakeMethodNotCompilable(JNIEnv* env, jobject o, jobject method, jint comp_level, jboolean is_osr))
530 jmethodID jmid = reflected_method_to_jmid(thread, env, method);
531 CHECK_JNI_EXCEPTION(env);
532 methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
533 if (is_osr) {
534 mh->set_not_osr_compilable(comp_level, true /* report */, "WhiteBox");
535 } else {
536 mh->set_not_compilable(comp_level, true /* report */, "WhiteBox");
537 }
538 WB_END
539
540 WB_ENTRY(jint, WB_GetMethodEntryBci(JNIEnv* env, jobject o, jobject method))
541 jmethodID jmid = reflected_method_to_jmid(thread, env, method);
542 CHECK_JNI_EXCEPTION_(env, InvocationEntryBci);
543 methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
544 nmethod* code = mh->lookup_osr_nmethod_for(InvocationEntryBci, CompLevel_none, false);
545 return (code != NULL && code->is_osr_method() ? code->osr_entry_bci() : InvocationEntryBci);
546 WB_END
547
548 WB_ENTRY(jboolean, WB_TestSetDontInlineMethod(JNIEnv* env, jobject o, jobject method, jboolean value))
549 jmethodID jmid = reflected_method_to_jmid(thread, env, method);
550 CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
551 methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
552 bool result = mh->dont_inline();
553 mh->set_dont_inline(value == JNI_TRUE);
554 return result;
555 WB_END
556
557 WB_ENTRY(jint, WB_GetCompileQueueSize(JNIEnv* env, jobject o, jint comp_level))
558 if (comp_level == CompLevel_any) {
559 return CompileBroker::queue_size(CompLevel_full_optimization) /* C2 */ +
560 CompileBroker::queue_size(CompLevel_full_profile) /* C1 */;
561 } else {
562 return CompileBroker::queue_size(comp_level);
563 }
564 WB_END
565
566 WB_ENTRY(jboolean, WB_TestSetForceInlineMethod(JNIEnv* env, jobject o, jobject method, jboolean value))
567 jmethodID jmid = reflected_method_to_jmid(thread, env, method);
568 CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
569 methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
570 bool result = mh->force_inline();
571 mh->set_force_inline(value == JNI_TRUE);
572 return result;
573 WB_END
574
575 WB_ENTRY(jboolean, WB_EnqueueMethodForCompilation(JNIEnv* env, jobject o, jobject method, jint comp_level, jint bci))
576 jmethodID jmid = reflected_method_to_jmid(thread, env, method);
577 CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
578 methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
579 nmethod* nm = CompileBroker::compile_method(mh, bci, comp_level, mh, mh->invocation_count(), "WhiteBox", THREAD);
580 MutexLockerEx mu(Compile_lock);
581 return (mh->queued_for_compilation() || nm != NULL);
582 WB_END
583
584 class AlwaysFalseClosure : public BoolObjectClosure {
585 public:
586 bool do_object_b(oop p) { return false; }
587 };
588
589 static AlwaysFalseClosure always_false;
590
591 WB_ENTRY(void, WB_ClearMethodState(JNIEnv* env, jobject o, jobject method))
592 jmethodID jmid = reflected_method_to_jmid(thread, env, method);
593 CHECK_JNI_EXCEPTION(env);
594 methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
595 MutexLockerEx mu(Compile_lock);
596 MethodData* mdo = mh->method_data();
597 MethodCounters* mcs = mh->method_counters();
598
599 if (mdo != NULL) {
600 mdo->init();
601 ResourceMark rm;
602 int arg_count = mdo->method()->size_of_parameters();
603 for (int i = 0; i < arg_count; i++) {
604 mdo->set_arg_modified(i, 0);
605 }
606 MutexLockerEx mu(mdo->extra_data_lock());
607 mdo->clean_method_data(&always_false);
608 }
609
610 mh->clear_not_c1_compilable();
611 mh->clear_not_c2_compilable();
612 mh->clear_not_c2_osr_compilable();
613 NOT_PRODUCT(mh->set_compiled_invocation_count(0));
614 if (mcs != NULL) {
615 mcs->backedge_counter()->init();
616 mcs->invocation_counter()->init();
617 mcs->set_interpreter_invocation_count(0);
618 mcs->set_interpreter_throwout_count(0);
619
620 #ifdef TIERED
621 mcs->set_rate(0.0F);
622 mh->set_prev_event_count(0);
623 mh->set_prev_time(0);
624 #endif
625 }
626 WB_END
627
628 template <typename T>
629 static bool GetVMFlag(JavaThread* thread, JNIEnv* env, jstring name, T* value, bool (*TAt)(const char*, T*, bool, bool)) {
630 if (name == NULL) {
631 return false;
632 }
633 ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
634 const char* flag_name = env->GetStringUTFChars(name, NULL);
635 bool result = (*TAt)(flag_name, value, true, true);
636 env->ReleaseStringUTFChars(name, flag_name);
637 return result;
638 }
639
640 template <typename T>
641 static bool SetVMFlag(JavaThread* thread, JNIEnv* env, jstring name, T* value, bool (*TAtPut)(const char*, T*, Flag::Flags)) {
642 if (name == NULL) {
643 return false;
644 }
645 ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
646 const char* flag_name = env->GetStringUTFChars(name, NULL);
647 bool result = (*TAtPut)(flag_name, value, Flag::INTERNAL);
648 env->ReleaseStringUTFChars(name, flag_name);
649 return result;
650 }
651
652 template <typename T>
653 static jobject box(JavaThread* thread, JNIEnv* env, Symbol* name, Symbol* sig, T value) {
654 ResourceMark rm(thread);
655 jclass clazz = env->FindClass(name->as_C_string());
656 CHECK_JNI_EXCEPTION_(env, NULL);
657 jmethodID methodID = env->GetStaticMethodID(clazz,
658 vmSymbols::valueOf_name()->as_C_string(),
659 sig->as_C_string());
660 CHECK_JNI_EXCEPTION_(env, NULL);
661 jobject result = env->CallStaticObjectMethod(clazz, methodID, value);
662 CHECK_JNI_EXCEPTION_(env, NULL);
663 return result;
664 }
665
666 static jobject booleanBox(JavaThread* thread, JNIEnv* env, jboolean value) {
667 return box(thread, env, vmSymbols::java_lang_Boolean(), vmSymbols::Boolean_valueOf_signature(), value);
668 }
669 static jobject integerBox(JavaThread* thread, JNIEnv* env, jint value) {
670 return box(thread, env, vmSymbols::java_lang_Integer(), vmSymbols::Integer_valueOf_signature(), value);
671 }
672 static jobject longBox(JavaThread* thread, JNIEnv* env, jlong value) {
673 return box(thread, env, vmSymbols::java_lang_Long(), vmSymbols::Long_valueOf_signature(), value);
674 }
675 /* static jobject floatBox(JavaThread* thread, JNIEnv* env, jfloat value) {
676 return box(thread, env, vmSymbols::java_lang_Float(), vmSymbols::Float_valueOf_signature(), value);
677 }*/
678 static jobject doubleBox(JavaThread* thread, JNIEnv* env, jdouble value) {
679 return box(thread, env, vmSymbols::java_lang_Double(), vmSymbols::Double_valueOf_signature(), value);
680 }
681
682 static Flag* getVMFlag(JavaThread* thread, JNIEnv* env, jstring name) {
683 ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
684 const char* flag_name = env->GetStringUTFChars(name, NULL);
685 Flag* result = Flag::find_flag(flag_name, strlen(flag_name), true, true);
686 env->ReleaseStringUTFChars(name, flag_name);
687 return result;
688 }
689
690 WB_ENTRY(jboolean, WB_IsConstantVMFlag(JNIEnv* env, jobject o, jstring name))
691 Flag* flag = getVMFlag(thread, env, name);
692 return (flag != NULL) && flag->is_constant_in_binary();
693 WB_END
694
695 WB_ENTRY(jboolean, WB_IsLockedVMFlag(JNIEnv* env, jobject o, jstring name))
696 Flag* flag = getVMFlag(thread, env, name);
697 return (flag != NULL) && !(flag->is_unlocked() || flag->is_unlocker());
698 WB_END
699
700 WB_ENTRY(jobject, WB_GetBooleanVMFlag(JNIEnv* env, jobject o, jstring name))
701 bool result;
702 if (GetVMFlag <bool> (thread, env, name, &result, &CommandLineFlags::boolAt)) {
703 ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
704 return booleanBox(thread, env, result);
705 }
706 return NULL;
707 WB_END
708
709 WB_ENTRY(jobject, WB_GetIntxVMFlag(JNIEnv* env, jobject o, jstring name))
710 intx result;
711 if (GetVMFlag <intx> (thread, env, name, &result, &CommandLineFlags::intxAt)) {
712 ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
713 return longBox(thread, env, result);
714 }
715 return NULL;
716 WB_END
717
718 WB_ENTRY(jobject, WB_GetUintxVMFlag(JNIEnv* env, jobject o, jstring name))
719 uintx result;
720 if (GetVMFlag <uintx> (thread, env, name, &result, &CommandLineFlags::uintxAt)) {
721 ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
722 return longBox(thread, env, result);
723 }
724 return NULL;
725 WB_END
726
727 WB_ENTRY(jobject, WB_GetUint64VMFlag(JNIEnv* env, jobject o, jstring name))
728 uint64_t result;
729 if (GetVMFlag <uint64_t> (thread, env, name, &result, &CommandLineFlags::uint64_tAt)) {
730 ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
731 return longBox(thread, env, result);
732 }
733 return NULL;
734 WB_END
735
736 WB_ENTRY(jobject, WB_GetSizeTVMFlag(JNIEnv* env, jobject o, jstring name))
737 uintx result;
738 if (GetVMFlag <size_t> (thread, env, name, &result, &CommandLineFlags::size_tAt)) {
739 ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
740 return longBox(thread, env, result);
741 }
742 return NULL;
743 WB_END
744
745 WB_ENTRY(jobject, WB_GetDoubleVMFlag(JNIEnv* env, jobject o, jstring name))
746 double result;
747 if (GetVMFlag <double> (thread, env, name, &result, &CommandLineFlags::doubleAt)) {
748 ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
749 return doubleBox(thread, env, result);
750 }
751 return NULL;
752 WB_END
753
754 WB_ENTRY(jstring, WB_GetStringVMFlag(JNIEnv* env, jobject o, jstring name))
755 ccstr ccstrResult;
756 if (GetVMFlag <ccstr> (thread, env, name, &ccstrResult, &CommandLineFlags::ccstrAt)) {
757 ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
758 jstring result = env->NewStringUTF(ccstrResult);
759 CHECK_JNI_EXCEPTION_(env, NULL);
760 return result;
761 }
762 return NULL;
763 WB_END
764
765 WB_ENTRY(void, WB_SetBooleanVMFlag(JNIEnv* env, jobject o, jstring name, jboolean value))
766 bool result = value == JNI_TRUE ? true : false;
767 SetVMFlag <bool> (thread, env, name, &result, &CommandLineFlags::boolAtPut);
768 WB_END
769
770 WB_ENTRY(void, WB_SetIntxVMFlag(JNIEnv* env, jobject o, jstring name, jlong value))
771 intx result = value;
772 SetVMFlag <intx> (thread, env, name, &result, &CommandLineFlags::intxAtPut);
773 WB_END
774
775 WB_ENTRY(void, WB_SetUintxVMFlag(JNIEnv* env, jobject o, jstring name, jlong value))
776 uintx result = value;
777 SetVMFlag <uintx> (thread, env, name, &result, &CommandLineFlags::uintxAtPut);
778 WB_END
779
780 WB_ENTRY(void, WB_SetUint64VMFlag(JNIEnv* env, jobject o, jstring name, jlong value))
781 uint64_t result = value;
782 SetVMFlag <uint64_t> (thread, env, name, &result, &CommandLineFlags::uint64_tAtPut);
783 WB_END
784
785 WB_ENTRY(void, WB_SetSizeTVMFlag(JNIEnv* env, jobject o, jstring name, jlong value))
786 size_t result = value;
787 SetVMFlag <size_t> (thread, env, name, &result, &CommandLineFlags::size_tAtPut);
788 WB_END
789
790 WB_ENTRY(void, WB_SetDoubleVMFlag(JNIEnv* env, jobject o, jstring name, jdouble value))
791 double result = value;
792 SetVMFlag <double> (thread, env, name, &result, &CommandLineFlags::doubleAtPut);
793 WB_END
794
795 WB_ENTRY(void, WB_SetStringVMFlag(JNIEnv* env, jobject o, jstring name, jstring value))
796 ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
797 const char* ccstrValue = (value == NULL) ? NULL : env->GetStringUTFChars(value, NULL);
798 ccstr ccstrResult = ccstrValue;
799 bool needFree;
800 {
801 ThreadInVMfromNative ttvfn(thread); // back to VM
802 needFree = SetVMFlag <ccstr> (thread, env, name, &ccstrResult, &CommandLineFlags::ccstrAtPut);
803 }
804 if (value != NULL) {
805 env->ReleaseStringUTFChars(value, ccstrValue);
806 }
807 if (needFree) {
808 FREE_C_HEAP_ARRAY(char, ccstrResult);
809 }
810 WB_END
811
812 WB_ENTRY(void, WB_LockCompilation(JNIEnv* env, jobject o, jlong timeout))
813 WhiteBox::compilation_locked = true;
814 WB_END
815
816 WB_ENTRY(void, WB_UnlockCompilation(JNIEnv* env, jobject o))
817 MonitorLockerEx mo(Compilation_lock, Mutex::_no_safepoint_check_flag);
818 WhiteBox::compilation_locked = false;
819 mo.notify_all();
820 WB_END
821
822 void WhiteBox::sweeper_thread_entry(JavaThread* thread, TRAPS) {
823 guarantee(WhiteBoxAPI, "internal testing API :: WhiteBox has to be enabled");
824 {
825 MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
826 NMethodSweeper::_should_sweep = true;
827 }
828 NMethodSweeper::possibly_sweep();
829 }
830
831 JavaThread* WhiteBox::create_sweeper_thread(TRAPS) {
832 // create sweeper thread w/ custom entry -- one iteration instead of loop
833 CodeCacheSweeperThread* sweeper_thread = new CodeCacheSweeperThread();
834 sweeper_thread->set_entry_point(&WhiteBox::sweeper_thread_entry);
835
836 // create j.l.Thread object and associate it w/ sweeper thread
837 {
838 // inherit deamon property from current thread
839 bool is_daemon = java_lang_Thread::is_daemon(JavaThread::current()->threadObj());
840
841 HandleMark hm(THREAD);
842 Handle thread_group(THREAD, Universe::system_thread_group());
843 const char* name = "WB Sweeper thread";
844 sweeper_thread->allocate_threadObj(thread_group, name, is_daemon, THREAD);
845 }
846
847 {
848 MutexLocker mu(Threads_lock, THREAD);
849 Threads::add(sweeper_thread);
850 }
851 return sweeper_thread;
852 }
853
854 WB_ENTRY(jobject, WB_ForceNMethodSweep(JNIEnv* env, jobject o))
855 JavaThread* sweeper_thread = WhiteBox::create_sweeper_thread(Thread::current());
856 if (sweeper_thread == NULL) {
857 return NULL;
858 }
859 jobject result = JNIHandles::make_local(env, sweeper_thread->threadObj());
860 Thread::start(sweeper_thread);
861 return result;
862 WB_END
863
864 WB_ENTRY(jboolean, WB_IsInStringTable(JNIEnv* env, jobject o, jstring javaString))
865 ResourceMark rm(THREAD);
866 int len;
867 jchar* name = java_lang_String::as_unicode_string(JNIHandles::resolve(javaString), len, CHECK_false);
868 return (StringTable::lookup(name, len) != NULL);
869 WB_END
870
871 WB_ENTRY(void, WB_FullGC(JNIEnv* env, jobject o))
872 Universe::heap()->collector_policy()->set_should_clear_all_soft_refs(true);
873 Universe::heap()->collect(GCCause::_last_ditch_collection);
874 #if INCLUDE_ALL_GCS
875 if (UseG1GC) {
876 // Needs to be cleared explicitly for G1
877 Universe::heap()->collector_policy()->set_should_clear_all_soft_refs(false);
878 }
879 #endif // INCLUDE_ALL_GCS
880 WB_END
881
882 WB_ENTRY(void, WB_YoungGC(JNIEnv* env, jobject o))
883 Universe::heap()->collect(GCCause::_wb_young_gc);
884 WB_END
885
886 WB_ENTRY(void, WB_ReadReservedMemory(JNIEnv* env, jobject o))
887 // static+volatile in order to force the read to happen
888 // (not be eliminated by the compiler)
889 static char c;
890 static volatile char* p;
891
892 p = os::reserve_memory(os::vm_allocation_granularity(), NULL, 0);
893 if (p == NULL) {
894 THROW_MSG(vmSymbols::java_lang_OutOfMemoryError(), "Failed to reserve memory");
895 }
896
897 c = *p;
898 WB_END
899
900 WB_ENTRY(jstring, WB_GetCPUFeatures(JNIEnv* env, jobject o))
901 const char* cpu_features = VM_Version::cpu_features();
902 ThreadToNativeFromVM ttn(thread);
903 jstring features_string = env->NewStringUTF(cpu_features);
904
905 CHECK_JNI_EXCEPTION_(env, NULL);
906
907 return features_string;
908 WB_END
909
910 int WhiteBox::get_blob_type(const CodeBlob* code) {
911 guarantee(WhiteBoxAPI, "internal testing API :: WhiteBox has to be enabled");
912 return CodeCache::get_code_heap(code)->code_blob_type();
913 }
914
915 CodeHeap* WhiteBox::get_code_heap(int blob_type) {
916 guarantee(WhiteBoxAPI, "internal testing API :: WhiteBox has to be enabled");
917 return CodeCache::get_code_heap(blob_type);
918 }
919
920 struct CodeBlobStub {
921 CodeBlobStub(const CodeBlob* blob) :
922 name(os::strdup(blob->name())),
923 size(blob->size()),
924 blob_type(WhiteBox::get_blob_type(blob)) { }
925 ~CodeBlobStub() { os::free((void*) name); }
926 const char* const name;
927 const int size;
928 const int blob_type;
929 };
930
931 static jobjectArray codeBlob2objectArray(JavaThread* thread, JNIEnv* env, CodeBlobStub* cb) {
932 jclass clazz = env->FindClass(vmSymbols::java_lang_Object()->as_C_string());
933 CHECK_JNI_EXCEPTION_(env, NULL);
934 jobjectArray result = env->NewObjectArray(3, clazz, NULL);
935
936 jstring name = env->NewStringUTF(cb->name);
937 CHECK_JNI_EXCEPTION_(env, NULL);
938 env->SetObjectArrayElement(result, 0, name);
939
940 jobject obj = integerBox(thread, env, cb->size);
941 CHECK_JNI_EXCEPTION_(env, NULL);
942 env->SetObjectArrayElement(result, 1, obj);
943
944 obj = integerBox(thread, env, cb->blob_type);
945 CHECK_JNI_EXCEPTION_(env, NULL);
946 env->SetObjectArrayElement(result, 2, obj);
947
948 return result;
949 }
950
951 WB_ENTRY(jobjectArray, WB_GetNMethod(JNIEnv* env, jobject o, jobject method, jboolean is_osr))
952 ResourceMark rm(THREAD);
953 jmethodID jmid = reflected_method_to_jmid(thread, env, method);
954 CHECK_JNI_EXCEPTION_(env, NULL);
955 methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
956 nmethod* code = is_osr ? mh->lookup_osr_nmethod_for(InvocationEntryBci, CompLevel_none, false) : mh->code();
957 jobjectArray result = NULL;
958 if (code == NULL) {
959 return result;
960 }
961 int insts_size = code->insts_size();
962
963 ThreadToNativeFromVM ttn(thread);
964 jclass clazz = env->FindClass(vmSymbols::java_lang_Object()->as_C_string());
965 CHECK_JNI_EXCEPTION_(env, NULL);
966 result = env->NewObjectArray(4, clazz, NULL);
967 if (result == NULL) {
968 return result;
969 }
970
971 CodeBlobStub stub(code);
972 jobjectArray codeBlob = codeBlob2objectArray(thread, env, &stub);
973 env->SetObjectArrayElement(result, 0, codeBlob);
974
975 jobject level = integerBox(thread, env, code->comp_level());
976 CHECK_JNI_EXCEPTION_(env, NULL);
977 env->SetObjectArrayElement(result, 1, level);
978
979 jbyteArray insts = env->NewByteArray(insts_size);
980 CHECK_JNI_EXCEPTION_(env, NULL);
981 env->SetByteArrayRegion(insts, 0, insts_size, (jbyte*) code->insts_begin());
982 env->SetObjectArrayElement(result, 2, insts);
983
984 jobject id = integerBox(thread, env, code->compile_id());
985 CHECK_JNI_EXCEPTION_(env, NULL);
986 env->SetObjectArrayElement(result, 3, id);
987
988 return result;
989 WB_END
990
991 CodeBlob* WhiteBox::allocate_code_blob(int size, int blob_type) {
992 guarantee(WhiteBoxAPI, "internal testing API :: WhiteBox has to be enabled");
993 BufferBlob* blob;
994 int full_size = CodeBlob::align_code_offset(sizeof(BufferBlob));
995 if (full_size < size) {
996 full_size += round_to(size - full_size, oopSize);
997 }
998 {
999 MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
1000 blob = (BufferBlob*) CodeCache::allocate(full_size, blob_type);
1001 ::new (blob) BufferBlob("WB::DummyBlob", full_size);
1002 }
1003 // Track memory usage statistic after releasing CodeCache_lock
1004 MemoryService::track_code_cache_memory_usage();
1005 return blob;
1006 }
1007
1008 WB_ENTRY(jlong, WB_AllocateCodeBlob(JNIEnv* env, jobject o, jint size, jint blob_type))
1009 return (jlong) WhiteBox::allocate_code_blob(size, blob_type);
1010 WB_END
1011
1012 WB_ENTRY(void, WB_FreeCodeBlob(JNIEnv* env, jobject o, jlong addr))
1013 BufferBlob::free((BufferBlob*) addr);
1014 WB_END
1015
1016 WB_ENTRY(jobjectArray, WB_GetCodeHeapEntries(JNIEnv* env, jobject o, jint blob_type))
1017 ResourceMark rm;
1018 GrowableArray<CodeBlobStub*> blobs;
1019 {
1020 MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
1021 CodeHeap* heap = WhiteBox::get_code_heap(blob_type);
1022 if (heap == NULL) {
1023 return NULL;
1024 }
1025 for (CodeBlob* cb = (CodeBlob*) heap->first();
1026 cb != NULL; cb = (CodeBlob*) heap->next(cb)) {
1027 CodeBlobStub* stub = NEW_RESOURCE_OBJ(CodeBlobStub);
1028 new (stub) CodeBlobStub(cb);
1029 blobs.append(stub);
1030 }
1031 }
1032 if (blobs.length() == 0) {
1033 return NULL;
1034 }
1035 ThreadToNativeFromVM ttn(thread);
1036 jobjectArray result = NULL;
1037 jclass clazz = env->FindClass(vmSymbols::java_lang_Object()->as_C_string());
1038 CHECK_JNI_EXCEPTION_(env, NULL);
1039 result = env->NewObjectArray(blobs.length(), clazz, NULL);
1040 if (result == NULL) {
1041 return result;
1042 }
1043 int i = 0;
1044 for (GrowableArrayIterator<CodeBlobStub*> it = blobs.begin();
1045 it != blobs.end(); ++it) {
1046 jobjectArray obj = codeBlob2objectArray(thread, env, *it);
1047 env->SetObjectArrayElement(result, i, obj);
1048 ++i;
1049 }
1050 return result;
1051 WB_END
1052
1053 WB_ENTRY(jint, WB_GetCompilationActivityMode(JNIEnv* env, jobject o))
1054 return CompileBroker::get_compilation_activity_mode();
1055 WB_END
1056
1057 WB_ENTRY(jobjectArray, WB_GetCodeBlob(JNIEnv* env, jobject o, jlong addr))
1058 ThreadToNativeFromVM ttn(thread);
1059 CodeBlobStub stub((CodeBlob*) addr);
1060 return codeBlob2objectArray(thread, env, &stub);
1061 WB_END
1062
1063 WB_ENTRY(jlong, WB_GetThreadStackSize(JNIEnv* env, jobject o))
1064 return (jlong) Thread::current()->stack_size();
1065 WB_END
1066
1067 WB_ENTRY(jlong, WB_GetThreadRemainingStackSize(JNIEnv* env, jobject o))
1068 JavaThread* t = JavaThread::current();
1069 return (jlong) t->stack_available(os::current_stack_pointer()) - (jlong) StackShadowPages * os::vm_page_size();
1070 WB_END
1071
1072 int WhiteBox::array_bytes_to_length(size_t bytes) {
1073 return Array<u1>::bytes_to_length(bytes);
1074 }
1075
1076 WB_ENTRY(jlong, WB_AllocateMetaspace(JNIEnv* env, jobject wb, jobject class_loader, jlong size))
1077 if (size < 0) {
1078 THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
1079 err_msg("WB_AllocateMetaspace: size is negative: " JLONG_FORMAT, size));
1080 }
1081
1082 oop class_loader_oop = JNIHandles::resolve(class_loader);
1083 ClassLoaderData* cld = class_loader_oop != NULL
1084 ? java_lang_ClassLoader::loader_data(class_loader_oop)
1085 : ClassLoaderData::the_null_class_loader_data();
1086
1087 void* metadata = MetadataFactory::new_writeable_array<u1>(cld, WhiteBox::array_bytes_to_length((size_t)size), thread);
1088
1089 return (jlong)(uintptr_t)metadata;
1090 WB_END
1091
1092 WB_ENTRY(void, WB_FreeMetaspace(JNIEnv* env, jobject wb, jobject class_loader, jlong addr, jlong size))
1093 oop class_loader_oop = JNIHandles::resolve(class_loader);
1094 ClassLoaderData* cld = class_loader_oop != NULL
1095 ? java_lang_ClassLoader::loader_data(class_loader_oop)
1096 : ClassLoaderData::the_null_class_loader_data();
1097
1098 MetadataFactory::free_array(cld, (Array<u1>*)(uintptr_t)addr);
1099 WB_END
1100
1101 WB_ENTRY(jlong, WB_IncMetaspaceCapacityUntilGC(JNIEnv* env, jobject wb, jlong inc))
1102 if (inc < 0) {
1103 THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
1104 err_msg("WB_IncMetaspaceCapacityUntilGC: inc is negative: " JLONG_FORMAT, inc));
1105 }
1106
1107 jlong max_size_t = (jlong) ((size_t) -1);
1108 if (inc > max_size_t) {
1109 THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
1110 err_msg("WB_IncMetaspaceCapacityUntilGC: inc does not fit in size_t: " JLONG_FORMAT, inc));
1111 }
1112
1113 size_t new_cap_until_GC = 0;
1114 size_t aligned_inc = align_size_down((size_t) inc, Metaspace::commit_alignment());
1115 bool success = MetaspaceGC::inc_capacity_until_GC(aligned_inc, &new_cap_until_GC);
1116 if (!success) {
1117 THROW_MSG_0(vmSymbols::java_lang_IllegalStateException(),
1118 "WB_IncMetaspaceCapacityUntilGC: could not increase capacity until GC "
1119 "due to contention with another thread");
1120 }
1121 return (jlong) new_cap_until_GC;
1122 WB_END
1123
1124 WB_ENTRY(jlong, WB_MetaspaceCapacityUntilGC(JNIEnv* env, jobject wb))
1125 return (jlong) MetaspaceGC::capacity_until_GC();
1126 WB_END
1127
1128 WB_ENTRY(void, WB_AssertMatchingSafepointCalls(JNIEnv* env, jobject o, jboolean mutexSafepointValue, jboolean attemptedNoSafepointValue))
1129 Monitor::SafepointCheckRequired sfpt_check_required = mutexSafepointValue ?
1130 Monitor::_safepoint_check_always :
1131 Monitor::_safepoint_check_never;
1132 MutexLockerEx ml(new Mutex(Mutex::leaf, "SFPT_Test_lock", true, sfpt_check_required),
1133 attemptedNoSafepointValue == JNI_TRUE);
1134 WB_END
1135
1136 WB_ENTRY(jboolean, WB_IsMonitorInflated(JNIEnv* env, jobject wb, jobject obj))
1137 oop obj_oop = JNIHandles::resolve(obj);
1138 return (jboolean) obj_oop->mark()->has_monitor();
1139 WB_END
1140
1141 WB_ENTRY(void, WB_ForceSafepoint(JNIEnv* env, jobject wb))
1142 VM_ForceSafepoint force_safepoint_op;
1143 VMThread::execute(&force_safepoint_op);
1144 WB_END
1145
1146 template <typename T>
1147 static bool GetMethodOption(JavaThread* thread, JNIEnv* env, jobject method, jstring name, T* value) {
1148 assert(value != NULL, "sanity");
1149 if (method == NULL || name == NULL) {
1150 return false;
1151 }
1152 jmethodID jmid = reflected_method_to_jmid(thread, env, method);
1153 CHECK_JNI_EXCEPTION_(env, false);
1154 methodHandle mh(thread, Method::checked_resolve_jmethod_id(jmid));
1155 // can't be in VM when we call JNI
1156 ThreadToNativeFromVM ttnfv(thread);
1157 const char* flag_name = env->GetStringUTFChars(name, NULL);
1158 bool result = CompilerOracle::has_option_value(mh, flag_name, *value);
1159 env->ReleaseStringUTFChars(name, flag_name);
1160 return result;
1161 }
1162
1163 WB_ENTRY(jobject, WB_GetMethodBooleaneOption(JNIEnv* env, jobject wb, jobject method, jstring name))
1164 bool result;
1165 if (GetMethodOption<bool> (thread, env, method, name, &result)) {
1166 // can't be in VM when we call JNI
1167 ThreadToNativeFromVM ttnfv(thread);
1168 return booleanBox(thread, env, result);
1169 }
1170 return NULL;
1171 WB_END
1172
1173 WB_ENTRY(jobject, WB_GetMethodIntxOption(JNIEnv* env, jobject wb, jobject method, jstring name))
1174 intx result;
1175 if (GetMethodOption <intx> (thread, env, method, name, &result)) {
1176 // can't be in VM when we call JNI
1177 ThreadToNativeFromVM ttnfv(thread);
1178 return longBox(thread, env, result);
1179 }
1180 return NULL;
1181 WB_END
1182
1183 WB_ENTRY(jobject, WB_GetMethodUintxOption(JNIEnv* env, jobject wb, jobject method, jstring name))
1184 uintx result;
1185 if (GetMethodOption <uintx> (thread, env, method, name, &result)) {
1186 // can't be in VM when we call JNI
1187 ThreadToNativeFromVM ttnfv(thread);
1188 return longBox(thread, env, result);
1189 }
1190 return NULL;
1191 WB_END
1192
1193 WB_ENTRY(jobject, WB_GetMethodDoubleOption(JNIEnv* env, jobject wb, jobject method, jstring name))
1194 double result;
1195 if (GetMethodOption <double> (thread, env, method, name, &result)) {
1196 // can't be in VM when we call JNI
1197 ThreadToNativeFromVM ttnfv(thread);
1198 return doubleBox(thread, env, result);
1199 }
1200 return NULL;
1201 WB_END
1202
1203 WB_ENTRY(jobject, WB_GetMethodStringOption(JNIEnv* env, jobject wb, jobject method, jstring name))
1204 ccstr ccstrResult;
1205 if (GetMethodOption <ccstr> (thread, env, method, name, &ccstrResult)) {
1206 // can't be in VM when we call JNI
1207 ThreadToNativeFromVM ttnfv(thread);
1208 jstring result = env->NewStringUTF(ccstrResult);
1209 CHECK_JNI_EXCEPTION_(env, NULL);
1210 return result;
1211 }
1212 return NULL;
1213 WB_END
1214
1215 //Some convenience methods to deal with objects from java
1216 int WhiteBox::offset_for_field(const char* field_name, oop object,
1217 Symbol* signature_symbol) {
1218 assert(field_name != NULL && strlen(field_name) > 0, "Field name not valid");
1219 Thread* THREAD = Thread::current();
1220
1221 //Get the class of our object
1222 Klass* arg_klass = object->klass();
1223 //Turn it into an instance-klass
1224 InstanceKlass* ik = InstanceKlass::cast(arg_klass);
1225
1226 //Create symbols to look for in the class
1227 TempNewSymbol name_symbol = SymbolTable::lookup(field_name, (int) strlen(field_name),
1228 THREAD);
1229
1230 //To be filled in with an offset of the field we're looking for
1231 fieldDescriptor fd;
1232
1233 Klass* res = ik->find_field(name_symbol, signature_symbol, &fd);
1234 if (res == NULL) {
1235 tty->print_cr("Invalid layout of %s at %s", ik->external_name(),
1236 name_symbol->as_C_string());
1237 fatal("Invalid layout of preloaded class");
1238 }
1239
1240 //fetch the field at the offset we've found
1241 int dest_offset = fd.offset();
1242
1243 return dest_offset;
1244 }
1245
1246
1247 const char* WhiteBox::lookup_jstring(const char* field_name, oop object) {
1248 int offset = offset_for_field(field_name, object,
1249 vmSymbols::string_signature());
1250 oop string = object->obj_field(offset);
1251 if (string == NULL) {
1252 return NULL;
1253 }
1254 const char* ret = java_lang_String::as_utf8_string(string);
1255 return ret;
1256 }
1257
1258 bool WhiteBox::lookup_bool(const char* field_name, oop object) {
1259 int offset =
1260 offset_for_field(field_name, object, vmSymbols::bool_signature());
1261 bool ret = (object->bool_field(offset) == JNI_TRUE);
1262 return ret;
1263 }
1264
1265 void WhiteBox::register_methods(JNIEnv* env, jclass wbclass, JavaThread* thread, JNINativeMethod* method_array, int method_count) {
1266 ResourceMark rm;
1267 ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
1268
1269 // one by one registration natives for exception catching
1270 jclass no_such_method_error_klass = env->FindClass(vmSymbols::java_lang_NoSuchMethodError()->as_C_string());
1271 CHECK_JNI_EXCEPTION(env);
1272 for (int i = 0, n = method_count; i < n; ++i) {
1273 // Skip dummy entries
1274 if (method_array[i].fnPtr == NULL) continue;
1275 if (env->RegisterNatives(wbclass, &method_array[i], 1) != 0) {
1276 jthrowable throwable_obj = env->ExceptionOccurred();
1277 if (throwable_obj != NULL) {
1278 env->ExceptionClear();
1279 if (env->IsInstanceOf(throwable_obj, no_such_method_error_klass)) {
1280 // NoSuchMethodError is thrown when a method can't be found or a method is not native.
1281 // Ignoring the exception since it is not preventing use of other WhiteBox methods.
1282 tty->print_cr("Warning: 'NoSuchMethodError' on register of sun.hotspot.WhiteBox::%s%s",
1283 method_array[i].name, method_array[i].signature);
1284 }
1285 } else {
1286 // Registration failed unexpectedly.
1287 tty->print_cr("Warning: unexpected error on register of sun.hotspot.WhiteBox::%s%s. All methods will be unregistered",
1288 method_array[i].name, method_array[i].signature);
1289 env->UnregisterNatives(wbclass);
1290 break;
1291 }
1292 }
1293 }
1294 }
1295
1296 #define CC (char*)
1297
1298 static JNINativeMethod methods[] = {
1299 {CC"getObjectAddress", CC"(Ljava/lang/Object;)J", (void*)&WB_GetObjectAddress },
1300 {CC"getObjectSize", CC"(Ljava/lang/Object;)J", (void*)&WB_GetObjectSize },
1301 {CC"isObjectInOldGen", CC"(Ljava/lang/Object;)Z", (void*)&WB_isObjectInOldGen },
1302 {CC"getHeapOopSize", CC"()I", (void*)&WB_GetHeapOopSize },
1303 {CC"getVMPageSize", CC"()I", (void*)&WB_GetVMPageSize },
1304 {CC"isClassAlive0", CC"(Ljava/lang/String;)Z", (void*)&WB_IsClassAlive },
1305 {CC"parseCommandLine",
1306 CC"(Ljava/lang/String;C[Lsun/hotspot/parser/DiagnosticCommand;)[Ljava/lang/Object;",
1307 (void*) &WB_ParseCommandLine
1308 },
1309 {CC"addToBootstrapClassLoaderSearch", CC"(Ljava/lang/String;)V",
1310 (void*)&WB_AddToBootstrapClassLoaderSearch},
1311 {CC"addToSystemClassLoaderSearch", CC"(Ljava/lang/String;)V",
1312 (void*)&WB_AddToSystemClassLoaderSearch},
1313 {CC"getCompressedOopsMaxHeapSize", CC"()J",
1314 (void*)&WB_GetCompressedOopsMaxHeapSize},
1315 {CC"printHeapSizes", CC"()V", (void*)&WB_PrintHeapSizes },
1316 {CC"runMemoryUnitTests", CC"()V", (void*)&WB_RunMemoryUnitTests},
1317 {CC"readFromNoaccessArea",CC"()V", (void*)&WB_ReadFromNoaccessArea},
1318 {CC"stressVirtualSpaceResize",CC"(JJJ)I", (void*)&WB_StressVirtualSpaceResize},
1319 #if INCLUDE_ALL_GCS
1320 {CC"g1InConcurrentMark", CC"()Z", (void*)&WB_G1InConcurrentMark},
1321 {CC"g1IsHumongous", CC"(Ljava/lang/Object;)Z", (void*)&WB_G1IsHumongous },
1322 {CC"g1NumMaxRegions", CC"()J", (void*)&WB_G1NumMaxRegions },
1323 {CC"g1NumFreeRegions", CC"()J", (void*)&WB_G1NumFreeRegions },
1324 {CC"g1RegionSize", CC"()I", (void*)&WB_G1RegionSize },
1325 {CC"g1StartConcMarkCycle", CC"()Z", (void*)&WB_G1StartMarkCycle },
1326 {CC"g1AuxiliaryMemoryUsage", CC"()Ljava/lang/management/MemoryUsage;",
1327 (void*)&WB_G1AuxiliaryMemoryUsage },
1328 #endif // INCLUDE_ALL_GCS
1329 #if INCLUDE_NMT
1330 {CC"NMTMalloc", CC"(J)J", (void*)&WB_NMTMalloc },
1331 {CC"NMTMallocWithPseudoStack", CC"(JI)J", (void*)&WB_NMTMallocWithPseudoStack},
1332 {CC"NMTFree", CC"(J)V", (void*)&WB_NMTFree },
1333 {CC"NMTReserveMemory", CC"(J)J", (void*)&WB_NMTReserveMemory },
1334 {CC"NMTCommitMemory", CC"(JJ)V", (void*)&WB_NMTCommitMemory },
1335 {CC"NMTUncommitMemory", CC"(JJ)V", (void*)&WB_NMTUncommitMemory },
1336 {CC"NMTReleaseMemory", CC"(JJ)V", (void*)&WB_NMTReleaseMemory },
1337 {CC"NMTChangeTrackingLevel", CC"()Z", (void*)&WB_NMTChangeTrackingLevel},
1338 {CC"NMTGetHashSize", CC"()I", (void*)&WB_NMTGetHashSize },
1339 #endif // INCLUDE_NMT
1340 {CC"deoptimizeFrames", CC"(Z)I", (void*)&WB_DeoptimizeFrames },
1341 {CC"deoptimizeAll", CC"()V", (void*)&WB_DeoptimizeAll },
1342 {CC"deoptimizeMethod", CC"(Ljava/lang/reflect/Executable;Z)I",
1343 (void*)&WB_DeoptimizeMethod },
1344 {CC"isMethodCompiled", CC"(Ljava/lang/reflect/Executable;Z)Z",
1345 (void*)&WB_IsMethodCompiled },
1346 {CC"isMethodCompilable", CC"(Ljava/lang/reflect/Executable;IZ)Z",
1347 (void*)&WB_IsMethodCompilable},
1348 {CC"isMethodQueuedForCompilation",
1349 CC"(Ljava/lang/reflect/Executable;)Z", (void*)&WB_IsMethodQueuedForCompilation},
1350 {CC"makeMethodNotCompilable",
1351 CC"(Ljava/lang/reflect/Executable;IZ)V", (void*)&WB_MakeMethodNotCompilable},
1352 {CC"testSetDontInlineMethod",
1353 CC"(Ljava/lang/reflect/Executable;Z)Z", (void*)&WB_TestSetDontInlineMethod},
1354 {CC"getMethodCompilationLevel",
1355 CC"(Ljava/lang/reflect/Executable;Z)I", (void*)&WB_GetMethodCompilationLevel},
1356 {CC"getMethodEntryBci",
1357 CC"(Ljava/lang/reflect/Executable;)I", (void*)&WB_GetMethodEntryBci},
1358 {CC"getCompileQueueSize",
1359 CC"(I)I", (void*)&WB_GetCompileQueueSize},
1360 {CC"testSetForceInlineMethod",
1361 CC"(Ljava/lang/reflect/Executable;Z)Z", (void*)&WB_TestSetForceInlineMethod},
1362 {CC"enqueueMethodForCompilation",
1363 CC"(Ljava/lang/reflect/Executable;II)Z", (void*)&WB_EnqueueMethodForCompilation},
1364 {CC"clearMethodState",
1365 CC"(Ljava/lang/reflect/Executable;)V", (void*)&WB_ClearMethodState},
1366 {CC"lockCompilation", CC"()V", (void*)&WB_LockCompilation},
1367 {CC"unlockCompilation", CC"()V", (void*)&WB_UnlockCompilation},
1368 {CC"isConstantVMFlag", CC"(Ljava/lang/String;)Z", (void*)&WB_IsConstantVMFlag},
1369 {CC"isLockedVMFlag", CC"(Ljava/lang/String;)Z", (void*)&WB_IsLockedVMFlag},
1370 {CC"setBooleanVMFlag", CC"(Ljava/lang/String;Z)V",(void*)&WB_SetBooleanVMFlag},
1371 {CC"setIntxVMFlag", CC"(Ljava/lang/String;J)V",(void*)&WB_SetIntxVMFlag},
1372 {CC"setUintxVMFlag", CC"(Ljava/lang/String;J)V",(void*)&WB_SetUintxVMFlag},
1373 {CC"setUint64VMFlag", CC"(Ljava/lang/String;J)V",(void*)&WB_SetUint64VMFlag},
1374 {CC"setSizeTVMFlag", CC"(Ljava/lang/String;J)V",(void*)&WB_SetSizeTVMFlag},
1375 {CC"setDoubleVMFlag", CC"(Ljava/lang/String;D)V",(void*)&WB_SetDoubleVMFlag},
1376 {CC"setStringVMFlag", CC"(Ljava/lang/String;Ljava/lang/String;)V",
1377 (void*)&WB_SetStringVMFlag},
1378 {CC"getBooleanVMFlag", CC"(Ljava/lang/String;)Ljava/lang/Boolean;",
1379 (void*)&WB_GetBooleanVMFlag},
1380 {CC"getIntxVMFlag", CC"(Ljava/lang/String;)Ljava/lang/Long;",
1381 (void*)&WB_GetIntxVMFlag},
1382 {CC"getUintxVMFlag", CC"(Ljava/lang/String;)Ljava/lang/Long;",
1383 (void*)&WB_GetUintxVMFlag},
1384 {CC"getUint64VMFlag", CC"(Ljava/lang/String;)Ljava/lang/Long;",
1385 (void*)&WB_GetUint64VMFlag},
1386 {CC"getSizeTVMFlag", CC"(Ljava/lang/String;)Ljava/lang/Long;",
1387 (void*)&WB_GetSizeTVMFlag},
1388 {CC"getDoubleVMFlag", CC"(Ljava/lang/String;)Ljava/lang/Double;",
1389 (void*)&WB_GetDoubleVMFlag},
1390 {CC"getStringVMFlag", CC"(Ljava/lang/String;)Ljava/lang/String;",
1391 (void*)&WB_GetStringVMFlag},
1392 {CC"isInStringTable", CC"(Ljava/lang/String;)Z", (void*)&WB_IsInStringTable },
1393 {CC"fullGC", CC"()V", (void*)&WB_FullGC },
1394 {CC"youngGC", CC"()V", (void*)&WB_YoungGC },
1395 {CC"readReservedMemory", CC"()V", (void*)&WB_ReadReservedMemory },
1396 {CC"allocateMetaspace",
1397 CC"(Ljava/lang/ClassLoader;J)J", (void*)&WB_AllocateMetaspace },
1398 {CC"freeMetaspace",
1399 CC"(Ljava/lang/ClassLoader;JJ)V", (void*)&WB_FreeMetaspace },
1400 {CC"incMetaspaceCapacityUntilGC", CC"(J)J", (void*)&WB_IncMetaspaceCapacityUntilGC },
1401 {CC"metaspaceCapacityUntilGC", CC"()J", (void*)&WB_MetaspaceCapacityUntilGC },
1402 {CC"getCPUFeatures", CC"()Ljava/lang/String;", (void*)&WB_GetCPUFeatures },
1403 {CC"getNMethod", CC"(Ljava/lang/reflect/Executable;Z)[Ljava/lang/Object;",
1404 (void*)&WB_GetNMethod },
1405 {CC"forceNMethodSweep0", CC"()Ljava/lang/Thread;", (void*)&WB_ForceNMethodSweep },
1406 {CC"allocateCodeBlob", CC"(II)J", (void*)&WB_AllocateCodeBlob },
1407 {CC"freeCodeBlob", CC"(J)V", (void*)&WB_FreeCodeBlob },
1408 {CC"getCodeHeapEntries", CC"(I)[Ljava/lang/Object;",(void*)&WB_GetCodeHeapEntries },
1409 {CC"getCompilationActivityMode",
1410 CC"()I", (void*)&WB_GetCompilationActivityMode},
1411 {CC"getCodeBlob", CC"(J)[Ljava/lang/Object;",(void*)&WB_GetCodeBlob },
1412 {CC"getThreadStackSize", CC"()J", (void*)&WB_GetThreadStackSize },
1413 {CC"getThreadRemainingStackSize", CC"()J", (void*)&WB_GetThreadRemainingStackSize },
1414 {CC"assertMatchingSafepointCalls", CC"(ZZ)V", (void*)&WB_AssertMatchingSafepointCalls },
1415 {CC"isMonitorInflated", CC"(Ljava/lang/Object;)Z", (void*)&WB_IsMonitorInflated },
1416 {CC"forceSafepoint", CC"()V", (void*)&WB_ForceSafepoint },
1417 {CC"getMethodBooleanOption",
1418 CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)Ljava/lang/Boolean;",
1419 (void*)&WB_GetMethodBooleaneOption},
1420 {CC"getMethodIntxOption",
1421 CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)Ljava/lang/Long;",
1422 (void*)&WB_GetMethodIntxOption},
1423 {CC"getMethodUintxOption",
1424 CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)Ljava/lang/Long;",
1425 (void*)&WB_GetMethodUintxOption},
1426 {CC"getMethodDoubleOption",
1427 CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)Ljava/lang/Double;",
1428 (void*)&WB_GetMethodDoubleOption},
1429 {CC"getMethodStringOption",
1430 CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)Ljava/lang/String;",
1431 (void*)&WB_GetMethodStringOption},
1432 };
1433
1434 #undef CC
1435
1436 JVM_ENTRY(void, JVM_RegisterWhiteBoxMethods(JNIEnv* env, jclass wbclass))
1437 {
1438 if (WhiteBoxAPI) {
1439 // Make sure that wbclass is loaded by the null classloader
1440 instanceKlassHandle ikh = instanceKlassHandle(JNIHandles::resolve(wbclass)->klass());
1441 Handle loader(ikh->class_loader());
1442 if (loader.is_null()) {
1443 WhiteBox::register_methods(env, wbclass, thread, methods, sizeof(methods) / sizeof(methods[0]));
1444 WhiteBox::register_extended(env, wbclass, thread);
1445 WhiteBox::set_used();
1446 }
1447 }
1448 }
1449 JVM_END
--- EOF ---