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