Wed, 11 Sep 2019 12:06:33 +0200
8230707: JFR related tests are failing
Reviewed-by: neugens
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 */
25 #include "precompiled.hpp"
27 #include "memory/metadataFactory.hpp"
28 #include "memory/metaspaceShared.hpp"
29 #include "memory/iterator.hpp"
30 #include "memory/universe.hpp"
31 #include "oops/oop.inline.hpp"
33 #include "classfile/symbolTable.hpp"
34 #include "classfile/classLoaderData.hpp"
36 #include "prims/whitebox.hpp"
37 #include "prims/wbtestmethods/parserTests.hpp"
39 #include "runtime/arguments.hpp"
40 #include "runtime/interfaceSupport.hpp"
41 #include "runtime/os.hpp"
42 #include "utilities/array.hpp"
43 #include "utilities/align.hpp"
44 #include "utilities/debug.hpp"
45 #include "utilities/macros.hpp"
46 #include "utilities/exceptions.hpp"
48 #if INCLUDE_ALL_GCS
49 #include "gc_implementation/parallelScavenge/parallelScavengeHeap.inline.hpp"
50 #include "gc_implementation/g1/concurrentMark.hpp"
51 #include "gc_implementation/g1/concurrentMarkThread.hpp"
52 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
53 #include "gc_implementation/g1/heapRegionRemSet.hpp"
54 #endif // INCLUDE_ALL_GCS
56 #if INCLUDE_NMT
57 #include "services/mallocSiteTable.hpp"
58 #include "services/memTracker.hpp"
59 #include "utilities/nativeCallStack.hpp"
60 #endif // INCLUDE_NMT
62 #include "compiler/compileBroker.hpp"
63 #include "jvmtifiles/jvmtiEnv.hpp"
64 #include "runtime/compilationPolicy.hpp"
66 PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
68 #define SIZE_T_MAX_VALUE ((size_t) -1)
70 bool WhiteBox::_used = false;
72 WB_ENTRY(jlong, WB_GetObjectAddress(JNIEnv* env, jobject o, jobject obj))
73 return (jlong)(void*)JNIHandles::resolve(obj);
74 WB_END
76 WB_ENTRY(jint, WB_GetHeapOopSize(JNIEnv* env, jobject o))
77 return heapOopSize;
78 WB_END
80 WB_ENTRY(jint, WB_GetVMPageSize(JNIEnv* env, jobject o))
81 return os::vm_page_size();
82 WB_END
84 WB_ENTRY(jlong, WB_GetVMLargePageSize(JNIEnv* env, jobject o))
85 return os::large_page_size();
86 WB_END
88 class WBIsKlassAliveClosure : public KlassClosure {
89 Symbol* _name;
90 bool _found;
91 public:
92 WBIsKlassAliveClosure(Symbol* name) : _name(name), _found(false) {}
94 void do_klass(Klass* k) {
95 if (_found) return;
96 Symbol* ksym = k->name();
97 if (ksym->fast_compare(_name) == 0) {
98 _found = true;
99 }
100 }
102 bool found() const {
103 return _found;
104 }
105 };
107 WB_ENTRY(jboolean, WB_IsClassAlive(JNIEnv* env, jobject target, jstring name))
108 Handle h_name = JNIHandles::resolve(name);
109 if (h_name.is_null()) return false;
110 Symbol* sym = java_lang_String::as_symbol(h_name, CHECK_false);
111 TempNewSymbol tsym(sym); // Make sure to decrement reference count on sym on return
113 WBIsKlassAliveClosure closure(sym);
114 ClassLoaderDataGraph::classes_do(&closure);
116 return closure.found();
117 WB_END
119 WB_ENTRY(jboolean, WB_ClassKnownToNotExist(JNIEnv* env, jobject o, jobject loader, jstring name))
120 ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
121 const char* class_name = env->GetStringUTFChars(name, NULL);
122 jboolean result = JVM_KnownToNotExist(env, loader, class_name);
123 env->ReleaseStringUTFChars(name, class_name);
124 return result;
125 WB_END
127 WB_ENTRY(jobjectArray, WB_GetLookupCacheURLs(JNIEnv* env, jobject o, jobject loader))
128 ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
129 return JVM_GetResourceLookupCacheURLs(env, loader);
130 WB_END
132 WB_ENTRY(jintArray, WB_GetLookupCacheMatches(JNIEnv* env, jobject o, jobject loader, jstring name))
133 ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
134 const char* resource_name = env->GetStringUTFChars(name, NULL);
135 jintArray result = JVM_GetResourceLookupCache(env, loader, resource_name);
137 env->ReleaseStringUTFChars(name, resource_name);
138 return result;
139 WB_END
141 WB_ENTRY(void, WB_AddToBootstrapClassLoaderSearch(JNIEnv* env, jobject o, jstring segment)) {
142 #if INCLUDE_JVMTI
143 ResourceMark rm;
144 const char* seg = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(segment));
145 JvmtiEnv* jvmti_env = JvmtiEnv::create_a_jvmti(JVMTI_VERSION);
146 jvmtiError err = jvmti_env->AddToBootstrapClassLoaderSearch(seg);
147 assert(err == JVMTI_ERROR_NONE, "must not fail");
148 #endif
149 }
150 WB_END
152 WB_ENTRY(void, WB_AddToSystemClassLoaderSearch(JNIEnv* env, jobject o, jstring segment)) {
153 #if INCLUDE_JVMTI
154 ResourceMark rm;
155 const char* seg = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(segment));
156 JvmtiEnv* jvmti_env = JvmtiEnv::create_a_jvmti(JVMTI_VERSION);
157 jvmtiError err = jvmti_env->AddToSystemClassLoaderSearch(seg);
158 assert(err == JVMTI_ERROR_NONE, "must not fail");
159 #endif
160 }
161 WB_END
163 #ifdef LINUX
164 #include "utilities/elfFile.hpp"
165 #include "osContainer_linux.hpp"
166 #endif
168 WB_ENTRY(jlong, WB_GetCompressedOopsMaxHeapSize(JNIEnv* env, jobject o)) {
169 return (jlong)Arguments::max_heap_for_compressed_oops();
170 }
171 WB_END
173 WB_ENTRY(void, WB_PrintHeapSizes(JNIEnv* env, jobject o)) {
174 CollectorPolicy * p = Universe::heap()->collector_policy();
175 gclog_or_tty->print_cr("Minimum heap " SIZE_FORMAT " Initial heap "
176 SIZE_FORMAT " Maximum heap " SIZE_FORMAT " Space alignment " SIZE_FORMAT " Heap alignment " SIZE_FORMAT,
177 p->min_heap_byte_size(), p->initial_heap_byte_size(), p->max_heap_byte_size(),
178 p->space_alignment(), p->heap_alignment());
179 }
180 WB_END
182 #ifndef PRODUCT
183 // Forward declaration
184 void TestReservedSpace_test();
185 void TestReserveMemorySpecial_test();
186 void TestVirtualSpace_test();
187 void TestMetaspaceAux_test();
188 #endif
190 WB_ENTRY(void, WB_RunMemoryUnitTests(JNIEnv* env, jobject o))
191 #ifndef PRODUCT
192 TestReservedSpace_test();
193 TestReserveMemorySpecial_test();
194 TestVirtualSpace_test();
195 TestMetaspaceAux_test();
196 #endif
197 WB_END
199 WB_ENTRY(void, WB_ReadFromNoaccessArea(JNIEnv* env, jobject o))
200 size_t granularity = os::vm_allocation_granularity();
201 ReservedHeapSpace rhs(100 * granularity, granularity, false, NULL);
202 VirtualSpace vs;
203 vs.initialize(rhs, 50 * granularity);
205 //Check if constraints are complied
206 if (!( UseCompressedOops && rhs.base() != NULL &&
207 Universe::narrow_oop_base() != NULL &&
208 Universe::narrow_oop_use_implicit_null_checks() )) {
209 tty->print_cr("WB_ReadFromNoaccessArea method is useless:\n "
210 "\tUseCompressedOops is %d\n"
211 "\trhs.base() is " PTR_FORMAT "\n"
212 "\tUniverse::narrow_oop_base() is " PTR_FORMAT "\n"
213 "\tUniverse::narrow_oop_use_implicit_null_checks() is %d",
214 UseCompressedOops,
215 rhs.base(),
216 Universe::narrow_oop_base(),
217 Universe::narrow_oop_use_implicit_null_checks());
218 return;
219 }
220 tty->print_cr("Reading from no access area... ");
221 tty->print_cr("*(vs.low_boundary() - rhs.noaccess_prefix() / 2 ) = %c",
222 *(vs.low_boundary() - rhs.noaccess_prefix() / 2 ));
223 WB_END
225 static jint wb_stress_virtual_space_resize(size_t reserved_space_size,
226 size_t magnitude, size_t iterations) {
227 size_t granularity = os::vm_allocation_granularity();
228 ReservedHeapSpace rhs(reserved_space_size * granularity, granularity, false, NULL);
229 VirtualSpace vs;
230 if (!vs.initialize(rhs, 0)) {
231 tty->print_cr("Failed to initialize VirtualSpace. Can't proceed.");
232 return 3;
233 }
235 long seed = os::random();
236 tty->print_cr("Random seed is %ld", seed);
237 os::init_random(seed);
239 for (size_t i = 0; i < iterations; i++) {
241 // Whether we will shrink or grow
242 bool shrink = os::random() % 2L == 0;
244 // Get random delta to resize virtual space
245 size_t delta = (size_t)os::random() % magnitude;
247 // If we are about to shrink virtual space below zero, then expand instead
248 if (shrink && vs.committed_size() < delta) {
249 shrink = false;
250 }
252 // Resizing by delta
253 if (shrink) {
254 vs.shrink_by(delta);
255 } else {
256 // If expanding fails expand_by will silently return false
257 vs.expand_by(delta, true);
258 }
259 }
260 return 0;
261 }
263 WB_ENTRY(jint, WB_StressVirtualSpaceResize(JNIEnv* env, jobject o,
264 jlong reserved_space_size, jlong magnitude, jlong iterations))
265 tty->print_cr("reservedSpaceSize=" JLONG_FORMAT ", magnitude=" JLONG_FORMAT ", "
266 "iterations=" JLONG_FORMAT "\n", reserved_space_size, magnitude,
267 iterations);
268 if (reserved_space_size < 0 || magnitude < 0 || iterations < 0) {
269 tty->print_cr("One of variables printed above is negative. Can't proceed.\n");
270 return 1;
271 }
273 // sizeof(size_t) depends on whether OS is 32bit or 64bit. sizeof(jlong) is
274 // always 8 byte. That's why we should avoid overflow in case of 32bit platform.
275 if (sizeof(size_t) < sizeof(jlong)) {
276 jlong size_t_max_value = (jlong) SIZE_T_MAX_VALUE;
277 if (reserved_space_size > size_t_max_value || magnitude > size_t_max_value
278 || iterations > size_t_max_value) {
279 tty->print_cr("One of variables printed above overflows size_t. Can't proceed.\n");
280 return 2;
281 }
282 }
284 return wb_stress_virtual_space_resize((size_t) reserved_space_size,
285 (size_t) magnitude, (size_t) iterations);
286 WB_END
288 WB_ENTRY(jboolean, WB_isObjectInOldGen(JNIEnv* env, jobject o, jobject obj))
289 oop p = JNIHandles::resolve(obj);
290 #if INCLUDE_ALL_GCS
291 if (UseG1GC) {
292 G1CollectedHeap* g1 = G1CollectedHeap::heap();
293 const HeapRegion* hr = g1->heap_region_containing(p);
294 if (hr == NULL) {
295 return false;
296 }
297 return !(hr->is_young());
298 } else if (UseParallelGC) {
299 ParallelScavengeHeap* psh = ParallelScavengeHeap::heap();
300 return !psh->is_in_young(p);
301 }
302 #endif // INCLUDE_ALL_GCS
303 GenCollectedHeap* gch = GenCollectedHeap::heap();
304 return !gch->is_in_young(p);
305 WB_END
307 WB_ENTRY(jlong, WB_GetObjectSize(JNIEnv* env, jobject o, jobject obj))
308 oop p = JNIHandles::resolve(obj);
309 return p->size() * HeapWordSize;
310 WB_END
312 #if INCLUDE_ALL_GCS
313 WB_ENTRY(jboolean, WB_G1IsHumongous(JNIEnv* env, jobject o, jobject obj))
314 G1CollectedHeap* g1 = G1CollectedHeap::heap();
315 oop result = JNIHandles::resolve(obj);
316 const HeapRegion* hr = g1->heap_region_containing(result);
317 return hr->isHumongous();
318 WB_END
320 WB_ENTRY(jlong, WB_G1NumMaxRegions(JNIEnv* env, jobject o))
321 G1CollectedHeap* g1 = G1CollectedHeap::heap();
322 size_t nr = g1->max_regions();
323 return (jlong)nr;
324 WB_END
326 WB_ENTRY(jlong, WB_G1NumFreeRegions(JNIEnv* env, jobject o))
327 G1CollectedHeap* g1 = G1CollectedHeap::heap();
328 size_t nr = g1->num_free_regions();
329 return (jlong)nr;
330 WB_END
332 WB_ENTRY(jboolean, WB_G1InConcurrentMark(JNIEnv* env, jobject o))
333 G1CollectedHeap* g1 = G1CollectedHeap::heap();
334 return g1->concurrent_mark()->cmThread()->during_cycle();
335 WB_END
337 WB_ENTRY(jboolean, WB_G1StartMarkCycle(JNIEnv* env, jobject o))
338 G1CollectedHeap* g1h = G1CollectedHeap::heap();
339 if (!g1h->concurrent_mark()->cmThread()->during_cycle()) {
340 g1h->collect(GCCause::_wb_conc_mark);
341 return true;
342 }
343 return false;
344 WB_END
346 WB_ENTRY(jint, WB_G1RegionSize(JNIEnv* env, jobject o))
347 return (jint)HeapRegion::GrainBytes;
348 WB_END
350 WB_ENTRY(jobject, WB_G1AuxiliaryMemoryUsage(JNIEnv* env))
351 ResourceMark rm(THREAD);
352 G1CollectedHeap* g1h = G1CollectedHeap::heap();
353 MemoryUsage usage = g1h->get_auxiliary_data_memory_usage();
354 Handle h = MemoryService::create_MemoryUsage_obj(usage, CHECK_NULL);
355 return JNIHandles::make_local(env, h());
356 WB_END
357 #endif // INCLUDE_ALL_GCS
359 #if INCLUDE_NMT
360 // Alloc memory using the test memory type so that we can use that to see if
361 // NMT picks it up correctly
362 WB_ENTRY(jlong, WB_NMTMalloc(JNIEnv* env, jobject o, jlong size))
363 jlong addr = 0;
364 addr = (jlong)(uintptr_t)os::malloc(size, mtTest);
365 return addr;
366 WB_END
368 // Alloc memory with pseudo call stack. The test can create psudo malloc
369 // allocation site to stress the malloc tracking.
370 WB_ENTRY(jlong, WB_NMTMallocWithPseudoStack(JNIEnv* env, jobject o, jlong size, jint pseudo_stack))
371 address pc = (address)(size_t)pseudo_stack;
372 NativeCallStack stack(&pc, 1);
373 return (jlong)(uintptr_t)os::malloc(size, mtTest, stack);
374 WB_END
376 // Alloc memory with pseudo call stack and specific memory type.
377 WB_ENTRY(jlong, WB_NMTMallocWithPseudoStackAndType(JNIEnv* env, jobject o, jlong size, jint pseudo_stack, jint type))
378 address pc = (address)(size_t)pseudo_stack;
379 NativeCallStack stack(&pc, 1);
380 return (jlong)(uintptr_t)os::malloc(size, (MEMFLAGS)type, stack);
381 WB_END
383 // Free the memory allocated by NMTAllocTest
384 WB_ENTRY(void, WB_NMTFree(JNIEnv* env, jobject o, jlong mem))
385 os::free((void*)(uintptr_t)mem, mtTest);
386 WB_END
388 WB_ENTRY(jlong, WB_NMTReserveMemory(JNIEnv* env, jobject o, jlong size))
389 jlong addr = 0;
391 addr = (jlong)(uintptr_t)os::reserve_memory(size);
392 MemTracker::record_virtual_memory_type((address)addr, mtTest);
394 return addr;
395 WB_END
398 WB_ENTRY(void, WB_NMTCommitMemory(JNIEnv* env, jobject o, jlong addr, jlong size))
399 os::commit_memory((char *)(uintptr_t)addr, size, !ExecMem);
400 MemTracker::record_virtual_memory_type((address)(uintptr_t)addr, mtTest);
401 WB_END
403 WB_ENTRY(void, WB_NMTUncommitMemory(JNIEnv* env, jobject o, jlong addr, jlong size))
404 os::uncommit_memory((char *)(uintptr_t)addr, size);
405 WB_END
407 WB_ENTRY(void, WB_NMTReleaseMemory(JNIEnv* env, jobject o, jlong addr, jlong size))
408 os::release_memory((char *)(uintptr_t)addr, size);
409 WB_END
411 WB_ENTRY(jboolean, WB_NMTIsDetailSupported(JNIEnv* env))
412 return MemTracker::tracking_level() == NMT_detail;
413 WB_END
415 WB_ENTRY(jboolean, WB_NMTChangeTrackingLevel(JNIEnv* env))
416 // Test that we can downgrade NMT levels but not upgrade them.
417 if (MemTracker::tracking_level() == NMT_off) {
418 MemTracker::transition_to(NMT_off);
419 return MemTracker::tracking_level() == NMT_off;
420 } else {
421 assert(MemTracker::tracking_level() == NMT_detail, "Should start out as detail tracking");
422 MemTracker::transition_to(NMT_summary);
423 assert(MemTracker::tracking_level() == NMT_summary, "Should be summary now");
425 // Can't go to detail once NMT is set to summary.
426 MemTracker::transition_to(NMT_detail);
427 assert(MemTracker::tracking_level() == NMT_summary, "Should still be summary now");
429 // Shutdown sets tracking level to minimal.
430 MemTracker::shutdown();
431 assert(MemTracker::tracking_level() == NMT_minimal, "Should be minimal now");
433 // Once the tracking level is minimal, we cannot increase to summary.
434 // The code ignores this request instead of asserting because if the malloc site
435 // table overflows in another thread, it tries to change the code to summary.
436 MemTracker::transition_to(NMT_summary);
437 assert(MemTracker::tracking_level() == NMT_minimal, "Should still be minimal now");
439 // Really can never go up to detail, verify that the code would never do this.
440 MemTracker::transition_to(NMT_detail);
441 assert(MemTracker::tracking_level() == NMT_minimal, "Should still be minimal now");
442 return MemTracker::tracking_level() == NMT_minimal;
443 }
444 WB_END
446 WB_ENTRY(jint, WB_NMTGetHashSize(JNIEnv* env, jobject o))
447 int hash_size = MallocSiteTable::hash_buckets();
448 assert(hash_size > 0, "NMT hash_size should be > 0");
449 return (jint)hash_size;
450 WB_END
451 #endif // INCLUDE_NMT
453 static jmethodID reflected_method_to_jmid(JavaThread* thread, JNIEnv* env, jobject method) {
454 assert(method != NULL, "method should not be null");
455 ThreadToNativeFromVM ttn(thread);
456 return env->FromReflectedMethod(method);
457 }
459 WB_ENTRY(void, WB_DeoptimizeAll(JNIEnv* env, jobject o))
460 MutexLockerEx mu(Compile_lock);
461 CodeCache::mark_all_nmethods_for_deoptimization();
462 VM_Deoptimize op;
463 VMThread::execute(&op);
464 WB_END
466 WB_ENTRY(jint, WB_DeoptimizeMethod(JNIEnv* env, jobject o, jobject method, jboolean is_osr))
467 jmethodID jmid = reflected_method_to_jmid(thread, env, method);
468 int result = 0;
469 CHECK_JNI_EXCEPTION_(env, result);
470 MutexLockerEx mu(Compile_lock);
471 methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
472 if (is_osr) {
473 result += mh->mark_osr_nmethods();
474 } else if (mh->code() != NULL) {
475 mh->code()->mark_for_deoptimization();
476 ++result;
477 }
478 result += CodeCache::mark_for_deoptimization(mh());
479 if (result > 0) {
480 VM_Deoptimize op;
481 VMThread::execute(&op);
482 }
483 return result;
484 WB_END
486 WB_ENTRY(jboolean, WB_IsMethodCompiled(JNIEnv* env, jobject o, jobject method, jboolean is_osr))
487 jmethodID jmid = reflected_method_to_jmid(thread, env, method);
488 CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
489 MutexLockerEx mu(Compile_lock);
490 methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
491 nmethod* code = is_osr ? mh->lookup_osr_nmethod_for(InvocationEntryBci, CompLevel_none, false) : mh->code();
492 if (code == NULL) {
493 return JNI_FALSE;
494 }
495 return (code->is_alive() && !code->is_marked_for_deoptimization());
496 WB_END
498 WB_ENTRY(jboolean, WB_IsMethodCompilable(JNIEnv* env, jobject o, jobject method, jint comp_level, jboolean is_osr))
499 jmethodID jmid = reflected_method_to_jmid(thread, env, method);
500 CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
501 MutexLockerEx mu(Compile_lock);
502 methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
503 if (is_osr) {
504 return CompilationPolicy::can_be_osr_compiled(mh, comp_level);
505 } else {
506 return CompilationPolicy::can_be_compiled(mh, comp_level);
507 }
508 WB_END
510 WB_ENTRY(jboolean, WB_IsMethodQueuedForCompilation(JNIEnv* env, jobject o, jobject method))
511 jmethodID jmid = reflected_method_to_jmid(thread, env, method);
512 CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
513 MutexLockerEx mu(Compile_lock);
514 methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
515 return mh->queued_for_compilation();
516 WB_END
518 WB_ENTRY(jint, WB_GetMethodCompilationLevel(JNIEnv* env, jobject o, jobject method, jboolean is_osr))
519 jmethodID jmid = reflected_method_to_jmid(thread, env, method);
520 CHECK_JNI_EXCEPTION_(env, CompLevel_none);
521 methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
522 nmethod* code = is_osr ? mh->lookup_osr_nmethod_for(InvocationEntryBci, CompLevel_none, false) : mh->code();
523 return (code != NULL ? code->comp_level() : CompLevel_none);
524 WB_END
526 WB_ENTRY(void, WB_MakeMethodNotCompilable(JNIEnv* env, jobject o, jobject method, jint comp_level, jboolean is_osr))
527 jmethodID jmid = reflected_method_to_jmid(thread, env, method);
528 CHECK_JNI_EXCEPTION(env);
529 methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
530 if (is_osr) {
531 mh->set_not_osr_compilable(comp_level, true /* report */, "WhiteBox");
532 } else {
533 mh->set_not_compilable(comp_level, true /* report */, "WhiteBox");
534 }
535 WB_END
537 WB_ENTRY(jint, WB_GetMethodEntryBci(JNIEnv* env, jobject o, jobject method))
538 jmethodID jmid = reflected_method_to_jmid(thread, env, method);
539 CHECK_JNI_EXCEPTION_(env, InvocationEntryBci);
540 methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
541 nmethod* code = mh->lookup_osr_nmethod_for(InvocationEntryBci, CompLevel_none, false);
542 return (code != NULL && code->is_osr_method() ? code->osr_entry_bci() : InvocationEntryBci);
543 WB_END
545 WB_ENTRY(jboolean, WB_TestSetDontInlineMethod(JNIEnv* env, jobject o, jobject method, jboolean value))
546 jmethodID jmid = reflected_method_to_jmid(thread, env, method);
547 CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
548 methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
549 bool result = mh->dont_inline();
550 mh->set_dont_inline(value == JNI_TRUE);
551 return result;
552 WB_END
554 WB_ENTRY(jint, WB_GetCompileQueueSize(JNIEnv* env, jobject o, jint comp_level))
555 if (comp_level == CompLevel_any) {
556 return CompileBroker::queue_size(CompLevel_full_optimization) /* C2 */ +
557 CompileBroker::queue_size(CompLevel_full_profile) /* C1 */;
558 } else {
559 return CompileBroker::queue_size(comp_level);
560 }
561 WB_END
563 WB_ENTRY(jboolean, WB_TestSetForceInlineMethod(JNIEnv* env, jobject o, jobject method, jboolean value))
564 jmethodID jmid = reflected_method_to_jmid(thread, env, method);
565 CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
566 methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
567 bool result = mh->force_inline();
568 mh->set_force_inline(value == JNI_TRUE);
569 return result;
570 WB_END
572 bool WhiteBox::compile_method(Method* method, int comp_level, int bci, Thread* THREAD) {
573 // Screen for unavailable/bad comp level or null method
574 AbstractCompiler* comp = CompileBroker::compiler(comp_level);
575 if (method == NULL) {
576 tty->print_cr("WB error: request to compile NULL method");
577 return false;
578 }
579 if (comp_level > MIN2((CompLevel) TieredStopAtLevel, CompLevel_highest_tier)) {
580 tty->print_cr("WB error: invalid compilation level %d", comp_level);
581 return false;
582 }
583 if (comp == NULL) {
584 tty->print_cr("WB error: no compiler for requested compilation level %d", comp_level);
585 return false;
586 }
588 methodHandle mh(THREAD, method);
590 // Compile method and check result
591 nmethod* nm = CompileBroker::compile_method(mh, bci, comp_level, mh, mh->invocation_count(), "Whitebox", THREAD);
592 MutexLocker mu(Compile_lock);
593 bool is_queued = mh->queued_for_compilation();
594 if (is_queued || nm != NULL) {
595 return true;
596 }
597 tty->print("WB error: failed to compile at level %d method ", comp_level);
598 mh->print_short_name(tty);
599 tty->cr();
600 if (is_queued) {
601 tty->print_cr("WB error: blocking compilation is still in queue!");
602 }
603 return false;
604 }
606 WB_ENTRY(jboolean, WB_EnqueueMethodForCompilation(JNIEnv* env, jobject o, jobject method, jint comp_level, jint bci))
607 jmethodID jmid = reflected_method_to_jmid(thread, env, method);
608 CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
609 return WhiteBox::compile_method(Method::checked_resolve_jmethod_id(jmid), comp_level, bci, THREAD);
610 WB_END
612 WB_ENTRY(jboolean, WB_EnqueueInitializerForCompilation(JNIEnv* env, jobject o, jclass klass, jint comp_level))
613 InstanceKlass* ik = InstanceKlass::cast(java_lang_Class::as_Klass(JNIHandles::resolve(klass)));
614 Method* clinit = ik->class_initializer();
615 if (clinit == NULL) {
616 return false;
617 }
618 return WhiteBox::compile_method(clinit, comp_level, InvocationEntryBci, THREAD);
619 WB_END
621 class VM_WhiteBoxOperation : public VM_Operation {
622 public:
623 VM_WhiteBoxOperation() { }
624 VMOp_Type type() const { return VMOp_WhiteBoxOperation; }
625 bool allow_nested_vm_operations() const { return true; }
626 };
628 static AlwaysFalseClosure always_false;
630 class VM_WhiteBoxCleanMethodData : public VM_WhiteBoxOperation {
631 public:
632 VM_WhiteBoxCleanMethodData(MethodData* mdo) : _mdo(mdo) { }
633 void doit() {
634 _mdo->clean_method_data(&always_false);
635 }
636 private:
637 MethodData* _mdo;
638 };
640 WB_ENTRY(void, WB_ClearMethodState(JNIEnv* env, jobject o, jobject method))
641 jmethodID jmid = reflected_method_to_jmid(thread, env, method);
642 CHECK_JNI_EXCEPTION(env);
643 methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
644 MutexLockerEx mu(Compile_lock);
645 MethodData* mdo = mh->method_data();
646 MethodCounters* mcs = mh->method_counters();
648 if (mdo != NULL) {
649 mdo->init();
650 ResourceMark rm;
651 int arg_count = mdo->method()->size_of_parameters();
652 for (int i = 0; i < arg_count; i++) {
653 mdo->set_arg_modified(i, 0);
654 }
655 VM_WhiteBoxCleanMethodData op(mdo);
656 VMThread::execute(&op);
657 }
659 mh->clear_not_c1_compilable();
660 mh->clear_not_c2_compilable();
661 mh->clear_not_c2_osr_compilable();
662 NOT_PRODUCT(mh->set_compiled_invocation_count(0));
663 if (mcs != NULL) {
664 mcs->backedge_counter()->init();
665 mcs->invocation_counter()->init();
666 mcs->set_interpreter_invocation_count(0);
667 mcs->set_interpreter_throwout_count(0);
669 #ifdef TIERED
670 mcs->set_rate(0.0F);
671 mh->set_prev_event_count(0);
672 mh->set_prev_time(0);
673 #endif
674 }
675 WB_END
677 WB_ENTRY(void, WB_MarkMethodProfiled(JNIEnv* env, jobject o, jobject method))
678 jmethodID jmid = reflected_method_to_jmid(thread, env, method);
679 CHECK_JNI_EXCEPTION(env);
680 methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
682 MethodData* mdo = mh->method_data();
683 if (mdo == NULL) {
684 Method::build_interpreter_method_data(mh, CHECK_AND_CLEAR);
685 mdo = mh->method_data();
686 }
687 mdo->init();
688 InvocationCounter* icnt = mdo->invocation_counter();
689 InvocationCounter* bcnt = mdo->backedge_counter();
690 // set i-counter according to AdvancedThresholdPolicy::is_method_profiled
691 // because SimpleThresholdPolicy::call_predicate_helper uses > in jdk8u, that's why we need to plus one.
692 icnt->set(InvocationCounter::wait_for_compile, Tier4MinInvocationThreshold + 1);
693 bcnt->set(InvocationCounter::wait_for_compile, Tier4CompileThreshold + 1);
694 WB_END
696 template <typename T>
697 static bool GetVMFlag(JavaThread* thread, JNIEnv* env, jstring name, T* value, bool (*TAt)(const char*, T*, bool, bool)) {
698 if (name == NULL) {
699 return false;
700 }
701 ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
702 const char* flag_name = env->GetStringUTFChars(name, NULL);
703 bool result = (*TAt)(flag_name, value, true, true);
704 env->ReleaseStringUTFChars(name, flag_name);
705 return result;
706 }
708 template <typename T>
709 static bool SetVMFlag(JavaThread* thread, JNIEnv* env, jstring name, T* value, bool (*TAtPut)(const char*, T*, Flag::Flags)) {
710 if (name == NULL) {
711 return false;
712 }
713 ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
714 const char* flag_name = env->GetStringUTFChars(name, NULL);
715 bool result = (*TAtPut)(flag_name, value, Flag::INTERNAL);
716 env->ReleaseStringUTFChars(name, flag_name);
717 return result;
718 }
720 template <typename T>
721 static jobject box(JavaThread* thread, JNIEnv* env, Symbol* name, Symbol* sig, T value) {
722 ResourceMark rm(thread);
723 jclass clazz = env->FindClass(name->as_C_string());
724 CHECK_JNI_EXCEPTION_(env, NULL);
725 jmethodID methodID = env->GetStaticMethodID(clazz,
726 vmSymbols::valueOf_name()->as_C_string(),
727 sig->as_C_string());
728 CHECK_JNI_EXCEPTION_(env, NULL);
729 jobject result = env->CallStaticObjectMethod(clazz, methodID, value);
730 CHECK_JNI_EXCEPTION_(env, NULL);
731 return result;
732 }
734 static jobject booleanBox(JavaThread* thread, JNIEnv* env, jboolean value) {
735 return box(thread, env, vmSymbols::java_lang_Boolean(), vmSymbols::Boolean_valueOf_signature(), value);
736 }
737 static jobject integerBox(JavaThread* thread, JNIEnv* env, jint value) {
738 return box(thread, env, vmSymbols::java_lang_Integer(), vmSymbols::Integer_valueOf_signature(), value);
739 }
740 static jobject longBox(JavaThread* thread, JNIEnv* env, jlong value) {
741 return box(thread, env, vmSymbols::java_lang_Long(), vmSymbols::Long_valueOf_signature(), value);
742 }
743 /* static jobject floatBox(JavaThread* thread, JNIEnv* env, jfloat value) {
744 return box(thread, env, vmSymbols::java_lang_Float(), vmSymbols::Float_valueOf_signature(), value);
745 }*/
746 static jobject doubleBox(JavaThread* thread, JNIEnv* env, jdouble value) {
747 return box(thread, env, vmSymbols::java_lang_Double(), vmSymbols::Double_valueOf_signature(), value);
748 }
750 WB_ENTRY(jobject, WB_GetBooleanVMFlag(JNIEnv* env, jobject o, jstring name))
751 bool result;
752 if (GetVMFlag <bool> (thread, env, name, &result, &CommandLineFlags::boolAt)) {
753 ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
754 return booleanBox(thread, env, result);
755 }
756 return NULL;
757 WB_END
759 WB_ENTRY(jobject, WB_GetIntxVMFlag(JNIEnv* env, jobject o, jstring name))
760 intx result;
761 if (GetVMFlag <intx> (thread, env, name, &result, &CommandLineFlags::intxAt)) {
762 ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
763 return longBox(thread, env, result);
764 }
765 return NULL;
766 WB_END
768 WB_ENTRY(jobject, WB_GetUintxVMFlag(JNIEnv* env, jobject o, jstring name))
769 uintx result;
770 if (GetVMFlag <uintx> (thread, env, name, &result, &CommandLineFlags::uintxAt)) {
771 ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
772 return longBox(thread, env, result);
773 }
774 return NULL;
775 WB_END
777 WB_ENTRY(jobject, WB_GetUint64VMFlag(JNIEnv* env, jobject o, jstring name))
778 uint64_t result;
779 if (GetVMFlag <uint64_t> (thread, env, name, &result, &CommandLineFlags::uint64_tAt)) {
780 ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
781 return longBox(thread, env, result);
782 }
783 return NULL;
784 WB_END
786 WB_ENTRY(jobject, WB_GetDoubleVMFlag(JNIEnv* env, jobject o, jstring name))
787 double result;
788 if (GetVMFlag <double> (thread, env, name, &result, &CommandLineFlags::doubleAt)) {
789 ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
790 return doubleBox(thread, env, result);
791 }
792 return NULL;
793 WB_END
795 WB_ENTRY(jstring, WB_GetStringVMFlag(JNIEnv* env, jobject o, jstring name))
796 ccstr ccstrResult;
797 if (GetVMFlag <ccstr> (thread, env, name, &ccstrResult, &CommandLineFlags::ccstrAt)) {
798 ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
799 jstring result = env->NewStringUTF(ccstrResult);
800 CHECK_JNI_EXCEPTION_(env, NULL);
801 return result;
802 }
803 return NULL;
804 WB_END
806 WB_ENTRY(void, WB_SetBooleanVMFlag(JNIEnv* env, jobject o, jstring name, jboolean value))
807 bool result = value == JNI_TRUE ? true : false;
808 SetVMFlag <bool> (thread, env, name, &result, &CommandLineFlags::boolAtPut);
809 WB_END
811 WB_ENTRY(void, WB_SetIntxVMFlag(JNIEnv* env, jobject o, jstring name, jlong value))
812 intx result = value;
813 SetVMFlag <intx> (thread, env, name, &result, &CommandLineFlags::intxAtPut);
814 WB_END
816 WB_ENTRY(void, WB_SetUintxVMFlag(JNIEnv* env, jobject o, jstring name, jlong value))
817 uintx result = value;
818 SetVMFlag <uintx> (thread, env, name, &result, &CommandLineFlags::uintxAtPut);
819 WB_END
821 WB_ENTRY(void, WB_SetUint64VMFlag(JNIEnv* env, jobject o, jstring name, jlong value))
822 uint64_t result = value;
823 SetVMFlag <uint64_t> (thread, env, name, &result, &CommandLineFlags::uint64_tAtPut);
824 WB_END
826 WB_ENTRY(void, WB_SetDoubleVMFlag(JNIEnv* env, jobject o, jstring name, jdouble value))
827 double result = value;
828 SetVMFlag <double> (thread, env, name, &result, &CommandLineFlags::doubleAtPut);
829 WB_END
831 WB_ENTRY(void, WB_SetStringVMFlag(JNIEnv* env, jobject o, jstring name, jstring value))
832 ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
833 const char* ccstrValue = (value == NULL) ? NULL : env->GetStringUTFChars(value, NULL);
834 ccstr ccstrResult = ccstrValue;
835 bool needFree;
836 {
837 ThreadInVMfromNative ttvfn(thread); // back to VM
838 needFree = SetVMFlag <ccstr> (thread, env, name, &ccstrResult, &CommandLineFlags::ccstrAtPut);
839 }
840 if (value != NULL) {
841 env->ReleaseStringUTFChars(value, ccstrValue);
842 }
843 if (needFree) {
844 FREE_C_HEAP_ARRAY(char, ccstrResult, mtInternal);
845 }
846 WB_END
848 WB_ENTRY(jboolean, WB_IsInStringTable(JNIEnv* env, jobject o, jstring javaString))
849 ResourceMark rm(THREAD);
850 int len;
851 jchar* name = java_lang_String::as_unicode_string(JNIHandles::resolve(javaString), len, CHECK_false);
852 return (StringTable::lookup(name, len) != NULL);
853 WB_END
855 WB_ENTRY(void, WB_FullGC(JNIEnv* env, jobject o))
856 Universe::heap()->collector_policy()->set_should_clear_all_soft_refs(true);
857 Universe::heap()->collect(GCCause::_last_ditch_collection);
858 #if INCLUDE_ALL_GCS
859 if (UseG1GC) {
860 // Needs to be cleared explicitly for G1
861 Universe::heap()->collector_policy()->set_should_clear_all_soft_refs(false);
862 }
863 #endif // INCLUDE_ALL_GCS
864 WB_END
866 WB_ENTRY(void, WB_YoungGC(JNIEnv* env, jobject o))
867 Universe::heap()->collect(GCCause::_wb_young_gc);
868 WB_END
870 WB_ENTRY(void, WB_ReadReservedMemory(JNIEnv* env, jobject o))
871 // static+volatile in order to force the read to happen
872 // (not be eliminated by the compiler)
873 static char c;
874 static volatile char* p;
876 p = os::reserve_memory(os::vm_allocation_granularity(), NULL, 0);
877 if (p == NULL) {
878 THROW_MSG(vmSymbols::java_lang_OutOfMemoryError(), "Failed to reserve memory");
879 }
881 c = *p;
882 WB_END
884 WB_ENTRY(jstring, WB_GetCPUFeatures(JNIEnv* env, jobject o))
885 const char* cpu_features = VM_Version::cpu_features();
886 ThreadToNativeFromVM ttn(thread);
887 jstring features_string = env->NewStringUTF(cpu_features);
889 CHECK_JNI_EXCEPTION_(env, NULL);
891 return features_string;
892 WB_END
894 int WhiteBox::get_blob_type(const CodeBlob* code) {
895 guarantee(WhiteBoxAPI, "internal testing API :: WhiteBox has to be enabled");
896 return CodeBlobType::All;;
897 }
899 struct CodeBlobStub {
900 CodeBlobStub(const CodeBlob* blob) :
901 name(os::strdup(blob->name())),
902 size(blob->size()),
903 blob_type(WhiteBox::get_blob_type(blob)),
904 address((jlong) blob) { }
905 ~CodeBlobStub() { os::free((void*) name); }
906 const char* const name;
907 const jint size;
908 const jint blob_type;
909 const jlong address;
910 };
912 static jobjectArray codeBlob2objectArray(JavaThread* thread, JNIEnv* env, CodeBlobStub* cb) {
913 jclass clazz = env->FindClass(vmSymbols::java_lang_Object()->as_C_string());
914 CHECK_JNI_EXCEPTION_(env, NULL);
915 jobjectArray result = env->NewObjectArray(4, clazz, NULL);
917 jstring name = env->NewStringUTF(cb->name);
918 CHECK_JNI_EXCEPTION_(env, NULL);
919 env->SetObjectArrayElement(result, 0, name);
921 jobject obj = integerBox(thread, env, cb->size);
922 CHECK_JNI_EXCEPTION_(env, NULL);
923 env->SetObjectArrayElement(result, 1, obj);
925 obj = integerBox(thread, env, cb->blob_type);
926 CHECK_JNI_EXCEPTION_(env, NULL);
927 env->SetObjectArrayElement(result, 2, obj);
929 obj = longBox(thread, env, cb->address);
930 CHECK_JNI_EXCEPTION_(env, NULL);
931 env->SetObjectArrayElement(result, 3, obj);
933 return result;
934 }
936 WB_ENTRY(jobjectArray, WB_GetNMethod(JNIEnv* env, jobject o, jobject method, jboolean is_osr))
937 ResourceMark rm(THREAD);
938 jmethodID jmid = reflected_method_to_jmid(thread, env, method);
939 CHECK_JNI_EXCEPTION_(env, NULL);
940 methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
941 nmethod* code = is_osr ? mh->lookup_osr_nmethod_for(InvocationEntryBci, CompLevel_none, false) : mh->code();
942 jobjectArray result = NULL;
943 if (code == NULL) {
944 return result;
945 }
946 int insts_size = code->insts_size();
948 ThreadToNativeFromVM ttn(thread);
949 jclass clazz = env->FindClass(vmSymbols::java_lang_Object()->as_C_string());
950 CHECK_JNI_EXCEPTION_(env, NULL);
951 result = env->NewObjectArray(3, clazz, NULL);
952 if (result == NULL) {
953 return result;
954 }
956 jobject level = integerBox(thread, env, code->comp_level());
957 CHECK_JNI_EXCEPTION_(env, NULL);
958 env->SetObjectArrayElement(result, 0, level);
960 jobject id = integerBox(thread, env, code->compile_id());
961 CHECK_JNI_EXCEPTION_(env, NULL);
962 env->SetObjectArrayElement(result, 1, id);
964 jbyteArray insts = env->NewByteArray(insts_size);
965 CHECK_JNI_EXCEPTION_(env, NULL);
966 env->SetByteArrayRegion(insts, 0, insts_size, (jbyte*) code->insts_begin());
967 env->SetObjectArrayElement(result, 2, insts);
969 return result;
970 WB_END
972 CodeBlob* WhiteBox::allocate_code_blob(int size, int blob_type) {
973 guarantee(WhiteBoxAPI, "internal testing API :: WhiteBox has to be enabled");
974 BufferBlob* blob;
975 int full_size = CodeBlob::align_code_offset(sizeof(BufferBlob));
976 if (full_size < size) {
977 full_size += align_up(size - full_size, oopSize);
978 }
979 {
980 MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
981 blob = (BufferBlob*) CodeCache::allocate(full_size);
982 ::new (blob) BufferBlob("WB::DummyBlob", full_size);
983 }
984 // Track memory usage statistic after releasing CodeCache_lock
985 MemoryService::track_code_cache_memory_usage();
986 return blob;
987 }
989 WB_ENTRY(jlong, WB_AllocateCodeBlob(JNIEnv* env, jobject o, jint size, jint blob_type))
990 if (size < 0) {
991 THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
992 err_msg("WB_AllocateCodeBlob: size is negative: " INT32_FORMAT, size));
993 }
994 return (jlong) WhiteBox::allocate_code_blob(size, blob_type);
995 WB_END
997 WB_ENTRY(void, WB_FreeCodeBlob(JNIEnv* env, jobject o, jlong addr))
998 if (addr == 0) {
999 return;
1000 }
1001 BufferBlob::free((BufferBlob*) addr);
1002 WB_END
1004 WB_ENTRY(jobjectArray, WB_GetCodeBlob(JNIEnv* env, jobject o, jlong addr))
1005 if (addr == 0) {
1006 THROW_MSG_NULL(vmSymbols::java_lang_NullPointerException(),
1007 "WB_GetCodeBlob: addr is null");
1008 }
1009 ThreadToNativeFromVM ttn(thread);
1010 CodeBlobStub stub((CodeBlob*) addr);
1011 return codeBlob2objectArray(thread, env, &stub);
1012 WB_END
1014 int WhiteBox::array_bytes_to_length(size_t bytes) {
1015 return Array<u1>::bytes_to_length(bytes);
1016 }
1018 WB_ENTRY(jlong, WB_AllocateMetaspace(JNIEnv* env, jobject wb, jobject class_loader, jlong size))
1019 if (size < 0) {
1020 THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
1021 err_msg("WB_AllocateMetaspace: size is negative: " JLONG_FORMAT, size));
1022 }
1024 oop class_loader_oop = JNIHandles::resolve(class_loader);
1025 ClassLoaderData* cld = class_loader_oop != NULL
1026 ? java_lang_ClassLoader::loader_data(class_loader_oop)
1027 : ClassLoaderData::the_null_class_loader_data();
1029 void* metadata = MetadataFactory::new_writeable_array<u1>(cld, WhiteBox::array_bytes_to_length((size_t)size), thread);
1031 return (jlong)(uintptr_t)metadata;
1032 WB_END
1034 WB_ENTRY(void, WB_FreeMetaspace(JNIEnv* env, jobject wb, jobject class_loader, jlong addr, jlong size))
1035 oop class_loader_oop = JNIHandles::resolve(class_loader);
1036 ClassLoaderData* cld = class_loader_oop != NULL
1037 ? java_lang_ClassLoader::loader_data(class_loader_oop)
1038 : ClassLoaderData::the_null_class_loader_data();
1040 MetadataFactory::free_array(cld, (Array<u1>*)(uintptr_t)addr);
1041 WB_END
1043 WB_ENTRY(jlong, WB_IncMetaspaceCapacityUntilGC(JNIEnv* env, jobject wb, jlong inc))
1044 if (inc < 0) {
1045 THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
1046 err_msg("WB_IncMetaspaceCapacityUntilGC: inc is negative: " JLONG_FORMAT, inc));
1047 }
1049 jlong max_size_t = (jlong) ((size_t) -1);
1050 if (inc > max_size_t) {
1051 THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
1052 err_msg("WB_IncMetaspaceCapacityUntilGC: inc does not fit in size_t: " JLONG_FORMAT, inc));
1053 }
1055 size_t new_cap_until_GC = 0;
1056 size_t aligned_inc = align_size_down((size_t) inc, Metaspace::commit_alignment());
1057 bool success = MetaspaceGC::inc_capacity_until_GC(aligned_inc, &new_cap_until_GC);
1058 if (!success) {
1059 THROW_MSG_0(vmSymbols::java_lang_IllegalStateException(),
1060 "WB_IncMetaspaceCapacityUntilGC: could not increase capacity until GC "
1061 "due to contention with another thread");
1062 }
1063 return (jlong) new_cap_until_GC;
1064 WB_END
1066 WB_ENTRY(jlong, WB_MetaspaceCapacityUntilGC(JNIEnv* env, jobject wb))
1067 return (jlong) MetaspaceGC::capacity_until_GC();
1068 WB_END
1070 WB_ENTRY(jboolean, WB_IsSharedClass(JNIEnv* env, jobject wb, jclass clazz))
1071 return (jboolean)MetaspaceShared::is_in_shared_space(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz)));
1072 WB_END
1074 WB_ENTRY(jboolean, WB_IsMonitorInflated(JNIEnv* env, jobject wb, jobject obj))
1075 oop obj_oop = JNIHandles::resolve(obj);
1076 return (jboolean) obj_oop->mark()->has_monitor();
1077 WB_END
1079 WB_ENTRY(void, WB_ForceSafepoint(JNIEnv* env, jobject wb))
1080 VM_ForceSafepoint force_safepoint_op;
1081 VMThread::execute(&force_safepoint_op);
1082 WB_END
1084 WB_ENTRY(jlong, WB_GetHeapAlignment(JNIEnv* env, jobject o))
1085 size_t alignment = Universe::heap()->collector_policy()->heap_alignment();
1086 return (jlong)alignment;
1087 WB_END
1089 //Some convenience methods to deal with objects from java
1090 int WhiteBox::offset_for_field(const char* field_name, oop object,
1091 Symbol* signature_symbol) {
1092 assert(field_name != NULL && strlen(field_name) > 0, "Field name not valid");
1093 Thread* THREAD = Thread::current();
1095 //Get the class of our object
1096 Klass* arg_klass = object->klass();
1097 //Turn it into an instance-klass
1098 InstanceKlass* ik = InstanceKlass::cast(arg_klass);
1100 //Create symbols to look for in the class
1101 TempNewSymbol name_symbol = SymbolTable::lookup(field_name, (int) strlen(field_name),
1102 THREAD);
1104 //To be filled in with an offset of the field we're looking for
1105 fieldDescriptor fd;
1107 Klass* res = ik->find_field(name_symbol, signature_symbol, &fd);
1108 if (res == NULL) {
1109 tty->print_cr("Invalid layout of %s at %s", ik->external_name(),
1110 name_symbol->as_C_string());
1111 vm_exit_during_initialization("Invalid layout of preloaded class: use -XX:+TraceClassLoading to see the origin of the problem class");
1112 }
1114 //fetch the field at the offset we've found
1115 int dest_offset = fd.offset();
1117 return dest_offset;
1118 }
1121 const char* WhiteBox::lookup_jstring(const char* field_name, oop object) {
1122 int offset = offset_for_field(field_name, object,
1123 vmSymbols::string_signature());
1124 oop string = object->obj_field(offset);
1125 if (string == NULL) {
1126 return NULL;
1127 }
1128 const char* ret = java_lang_String::as_utf8_string(string);
1129 return ret;
1130 }
1132 bool WhiteBox::lookup_bool(const char* field_name, oop object) {
1133 int offset =
1134 offset_for_field(field_name, object, vmSymbols::bool_signature());
1135 bool ret = (object->bool_field(offset) == JNI_TRUE);
1136 return ret;
1137 }
1139 void WhiteBox::register_methods(JNIEnv* env, jclass wbclass, JavaThread* thread, JNINativeMethod* method_array, int method_count) {
1140 ResourceMark rm;
1141 ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
1143 // one by one registration natives for exception catching
1144 jclass no_such_method_error_klass = env->FindClass(vmSymbols::java_lang_NoSuchMethodError()->as_C_string());
1145 CHECK_JNI_EXCEPTION(env);
1146 for (int i = 0, n = method_count; i < n; ++i) {
1147 // Skip dummy entries
1148 if (method_array[i].fnPtr == NULL) continue;
1149 if (env->RegisterNatives(wbclass, &method_array[i], 1) != 0) {
1150 jthrowable throwable_obj = env->ExceptionOccurred();
1151 if (throwable_obj != NULL) {
1152 env->ExceptionClear();
1153 if (env->IsInstanceOf(throwable_obj, no_such_method_error_klass)) {
1154 // NoSuchMethodError is thrown when a method can't be found or a method is not native.
1155 // Ignoring the exception since it is not preventing use of other WhiteBox methods.
1156 tty->print_cr("Warning: 'NoSuchMethodError' on register of sun.hotspot.WhiteBox::%s%s",
1157 method_array[i].name, method_array[i].signature);
1158 }
1159 } else {
1160 // Registration failed unexpectedly.
1161 tty->print_cr("Warning: unexpected error on register of sun.hotspot.WhiteBox::%s%s. All methods will be unregistered",
1162 method_array[i].name, method_array[i].signature);
1163 env->UnregisterNatives(wbclass);
1164 break;
1165 }
1166 }
1167 }
1168 }
1170 // Checks that the library libfile has the noexecstack bit set.
1171 WB_ENTRY(jboolean, WB_CheckLibSpecifiesNoexecstack(JNIEnv* env, jobject o, jstring libfile))
1172 jboolean ret = false;
1173 #ifdef LINUX
1174 // Can't be in VM when we call JNI.
1175 ThreadToNativeFromVM ttnfv(thread);
1176 const char* lf = env->GetStringUTFChars(libfile, NULL);
1177 CHECK_JNI_EXCEPTION_(env, 0);
1178 ElfFile ef(lf);
1179 ret = (jboolean) ef.specifies_noexecstack();
1180 env->ReleaseStringUTFChars(libfile, lf);
1181 #endif
1182 return ret;
1183 WB_END
1185 WB_ENTRY(jboolean, WB_IsContainerized(JNIEnv* env, jobject o))
1186 LINUX_ONLY(return OSContainer::is_containerized();)
1187 return false;
1188 WB_END
1190 WB_ENTRY(void, WB_PrintOsInfo(JNIEnv* env, jobject o))
1191 os::print_os_info(tty);
1192 WB_END
1194 #define CC (char*)
1196 static JNINativeMethod methods[] = {
1197 {CC"getObjectAddress", CC"(Ljava/lang/Object;)J", (void*)&WB_GetObjectAddress },
1198 {CC"getObjectSize", CC"(Ljava/lang/Object;)J", (void*)&WB_GetObjectSize },
1199 {CC"isObjectInOldGen", CC"(Ljava/lang/Object;)Z", (void*)&WB_isObjectInOldGen },
1200 {CC"getHeapOopSize", CC"()I", (void*)&WB_GetHeapOopSize },
1201 {CC"getVMPageSize", CC"()I", (void*)&WB_GetVMPageSize },
1202 {CC"getVMLargePageSize", CC"()J", (void*)&WB_GetVMLargePageSize},
1203 {CC"getHeapAlignment", CC"()J", (void*)&WB_GetHeapAlignment },
1204 {CC"isClassAlive0", CC"(Ljava/lang/String;)Z", (void*)&WB_IsClassAlive },
1205 {CC"classKnownToNotExist",
1206 CC"(Ljava/lang/ClassLoader;Ljava/lang/String;)Z",(void*)&WB_ClassKnownToNotExist},
1207 {CC"getLookupCacheURLs", CC"(Ljava/lang/ClassLoader;)[Ljava/net/URL;", (void*)&WB_GetLookupCacheURLs},
1208 {CC"getLookupCacheMatches", CC"(Ljava/lang/ClassLoader;Ljava/lang/String;)[I",
1209 (void*)&WB_GetLookupCacheMatches},
1210 {CC"parseCommandLine",
1211 CC"(Ljava/lang/String;[Lsun/hotspot/parser/DiagnosticCommand;)[Ljava/lang/Object;",
1212 (void*) &WB_ParseCommandLine
1213 },
1214 {CC"addToBootstrapClassLoaderSearch", CC"(Ljava/lang/String;)V",
1215 (void*)&WB_AddToBootstrapClassLoaderSearch},
1216 {CC"addToSystemClassLoaderSearch", CC"(Ljava/lang/String;)V",
1217 (void*)&WB_AddToSystemClassLoaderSearch},
1218 {CC"getCompressedOopsMaxHeapSize", CC"()J",
1219 (void*)&WB_GetCompressedOopsMaxHeapSize},
1220 {CC"printHeapSizes", CC"()V", (void*)&WB_PrintHeapSizes },
1221 {CC"runMemoryUnitTests", CC"()V", (void*)&WB_RunMemoryUnitTests},
1222 {CC"readFromNoaccessArea",CC"()V", (void*)&WB_ReadFromNoaccessArea},
1223 {CC"stressVirtualSpaceResize",CC"(JJJ)I", (void*)&WB_StressVirtualSpaceResize},
1224 {CC"isSharedClass", CC"(Ljava/lang/Class;)Z", (void*)&WB_IsSharedClass },
1225 #if INCLUDE_ALL_GCS
1226 {CC"g1InConcurrentMark", CC"()Z", (void*)&WB_G1InConcurrentMark},
1227 {CC"g1IsHumongous", CC"(Ljava/lang/Object;)Z", (void*)&WB_G1IsHumongous },
1228 {CC"g1NumMaxRegions", CC"()J", (void*)&WB_G1NumMaxRegions },
1229 {CC"g1NumFreeRegions", CC"()J", (void*)&WB_G1NumFreeRegions },
1230 {CC"g1RegionSize", CC"()I", (void*)&WB_G1RegionSize },
1231 {CC"g1StartConcMarkCycle", CC"()Z", (void*)&WB_G1StartMarkCycle },
1232 {CC"g1AuxiliaryMemoryUsage", CC"()Ljava/lang/management/MemoryUsage;",
1233 (void*)&WB_G1AuxiliaryMemoryUsage },
1234 #endif // INCLUDE_ALL_GCS
1235 #if INCLUDE_NMT
1236 {CC"NMTMalloc", CC"(J)J", (void*)&WB_NMTMalloc },
1237 {CC"NMTMallocWithPseudoStack", CC"(JI)J", (void*)&WB_NMTMallocWithPseudoStack},
1238 {CC"NMTMallocWithPseudoStackAndType", CC"(JII)J", (void*)&WB_NMTMallocWithPseudoStackAndType},
1239 {CC"NMTFree", CC"(J)V", (void*)&WB_NMTFree },
1240 {CC"NMTReserveMemory", CC"(J)J", (void*)&WB_NMTReserveMemory },
1241 {CC"NMTCommitMemory", CC"(JJ)V", (void*)&WB_NMTCommitMemory },
1242 {CC"NMTUncommitMemory", CC"(JJ)V", (void*)&WB_NMTUncommitMemory },
1243 {CC"NMTReleaseMemory", CC"(JJ)V", (void*)&WB_NMTReleaseMemory },
1244 {CC"NMTIsDetailSupported",CC"()Z", (void*)&WB_NMTIsDetailSupported},
1245 {CC"NMTChangeTrackingLevel", CC"()Z", (void*)&WB_NMTChangeTrackingLevel},
1246 {CC"NMTGetHashSize", CC"()I", (void*)&WB_NMTGetHashSize },
1247 #endif // INCLUDE_NMT
1248 {CC"deoptimizeAll", CC"()V", (void*)&WB_DeoptimizeAll },
1249 {CC"deoptimizeMethod", CC"(Ljava/lang/reflect/Executable;Z)I",
1250 (void*)&WB_DeoptimizeMethod },
1251 {CC"isMethodCompiled", CC"(Ljava/lang/reflect/Executable;Z)Z",
1252 (void*)&WB_IsMethodCompiled },
1253 {CC"isMethodCompilable", CC"(Ljava/lang/reflect/Executable;IZ)Z",
1254 (void*)&WB_IsMethodCompilable},
1255 {CC"isMethodQueuedForCompilation",
1256 CC"(Ljava/lang/reflect/Executable;)Z", (void*)&WB_IsMethodQueuedForCompilation},
1257 {CC"makeMethodNotCompilable",
1258 CC"(Ljava/lang/reflect/Executable;IZ)V", (void*)&WB_MakeMethodNotCompilable},
1259 {CC"testSetDontInlineMethod",
1260 CC"(Ljava/lang/reflect/Executable;Z)Z", (void*)&WB_TestSetDontInlineMethod},
1261 {CC"getMethodCompilationLevel",
1262 CC"(Ljava/lang/reflect/Executable;Z)I", (void*)&WB_GetMethodCompilationLevel},
1263 {CC"getMethodEntryBci",
1264 CC"(Ljava/lang/reflect/Executable;)I", (void*)&WB_GetMethodEntryBci},
1265 {CC"getCompileQueueSize",
1266 CC"(I)I", (void*)&WB_GetCompileQueueSize},
1267 {CC"testSetForceInlineMethod",
1268 CC"(Ljava/lang/reflect/Executable;Z)Z", (void*)&WB_TestSetForceInlineMethod},
1269 {CC"enqueueMethodForCompilation0",
1270 CC"(Ljava/lang/reflect/Executable;II)Z", (void*)&WB_EnqueueMethodForCompilation},
1271 {CC"enqueueInitializerForCompilation0",
1272 CC"(Ljava/lang/Class;I)Z", (void*)&WB_EnqueueInitializerForCompilation},
1273 {CC"clearMethodState",
1274 CC"(Ljava/lang/reflect/Executable;)V", (void*)&WB_ClearMethodState},
1275 {CC"markMethodProfiled",
1276 CC"(Ljava/lang/reflect/Executable;)V", (void*)&WB_MarkMethodProfiled},
1277 {CC"setBooleanVMFlag", CC"(Ljava/lang/String;Z)V",(void*)&WB_SetBooleanVMFlag},
1278 {CC"setIntxVMFlag", CC"(Ljava/lang/String;J)V",(void*)&WB_SetIntxVMFlag},
1279 {CC"setUintxVMFlag", CC"(Ljava/lang/String;J)V",(void*)&WB_SetUintxVMFlag},
1280 {CC"setUint64VMFlag", CC"(Ljava/lang/String;J)V",(void*)&WB_SetUint64VMFlag},
1281 {CC"setDoubleVMFlag", CC"(Ljava/lang/String;D)V",(void*)&WB_SetDoubleVMFlag},
1282 {CC"setStringVMFlag", CC"(Ljava/lang/String;Ljava/lang/String;)V",
1283 (void*)&WB_SetStringVMFlag},
1284 {CC"getBooleanVMFlag", CC"(Ljava/lang/String;)Ljava/lang/Boolean;",
1285 (void*)&WB_GetBooleanVMFlag},
1286 {CC"getIntxVMFlag", CC"(Ljava/lang/String;)Ljava/lang/Long;",
1287 (void*)&WB_GetIntxVMFlag},
1288 {CC"getUintxVMFlag", CC"(Ljava/lang/String;)Ljava/lang/Long;",
1289 (void*)&WB_GetUintxVMFlag},
1290 {CC"getUint64VMFlag", CC"(Ljava/lang/String;)Ljava/lang/Long;",
1291 (void*)&WB_GetUint64VMFlag},
1292 {CC"getDoubleVMFlag", CC"(Ljava/lang/String;)Ljava/lang/Double;",
1293 (void*)&WB_GetDoubleVMFlag},
1294 {CC"getStringVMFlag", CC"(Ljava/lang/String;)Ljava/lang/String;",
1295 (void*)&WB_GetStringVMFlag},
1296 {CC"isInStringTable", CC"(Ljava/lang/String;)Z", (void*)&WB_IsInStringTable },
1297 {CC"fullGC", CC"()V", (void*)&WB_FullGC },
1298 {CC"youngGC", CC"()V", (void*)&WB_YoungGC },
1299 {CC"readReservedMemory", CC"()V", (void*)&WB_ReadReservedMemory },
1300 {CC"allocateCodeBlob", CC"(II)J", (void*)&WB_AllocateCodeBlob },
1301 {CC"freeCodeBlob", CC"(J)V", (void*)&WB_FreeCodeBlob },
1302 {CC"getCodeBlob", CC"(J)[Ljava/lang/Object;",(void*)&WB_GetCodeBlob },
1303 {CC"allocateMetaspace",
1304 CC"(Ljava/lang/ClassLoader;J)J", (void*)&WB_AllocateMetaspace },
1305 {CC"freeMetaspace",
1306 CC"(Ljava/lang/ClassLoader;JJ)V", (void*)&WB_FreeMetaspace },
1307 {CC"incMetaspaceCapacityUntilGC", CC"(J)J", (void*)&WB_IncMetaspaceCapacityUntilGC },
1308 {CC"metaspaceCapacityUntilGC", CC"()J", (void*)&WB_MetaspaceCapacityUntilGC },
1309 {CC"getCPUFeatures", CC"()Ljava/lang/String;", (void*)&WB_GetCPUFeatures },
1310 {CC"getNMethod", CC"(Ljava/lang/reflect/Executable;Z)[Ljava/lang/Object;",
1311 (void*)&WB_GetNMethod },
1312 {CC"isMonitorInflated", CC"(Ljava/lang/Object;)Z", (void*)&WB_IsMonitorInflated },
1313 {CC"forceSafepoint", CC"()V", (void*)&WB_ForceSafepoint },
1314 {CC"checkLibSpecifiesNoexecstack", CC"(Ljava/lang/String;)Z",
1315 (void*)&WB_CheckLibSpecifiesNoexecstack},
1316 {CC"isContainerized", CC"()Z", (void*)&WB_IsContainerized },
1317 {CC"printOsInfo", CC"()V", (void*)&WB_PrintOsInfo },
1318 };
1320 #undef CC
1322 JVM_ENTRY(void, JVM_RegisterWhiteBoxMethods(JNIEnv* env, jclass wbclass))
1323 {
1324 if (WhiteBoxAPI) {
1325 // Make sure that wbclass is loaded by the null classloader
1326 instanceKlassHandle ikh = instanceKlassHandle(JNIHandles::resolve(wbclass)->klass());
1327 Handle loader(ikh->class_loader());
1328 if (loader.is_null()) {
1329 WhiteBox::register_methods(env, wbclass, thread, methods, sizeof(methods) / sizeof(methods[0]));
1330 WhiteBox::register_extended(env, wbclass, thread);
1331 WhiteBox::set_used();
1332 }
1333 }
1334 }
1335 JVM_END