whitebox.cpp revision 12290:8953c0318163
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  return CodeCache::get_code_heap(code)->code_blob_type();
1176}
1177
1178CodeHeap* WhiteBox::get_code_heap(int blob_type) {
1179  guarantee(WhiteBoxAPI, "internal testing API :: WhiteBox has to be enabled");
1180  return CodeCache::get_code_heap(blob_type);
1181}
1182
1183struct CodeBlobStub {
1184  CodeBlobStub(const CodeBlob* blob) :
1185      name(os::strdup(blob->name())),
1186      size(blob->size()),
1187      blob_type(WhiteBox::get_blob_type(blob)),
1188      address((jlong) blob) { }
1189  ~CodeBlobStub() { os::free((void*) name); }
1190  const char* const name;
1191  const jint        size;
1192  const jint        blob_type;
1193  const jlong       address;
1194};
1195
1196static jobjectArray codeBlob2objectArray(JavaThread* thread, JNIEnv* env, CodeBlobStub* cb) {
1197  jclass clazz = env->FindClass(vmSymbols::java_lang_Object()->as_C_string());
1198  CHECK_JNI_EXCEPTION_(env, NULL);
1199  jobjectArray result = env->NewObjectArray(4, clazz, NULL);
1200
1201  jstring name = env->NewStringUTF(cb->name);
1202  CHECK_JNI_EXCEPTION_(env, NULL);
1203  env->SetObjectArrayElement(result, 0, name);
1204
1205  jobject obj = integerBox(thread, env, cb->size);
1206  CHECK_JNI_EXCEPTION_(env, NULL);
1207  env->SetObjectArrayElement(result, 1, obj);
1208
1209  obj = integerBox(thread, env, cb->blob_type);
1210  CHECK_JNI_EXCEPTION_(env, NULL);
1211  env->SetObjectArrayElement(result, 2, obj);
1212
1213  obj = longBox(thread, env, cb->address);
1214  CHECK_JNI_EXCEPTION_(env, NULL);
1215  env->SetObjectArrayElement(result, 3, obj);
1216
1217  return result;
1218}
1219
1220WB_ENTRY(jobjectArray, WB_GetNMethod(JNIEnv* env, jobject o, jobject method, jboolean is_osr))
1221  ResourceMark rm(THREAD);
1222  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
1223  CHECK_JNI_EXCEPTION_(env, NULL);
1224  methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
1225  CompiledMethod* code = is_osr ? mh->lookup_osr_nmethod_for(InvocationEntryBci, CompLevel_none, false) : mh->code();
1226  jobjectArray result = NULL;
1227  if (code == NULL) {
1228    return result;
1229  }
1230  int insts_size = code->insts_size();
1231
1232  ThreadToNativeFromVM ttn(thread);
1233  jclass clazz = env->FindClass(vmSymbols::java_lang_Object()->as_C_string());
1234  CHECK_JNI_EXCEPTION_(env, NULL);
1235  result = env->NewObjectArray(5, clazz, NULL);
1236  if (result == NULL) {
1237    return result;
1238  }
1239
1240  CodeBlobStub stub(code);
1241  jobjectArray codeBlob = codeBlob2objectArray(thread, env, &stub);
1242  CHECK_JNI_EXCEPTION_(env, NULL);
1243  env->SetObjectArrayElement(result, 0, codeBlob);
1244
1245  jobject level = integerBox(thread, env, code->comp_level());
1246  CHECK_JNI_EXCEPTION_(env, NULL);
1247  env->SetObjectArrayElement(result, 1, level);
1248
1249  jbyteArray insts = env->NewByteArray(insts_size);
1250  CHECK_JNI_EXCEPTION_(env, NULL);
1251  env->SetByteArrayRegion(insts, 0, insts_size, (jbyte*) code->insts_begin());
1252  env->SetObjectArrayElement(result, 2, insts);
1253
1254  jobject id = integerBox(thread, env, code->compile_id());
1255  CHECK_JNI_EXCEPTION_(env, NULL);
1256  env->SetObjectArrayElement(result, 3, id);
1257
1258  jobject entry_point = longBox(thread, env, (jlong) code->entry_point());
1259  CHECK_JNI_EXCEPTION_(env, NULL);
1260  env->SetObjectArrayElement(result, 4, entry_point);
1261
1262  return result;
1263WB_END
1264
1265CodeBlob* WhiteBox::allocate_code_blob(int size, int blob_type) {
1266  guarantee(WhiteBoxAPI, "internal testing API :: WhiteBox has to be enabled");
1267  BufferBlob* blob;
1268  int full_size = CodeBlob::align_code_offset(sizeof(BufferBlob));
1269  if (full_size < size) {
1270    full_size += round_to(size - full_size, oopSize);
1271  }
1272  {
1273    MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
1274    blob = (BufferBlob*) CodeCache::allocate(full_size, blob_type);
1275    ::new (blob) BufferBlob("WB::DummyBlob", full_size);
1276  }
1277  // Track memory usage statistic after releasing CodeCache_lock
1278  MemoryService::track_code_cache_memory_usage();
1279  return blob;
1280}
1281
1282WB_ENTRY(jlong, WB_AllocateCodeBlob(JNIEnv* env, jobject o, jint size, jint blob_type))
1283  if (size < 0) {
1284    THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
1285      err_msg("WB_AllocateCodeBlob: size is negative: " INT32_FORMAT, size));
1286  }
1287  return (jlong) WhiteBox::allocate_code_blob(size, blob_type);
1288WB_END
1289
1290WB_ENTRY(void, WB_FreeCodeBlob(JNIEnv* env, jobject o, jlong addr))
1291  if (addr == 0) {
1292    return;
1293  }
1294  BufferBlob::free((BufferBlob*) addr);
1295WB_END
1296
1297WB_ENTRY(jobjectArray, WB_GetCodeHeapEntries(JNIEnv* env, jobject o, jint blob_type))
1298  ResourceMark rm;
1299  GrowableArray<CodeBlobStub*> blobs;
1300  {
1301    MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
1302    CodeHeap* heap = WhiteBox::get_code_heap(blob_type);
1303    if (heap == NULL) {
1304      return NULL;
1305    }
1306    for (CodeBlob* cb = (CodeBlob*) heap->first();
1307         cb != NULL; cb = (CodeBlob*) heap->next(cb)) {
1308      CodeBlobStub* stub = NEW_RESOURCE_OBJ(CodeBlobStub);
1309      new (stub) CodeBlobStub(cb);
1310      blobs.append(stub);
1311    }
1312  }
1313  if (blobs.length() == 0) {
1314    return NULL;
1315  }
1316  ThreadToNativeFromVM ttn(thread);
1317  jobjectArray result = NULL;
1318  jclass clazz = env->FindClass(vmSymbols::java_lang_Object()->as_C_string());
1319  CHECK_JNI_EXCEPTION_(env, NULL);
1320  result = env->NewObjectArray(blobs.length(), clazz, NULL);
1321  CHECK_JNI_EXCEPTION_(env, NULL);
1322  if (result == NULL) {
1323    return result;
1324  }
1325  int i = 0;
1326  for (GrowableArrayIterator<CodeBlobStub*> it = blobs.begin();
1327       it != blobs.end(); ++it) {
1328    jobjectArray obj = codeBlob2objectArray(thread, env, *it);
1329    CHECK_JNI_EXCEPTION_(env, NULL);
1330    env->SetObjectArrayElement(result, i, obj);
1331    CHECK_JNI_EXCEPTION_(env, NULL);
1332    ++i;
1333  }
1334  return result;
1335WB_END
1336
1337WB_ENTRY(jint, WB_GetCompilationActivityMode(JNIEnv* env, jobject o))
1338  return CompileBroker::get_compilation_activity_mode();
1339WB_END
1340
1341WB_ENTRY(jobjectArray, WB_GetCodeBlob(JNIEnv* env, jobject o, jlong addr))
1342  if (addr == 0) {
1343    THROW_MSG_NULL(vmSymbols::java_lang_NullPointerException(),
1344      "WB_GetCodeBlob: addr is null");
1345  }
1346  ThreadToNativeFromVM ttn(thread);
1347  CodeBlobStub stub((CodeBlob*) addr);
1348  return codeBlob2objectArray(thread, env, &stub);
1349WB_END
1350
1351WB_ENTRY(jlong, WB_GetMethodData(JNIEnv* env, jobject wv, jobject method))
1352  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
1353  CHECK_JNI_EXCEPTION_(env, 0);
1354  methodHandle mh(thread, Method::checked_resolve_jmethod_id(jmid));
1355  return (jlong) mh->method_data();
1356WB_END
1357
1358WB_ENTRY(jlong, WB_GetThreadStackSize(JNIEnv* env, jobject o))
1359  return (jlong) Thread::current()->stack_size();
1360WB_END
1361
1362WB_ENTRY(jlong, WB_GetThreadRemainingStackSize(JNIEnv* env, jobject o))
1363  JavaThread* t = JavaThread::current();
1364  return (jlong) t->stack_available(os::current_stack_pointer()) - (jlong)JavaThread::stack_shadow_zone_size();
1365WB_END
1366
1367
1368int WhiteBox::array_bytes_to_length(size_t bytes) {
1369  return Array<u1>::bytes_to_length(bytes);
1370}
1371
1372WB_ENTRY(jlong, WB_AllocateMetaspace(JNIEnv* env, jobject wb, jobject class_loader, jlong size))
1373  if (size < 0) {
1374    THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
1375        err_msg("WB_AllocateMetaspace: size is negative: " JLONG_FORMAT, size));
1376  }
1377
1378  oop class_loader_oop = JNIHandles::resolve(class_loader);
1379  ClassLoaderData* cld = class_loader_oop != NULL
1380      ? java_lang_ClassLoader::loader_data(class_loader_oop)
1381      : ClassLoaderData::the_null_class_loader_data();
1382
1383  void* metadata = MetadataFactory::new_writeable_array<u1>(cld, WhiteBox::array_bytes_to_length((size_t)size), thread);
1384
1385  return (jlong)(uintptr_t)metadata;
1386WB_END
1387
1388WB_ENTRY(void, WB_FreeMetaspace(JNIEnv* env, jobject wb, jobject class_loader, jlong addr, jlong size))
1389  oop class_loader_oop = JNIHandles::resolve(class_loader);
1390  ClassLoaderData* cld = class_loader_oop != NULL
1391      ? java_lang_ClassLoader::loader_data(class_loader_oop)
1392      : ClassLoaderData::the_null_class_loader_data();
1393
1394  MetadataFactory::free_array(cld, (Array<u1>*)(uintptr_t)addr);
1395WB_END
1396
1397WB_ENTRY(void, WB_DefineModule(JNIEnv* env, jobject o, jobject module, jstring version, jstring location,
1398                                jobjectArray packages))
1399  Modules::define_module(module, version, location, packages, CHECK);
1400WB_END
1401
1402WB_ENTRY(void, WB_AddModuleExports(JNIEnv* env, jobject o, jobject from_module, jstring package, jobject to_module))
1403  Modules::add_module_exports_qualified(from_module, package, to_module, CHECK);
1404WB_END
1405
1406WB_ENTRY(void, WB_AddModuleExportsToAllUnnamed(JNIEnv* env, jobject o, jclass module, jstring package))
1407  Modules::add_module_exports_to_all_unnamed(module, package, CHECK);
1408WB_END
1409
1410WB_ENTRY(void, WB_AddModuleExportsToAll(JNIEnv* env, jobject o, jclass module, jstring package))
1411  Modules::add_module_exports(module, package, NULL, CHECK);
1412WB_END
1413
1414WB_ENTRY(void, WB_AddReadsModule(JNIEnv* env, jobject o, jobject from_module, jobject source_module))
1415  Modules::add_reads_module(from_module, source_module, CHECK);
1416WB_END
1417
1418WB_ENTRY(void, WB_AddModulePackage(JNIEnv* env, jobject o, jclass module, jstring package))
1419  Modules::add_module_package(module, package, CHECK);
1420WB_END
1421
1422WB_ENTRY(jobject, WB_GetModuleByPackageName(JNIEnv* env, jobject o, jobject loader, jstring package))
1423  return Modules::get_module_by_package_name(loader, package, THREAD);
1424WB_END
1425
1426WB_ENTRY(jlong, WB_IncMetaspaceCapacityUntilGC(JNIEnv* env, jobject wb, jlong inc))
1427  if (inc < 0) {
1428    THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
1429        err_msg("WB_IncMetaspaceCapacityUntilGC: inc is negative: " JLONG_FORMAT, inc));
1430  }
1431
1432  jlong max_size_t = (jlong) ((size_t) -1);
1433  if (inc > max_size_t) {
1434    THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
1435        err_msg("WB_IncMetaspaceCapacityUntilGC: inc does not fit in size_t: " JLONG_FORMAT, inc));
1436  }
1437
1438  size_t new_cap_until_GC = 0;
1439  size_t aligned_inc = align_size_down((size_t) inc, Metaspace::commit_alignment());
1440  bool success = MetaspaceGC::inc_capacity_until_GC(aligned_inc, &new_cap_until_GC);
1441  if (!success) {
1442    THROW_MSG_0(vmSymbols::java_lang_IllegalStateException(),
1443                "WB_IncMetaspaceCapacityUntilGC: could not increase capacity until GC "
1444                "due to contention with another thread");
1445  }
1446  return (jlong) new_cap_until_GC;
1447WB_END
1448
1449WB_ENTRY(jlong, WB_MetaspaceCapacityUntilGC(JNIEnv* env, jobject wb))
1450  return (jlong) MetaspaceGC::capacity_until_GC();
1451WB_END
1452
1453WB_ENTRY(jboolean, WB_MetaspaceShouldConcurrentCollect(JNIEnv* env, jobject wb))
1454  return MetaspaceGC::should_concurrent_collect();
1455WB_END
1456
1457
1458WB_ENTRY(void, WB_AssertMatchingSafepointCalls(JNIEnv* env, jobject o, jboolean mutexSafepointValue, jboolean attemptedNoSafepointValue))
1459  Monitor::SafepointCheckRequired sfpt_check_required = mutexSafepointValue ?
1460                                           Monitor::_safepoint_check_always :
1461                                           Monitor::_safepoint_check_never;
1462  MutexLockerEx ml(new Mutex(Mutex::leaf, "SFPT_Test_lock", true, sfpt_check_required),
1463                   attemptedNoSafepointValue == JNI_TRUE);
1464WB_END
1465
1466WB_ENTRY(jboolean, WB_IsMonitorInflated(JNIEnv* env, jobject wb, jobject obj))
1467  oop obj_oop = JNIHandles::resolve(obj);
1468  return (jboolean) obj_oop->mark()->has_monitor();
1469WB_END
1470
1471WB_ENTRY(void, WB_ForceSafepoint(JNIEnv* env, jobject wb))
1472  VM_ForceSafepoint force_safepoint_op;
1473  VMThread::execute(&force_safepoint_op);
1474WB_END
1475
1476WB_ENTRY(jlong, WB_GetConstantPool(JNIEnv* env, jobject wb, jclass klass))
1477  instanceKlassHandle ikh(java_lang_Class::as_Klass(JNIHandles::resolve(klass)));
1478  return (jlong) ikh->constants();
1479WB_END
1480
1481WB_ENTRY(jint, WB_GetConstantPoolCacheIndexTag(JNIEnv* env, jobject wb))
1482  return ConstantPool::CPCACHE_INDEX_TAG;
1483WB_END
1484
1485WB_ENTRY(jint, WB_GetConstantPoolCacheLength(JNIEnv* env, jobject wb, jclass klass))
1486  instanceKlassHandle ikh(java_lang_Class::as_Klass(JNIHandles::resolve(klass)));
1487  ConstantPool* cp = ikh->constants();
1488  if (cp->cache() == NULL) {
1489      return -1;
1490  }
1491  return cp->cache()->length();
1492WB_END
1493
1494WB_ENTRY(jint, WB_ConstantPoolRemapInstructionOperandFromCache(JNIEnv* env, jobject wb, jclass klass, jint index))
1495  instanceKlassHandle ikh(java_lang_Class::as_Klass(JNIHandles::resolve(klass)));
1496  ConstantPool* cp = ikh->constants();
1497  if (cp->cache() == NULL) {
1498    THROW_MSG_0(vmSymbols::java_lang_IllegalStateException(), "Constant pool does not have a cache");
1499  }
1500  jint cpci = index;
1501  jint cpciTag = ConstantPool::CPCACHE_INDEX_TAG;
1502  if (cpciTag > cpci || cpci >= cp->cache()->length() + cpciTag) {
1503    THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Constant pool cache index is out of range");
1504  }
1505  jint cpi = cp->remap_instruction_operand_from_cache(cpci);
1506  return cpi;
1507WB_END
1508
1509WB_ENTRY(jint, WB_ConstantPoolEncodeIndyIndex(JNIEnv* env, jobject wb, jint index))
1510  return ConstantPool::encode_invokedynamic_index(index);
1511WB_END
1512
1513WB_ENTRY(void, WB_ClearInlineCaches(JNIEnv* env, jobject wb, jboolean preserve_static_stubs))
1514  VM_ClearICs clear_ics(preserve_static_stubs == JNI_TRUE);
1515  VMThread::execute(&clear_ics);
1516WB_END
1517
1518template <typename T>
1519static bool GetMethodOption(JavaThread* thread, JNIEnv* env, jobject method, jstring name, T* value) {
1520  assert(value != NULL, "sanity");
1521  if (method == NULL || name == NULL) {
1522    return false;
1523  }
1524  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
1525  CHECK_JNI_EXCEPTION_(env, false);
1526  methodHandle mh(thread, Method::checked_resolve_jmethod_id(jmid));
1527  // can't be in VM when we call JNI
1528  ThreadToNativeFromVM ttnfv(thread);
1529  const char* flag_name = env->GetStringUTFChars(name, NULL);
1530  CHECK_JNI_EXCEPTION_(env, false);
1531  bool result =  CompilerOracle::has_option_value(mh, flag_name, *value);
1532  env->ReleaseStringUTFChars(name, flag_name);
1533  return result;
1534}
1535
1536WB_ENTRY(jobject, WB_GetMethodBooleaneOption(JNIEnv* env, jobject wb, jobject method, jstring name))
1537  bool result;
1538  if (GetMethodOption<bool> (thread, env, method, name, &result)) {
1539    // can't be in VM when we call JNI
1540    ThreadToNativeFromVM ttnfv(thread);
1541    return booleanBox(thread, env, result);
1542  }
1543  return NULL;
1544WB_END
1545
1546WB_ENTRY(jobject, WB_GetMethodIntxOption(JNIEnv* env, jobject wb, jobject method, jstring name))
1547  intx result;
1548  if (GetMethodOption <intx> (thread, env, method, name, &result)) {
1549    // can't be in VM when we call JNI
1550    ThreadToNativeFromVM ttnfv(thread);
1551    return longBox(thread, env, result);
1552  }
1553  return NULL;
1554WB_END
1555
1556WB_ENTRY(jobject, WB_GetMethodUintxOption(JNIEnv* env, jobject wb, jobject method, jstring name))
1557  uintx result;
1558  if (GetMethodOption <uintx> (thread, env, method, name, &result)) {
1559    // can't be in VM when we call JNI
1560    ThreadToNativeFromVM ttnfv(thread);
1561    return longBox(thread, env, result);
1562  }
1563  return NULL;
1564WB_END
1565
1566WB_ENTRY(jobject, WB_GetMethodDoubleOption(JNIEnv* env, jobject wb, jobject method, jstring name))
1567  double result;
1568  if (GetMethodOption <double> (thread, env, method, name, &result)) {
1569    // can't be in VM when we call JNI
1570    ThreadToNativeFromVM ttnfv(thread);
1571    return doubleBox(thread, env, result);
1572  }
1573  return NULL;
1574WB_END
1575
1576WB_ENTRY(jobject, WB_GetMethodStringOption(JNIEnv* env, jobject wb, jobject method, jstring name))
1577  ccstr ccstrResult;
1578  if (GetMethodOption <ccstr> (thread, env, method, name, &ccstrResult)) {
1579    // can't be in VM when we call JNI
1580    ThreadToNativeFromVM ttnfv(thread);
1581    jstring result = env->NewStringUTF(ccstrResult);
1582    CHECK_JNI_EXCEPTION_(env, NULL);
1583    return result;
1584  }
1585  return NULL;
1586WB_END
1587
1588WB_ENTRY(jboolean, WB_IsShared(JNIEnv* env, jobject wb, jobject obj))
1589  oop obj_oop = JNIHandles::resolve(obj);
1590  return MetaspaceShared::is_in_shared_space((void*)obj_oop);
1591WB_END
1592
1593WB_ENTRY(jboolean, WB_IsSharedClass(JNIEnv* env, jobject wb, jclass clazz))
1594  return (jboolean)MetaspaceShared::is_in_shared_space(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz)));
1595WB_END
1596
1597WB_ENTRY(jboolean, WB_AreSharedStringsIgnored(JNIEnv* env))
1598  return StringTable::shared_string_ignored();
1599WB_END
1600
1601//Some convenience methods to deal with objects from java
1602int WhiteBox::offset_for_field(const char* field_name, oop object,
1603    Symbol* signature_symbol) {
1604  assert(field_name != NULL && strlen(field_name) > 0, "Field name not valid");
1605  Thread* THREAD = Thread::current();
1606
1607  //Get the class of our object
1608  Klass* arg_klass = object->klass();
1609  //Turn it into an instance-klass
1610  InstanceKlass* ik = InstanceKlass::cast(arg_klass);
1611
1612  //Create symbols to look for in the class
1613  TempNewSymbol name_symbol = SymbolTable::lookup(field_name, (int) strlen(field_name),
1614      THREAD);
1615
1616  //To be filled in with an offset of the field we're looking for
1617  fieldDescriptor fd;
1618
1619  Klass* res = ik->find_field(name_symbol, signature_symbol, &fd);
1620  if (res == NULL) {
1621    tty->print_cr("Invalid layout of %s at %s", ik->external_name(),
1622        name_symbol->as_C_string());
1623    vm_exit_during_initialization("Invalid layout of preloaded class: use -Xlog:class+load=info to see the origin of the problem class");
1624  }
1625
1626  //fetch the field at the offset we've found
1627  int dest_offset = fd.offset();
1628
1629  return dest_offset;
1630}
1631
1632
1633const char* WhiteBox::lookup_jstring(const char* field_name, oop object) {
1634  int offset = offset_for_field(field_name, object,
1635      vmSymbols::string_signature());
1636  oop string = object->obj_field(offset);
1637  if (string == NULL) {
1638    return NULL;
1639  }
1640  const char* ret = java_lang_String::as_utf8_string(string);
1641  return ret;
1642}
1643
1644bool WhiteBox::lookup_bool(const char* field_name, oop object) {
1645  int offset =
1646      offset_for_field(field_name, object, vmSymbols::bool_signature());
1647  bool ret = (object->bool_field(offset) == JNI_TRUE);
1648  return ret;
1649}
1650
1651void WhiteBox::register_methods(JNIEnv* env, jclass wbclass, JavaThread* thread, JNINativeMethod* method_array, int method_count) {
1652  ResourceMark rm;
1653  ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
1654
1655  //  one by one registration natives for exception catching
1656  jclass no_such_method_error_klass = env->FindClass(vmSymbols::java_lang_NoSuchMethodError()->as_C_string());
1657  CHECK_JNI_EXCEPTION(env);
1658  for (int i = 0, n = method_count; i < n; ++i) {
1659    // Skip dummy entries
1660    if (method_array[i].fnPtr == NULL) continue;
1661    if (env->RegisterNatives(wbclass, &method_array[i], 1) != 0) {
1662      jthrowable throwable_obj = env->ExceptionOccurred();
1663      if (throwable_obj != NULL) {
1664        env->ExceptionClear();
1665        if (env->IsInstanceOf(throwable_obj, no_such_method_error_klass)) {
1666          // NoSuchMethodError is thrown when a method can't be found or a method is not native.
1667          // Ignoring the exception since it is not preventing use of other WhiteBox methods.
1668          tty->print_cr("Warning: 'NoSuchMethodError' on register of sun.hotspot.WhiteBox::%s%s",
1669              method_array[i].name, method_array[i].signature);
1670        }
1671      } else {
1672        // Registration failed unexpectedly.
1673        tty->print_cr("Warning: unexpected error on register of sun.hotspot.WhiteBox::%s%s. All methods will be unregistered",
1674            method_array[i].name, method_array[i].signature);
1675        env->UnregisterNatives(wbclass);
1676        break;
1677      }
1678    }
1679  }
1680}
1681
1682WB_ENTRY(jint, WB_AddCompilerDirective(JNIEnv* env, jobject o, jstring compDirect))
1683  // can't be in VM when we call JNI
1684  ThreadToNativeFromVM ttnfv(thread);
1685  const char* dir = env->GetStringUTFChars(compDirect, NULL);
1686  CHECK_JNI_EXCEPTION_(env, 0);
1687  int ret;
1688  {
1689    ThreadInVMfromNative ttvfn(thread); // back to VM
1690    ret = DirectivesParser::parse_string(dir, tty);
1691  }
1692  env->ReleaseStringUTFChars(compDirect, dir);
1693  // -1 for error parsing directive. Return 0 as number of directives added.
1694  if (ret == -1) {
1695    ret = 0;
1696  }
1697  return (jint) ret;
1698WB_END
1699
1700WB_ENTRY(void, WB_RemoveCompilerDirective(JNIEnv* env, jobject o, jint count))
1701  DirectivesStack::pop(count);
1702WB_END
1703
1704#define CC (char*)
1705
1706static JNINativeMethod methods[] = {
1707  {CC"getObjectAddress0",                CC"(Ljava/lang/Object;)J", (void*)&WB_GetObjectAddress  },
1708  {CC"getObjectSize0",                   CC"(Ljava/lang/Object;)J", (void*)&WB_GetObjectSize     },
1709  {CC"isObjectInOldGen0",                CC"(Ljava/lang/Object;)Z", (void*)&WB_isObjectInOldGen  },
1710  {CC"getHeapOopSize",                   CC"()I",                   (void*)&WB_GetHeapOopSize    },
1711  {CC"getVMPageSize",                    CC"()I",                   (void*)&WB_GetVMPageSize     },
1712  {CC"getVMAllocationGranularity",       CC"()J",                   (void*)&WB_GetVMAllocationGranularity },
1713  {CC"getVMLargePageSize",               CC"()J",                   (void*)&WB_GetVMLargePageSize},
1714  {CC"getHeapSpaceAlignment",            CC"()J",                   (void*)&WB_GetHeapSpaceAlignment},
1715  {CC"getHeapAlignment",                 CC"()J",                   (void*)&WB_GetHeapAlignment},
1716  {CC"isClassAlive0",                    CC"(Ljava/lang/String;)Z", (void*)&WB_IsClassAlive      },
1717  {CC"parseCommandLine0",
1718      CC"(Ljava/lang/String;C[Lsun/hotspot/parser/DiagnosticCommand;)[Ljava/lang/Object;",
1719      (void*) &WB_ParseCommandLine
1720  },
1721  {CC"addToBootstrapClassLoaderSearch0", CC"(Ljava/lang/String;)V",
1722                                                      (void*)&WB_AddToBootstrapClassLoaderSearch},
1723  {CC"addToSystemClassLoaderSearch0",    CC"(Ljava/lang/String;)V",
1724                                                      (void*)&WB_AddToSystemClassLoaderSearch},
1725  {CC"getCompressedOopsMaxHeapSize", CC"()J",
1726      (void*)&WB_GetCompressedOopsMaxHeapSize},
1727  {CC"printHeapSizes",     CC"()V",                   (void*)&WB_PrintHeapSizes    },
1728  {CC"runMemoryUnitTests", CC"()V",                   (void*)&WB_RunMemoryUnitTests},
1729  {CC"readFromNoaccessArea",CC"()V",                  (void*)&WB_ReadFromNoaccessArea},
1730  {CC"stressVirtualSpaceResize",CC"(JJJ)I",           (void*)&WB_StressVirtualSpaceResize},
1731#if INCLUDE_ALL_GCS
1732  {CC"g1InConcurrentMark", CC"()Z",                   (void*)&WB_G1InConcurrentMark},
1733  {CC"g1IsHumongous0",      CC"(Ljava/lang/Object;)Z", (void*)&WB_G1IsHumongous     },
1734  {CC"g1BelongsToHumongousRegion0", CC"(J)Z",         (void*)&WB_G1BelongsToHumongousRegion},
1735  {CC"g1BelongsToFreeRegion0", CC"(J)Z",              (void*)&WB_G1BelongsToFreeRegion},
1736  {CC"g1NumMaxRegions",    CC"()J",                   (void*)&WB_G1NumMaxRegions  },
1737  {CC"g1NumFreeRegions",   CC"()J",                   (void*)&WB_G1NumFreeRegions  },
1738  {CC"g1RegionSize",       CC"()I",                   (void*)&WB_G1RegionSize      },
1739  {CC"g1StartConcMarkCycle",       CC"()Z",           (void*)&WB_G1StartMarkCycle  },
1740  {CC"g1AuxiliaryMemoryUsage", CC"()Ljava/lang/management/MemoryUsage;",
1741                                                      (void*)&WB_G1AuxiliaryMemoryUsage  },
1742  {CC"psVirtualSpaceAlignment",CC"()J",               (void*)&WB_PSVirtualSpaceAlignment},
1743  {CC"psHeapGenerationAlignment",CC"()J",             (void*)&WB_PSHeapGenerationAlignment},
1744  {CC"g1GetMixedGCInfo",   CC"(I)[J",                 (void*)&WB_G1GetMixedGCInfo },
1745#endif // INCLUDE_ALL_GCS
1746#if INCLUDE_NMT
1747  {CC"NMTMalloc",           CC"(J)J",                 (void*)&WB_NMTMalloc          },
1748  {CC"NMTMallocWithPseudoStack", CC"(JI)J",           (void*)&WB_NMTMallocWithPseudoStack},
1749  {CC"NMTFree",             CC"(J)V",                 (void*)&WB_NMTFree            },
1750  {CC"NMTReserveMemory",    CC"(J)J",                 (void*)&WB_NMTReserveMemory   },
1751  {CC"NMTCommitMemory",     CC"(JJ)V",                (void*)&WB_NMTCommitMemory    },
1752  {CC"NMTUncommitMemory",   CC"(JJ)V",                (void*)&WB_NMTUncommitMemory  },
1753  {CC"NMTReleaseMemory",    CC"(JJ)V",                (void*)&WB_NMTReleaseMemory   },
1754  {CC"NMTChangeTrackingLevel", CC"()Z",               (void*)&WB_NMTChangeTrackingLevel},
1755  {CC"NMTGetHashSize",      CC"()I",                  (void*)&WB_NMTGetHashSize     },
1756#endif // INCLUDE_NMT
1757  {CC"deoptimizeFrames",   CC"(Z)I",                  (void*)&WB_DeoptimizeFrames  },
1758  {CC"deoptimizeAll",      CC"()V",                   (void*)&WB_DeoptimizeAll     },
1759  {CC"deoptimizeMethod0",   CC"(Ljava/lang/reflect/Executable;Z)I",
1760                                                      (void*)&WB_DeoptimizeMethod  },
1761  {CC"isMethodCompiled0",   CC"(Ljava/lang/reflect/Executable;Z)Z",
1762                                                      (void*)&WB_IsMethodCompiled  },
1763  {CC"isMethodCompilable0", CC"(Ljava/lang/reflect/Executable;IZ)Z",
1764                                                      (void*)&WB_IsMethodCompilable},
1765  {CC"isMethodQueuedForCompilation0",
1766      CC"(Ljava/lang/reflect/Executable;)Z",          (void*)&WB_IsMethodQueuedForCompilation},
1767  {CC"isIntrinsicAvailable0",
1768      CC"(Ljava/lang/reflect/Executable;Ljava/lang/reflect/Executable;I)Z",
1769                                                      (void*)&WB_IsIntrinsicAvailable},
1770  {CC"makeMethodNotCompilable0",
1771      CC"(Ljava/lang/reflect/Executable;IZ)V",        (void*)&WB_MakeMethodNotCompilable},
1772  {CC"testSetDontInlineMethod0",
1773      CC"(Ljava/lang/reflect/Executable;Z)Z",         (void*)&WB_TestSetDontInlineMethod},
1774  {CC"getMethodCompilationLevel0",
1775      CC"(Ljava/lang/reflect/Executable;Z)I",         (void*)&WB_GetMethodCompilationLevel},
1776  {CC"getMethodEntryBci0",
1777      CC"(Ljava/lang/reflect/Executable;)I",          (void*)&WB_GetMethodEntryBci},
1778  {CC"getCompileQueueSize",
1779      CC"(I)I",                                       (void*)&WB_GetCompileQueueSize},
1780  {CC"testSetForceInlineMethod0",
1781      CC"(Ljava/lang/reflect/Executable;Z)Z",         (void*)&WB_TestSetForceInlineMethod},
1782  {CC"enqueueMethodForCompilation0",
1783      CC"(Ljava/lang/reflect/Executable;II)Z",        (void*)&WB_EnqueueMethodForCompilation},
1784  {CC"enqueueInitializerForCompilation0",
1785      CC"(Ljava/lang/Class;I)Z",                      (void*)&WB_EnqueueInitializerForCompilation},
1786  {CC"clearMethodState0",
1787      CC"(Ljava/lang/reflect/Executable;)V",          (void*)&WB_ClearMethodState},
1788  {CC"lockCompilation",    CC"()V",                   (void*)&WB_LockCompilation},
1789  {CC"unlockCompilation",  CC"()V",                   (void*)&WB_UnlockCompilation},
1790  {CC"matchesMethod",
1791      CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)I",
1792                                                      (void*)&WB_MatchesMethod},
1793  {CC"matchesInline",
1794      CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)I",
1795                                                      (void*)&WB_MatchesInline},
1796  {CC"shouldPrintAssembly",
1797        CC"(Ljava/lang/reflect/Executable;I)Z",
1798                                                        (void*)&WB_ShouldPrintAssembly},
1799
1800  {CC"isConstantVMFlag",   CC"(Ljava/lang/String;)Z", (void*)&WB_IsConstantVMFlag},
1801  {CC"isLockedVMFlag",     CC"(Ljava/lang/String;)Z", (void*)&WB_IsLockedVMFlag},
1802  {CC"setBooleanVMFlag",   CC"(Ljava/lang/String;Z)V",(void*)&WB_SetBooleanVMFlag},
1803  {CC"setIntVMFlag",       CC"(Ljava/lang/String;J)V",(void*)&WB_SetIntVMFlag},
1804  {CC"setUintVMFlag",      CC"(Ljava/lang/String;J)V",(void*)&WB_SetUintVMFlag},
1805  {CC"setIntxVMFlag",      CC"(Ljava/lang/String;J)V",(void*)&WB_SetIntxVMFlag},
1806  {CC"setUintxVMFlag",     CC"(Ljava/lang/String;J)V",(void*)&WB_SetUintxVMFlag},
1807  {CC"setUint64VMFlag",    CC"(Ljava/lang/String;J)V",(void*)&WB_SetUint64VMFlag},
1808  {CC"setSizeTVMFlag",     CC"(Ljava/lang/String;J)V",(void*)&WB_SetSizeTVMFlag},
1809  {CC"setDoubleVMFlag",    CC"(Ljava/lang/String;D)V",(void*)&WB_SetDoubleVMFlag},
1810  {CC"setStringVMFlag",    CC"(Ljava/lang/String;Ljava/lang/String;)V",
1811                                                      (void*)&WB_SetStringVMFlag},
1812  {CC"getBooleanVMFlag",   CC"(Ljava/lang/String;)Ljava/lang/Boolean;",
1813                                                      (void*)&WB_GetBooleanVMFlag},
1814  {CC"getIntVMFlag",       CC"(Ljava/lang/String;)Ljava/lang/Long;",
1815                                                      (void*)&WB_GetIntVMFlag},
1816  {CC"getUintVMFlag",      CC"(Ljava/lang/String;)Ljava/lang/Long;",
1817                                                      (void*)&WB_GetUintVMFlag},
1818  {CC"getIntxVMFlag",      CC"(Ljava/lang/String;)Ljava/lang/Long;",
1819                                                      (void*)&WB_GetIntxVMFlag},
1820  {CC"getUintxVMFlag",     CC"(Ljava/lang/String;)Ljava/lang/Long;",
1821                                                      (void*)&WB_GetUintxVMFlag},
1822  {CC"getUint64VMFlag",    CC"(Ljava/lang/String;)Ljava/lang/Long;",
1823                                                      (void*)&WB_GetUint64VMFlag},
1824  {CC"getSizeTVMFlag",     CC"(Ljava/lang/String;)Ljava/lang/Long;",
1825                                                      (void*)&WB_GetSizeTVMFlag},
1826  {CC"getDoubleVMFlag",    CC"(Ljava/lang/String;)Ljava/lang/Double;",
1827                                                      (void*)&WB_GetDoubleVMFlag},
1828  {CC"getStringVMFlag",    CC"(Ljava/lang/String;)Ljava/lang/String;",
1829                                                      (void*)&WB_GetStringVMFlag},
1830  {CC"isInStringTable",    CC"(Ljava/lang/String;)Z", (void*)&WB_IsInStringTable  },
1831  {CC"fullGC",   CC"()V",                             (void*)&WB_FullGC },
1832  {CC"youngGC",  CC"()V",                             (void*)&WB_YoungGC },
1833  {CC"readReservedMemory", CC"()V",                   (void*)&WB_ReadReservedMemory },
1834  {CC"allocateMetaspace",
1835     CC"(Ljava/lang/ClassLoader;J)J",                 (void*)&WB_AllocateMetaspace },
1836  {CC"freeMetaspace",
1837     CC"(Ljava/lang/ClassLoader;JJ)V",                (void*)&WB_FreeMetaspace },
1838  {CC"incMetaspaceCapacityUntilGC", CC"(J)J",         (void*)&WB_IncMetaspaceCapacityUntilGC },
1839  {CC"metaspaceCapacityUntilGC", CC"()J",             (void*)&WB_MetaspaceCapacityUntilGC },
1840  {CC"metaspaceShouldConcurrentCollect", CC"()Z",     (void*)&WB_MetaspaceShouldConcurrentCollect },
1841  {CC"getCPUFeatures",     CC"()Ljava/lang/String;",  (void*)&WB_GetCPUFeatures     },
1842  {CC"getNMethod0",         CC"(Ljava/lang/reflect/Executable;Z)[Ljava/lang/Object;",
1843                                                      (void*)&WB_GetNMethod         },
1844  {CC"forceNMethodSweep",  CC"()V",                   (void*)&WB_ForceNMethodSweep  },
1845  {CC"allocateCodeBlob",   CC"(II)J",                 (void*)&WB_AllocateCodeBlob   },
1846  {CC"freeCodeBlob",       CC"(J)V",                  (void*)&WB_FreeCodeBlob       },
1847  {CC"getCodeHeapEntries", CC"(I)[Ljava/lang/Object;",(void*)&WB_GetCodeHeapEntries },
1848  {CC"getCompilationActivityMode",
1849                           CC"()I",                   (void*)&WB_GetCompilationActivityMode},
1850  {CC"getMethodData0",     CC"(Ljava/lang/reflect/Executable;)J",
1851                                                      (void*)&WB_GetMethodData      },
1852  {CC"getCodeBlob",        CC"(J)[Ljava/lang/Object;",(void*)&WB_GetCodeBlob        },
1853  {CC"getThreadStackSize", CC"()J",                   (void*)&WB_GetThreadStackSize },
1854  {CC"getThreadRemainingStackSize", CC"()J",          (void*)&WB_GetThreadRemainingStackSize },
1855  {CC"DefineModule",       CC"(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/Object;)V",
1856                                                      (void*)&WB_DefineModule },
1857  {CC"AddModuleExports",   CC"(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)V",
1858                                                      (void*)&WB_AddModuleExports },
1859  {CC"AddReadsModule",     CC"(Ljava/lang/Object;Ljava/lang/Object;)V",
1860                                                      (void*)&WB_AddReadsModule },
1861  {CC"AddModulePackage",   CC"(Ljava/lang/Object;Ljava/lang/String;)V",
1862                                                      (void*)&WB_AddModulePackage },
1863  {CC"GetModuleByPackageName", CC"(Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/Object;",
1864                                                      (void*)&WB_GetModuleByPackageName },
1865  {CC"AddModuleExportsToAllUnnamed", CC"(Ljava/lang/Object;Ljava/lang/String;)V",
1866                                                      (void*)&WB_AddModuleExportsToAllUnnamed },
1867  {CC"AddModuleExportsToAll", CC"(Ljava/lang/Object;Ljava/lang/String;)V",
1868                                                      (void*)&WB_AddModuleExportsToAll },
1869  {CC"assertMatchingSafepointCalls", CC"(ZZ)V",       (void*)&WB_AssertMatchingSafepointCalls },
1870  {CC"isMonitorInflated0", CC"(Ljava/lang/Object;)Z", (void*)&WB_IsMonitorInflated  },
1871  {CC"forceSafepoint",     CC"()V",                   (void*)&WB_ForceSafepoint     },
1872  {CC"getConstantPool0",   CC"(Ljava/lang/Class;)J",  (void*)&WB_GetConstantPool    },
1873  {CC"getConstantPoolCacheIndexTag0", CC"()I",  (void*)&WB_GetConstantPoolCacheIndexTag},
1874  {CC"getConstantPoolCacheLength0", CC"(Ljava/lang/Class;)I",  (void*)&WB_GetConstantPoolCacheLength},
1875  {CC"remapInstructionOperandFromCPCache0",
1876      CC"(Ljava/lang/Class;I)I",                      (void*)&WB_ConstantPoolRemapInstructionOperandFromCache},
1877  {CC"encodeConstantPoolIndyIndex0",
1878      CC"(I)I",                      (void*)&WB_ConstantPoolEncodeIndyIndex},
1879  {CC"getMethodBooleanOption",
1880      CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)Ljava/lang/Boolean;",
1881                                                      (void*)&WB_GetMethodBooleaneOption},
1882  {CC"getMethodIntxOption",
1883      CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)Ljava/lang/Long;",
1884                                                      (void*)&WB_GetMethodIntxOption},
1885  {CC"getMethodUintxOption",
1886      CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)Ljava/lang/Long;",
1887                                                      (void*)&WB_GetMethodUintxOption},
1888  {CC"getMethodDoubleOption",
1889      CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)Ljava/lang/Double;",
1890                                                      (void*)&WB_GetMethodDoubleOption},
1891  {CC"getMethodStringOption",
1892      CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)Ljava/lang/String;",
1893                                                      (void*)&WB_GetMethodStringOption},
1894  {CC"isShared",           CC"(Ljava/lang/Object;)Z", (void*)&WB_IsShared },
1895  {CC"isSharedClass",      CC"(Ljava/lang/Class;)Z",  (void*)&WB_IsSharedClass },
1896  {CC"areSharedStringsIgnored",           CC"()Z",    (void*)&WB_AreSharedStringsIgnored },
1897  {CC"clearInlineCaches0",  CC"(Z)V",                 (void*)&WB_ClearInlineCaches },
1898  {CC"addCompilerDirective",    CC"(Ljava/lang/String;)I",
1899                                                      (void*)&WB_AddCompilerDirective },
1900  {CC"removeCompilerDirective",   CC"(I)V",             (void*)&WB_RemoveCompilerDirective },
1901  {CC"currentGC",                 CC"()I",            (void*)&WB_CurrentGC},
1902  {CC"allSupportedGC",            CC"()I",            (void*)&WB_AllSupportedGC},
1903  {CC"gcSelectedByErgo",          CC"()Z",            (void*)&WB_GCSelectedByErgo},
1904};
1905
1906#undef CC
1907
1908JVM_ENTRY(void, JVM_RegisterWhiteBoxMethods(JNIEnv* env, jclass wbclass))
1909  {
1910    if (WhiteBoxAPI) {
1911      // Make sure that wbclass is loaded by the null classloader
1912      instanceKlassHandle ikh = instanceKlassHandle(JNIHandles::resolve(wbclass)->klass());
1913      Handle loader(ikh->class_loader());
1914      if (loader.is_null()) {
1915        WhiteBox::register_methods(env, wbclass, thread, methods, sizeof(methods) / sizeof(methods[0]));
1916        WhiteBox::register_extended(env, wbclass, thread);
1917        WhiteBox::set_used();
1918      }
1919    }
1920  }
1921JVM_END
1922