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