whitebox.cpp revision 12408:777aaa19c4b1
1/*
2 * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25#include "precompiled.hpp"
26
27#include <new>
28
29#include "classfile/classLoaderData.hpp"
30#include "classfile/modules.hpp"
31#include "classfile/stringTable.hpp"
32#include "code/codeCache.hpp"
33#include "compiler/methodMatcher.hpp"
34#include "compiler/directivesParser.hpp"
35#include "jvmtifiles/jvmtiEnv.hpp"
36#include "memory/metadataFactory.hpp"
37#include "memory/metaspaceShared.hpp"
38#include "memory/iterator.hpp"
39#include "memory/resourceArea.hpp"
40#include "memory/universe.hpp"
41#include "memory/oopFactory.hpp"
42#include "oops/constantPool.hpp"
43#include "oops/oop.inline.hpp"
44#include "prims/wbtestmethods/parserTests.hpp"
45#include "prims/whitebox.hpp"
46#include "runtime/arguments.hpp"
47#include "runtime/compilationPolicy.hpp"
48#include "runtime/deoptimization.hpp"
49#include "runtime/interfaceSupport.hpp"
50#include "runtime/javaCalls.hpp"
51#include "runtime/os.hpp"
52#include "runtime/sweeper.hpp"
53#include "runtime/thread.hpp"
54#include "runtime/vm_version.hpp"
55#include "utilities/array.hpp"
56#include "utilities/debug.hpp"
57#include "utilities/exceptions.hpp"
58#include "utilities/macros.hpp"
59#if INCLUDE_ALL_GCS
60#include "gc/g1/concurrentMarkThread.hpp"
61#include "gc/g1/g1CollectedHeap.inline.hpp"
62#include "gc/g1/g1ConcurrentMark.hpp"
63#include "gc/g1/heapRegionRemSet.hpp"
64#include "gc/parallel/parallelScavengeHeap.inline.hpp"
65#include "gc/parallel/adjoiningGenerations.hpp"
66#endif // INCLUDE_ALL_GCS
67#if INCLUDE_NMT
68#include "services/mallocSiteTable.hpp"
69#include "services/memTracker.hpp"
70#include "utilities/nativeCallStack.hpp"
71#endif // INCLUDE_NMT
72
73
74#define SIZE_T_MAX_VALUE ((size_t) -1)
75
76bool WhiteBox::_used = false;
77volatile bool WhiteBox::compilation_locked = false;
78
79class VM_WhiteBoxOperation : public VM_Operation {
80 public:
81  VM_WhiteBoxOperation()                         { }
82  VMOp_Type type()                  const        { return VMOp_WhiteBoxOperation; }
83  bool allow_nested_vm_operations() const        { return true; }
84};
85
86
87WB_ENTRY(jlong, WB_GetObjectAddress(JNIEnv* env, jobject o, jobject obj))
88  return (jlong)(void*)JNIHandles::resolve(obj);
89WB_END
90
91WB_ENTRY(jint, WB_GetHeapOopSize(JNIEnv* env, jobject o))
92  return heapOopSize;
93WB_END
94
95WB_ENTRY(jint, WB_GetVMPageSize(JNIEnv* env, jobject o))
96  return os::vm_page_size();
97WB_END
98
99WB_ENTRY(jlong, WB_GetVMAllocationGranularity(JNIEnv* env, jobject o))
100  return os::vm_allocation_granularity();
101WB_END
102
103WB_ENTRY(jlong, WB_GetVMLargePageSize(JNIEnv* env, jobject o))
104  return os::large_page_size();
105WB_END
106
107class WBIsKlassAliveClosure : public KlassClosure {
108    Symbol* _name;
109    bool _found;
110public:
111    WBIsKlassAliveClosure(Symbol* name) : _name(name), _found(false) {}
112
113    void do_klass(Klass* k) {
114      if (_found) return;
115      Symbol* ksym = k->name();
116      if (ksym->fast_compare(_name) == 0) {
117        _found = true;
118      }
119    }
120
121    bool found() const {
122        return _found;
123    }
124};
125
126WB_ENTRY(jboolean, WB_IsClassAlive(JNIEnv* env, jobject target, jstring name))
127  Handle h_name = JNIHandles::resolve(name);
128  if (h_name.is_null()) return false;
129  Symbol* sym = java_lang_String::as_symbol(h_name, CHECK_false);
130  TempNewSymbol tsym(sym); // Make sure to decrement reference count on sym on return
131
132  WBIsKlassAliveClosure closure(sym);
133  ClassLoaderDataGraph::classes_do(&closure);
134
135  return closure.found();
136WB_END
137
138WB_ENTRY(void, WB_AddToBootstrapClassLoaderSearch(JNIEnv* env, jobject o, jstring segment)) {
139#if INCLUDE_JVMTI
140  ResourceMark rm;
141  const char* seg = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(segment));
142  JvmtiEnv* jvmti_env = JvmtiEnv::create_a_jvmti(JVMTI_VERSION);
143  jvmtiError err = jvmti_env->AddToBootstrapClassLoaderSearch(seg);
144  assert(err == JVMTI_ERROR_NONE, "must not fail");
145#endif
146}
147WB_END
148
149WB_ENTRY(void, WB_AddToSystemClassLoaderSearch(JNIEnv* env, jobject o, jstring segment)) {
150#if INCLUDE_JVMTI
151  ResourceMark rm;
152  const char* seg = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(segment));
153  JvmtiEnv* jvmti_env = JvmtiEnv::create_a_jvmti(JVMTI_VERSION);
154  jvmtiError err = jvmti_env->AddToSystemClassLoaderSearch(seg);
155  assert(err == JVMTI_ERROR_NONE, "must not fail");
156#endif
157}
158WB_END
159
160
161WB_ENTRY(jlong, WB_GetCompressedOopsMaxHeapSize(JNIEnv* env, jobject o)) {
162  return (jlong)Arguments::max_heap_for_compressed_oops();
163}
164WB_END
165
166WB_ENTRY(void, WB_PrintHeapSizes(JNIEnv* env, jobject o)) {
167  CollectorPolicy * p = Universe::heap()->collector_policy();
168  tty->print_cr("Minimum heap " SIZE_FORMAT " Initial heap "
169    SIZE_FORMAT " Maximum heap " SIZE_FORMAT " Space alignment " SIZE_FORMAT " Heap alignment " SIZE_FORMAT,
170    p->min_heap_byte_size(), p->initial_heap_byte_size(), p->max_heap_byte_size(),
171    p->space_alignment(), p->heap_alignment());
172}
173WB_END
174
175#ifndef PRODUCT
176// Forward declaration
177void TestReservedSpace_test();
178void TestReserveMemorySpecial_test();
179void TestVirtualSpace_test();
180void TestMetaspaceAux_test();
181#endif
182
183WB_ENTRY(void, WB_RunMemoryUnitTests(JNIEnv* env, jobject o))
184#ifndef PRODUCT
185  TestReservedSpace_test();
186  TestReserveMemorySpecial_test();
187  TestVirtualSpace_test();
188  TestMetaspaceAux_test();
189#endif
190WB_END
191
192WB_ENTRY(void, WB_ReadFromNoaccessArea(JNIEnv* env, jobject o))
193  size_t granularity = os::vm_allocation_granularity();
194  ReservedHeapSpace rhs(100 * granularity, granularity, false);
195  VirtualSpace vs;
196  vs.initialize(rhs, 50 * granularity);
197
198  // Check if constraints are complied
199  if (!( UseCompressedOops && rhs.base() != NULL &&
200         Universe::narrow_oop_base() != NULL &&
201         Universe::narrow_oop_use_implicit_null_checks() )) {
202    tty->print_cr("WB_ReadFromNoaccessArea method is useless:\n "
203                  "\tUseCompressedOops is %d\n"
204                  "\trhs.base() is " PTR_FORMAT "\n"
205                  "\tUniverse::narrow_oop_base() is " PTR_FORMAT "\n"
206                  "\tUniverse::narrow_oop_use_implicit_null_checks() is %d",
207                  UseCompressedOops,
208                  p2i(rhs.base()),
209                  p2i(Universe::narrow_oop_base()),
210                  Universe::narrow_oop_use_implicit_null_checks());
211    return;
212  }
213  tty->print_cr("Reading from no access area... ");
214  tty->print_cr("*(vs.low_boundary() - rhs.noaccess_prefix() / 2 ) = %c",
215                *(vs.low_boundary() - rhs.noaccess_prefix() / 2 ));
216WB_END
217
218static jint wb_stress_virtual_space_resize(size_t reserved_space_size,
219                                           size_t magnitude, size_t iterations) {
220  size_t granularity = os::vm_allocation_granularity();
221  ReservedHeapSpace rhs(reserved_space_size * granularity, granularity, false);
222  VirtualSpace vs;
223  if (!vs.initialize(rhs, 0)) {
224    tty->print_cr("Failed to initialize VirtualSpace. Can't proceed.");
225    return 3;
226  }
227
228  long seed = os::random();
229  tty->print_cr("Random seed is %ld", seed);
230  os::init_random(seed);
231
232  for (size_t i = 0; i < iterations; i++) {
233
234    // Whether we will shrink or grow
235    bool shrink = os::random() % 2L == 0;
236
237    // Get random delta to resize virtual space
238    size_t delta = (size_t)os::random() % magnitude;
239
240    // If we are about to shrink virtual space below zero, then expand instead
241    if (shrink && vs.committed_size() < delta) {
242      shrink = false;
243    }
244
245    // Resizing by delta
246    if (shrink) {
247      vs.shrink_by(delta);
248    } else {
249      // If expanding fails expand_by will silently return false
250      vs.expand_by(delta, true);
251    }
252  }
253  return 0;
254}
255
256WB_ENTRY(jint, WB_StressVirtualSpaceResize(JNIEnv* env, jobject o,
257        jlong reserved_space_size, jlong magnitude, jlong iterations))
258  tty->print_cr("reservedSpaceSize=" JLONG_FORMAT ", magnitude=" JLONG_FORMAT ", "
259                "iterations=" JLONG_FORMAT "\n", reserved_space_size, magnitude,
260                iterations);
261  if (reserved_space_size < 0 || magnitude < 0 || iterations < 0) {
262    tty->print_cr("One of variables printed above is negative. Can't proceed.\n");
263    return 1;
264  }
265
266  // sizeof(size_t) depends on whether OS is 32bit or 64bit. sizeof(jlong) is
267  // always 8 byte. That's why we should avoid overflow in case of 32bit platform.
268  if (sizeof(size_t) < sizeof(jlong)) {
269    jlong size_t_max_value = (jlong) SIZE_T_MAX_VALUE;
270    if (reserved_space_size > size_t_max_value || magnitude > size_t_max_value
271        || iterations > size_t_max_value) {
272      tty->print_cr("One of variables printed above overflows size_t. Can't proceed.\n");
273      return 2;
274    }
275  }
276
277  return wb_stress_virtual_space_resize((size_t) reserved_space_size,
278                                        (size_t) magnitude, (size_t) iterations);
279WB_END
280
281static const jint serial_code   = 1;
282static const jint parallel_code = 2;
283static const jint cms_code      = 4;
284static const jint g1_code       = 8;
285
286WB_ENTRY(jint, WB_CurrentGC(JNIEnv* env, jobject o, jobject obj))
287  if (UseSerialGC) {
288    return serial_code;
289  } else if (UseParallelGC || UseParallelOldGC) {
290    return parallel_code;
291  } if (UseConcMarkSweepGC) {
292    return cms_code;
293  } else if (UseG1GC) {
294    return g1_code;
295  }
296  ShouldNotReachHere();
297  return 0;
298WB_END
299
300WB_ENTRY(jint, WB_AllSupportedGC(JNIEnv* env, jobject o, jobject obj))
301#if INCLUDE_ALL_GCS
302  return serial_code | parallel_code | cms_code | g1_code;
303#else
304  return serial_code;
305#endif // INCLUDE_ALL_GCS
306WB_END
307
308WB_ENTRY(jboolean, WB_GCSelectedByErgo(JNIEnv* env, jobject o, jobject obj))
309  if (UseSerialGC) {
310    return FLAG_IS_ERGO(UseSerialGC);
311  } else if (UseParallelGC) {
312    return FLAG_IS_ERGO(UseParallelGC);
313  } else if (UseParallelOldGC) {
314    return FLAG_IS_ERGO(UseParallelOldGC);
315  } else if (UseConcMarkSweepGC) {
316    return FLAG_IS_ERGO(UseConcMarkSweepGC);
317  } else if (UseG1GC) {
318    return FLAG_IS_ERGO(UseG1GC);
319  }
320  ShouldNotReachHere();
321  return false;
322WB_END
323
324WB_ENTRY(jboolean, WB_isObjectInOldGen(JNIEnv* env, jobject o, jobject obj))
325  oop p = JNIHandles::resolve(obj);
326#if INCLUDE_ALL_GCS
327  if (UseG1GC) {
328    G1CollectedHeap* g1 = G1CollectedHeap::heap();
329    const HeapRegion* hr = g1->heap_region_containing(p);
330    if (hr == NULL) {
331      return false;
332    }
333    return !(hr->is_young());
334  } else if (UseParallelGC) {
335    ParallelScavengeHeap* psh = ParallelScavengeHeap::heap();
336    return !psh->is_in_young(p);
337  }
338#endif // INCLUDE_ALL_GCS
339  GenCollectedHeap* gch = GenCollectedHeap::heap();
340  return !gch->is_in_young(p);
341WB_END
342
343WB_ENTRY(jlong, WB_GetObjectSize(JNIEnv* env, jobject o, jobject obj))
344  oop p = JNIHandles::resolve(obj);
345  return p->size() * HeapWordSize;
346WB_END
347
348WB_ENTRY(jlong, WB_GetHeapSpaceAlignment(JNIEnv* env, jobject o))
349  size_t alignment = Universe::heap()->collector_policy()->space_alignment();
350  return (jlong)alignment;
351WB_END
352
353WB_ENTRY(jlong, WB_GetHeapAlignment(JNIEnv* env, jobject o))
354  size_t alignment = Universe::heap()->collector_policy()->heap_alignment();
355  return (jlong)alignment;
356WB_END
357
358#if INCLUDE_ALL_GCS
359WB_ENTRY(jboolean, WB_G1IsHumongous(JNIEnv* env, jobject o, jobject obj))
360  G1CollectedHeap* g1 = G1CollectedHeap::heap();
361  oop result = JNIHandles::resolve(obj);
362  const HeapRegion* hr = g1->heap_region_containing(result);
363  return hr->is_humongous();
364WB_END
365
366WB_ENTRY(jboolean, WB_G1BelongsToHumongousRegion(JNIEnv* env, jobject o, jlong addr))
367  G1CollectedHeap* g1 = G1CollectedHeap::heap();
368  const HeapRegion* hr = g1->heap_region_containing((void*) addr);
369  return hr->is_humongous();
370WB_END
371
372WB_ENTRY(jboolean, WB_G1BelongsToFreeRegion(JNIEnv* env, jobject o, jlong addr))
373  G1CollectedHeap* g1 = G1CollectedHeap::heap();
374  const HeapRegion* hr = g1->heap_region_containing((void*) addr);
375  return hr->is_free();
376WB_END
377
378WB_ENTRY(jlong, WB_G1NumMaxRegions(JNIEnv* env, jobject o))
379  G1CollectedHeap* g1 = G1CollectedHeap::heap();
380  size_t nr = g1->max_regions();
381  return (jlong)nr;
382WB_END
383
384WB_ENTRY(jlong, WB_G1NumFreeRegions(JNIEnv* env, jobject o))
385  G1CollectedHeap* g1 = G1CollectedHeap::heap();
386  size_t nr = g1->num_free_regions();
387  return (jlong)nr;
388WB_END
389
390WB_ENTRY(jboolean, WB_G1InConcurrentMark(JNIEnv* env, jobject o))
391  G1CollectedHeap* g1h = G1CollectedHeap::heap();
392  return g1h->concurrent_mark()->cmThread()->during_cycle();
393WB_END
394
395WB_ENTRY(jboolean, WB_G1StartMarkCycle(JNIEnv* env, jobject o))
396  G1CollectedHeap* g1h = G1CollectedHeap::heap();
397  if (!g1h->concurrent_mark()->cmThread()->during_cycle()) {
398    g1h->collect(GCCause::_wb_conc_mark);
399    return true;
400  }
401  return false;
402WB_END
403
404WB_ENTRY(jint, WB_G1RegionSize(JNIEnv* env, jobject o))
405  return (jint)HeapRegion::GrainBytes;
406WB_END
407
408WB_ENTRY(jlong, WB_PSVirtualSpaceAlignment(JNIEnv* env, jobject o))
409#if INCLUDE_ALL_GCS
410  if (UseParallelGC) {
411    return ParallelScavengeHeap::heap()->gens()->virtual_spaces()->alignment();
412  }
413#endif // INCLUDE_ALL_GCS
414  THROW_MSG_0(vmSymbols::java_lang_RuntimeException(), "WB_PSVirtualSpaceAlignment: Parallel GC is not enabled");
415WB_END
416
417WB_ENTRY(jlong, WB_PSHeapGenerationAlignment(JNIEnv* env, jobject o))
418#if INCLUDE_ALL_GCS
419  if (UseParallelGC) {
420    return ParallelScavengeHeap::heap()->generation_alignment();
421  }
422#endif // INCLUDE_ALL_GCS
423  THROW_MSG_0(vmSymbols::java_lang_RuntimeException(), "WB_PSHeapGenerationAlignment: Parallel GC is not enabled");
424WB_END
425
426WB_ENTRY(jobject, WB_G1AuxiliaryMemoryUsage(JNIEnv* env))
427  ResourceMark rm(THREAD);
428  G1CollectedHeap* g1h = G1CollectedHeap::heap();
429  MemoryUsage usage = g1h->get_auxiliary_data_memory_usage();
430  Handle h = MemoryService::create_MemoryUsage_obj(usage, CHECK_NULL);
431  return JNIHandles::make_local(env, h());
432WB_END
433
434class OldRegionsLivenessClosure: public HeapRegionClosure {
435
436 private:
437  const int _liveness;
438  size_t _total_count;
439  size_t _total_memory;
440  size_t _total_memory_to_free;
441
442 public:
443  OldRegionsLivenessClosure(int liveness) :
444    _liveness(liveness),
445    _total_count(0),
446    _total_memory(0),
447    _total_memory_to_free(0) { }
448
449    size_t total_count() { return _total_count; }
450    size_t total_memory() { return _total_memory; }
451    size_t total_memory_to_free() { return _total_memory_to_free; }
452
453  bool doHeapRegion(HeapRegion* r) {
454    if (r->is_old()) {
455      size_t prev_live = r->marked_bytes();
456      size_t live = r->live_bytes();
457      size_t size = r->used();
458      size_t reg_size = HeapRegion::GrainBytes;
459      if (size > 0 && ((int)(live * 100 / size) < _liveness)) {
460        _total_memory += size;
461        ++_total_count;
462        if (size == reg_size) {
463        // we don't include non-full regions since they are unlikely included in mixed gc
464        // for testing purposes it's enough to have lowest estimation of total memory that is expected to be freed
465          _total_memory_to_free += size - prev_live;
466        }
467      }
468    }
469    return false;
470  }
471};
472
473
474WB_ENTRY(jlongArray, WB_G1GetMixedGCInfo(JNIEnv* env, jobject o, jint liveness))
475  if (!UseG1GC) {
476    THROW_MSG_NULL(vmSymbols::java_lang_RuntimeException(), "WB_G1GetMixedGCInfo: G1 is not enabled");
477  }
478  if (liveness < 0) {
479    THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), "liveness value should be non-negative");
480  }
481
482  G1CollectedHeap* g1h = G1CollectedHeap::heap();
483  OldRegionsLivenessClosure rli(liveness);
484  g1h->heap_region_iterate(&rli);
485
486  typeArrayOop result = oopFactory::new_longArray(3, CHECK_NULL);
487  result->long_at_put(0, rli.total_count());
488  result->long_at_put(1, rli.total_memory());
489  result->long_at_put(2, rli.total_memory_to_free());
490  return (jlongArray) JNIHandles::make_local(env, result);
491WB_END
492
493
494
495#endif // INCLUDE_ALL_GCS
496
497#if INCLUDE_NMT
498// Alloc memory using the test memory type so that we can use that to see if
499// NMT picks it up correctly
500WB_ENTRY(jlong, WB_NMTMalloc(JNIEnv* env, jobject o, jlong size))
501  jlong addr = 0;
502  addr = (jlong)(uintptr_t)os::malloc(size, mtTest);
503  return addr;
504WB_END
505
506// Alloc memory with pseudo call stack. The test can create psudo malloc
507// allocation site to stress the malloc tracking.
508WB_ENTRY(jlong, WB_NMTMallocWithPseudoStack(JNIEnv* env, jobject o, jlong size, jint pseudo_stack))
509  address pc = (address)(size_t)pseudo_stack;
510  NativeCallStack stack(&pc, 1);
511  return (jlong)(uintptr_t)os::malloc(size, mtTest, stack);
512WB_END
513
514// Free the memory allocated by NMTAllocTest
515WB_ENTRY(void, WB_NMTFree(JNIEnv* env, jobject o, jlong mem))
516  os::free((void*)(uintptr_t)mem);
517WB_END
518
519WB_ENTRY(jlong, WB_NMTReserveMemory(JNIEnv* env, jobject o, jlong size))
520  jlong addr = 0;
521
522  addr = (jlong)(uintptr_t)os::reserve_memory(size);
523  MemTracker::record_virtual_memory_type((address)addr, mtTest);
524
525  return addr;
526WB_END
527
528WB_ENTRY(void, WB_NMTCommitMemory(JNIEnv* env, jobject o, jlong addr, jlong size))
529  os::commit_memory((char *)(uintptr_t)addr, size, !ExecMem);
530  MemTracker::record_virtual_memory_type((address)(uintptr_t)addr, mtTest);
531WB_END
532
533WB_ENTRY(void, WB_NMTUncommitMemory(JNIEnv* env, jobject o, jlong addr, jlong size))
534  os::uncommit_memory((char *)(uintptr_t)addr, size);
535WB_END
536
537WB_ENTRY(void, WB_NMTReleaseMemory(JNIEnv* env, jobject o, jlong addr, jlong size))
538  os::release_memory((char *)(uintptr_t)addr, size);
539WB_END
540
541WB_ENTRY(jboolean, WB_NMTChangeTrackingLevel(JNIEnv* env))
542  // Test that we can downgrade NMT levels but not upgrade them.
543  if (MemTracker::tracking_level() == NMT_off) {
544    MemTracker::transition_to(NMT_off);
545    return MemTracker::tracking_level() == NMT_off;
546  } else {
547    assert(MemTracker::tracking_level() == NMT_detail, "Should start out as detail tracking");
548    MemTracker::transition_to(NMT_summary);
549    assert(MemTracker::tracking_level() == NMT_summary, "Should be summary now");
550
551    // Can't go to detail once NMT is set to summary.
552    MemTracker::transition_to(NMT_detail);
553    assert(MemTracker::tracking_level() == NMT_summary, "Should still be summary now");
554
555    // Shutdown sets tracking level to minimal.
556    MemTracker::shutdown();
557    assert(MemTracker::tracking_level() == NMT_minimal, "Should be minimal now");
558
559    // Once the tracking level is minimal, we cannot increase to summary.
560    // The code ignores this request instead of asserting because if the malloc site
561    // table overflows in another thread, it tries to change the code to summary.
562    MemTracker::transition_to(NMT_summary);
563    assert(MemTracker::tracking_level() == NMT_minimal, "Should still be minimal now");
564
565    // Really can never go up to detail, verify that the code would never do this.
566    MemTracker::transition_to(NMT_detail);
567    assert(MemTracker::tracking_level() == NMT_minimal, "Should still be minimal now");
568    return MemTracker::tracking_level() == NMT_minimal;
569  }
570WB_END
571
572WB_ENTRY(jint, WB_NMTGetHashSize(JNIEnv* env, jobject o))
573  int hash_size = MallocSiteTable::hash_buckets();
574  assert(hash_size > 0, "NMT hash_size should be > 0");
575  return (jint)hash_size;
576WB_END
577#endif // INCLUDE_NMT
578
579static jmethodID reflected_method_to_jmid(JavaThread* thread, JNIEnv* env, jobject method) {
580  assert(method != NULL, "method should not be null");
581  ThreadToNativeFromVM ttn(thread);
582  return env->FromReflectedMethod(method);
583}
584
585// Deoptimizes all compiled frames and makes nmethods not entrant if it's requested
586class VM_WhiteBoxDeoptimizeFrames : public VM_WhiteBoxOperation {
587 private:
588  int _result;
589  const bool _make_not_entrant;
590 public:
591  VM_WhiteBoxDeoptimizeFrames(bool make_not_entrant) :
592        _result(0), _make_not_entrant(make_not_entrant) { }
593  int  result() const { return _result; }
594
595  void doit() {
596    for (JavaThread* t = Threads::first(); t != NULL; t = t->next()) {
597      if (t->has_last_Java_frame()) {
598        for (StackFrameStream fst(t, UseBiasedLocking); !fst.is_done(); fst.next()) {
599          frame* f = fst.current();
600          if (f->can_be_deoptimized() && !f->is_deoptimized_frame()) {
601            RegisterMap* reg_map = fst.register_map();
602            Deoptimization::deoptimize(t, *f, reg_map);
603            if (_make_not_entrant) {
604                CompiledMethod* cm = CodeCache::find_compiled(f->pc());
605                assert(cm != NULL, "sanity check");
606                cm->make_not_entrant();
607            }
608            ++_result;
609          }
610        }
611      }
612    }
613  }
614};
615
616WB_ENTRY(jint, WB_DeoptimizeFrames(JNIEnv* env, jobject o, jboolean make_not_entrant))
617  VM_WhiteBoxDeoptimizeFrames op(make_not_entrant == JNI_TRUE);
618  VMThread::execute(&op);
619  return op.result();
620WB_END
621
622WB_ENTRY(void, WB_DeoptimizeAll(JNIEnv* env, jobject o))
623  MutexLockerEx mu(Compile_lock);
624  CodeCache::mark_all_nmethods_for_deoptimization();
625  VM_Deoptimize op;
626  VMThread::execute(&op);
627WB_END
628
629WB_ENTRY(jint, WB_DeoptimizeMethod(JNIEnv* env, jobject o, jobject method, jboolean is_osr))
630  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
631  int result = 0;
632  CHECK_JNI_EXCEPTION_(env, result);
633  MutexLockerEx mu(Compile_lock);
634  methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
635  if (is_osr) {
636    result += mh->mark_osr_nmethods();
637  } else if (mh->code() != NULL) {
638    mh->code()->mark_for_deoptimization();
639    ++result;
640  }
641  result += CodeCache::mark_for_deoptimization(mh());
642  if (result > 0) {
643    VM_Deoptimize op;
644    VMThread::execute(&op);
645  }
646  return result;
647WB_END
648
649WB_ENTRY(jboolean, WB_IsMethodCompiled(JNIEnv* env, jobject o, jobject method, jboolean is_osr))
650  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
651  CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
652  MutexLockerEx mu(Compile_lock);
653  methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
654  CompiledMethod* code = is_osr ? mh->lookup_osr_nmethod_for(InvocationEntryBci, CompLevel_none, false) : mh->code();
655  if (code == NULL) {
656    return JNI_FALSE;
657  }
658  return (code->is_alive() && !code->is_marked_for_deoptimization());
659WB_END
660
661WB_ENTRY(jboolean, WB_IsMethodCompilable(JNIEnv* env, jobject o, jobject method, jint comp_level, jboolean is_osr))
662  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
663  CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
664  MutexLockerEx mu(Compile_lock);
665  methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
666  if (is_osr) {
667    return CompilationPolicy::can_be_osr_compiled(mh, comp_level);
668  } else {
669    return CompilationPolicy::can_be_compiled(mh, comp_level);
670  }
671WB_END
672
673WB_ENTRY(jboolean, WB_IsMethodQueuedForCompilation(JNIEnv* env, jobject o, jobject method))
674  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
675  CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
676  MutexLockerEx mu(Compile_lock);
677  methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
678  return mh->queued_for_compilation();
679WB_END
680
681WB_ENTRY(jboolean, WB_IsIntrinsicAvailable(JNIEnv* env, jobject o, jobject method, jobject compilation_context, jint compLevel))
682  if (compLevel < CompLevel_none || compLevel > MIN2((CompLevel) TieredStopAtLevel, CompLevel_highest_tier)) {
683    return false; // Intrinsic is not available on a non-existent compilation level.
684  }
685  jmethodID method_id, compilation_context_id;
686  method_id = reflected_method_to_jmid(thread, env, method);
687  CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
688  methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(method_id));
689
690  DirectiveSet* directive;
691  AbstractCompiler* comp = CompileBroker::compiler((int)compLevel);
692  assert(comp != NULL, "compiler not available");
693  if (compilation_context != NULL) {
694    compilation_context_id = reflected_method_to_jmid(thread, env, compilation_context);
695    CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
696    methodHandle cch(THREAD, Method::checked_resolve_jmethod_id(compilation_context_id));
697    directive = DirectivesStack::getMatchingDirective(cch, comp);
698  } else {
699    // Calling with NULL matches default directive
700    directive = DirectivesStack::getDefaultDirective(comp);
701  }
702  bool result = comp->is_intrinsic_available(mh, directive);
703  DirectivesStack::release(directive);
704  return result;
705WB_END
706
707WB_ENTRY(jint, WB_GetMethodCompilationLevel(JNIEnv* env, jobject o, jobject method, jboolean is_osr))
708  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
709  CHECK_JNI_EXCEPTION_(env, CompLevel_none);
710  methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
711  CompiledMethod* code = is_osr ? mh->lookup_osr_nmethod_for(InvocationEntryBci, CompLevel_none, false) : mh->code();
712  return (code != NULL ? code->comp_level() : CompLevel_none);
713WB_END
714
715WB_ENTRY(void, WB_MakeMethodNotCompilable(JNIEnv* env, jobject o, jobject method, jint comp_level, jboolean is_osr))
716  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
717  CHECK_JNI_EXCEPTION(env);
718  methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
719  if (is_osr) {
720    mh->set_not_osr_compilable(comp_level, true /* report */, "WhiteBox");
721  } else {
722    mh->set_not_compilable(comp_level, true /* report */, "WhiteBox");
723  }
724WB_END
725
726WB_ENTRY(jint, WB_GetMethodEntryBci(JNIEnv* env, jobject o, jobject method))
727  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
728  CHECK_JNI_EXCEPTION_(env, InvocationEntryBci);
729  methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
730  CompiledMethod* code = mh->lookup_osr_nmethod_for(InvocationEntryBci, CompLevel_none, false);
731  return (code != NULL && code->is_osr_method() ? code->osr_entry_bci() : InvocationEntryBci);
732WB_END
733
734WB_ENTRY(jboolean, WB_TestSetDontInlineMethod(JNIEnv* env, jobject o, jobject method, jboolean value))
735  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
736  CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
737  methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
738  bool result = mh->dont_inline();
739  mh->set_dont_inline(value == JNI_TRUE);
740  return result;
741WB_END
742
743WB_ENTRY(jint, WB_GetCompileQueueSize(JNIEnv* env, jobject o, jint comp_level))
744  if (comp_level == CompLevel_any) {
745    return CompileBroker::queue_size(CompLevel_full_optimization) /* C2 */ +
746        CompileBroker::queue_size(CompLevel_full_profile) /* C1 */;
747  } else {
748    return CompileBroker::queue_size(comp_level);
749  }
750WB_END
751
752WB_ENTRY(jboolean, WB_TestSetForceInlineMethod(JNIEnv* env, jobject o, jobject method, jboolean value))
753  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
754  CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
755  methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
756  bool result = mh->force_inline();
757  mh->set_force_inline(value == JNI_TRUE);
758  return result;
759WB_END
760
761bool WhiteBox::compile_method(Method* method, int comp_level, int bci, Thread* THREAD) {
762  // Screen for unavailable/bad comp level or null method
763  if (method == NULL || comp_level > TieredStopAtLevel ||
764      CompileBroker::compiler(comp_level) == NULL) {
765    return false;
766  }
767  methodHandle mh(THREAD, method);
768  nmethod* nm = CompileBroker::compile_method(mh, bci, comp_level, mh, mh->invocation_count(), CompileTask::Reason_Whitebox, THREAD);
769  MutexLockerEx mu(Compile_lock);
770  return (mh->queued_for_compilation() || nm != NULL);
771}
772
773WB_ENTRY(jboolean, WB_EnqueueMethodForCompilation(JNIEnv* env, jobject o, jobject method, jint comp_level, jint bci))
774  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
775  CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
776  return WhiteBox::compile_method(Method::checked_resolve_jmethod_id(jmid), comp_level, bci, THREAD);
777WB_END
778
779WB_ENTRY(jboolean, WB_EnqueueInitializerForCompilation(JNIEnv* env, jobject o, jclass klass, jint comp_level))
780  instanceKlassHandle ikh(java_lang_Class::as_Klass(JNIHandles::resolve(klass)));
781  return WhiteBox::compile_method(ikh->class_initializer(), comp_level, InvocationEntryBci, THREAD);
782WB_END
783
784WB_ENTRY(jboolean, WB_ShouldPrintAssembly(JNIEnv* env, jobject o, jobject method, jint comp_level))
785  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
786  CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
787
788  methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
789  DirectiveSet* directive = DirectivesStack::getMatchingDirective(mh, CompileBroker::compiler(comp_level));
790  bool result = directive->PrintAssemblyOption;
791  DirectivesStack::release(directive);
792
793  return result;
794WB_END
795
796WB_ENTRY(jint, WB_MatchesInline(JNIEnv* env, jobject o, jobject method, jstring pattern))
797  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
798  CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
799
800  methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
801
802  ResourceMark rm;
803  const char* error_msg = NULL;
804  char* method_str = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(pattern));
805  InlineMatcher* m = InlineMatcher::parse_inline_pattern(method_str, error_msg);
806
807  if (m == NULL) {
808    assert(error_msg != NULL, "Always have an error message");
809    tty->print_cr("Got error: %s", error_msg);
810    return -1; // Pattern failed
811  }
812
813  // Pattern works - now check if it matches
814  int result;
815  if (m->match(mh, InlineMatcher::force_inline)) {
816    result = 2; // Force inline match
817  } else if (m->match(mh, InlineMatcher::dont_inline)) {
818    result = 1; // Dont inline match
819  } else {
820    result = 0; // No match
821  }
822  delete m;
823  return result;
824WB_END
825
826WB_ENTRY(jint, WB_MatchesMethod(JNIEnv* env, jobject o, jobject method, jstring pattern))
827  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
828  CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
829
830  methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
831
832  ResourceMark rm;
833  char* method_str = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(pattern));
834
835  const char* error_msg = NULL;
836
837  BasicMatcher* m = BasicMatcher::parse_method_pattern(method_str, error_msg);
838  if (m == NULL) {
839    assert(error_msg != NULL, "Must have error_msg");
840    tty->print_cr("Got error: %s", error_msg);
841    return -1;
842  }
843
844  // Pattern works - now check if it matches
845  int result = m->matches(mh);
846  delete m;
847  assert(result == 0 || result == 1, "Result out of range");
848  return result;
849WB_END
850
851static AlwaysFalseClosure always_false;
852
853WB_ENTRY(void, WB_ClearMethodState(JNIEnv* env, jobject o, jobject method))
854  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
855  CHECK_JNI_EXCEPTION(env);
856  methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
857  MutexLockerEx mu(Compile_lock);
858  MethodData* mdo = mh->method_data();
859  MethodCounters* mcs = mh->method_counters();
860
861  if (mdo != NULL) {
862    mdo->init();
863    ResourceMark rm;
864    int arg_count = mdo->method()->size_of_parameters();
865    for (int i = 0; i < arg_count; i++) {
866      mdo->set_arg_modified(i, 0);
867    }
868    MutexLockerEx mu(mdo->extra_data_lock());
869    mdo->clean_method_data(&always_false);
870  }
871
872  mh->clear_not_c1_compilable();
873  mh->clear_not_c2_compilable();
874  mh->clear_not_c2_osr_compilable();
875  NOT_PRODUCT(mh->set_compiled_invocation_count(0));
876  if (mcs != NULL) {
877    mcs->backedge_counter()->init();
878    mcs->invocation_counter()->init();
879    mcs->set_interpreter_invocation_count(0);
880    mcs->set_interpreter_throwout_count(0);
881
882#ifdef TIERED
883    mcs->set_rate(0.0F);
884    mh->set_prev_event_count(0);
885    mh->set_prev_time(0);
886#endif
887  }
888WB_END
889
890template <typename T>
891static bool GetVMFlag(JavaThread* thread, JNIEnv* env, jstring name, T* value, Flag::Error (*TAt)(const char*, T*, bool, bool)) {
892  if (name == NULL) {
893    return false;
894  }
895  ThreadToNativeFromVM ttnfv(thread);   // can't be in VM when we call JNI
896  const char* flag_name = env->GetStringUTFChars(name, NULL);
897  CHECK_JNI_EXCEPTION_(env, false);
898  Flag::Error result = (*TAt)(flag_name, value, true, true);
899  env->ReleaseStringUTFChars(name, flag_name);
900  return (result == Flag::SUCCESS);
901}
902
903template <typename T>
904static bool SetVMFlag(JavaThread* thread, JNIEnv* env, jstring name, T* value, Flag::Error (*TAtPut)(const char*, T*, Flag::Flags)) {
905  if (name == NULL) {
906    return false;
907  }
908  ThreadToNativeFromVM ttnfv(thread);   // can't be in VM when we call JNI
909  const char* flag_name = env->GetStringUTFChars(name, NULL);
910  CHECK_JNI_EXCEPTION_(env, false);
911  Flag::Error result = (*TAtPut)(flag_name, value, Flag::INTERNAL);
912  env->ReleaseStringUTFChars(name, flag_name);
913  return (result == Flag::SUCCESS);
914}
915
916template <typename T>
917static jobject box(JavaThread* thread, JNIEnv* env, Symbol* name, Symbol* sig, T value) {
918  ResourceMark rm(thread);
919  jclass clazz = env->FindClass(name->as_C_string());
920  CHECK_JNI_EXCEPTION_(env, NULL);
921  jmethodID methodID = env->GetStaticMethodID(clazz,
922        vmSymbols::valueOf_name()->as_C_string(),
923        sig->as_C_string());
924  CHECK_JNI_EXCEPTION_(env, NULL);
925  jobject result = env->CallStaticObjectMethod(clazz, methodID, value);
926  CHECK_JNI_EXCEPTION_(env, NULL);
927  return result;
928}
929
930static jobject booleanBox(JavaThread* thread, JNIEnv* env, jboolean value) {
931  return box(thread, env, vmSymbols::java_lang_Boolean(), vmSymbols::Boolean_valueOf_signature(), value);
932}
933static jobject integerBox(JavaThread* thread, JNIEnv* env, jint value) {
934  return box(thread, env, vmSymbols::java_lang_Integer(), vmSymbols::Integer_valueOf_signature(), value);
935}
936static jobject longBox(JavaThread* thread, JNIEnv* env, jlong value) {
937  return box(thread, env, vmSymbols::java_lang_Long(), vmSymbols::Long_valueOf_signature(), value);
938}
939/* static jobject floatBox(JavaThread* thread, JNIEnv* env, jfloat value) {
940  return box(thread, env, vmSymbols::java_lang_Float(), vmSymbols::Float_valueOf_signature(), value);
941}*/
942static jobject doubleBox(JavaThread* thread, JNIEnv* env, jdouble value) {
943  return box(thread, env, vmSymbols::java_lang_Double(), vmSymbols::Double_valueOf_signature(), value);
944}
945
946static Flag* getVMFlag(JavaThread* thread, JNIEnv* env, jstring name) {
947  ThreadToNativeFromVM ttnfv(thread);   // can't be in VM when we call JNI
948  const char* flag_name = env->GetStringUTFChars(name, NULL);
949  CHECK_JNI_EXCEPTION_(env, NULL);
950  Flag* result = Flag::find_flag(flag_name, strlen(flag_name), true, true);
951  env->ReleaseStringUTFChars(name, flag_name);
952  return result;
953}
954
955WB_ENTRY(jboolean, WB_IsConstantVMFlag(JNIEnv* env, jobject o, jstring name))
956  Flag* flag = getVMFlag(thread, env, name);
957  return (flag != NULL) && flag->is_constant_in_binary();
958WB_END
959
960WB_ENTRY(jboolean, WB_IsLockedVMFlag(JNIEnv* env, jobject o, jstring name))
961  Flag* flag = getVMFlag(thread, env, name);
962  return (flag != NULL) && !(flag->is_unlocked() || flag->is_unlocker());
963WB_END
964
965WB_ENTRY(jobject, WB_GetBooleanVMFlag(JNIEnv* env, jobject o, jstring name))
966  bool result;
967  if (GetVMFlag <bool> (thread, env, name, &result, &CommandLineFlags::boolAt)) {
968    ThreadToNativeFromVM ttnfv(thread);   // can't be in VM when we call JNI
969    return booleanBox(thread, env, result);
970  }
971  return NULL;
972WB_END
973
974WB_ENTRY(jobject, WB_GetIntVMFlag(JNIEnv* env, jobject o, jstring name))
975  int result;
976  if (GetVMFlag <int> (thread, env, name, &result, &CommandLineFlags::intAt)) {
977    ThreadToNativeFromVM ttnfv(thread);   // can't be in VM when we call JNI
978    return longBox(thread, env, result);
979  }
980  return NULL;
981WB_END
982
983WB_ENTRY(jobject, WB_GetUintVMFlag(JNIEnv* env, jobject o, jstring name))
984  uint result;
985  if (GetVMFlag <uint> (thread, env, name, &result, &CommandLineFlags::uintAt)) {
986    ThreadToNativeFromVM ttnfv(thread);   // can't be in VM when we call JNI
987    return longBox(thread, env, result);
988  }
989  return NULL;
990WB_END
991
992WB_ENTRY(jobject, WB_GetIntxVMFlag(JNIEnv* env, jobject o, jstring name))
993  intx result;
994  if (GetVMFlag <intx> (thread, env, name, &result, &CommandLineFlags::intxAt)) {
995    ThreadToNativeFromVM ttnfv(thread);   // can't be in VM when we call JNI
996    return longBox(thread, env, result);
997  }
998  return NULL;
999WB_END
1000
1001WB_ENTRY(jobject, WB_GetUintxVMFlag(JNIEnv* env, jobject o, jstring name))
1002  uintx result;
1003  if (GetVMFlag <uintx> (thread, env, name, &result, &CommandLineFlags::uintxAt)) {
1004    ThreadToNativeFromVM ttnfv(thread);   // can't be in VM when we call JNI
1005    return longBox(thread, env, result);
1006  }
1007  return NULL;
1008WB_END
1009
1010WB_ENTRY(jobject, WB_GetUint64VMFlag(JNIEnv* env, jobject o, jstring name))
1011  uint64_t result;
1012  if (GetVMFlag <uint64_t> (thread, env, name, &result, &CommandLineFlags::uint64_tAt)) {
1013    ThreadToNativeFromVM ttnfv(thread);   // can't be in VM when we call JNI
1014    return longBox(thread, env, result);
1015  }
1016  return NULL;
1017WB_END
1018
1019WB_ENTRY(jobject, WB_GetSizeTVMFlag(JNIEnv* env, jobject o, jstring name))
1020  uintx result;
1021  if (GetVMFlag <size_t> (thread, env, name, &result, &CommandLineFlags::size_tAt)) {
1022    ThreadToNativeFromVM ttnfv(thread);   // can't be in VM when we call JNI
1023    return longBox(thread, env, result);
1024  }
1025  return NULL;
1026WB_END
1027
1028WB_ENTRY(jobject, WB_GetDoubleVMFlag(JNIEnv* env, jobject o, jstring name))
1029  double result;
1030  if (GetVMFlag <double> (thread, env, name, &result, &CommandLineFlags::doubleAt)) {
1031    ThreadToNativeFromVM ttnfv(thread);   // can't be in VM when we call JNI
1032    return doubleBox(thread, env, result);
1033  }
1034  return NULL;
1035WB_END
1036
1037WB_ENTRY(jstring, WB_GetStringVMFlag(JNIEnv* env, jobject o, jstring name))
1038  ccstr ccstrResult;
1039  if (GetVMFlag <ccstr> (thread, env, name, &ccstrResult, &CommandLineFlags::ccstrAt)) {
1040    ThreadToNativeFromVM ttnfv(thread);   // can't be in VM when we call JNI
1041    jstring result = env->NewStringUTF(ccstrResult);
1042    CHECK_JNI_EXCEPTION_(env, NULL);
1043    return result;
1044  }
1045  return NULL;
1046WB_END
1047
1048WB_ENTRY(void, WB_SetBooleanVMFlag(JNIEnv* env, jobject o, jstring name, jboolean value))
1049  bool result = value == JNI_TRUE ? true : false;
1050  SetVMFlag <bool> (thread, env, name, &result, &CommandLineFlags::boolAtPut);
1051WB_END
1052
1053WB_ENTRY(void, WB_SetIntVMFlag(JNIEnv* env, jobject o, jstring name, jlong value))
1054  int result = value;
1055  SetVMFlag <int> (thread, env, name, &result, &CommandLineFlags::intAtPut);
1056WB_END
1057
1058WB_ENTRY(void, WB_SetUintVMFlag(JNIEnv* env, jobject o, jstring name, jlong value))
1059  uint result = value;
1060  SetVMFlag <uint> (thread, env, name, &result, &CommandLineFlags::uintAtPut);
1061WB_END
1062
1063WB_ENTRY(void, WB_SetIntxVMFlag(JNIEnv* env, jobject o, jstring name, jlong value))
1064  intx result = value;
1065  SetVMFlag <intx> (thread, env, name, &result, &CommandLineFlags::intxAtPut);
1066WB_END
1067
1068WB_ENTRY(void, WB_SetUintxVMFlag(JNIEnv* env, jobject o, jstring name, jlong value))
1069  uintx result = value;
1070  SetVMFlag <uintx> (thread, env, name, &result, &CommandLineFlags::uintxAtPut);
1071WB_END
1072
1073WB_ENTRY(void, WB_SetUint64VMFlag(JNIEnv* env, jobject o, jstring name, jlong value))
1074  uint64_t result = value;
1075  SetVMFlag <uint64_t> (thread, env, name, &result, &CommandLineFlags::uint64_tAtPut);
1076WB_END
1077
1078WB_ENTRY(void, WB_SetSizeTVMFlag(JNIEnv* env, jobject o, jstring name, jlong value))
1079  size_t result = value;
1080  SetVMFlag <size_t> (thread, env, name, &result, &CommandLineFlags::size_tAtPut);
1081WB_END
1082
1083WB_ENTRY(void, WB_SetDoubleVMFlag(JNIEnv* env, jobject o, jstring name, jdouble value))
1084  double result = value;
1085  SetVMFlag <double> (thread, env, name, &result, &CommandLineFlags::doubleAtPut);
1086WB_END
1087
1088WB_ENTRY(void, WB_SetStringVMFlag(JNIEnv* env, jobject o, jstring name, jstring value))
1089  ThreadToNativeFromVM ttnfv(thread);   // can't be in VM when we call JNI
1090  const char* ccstrValue;
1091  if (value == NULL) {
1092    ccstrValue = NULL;
1093  }
1094  else {
1095    ccstrValue = env->GetStringUTFChars(value, NULL);
1096    CHECK_JNI_EXCEPTION(env);
1097  }
1098  ccstr ccstrResult = ccstrValue;
1099  bool needFree;
1100  {
1101    ThreadInVMfromNative ttvfn(thread); // back to VM
1102    needFree = SetVMFlag <ccstr> (thread, env, name, &ccstrResult, &CommandLineFlags::ccstrAtPut);
1103  }
1104  if (value != NULL) {
1105    env->ReleaseStringUTFChars(value, ccstrValue);
1106  }
1107  if (needFree) {
1108    FREE_C_HEAP_ARRAY(char, ccstrResult);
1109  }
1110WB_END
1111
1112WB_ENTRY(void, WB_LockCompilation(JNIEnv* env, jobject o, jlong timeout))
1113  WhiteBox::compilation_locked = true;
1114WB_END
1115
1116WB_ENTRY(void, WB_UnlockCompilation(JNIEnv* env, jobject o))
1117  MonitorLockerEx mo(Compilation_lock, Mutex::_no_safepoint_check_flag);
1118  WhiteBox::compilation_locked = false;
1119  mo.notify_all();
1120WB_END
1121
1122WB_ENTRY(void, WB_ForceNMethodSweep(JNIEnv* env, jobject o))
1123  // Force a code cache sweep and block until it finished
1124  NMethodSweeper::force_sweep();
1125WB_END
1126
1127WB_ENTRY(jboolean, WB_IsInStringTable(JNIEnv* env, jobject o, jstring javaString))
1128  ResourceMark rm(THREAD);
1129  int len;
1130  jchar* name = java_lang_String::as_unicode_string(JNIHandles::resolve(javaString), len, CHECK_false);
1131  return (StringTable::lookup(name, len) != NULL);
1132WB_END
1133
1134WB_ENTRY(void, WB_FullGC(JNIEnv* env, jobject o))
1135  Universe::heap()->collector_policy()->set_should_clear_all_soft_refs(true);
1136  Universe::heap()->collect(GCCause::_wb_full_gc);
1137#if INCLUDE_ALL_GCS
1138  if (UseG1GC) {
1139    // Needs to be cleared explicitly for G1
1140    Universe::heap()->collector_policy()->set_should_clear_all_soft_refs(false);
1141  }
1142#endif // INCLUDE_ALL_GCS
1143WB_END
1144
1145WB_ENTRY(void, WB_YoungGC(JNIEnv* env, jobject o))
1146  Universe::heap()->collect(GCCause::_wb_young_gc);
1147WB_END
1148
1149WB_ENTRY(void, WB_ReadReservedMemory(JNIEnv* env, jobject o))
1150  // static+volatile in order to force the read to happen
1151  // (not be eliminated by the compiler)
1152  static char c;
1153  static volatile char* p;
1154
1155  p = os::reserve_memory(os::vm_allocation_granularity(), NULL, 0);
1156  if (p == NULL) {
1157    THROW_MSG(vmSymbols::java_lang_OutOfMemoryError(), "Failed to reserve memory");
1158  }
1159
1160  c = *p;
1161WB_END
1162
1163WB_ENTRY(jstring, WB_GetCPUFeatures(JNIEnv* env, jobject o))
1164  const char* features = VM_Version::features_string();
1165  ThreadToNativeFromVM ttn(thread);
1166  jstring features_string = env->NewStringUTF(features);
1167
1168  CHECK_JNI_EXCEPTION_(env, NULL);
1169
1170  return features_string;
1171WB_END
1172
1173int WhiteBox::get_blob_type(const CodeBlob* code) {
1174  guarantee(WhiteBoxAPI, "internal testing API :: WhiteBox has to be enabled");
1175  if (code->is_aot()) {
1176    return -1;
1177  }
1178  return CodeCache::get_code_heap(code)->code_blob_type();
1179}
1180
1181CodeHeap* WhiteBox::get_code_heap(int blob_type) {
1182  guarantee(WhiteBoxAPI, "internal testing API :: WhiteBox has to be enabled");
1183  return CodeCache::get_code_heap(blob_type);
1184}
1185
1186struct CodeBlobStub {
1187  CodeBlobStub(const CodeBlob* blob) :
1188      name(os::strdup(blob->name())),
1189      size(blob->size()),
1190      blob_type(WhiteBox::get_blob_type(blob)),
1191      address((jlong) blob) { }
1192  ~CodeBlobStub() { os::free((void*) name); }
1193  const char* const name;
1194  const jint        size;
1195  const jint        blob_type;
1196  const jlong       address;
1197};
1198
1199static jobjectArray codeBlob2objectArray(JavaThread* thread, JNIEnv* env, CodeBlobStub* cb) {
1200  jclass clazz = env->FindClass(vmSymbols::java_lang_Object()->as_C_string());
1201  CHECK_JNI_EXCEPTION_(env, NULL);
1202  jobjectArray result = env->NewObjectArray(4, clazz, NULL);
1203
1204  jstring name = env->NewStringUTF(cb->name);
1205  CHECK_JNI_EXCEPTION_(env, NULL);
1206  env->SetObjectArrayElement(result, 0, name);
1207
1208  jobject obj = integerBox(thread, env, cb->size);
1209  CHECK_JNI_EXCEPTION_(env, NULL);
1210  env->SetObjectArrayElement(result, 1, obj);
1211
1212  obj = integerBox(thread, env, cb->blob_type);
1213  CHECK_JNI_EXCEPTION_(env, NULL);
1214  env->SetObjectArrayElement(result, 2, obj);
1215
1216  obj = longBox(thread, env, cb->address);
1217  CHECK_JNI_EXCEPTION_(env, NULL);
1218  env->SetObjectArrayElement(result, 3, obj);
1219
1220  return result;
1221}
1222
1223WB_ENTRY(jobjectArray, WB_GetNMethod(JNIEnv* env, jobject o, jobject method, jboolean is_osr))
1224  ResourceMark rm(THREAD);
1225  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
1226  CHECK_JNI_EXCEPTION_(env, NULL);
1227  methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
1228  CompiledMethod* code = is_osr ? mh->lookup_osr_nmethod_for(InvocationEntryBci, CompLevel_none, false) : mh->code();
1229  jobjectArray result = NULL;
1230  if (code == NULL) {
1231    return result;
1232  }
1233  int comp_level = code->comp_level();
1234  int insts_size = comp_level == CompLevel_aot ? code->code_end() - code->code_begin() : code->insts_size();
1235
1236  ThreadToNativeFromVM ttn(thread);
1237  jclass clazz = env->FindClass(vmSymbols::java_lang_Object()->as_C_string());
1238  CHECK_JNI_EXCEPTION_(env, NULL);
1239  result = env->NewObjectArray(5, clazz, NULL);
1240  if (result == NULL) {
1241    return result;
1242  }
1243
1244  CodeBlobStub stub(code);
1245  jobjectArray codeBlob = codeBlob2objectArray(thread, env, &stub);
1246  CHECK_JNI_EXCEPTION_(env, NULL);
1247  env->SetObjectArrayElement(result, 0, codeBlob);
1248
1249  jobject level = integerBox(thread, env, comp_level);
1250  CHECK_JNI_EXCEPTION_(env, NULL);
1251  env->SetObjectArrayElement(result, 1, level);
1252
1253  jbyteArray insts = env->NewByteArray(insts_size);
1254  CHECK_JNI_EXCEPTION_(env, NULL);
1255  env->SetByteArrayRegion(insts, 0, insts_size, (jbyte*) code->insts_begin());
1256  env->SetObjectArrayElement(result, 2, insts);
1257
1258  jobject id = integerBox(thread, env, code->compile_id());
1259  CHECK_JNI_EXCEPTION_(env, NULL);
1260  env->SetObjectArrayElement(result, 3, id);
1261
1262  jobject entry_point = longBox(thread, env, (jlong) code->entry_point());
1263  CHECK_JNI_EXCEPTION_(env, NULL);
1264  env->SetObjectArrayElement(result, 4, entry_point);
1265
1266  return result;
1267WB_END
1268
1269CodeBlob* WhiteBox::allocate_code_blob(int size, int blob_type) {
1270  guarantee(WhiteBoxAPI, "internal testing API :: WhiteBox has to be enabled");
1271  BufferBlob* blob;
1272  int full_size = CodeBlob::align_code_offset(sizeof(BufferBlob));
1273  if (full_size < size) {
1274    full_size += round_to(size - full_size, oopSize);
1275  }
1276  {
1277    MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
1278    blob = (BufferBlob*) CodeCache::allocate(full_size, blob_type);
1279    ::new (blob) BufferBlob("WB::DummyBlob", full_size);
1280  }
1281  // Track memory usage statistic after releasing CodeCache_lock
1282  MemoryService::track_code_cache_memory_usage();
1283  return blob;
1284}
1285
1286WB_ENTRY(jlong, WB_AllocateCodeBlob(JNIEnv* env, jobject o, jint size, jint blob_type))
1287  if (size < 0) {
1288    THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
1289      err_msg("WB_AllocateCodeBlob: size is negative: " INT32_FORMAT, size));
1290  }
1291  return (jlong) WhiteBox::allocate_code_blob(size, blob_type);
1292WB_END
1293
1294WB_ENTRY(void, WB_FreeCodeBlob(JNIEnv* env, jobject o, jlong addr))
1295  if (addr == 0) {
1296    return;
1297  }
1298  BufferBlob::free((BufferBlob*) addr);
1299WB_END
1300
1301WB_ENTRY(jobjectArray, WB_GetCodeHeapEntries(JNIEnv* env, jobject o, jint blob_type))
1302  ResourceMark rm;
1303  GrowableArray<CodeBlobStub*> blobs;
1304  {
1305    MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
1306    CodeHeap* heap = WhiteBox::get_code_heap(blob_type);
1307    if (heap == NULL) {
1308      return NULL;
1309    }
1310    for (CodeBlob* cb = (CodeBlob*) heap->first();
1311         cb != NULL; cb = (CodeBlob*) heap->next(cb)) {
1312      CodeBlobStub* stub = NEW_RESOURCE_OBJ(CodeBlobStub);
1313      new (stub) CodeBlobStub(cb);
1314      blobs.append(stub);
1315    }
1316  }
1317  if (blobs.length() == 0) {
1318    return NULL;
1319  }
1320  ThreadToNativeFromVM ttn(thread);
1321  jobjectArray result = NULL;
1322  jclass clazz = env->FindClass(vmSymbols::java_lang_Object()->as_C_string());
1323  CHECK_JNI_EXCEPTION_(env, NULL);
1324  result = env->NewObjectArray(blobs.length(), clazz, NULL);
1325  CHECK_JNI_EXCEPTION_(env, NULL);
1326  if (result == NULL) {
1327    return result;
1328  }
1329  int i = 0;
1330  for (GrowableArrayIterator<CodeBlobStub*> it = blobs.begin();
1331       it != blobs.end(); ++it) {
1332    jobjectArray obj = codeBlob2objectArray(thread, env, *it);
1333    CHECK_JNI_EXCEPTION_(env, NULL);
1334    env->SetObjectArrayElement(result, i, obj);
1335    CHECK_JNI_EXCEPTION_(env, NULL);
1336    ++i;
1337  }
1338  return result;
1339WB_END
1340
1341WB_ENTRY(jint, WB_GetCompilationActivityMode(JNIEnv* env, jobject o))
1342  return CompileBroker::get_compilation_activity_mode();
1343WB_END
1344
1345WB_ENTRY(jobjectArray, WB_GetCodeBlob(JNIEnv* env, jobject o, jlong addr))
1346  if (addr == 0) {
1347    THROW_MSG_NULL(vmSymbols::java_lang_NullPointerException(),
1348      "WB_GetCodeBlob: addr is null");
1349  }
1350  ThreadToNativeFromVM ttn(thread);
1351  CodeBlobStub stub((CodeBlob*) addr);
1352  return codeBlob2objectArray(thread, env, &stub);
1353WB_END
1354
1355WB_ENTRY(jlong, WB_GetMethodData(JNIEnv* env, jobject wv, jobject method))
1356  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
1357  CHECK_JNI_EXCEPTION_(env, 0);
1358  methodHandle mh(thread, Method::checked_resolve_jmethod_id(jmid));
1359  return (jlong) mh->method_data();
1360WB_END
1361
1362WB_ENTRY(jlong, WB_GetThreadStackSize(JNIEnv* env, jobject o))
1363  return (jlong) Thread::current()->stack_size();
1364WB_END
1365
1366WB_ENTRY(jlong, WB_GetThreadRemainingStackSize(JNIEnv* env, jobject o))
1367  JavaThread* t = JavaThread::current();
1368  return (jlong) t->stack_available(os::current_stack_pointer()) - (jlong)JavaThread::stack_shadow_zone_size();
1369WB_END
1370
1371
1372int WhiteBox::array_bytes_to_length(size_t bytes) {
1373  return Array<u1>::bytes_to_length(bytes);
1374}
1375
1376WB_ENTRY(jlong, WB_AllocateMetaspace(JNIEnv* env, jobject wb, jobject class_loader, jlong size))
1377  if (size < 0) {
1378    THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
1379        err_msg("WB_AllocateMetaspace: size is negative: " JLONG_FORMAT, size));
1380  }
1381
1382  oop class_loader_oop = JNIHandles::resolve(class_loader);
1383  ClassLoaderData* cld = class_loader_oop != NULL
1384      ? java_lang_ClassLoader::loader_data(class_loader_oop)
1385      : ClassLoaderData::the_null_class_loader_data();
1386
1387  void* metadata = MetadataFactory::new_writeable_array<u1>(cld, WhiteBox::array_bytes_to_length((size_t)size), thread);
1388
1389  return (jlong)(uintptr_t)metadata;
1390WB_END
1391
1392WB_ENTRY(void, WB_FreeMetaspace(JNIEnv* env, jobject wb, jobject class_loader, jlong addr, jlong size))
1393  oop class_loader_oop = JNIHandles::resolve(class_loader);
1394  ClassLoaderData* cld = class_loader_oop != NULL
1395      ? java_lang_ClassLoader::loader_data(class_loader_oop)
1396      : ClassLoaderData::the_null_class_loader_data();
1397
1398  MetadataFactory::free_array(cld, (Array<u1>*)(uintptr_t)addr);
1399WB_END
1400
1401WB_ENTRY(void, WB_DefineModule(JNIEnv* env, jobject o, jobject module, jstring version, jstring location,
1402                                jobjectArray packages))
1403  Modules::define_module(module, version, location, packages, CHECK);
1404WB_END
1405
1406WB_ENTRY(void, WB_AddModuleExports(JNIEnv* env, jobject o, jobject from_module, jstring package, jobject to_module))
1407  Modules::add_module_exports_qualified(from_module, package, to_module, CHECK);
1408WB_END
1409
1410WB_ENTRY(void, WB_AddModuleExportsToAllUnnamed(JNIEnv* env, jobject o, jclass module, jstring package))
1411  Modules::add_module_exports_to_all_unnamed(module, package, CHECK);
1412WB_END
1413
1414WB_ENTRY(void, WB_AddModuleExportsToAll(JNIEnv* env, jobject o, jclass module, jstring package))
1415  Modules::add_module_exports(module, package, NULL, CHECK);
1416WB_END
1417
1418WB_ENTRY(void, WB_AddReadsModule(JNIEnv* env, jobject o, jobject from_module, jobject source_module))
1419  Modules::add_reads_module(from_module, source_module, CHECK);
1420WB_END
1421
1422WB_ENTRY(void, WB_AddModulePackage(JNIEnv* env, jobject o, jclass module, jstring package))
1423  Modules::add_module_package(module, package, CHECK);
1424WB_END
1425
1426WB_ENTRY(jobject, WB_GetModuleByPackageName(JNIEnv* env, jobject o, jobject loader, jstring package))
1427  return Modules::get_module_by_package_name(loader, package, THREAD);
1428WB_END
1429
1430WB_ENTRY(jlong, WB_IncMetaspaceCapacityUntilGC(JNIEnv* env, jobject wb, jlong inc))
1431  if (inc < 0) {
1432    THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
1433        err_msg("WB_IncMetaspaceCapacityUntilGC: inc is negative: " JLONG_FORMAT, inc));
1434  }
1435
1436  jlong max_size_t = (jlong) ((size_t) -1);
1437  if (inc > max_size_t) {
1438    THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
1439        err_msg("WB_IncMetaspaceCapacityUntilGC: inc does not fit in size_t: " JLONG_FORMAT, inc));
1440  }
1441
1442  size_t new_cap_until_GC = 0;
1443  size_t aligned_inc = align_size_down((size_t) inc, Metaspace::commit_alignment());
1444  bool success = MetaspaceGC::inc_capacity_until_GC(aligned_inc, &new_cap_until_GC);
1445  if (!success) {
1446    THROW_MSG_0(vmSymbols::java_lang_IllegalStateException(),
1447                "WB_IncMetaspaceCapacityUntilGC: could not increase capacity until GC "
1448                "due to contention with another thread");
1449  }
1450  return (jlong) new_cap_until_GC;
1451WB_END
1452
1453WB_ENTRY(jlong, WB_MetaspaceCapacityUntilGC(JNIEnv* env, jobject wb))
1454  return (jlong) MetaspaceGC::capacity_until_GC();
1455WB_END
1456
1457WB_ENTRY(jboolean, WB_MetaspaceShouldConcurrentCollect(JNIEnv* env, jobject wb))
1458  return MetaspaceGC::should_concurrent_collect();
1459WB_END
1460
1461
1462WB_ENTRY(void, WB_AssertMatchingSafepointCalls(JNIEnv* env, jobject o, jboolean mutexSafepointValue, jboolean attemptedNoSafepointValue))
1463  Monitor::SafepointCheckRequired sfpt_check_required = mutexSafepointValue ?
1464                                           Monitor::_safepoint_check_always :
1465                                           Monitor::_safepoint_check_never;
1466  MutexLockerEx ml(new Mutex(Mutex::leaf, "SFPT_Test_lock", true, sfpt_check_required),
1467                   attemptedNoSafepointValue == JNI_TRUE);
1468WB_END
1469
1470WB_ENTRY(jboolean, WB_IsMonitorInflated(JNIEnv* env, jobject wb, jobject obj))
1471  oop obj_oop = JNIHandles::resolve(obj);
1472  return (jboolean) obj_oop->mark()->has_monitor();
1473WB_END
1474
1475WB_ENTRY(void, WB_ForceSafepoint(JNIEnv* env, jobject wb))
1476  VM_ForceSafepoint force_safepoint_op;
1477  VMThread::execute(&force_safepoint_op);
1478WB_END
1479
1480WB_ENTRY(jlong, WB_GetConstantPool(JNIEnv* env, jobject wb, jclass klass))
1481  instanceKlassHandle ikh(java_lang_Class::as_Klass(JNIHandles::resolve(klass)));
1482  return (jlong) ikh->constants();
1483WB_END
1484
1485WB_ENTRY(jint, WB_GetConstantPoolCacheIndexTag(JNIEnv* env, jobject wb))
1486  return ConstantPool::CPCACHE_INDEX_TAG;
1487WB_END
1488
1489WB_ENTRY(jint, WB_GetConstantPoolCacheLength(JNIEnv* env, jobject wb, jclass klass))
1490  instanceKlassHandle ikh(java_lang_Class::as_Klass(JNIHandles::resolve(klass)));
1491  ConstantPool* cp = ikh->constants();
1492  if (cp->cache() == NULL) {
1493      return -1;
1494  }
1495  return cp->cache()->length();
1496WB_END
1497
1498WB_ENTRY(jint, WB_ConstantPoolRemapInstructionOperandFromCache(JNIEnv* env, jobject wb, jclass klass, jint index))
1499  instanceKlassHandle ikh(java_lang_Class::as_Klass(JNIHandles::resolve(klass)));
1500  ConstantPool* cp = ikh->constants();
1501  if (cp->cache() == NULL) {
1502    THROW_MSG_0(vmSymbols::java_lang_IllegalStateException(), "Constant pool does not have a cache");
1503  }
1504  jint cpci = index;
1505  jint cpciTag = ConstantPool::CPCACHE_INDEX_TAG;
1506  if (cpciTag > cpci || cpci >= cp->cache()->length() + cpciTag) {
1507    THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Constant pool cache index is out of range");
1508  }
1509  jint cpi = cp->remap_instruction_operand_from_cache(cpci);
1510  return cpi;
1511WB_END
1512
1513WB_ENTRY(jint, WB_ConstantPoolEncodeIndyIndex(JNIEnv* env, jobject wb, jint index))
1514  return ConstantPool::encode_invokedynamic_index(index);
1515WB_END
1516
1517WB_ENTRY(void, WB_ClearInlineCaches(JNIEnv* env, jobject wb, jboolean preserve_static_stubs))
1518  VM_ClearICs clear_ics(preserve_static_stubs == JNI_TRUE);
1519  VMThread::execute(&clear_ics);
1520WB_END
1521
1522template <typename T>
1523static bool GetMethodOption(JavaThread* thread, JNIEnv* env, jobject method, jstring name, T* value) {
1524  assert(value != NULL, "sanity");
1525  if (method == NULL || name == NULL) {
1526    return false;
1527  }
1528  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
1529  CHECK_JNI_EXCEPTION_(env, false);
1530  methodHandle mh(thread, Method::checked_resolve_jmethod_id(jmid));
1531  // can't be in VM when we call JNI
1532  ThreadToNativeFromVM ttnfv(thread);
1533  const char* flag_name = env->GetStringUTFChars(name, NULL);
1534  CHECK_JNI_EXCEPTION_(env, false);
1535  bool result =  CompilerOracle::has_option_value(mh, flag_name, *value);
1536  env->ReleaseStringUTFChars(name, flag_name);
1537  return result;
1538}
1539
1540WB_ENTRY(jobject, WB_GetMethodBooleaneOption(JNIEnv* env, jobject wb, jobject method, jstring name))
1541  bool result;
1542  if (GetMethodOption<bool> (thread, env, method, name, &result)) {
1543    // can't be in VM when we call JNI
1544    ThreadToNativeFromVM ttnfv(thread);
1545    return booleanBox(thread, env, result);
1546  }
1547  return NULL;
1548WB_END
1549
1550WB_ENTRY(jobject, WB_GetMethodIntxOption(JNIEnv* env, jobject wb, jobject method, jstring name))
1551  intx result;
1552  if (GetMethodOption <intx> (thread, env, method, name, &result)) {
1553    // can't be in VM when we call JNI
1554    ThreadToNativeFromVM ttnfv(thread);
1555    return longBox(thread, env, result);
1556  }
1557  return NULL;
1558WB_END
1559
1560WB_ENTRY(jobject, WB_GetMethodUintxOption(JNIEnv* env, jobject wb, jobject method, jstring name))
1561  uintx result;
1562  if (GetMethodOption <uintx> (thread, env, method, name, &result)) {
1563    // can't be in VM when we call JNI
1564    ThreadToNativeFromVM ttnfv(thread);
1565    return longBox(thread, env, result);
1566  }
1567  return NULL;
1568WB_END
1569
1570WB_ENTRY(jobject, WB_GetMethodDoubleOption(JNIEnv* env, jobject wb, jobject method, jstring name))
1571  double result;
1572  if (GetMethodOption <double> (thread, env, method, name, &result)) {
1573    // can't be in VM when we call JNI
1574    ThreadToNativeFromVM ttnfv(thread);
1575    return doubleBox(thread, env, result);
1576  }
1577  return NULL;
1578WB_END
1579
1580WB_ENTRY(jobject, WB_GetMethodStringOption(JNIEnv* env, jobject wb, jobject method, jstring name))
1581  ccstr ccstrResult;
1582  if (GetMethodOption <ccstr> (thread, env, method, name, &ccstrResult)) {
1583    // can't be in VM when we call JNI
1584    ThreadToNativeFromVM ttnfv(thread);
1585    jstring result = env->NewStringUTF(ccstrResult);
1586    CHECK_JNI_EXCEPTION_(env, NULL);
1587    return result;
1588  }
1589  return NULL;
1590WB_END
1591
1592WB_ENTRY(jboolean, WB_IsShared(JNIEnv* env, jobject wb, jobject obj))
1593  oop obj_oop = JNIHandles::resolve(obj);
1594  return MetaspaceShared::is_in_shared_space((void*)obj_oop);
1595WB_END
1596
1597WB_ENTRY(jboolean, WB_IsSharedClass(JNIEnv* env, jobject wb, jclass clazz))
1598  return (jboolean)MetaspaceShared::is_in_shared_space(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz)));
1599WB_END
1600
1601WB_ENTRY(jboolean, WB_AreSharedStringsIgnored(JNIEnv* env))
1602  return StringTable::shared_string_ignored();
1603WB_END
1604
1605//Some convenience methods to deal with objects from java
1606int WhiteBox::offset_for_field(const char* field_name, oop object,
1607    Symbol* signature_symbol) {
1608  assert(field_name != NULL && strlen(field_name) > 0, "Field name not valid");
1609  Thread* THREAD = Thread::current();
1610
1611  //Get the class of our object
1612  Klass* arg_klass = object->klass();
1613  //Turn it into an instance-klass
1614  InstanceKlass* ik = InstanceKlass::cast(arg_klass);
1615
1616  //Create symbols to look for in the class
1617  TempNewSymbol name_symbol = SymbolTable::lookup(field_name, (int) strlen(field_name),
1618      THREAD);
1619
1620  //To be filled in with an offset of the field we're looking for
1621  fieldDescriptor fd;
1622
1623  Klass* res = ik->find_field(name_symbol, signature_symbol, &fd);
1624  if (res == NULL) {
1625    tty->print_cr("Invalid layout of %s at %s", ik->external_name(),
1626        name_symbol->as_C_string());
1627    vm_exit_during_initialization("Invalid layout of preloaded class: use -Xlog:class+load=info to see the origin of the problem class");
1628  }
1629
1630  //fetch the field at the offset we've found
1631  int dest_offset = fd.offset();
1632
1633  return dest_offset;
1634}
1635
1636
1637const char* WhiteBox::lookup_jstring(const char* field_name, oop object) {
1638  int offset = offset_for_field(field_name, object,
1639      vmSymbols::string_signature());
1640  oop string = object->obj_field(offset);
1641  if (string == NULL) {
1642    return NULL;
1643  }
1644  const char* ret = java_lang_String::as_utf8_string(string);
1645  return ret;
1646}
1647
1648bool WhiteBox::lookup_bool(const char* field_name, oop object) {
1649  int offset =
1650      offset_for_field(field_name, object, vmSymbols::bool_signature());
1651  bool ret = (object->bool_field(offset) == JNI_TRUE);
1652  return ret;
1653}
1654
1655void WhiteBox::register_methods(JNIEnv* env, jclass wbclass, JavaThread* thread, JNINativeMethod* method_array, int method_count) {
1656  ResourceMark rm;
1657  ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
1658
1659  //  one by one registration natives for exception catching
1660  jclass no_such_method_error_klass = env->FindClass(vmSymbols::java_lang_NoSuchMethodError()->as_C_string());
1661  CHECK_JNI_EXCEPTION(env);
1662  for (int i = 0, n = method_count; i < n; ++i) {
1663    // Skip dummy entries
1664    if (method_array[i].fnPtr == NULL) continue;
1665    if (env->RegisterNatives(wbclass, &method_array[i], 1) != 0) {
1666      jthrowable throwable_obj = env->ExceptionOccurred();
1667      if (throwable_obj != NULL) {
1668        env->ExceptionClear();
1669        if (env->IsInstanceOf(throwable_obj, no_such_method_error_klass)) {
1670          // NoSuchMethodError is thrown when a method can't be found or a method is not native.
1671          // Ignoring the exception since it is not preventing use of other WhiteBox methods.
1672          tty->print_cr("Warning: 'NoSuchMethodError' on register of sun.hotspot.WhiteBox::%s%s",
1673              method_array[i].name, method_array[i].signature);
1674        }
1675      } else {
1676        // Registration failed unexpectedly.
1677        tty->print_cr("Warning: unexpected error on register of sun.hotspot.WhiteBox::%s%s. All methods will be unregistered",
1678            method_array[i].name, method_array[i].signature);
1679        env->UnregisterNatives(wbclass);
1680        break;
1681      }
1682    }
1683  }
1684}
1685
1686WB_ENTRY(jint, WB_AddCompilerDirective(JNIEnv* env, jobject o, jstring compDirect))
1687  // can't be in VM when we call JNI
1688  ThreadToNativeFromVM ttnfv(thread);
1689  const char* dir = env->GetStringUTFChars(compDirect, NULL);
1690  CHECK_JNI_EXCEPTION_(env, 0);
1691  int ret;
1692  {
1693    ThreadInVMfromNative ttvfn(thread); // back to VM
1694    ret = DirectivesParser::parse_string(dir, tty);
1695  }
1696  env->ReleaseStringUTFChars(compDirect, dir);
1697  // -1 for error parsing directive. Return 0 as number of directives added.
1698  if (ret == -1) {
1699    ret = 0;
1700  }
1701  return (jint) ret;
1702WB_END
1703
1704WB_ENTRY(void, WB_RemoveCompilerDirective(JNIEnv* env, jobject o, jint count))
1705  DirectivesStack::pop(count);
1706WB_END
1707
1708#define CC (char*)
1709
1710static JNINativeMethod methods[] = {
1711  {CC"getObjectAddress0",                CC"(Ljava/lang/Object;)J", (void*)&WB_GetObjectAddress  },
1712  {CC"getObjectSize0",                   CC"(Ljava/lang/Object;)J", (void*)&WB_GetObjectSize     },
1713  {CC"isObjectInOldGen0",                CC"(Ljava/lang/Object;)Z", (void*)&WB_isObjectInOldGen  },
1714  {CC"getHeapOopSize",                   CC"()I",                   (void*)&WB_GetHeapOopSize    },
1715  {CC"getVMPageSize",                    CC"()I",                   (void*)&WB_GetVMPageSize     },
1716  {CC"getVMAllocationGranularity",       CC"()J",                   (void*)&WB_GetVMAllocationGranularity },
1717  {CC"getVMLargePageSize",               CC"()J",                   (void*)&WB_GetVMLargePageSize},
1718  {CC"getHeapSpaceAlignment",            CC"()J",                   (void*)&WB_GetHeapSpaceAlignment},
1719  {CC"getHeapAlignment",                 CC"()J",                   (void*)&WB_GetHeapAlignment},
1720  {CC"isClassAlive0",                    CC"(Ljava/lang/String;)Z", (void*)&WB_IsClassAlive      },
1721  {CC"parseCommandLine0",
1722      CC"(Ljava/lang/String;C[Lsun/hotspot/parser/DiagnosticCommand;)[Ljava/lang/Object;",
1723      (void*) &WB_ParseCommandLine
1724  },
1725  {CC"addToBootstrapClassLoaderSearch0", CC"(Ljava/lang/String;)V",
1726                                                      (void*)&WB_AddToBootstrapClassLoaderSearch},
1727  {CC"addToSystemClassLoaderSearch0",    CC"(Ljava/lang/String;)V",
1728                                                      (void*)&WB_AddToSystemClassLoaderSearch},
1729  {CC"getCompressedOopsMaxHeapSize", CC"()J",
1730      (void*)&WB_GetCompressedOopsMaxHeapSize},
1731  {CC"printHeapSizes",     CC"()V",                   (void*)&WB_PrintHeapSizes    },
1732  {CC"runMemoryUnitTests", CC"()V",                   (void*)&WB_RunMemoryUnitTests},
1733  {CC"readFromNoaccessArea",CC"()V",                  (void*)&WB_ReadFromNoaccessArea},
1734  {CC"stressVirtualSpaceResize",CC"(JJJ)I",           (void*)&WB_StressVirtualSpaceResize},
1735#if INCLUDE_ALL_GCS
1736  {CC"g1InConcurrentMark", CC"()Z",                   (void*)&WB_G1InConcurrentMark},
1737  {CC"g1IsHumongous0",      CC"(Ljava/lang/Object;)Z", (void*)&WB_G1IsHumongous     },
1738  {CC"g1BelongsToHumongousRegion0", CC"(J)Z",         (void*)&WB_G1BelongsToHumongousRegion},
1739  {CC"g1BelongsToFreeRegion0", CC"(J)Z",              (void*)&WB_G1BelongsToFreeRegion},
1740  {CC"g1NumMaxRegions",    CC"()J",                   (void*)&WB_G1NumMaxRegions  },
1741  {CC"g1NumFreeRegions",   CC"()J",                   (void*)&WB_G1NumFreeRegions  },
1742  {CC"g1RegionSize",       CC"()I",                   (void*)&WB_G1RegionSize      },
1743  {CC"g1StartConcMarkCycle",       CC"()Z",           (void*)&WB_G1StartMarkCycle  },
1744  {CC"g1AuxiliaryMemoryUsage", CC"()Ljava/lang/management/MemoryUsage;",
1745                                                      (void*)&WB_G1AuxiliaryMemoryUsage  },
1746  {CC"psVirtualSpaceAlignment",CC"()J",               (void*)&WB_PSVirtualSpaceAlignment},
1747  {CC"psHeapGenerationAlignment",CC"()J",             (void*)&WB_PSHeapGenerationAlignment},
1748  {CC"g1GetMixedGCInfo",   CC"(I)[J",                 (void*)&WB_G1GetMixedGCInfo },
1749#endif // INCLUDE_ALL_GCS
1750#if INCLUDE_NMT
1751  {CC"NMTMalloc",           CC"(J)J",                 (void*)&WB_NMTMalloc          },
1752  {CC"NMTMallocWithPseudoStack", CC"(JI)J",           (void*)&WB_NMTMallocWithPseudoStack},
1753  {CC"NMTFree",             CC"(J)V",                 (void*)&WB_NMTFree            },
1754  {CC"NMTReserveMemory",    CC"(J)J",                 (void*)&WB_NMTReserveMemory   },
1755  {CC"NMTCommitMemory",     CC"(JJ)V",                (void*)&WB_NMTCommitMemory    },
1756  {CC"NMTUncommitMemory",   CC"(JJ)V",                (void*)&WB_NMTUncommitMemory  },
1757  {CC"NMTReleaseMemory",    CC"(JJ)V",                (void*)&WB_NMTReleaseMemory   },
1758  {CC"NMTChangeTrackingLevel", CC"()Z",               (void*)&WB_NMTChangeTrackingLevel},
1759  {CC"NMTGetHashSize",      CC"()I",                  (void*)&WB_NMTGetHashSize     },
1760#endif // INCLUDE_NMT
1761  {CC"deoptimizeFrames",   CC"(Z)I",                  (void*)&WB_DeoptimizeFrames  },
1762  {CC"deoptimizeAll",      CC"()V",                   (void*)&WB_DeoptimizeAll     },
1763  {CC"deoptimizeMethod0",   CC"(Ljava/lang/reflect/Executable;Z)I",
1764                                                      (void*)&WB_DeoptimizeMethod  },
1765  {CC"isMethodCompiled0",   CC"(Ljava/lang/reflect/Executable;Z)Z",
1766                                                      (void*)&WB_IsMethodCompiled  },
1767  {CC"isMethodCompilable0", CC"(Ljava/lang/reflect/Executable;IZ)Z",
1768                                                      (void*)&WB_IsMethodCompilable},
1769  {CC"isMethodQueuedForCompilation0",
1770      CC"(Ljava/lang/reflect/Executable;)Z",          (void*)&WB_IsMethodQueuedForCompilation},
1771  {CC"isIntrinsicAvailable0",
1772      CC"(Ljava/lang/reflect/Executable;Ljava/lang/reflect/Executable;I)Z",
1773                                                      (void*)&WB_IsIntrinsicAvailable},
1774  {CC"makeMethodNotCompilable0",
1775      CC"(Ljava/lang/reflect/Executable;IZ)V",        (void*)&WB_MakeMethodNotCompilable},
1776  {CC"testSetDontInlineMethod0",
1777      CC"(Ljava/lang/reflect/Executable;Z)Z",         (void*)&WB_TestSetDontInlineMethod},
1778  {CC"getMethodCompilationLevel0",
1779      CC"(Ljava/lang/reflect/Executable;Z)I",         (void*)&WB_GetMethodCompilationLevel},
1780  {CC"getMethodEntryBci0",
1781      CC"(Ljava/lang/reflect/Executable;)I",          (void*)&WB_GetMethodEntryBci},
1782  {CC"getCompileQueueSize",
1783      CC"(I)I",                                       (void*)&WB_GetCompileQueueSize},
1784  {CC"testSetForceInlineMethod0",
1785      CC"(Ljava/lang/reflect/Executable;Z)Z",         (void*)&WB_TestSetForceInlineMethod},
1786  {CC"enqueueMethodForCompilation0",
1787      CC"(Ljava/lang/reflect/Executable;II)Z",        (void*)&WB_EnqueueMethodForCompilation},
1788  {CC"enqueueInitializerForCompilation0",
1789      CC"(Ljava/lang/Class;I)Z",                      (void*)&WB_EnqueueInitializerForCompilation},
1790  {CC"clearMethodState0",
1791      CC"(Ljava/lang/reflect/Executable;)V",          (void*)&WB_ClearMethodState},
1792  {CC"lockCompilation",    CC"()V",                   (void*)&WB_LockCompilation},
1793  {CC"unlockCompilation",  CC"()V",                   (void*)&WB_UnlockCompilation},
1794  {CC"matchesMethod",
1795      CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)I",
1796                                                      (void*)&WB_MatchesMethod},
1797  {CC"matchesInline",
1798      CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)I",
1799                                                      (void*)&WB_MatchesInline},
1800  {CC"shouldPrintAssembly",
1801        CC"(Ljava/lang/reflect/Executable;I)Z",
1802                                                        (void*)&WB_ShouldPrintAssembly},
1803
1804  {CC"isConstantVMFlag",   CC"(Ljava/lang/String;)Z", (void*)&WB_IsConstantVMFlag},
1805  {CC"isLockedVMFlag",     CC"(Ljava/lang/String;)Z", (void*)&WB_IsLockedVMFlag},
1806  {CC"setBooleanVMFlag",   CC"(Ljava/lang/String;Z)V",(void*)&WB_SetBooleanVMFlag},
1807  {CC"setIntVMFlag",       CC"(Ljava/lang/String;J)V",(void*)&WB_SetIntVMFlag},
1808  {CC"setUintVMFlag",      CC"(Ljava/lang/String;J)V",(void*)&WB_SetUintVMFlag},
1809  {CC"setIntxVMFlag",      CC"(Ljava/lang/String;J)V",(void*)&WB_SetIntxVMFlag},
1810  {CC"setUintxVMFlag",     CC"(Ljava/lang/String;J)V",(void*)&WB_SetUintxVMFlag},
1811  {CC"setUint64VMFlag",    CC"(Ljava/lang/String;J)V",(void*)&WB_SetUint64VMFlag},
1812  {CC"setSizeTVMFlag",     CC"(Ljava/lang/String;J)V",(void*)&WB_SetSizeTVMFlag},
1813  {CC"setDoubleVMFlag",    CC"(Ljava/lang/String;D)V",(void*)&WB_SetDoubleVMFlag},
1814  {CC"setStringVMFlag",    CC"(Ljava/lang/String;Ljava/lang/String;)V",
1815                                                      (void*)&WB_SetStringVMFlag},
1816  {CC"getBooleanVMFlag",   CC"(Ljava/lang/String;)Ljava/lang/Boolean;",
1817                                                      (void*)&WB_GetBooleanVMFlag},
1818  {CC"getIntVMFlag",       CC"(Ljava/lang/String;)Ljava/lang/Long;",
1819                                                      (void*)&WB_GetIntVMFlag},
1820  {CC"getUintVMFlag",      CC"(Ljava/lang/String;)Ljava/lang/Long;",
1821                                                      (void*)&WB_GetUintVMFlag},
1822  {CC"getIntxVMFlag",      CC"(Ljava/lang/String;)Ljava/lang/Long;",
1823                                                      (void*)&WB_GetIntxVMFlag},
1824  {CC"getUintxVMFlag",     CC"(Ljava/lang/String;)Ljava/lang/Long;",
1825                                                      (void*)&WB_GetUintxVMFlag},
1826  {CC"getUint64VMFlag",    CC"(Ljava/lang/String;)Ljava/lang/Long;",
1827                                                      (void*)&WB_GetUint64VMFlag},
1828  {CC"getSizeTVMFlag",     CC"(Ljava/lang/String;)Ljava/lang/Long;",
1829                                                      (void*)&WB_GetSizeTVMFlag},
1830  {CC"getDoubleVMFlag",    CC"(Ljava/lang/String;)Ljava/lang/Double;",
1831                                                      (void*)&WB_GetDoubleVMFlag},
1832  {CC"getStringVMFlag",    CC"(Ljava/lang/String;)Ljava/lang/String;",
1833                                                      (void*)&WB_GetStringVMFlag},
1834  {CC"isInStringTable",    CC"(Ljava/lang/String;)Z", (void*)&WB_IsInStringTable  },
1835  {CC"fullGC",   CC"()V",                             (void*)&WB_FullGC },
1836  {CC"youngGC",  CC"()V",                             (void*)&WB_YoungGC },
1837  {CC"readReservedMemory", CC"()V",                   (void*)&WB_ReadReservedMemory },
1838  {CC"allocateMetaspace",
1839     CC"(Ljava/lang/ClassLoader;J)J",                 (void*)&WB_AllocateMetaspace },
1840  {CC"freeMetaspace",
1841     CC"(Ljava/lang/ClassLoader;JJ)V",                (void*)&WB_FreeMetaspace },
1842  {CC"incMetaspaceCapacityUntilGC", CC"(J)J",         (void*)&WB_IncMetaspaceCapacityUntilGC },
1843  {CC"metaspaceCapacityUntilGC", CC"()J",             (void*)&WB_MetaspaceCapacityUntilGC },
1844  {CC"metaspaceShouldConcurrentCollect", CC"()Z",     (void*)&WB_MetaspaceShouldConcurrentCollect },
1845  {CC"getCPUFeatures",     CC"()Ljava/lang/String;",  (void*)&WB_GetCPUFeatures     },
1846  {CC"getNMethod0",         CC"(Ljava/lang/reflect/Executable;Z)[Ljava/lang/Object;",
1847                                                      (void*)&WB_GetNMethod         },
1848  {CC"forceNMethodSweep",  CC"()V",                   (void*)&WB_ForceNMethodSweep  },
1849  {CC"allocateCodeBlob",   CC"(II)J",                 (void*)&WB_AllocateCodeBlob   },
1850  {CC"freeCodeBlob",       CC"(J)V",                  (void*)&WB_FreeCodeBlob       },
1851  {CC"getCodeHeapEntries", CC"(I)[Ljava/lang/Object;",(void*)&WB_GetCodeHeapEntries },
1852  {CC"getCompilationActivityMode",
1853                           CC"()I",                   (void*)&WB_GetCompilationActivityMode},
1854  {CC"getMethodData0",     CC"(Ljava/lang/reflect/Executable;)J",
1855                                                      (void*)&WB_GetMethodData      },
1856  {CC"getCodeBlob",        CC"(J)[Ljava/lang/Object;",(void*)&WB_GetCodeBlob        },
1857  {CC"getThreadStackSize", CC"()J",                   (void*)&WB_GetThreadStackSize },
1858  {CC"getThreadRemainingStackSize", CC"()J",          (void*)&WB_GetThreadRemainingStackSize },
1859  {CC"DefineModule",       CC"(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/Object;)V",
1860                                                      (void*)&WB_DefineModule },
1861  {CC"AddModuleExports",   CC"(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)V",
1862                                                      (void*)&WB_AddModuleExports },
1863  {CC"AddReadsModule",     CC"(Ljava/lang/Object;Ljava/lang/Object;)V",
1864                                                      (void*)&WB_AddReadsModule },
1865  {CC"AddModulePackage",   CC"(Ljava/lang/Object;Ljava/lang/String;)V",
1866                                                      (void*)&WB_AddModulePackage },
1867  {CC"GetModuleByPackageName", CC"(Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/Object;",
1868                                                      (void*)&WB_GetModuleByPackageName },
1869  {CC"AddModuleExportsToAllUnnamed", CC"(Ljava/lang/Object;Ljava/lang/String;)V",
1870                                                      (void*)&WB_AddModuleExportsToAllUnnamed },
1871  {CC"AddModuleExportsToAll", CC"(Ljava/lang/Object;Ljava/lang/String;)V",
1872                                                      (void*)&WB_AddModuleExportsToAll },
1873  {CC"assertMatchingSafepointCalls", CC"(ZZ)V",       (void*)&WB_AssertMatchingSafepointCalls },
1874  {CC"isMonitorInflated0", CC"(Ljava/lang/Object;)Z", (void*)&WB_IsMonitorInflated  },
1875  {CC"forceSafepoint",     CC"()V",                   (void*)&WB_ForceSafepoint     },
1876  {CC"getConstantPool0",   CC"(Ljava/lang/Class;)J",  (void*)&WB_GetConstantPool    },
1877  {CC"getConstantPoolCacheIndexTag0", CC"()I",  (void*)&WB_GetConstantPoolCacheIndexTag},
1878  {CC"getConstantPoolCacheLength0", CC"(Ljava/lang/Class;)I",  (void*)&WB_GetConstantPoolCacheLength},
1879  {CC"remapInstructionOperandFromCPCache0",
1880      CC"(Ljava/lang/Class;I)I",                      (void*)&WB_ConstantPoolRemapInstructionOperandFromCache},
1881  {CC"encodeConstantPoolIndyIndex0",
1882      CC"(I)I",                      (void*)&WB_ConstantPoolEncodeIndyIndex},
1883  {CC"getMethodBooleanOption",
1884      CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)Ljava/lang/Boolean;",
1885                                                      (void*)&WB_GetMethodBooleaneOption},
1886  {CC"getMethodIntxOption",
1887      CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)Ljava/lang/Long;",
1888                                                      (void*)&WB_GetMethodIntxOption},
1889  {CC"getMethodUintxOption",
1890      CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)Ljava/lang/Long;",
1891                                                      (void*)&WB_GetMethodUintxOption},
1892  {CC"getMethodDoubleOption",
1893      CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)Ljava/lang/Double;",
1894                                                      (void*)&WB_GetMethodDoubleOption},
1895  {CC"getMethodStringOption",
1896      CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)Ljava/lang/String;",
1897                                                      (void*)&WB_GetMethodStringOption},
1898  {CC"isShared",           CC"(Ljava/lang/Object;)Z", (void*)&WB_IsShared },
1899  {CC"isSharedClass",      CC"(Ljava/lang/Class;)Z",  (void*)&WB_IsSharedClass },
1900  {CC"areSharedStringsIgnored",           CC"()Z",    (void*)&WB_AreSharedStringsIgnored },
1901  {CC"clearInlineCaches0",  CC"(Z)V",                 (void*)&WB_ClearInlineCaches },
1902  {CC"addCompilerDirective",    CC"(Ljava/lang/String;)I",
1903                                                      (void*)&WB_AddCompilerDirective },
1904  {CC"removeCompilerDirective",   CC"(I)V",             (void*)&WB_RemoveCompilerDirective },
1905  {CC"currentGC",                 CC"()I",            (void*)&WB_CurrentGC},
1906  {CC"allSupportedGC",            CC"()I",            (void*)&WB_AllSupportedGC},
1907  {CC"gcSelectedByErgo",          CC"()Z",            (void*)&WB_GCSelectedByErgo},
1908};
1909
1910#undef CC
1911
1912JVM_ENTRY(void, JVM_RegisterWhiteBoxMethods(JNIEnv* env, jclass wbclass))
1913  {
1914    if (WhiteBoxAPI) {
1915      // Make sure that wbclass is loaded by the null classloader
1916      instanceKlassHandle ikh = instanceKlassHandle(JNIHandles::resolve(wbclass)->klass());
1917      Handle loader(ikh->class_loader());
1918      if (loader.is_null()) {
1919        WhiteBox::register_methods(env, wbclass, thread, methods, sizeof(methods) / sizeof(methods[0]));
1920        WhiteBox::register_extended(env, wbclass, thread);
1921        WhiteBox::set_used();
1922      }
1923    }
1924  }
1925JVM_END
1926