1 /*
   2  * Copyright (c) 2012, 2022, 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 #include <new>
  27 #include "cds.h"
  28 #include "cds/archiveHeapLoader.hpp"
  29 #include "cds/cdsConstants.hpp"
  30 #include "cds/filemap.hpp"
  31 #include "cds/heapShared.hpp"
  32 #include "cds/metaspaceShared.hpp"
  33 #include "classfile/classLoaderDataGraph.hpp"
  34 #include "classfile/javaClasses.inline.hpp"
  35 #include "classfile/modules.hpp"
  36 #include "classfile/protectionDomainCache.hpp"
  37 #include "classfile/stringTable.hpp"
  38 #include "classfile/symbolTable.hpp"
  39 #include "classfile/systemDictionary.hpp"
  40 #include "classfile/vmSymbols.hpp"
  41 #include "code/codeCache.hpp"
  42 #include "compiler/compilationPolicy.hpp"
  43 #include "compiler/directivesParser.hpp"
  44 #include "compiler/methodMatcher.hpp"
  45 #include "gc/shared/concurrentGCBreakpoints.hpp"
  46 #include "gc/shared/gcConfig.hpp"
  47 #include "gc/shared/gcLocker.inline.hpp"
  48 #include "gc/shared/genArguments.hpp"
  49 #include "gc/shared/genCollectedHeap.hpp"
  50 #include "jvmtifiles/jvmtiEnv.hpp"
  51 #include "logging/log.hpp"
  52 #include "memory/iterator.hpp"
  53 #include "memory/metadataFactory.hpp"
  54 #include "memory/metaspace/testHelpers.hpp"
  55 #include "memory/metaspaceUtils.hpp"
  56 #include "memory/oopFactory.hpp"
  57 #include "memory/resourceArea.hpp"
  58 #include "memory/universe.hpp"
  59 #include "oops/array.hpp"
  60 #include "oops/compressedOops.hpp"
  61 #include "oops/constantPool.inline.hpp"
  62 #include "oops/klass.inline.hpp"
  63 #include "oops/method.inline.hpp"
  64 #include "oops/objArrayKlass.hpp"
  65 #include "oops/objArrayOop.inline.hpp"
  66 #include "oops/oop.inline.hpp"
  67 #include "oops/typeArrayOop.inline.hpp"
  68 #include "prims/resolvedMethodTable.hpp"
  69 #include "prims/wbtestmethods/parserTests.hpp"
  70 #include "prims/whitebox.inline.hpp"
  71 #include "runtime/arguments.hpp"
  72 #include "runtime/atomic.hpp"
  73 #include "runtime/deoptimization.hpp"
  74 #include "runtime/fieldDescriptor.inline.hpp"
  75 #include "runtime/flags/jvmFlag.hpp"
  76 #include "runtime/flags/jvmFlagAccess.hpp"
  77 #include "runtime/frame.inline.hpp"
  78 #include "runtime/handles.inline.hpp"
  79 #include "runtime/handshake.hpp"
  80 #include "runtime/interfaceSupport.inline.hpp"
  81 #include "runtime/javaCalls.hpp"
  82 #include "runtime/javaThread.inline.hpp"
  83 #include "runtime/jniHandles.inline.hpp"
  84 #include "runtime/os.hpp"
  85 #include "runtime/stackFrameStream.inline.hpp"
  86 #include "runtime/synchronizer.hpp"
  87 #include "runtime/threadSMR.hpp"
  88 #include "runtime/vframe.hpp"
  89 #include "runtime/vm_version.hpp"
  90 #include "services/mallocSiteTable.hpp"
  91 #include "services/memoryService.hpp"
  92 #include "services/memTracker.hpp"
  93 #include "utilities/align.hpp"
  94 #include "utilities/debug.hpp"
  95 #include "utilities/elfFile.hpp"
  96 #include "utilities/exceptions.hpp"
  97 #include "utilities/macros.hpp"
  98 #include "utilities/nativeCallStack.hpp"
  99 #include "utilities/ostream.hpp"
 100 #if INCLUDE_G1GC
 101 #include "gc/g1/g1Arguments.hpp"
 102 #include "gc/g1/g1CollectedHeap.inline.hpp"
 103 #include "gc/g1/g1ConcurrentMark.hpp"
 104 #include "gc/g1/g1ConcurrentMarkThread.inline.hpp"
 105 #include "gc/g1/heapRegionManager.hpp"
 106 #include "gc/g1/heapRegionRemSet.inline.hpp"
 107 #endif // INCLUDE_G1GC
 108 #if INCLUDE_PARALLELGC
 109 #include "gc/parallel/parallelScavengeHeap.inline.hpp"
 110 #endif // INCLUDE_PARALLELGC
 111 #if INCLUDE_JVMCI
 112 #include "jvmci/jvmciEnv.hpp"
 113 #include "jvmci/jvmciRuntime.hpp"
 114 #endif
 115 
 116 #ifdef LINUX
 117 #include "osContainer_linux.hpp"
 118 #include "cgroupSubsystem_linux.hpp"
 119 #endif
 120 
 121 #define SIZE_T_MAX_VALUE ((size_t) -1)
 122 
 123 #define CHECK_JNI_EXCEPTION_(env, value)                               \
 124   do {                                                                 \
 125     JavaThread* THREAD = JavaThread::thread_from_jni_environment(env); \
 126     THREAD->clear_pending_jni_exception_check();                       \
 127     if (HAS_PENDING_EXCEPTION) {                                       \
 128       return(value);                                                   \
 129     }                                                                  \
 130   } while (0)
 131 
 132 #define CHECK_JNI_EXCEPTION(env)                                       \
 133   do {                                                                 \
 134     JavaThread* THREAD = JavaThread::thread_from_jni_environment(env); \
 135     THREAD->clear_pending_jni_exception_check();                       \
 136     if (HAS_PENDING_EXCEPTION) {                                       \
 137       return;                                                          \
 138     }                                                                  \
 139   } while (0)
 140 
 141 bool WhiteBox::_used = false;
 142 volatile bool WhiteBox::compilation_locked = false;
 143 
 144 class VM_WhiteBoxOperation : public VM_Operation {
 145  public:
 146   VM_WhiteBoxOperation()                         { }
 147   VMOp_Type type()                  const        { return VMOp_WhiteBoxOperation; }
 148   bool allow_nested_vm_operations() const        { return true; }
 149 };
 150 
 151 
 152 WB_ENTRY(jlong, WB_GetObjectAddress(JNIEnv* env, jobject o, jobject obj))
 153   return (jlong)(void*)JNIHandles::resolve(obj);
 154 WB_END
 155 
 156 WB_ENTRY(jint, WB_GetHeapOopSize(JNIEnv* env, jobject o))
 157   return heapOopSize;
 158 WB_END
 159 
 160 WB_ENTRY(jint, WB_GetVMPageSize(JNIEnv* env, jobject o))
 161   return os::vm_page_size();
 162 WB_END
 163 
 164 WB_ENTRY(jlong, WB_GetVMAllocationGranularity(JNIEnv* env, jobject o))
 165   return os::vm_allocation_granularity();
 166 WB_END
 167 
 168 WB_ENTRY(jlong, WB_GetVMLargePageSize(JNIEnv* env, jobject o))
 169   return os::large_page_size();
 170 WB_END
 171 
 172 class WBIsKlassAliveClosure : public LockedClassesDo {
 173     Symbol* _name;
 174     int _count;
 175 public:
 176     WBIsKlassAliveClosure(Symbol* name) : _name(name), _count(0) {}
 177 
 178     void do_klass(Klass* k) {
 179       Symbol* ksym = k->name();
 180       if (ksym->fast_compare(_name) == 0) {
 181         _count++;
 182       } else if (k->is_instance_klass()) {
 183         // Need special handling for hidden classes because the JVM
 184         // appends "+<hex-address>" to hidden class names.
 185         InstanceKlass *ik = InstanceKlass::cast(k);
 186         if (ik->is_hidden()) {
 187           ResourceMark rm;
 188           char* k_name = ksym->as_C_string();
 189           // Find the first '+' char and truncate the string at that point.
 190           // NOTE: This will not work correctly if the original hidden class
 191           // name contains a '+'.
 192           char* plus_char = strchr(k_name, '+');
 193           if (plus_char != NULL) {
 194             *plus_char = 0;
 195             char* c_name = _name->as_C_string();
 196             if (strcmp(c_name, k_name) == 0) {
 197               _count++;
 198             }
 199           }
 200         }
 201       }
 202     }
 203 
 204     int count() const {
 205         return _count;
 206     }
 207 };
 208 
 209 WB_ENTRY(jint, WB_CountAliveClasses(JNIEnv* env, jobject target, jstring name))
 210   oop h_name = JNIHandles::resolve(name);
 211   if (h_name == NULL) return false;
 212   Symbol* sym = java_lang_String::as_symbol(h_name);
 213   TempNewSymbol tsym(sym); // Make sure to decrement reference count on sym on return
 214 
 215   WBIsKlassAliveClosure closure(sym);
 216   ClassLoaderDataGraph::classes_do(&closure);
 217 
 218   // Return the count of alive classes with this name.
 219   return closure.count();
 220 WB_END
 221 
 222 WB_ENTRY(jint, WB_GetSymbolRefcount(JNIEnv* env, jobject unused, jstring name))
 223   oop h_name = JNIHandles::resolve(name);
 224   if (h_name == NULL) return false;
 225   Symbol* sym = java_lang_String::as_symbol(h_name);
 226   TempNewSymbol tsym(sym); // Make sure to decrement reference count on sym on return
 227   return (jint)sym->refcount();
 228 WB_END
 229 
 230 
 231 WB_ENTRY(void, WB_AddToBootstrapClassLoaderSearch(JNIEnv* env, jobject o, jstring segment)) {
 232 #if INCLUDE_JVMTI
 233   ResourceMark rm;
 234   const char* seg = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(segment));
 235   JvmtiEnv* jvmti_env = JvmtiEnv::create_a_jvmti(JVMTI_VERSION);
 236   jvmtiError err = jvmti_env->AddToBootstrapClassLoaderSearch(seg);
 237   assert(err == JVMTI_ERROR_NONE, "must not fail");
 238 #endif
 239 }
 240 WB_END
 241 
 242 WB_ENTRY(void, WB_AddToSystemClassLoaderSearch(JNIEnv* env, jobject o, jstring segment)) {
 243 #if INCLUDE_JVMTI
 244   ResourceMark rm;
 245   const char* seg = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(segment));
 246   JvmtiEnv* jvmti_env = JvmtiEnv::create_a_jvmti(JVMTI_VERSION);
 247   jvmtiError err = jvmti_env->AddToSystemClassLoaderSearch(seg);
 248   assert(err == JVMTI_ERROR_NONE, "must not fail");
 249 #endif
 250 }
 251 WB_END
 252 
 253 
 254 WB_ENTRY(jlong, WB_GetCompressedOopsMaxHeapSize(JNIEnv* env, jobject o)) {
 255   return (jlong)Arguments::max_heap_for_compressed_oops();
 256 }
 257 WB_END
 258 
 259 WB_ENTRY(void, WB_PrintHeapSizes(JNIEnv* env, jobject o)) {
 260   tty->print_cr("Minimum heap " SIZE_FORMAT " Initial heap " SIZE_FORMAT " "
 261                 "Maximum heap " SIZE_FORMAT " Space alignment " SIZE_FORMAT " Heap alignment " SIZE_FORMAT,
 262                 MinHeapSize,
 263                 InitialHeapSize,
 264                 MaxHeapSize,
 265                 SpaceAlignment,
 266                 HeapAlignment);
 267 }
 268 WB_END
 269 
 270 WB_ENTRY(void, WB_ReadFromNoaccessArea(JNIEnv* env, jobject o))
 271   size_t granularity = os::vm_allocation_granularity();
 272   ReservedHeapSpace rhs(100 * granularity, granularity, os::vm_page_size());
 273   VirtualSpace vs;
 274   vs.initialize(rhs, 50 * granularity);
 275 
 276   // Check if constraints are complied
 277   if (!( UseCompressedOops && rhs.base() != NULL &&
 278          CompressedOops::base() != NULL &&
 279          CompressedOops::use_implicit_null_checks() )) {
 280     tty->print_cr("WB_ReadFromNoaccessArea method is useless:\n "
 281                   "\tUseCompressedOops is %d\n"
 282                   "\trhs.base() is " PTR_FORMAT "\n"
 283                   "\tCompressedOops::base() is " PTR_FORMAT "\n"
 284                   "\tCompressedOops::use_implicit_null_checks() is %d",
 285                   UseCompressedOops,
 286                   p2i(rhs.base()),
 287                   p2i(CompressedOops::base()),
 288                   CompressedOops::use_implicit_null_checks());
 289     return;
 290   }
 291   tty->print_cr("Reading from no access area... ");
 292   tty->print_cr("*(vs.low_boundary() - rhs.noaccess_prefix() / 2 ) = %c",
 293                 *(vs.low_boundary() - rhs.noaccess_prefix() / 2 ));
 294 WB_END
 295 
 296 static jint wb_stress_virtual_space_resize(size_t reserved_space_size,
 297                                            size_t magnitude, size_t iterations) {
 298   size_t granularity = os::vm_allocation_granularity();
 299   ReservedHeapSpace rhs(reserved_space_size * granularity, granularity, os::vm_page_size());
 300   VirtualSpace vs;
 301   if (!vs.initialize(rhs, 0)) {
 302     tty->print_cr("Failed to initialize VirtualSpace. Can't proceed.");
 303     return 3;
 304   }
 305 
 306   int seed = os::random();
 307   tty->print_cr("Random seed is %d", seed);
 308 
 309   for (size_t i = 0; i < iterations; i++) {
 310 
 311     // Whether we will shrink or grow
 312     bool shrink = os::random() % 2L == 0;
 313 
 314     // Get random delta to resize virtual space
 315     size_t delta = (size_t)os::random() % magnitude;
 316 
 317     // If we are about to shrink virtual space below zero, then expand instead
 318     if (shrink && vs.committed_size() < delta) {
 319       shrink = false;
 320     }
 321 
 322     // Resizing by delta
 323     if (shrink) {
 324       vs.shrink_by(delta);
 325     } else {
 326       // If expanding fails expand_by will silently return false
 327       vs.expand_by(delta, true);
 328     }
 329   }
 330   return 0;
 331 }
 332 
 333 WB_ENTRY(jint, WB_StressVirtualSpaceResize(JNIEnv* env, jobject o,
 334         jlong reserved_space_size, jlong magnitude, jlong iterations))
 335   tty->print_cr("reservedSpaceSize=" JLONG_FORMAT ", magnitude=" JLONG_FORMAT ", "
 336                 "iterations=" JLONG_FORMAT "\n", reserved_space_size, magnitude,
 337                 iterations);
 338   if (reserved_space_size < 0 || magnitude < 0 || iterations < 0) {
 339     tty->print_cr("One of variables printed above is negative. Can't proceed.\n");
 340     return 1;
 341   }
 342 
 343   // sizeof(size_t) depends on whether OS is 32bit or 64bit. sizeof(jlong) is
 344   // always 8 byte. That's why we should avoid overflow in case of 32bit platform.
 345   if (sizeof(size_t) < sizeof(jlong)) {
 346     jlong size_t_max_value = (jlong) SIZE_T_MAX_VALUE;
 347     if (reserved_space_size > size_t_max_value || magnitude > size_t_max_value
 348         || iterations > size_t_max_value) {
 349       tty->print_cr("One of variables printed above overflows size_t. Can't proceed.\n");
 350       return 2;
 351     }
 352   }
 353 
 354   return wb_stress_virtual_space_resize((size_t) reserved_space_size,
 355                                         (size_t) magnitude, (size_t) iterations);
 356 WB_END
 357 
 358 WB_ENTRY(jboolean, WB_IsGCSupported(JNIEnv* env, jobject o, jint name))
 359   return GCConfig::is_gc_supported((CollectedHeap::Name)name);
 360 WB_END
 361 
 362 WB_ENTRY(jboolean, WB_IsGCSupportedByJVMCICompiler(JNIEnv* env, jobject o, jint name))
 363 #if INCLUDE_JVMCI
 364   if (EnableJVMCI) {
 365     JVMCIEnv jvmciEnv(thread, env, __FILE__, __LINE__);
 366     return jvmciEnv.runtime()->is_gc_supported(&jvmciEnv, (CollectedHeap::Name)name);
 367   }
 368 #endif
 369   return false;
 370 WB_END
 371 
 372 WB_ENTRY(jboolean, WB_IsGCSelected(JNIEnv* env, jobject o, jint name))
 373   return GCConfig::is_gc_selected((CollectedHeap::Name)name);
 374 WB_END
 375 
 376 WB_ENTRY(jboolean, WB_IsGCSelectedErgonomically(JNIEnv* env, jobject o))
 377   return GCConfig::is_gc_selected_ergonomically();
 378 WB_END
 379 
 380 WB_ENTRY(jboolean, WB_isObjectInOldGen(JNIEnv* env, jobject o, jobject obj))
 381   oop p = JNIHandles::resolve(obj);
 382 #if INCLUDE_G1GC
 383   if (UseG1GC) {
 384     G1CollectedHeap* g1h = G1CollectedHeap::heap();
 385     const HeapRegion* hr = g1h->heap_region_containing(p);
 386     return !(hr->is_young());
 387   }
 388 #endif
 389 #if INCLUDE_PARALLELGC
 390   if (UseParallelGC) {
 391     ParallelScavengeHeap* psh = ParallelScavengeHeap::heap();
 392     return !psh->is_in_young(p);
 393   }
 394 #endif
 395 #if INCLUDE_ZGC
 396   if (UseZGC) {
 397     return Universe::heap()->is_in(p);
 398   }
 399 #endif
 400 #if INCLUDE_SHENANDOAHGC
 401   if (UseShenandoahGC) {
 402     return Universe::heap()->is_in(p);
 403   }
 404 #endif
 405   GenCollectedHeap* gch = GenCollectedHeap::heap();
 406   return !gch->is_in_young(p);
 407 WB_END
 408 
 409 WB_ENTRY(jlong, WB_GetObjectSize(JNIEnv* env, jobject o, jobject obj))
 410   oop p = JNIHandles::resolve(obj);
 411   return p->size() * HeapWordSize;
 412 WB_END
 413 
 414 WB_ENTRY(jlong, WB_GetHeapSpaceAlignment(JNIEnv* env, jobject o))
 415   return (jlong)SpaceAlignment;
 416 WB_END
 417 
 418 WB_ENTRY(jlong, WB_GetHeapAlignment(JNIEnv* env, jobject o))
 419   return (jlong)HeapAlignment;
 420 WB_END
 421 
 422 WB_ENTRY(jboolean, WB_SupportsConcurrentGCBreakpoints(JNIEnv* env, jobject o))
 423   return Universe::heap()->supports_concurrent_gc_breakpoints();
 424 WB_END
 425 
 426 WB_ENTRY(void, WB_ConcurrentGCAcquireControl(JNIEnv* env, jobject o))
 427   ConcurrentGCBreakpoints::acquire_control();
 428 WB_END
 429 
 430 WB_ENTRY(void, WB_ConcurrentGCReleaseControl(JNIEnv* env, jobject o))
 431   ConcurrentGCBreakpoints::release_control();
 432 WB_END
 433 
 434 WB_ENTRY(void, WB_ConcurrentGCRunToIdle(JNIEnv* env, jobject o))
 435   ConcurrentGCBreakpoints::run_to_idle();
 436 WB_END
 437 
 438 WB_ENTRY(jboolean, WB_ConcurrentGCRunTo(JNIEnv* env, jobject o, jobject at))
 439   Handle h_name(THREAD, JNIHandles::resolve(at));
 440   ResourceMark rm;
 441   const char* c_name = java_lang_String::as_utf8_string(h_name());
 442   return ConcurrentGCBreakpoints::run_to(c_name);
 443 WB_END
 444 
 445 #if INCLUDE_G1GC
 446 
 447 WB_ENTRY(jboolean, WB_G1IsHumongous(JNIEnv* env, jobject o, jobject obj))
 448   if (UseG1GC) {
 449     G1CollectedHeap* g1h = G1CollectedHeap::heap();
 450     oop result = JNIHandles::resolve(obj);
 451     const HeapRegion* hr = g1h->heap_region_containing(result);
 452     return hr->is_humongous();
 453   }
 454   THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_G1IsHumongous: G1 GC is not enabled");
 455 WB_END
 456 
 457 WB_ENTRY(jboolean, WB_G1BelongsToHumongousRegion(JNIEnv* env, jobject o, jlong addr))
 458   if (UseG1GC) {
 459     G1CollectedHeap* g1h = G1CollectedHeap::heap();
 460     const HeapRegion* hr = g1h->heap_region_containing((void*) addr);
 461     return hr->is_humongous();
 462   }
 463   THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_G1BelongsToHumongousRegion: G1 GC is not enabled");
 464 WB_END
 465 
 466 WB_ENTRY(jboolean, WB_G1BelongsToFreeRegion(JNIEnv* env, jobject o, jlong addr))
 467   if (UseG1GC) {
 468     G1CollectedHeap* g1h = G1CollectedHeap::heap();
 469     const HeapRegion* hr = g1h->heap_region_containing((void*) addr);
 470     return hr->is_free();
 471   }
 472   THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_G1BelongsToFreeRegion: G1 GC is not enabled");
 473 WB_END
 474 
 475 WB_ENTRY(jlong, WB_G1NumMaxRegions(JNIEnv* env, jobject o))
 476   if (UseG1GC) {
 477     G1CollectedHeap* g1h = G1CollectedHeap::heap();
 478     size_t nr = g1h->max_regions();
 479     return (jlong)nr;
 480   }
 481   THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_G1NumMaxRegions: G1 GC is not enabled");
 482 WB_END
 483 
 484 WB_ENTRY(jlong, WB_G1NumFreeRegions(JNIEnv* env, jobject o))
 485   if (UseG1GC) {
 486     G1CollectedHeap* g1h = G1CollectedHeap::heap();
 487     size_t nr = g1h->num_free_regions();
 488     return (jlong)nr;
 489   }
 490   THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_G1NumFreeRegions: G1 GC is not enabled");
 491 WB_END
 492 
 493 WB_ENTRY(jboolean, WB_G1InConcurrentMark(JNIEnv* env, jobject o))
 494   if (UseG1GC) {
 495     G1CollectedHeap* g1h = G1CollectedHeap::heap();
 496     return g1h->concurrent_mark()->cm_thread()->in_progress();
 497   }
 498   THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_G1InConcurrentMark: G1 GC is not enabled");
 499 WB_END
 500 
 501 WB_ENTRY(jboolean, WB_G1StartMarkCycle(JNIEnv* env, jobject o))
 502   if (UseG1GC) {
 503     G1CollectedHeap* g1h = G1CollectedHeap::heap();
 504     if (!g1h->concurrent_mark()->cm_thread()->in_progress()) {
 505       g1h->collect(GCCause::_wb_conc_mark);
 506       return true;
 507     }
 508     return false;
 509   }
 510   THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_G1StartMarkCycle: G1 GC is not enabled");
 511 WB_END
 512 
 513 WB_ENTRY(jint, WB_G1RegionSize(JNIEnv* env, jobject o))
 514   if (UseG1GC) {
 515     return (jint)HeapRegion::GrainBytes;
 516   }
 517   THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_G1RegionSize: G1 GC is not enabled");
 518 WB_END
 519 
 520 WB_ENTRY(jboolean, WB_G1HasRegionsToUncommit(JNIEnv* env, jobject o))
 521   if (UseG1GC) {
 522     return G1CollectedHeap::heap()->has_uncommittable_regions();
 523   }
 524   THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_G1HasRegionsToUncommit: G1 GC is not enabled");
 525 WB_END
 526 
 527 #endif // INCLUDE_G1GC
 528 
 529 #if INCLUDE_PARALLELGC
 530 
 531 WB_ENTRY(jlong, WB_PSVirtualSpaceAlignment(JNIEnv* env, jobject o))
 532   if (UseParallelGC) {
 533     return GenAlignment;
 534   }
 535   THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_PSVirtualSpaceAlignment: Parallel GC is not enabled");
 536 WB_END
 537 
 538 WB_ENTRY(jlong, WB_PSHeapGenerationAlignment(JNIEnv* env, jobject o))
 539   if (UseParallelGC) {
 540     return GenAlignment;
 541   }
 542   THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_PSHeapGenerationAlignment: Parallel GC is not enabled");
 543 WB_END
 544 
 545 #endif // INCLUDE_PARALLELGC
 546 
 547 #if INCLUDE_G1GC
 548 
 549 WB_ENTRY(jobject, WB_G1AuxiliaryMemoryUsage(JNIEnv* env))
 550   if (UseG1GC) {
 551     ResourceMark rm(THREAD);
 552     G1CollectedHeap* g1h = G1CollectedHeap::heap();
 553     MemoryUsage usage = g1h->get_auxiliary_data_memory_usage();
 554     Handle h = MemoryService::create_MemoryUsage_obj(usage, CHECK_NULL);
 555     return JNIHandles::make_local(THREAD, h());
 556   }
 557   THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_G1AuxiliaryMemoryUsage: G1 GC is not enabled");
 558 WB_END
 559 
 560 WB_ENTRY(jint, WB_G1ActiveMemoryNodeCount(JNIEnv* env, jobject o))
 561   if (UseG1GC) {
 562     G1NUMA* numa = G1NUMA::numa();
 563     return (jint)numa->num_active_nodes();
 564   }
 565   THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_G1ActiveMemoryNodeCount: G1 GC is not enabled");
 566 WB_END
 567 
 568 WB_ENTRY(jintArray, WB_G1MemoryNodeIds(JNIEnv* env, jobject o))
 569   if (UseG1GC) {
 570     G1NUMA* numa = G1NUMA::numa();
 571     int num_node_ids = (int)numa->num_active_nodes();
 572     const int* node_ids = numa->node_ids();
 573 
 574     typeArrayOop result = oopFactory::new_intArray(num_node_ids, CHECK_NULL);
 575     for (int i = 0; i < num_node_ids; i++) {
 576       result->int_at_put(i, (jint)node_ids[i]);
 577     }
 578     return (jintArray) JNIHandles::make_local(THREAD, result);
 579   }
 580   THROW_MSG_NULL(vmSymbols::java_lang_UnsupportedOperationException(), "WB_G1MemoryNodeIds: G1 GC is not enabled");
 581 WB_END
 582 
 583 class OldRegionsLivenessClosure: public HeapRegionClosure {
 584 
 585  private:
 586   const int _liveness;
 587   size_t _total_count;
 588   size_t _total_memory;
 589   size_t _total_memory_to_free;
 590 
 591  public:
 592   OldRegionsLivenessClosure(int liveness) :
 593     _liveness(liveness),
 594     _total_count(0),
 595     _total_memory(0),
 596     _total_memory_to_free(0) { }
 597 
 598     size_t total_count() { return _total_count; }
 599     size_t total_memory() { return _total_memory; }
 600     size_t total_memory_to_free() { return _total_memory_to_free; }
 601 
 602   bool do_heap_region(HeapRegion* r) {
 603     if (r->is_old()) {
 604       size_t live = r->live_bytes();
 605       size_t size = r->used();
 606       size_t reg_size = HeapRegion::GrainBytes;
 607       if (size > 0 && ((int)(live * 100 / size) < _liveness)) {
 608         _total_memory += size;
 609         ++_total_count;
 610         if (size == reg_size) {
 611           // We don't include non-full regions since they are unlikely included in mixed gc
 612           // for testing purposes it's enough to have lowest estimation of total memory that is expected to be freed
 613           _total_memory_to_free += size - live;
 614         }
 615       }
 616     }
 617     return false;
 618   }
 619 };
 620 
 621 
 622 WB_ENTRY(jlongArray, WB_G1GetMixedGCInfo(JNIEnv* env, jobject o, jint liveness))
 623   if (!UseG1GC) {
 624     THROW_MSG_NULL(vmSymbols::java_lang_UnsupportedOperationException(), "WB_G1GetMixedGCInfo: G1 GC is not enabled");
 625   }
 626   if (liveness < 0) {
 627     THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), "liveness value should be non-negative");
 628   }
 629 
 630   G1CollectedHeap* g1h = G1CollectedHeap::heap();
 631   OldRegionsLivenessClosure rli(liveness);
 632   g1h->heap_region_iterate(&rli);
 633 
 634   typeArrayOop result = oopFactory::new_longArray(3, CHECK_NULL);
 635   result->long_at_put(0, rli.total_count());
 636   result->long_at_put(1, rli.total_memory());
 637   result->long_at_put(2, rli.total_memory_to_free());
 638   return (jlongArray) JNIHandles::make_local(THREAD, result);
 639 WB_END
 640 
 641 #endif // INCLUDE_G1GC
 642 
 643 // Alloc memory using the test memory type so that we can use that to see if
 644 // NMT picks it up correctly
 645 WB_ENTRY(jlong, WB_NMTMalloc(JNIEnv* env, jobject o, jlong size))
 646   jlong addr = 0;
 647   addr = (jlong)(uintptr_t)os::malloc(size, mtTest);
 648   return addr;
 649 WB_END
 650 
 651 // Alloc memory with pseudo call stack. The test can create pseudo malloc
 652 // allocation site to stress the malloc tracking.
 653 WB_ENTRY(jlong, WB_NMTMallocWithPseudoStack(JNIEnv* env, jobject o, jlong size, jint pseudo_stack))
 654   address pc = (address)(size_t)pseudo_stack;
 655   NativeCallStack stack(&pc, 1);
 656   return (jlong)(uintptr_t)os::malloc(size, mtTest, stack);
 657 WB_END
 658 
 659 // Alloc memory with pseudo call stack and specific memory type.
 660 WB_ENTRY(jlong, WB_NMTMallocWithPseudoStackAndType(JNIEnv* env, jobject o, jlong size, jint pseudo_stack, jint type))
 661   address pc = (address)(size_t)pseudo_stack;
 662   NativeCallStack stack(&pc, 1);
 663   return (jlong)(uintptr_t)os::malloc(size, (MEMFLAGS)type, stack);
 664 WB_END
 665 
 666 // Free the memory allocated by NMTAllocTest
 667 WB_ENTRY(void, WB_NMTFree(JNIEnv* env, jobject o, jlong mem))
 668   os::free((void*)(uintptr_t)mem);
 669 WB_END
 670 
 671 WB_ENTRY(jlong, WB_NMTReserveMemory(JNIEnv* env, jobject o, jlong size))
 672   jlong addr = 0;
 673 
 674   addr = (jlong)(uintptr_t)os::reserve_memory(size);
 675   MemTracker::record_virtual_memory_type((address)addr, mtTest);
 676 
 677   return addr;
 678 WB_END
 679 
 680 WB_ENTRY(jlong, WB_NMTAttemptReserveMemoryAt(JNIEnv* env, jobject o, jlong addr, jlong size))
 681   addr = (jlong)(uintptr_t)os::attempt_reserve_memory_at((char*)(uintptr_t)addr, (size_t)size);
 682   MemTracker::record_virtual_memory_type((address)addr, mtTest);
 683 
 684   return addr;
 685 WB_END
 686 
 687 WB_ENTRY(void, WB_NMTCommitMemory(JNIEnv* env, jobject o, jlong addr, jlong size))
 688   os::commit_memory((char *)(uintptr_t)addr, size, !ExecMem);
 689   MemTracker::record_virtual_memory_type((address)(uintptr_t)addr, mtTest);
 690 WB_END
 691 
 692 WB_ENTRY(void, WB_NMTUncommitMemory(JNIEnv* env, jobject o, jlong addr, jlong size))
 693   os::uncommit_memory((char *)(uintptr_t)addr, size);
 694 WB_END
 695 
 696 WB_ENTRY(void, WB_NMTReleaseMemory(JNIEnv* env, jobject o, jlong addr, jlong size))
 697   os::release_memory((char *)(uintptr_t)addr, size);
 698 WB_END
 699 
 700 WB_ENTRY(jint, WB_NMTGetHashSize(JNIEnv* env, jobject o))
 701   int hash_size = MallocSiteTable::hash_buckets();
 702   assert(hash_size > 0, "NMT hash_size should be > 0");
 703   return (jint)hash_size;
 704 WB_END
 705 
 706 WB_ENTRY(jlong, WB_NMTNewArena(JNIEnv* env, jobject o, jlong init_size))
 707   Arena* arena =  new (mtTest) Arena(mtTest, size_t(init_size));
 708   return (jlong)arena;
 709 WB_END
 710 
 711 WB_ENTRY(void, WB_NMTFreeArena(JNIEnv* env, jobject o, jlong arena))
 712   Arena* a = (Arena*)arena;
 713   delete a;
 714 WB_END
 715 
 716 WB_ENTRY(void, WB_NMTArenaMalloc(JNIEnv* env, jobject o, jlong arena, jlong size))
 717   Arena* a = (Arena*)arena;
 718   a->Amalloc(size_t(size));
 719 WB_END
 720 
 721 static jmethodID reflected_method_to_jmid(JavaThread* thread, JNIEnv* env, jobject method) {
 722   assert(method != NULL, "method should not be null");
 723   ThreadToNativeFromVM ttn(thread);
 724   return env->FromReflectedMethod(method);
 725 }
 726 
 727 // Deoptimizes all compiled frames and makes nmethods not entrant if it's requested
 728 class VM_WhiteBoxDeoptimizeFrames : public VM_WhiteBoxOperation {
 729  private:
 730   int _result;
 731   const bool _make_not_entrant;
 732  public:
 733   VM_WhiteBoxDeoptimizeFrames(bool make_not_entrant) :
 734         _result(0), _make_not_entrant(make_not_entrant) { }
 735   int  result() const { return _result; }
 736 
 737   void doit() {
 738     for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) {
 739       if (t->has_last_Java_frame()) {
 740         for (StackFrameStream fst(t, false /* update */, true /* process_frames */); !fst.is_done(); fst.next()) {
 741           frame* f = fst.current();
 742           if (f->can_be_deoptimized() && !f->is_deoptimized_frame()) {
 743             Deoptimization::deoptimize(t, *f);
 744             if (_make_not_entrant) {
 745                 CompiledMethod* cm = CodeCache::find_compiled(f->pc());
 746                 assert(cm != NULL, "sanity check");
 747                 cm->make_not_entrant();
 748             }
 749             ++_result;
 750           }
 751         }
 752       }
 753     }
 754   }
 755 };
 756 
 757 WB_ENTRY(jint, WB_DeoptimizeFrames(JNIEnv* env, jobject o, jboolean make_not_entrant))
 758   VM_WhiteBoxDeoptimizeFrames op(make_not_entrant == JNI_TRUE);
 759   VMThread::execute(&op);
 760   return op.result();
 761 WB_END
 762 
 763 WB_ENTRY(jboolean, WB_IsFrameDeoptimized(JNIEnv* env, jobject o, jint depth))
 764   bool result = false;
 765   if (thread->has_last_Java_frame()) {
 766     RegisterMap reg_map(thread,
 767                         RegisterMap::UpdateMap::include,
 768                         RegisterMap::ProcessFrames::include,
 769                         RegisterMap::WalkContinuation::skip);
 770     javaVFrame *jvf = thread->last_java_vframe(&reg_map);
 771     for (jint d = 0; d < depth && jvf != NULL; d++) {
 772       jvf = jvf->java_sender();
 773     }
 774     result = jvf != NULL && jvf->fr().is_deoptimized_frame();
 775   }
 776   return result;
 777 WB_END
 778 
 779 WB_ENTRY(void, WB_DeoptimizeAll(JNIEnv* env, jobject o))
 780   CodeCache::mark_all_nmethods_for_deoptimization();
 781   Deoptimization::deoptimize_all_marked();
 782 WB_END
 783 
 784 WB_ENTRY(jint, WB_DeoptimizeMethod(JNIEnv* env, jobject o, jobject method, jboolean is_osr))
 785   jmethodID jmid = reflected_method_to_jmid(thread, env, method);
 786   int result = 0;
 787   CHECK_JNI_EXCEPTION_(env, result);
 788   MutexLocker mu(Compile_lock);
 789   methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
 790   if (is_osr) {
 791     result += mh->mark_osr_nmethods();
 792   } else if (mh->code() != NULL) {
 793     mh->code()->mark_for_deoptimization();
 794     ++result;
 795   }
 796   result += CodeCache::mark_for_deoptimization(mh());
 797   if (result > 0) {
 798     Deoptimization::deoptimize_all_marked();
 799   }
 800   return result;
 801 WB_END
 802 
 803 WB_ENTRY(jboolean, WB_IsMethodCompiled(JNIEnv* env, jobject o, jobject method, jboolean is_osr))
 804   jmethodID jmid = reflected_method_to_jmid(thread, env, method);
 805   CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
 806   MutexLocker mu(Compile_lock);
 807   methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
 808   CompiledMethod* code = is_osr ? mh->lookup_osr_nmethod_for(InvocationEntryBci, CompLevel_none, false) : mh->code();
 809   if (code == NULL) {
 810     return JNI_FALSE;
 811   }
 812   return !code->is_marked_for_deoptimization();
 813 WB_END
 814 
 815 static bool is_excluded_for_compiler(AbstractCompiler* comp, methodHandle& mh) {
 816   if (comp == NULL) {
 817     return true;
 818   }
 819   DirectiveSet* directive = DirectivesStack::getMatchingDirective(mh, comp);
 820   if (directive->ExcludeOption) {
 821     return true;
 822   }
 823   return false;
 824 }
 825 
 826 static bool can_be_compiled_at_level(methodHandle& mh, jboolean is_osr, int level) {
 827   if (is_osr) {
 828     return CompilationPolicy::can_be_osr_compiled(mh, level);
 829   } else {
 830     return CompilationPolicy::can_be_compiled(mh, level);
 831   }
 832 }
 833 
 834 WB_ENTRY(jboolean, WB_IsMethodCompilable(JNIEnv* env, jobject o, jobject method, jint comp_level, jboolean is_osr))
 835   if (method == NULL || comp_level > CompilationPolicy::highest_compile_level()) {
 836     return false;
 837   }
 838   jmethodID jmid = reflected_method_to_jmid(thread, env, method);
 839   CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
 840   MutexLocker mu(Compile_lock);
 841   methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
 842 
 843   // The ExcludeOption directive is evaluated lazily upon compilation attempt. If a method was not tried to be compiled by
 844   // a compiler, yet, the method object is not set to be not compilable by that compiler. Thus, evaluate the compiler directive
 845   // to exclude a compilation of 'method'.
 846   if (comp_level == CompLevel_any) {
 847     // Both compilers could have ExcludeOption set. Check all combinations.
 848     bool excluded_c1 = is_excluded_for_compiler(CompileBroker::compiler1(), mh);
 849     bool excluded_c2 = is_excluded_for_compiler(CompileBroker::compiler2(), mh);
 850     if (excluded_c1 && excluded_c2) {
 851       // Compilation of 'method' excluded by both compilers.
 852       return false;
 853     }
 854 
 855     if (excluded_c1) {
 856       // C1 only has ExcludeOption set: Check if compilable with C2.
 857       return can_be_compiled_at_level(mh, is_osr, CompLevel_full_optimization);
 858     } else if (excluded_c2) {
 859       // C2 only has ExcludeOption set: Check if compilable with C1.
 860       return can_be_compiled_at_level(mh, is_osr, CompLevel_simple);
 861     }
 862   } else if (comp_level > CompLevel_none && is_excluded_for_compiler(CompileBroker::compiler((int)comp_level), mh)) {
 863     // Compilation of 'method' excluded by compiler used for 'comp_level'.
 864     return false;
 865   }
 866 
 867   return can_be_compiled_at_level(mh, is_osr, (int)comp_level);
 868 WB_END
 869 
 870 WB_ENTRY(jboolean, WB_IsMethodQueuedForCompilation(JNIEnv* env, jobject o, jobject method))
 871   jmethodID jmid = reflected_method_to_jmid(thread, env, method);
 872   CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
 873   MutexLocker mu(Compile_lock);
 874   methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
 875   return mh->queued_for_compilation();
 876 WB_END
 877 
 878 WB_ENTRY(jboolean, WB_IsIntrinsicAvailable(JNIEnv* env, jobject o, jobject method, jobject compilation_context, jint compLevel))
 879   if (compLevel < CompLevel_none || compLevel > CompilationPolicy::highest_compile_level()) {
 880     return false; // Intrinsic is not available on a non-existent compilation level.
 881   }
 882   jmethodID method_id, compilation_context_id;
 883   method_id = reflected_method_to_jmid(thread, env, method);
 884   CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
 885   methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(method_id));
 886 
 887   DirectiveSet* directive;
 888   AbstractCompiler* comp = CompileBroker::compiler((int)compLevel);
 889   assert(comp != NULL, "compiler not available");
 890   if (compilation_context != NULL) {
 891     compilation_context_id = reflected_method_to_jmid(thread, env, compilation_context);
 892     CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
 893     methodHandle cch(THREAD, Method::checked_resolve_jmethod_id(compilation_context_id));
 894     directive = DirectivesStack::getMatchingDirective(cch, comp);
 895   } else {
 896     // Calling with NULL matches default directive
 897     directive = DirectivesStack::getDefaultDirective(comp);
 898   }
 899   bool result = comp->is_intrinsic_available(mh, directive);
 900   DirectivesStack::release(directive);
 901   return result;
 902 WB_END
 903 
 904 WB_ENTRY(jint, WB_GetMethodCompilationLevel(JNIEnv* env, jobject o, jobject method, jboolean is_osr))
 905   jmethodID jmid = reflected_method_to_jmid(thread, env, method);
 906   CHECK_JNI_EXCEPTION_(env, CompLevel_none);
 907   methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
 908   CompiledMethod* code = is_osr ? mh->lookup_osr_nmethod_for(InvocationEntryBci, CompLevel_none, false) : mh->code();
 909   return (code != NULL ? code->comp_level() : CompLevel_none);
 910 WB_END
 911 
 912 WB_ENTRY(void, WB_MakeMethodNotCompilable(JNIEnv* env, jobject o, jobject method, jint comp_level, jboolean is_osr))
 913   jmethodID jmid = reflected_method_to_jmid(thread, env, method);
 914   CHECK_JNI_EXCEPTION(env);
 915   methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
 916   if (is_osr) {
 917     mh->set_not_osr_compilable("WhiteBox", comp_level);
 918   } else {
 919     mh->set_not_compilable("WhiteBox", comp_level);
 920   }
 921 WB_END
 922 
 923 WB_ENTRY(jint, WB_GetMethodDecompileCount(JNIEnv* env, jobject o, jobject method))
 924   jmethodID jmid = reflected_method_to_jmid(thread, env, method);
 925   CHECK_JNI_EXCEPTION_(env, 0);
 926   methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
 927   uint cnt = 0;
 928   MethodData* mdo = mh->method_data();
 929   if (mdo != NULL) {
 930     cnt = mdo->decompile_count();
 931   }
 932   return cnt;
 933 WB_END
 934 
 935 // Get the trap count of a method for a specific reason. If the trap count for
 936 // that reason did overflow, this includes the overflow trap count of the method.
 937 // If 'reason' is NULL, the sum of the traps for all reasons will be returned.
 938 // This number includes the overflow trap count if the trap count for any reason
 939 // did overflow.
 940 WB_ENTRY(jint, WB_GetMethodTrapCount(JNIEnv* env, jobject o, jobject method, jstring reason_obj))
 941   jmethodID jmid = reflected_method_to_jmid(thread, env, method);
 942   CHECK_JNI_EXCEPTION_(env, 0);
 943   methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
 944   uint cnt = 0;
 945   MethodData* mdo = mh->method_data();
 946   if (mdo != NULL) {
 947     ResourceMark rm(THREAD);
 948     char* reason_str = (reason_obj == NULL) ?
 949       NULL : java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(reason_obj));
 950     bool overflow = false;
 951     for (uint reason = 0; reason < mdo->trap_reason_limit(); reason++) {
 952       if (reason_str != NULL && !strcmp(reason_str, Deoptimization::trap_reason_name(reason))) {
 953         cnt = mdo->trap_count(reason);
 954         // Count in the overflow trap count on overflow
 955         if (cnt == (uint)-1) {
 956           cnt = mdo->trap_count_limit() + mdo->overflow_trap_count();
 957         }
 958         break;
 959       } else if (reason_str == NULL) {
 960         uint c = mdo->trap_count(reason);
 961         if (c == (uint)-1) {
 962           c = mdo->trap_count_limit();
 963           if (!overflow) {
 964             // Count overflow trap count just once
 965             overflow = true;
 966             c += mdo->overflow_trap_count();
 967           }
 968         }
 969         cnt += c;
 970       }
 971     }
 972   }
 973   return cnt;
 974 WB_END
 975 
 976 WB_ENTRY(jint, WB_GetDeoptCount(JNIEnv* env, jobject o, jstring reason_obj, jstring action_obj))
 977   if (reason_obj == NULL && action_obj == NULL) {
 978     return Deoptimization::total_deoptimization_count();
 979   }
 980   ResourceMark rm(THREAD);
 981   const char *reason_str = (reason_obj == NULL) ?
 982     NULL : java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(reason_obj));
 983   const char *action_str = (action_obj == NULL) ?
 984     NULL : java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(action_obj));
 985 
 986   return Deoptimization::deoptimization_count(reason_str, action_str);
 987 WB_END
 988 
 989 WB_ENTRY(jint, WB_GetMethodEntryBci(JNIEnv* env, jobject o, jobject method))
 990   jmethodID jmid = reflected_method_to_jmid(thread, env, method);
 991   CHECK_JNI_EXCEPTION_(env, InvocationEntryBci);
 992   methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
 993   CompiledMethod* code = mh->lookup_osr_nmethod_for(InvocationEntryBci, CompLevel_none, false);
 994   return (code != NULL && code->is_osr_method() ? code->osr_entry_bci() : InvocationEntryBci);
 995 WB_END
 996 
 997 WB_ENTRY(jboolean, WB_TestSetDontInlineMethod(JNIEnv* env, jobject o, jobject method, jboolean value))
 998   jmethodID jmid = reflected_method_to_jmid(thread, env, method);
 999   CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
1000   methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
1001   bool result = mh->dont_inline();
1002   mh->set_dont_inline(value == JNI_TRUE);
1003   return result;
1004 WB_END
1005 
1006 WB_ENTRY(jint, WB_GetCompileQueueSize(JNIEnv* env, jobject o, jint comp_level))
1007   if (comp_level == CompLevel_any) {
1008     return CompileBroker::queue_size(CompLevel_full_optimization) /* C2 */ +
1009         CompileBroker::queue_size(CompLevel_full_profile) /* C1 */;
1010   } else {
1011     return CompileBroker::queue_size(comp_level);
1012   }
1013 WB_END
1014 
1015 WB_ENTRY(jboolean, WB_TestSetForceInlineMethod(JNIEnv* env, jobject o, jobject method, jboolean value))
1016   jmethodID jmid = reflected_method_to_jmid(thread, env, method);
1017   CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
1018   methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
1019   bool result = mh->force_inline();
1020   mh->set_force_inline(value == JNI_TRUE);
1021   return result;
1022 WB_END
1023 
1024 #ifdef LINUX
1025 bool WhiteBox::validate_cgroup(const char* proc_cgroups,
1026                                const char* proc_self_cgroup,
1027                                const char* proc_self_mountinfo,
1028                                u1* cg_flags) {
1029   CgroupInfo cg_infos[CG_INFO_LENGTH];
1030   return CgroupSubsystemFactory::determine_type(cg_infos, proc_cgroups,
1031                                                     proc_self_cgroup,
1032                                                     proc_self_mountinfo, cg_flags);
1033 }
1034 #endif
1035 
1036 bool WhiteBox::compile_method(Method* method, int comp_level, int bci, JavaThread* THREAD) {
1037   // Screen for unavailable/bad comp level or null method
1038   AbstractCompiler* comp = CompileBroker::compiler(comp_level);
1039   if (method == NULL) {
1040     tty->print_cr("WB error: request to compile NULL method");
1041     return false;
1042   }
1043   if (comp_level > CompilationPolicy::highest_compile_level()) {
1044     tty->print_cr("WB error: invalid compilation level %d", comp_level);
1045     return false;
1046   }
1047   if (comp == NULL) {
1048     tty->print_cr("WB error: no compiler for requested compilation level %d", comp_level);
1049     return false;
1050   }
1051 
1052   // Check if compilation is blocking
1053   methodHandle mh(THREAD, method);
1054   DirectiveSet* directive = DirectivesStack::getMatchingDirective(mh, comp);
1055   bool is_blocking = !directive->BackgroundCompilationOption;
1056   DirectivesStack::release(directive);
1057 
1058   // Compile method and check result
1059   nmethod* nm = CompileBroker::compile_method(mh, bci, comp_level, mh, mh->invocation_count(), CompileTask::Reason_Whitebox, CHECK_false);
1060   MutexLocker mu(THREAD, Compile_lock);
1061   bool is_queued = mh->queued_for_compilation();
1062   if ((!is_blocking && is_queued) || nm != NULL) {
1063     return true;
1064   }
1065   // Check code again because compilation may be finished before Compile_lock is acquired.
1066   if (bci == InvocationEntryBci) {
1067     CompiledMethod* code = mh->code();
1068     if (code != NULL && code->as_nmethod_or_null() != NULL) {
1069       return true;
1070     }
1071   } else if (mh->lookup_osr_nmethod_for(bci, comp_level, false) != NULL) {
1072     return true;
1073   }
1074   tty->print("WB error: failed to %s compile at level %d method ", is_blocking ? "blocking" : "", comp_level);
1075   mh->print_short_name(tty);
1076   tty->cr();
1077   if (is_blocking && is_queued) {
1078     tty->print_cr("WB error: blocking compilation is still in queue!");
1079   }
1080   return false;
1081 }
1082 
1083 WB_ENTRY(jboolean, WB_EnqueueMethodForCompilation(JNIEnv* env, jobject o, jobject method, jint comp_level, jint bci))
1084   jmethodID jmid = reflected_method_to_jmid(thread, env, method);
1085   CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
1086   return WhiteBox::compile_method(Method::checked_resolve_jmethod_id(jmid), comp_level, bci, THREAD);
1087 WB_END
1088 
1089 WB_ENTRY(jboolean, WB_EnqueueInitializerForCompilation(JNIEnv* env, jobject o, jclass klass, jint comp_level))
1090   InstanceKlass* ik = InstanceKlass::cast(java_lang_Class::as_Klass(JNIHandles::resolve(klass)));
1091   Method* clinit = ik->class_initializer();
1092   if (clinit == NULL || clinit->method_holder()->is_not_initialized()) {
1093     return false;
1094   }
1095   return WhiteBox::compile_method(clinit, comp_level, InvocationEntryBci, THREAD);
1096 WB_END
1097 
1098 WB_ENTRY(jboolean, WB_ShouldPrintAssembly(JNIEnv* env, jobject o, jobject method, jint comp_level))
1099   jmethodID jmid = reflected_method_to_jmid(thread, env, method);
1100   CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
1101 
1102   methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
1103   DirectiveSet* directive = DirectivesStack::getMatchingDirective(mh, CompileBroker::compiler(comp_level));
1104   bool result = directive->PrintAssemblyOption;
1105   DirectivesStack::release(directive);
1106 
1107   return result;
1108 WB_END
1109 
1110 WB_ENTRY(jint, WB_MatchesInline(JNIEnv* env, jobject o, jobject method, jstring pattern))
1111   jmethodID jmid = reflected_method_to_jmid(thread, env, method);
1112   CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
1113 
1114   methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
1115 
1116   ResourceMark rm(THREAD);
1117   const char* error_msg = NULL;
1118   char* method_str = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(pattern));
1119   InlineMatcher* m = InlineMatcher::parse_inline_pattern(method_str, error_msg);
1120 
1121   if (m == NULL) {
1122     assert(error_msg != NULL, "Always have an error message");
1123     tty->print_cr("Got error: %s", error_msg);
1124     return -1; // Pattern failed
1125   }
1126 
1127   // Pattern works - now check if it matches
1128   int result;
1129   if (m->match(mh, InlineMatcher::force_inline)) {
1130     result = 2; // Force inline match
1131   } else if (m->match(mh, InlineMatcher::dont_inline)) {
1132     result = 1; // Dont inline match
1133   } else {
1134     result = 0; // No match
1135   }
1136   delete m;
1137   return result;
1138 WB_END
1139 
1140 WB_ENTRY(jint, WB_MatchesMethod(JNIEnv* env, jobject o, jobject method, jstring pattern))
1141   jmethodID jmid = reflected_method_to_jmid(thread, env, method);
1142   CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
1143 
1144   methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
1145 
1146   ResourceMark rm;
1147   char* method_str = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(pattern));
1148 
1149   const char* error_msg = NULL;
1150 
1151   BasicMatcher* m = BasicMatcher::parse_method_pattern(method_str, error_msg, false);
1152   if (m == NULL) {
1153     assert(error_msg != NULL, "Must have error_msg");
1154     tty->print_cr("Got error: %s", error_msg);
1155     return -1;
1156   }
1157 
1158   // Pattern works - now check if it matches
1159   int result = m->matches(mh);
1160   delete m;
1161   assert(result == 0 || result == 1, "Result out of range");
1162   return result;
1163 WB_END
1164 
1165 WB_ENTRY(void, WB_MarkMethodProfiled(JNIEnv* env, jobject o, jobject method))
1166   jmethodID jmid = reflected_method_to_jmid(thread, env, method);
1167   CHECK_JNI_EXCEPTION(env);
1168   methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
1169 
1170   MethodData* mdo = mh->method_data();
1171   if (mdo == NULL) {
1172     Method::build_profiling_method_data(mh, CHECK_AND_CLEAR);
1173     mdo = mh->method_data();
1174   }
1175   mdo->init();
1176   InvocationCounter* icnt = mdo->invocation_counter();
1177   InvocationCounter* bcnt = mdo->backedge_counter();
1178   // set i-counter according to CompilationPolicy::is_method_profiled
1179   icnt->set(Tier4MinInvocationThreshold);
1180   bcnt->set(Tier4CompileThreshold);
1181 WB_END
1182 
1183 WB_ENTRY(void, WB_ClearMethodState(JNIEnv* env, jobject o, jobject method))
1184   jmethodID jmid = reflected_method_to_jmid(thread, env, method);
1185   CHECK_JNI_EXCEPTION(env);
1186   methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
1187   MutexLocker mu(THREAD, Compile_lock);
1188   MethodData* mdo = mh->method_data();
1189   MethodCounters* mcs = mh->method_counters();
1190 
1191   if (mdo != NULL) {
1192     mdo->init();
1193     ResourceMark rm(THREAD);
1194     int arg_count = mdo->method()->size_of_parameters();
1195     for (int i = 0; i < arg_count; i++) {
1196       mdo->set_arg_modified(i, 0);
1197     }
1198     MutexLocker mu(THREAD, mdo->extra_data_lock());
1199     mdo->clean_method_data(/*always_clean*/true);
1200   }
1201 
1202   mh->clear_not_c1_compilable();
1203   mh->clear_not_c2_compilable();
1204   mh->clear_not_c2_osr_compilable();
1205   NOT_PRODUCT(mh->set_compiled_invocation_count(0));
1206   if (mcs != NULL) {
1207     mcs->clear_counters();
1208   }
1209 WB_END
1210 
1211 template <typename T, int type_enum>
1212 static bool GetVMFlag(JavaThread* thread, JNIEnv* env, jstring name, T* value) {
1213   if (name == NULL) {
1214     return false;
1215   }
1216   ThreadToNativeFromVM ttnfv(thread);   // can't be in VM when we call JNI
1217   const char* flag_name = env->GetStringUTFChars(name, NULL);
1218   CHECK_JNI_EXCEPTION_(env, false);
1219   const JVMFlag* flag = JVMFlag::find_declared_flag(flag_name);
1220   JVMFlag::Error result = JVMFlagAccess::get<T, type_enum>(flag, value);
1221   env->ReleaseStringUTFChars(name, flag_name);
1222   return (result == JVMFlag::SUCCESS);
1223 }
1224 
1225 template <typename T, int type_enum>
1226 static bool SetVMFlag(JavaThread* thread, JNIEnv* env, jstring name, T* value) {
1227   if (name == NULL) {
1228     return false;
1229   }
1230   ThreadToNativeFromVM ttnfv(thread);   // can't be in VM when we call JNI
1231   const char* flag_name = env->GetStringUTFChars(name, NULL);
1232   CHECK_JNI_EXCEPTION_(env, false);
1233   JVMFlag* flag = JVMFlag::find_flag(flag_name);
1234   JVMFlag::Error result = JVMFlagAccess::set<T, type_enum>(flag, value, JVMFlagOrigin::INTERNAL);
1235   env->ReleaseStringUTFChars(name, flag_name);
1236   return (result == JVMFlag::SUCCESS);
1237 }
1238 
1239 template <typename T>
1240 static jobject box(JavaThread* thread, JNIEnv* env, Symbol* name, Symbol* sig, T value) {
1241   ResourceMark rm(thread);
1242   jclass clazz = env->FindClass(name->as_C_string());
1243   CHECK_JNI_EXCEPTION_(env, NULL);
1244   jmethodID methodID = env->GetStaticMethodID(clazz,
1245         vmSymbols::valueOf_name()->as_C_string(),
1246         sig->as_C_string());
1247   CHECK_JNI_EXCEPTION_(env, NULL);
1248   jobject result = env->CallStaticObjectMethod(clazz, methodID, value);
1249   CHECK_JNI_EXCEPTION_(env, NULL);
1250   return result;
1251 }
1252 
1253 static jobject booleanBox(JavaThread* thread, JNIEnv* env, jboolean value) {
1254   return box(thread, env, vmSymbols::java_lang_Boolean(), vmSymbols::Boolean_valueOf_signature(), value);
1255 }
1256 static jobject integerBox(JavaThread* thread, JNIEnv* env, jint value) {
1257   return box(thread, env, vmSymbols::java_lang_Integer(), vmSymbols::Integer_valueOf_signature(), value);
1258 }
1259 static jobject longBox(JavaThread* thread, JNIEnv* env, jlong value) {
1260   return box(thread, env, vmSymbols::java_lang_Long(), vmSymbols::Long_valueOf_signature(), value);
1261 }
1262 /* static jobject floatBox(JavaThread* thread, JNIEnv* env, jfloat value) {
1263   return box(thread, env, vmSymbols::java_lang_Float(), vmSymbols::Float_valueOf_signature(), value);
1264 }*/
1265 static jobject doubleBox(JavaThread* thread, JNIEnv* env, jdouble value) {
1266   return box(thread, env, vmSymbols::java_lang_Double(), vmSymbols::Double_valueOf_signature(), value);
1267 }
1268 
1269 static const JVMFlag* getVMFlag(JavaThread* thread, JNIEnv* env, jstring name) {
1270   ThreadToNativeFromVM ttnfv(thread);   // can't be in VM when we call JNI
1271   const char* flag_name = env->GetStringUTFChars(name, NULL);
1272   CHECK_JNI_EXCEPTION_(env, NULL);
1273   const JVMFlag* result = JVMFlag::find_declared_flag(flag_name);
1274   env->ReleaseStringUTFChars(name, flag_name);
1275   return result;
1276 }
1277 
1278 WB_ENTRY(jboolean, WB_IsConstantVMFlag(JNIEnv* env, jobject o, jstring name))
1279   const JVMFlag* flag = getVMFlag(thread, env, name);
1280   return (flag != NULL) && flag->is_constant_in_binary();
1281 WB_END
1282 
1283 WB_ENTRY(jboolean, WB_IsLockedVMFlag(JNIEnv* env, jobject o, jstring name))
1284   const JVMFlag* flag = getVMFlag(thread, env, name);
1285   return (flag != NULL) && !(flag->is_unlocked() || flag->is_unlocker());
1286 WB_END
1287 
1288 WB_ENTRY(jobject, WB_GetBooleanVMFlag(JNIEnv* env, jobject o, jstring name))
1289   bool result;
1290   if (GetVMFlag <JVM_FLAG_TYPE(bool)> (thread, env, name, &result)) {
1291     ThreadToNativeFromVM ttnfv(thread);   // can't be in VM when we call JNI
1292     return booleanBox(thread, env, result);
1293   }
1294   return NULL;
1295 WB_END
1296 
1297 template <typename T, int type_enum>
1298 jobject GetVMFlag_longBox(JNIEnv* env, JavaThread* thread, jstring name) {
1299   T result;
1300   if (GetVMFlag <T, type_enum> (thread, env, name, &result)) {
1301     ThreadToNativeFromVM ttnfv(thread);   // can't be in VM when we call JNI
1302     return longBox(thread, env, result);
1303   }
1304   return NULL;
1305 }
1306 
1307 WB_ENTRY(jobject, WB_GetIntVMFlag(JNIEnv* env, jobject o, jstring name))
1308   return GetVMFlag_longBox<JVM_FLAG_TYPE(int)>(env, thread, name);
1309 WB_END
1310 
1311 WB_ENTRY(jobject, WB_GetUintVMFlag(JNIEnv* env, jobject o, jstring name))
1312   return GetVMFlag_longBox<JVM_FLAG_TYPE(uint)>(env, thread, name);
1313 WB_END
1314 
1315 WB_ENTRY(jobject, WB_GetIntxVMFlag(JNIEnv* env, jobject o, jstring name))
1316   return GetVMFlag_longBox<JVM_FLAG_TYPE(intx)>(env, thread, name);
1317 WB_END
1318 
1319 WB_ENTRY(jobject, WB_GetUintxVMFlag(JNIEnv* env, jobject o, jstring name))
1320   return GetVMFlag_longBox<JVM_FLAG_TYPE(uintx)>(env, thread, name);
1321 WB_END
1322 
1323 WB_ENTRY(jobject, WB_GetUint64VMFlag(JNIEnv* env, jobject o, jstring name))
1324   return GetVMFlag_longBox<JVM_FLAG_TYPE(uint64_t)>(env, thread, name);
1325 WB_END
1326 
1327 WB_ENTRY(jobject, WB_GetSizeTVMFlag(JNIEnv* env, jobject o, jstring name))
1328   return GetVMFlag_longBox<JVM_FLAG_TYPE(size_t)>(env, thread, name);
1329 WB_END
1330 
1331 WB_ENTRY(jobject, WB_GetDoubleVMFlag(JNIEnv* env, jobject o, jstring name))
1332   double result;
1333   if (GetVMFlag <JVM_FLAG_TYPE(double)> (thread, env, name, &result)) {
1334     ThreadToNativeFromVM ttnfv(thread);   // can't be in VM when we call JNI
1335     return doubleBox(thread, env, result);
1336   }
1337   return NULL;
1338 WB_END
1339 
1340 WB_ENTRY(jstring, WB_GetStringVMFlag(JNIEnv* env, jobject o, jstring name))
1341   ccstr ccstrResult;
1342   if (GetVMFlag <JVM_FLAG_TYPE(ccstr)> (thread, env, name, &ccstrResult)) {
1343     ThreadToNativeFromVM ttnfv(thread);   // can't be in VM when we call JNI
1344     jstring result = env->NewStringUTF(ccstrResult);
1345     CHECK_JNI_EXCEPTION_(env, NULL);
1346     return result;
1347   }
1348   return NULL;
1349 WB_END
1350 
1351 WB_ENTRY(void, WB_SetBooleanVMFlag(JNIEnv* env, jobject o, jstring name, jboolean value))
1352   bool result = value == JNI_TRUE ? true : false;
1353   SetVMFlag <JVM_FLAG_TYPE(bool)> (thread, env, name, &result);
1354 WB_END
1355 
1356 WB_ENTRY(void, WB_SetIntVMFlag(JNIEnv* env, jobject o, jstring name, jlong value))
1357   int result = value;
1358   SetVMFlag <JVM_FLAG_TYPE(int)> (thread, env, name, &result);
1359 WB_END
1360 
1361 WB_ENTRY(void, WB_SetUintVMFlag(JNIEnv* env, jobject o, jstring name, jlong value))
1362   uint result = value;
1363   SetVMFlag <JVM_FLAG_TYPE(uint)> (thread, env, name, &result);
1364 WB_END
1365 
1366 WB_ENTRY(void, WB_SetIntxVMFlag(JNIEnv* env, jobject o, jstring name, jlong value))
1367   intx result = value;
1368   SetVMFlag <JVM_FLAG_TYPE(intx)> (thread, env, name, &result);
1369 WB_END
1370 
1371 WB_ENTRY(void, WB_SetUintxVMFlag(JNIEnv* env, jobject o, jstring name, jlong value))
1372   uintx result = value;
1373   SetVMFlag <JVM_FLAG_TYPE(uintx)> (thread, env, name, &result);
1374 WB_END
1375 
1376 WB_ENTRY(void, WB_SetUint64VMFlag(JNIEnv* env, jobject o, jstring name, jlong value))
1377   uint64_t result = value;
1378   SetVMFlag <JVM_FLAG_TYPE(uint64_t)> (thread, env, name, &result);
1379 WB_END
1380 
1381 WB_ENTRY(void, WB_SetSizeTVMFlag(JNIEnv* env, jobject o, jstring name, jlong value))
1382   size_t result = value;
1383   SetVMFlag <JVM_FLAG_TYPE(size_t)> (thread, env, name, &result);
1384 WB_END
1385 
1386 WB_ENTRY(void, WB_SetDoubleVMFlag(JNIEnv* env, jobject o, jstring name, jdouble value))
1387   double result = value;
1388   SetVMFlag <JVM_FLAG_TYPE(double)> (thread, env, name, &result);
1389 WB_END
1390 
1391 WB_ENTRY(void, WB_SetStringVMFlag(JNIEnv* env, jobject o, jstring name, jstring value))
1392   ThreadToNativeFromVM ttnfv(thread);   // can't be in VM when we call JNI
1393   const char* ccstrValue;
1394   if (value == NULL) {
1395     ccstrValue = NULL;
1396   }
1397   else {
1398     ccstrValue = env->GetStringUTFChars(value, NULL);
1399     CHECK_JNI_EXCEPTION(env);
1400   }
1401   {
1402     ccstr param = ccstrValue;
1403     ThreadInVMfromNative ttvfn(thread); // back to VM
1404     if (SetVMFlag <JVM_FLAG_TYPE(ccstr)> (thread, env, name, &param)) {
1405       assert(param == NULL, "old value is freed automatically and not returned");
1406     }
1407   }
1408   if (value != NULL) {
1409     env->ReleaseStringUTFChars(value, ccstrValue);
1410   }
1411 WB_END
1412 
1413 WB_ENTRY(void, WB_LockCompilation(JNIEnv* env, jobject o, jlong timeout))
1414   WhiteBox::compilation_locked = true;
1415 WB_END
1416 
1417 WB_ENTRY(void, WB_UnlockCompilation(JNIEnv* env, jobject o))
1418   MonitorLocker mo(Compilation_lock, Mutex::_no_safepoint_check_flag);
1419   WhiteBox::compilation_locked = false;
1420   mo.notify_all();
1421 WB_END
1422 
1423 WB_ENTRY(jboolean, WB_IsInStringTable(JNIEnv* env, jobject o, jstring javaString))
1424   ResourceMark rm(THREAD);
1425   int len;
1426   jchar* name = java_lang_String::as_unicode_string(JNIHandles::resolve(javaString), len, CHECK_false);
1427   return (StringTable::lookup(name, len) != NULL);
1428 WB_END
1429 
1430 WB_ENTRY(void, WB_FullGC(JNIEnv* env, jobject o))
1431   Universe::heap()->soft_ref_policy()->set_should_clear_all_soft_refs(true);
1432   Universe::heap()->collect(GCCause::_wb_full_gc);
1433 #if INCLUDE_G1GC
1434   if (UseG1GC) {
1435     // Needs to be cleared explicitly for G1
1436     Universe::heap()->soft_ref_policy()->set_should_clear_all_soft_refs(false);
1437   }
1438 #endif // INCLUDE_G1GC
1439 WB_END
1440 
1441 WB_ENTRY(void, WB_YoungGC(JNIEnv* env, jobject o))
1442   Universe::heap()->collect(GCCause::_wb_young_gc);
1443 WB_END
1444 
1445 WB_ENTRY(void, WB_ReadReservedMemory(JNIEnv* env, jobject o))
1446   // static+volatile in order to force the read to happen
1447   // (not be eliminated by the compiler)
1448   static char c;
1449   static volatile char* p;
1450 
1451   p = os::reserve_memory(os::vm_allocation_granularity());
1452   if (p == NULL) {
1453     THROW_MSG(vmSymbols::java_lang_OutOfMemoryError(), "Failed to reserve memory");
1454   }
1455 
1456   c = *p;
1457 WB_END
1458 
1459 WB_ENTRY(jstring, WB_GetCPUFeatures(JNIEnv* env, jobject o))
1460   const char* features = VM_Version::features_string();
1461   ThreadToNativeFromVM ttn(thread);
1462   jstring features_string = env->NewStringUTF(features);
1463 
1464   CHECK_JNI_EXCEPTION_(env, NULL);
1465 
1466   return features_string;
1467 WB_END
1468 
1469 CodeBlobType WhiteBox::get_blob_type(const CodeBlob* code) {
1470   guarantee(WhiteBoxAPI, "internal testing API :: WhiteBox has to be enabled");
1471   return CodeCache::get_code_heap(code)->code_blob_type();
1472 }
1473 
1474 CodeHeap* WhiteBox::get_code_heap(CodeBlobType blob_type) {
1475   guarantee(WhiteBoxAPI, "internal testing API :: WhiteBox has to be enabled");
1476   return CodeCache::get_code_heap(blob_type);
1477 }
1478 
1479 struct CodeBlobStub {
1480   CodeBlobStub(const CodeBlob* blob) :
1481       name(os::strdup(blob->name())),
1482       size(blob->size()),
1483       blob_type(static_cast<jint>(WhiteBox::get_blob_type(blob))),
1484       address((jlong) blob) { }
1485   ~CodeBlobStub() { os::free((void*) name); }
1486   const char* const name;
1487   const jint        size;
1488   const jint        blob_type;
1489   const jlong       address;
1490 };
1491 
1492 static jobjectArray codeBlob2objectArray(JavaThread* thread, JNIEnv* env, CodeBlobStub* cb) {
1493   ResourceMark rm;
1494   jclass clazz = env->FindClass(vmSymbols::java_lang_Object()->as_C_string());
1495   CHECK_JNI_EXCEPTION_(env, NULL);
1496   jobjectArray result = env->NewObjectArray(4, clazz, NULL);
1497 
1498   jstring name = env->NewStringUTF(cb->name);
1499   CHECK_JNI_EXCEPTION_(env, NULL);
1500   env->SetObjectArrayElement(result, 0, name);
1501 
1502   jobject obj = integerBox(thread, env, cb->size);
1503   CHECK_JNI_EXCEPTION_(env, NULL);
1504   env->SetObjectArrayElement(result, 1, obj);
1505 
1506   obj = integerBox(thread, env, cb->blob_type);
1507   CHECK_JNI_EXCEPTION_(env, NULL);
1508   env->SetObjectArrayElement(result, 2, obj);
1509 
1510   obj = longBox(thread, env, cb->address);
1511   CHECK_JNI_EXCEPTION_(env, NULL);
1512   env->SetObjectArrayElement(result, 3, obj);
1513 
1514   return result;
1515 }
1516 
1517 WB_ENTRY(jobjectArray, WB_GetNMethod(JNIEnv* env, jobject o, jobject method, jboolean is_osr))
1518   ResourceMark rm(THREAD);
1519   jmethodID jmid = reflected_method_to_jmid(thread, env, method);
1520   CHECK_JNI_EXCEPTION_(env, NULL);
1521   methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
1522   CompiledMethod* code = is_osr ? mh->lookup_osr_nmethod_for(InvocationEntryBci, CompLevel_none, false) : mh->code();
1523   jobjectArray result = NULL;
1524   if (code == NULL) {
1525     return result;
1526   }
1527   int comp_level = code->comp_level();
1528   int insts_size = code->insts_size();
1529 
1530   ThreadToNativeFromVM ttn(thread);
1531   jclass clazz = env->FindClass(vmSymbols::java_lang_Object()->as_C_string());
1532   CHECK_JNI_EXCEPTION_(env, NULL);
1533   result = env->NewObjectArray(5, clazz, NULL);
1534   if (result == NULL) {
1535     return result;
1536   }
1537 
1538   CodeBlobStub stub(code);
1539   jobjectArray codeBlob = codeBlob2objectArray(thread, env, &stub);
1540   CHECK_JNI_EXCEPTION_(env, NULL);
1541   env->SetObjectArrayElement(result, 0, codeBlob);
1542 
1543   jobject level = integerBox(thread, env, comp_level);
1544   CHECK_JNI_EXCEPTION_(env, NULL);
1545   env->SetObjectArrayElement(result, 1, level);
1546 
1547   jbyteArray insts = env->NewByteArray(insts_size);
1548   CHECK_JNI_EXCEPTION_(env, NULL);
1549   env->SetByteArrayRegion(insts, 0, insts_size, (jbyte*) code->insts_begin());
1550   env->SetObjectArrayElement(result, 2, insts);
1551 
1552   jobject id = integerBox(thread, env, code->compile_id());
1553   CHECK_JNI_EXCEPTION_(env, NULL);
1554   env->SetObjectArrayElement(result, 3, id);
1555 
1556   jobject entry_point = longBox(thread, env, (jlong) code->entry_point());
1557   CHECK_JNI_EXCEPTION_(env, NULL);
1558   env->SetObjectArrayElement(result, 4, entry_point);
1559 
1560   return result;
1561 WB_END
1562 
1563 CodeBlob* WhiteBox::allocate_code_blob(int size, CodeBlobType blob_type) {
1564   guarantee(WhiteBoxAPI, "internal testing API :: WhiteBox has to be enabled");
1565   BufferBlob* blob;
1566   int full_size = CodeBlob::align_code_offset(sizeof(BufferBlob));
1567   if (full_size < size) {
1568     full_size += align_up(size - full_size, oopSize);
1569   }
1570   {
1571     MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
1572     blob = (BufferBlob*) CodeCache::allocate(full_size, blob_type);
1573     if (blob != NULL) {
1574       ::new (blob) BufferBlob("WB::DummyBlob", full_size);
1575     }
1576   }
1577   // Track memory usage statistic after releasing CodeCache_lock
1578   MemoryService::track_code_cache_memory_usage();
1579   return blob;
1580 }
1581 
1582 WB_ENTRY(jlong, WB_AllocateCodeBlob(JNIEnv* env, jobject o, jint size, jint blob_type))
1583   if (size < 0) {
1584     THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
1585       err_msg("WB_AllocateCodeBlob: size is negative: " INT32_FORMAT, size));
1586   }
1587   return (jlong) WhiteBox::allocate_code_blob(size, static_cast<CodeBlobType>(blob_type));
1588 WB_END
1589 
1590 WB_ENTRY(void, WB_FreeCodeBlob(JNIEnv* env, jobject o, jlong addr))
1591   if (addr == 0) {
1592     return;
1593   }
1594   BufferBlob::free((BufferBlob*) addr);
1595 WB_END
1596 
1597 WB_ENTRY(jobjectArray, WB_GetCodeHeapEntries(JNIEnv* env, jobject o, jint blob_type))
1598   ResourceMark rm;
1599   GrowableArray<CodeBlobStub*> blobs;
1600   {
1601     MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
1602     CodeHeap* heap = WhiteBox::get_code_heap(static_cast<CodeBlobType>(blob_type));
1603     if (heap == NULL) {
1604       return NULL;
1605     }
1606     for (CodeBlob* cb = (CodeBlob*) heap->first();
1607          cb != NULL; cb = (CodeBlob*) heap->next(cb)) {
1608       CodeBlobStub* stub = NEW_RESOURCE_OBJ(CodeBlobStub);
1609       new (stub) CodeBlobStub(cb);
1610       blobs.append(stub);
1611     }
1612   }
1613   ThreadToNativeFromVM ttn(thread);
1614   jobjectArray result = NULL;
1615   jclass clazz = env->FindClass(vmSymbols::java_lang_Object()->as_C_string());
1616   CHECK_JNI_EXCEPTION_(env, NULL);
1617   result = env->NewObjectArray(blobs.length(), clazz, NULL);
1618   CHECK_JNI_EXCEPTION_(env, NULL);
1619   if (result == NULL) {
1620     return result;
1621   }
1622   int i = 0;
1623   for (GrowableArrayIterator<CodeBlobStub*> it = blobs.begin();
1624        it != blobs.end(); ++it) {
1625     jobjectArray obj = codeBlob2objectArray(thread, env, *it);
1626     CHECK_JNI_EXCEPTION_(env, NULL);
1627     env->SetObjectArrayElement(result, i, obj);
1628     CHECK_JNI_EXCEPTION_(env, NULL);
1629     ++i;
1630   }
1631   return result;
1632 WB_END
1633 
1634 WB_ENTRY(jint, WB_GetCompilationActivityMode(JNIEnv* env, jobject o))
1635   return CompileBroker::get_compilation_activity_mode();
1636 WB_END
1637 
1638 WB_ENTRY(jobjectArray, WB_GetCodeBlob(JNIEnv* env, jobject o, jlong addr))
1639   if (addr == 0) {
1640     THROW_MSG_NULL(vmSymbols::java_lang_NullPointerException(),
1641       "WB_GetCodeBlob: addr is null");
1642   }
1643   ThreadToNativeFromVM ttn(thread);
1644   CodeBlobStub stub((CodeBlob*) addr);
1645   return codeBlob2objectArray(thread, env, &stub);
1646 WB_END
1647 
1648 WB_ENTRY(jlong, WB_GetMethodData(JNIEnv* env, jobject wv, jobject method))
1649   jmethodID jmid = reflected_method_to_jmid(thread, env, method);
1650   CHECK_JNI_EXCEPTION_(env, 0);
1651   methodHandle mh(thread, Method::checked_resolve_jmethod_id(jmid));
1652   return (jlong) mh->method_data();
1653 WB_END
1654 
1655 WB_ENTRY(jlong, WB_GetThreadStackSize(JNIEnv* env, jobject o))
1656   return (jlong) thread->stack_size();
1657 WB_END
1658 
1659 WB_ENTRY(jlong, WB_GetThreadRemainingStackSize(JNIEnv* env, jobject o))
1660   return (jlong) thread->stack_overflow_state()->stack_available(
1661                    os::current_stack_pointer()) - (jlong)StackOverflow::stack_shadow_zone_size();
1662 WB_END
1663 
1664 
1665 int WhiteBox::array_bytes_to_length(size_t bytes) {
1666   return Array<u1>::bytes_to_length(bytes);
1667 }
1668 
1669 ///////////////
1670 // MetaspaceTestContext and MetaspaceTestArena
1671 WB_ENTRY(jlong, WB_CreateMetaspaceTestContext(JNIEnv* env, jobject wb, jlong commit_limit, jlong reserve_limit))
1672   metaspace::MetaspaceTestContext* context =
1673       new metaspace::MetaspaceTestContext("whitebox-metaspace-context", (size_t) commit_limit, (size_t) reserve_limit);
1674   return (jlong)p2i(context);
1675 WB_END
1676 
1677 WB_ENTRY(void, WB_DestroyMetaspaceTestContext(JNIEnv* env, jobject wb, jlong context))
1678   delete (metaspace::MetaspaceTestContext*) context;
1679 WB_END
1680 
1681 WB_ENTRY(void, WB_PurgeMetaspaceTestContext(JNIEnv* env, jobject wb, jlong context))
1682   metaspace::MetaspaceTestContext* context0 = (metaspace::MetaspaceTestContext*) context;
1683   context0->purge_area();
1684 WB_END
1685 
1686 WB_ENTRY(void, WB_PrintMetaspaceTestContext(JNIEnv* env, jobject wb, jlong context))
1687   metaspace::MetaspaceTestContext* context0 = (metaspace::MetaspaceTestContext*) context;
1688   context0->print_on(tty);
1689 WB_END
1690 
1691 WB_ENTRY(jlong, WB_GetTotalCommittedWordsInMetaspaceTestContext(JNIEnv* env, jobject wb, jlong context))
1692   metaspace::MetaspaceTestContext* context0 = (metaspace::MetaspaceTestContext*) context;
1693   return context0->committed_words();
1694 WB_END
1695 
1696 WB_ENTRY(jlong, WB_GetTotalUsedWordsInMetaspaceTestContext(JNIEnv* env, jobject wb, jlong context))
1697   metaspace::MetaspaceTestContext* context0 = (metaspace::MetaspaceTestContext*) context;
1698   return context0->used_words();
1699 WB_END
1700 
1701 WB_ENTRY(jlong, WB_CreateArenaInTestContext(JNIEnv* env, jobject wb, jlong context, jboolean is_micro))
1702   const Metaspace::MetaspaceType type = is_micro ? Metaspace::ReflectionMetaspaceType : Metaspace::StandardMetaspaceType;
1703   metaspace::MetaspaceTestContext* context0 = (metaspace::MetaspaceTestContext*) context;
1704   return (jlong)p2i(context0->create_arena(type));
1705 WB_END
1706 
1707 WB_ENTRY(void, WB_DestroyMetaspaceTestArena(JNIEnv* env, jobject wb, jlong arena))
1708   delete (metaspace::MetaspaceTestArena*) arena;
1709 WB_END
1710 
1711 WB_ENTRY(jlong, WB_AllocateFromMetaspaceTestArena(JNIEnv* env, jobject wb, jlong arena, jlong word_size))
1712   metaspace::MetaspaceTestArena* arena0 = (metaspace::MetaspaceTestArena*) arena;
1713   MetaWord* p = arena0->allocate((size_t) word_size);
1714   return (jlong)p2i(p);
1715 WB_END
1716 
1717 WB_ENTRY(void, WB_DeallocateToMetaspaceTestArena(JNIEnv* env, jobject wb, jlong arena, jlong p, jlong word_size))
1718   metaspace::MetaspaceTestArena* arena0 = (metaspace::MetaspaceTestArena*) arena;
1719   arena0->deallocate((MetaWord*)p, (size_t) word_size);
1720 WB_END
1721 
1722 WB_ENTRY(jlong, WB_GetMaxMetaspaceAllocationSize(JNIEnv* env, jobject wb))
1723   return (jlong) Metaspace::max_allocation_word_size() * BytesPerWord;
1724 WB_END
1725 
1726 //////////////
1727 
1728 WB_ENTRY(jlong, WB_AllocateMetaspace(JNIEnv* env, jobject wb, jobject class_loader, jlong size))
1729   if (size < 0) {
1730     THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
1731         err_msg("WB_AllocateMetaspace: size is negative: " JLONG_FORMAT, size));
1732   }
1733 
1734   oop class_loader_oop = JNIHandles::resolve(class_loader);
1735   ClassLoaderData* cld = class_loader_oop != NULL
1736       ? java_lang_ClassLoader::loader_data_acquire(class_loader_oop)
1737       : ClassLoaderData::the_null_class_loader_data();
1738 
1739   void* metadata = MetadataFactory::new_array<u1>(cld, WhiteBox::array_bytes_to_length((size_t)size), thread);
1740 
1741   return (jlong)(uintptr_t)metadata;
1742 WB_END
1743 
1744 WB_ENTRY(void, WB_DefineModule(JNIEnv* env, jobject o, jobject module, jboolean is_open,
1745                                 jstring version, jstring location, jobjectArray packages))
1746   Handle h_module (THREAD, JNIHandles::resolve(module));
1747   Modules::define_module(h_module, is_open, version, location, packages, CHECK);
1748 WB_END
1749 
1750 WB_ENTRY(void, WB_AddModuleExports(JNIEnv* env, jobject o, jobject from_module, jstring package, jobject to_module))
1751   Handle h_from_module (THREAD, JNIHandles::resolve(from_module));
1752   Handle h_to_module (THREAD, JNIHandles::resolve(to_module));
1753   Modules::add_module_exports_qualified(h_from_module, package, h_to_module, CHECK);
1754 WB_END
1755 
1756 WB_ENTRY(void, WB_AddModuleExportsToAllUnnamed(JNIEnv* env, jobject o, jclass module, jstring package))
1757   Handle h_module (THREAD, JNIHandles::resolve(module));
1758   Modules::add_module_exports_to_all_unnamed(h_module, package, CHECK);
1759 WB_END
1760 
1761 WB_ENTRY(void, WB_AddModuleExportsToAll(JNIEnv* env, jobject o, jclass module, jstring package))
1762   Handle h_module (THREAD, JNIHandles::resolve(module));
1763   Modules::add_module_exports(h_module, package, Handle(), CHECK);
1764 WB_END
1765 
1766 WB_ENTRY(void, WB_AddReadsModule(JNIEnv* env, jobject o, jobject from_module, jobject source_module))
1767   Handle h_from_module (THREAD, JNIHandles::resolve(from_module));
1768   Handle h_source_module (THREAD, JNIHandles::resolve(source_module));
1769   Modules::add_reads_module(h_from_module, h_source_module, CHECK);
1770 WB_END
1771 
1772 WB_ENTRY(jlong, WB_IncMetaspaceCapacityUntilGC(JNIEnv* env, jobject wb, jlong inc))
1773   if (inc < 0) {
1774     THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
1775         err_msg("WB_IncMetaspaceCapacityUntilGC: inc is negative: " JLONG_FORMAT, inc));
1776   }
1777 
1778   jlong max_size_t = (jlong) ((size_t) -1);
1779   if (inc > max_size_t) {
1780     THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
1781         err_msg("WB_IncMetaspaceCapacityUntilGC: inc does not fit in size_t: " JLONG_FORMAT, inc));
1782   }
1783 
1784   size_t new_cap_until_GC = 0;
1785   size_t aligned_inc = align_down((size_t) inc, Metaspace::commit_alignment());
1786   bool success = MetaspaceGC::inc_capacity_until_GC(aligned_inc, &new_cap_until_GC);
1787   if (!success) {
1788     THROW_MSG_0(vmSymbols::java_lang_IllegalStateException(),
1789                 "WB_IncMetaspaceCapacityUntilGC: could not increase capacity until GC "
1790                 "due to contention with another thread");
1791   }
1792   return (jlong) new_cap_until_GC;
1793 WB_END
1794 
1795 WB_ENTRY(jlong, WB_MetaspaceCapacityUntilGC(JNIEnv* env, jobject wb))
1796   return (jlong) MetaspaceGC::capacity_until_GC();
1797 WB_END
1798 
1799 // The function is only valid when CDS is available.
1800 WB_ENTRY(jlong, WB_MetaspaceSharedRegionAlignment(JNIEnv* env, jobject wb))
1801 #if INCLUDE_CDS
1802   return (jlong)MetaspaceShared::core_region_alignment();
1803 #else
1804   ShouldNotReachHere();
1805   return 0L;
1806 #endif
1807 WB_END
1808 
1809 WB_ENTRY(jboolean, WB_IsMonitorInflated(JNIEnv* env, jobject wb, jobject obj))
1810   oop obj_oop = JNIHandles::resolve(obj);
1811   return (jboolean) obj_oop->mark().has_monitor();
1812 WB_END
1813 
1814 WB_ENTRY(jboolean, WB_DeflateIdleMonitors(JNIEnv* env, jobject wb))
1815   log_info(monitorinflation)("WhiteBox initiated DeflateIdleMonitors");
1816   return ObjectSynchronizer::request_deflate_idle_monitors();
1817 WB_END
1818 
1819 WB_ENTRY(void, WB_ForceSafepoint(JNIEnv* env, jobject wb))
1820   VM_ForceSafepoint force_safepoint_op;
1821   VMThread::execute(&force_safepoint_op);
1822 WB_END
1823 
1824 WB_ENTRY(jlong, WB_GetConstantPool(JNIEnv* env, jobject wb, jclass klass))
1825   InstanceKlass* ik = InstanceKlass::cast(java_lang_Class::as_Klass(JNIHandles::resolve(klass)));
1826   return (jlong) ik->constants();
1827 WB_END
1828 
1829 WB_ENTRY(jint, WB_GetConstantPoolCacheIndexTag(JNIEnv* env, jobject wb))
1830   return ConstantPool::CPCACHE_INDEX_TAG;
1831 WB_END
1832 
1833 WB_ENTRY(jint, WB_GetConstantPoolCacheLength(JNIEnv* env, jobject wb, jclass klass))
1834   InstanceKlass* ik = InstanceKlass::cast(java_lang_Class::as_Klass(JNIHandles::resolve(klass)));
1835   ConstantPool* cp = ik->constants();
1836   if (cp->cache() == NULL) {
1837       return -1;
1838   }
1839   return cp->cache()->length();
1840 WB_END
1841 
1842 WB_ENTRY(jint, WB_ConstantPoolRemapInstructionOperandFromCache(JNIEnv* env, jobject wb, jclass klass, jint index))
1843   InstanceKlass* ik = InstanceKlass::cast(java_lang_Class::as_Klass(JNIHandles::resolve(klass)));
1844   ConstantPool* cp = ik->constants();
1845   if (cp->cache() == NULL) {
1846     THROW_MSG_0(vmSymbols::java_lang_IllegalStateException(), "Constant pool does not have a cache");
1847   }
1848   jint cpci = index;
1849   jint cpciTag = ConstantPool::CPCACHE_INDEX_TAG;
1850   if (cpciTag > cpci || cpci >= cp->cache()->length() + cpciTag) {
1851     THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Constant pool cache index is out of range");
1852   }
1853   jint cpi = cp->remap_instruction_operand_from_cache(cpci);
1854   return cpi;
1855 WB_END
1856 
1857 WB_ENTRY(jint, WB_ConstantPoolEncodeIndyIndex(JNIEnv* env, jobject wb, jint index))
1858   return ConstantPool::encode_invokedynamic_index(index);
1859 WB_END
1860 
1861 WB_ENTRY(void, WB_ClearInlineCaches(JNIEnv* env, jobject wb, jboolean preserve_static_stubs))
1862   VM_ClearICs clear_ics(preserve_static_stubs == JNI_TRUE);
1863   VMThread::execute(&clear_ics);
1864 WB_END
1865 
1866 template <typename T>
1867 static bool GetMethodOption(JavaThread* thread, JNIEnv* env, jobject method, jstring name, T* value) {
1868   assert(value != NULL, "sanity");
1869   if (method == NULL || name == NULL) {
1870     return false;
1871   }
1872   jmethodID jmid = reflected_method_to_jmid(thread, env, method);
1873   CHECK_JNI_EXCEPTION_(env, false);
1874   methodHandle mh(thread, Method::checked_resolve_jmethod_id(jmid));
1875   // can't be in VM when we call JNI
1876   ThreadToNativeFromVM ttnfv(thread);
1877   const char* flag_name = env->GetStringUTFChars(name, NULL);
1878   CHECK_JNI_EXCEPTION_(env, false);
1879   enum CompileCommand option = CompilerOracle::string_to_option(flag_name);
1880   env->ReleaseStringUTFChars(name, flag_name);
1881   if (option == CompileCommand::Unknown) {
1882     return false;
1883   }
1884   if (!CompilerOracle::option_matches_type(option, *value)) {
1885     return false;
1886   }
1887   return CompilerOracle::has_option_value(mh, option, *value);
1888 }
1889 
1890 WB_ENTRY(jobject, WB_GetMethodBooleaneOption(JNIEnv* env, jobject wb, jobject method, jstring name))
1891   bool result;
1892   if (GetMethodOption<bool> (thread, env, method, name, &result)) {
1893     // can't be in VM when we call JNI
1894     ThreadToNativeFromVM ttnfv(thread);
1895     return booleanBox(thread, env, result);
1896   }
1897   return NULL;
1898 WB_END
1899 
1900 WB_ENTRY(jobject, WB_GetMethodIntxOption(JNIEnv* env, jobject wb, jobject method, jstring name))
1901   intx result;
1902   if (GetMethodOption <intx> (thread, env, method, name, &result)) {
1903     // can't be in VM when we call JNI
1904     ThreadToNativeFromVM ttnfv(thread);
1905     return longBox(thread, env, result);
1906   }
1907   return NULL;
1908 WB_END
1909 
1910 WB_ENTRY(jobject, WB_GetMethodUintxOption(JNIEnv* env, jobject wb, jobject method, jstring name))
1911   uintx result;
1912   if (GetMethodOption <uintx> (thread, env, method, name, &result)) {
1913     // can't be in VM when we call JNI
1914     ThreadToNativeFromVM ttnfv(thread);
1915     return longBox(thread, env, result);
1916   }
1917   return NULL;
1918 WB_END
1919 
1920 WB_ENTRY(jobject, WB_GetMethodDoubleOption(JNIEnv* env, jobject wb, jobject method, jstring name))
1921   double result;
1922   if (GetMethodOption <double> (thread, env, method, name, &result)) {
1923     // can't be in VM when we call JNI
1924     ThreadToNativeFromVM ttnfv(thread);
1925     return doubleBox(thread, env, result);
1926   }
1927   return NULL;
1928 WB_END
1929 
1930 WB_ENTRY(jobject, WB_GetMethodStringOption(JNIEnv* env, jobject wb, jobject method, jstring name))
1931   ccstr ccstrResult;
1932   if (GetMethodOption <ccstr> (thread, env, method, name, &ccstrResult)) {
1933     // can't be in VM when we call JNI
1934     ThreadToNativeFromVM ttnfv(thread);
1935     jstring result = env->NewStringUTF(ccstrResult);
1936     CHECK_JNI_EXCEPTION_(env, NULL);
1937     return result;
1938   }
1939   return NULL;
1940 WB_END
1941 
1942 WB_ENTRY(jobject, WB_GetDefaultArchivePath(JNIEnv* env, jobject wb))
1943   const char* p = Arguments::get_default_shared_archive_path();
1944   ThreadToNativeFromVM ttn(thread);
1945   jstring path_string = env->NewStringUTF(p);
1946 
1947   CHECK_JNI_EXCEPTION_(env, NULL);
1948 
1949   return path_string;
1950 WB_END
1951 
1952 WB_ENTRY(jboolean, WB_IsSharingEnabled(JNIEnv* env, jobject wb))
1953   return UseSharedSpaces;
1954 WB_END
1955 
1956 WB_ENTRY(jint, WB_GetCDSGenericHeaderMinVersion(JNIEnv* env, jobject wb))
1957 #if INCLUDE_CDS
1958   return (jint)CDS_GENERIC_HEADER_SUPPORTED_MIN_VERSION;
1959 #else
1960   ShouldNotReachHere();
1961   return (jint)-1;
1962 #endif
1963 WB_END
1964 
1965 WB_ENTRY(jint, WB_GetCDSCurrentVersion(JNIEnv* env, jobject wb))
1966 #if INCLUDE_CDS
1967   return (jint)CURRENT_CDS_ARCHIVE_VERSION;
1968 #else
1969   ShouldNotReachHere();
1970   return (jint)-1;
1971 #endif
1972 WB_END
1973 
1974 WB_ENTRY(jboolean, WB_CDSMemoryMappingFailed(JNIEnv* env, jobject wb))
1975   return FileMapInfo::memory_mapping_failed();
1976 WB_END
1977 
1978 WB_ENTRY(jboolean, WB_IsShared(JNIEnv* env, jobject wb, jobject obj))
1979   oop obj_oop = JNIHandles::resolve(obj);
1980   return Universe::heap()->is_archived_object(obj_oop);
1981 WB_END
1982 
1983 WB_ENTRY(jboolean, WB_IsSharedInternedString(JNIEnv* env, jobject wb, jobject str))
1984   ResourceMark rm(THREAD);
1985   oop str_oop = JNIHandles::resolve(str);
1986   int length;
1987   jchar* chars = java_lang_String::as_unicode_string(str_oop, length, CHECK_(false));
1988   return StringTable::lookup_shared(chars, length) == str_oop;
1989 WB_END
1990 
1991 WB_ENTRY(jboolean, WB_IsSharedClass(JNIEnv* env, jobject wb, jclass clazz))
1992   return (jboolean)MetaspaceShared::is_in_shared_metaspace(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz)));
1993 WB_END
1994 
1995 WB_ENTRY(jboolean, WB_AreSharedStringsMapped(JNIEnv* env))
1996   return ArchiveHeapLoader::closed_regions_mapped();
1997 WB_END
1998 
1999 WB_ENTRY(jobject, WB_GetResolvedReferences(JNIEnv* env, jobject wb, jclass clazz))
2000   Klass *k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz));
2001   if (k->is_instance_klass()) {
2002     InstanceKlass *ik = InstanceKlass::cast(k);
2003     ConstantPool *cp = ik->constants();
2004     objArrayOop refs =  cp->resolved_references();
2005     return (jobject)JNIHandles::make_local(THREAD, refs);
2006   } else {
2007     return NULL;
2008   }
2009 WB_END
2010 
2011 WB_ENTRY(void, WB_LinkClass(JNIEnv* env, jobject wb, jclass clazz))
2012   Klass *k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz));
2013   if (!k->is_instance_klass()) {
2014     return;
2015   }
2016   InstanceKlass *ik = InstanceKlass::cast(k);
2017   ik->link_class(THREAD); // may throw verification error
2018 WB_END
2019 
2020 WB_ENTRY(jboolean, WB_AreOpenArchiveHeapObjectsMapped(JNIEnv* env))
2021   return ArchiveHeapLoader::open_regions_mapped();
2022 WB_END
2023 
2024 WB_ENTRY(jboolean, WB_IsCDSIncluded(JNIEnv* env))
2025 #if INCLUDE_CDS
2026   return true;
2027 #else
2028   return false;
2029 #endif // INCLUDE_CDS
2030 WB_END
2031 
2032 WB_ENTRY(jboolean, WB_isC2OrJVMCIIncluded(JNIEnv* env))
2033 #if COMPILER2_OR_JVMCI
2034   return true;
2035 #else
2036   return false;
2037 #endif
2038 WB_END
2039 
2040 WB_ENTRY(jboolean, WB_IsJVMCISupportedByGC(JNIEnv* env))
2041 #if INCLUDE_JVMCI
2042   return JVMCIGlobals::gc_supports_jvmci();
2043 #else
2044   return false;
2045 #endif
2046 WB_END
2047 
2048 WB_ENTRY(jboolean, WB_CanWriteJavaHeapArchive(JNIEnv* env))
2049   return HeapShared::can_write();
2050 WB_END
2051 
2052 
2053 WB_ENTRY(jboolean, WB_IsJFRIncluded(JNIEnv* env))
2054 #if INCLUDE_JFR
2055   return true;
2056 #else
2057   return false;
2058 #endif // INCLUDE_JFR
2059 WB_END
2060 
2061 WB_ENTRY(jboolean, WB_IsDTraceIncluded(JNIEnv* env))
2062 #if defined(DTRACE_ENABLED)
2063   return true;
2064 #else
2065   return false;
2066 #endif // DTRACE_ENABLED
2067 WB_END
2068 
2069 #if INCLUDE_CDS
2070 
2071 WB_ENTRY(jint, WB_GetCDSOffsetForName(JNIEnv* env, jobject o, jstring name))
2072   ResourceMark rm;
2073   char* c_name = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(name));
2074   jint result = (jint)CDSConstants::get_cds_offset(c_name);
2075   return result;
2076 WB_END
2077 
2078 WB_ENTRY(jint, WB_GetCDSConstantForName(JNIEnv* env, jobject o, jstring name))
2079   ResourceMark rm;
2080   char* c_name = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(name));
2081   jint result = (jint)CDSConstants::get_cds_constant(c_name);
2082   return result;
2083 WB_END
2084 
2085 #endif // INCLUDE_CDS
2086 
2087 WB_ENTRY(jboolean, WB_HandshakeReadMonitors(JNIEnv* env, jobject wb, jobject thread_handle))
2088   class ReadMonitorsClosure : public HandshakeClosure {
2089     jboolean _executed;
2090 
2091     void do_thread(Thread* th) {
2092       JavaThread* jt = JavaThread::cast(th);
2093       ResourceMark rm;
2094 
2095       GrowableArray<MonitorInfo*>* info = new GrowableArray<MonitorInfo*>();
2096 
2097       if (!jt->has_last_Java_frame()) {
2098         return;
2099       }
2100       RegisterMap rmap(jt,
2101                        RegisterMap::UpdateMap::include,
2102                        RegisterMap::ProcessFrames::include,
2103                        RegisterMap::WalkContinuation::skip);
2104       for (javaVFrame* vf = jt->last_java_vframe(&rmap); vf != NULL; vf = vf->java_sender()) {
2105         GrowableArray<MonitorInfo*> *monitors = vf->monitors();
2106         if (monitors != NULL) {
2107           int len = monitors->length();
2108           // Walk monitors youngest to oldest
2109           for (int i = len - 1; i >= 0; i--) {
2110             MonitorInfo* mon_info = monitors->at(i);
2111             if (mon_info->eliminated()) continue;
2112             oop owner = mon_info->owner();
2113             if (owner != NULL) {
2114               info->append(mon_info);
2115             }
2116           }
2117         }
2118       }
2119       _executed = true;
2120     }
2121 
2122    public:
2123     ReadMonitorsClosure() : HandshakeClosure("WB_HandshakeReadMonitors"), _executed(false) {}
2124     jboolean executed() const { return _executed; }
2125   };
2126 
2127   ReadMonitorsClosure rmc;
2128   if (thread_handle != NULL) {
2129     ThreadsListHandle tlh;
2130     JavaThread* target = nullptr;
2131     bool is_alive = tlh.cv_internal_thread_to_JavaThread(thread_handle, &target, NULL);
2132     if (is_alive) {
2133       Handshake::execute(&rmc, &tlh, target);
2134     }
2135   }
2136   return rmc.executed();
2137 WB_END
2138 
2139 WB_ENTRY(jint, WB_HandshakeWalkStack(JNIEnv* env, jobject wb, jobject thread_handle, jboolean all_threads))
2140   class TraceSelfClosure : public HandshakeClosure {
2141     jint _num_threads_completed;
2142 
2143     void do_thread(Thread* th) {
2144       JavaThread* jt = JavaThread::cast(th);
2145       ResourceMark rm;
2146 
2147       jt->print_on(tty);
2148       jt->print_stack_on(tty);
2149       tty->cr();
2150       Atomic::inc(&_num_threads_completed);
2151     }
2152 
2153   public:
2154     TraceSelfClosure(Thread* thread) : HandshakeClosure("WB_TraceSelf"), _num_threads_completed(0) {}
2155 
2156     jint num_threads_completed() const { return _num_threads_completed; }
2157   };
2158   TraceSelfClosure tsc(Thread::current());
2159 
2160   if (all_threads) {
2161     Handshake::execute(&tsc);
2162   } else if (thread_handle != NULL) {
2163     ThreadsListHandle tlh;
2164     JavaThread* target = nullptr;
2165     bool is_alive = tlh.cv_internal_thread_to_JavaThread(thread_handle, &target, NULL);
2166     if (is_alive) {
2167       Handshake::execute(&tsc, &tlh, target);
2168     }
2169   }
2170   return tsc.num_threads_completed();
2171 WB_END
2172 
2173 WB_ENTRY(void, WB_AsyncHandshakeWalkStack(JNIEnv* env, jobject wb, jobject thread_handle))
2174   class TraceSelfClosure : public AsyncHandshakeClosure {
2175     JavaThread* _self;
2176     void do_thread(Thread* th) {
2177       assert(th->is_Java_thread(), "sanity");
2178       // AsynchHandshake handshakes are only executed by target.
2179       assert(_self == th, "Must be");
2180       assert(Thread::current() == th, "Must be");
2181       JavaThread* jt = JavaThread::cast(th);
2182       ResourceMark rm;
2183       jt->print_on(tty);
2184       jt->print_stack_on(tty);
2185       tty->cr();
2186     }
2187 
2188   public:
2189     TraceSelfClosure(JavaThread* self_target) : AsyncHandshakeClosure("WB_TraceSelf"), _self(self_target) {}
2190   };
2191   if (thread_handle != NULL) {
2192     ThreadsListHandle tlh;
2193     JavaThread* target = nullptr;
2194     bool is_alive = tlh.cv_internal_thread_to_JavaThread(thread_handle, &target, NULL);
2195     if (is_alive) {
2196       TraceSelfClosure* tsc = new TraceSelfClosure(target);
2197       Handshake::execute(tsc, target);
2198     }
2199   }
2200 WB_END
2201 
2202 static volatile int _emulated_lock = 0;
2203 
2204 WB_ENTRY(void, WB_LockAndBlock(JNIEnv* env, jobject wb, jboolean suspender))
2205   JavaThread* self = JavaThread::current();
2206 
2207   {
2208     // Before trying to acquire the lock transition into a safepoint safe state.
2209     // Otherwise if either suspender or suspendee blocks for a safepoint
2210     // in ~ThreadBlockInVM the other one could loop forever trying to acquire
2211     // the lock without allowing the safepoint to progress.
2212     ThreadBlockInVM tbivm(self);
2213 
2214     // We will deadlock here if we are 'suspender' and 'suspendee'
2215     // suspended in ~ThreadBlockInVM. This verifies we only suspend
2216     // at the right place.
2217     while (Atomic::cmpxchg(&_emulated_lock, 0, 1) != 0) {}
2218     assert(_emulated_lock == 1, "Must be locked");
2219 
2220     // Sleep much longer in suspendee to force situation where
2221     // 'suspender' is waiting above to acquire lock.
2222     os::naked_short_sleep(suspender ? 1 : 10);
2223   }
2224   Atomic::store(&_emulated_lock, 0);
2225 WB_END
2226 
2227 // Some convenience methods to deal with objects from java
2228 int WhiteBox::offset_for_field(const char* field_name, oop object,
2229     Symbol* signature_symbol) {
2230   assert(field_name != NULL && strlen(field_name) > 0, "Field name not valid");
2231 
2232   //Get the class of our object
2233   Klass* arg_klass = object->klass();
2234   //Turn it into an instance-klass
2235   InstanceKlass* ik = InstanceKlass::cast(arg_klass);
2236 
2237   //Create symbols to look for in the class
2238   TempNewSymbol name_symbol = SymbolTable::new_symbol(field_name);
2239 
2240   //To be filled in with an offset of the field we're looking for
2241   fieldDescriptor fd;
2242 
2243   Klass* res = ik->find_field(name_symbol, signature_symbol, &fd);
2244   if (res == NULL) {
2245     tty->print_cr("Invalid layout of %s at %s", ik->external_name(),
2246         name_symbol->as_C_string());
2247     vm_exit_during_initialization("Invalid layout of preloaded class: use -Xlog:class+load=info to see the origin of the problem class");
2248   }
2249 
2250   //fetch the field at the offset we've found
2251   int dest_offset = fd.offset();
2252 
2253   return dest_offset;
2254 }
2255 
2256 
2257 const char* WhiteBox::lookup_jstring(const char* field_name, oop object) {
2258   int offset = offset_for_field(field_name, object,
2259       vmSymbols::string_signature());
2260   oop string = object->obj_field(offset);
2261   if (string == NULL) {
2262     return NULL;
2263   }
2264   const char* ret = java_lang_String::as_utf8_string(string);
2265   return ret;
2266 }
2267 
2268 bool WhiteBox::lookup_bool(const char* field_name, oop object) {
2269   int offset =
2270       offset_for_field(field_name, object, vmSymbols::bool_signature());
2271   bool ret = (object->bool_field(offset) == JNI_TRUE);
2272   return ret;
2273 }
2274 
2275 void WhiteBox::register_methods(JNIEnv* env, jclass wbclass, JavaThread* thread, JNINativeMethod* method_array, int method_count) {
2276   ResourceMark rm;
2277   Klass* klass = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(wbclass));
2278   const char* klass_name = klass->external_name();
2279 
2280   ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
2281 
2282   //  one by one registration natives for exception catching
2283   jclass no_such_method_error_klass = env->FindClass(vmSymbols::java_lang_NoSuchMethodError()->as_C_string());
2284   CHECK_JNI_EXCEPTION(env);
2285   for (int i = 0, n = method_count; i < n; ++i) {
2286     // Skip dummy entries
2287     if (method_array[i].fnPtr == NULL) continue;
2288     if (env->RegisterNatives(wbclass, &method_array[i], 1) != 0) {
2289       jthrowable throwable_obj = env->ExceptionOccurred();
2290       if (throwable_obj != NULL) {
2291         env->ExceptionClear();
2292         if (env->IsInstanceOf(throwable_obj, no_such_method_error_klass)) {
2293           // NoSuchMethodError is thrown when a method can't be found or a method is not native.
2294           // Ignoring the exception since it is not preventing use of other WhiteBox methods.
2295           tty->print_cr("Warning: 'NoSuchMethodError' on register of %s::%s%s",
2296               klass_name, method_array[i].name, method_array[i].signature);
2297         }
2298       } else {
2299         // Registration failed unexpectedly.
2300         tty->print_cr("Warning: unexpected error on register of %s::%s%s. All methods will be unregistered",
2301             klass_name, method_array[i].name, method_array[i].signature);
2302         env->UnregisterNatives(wbclass);
2303         break;
2304       }
2305     }
2306   }
2307 }
2308 
2309 WB_ENTRY(jint, WB_AddCompilerDirective(JNIEnv* env, jobject o, jstring compDirect))
2310   // can't be in VM when we call JNI
2311   ThreadToNativeFromVM ttnfv(thread);
2312   const char* dir = env->GetStringUTFChars(compDirect, NULL);
2313   CHECK_JNI_EXCEPTION_(env, 0);
2314   int ret;
2315   {
2316     ThreadInVMfromNative ttvfn(thread); // back to VM
2317     ret = DirectivesParser::parse_string(dir, tty);
2318   }
2319   env->ReleaseStringUTFChars(compDirect, dir);
2320   // -1 for error parsing directive. Return 0 as number of directives added.
2321   if (ret == -1) {
2322     ret = 0;
2323   }
2324   return (jint) ret;
2325 WB_END
2326 
2327 WB_ENTRY(void, WB_RemoveCompilerDirective(JNIEnv* env, jobject o, jint count))
2328   DirectivesStack::pop(count);
2329 WB_END
2330 
2331 // Checks that the library libfile has the noexecstack bit set.
2332 WB_ENTRY(jboolean, WB_CheckLibSpecifiesNoexecstack(JNIEnv* env, jobject o, jstring libfile))
2333   jboolean ret = false;
2334 #ifdef LINUX
2335   // Can't be in VM when we call JNI.
2336   ThreadToNativeFromVM ttnfv(thread);
2337   const char* lf = env->GetStringUTFChars(libfile, NULL);
2338   CHECK_JNI_EXCEPTION_(env, 0);
2339   ret = (jboolean) ElfFile::specifies_noexecstack(lf);
2340   env->ReleaseStringUTFChars(libfile, lf);
2341 #endif
2342   return ret;
2343 WB_END
2344 
2345 WB_ENTRY(jboolean, WB_IsContainerized(JNIEnv* env, jobject o))
2346   LINUX_ONLY(return OSContainer::is_containerized();)
2347   return false;
2348 WB_END
2349 
2350 WB_ENTRY(jint, WB_ValidateCgroup(JNIEnv* env,
2351                                     jobject o,
2352                                     jstring proc_cgroups,
2353                                     jstring proc_self_cgroup,
2354                                     jstring proc_self_mountinfo))
2355   jint ret = 0;
2356 #ifdef LINUX
2357   ThreadToNativeFromVM ttnfv(thread);
2358   const char* p_cgroups = env->GetStringUTFChars(proc_cgroups, NULL);
2359   CHECK_JNI_EXCEPTION_(env, 0);
2360   const char* p_s_cgroup = env->GetStringUTFChars(proc_self_cgroup, NULL);
2361   CHECK_JNI_EXCEPTION_(env, 0);
2362   const char* p_s_mountinfo = env->GetStringUTFChars(proc_self_mountinfo, NULL);
2363   CHECK_JNI_EXCEPTION_(env, 0);
2364   u1 cg_type_flags = 0;
2365   // This sets cg_type_flags
2366   WhiteBox::validate_cgroup(p_cgroups, p_s_cgroup, p_s_mountinfo, &cg_type_flags);
2367   ret = (jint)cg_type_flags;
2368   env->ReleaseStringUTFChars(proc_cgroups, p_cgroups);
2369   env->ReleaseStringUTFChars(proc_self_cgroup, p_s_cgroup);
2370   env->ReleaseStringUTFChars(proc_self_mountinfo, p_s_mountinfo);
2371 #endif
2372   return ret;
2373 WB_END
2374 
2375 WB_ENTRY(void, WB_PrintOsInfo(JNIEnv* env, jobject o))
2376   os::print_os_info(tty);
2377 WB_END
2378 
2379 // Elf decoder
2380 WB_ENTRY(void, WB_DisableElfSectionCache(JNIEnv* env))
2381 #if !defined(_WINDOWS) && !defined(__APPLE__) && !defined(_AIX)
2382   ElfFile::_do_not_cache_elf_section = true;
2383 #endif
2384 WB_END
2385 
2386 WB_ENTRY(jlong, WB_ResolvedMethodItemsCount(JNIEnv* env, jobject o))
2387   return (jlong) ResolvedMethodTable::items_count();
2388 WB_END
2389 
2390 WB_ENTRY(jint, WB_ProtectionDomainRemovedCount(JNIEnv* env, jobject o))
2391   return (jint) ProtectionDomainCacheTable::removed_entries_count();
2392 WB_END
2393 
2394 WB_ENTRY(jint, WB_GetKlassMetadataSize(JNIEnv* env, jobject wb, jclass mirror))
2395   Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve(mirror));
2396   // Return size in bytes.
2397   return k->size() * wordSize;
2398 WB_END
2399 
2400 // See test/hotspot/jtreg/runtime/Thread/ThreadObjAccessAtExit.java.
2401 // It explains how the thread's priority field is used for test state coordination.
2402 //
2403 WB_ENTRY(void, WB_CheckThreadObjOfTerminatingThread(JNIEnv* env, jobject wb, jobject target_handle))
2404   oop target_oop = JNIHandles::resolve_non_null(target_handle);
2405   jlong tid = java_lang_Thread::thread_id(target_oop);
2406   JavaThread* target = java_lang_Thread::thread(target_oop);
2407 
2408   // Grab a ThreadsListHandle to protect the target thread whilst terminating
2409   ThreadsListHandle tlh;
2410 
2411   // Look up the target thread by tid to ensure it is present
2412   JavaThread* t = tlh.list()->find_JavaThread_from_java_tid(tid);
2413   if (t == NULL) {
2414     THROW_MSG(vmSymbols::java_lang_RuntimeException(), "Target thread not found in ThreadsList!");
2415   }
2416 
2417   tty->print_cr("WB_CheckThreadObjOfTerminatingThread: target thread is protected");
2418   // Allow target to terminate by boosting priority
2419   java_lang_Thread::set_priority(t->threadObj(), ThreadPriority(NormPriority + 1));
2420 
2421   // Now wait for the target to terminate
2422   while (!target->is_terminated()) {
2423     ThreadBlockInVM tbivm(thread);  // just in case target is involved in a safepoint
2424     os::naked_short_sleep(0);
2425   }
2426 
2427   tty->print_cr("WB_CheckThreadObjOfTerminatingThread: target thread is terminated");
2428 
2429   // Now release the GC inducing thread - we have to re-resolve the external oop that
2430   // was passed in as GC may have occurred and we don't know if we can trust t->threadObj() now.
2431   oop original = JNIHandles::resolve_non_null(target_handle);
2432   java_lang_Thread::set_priority(original, ThreadPriority(NormPriority + 2));
2433 
2434   tty->print_cr("WB_CheckThreadObjOfTerminatingThread: GC has been initiated - checking threadObj:");
2435 
2436   // The Java code should be creating garbage and triggering GC, which would potentially move
2437   // the threadObj oop. If the exiting thread is properly protected then its threadObj should
2438   // remain valid and equal to our initial target_handle. Loop a few times to give GC a chance to
2439   // kick in.
2440   for (int i = 0; i < 5; i++) {
2441     oop original = JNIHandles::resolve_non_null(target_handle);
2442     oop current = t->threadObj();
2443     if (original != current) {
2444       tty->print_cr("WB_CheckThreadObjOfTerminatingThread: failed comparison on iteration %d", i);
2445       THROW_MSG(vmSymbols::java_lang_RuntimeException(), "Target thread oop has changed!");
2446     } else {
2447       tty->print_cr("WB_CheckThreadObjOfTerminatingThread: successful comparison on iteration %d", i);
2448       ThreadBlockInVM tbivm(thread);
2449       os::naked_short_sleep(50);
2450     }
2451   }
2452 WB_END
2453 
2454 WB_ENTRY(void, WB_VerifyFrames(JNIEnv* env, jobject wb, jboolean log, jboolean update_map))
2455   ResourceMark rm; // for verify
2456   stringStream st;
2457   for (StackFrameStream fst(JavaThread::current(), update_map, true); !fst.is_done(); fst.next()) {
2458     frame* current_frame = fst.current();
2459     if (log) {
2460       current_frame->print_value_on(&st, NULL);
2461     }
2462     current_frame->verify(fst.register_map());
2463   }
2464   if (log) {
2465     tty->print_cr("[WhiteBox::VerifyFrames] Walking Frames");
2466     tty->print_raw(st.freeze());
2467     tty->print_cr("[WhiteBox::VerifyFrames] Done");
2468   }
2469 WB_END
2470 
2471 WB_ENTRY(jboolean, WB_IsJVMTIIncluded(JNIEnv* env, jobject wb))
2472 #if INCLUDE_JVMTI
2473   return JNI_TRUE;
2474 #else
2475   return JNI_FALSE;
2476 #endif
2477 WB_END
2478 
2479 WB_ENTRY(void, WB_WaitUnsafe(JNIEnv* env, jobject wb, jint time))
2480     os::naked_short_sleep(time);
2481 WB_END
2482 
2483 WB_ENTRY(jstring, WB_GetLibcName(JNIEnv* env, jobject o))
2484   ThreadToNativeFromVM ttn(thread);
2485   jstring info_string = env->NewStringUTF(XSTR(LIBC));
2486   CHECK_JNI_EXCEPTION_(env, NULL);
2487   return info_string;
2488 WB_END
2489 
2490 WB_ENTRY(void, WB_LockCritical(JNIEnv* env, jobject wb))
2491   GCLocker::lock_critical(thread);
2492 WB_END
2493 
2494 WB_ENTRY(void, WB_UnlockCritical(JNIEnv* env, jobject wb))
2495   GCLocker::unlock_critical(thread);
2496 WB_END
2497 
2498 #define CC (char*)
2499 
2500 static JNINativeMethod methods[] = {
2501   {CC"getObjectAddress0",                CC"(Ljava/lang/Object;)J", (void*)&WB_GetObjectAddress  },
2502   {CC"getObjectSize0",                   CC"(Ljava/lang/Object;)J", (void*)&WB_GetObjectSize     },
2503   {CC"isObjectInOldGen0",                CC"(Ljava/lang/Object;)Z", (void*)&WB_isObjectInOldGen  },
2504   {CC"getHeapOopSize",                   CC"()I",                   (void*)&WB_GetHeapOopSize    },
2505   {CC"getVMPageSize",                    CC"()I",                   (void*)&WB_GetVMPageSize     },
2506   {CC"getVMAllocationGranularity",       CC"()J",                   (void*)&WB_GetVMAllocationGranularity },
2507   {CC"getVMLargePageSize",               CC"()J",                   (void*)&WB_GetVMLargePageSize},
2508   {CC"getHeapSpaceAlignment",            CC"()J",                   (void*)&WB_GetHeapSpaceAlignment},
2509   {CC"getHeapAlignment",                 CC"()J",                   (void*)&WB_GetHeapAlignment},
2510   {CC"countAliveClasses0",               CC"(Ljava/lang/String;)I", (void*)&WB_CountAliveClasses },
2511   {CC"getSymbolRefcount",                CC"(Ljava/lang/String;)I", (void*)&WB_GetSymbolRefcount },
2512   {CC"parseCommandLine0",
2513       CC"(Ljava/lang/String;C[Ljdk/test/whitebox/parser/DiagnosticCommand;)[Ljava/lang/Object;",
2514       (void*) &WB_ParseCommandLine
2515   },
2516   {CC"addToBootstrapClassLoaderSearch0", CC"(Ljava/lang/String;)V",
2517                                                       (void*)&WB_AddToBootstrapClassLoaderSearch},
2518   {CC"addToSystemClassLoaderSearch0",    CC"(Ljava/lang/String;)V",
2519                                                       (void*)&WB_AddToSystemClassLoaderSearch},
2520   {CC"getCompressedOopsMaxHeapSize", CC"()J",
2521       (void*)&WB_GetCompressedOopsMaxHeapSize},
2522   {CC"printHeapSizes",     CC"()V",                   (void*)&WB_PrintHeapSizes    },
2523   {CC"readFromNoaccessArea",CC"()V",                  (void*)&WB_ReadFromNoaccessArea},
2524   {CC"stressVirtualSpaceResize",CC"(JJJ)I",           (void*)&WB_StressVirtualSpaceResize},
2525 #if INCLUDE_CDS
2526   {CC"getCDSOffsetForName0", CC"(Ljava/lang/String;)I",  (void*)&WB_GetCDSOffsetForName},
2527   {CC"getCDSConstantForName0", CC"(Ljava/lang/String;)I",  (void*)&WB_GetCDSConstantForName},
2528 #endif
2529 #if INCLUDE_G1GC
2530   {CC"g1InConcurrentMark", CC"()Z",                   (void*)&WB_G1InConcurrentMark},
2531   {CC"g1IsHumongous0",      CC"(Ljava/lang/Object;)Z", (void*)&WB_G1IsHumongous     },
2532   {CC"g1BelongsToHumongousRegion0", CC"(J)Z",         (void*)&WB_G1BelongsToHumongousRegion},
2533   {CC"g1BelongsToFreeRegion0", CC"(J)Z",              (void*)&WB_G1BelongsToFreeRegion},
2534   {CC"g1NumMaxRegions",    CC"()J",                   (void*)&WB_G1NumMaxRegions  },
2535   {CC"g1NumFreeRegions",   CC"()J",                   (void*)&WB_G1NumFreeRegions  },
2536   {CC"g1RegionSize",       CC"()I",                   (void*)&WB_G1RegionSize      },
2537   {CC"g1StartConcMarkCycle",       CC"()Z",           (void*)&WB_G1StartMarkCycle  },
2538   {CC"g1HasRegionsToUncommit",  CC"()Z",              (void*)&WB_G1HasRegionsToUncommit},
2539   {CC"g1AuxiliaryMemoryUsage", CC"()Ljava/lang/management/MemoryUsage;",
2540                                                       (void*)&WB_G1AuxiliaryMemoryUsage  },
2541   {CC"g1ActiveMemoryNodeCount", CC"()I",              (void*)&WB_G1ActiveMemoryNodeCount },
2542   {CC"g1MemoryNodeIds",    CC"()[I",                  (void*)&WB_G1MemoryNodeIds },
2543   {CC"g1GetMixedGCInfo",   CC"(I)[J",                 (void*)&WB_G1GetMixedGCInfo },
2544 #endif // INCLUDE_G1GC
2545 #if INCLUDE_PARALLELGC
2546   {CC"psVirtualSpaceAlignment",CC"()J",               (void*)&WB_PSVirtualSpaceAlignment},
2547   {CC"psHeapGenerationAlignment",CC"()J",             (void*)&WB_PSHeapGenerationAlignment},
2548 #endif
2549   {CC"NMTMalloc",           CC"(J)J",                 (void*)&WB_NMTMalloc          },
2550   {CC"NMTMallocWithPseudoStack", CC"(JI)J",           (void*)&WB_NMTMallocWithPseudoStack},
2551   {CC"NMTMallocWithPseudoStackAndType", CC"(JII)J",   (void*)&WB_NMTMallocWithPseudoStackAndType},
2552   {CC"NMTFree",             CC"(J)V",                 (void*)&WB_NMTFree            },
2553   {CC"NMTReserveMemory",    CC"(J)J",                 (void*)&WB_NMTReserveMemory   },
2554   {CC"NMTAttemptReserveMemoryAt",    CC"(JJ)J",       (void*)&WB_NMTAttemptReserveMemoryAt },
2555   {CC"NMTCommitMemory",     CC"(JJ)V",                (void*)&WB_NMTCommitMemory    },
2556   {CC"NMTUncommitMemory",   CC"(JJ)V",                (void*)&WB_NMTUncommitMemory  },
2557   {CC"NMTReleaseMemory",    CC"(JJ)V",                (void*)&WB_NMTReleaseMemory   },
2558   {CC"NMTGetHashSize",      CC"()I",                  (void*)&WB_NMTGetHashSize     },
2559   {CC"NMTNewArena",         CC"(J)J",                 (void*)&WB_NMTNewArena        },
2560   {CC"NMTFreeArena",        CC"(J)V",                 (void*)&WB_NMTFreeArena       },
2561   {CC"NMTArenaMalloc",      CC"(JJ)V",                (void*)&WB_NMTArenaMalloc     },
2562   {CC"deoptimizeFrames",   CC"(Z)I",                  (void*)&WB_DeoptimizeFrames  },
2563   {CC"isFrameDeoptimized", CC"(I)Z",                  (void*)&WB_IsFrameDeoptimized},
2564   {CC"deoptimizeAll",      CC"()V",                   (void*)&WB_DeoptimizeAll     },
2565   {CC"deoptimizeMethod0",   CC"(Ljava/lang/reflect/Executable;Z)I",
2566                                                       (void*)&WB_DeoptimizeMethod  },
2567   {CC"isMethodCompiled0",   CC"(Ljava/lang/reflect/Executable;Z)Z",
2568                                                       (void*)&WB_IsMethodCompiled  },
2569   {CC"isMethodCompilable0", CC"(Ljava/lang/reflect/Executable;IZ)Z",
2570                                                       (void*)&WB_IsMethodCompilable},
2571   {CC"isMethodQueuedForCompilation0",
2572       CC"(Ljava/lang/reflect/Executable;)Z",          (void*)&WB_IsMethodQueuedForCompilation},
2573   {CC"isIntrinsicAvailable0",
2574       CC"(Ljava/lang/reflect/Executable;Ljava/lang/reflect/Executable;I)Z",
2575                                                       (void*)&WB_IsIntrinsicAvailable},
2576   {CC"makeMethodNotCompilable0",
2577       CC"(Ljava/lang/reflect/Executable;IZ)V",        (void*)&WB_MakeMethodNotCompilable},
2578   {CC"testSetDontInlineMethod0",
2579       CC"(Ljava/lang/reflect/Executable;Z)Z",         (void*)&WB_TestSetDontInlineMethod},
2580   {CC"getMethodCompilationLevel0",
2581       CC"(Ljava/lang/reflect/Executable;Z)I",         (void*)&WB_GetMethodCompilationLevel},
2582   {CC"getMethodDecompileCount0",
2583       CC"(Ljava/lang/reflect/Executable;)I",          (void*)&WB_GetMethodDecompileCount},
2584   {CC"getMethodTrapCount0",
2585       CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)I",
2586                                                       (void*)&WB_GetMethodTrapCount},
2587   {CC"getDeoptCount0",
2588       CC"(Ljava/lang/String;Ljava/lang/String;)I",    (void*)&WB_GetDeoptCount},
2589   {CC"getMethodEntryBci0",
2590       CC"(Ljava/lang/reflect/Executable;)I",          (void*)&WB_GetMethodEntryBci},
2591   {CC"getCompileQueueSize",
2592       CC"(I)I",                                       (void*)&WB_GetCompileQueueSize},
2593   {CC"testSetForceInlineMethod0",
2594       CC"(Ljava/lang/reflect/Executable;Z)Z",         (void*)&WB_TestSetForceInlineMethod},
2595   {CC"enqueueMethodForCompilation0",
2596       CC"(Ljava/lang/reflect/Executable;II)Z",        (void*)&WB_EnqueueMethodForCompilation},
2597   {CC"enqueueInitializerForCompilation0",
2598       CC"(Ljava/lang/Class;I)Z",                      (void*)&WB_EnqueueInitializerForCompilation},
2599   {CC"markMethodProfiled",
2600       CC"(Ljava/lang/reflect/Executable;)V",          (void*)&WB_MarkMethodProfiled},
2601   {CC"clearMethodState0",
2602       CC"(Ljava/lang/reflect/Executable;)V",          (void*)&WB_ClearMethodState},
2603   {CC"lockCompilation",    CC"()V",                   (void*)&WB_LockCompilation},
2604   {CC"unlockCompilation",  CC"()V",                   (void*)&WB_UnlockCompilation},
2605   {CC"matchesMethod",
2606       CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)I",
2607                                                       (void*)&WB_MatchesMethod},
2608   {CC"matchesInline",
2609       CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)I",
2610                                                       (void*)&WB_MatchesInline},
2611   {CC"shouldPrintAssembly",
2612         CC"(Ljava/lang/reflect/Executable;I)Z",
2613                                                         (void*)&WB_ShouldPrintAssembly},
2614 
2615   {CC"isConstantVMFlag",   CC"(Ljava/lang/String;)Z", (void*)&WB_IsConstantVMFlag},
2616   {CC"isLockedVMFlag",     CC"(Ljava/lang/String;)Z", (void*)&WB_IsLockedVMFlag},
2617   {CC"setBooleanVMFlag",   CC"(Ljava/lang/String;Z)V",(void*)&WB_SetBooleanVMFlag},
2618   {CC"setIntVMFlag",       CC"(Ljava/lang/String;J)V",(void*)&WB_SetIntVMFlag},
2619   {CC"setUintVMFlag",      CC"(Ljava/lang/String;J)V",(void*)&WB_SetUintVMFlag},
2620   {CC"setIntxVMFlag",      CC"(Ljava/lang/String;J)V",(void*)&WB_SetIntxVMFlag},
2621   {CC"setUintxVMFlag",     CC"(Ljava/lang/String;J)V",(void*)&WB_SetUintxVMFlag},
2622   {CC"setUint64VMFlag",    CC"(Ljava/lang/String;J)V",(void*)&WB_SetUint64VMFlag},
2623   {CC"setSizeTVMFlag",     CC"(Ljava/lang/String;J)V",(void*)&WB_SetSizeTVMFlag},
2624   {CC"setDoubleVMFlag",    CC"(Ljava/lang/String;D)V",(void*)&WB_SetDoubleVMFlag},
2625   {CC"setStringVMFlag",    CC"(Ljava/lang/String;Ljava/lang/String;)V",
2626                                                       (void*)&WB_SetStringVMFlag},
2627   {CC"getBooleanVMFlag",   CC"(Ljava/lang/String;)Ljava/lang/Boolean;",
2628                                                       (void*)&WB_GetBooleanVMFlag},
2629   {CC"getIntVMFlag",       CC"(Ljava/lang/String;)Ljava/lang/Long;",
2630                                                       (void*)&WB_GetIntVMFlag},
2631   {CC"getUintVMFlag",      CC"(Ljava/lang/String;)Ljava/lang/Long;",
2632                                                       (void*)&WB_GetUintVMFlag},
2633   {CC"getIntxVMFlag",      CC"(Ljava/lang/String;)Ljava/lang/Long;",
2634                                                       (void*)&WB_GetIntxVMFlag},
2635   {CC"getUintxVMFlag",     CC"(Ljava/lang/String;)Ljava/lang/Long;",
2636                                                       (void*)&WB_GetUintxVMFlag},
2637   {CC"getUint64VMFlag",    CC"(Ljava/lang/String;)Ljava/lang/Long;",
2638                                                       (void*)&WB_GetUint64VMFlag},
2639   {CC"getSizeTVMFlag",     CC"(Ljava/lang/String;)Ljava/lang/Long;",
2640                                                       (void*)&WB_GetSizeTVMFlag},
2641   {CC"getDoubleVMFlag",    CC"(Ljava/lang/String;)Ljava/lang/Double;",
2642                                                       (void*)&WB_GetDoubleVMFlag},
2643   {CC"getStringVMFlag",    CC"(Ljava/lang/String;)Ljava/lang/String;",
2644                                                       (void*)&WB_GetStringVMFlag},
2645   {CC"isInStringTable",    CC"(Ljava/lang/String;)Z", (void*)&WB_IsInStringTable  },
2646   {CC"fullGC",   CC"()V",                             (void*)&WB_FullGC },
2647   {CC"youngGC",  CC"()V",                             (void*)&WB_YoungGC },
2648   {CC"readReservedMemory", CC"()V",                   (void*)&WB_ReadReservedMemory },
2649   {CC"allocateMetaspace",
2650      CC"(Ljava/lang/ClassLoader;J)J",                 (void*)&WB_AllocateMetaspace },
2651   {CC"incMetaspaceCapacityUntilGC", CC"(J)J",         (void*)&WB_IncMetaspaceCapacityUntilGC },
2652   {CC"metaspaceCapacityUntilGC", CC"()J",             (void*)&WB_MetaspaceCapacityUntilGC },
2653   {CC"metaspaceSharedRegionAlignment", CC"()J",       (void*)&WB_MetaspaceSharedRegionAlignment },
2654   {CC"getCPUFeatures",     CC"()Ljava/lang/String;",  (void*)&WB_GetCPUFeatures     },
2655   {CC"getNMethod0",         CC"(Ljava/lang/reflect/Executable;Z)[Ljava/lang/Object;",
2656                                                       (void*)&WB_GetNMethod         },
2657   {CC"allocateCodeBlob",   CC"(II)J",                 (void*)&WB_AllocateCodeBlob   },
2658   {CC"freeCodeBlob",       CC"(J)V",                  (void*)&WB_FreeCodeBlob       },
2659   {CC"getCodeHeapEntries", CC"(I)[Ljava/lang/Object;",(void*)&WB_GetCodeHeapEntries },
2660   {CC"getCompilationActivityMode",
2661                            CC"()I",                   (void*)&WB_GetCompilationActivityMode},
2662   {CC"getMethodData0",     CC"(Ljava/lang/reflect/Executable;)J",
2663                                                       (void*)&WB_GetMethodData      },
2664   {CC"getCodeBlob",        CC"(J)[Ljava/lang/Object;",(void*)&WB_GetCodeBlob        },
2665   {CC"getThreadStackSize", CC"()J",                   (void*)&WB_GetThreadStackSize },
2666   {CC"getThreadRemainingStackSize", CC"()J",          (void*)&WB_GetThreadRemainingStackSize },
2667   {CC"DefineModule",       CC"(Ljava/lang/Object;ZLjava/lang/String;Ljava/lang/String;[Ljava/lang/Object;)V",
2668                                                       (void*)&WB_DefineModule },
2669   {CC"AddModuleExports",   CC"(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)V",
2670                                                       (void*)&WB_AddModuleExports },
2671   {CC"AddReadsModule",     CC"(Ljava/lang/Object;Ljava/lang/Object;)V",
2672                                                       (void*)&WB_AddReadsModule },
2673   {CC"AddModuleExportsToAllUnnamed", CC"(Ljava/lang/Object;Ljava/lang/String;)V",
2674                                                       (void*)&WB_AddModuleExportsToAllUnnamed },
2675   {CC"AddModuleExportsToAll", CC"(Ljava/lang/Object;Ljava/lang/String;)V",
2676                                                       (void*)&WB_AddModuleExportsToAll },
2677   {CC"deflateIdleMonitors", CC"()Z",                  (void*)&WB_DeflateIdleMonitors },
2678   {CC"isMonitorInflated0", CC"(Ljava/lang/Object;)Z", (void*)&WB_IsMonitorInflated  },
2679   {CC"forceSafepoint",     CC"()V",                   (void*)&WB_ForceSafepoint     },
2680   {CC"getConstantPool0",   CC"(Ljava/lang/Class;)J",  (void*)&WB_GetConstantPool    },
2681   {CC"getConstantPoolCacheIndexTag0", CC"()I",  (void*)&WB_GetConstantPoolCacheIndexTag},
2682   {CC"getConstantPoolCacheLength0", CC"(Ljava/lang/Class;)I",  (void*)&WB_GetConstantPoolCacheLength},
2683   {CC"remapInstructionOperandFromCPCache0",
2684       CC"(Ljava/lang/Class;I)I",                      (void*)&WB_ConstantPoolRemapInstructionOperandFromCache},
2685   {CC"encodeConstantPoolIndyIndex0",
2686       CC"(I)I",                      (void*)&WB_ConstantPoolEncodeIndyIndex},
2687   {CC"getMethodBooleanOption",
2688       CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)Ljava/lang/Boolean;",
2689                                                       (void*)&WB_GetMethodBooleaneOption},
2690   {CC"getMethodIntxOption",
2691       CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)Ljava/lang/Long;",
2692                                                       (void*)&WB_GetMethodIntxOption},
2693   {CC"getMethodUintxOption",
2694       CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)Ljava/lang/Long;",
2695                                                       (void*)&WB_GetMethodUintxOption},
2696   {CC"getMethodDoubleOption",
2697       CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)Ljava/lang/Double;",
2698                                                       (void*)&WB_GetMethodDoubleOption},
2699   {CC"getMethodStringOption",
2700       CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)Ljava/lang/String;",
2701                                                       (void*)&WB_GetMethodStringOption},
2702   {CC"getDefaultArchivePath",             CC"()Ljava/lang/String;",
2703                                                       (void*)&WB_GetDefaultArchivePath},
2704   {CC"getCDSGenericHeaderMinVersion",     CC"()I",    (void*)&WB_GetCDSGenericHeaderMinVersion},
2705   {CC"getCurrentCDSVersion",              CC"()I",    (void*)&WB_GetCDSCurrentVersion},
2706   {CC"isSharingEnabled",   CC"()Z",                   (void*)&WB_IsSharingEnabled},
2707   {CC"isShared",           CC"(Ljava/lang/Object;)Z", (void*)&WB_IsShared },
2708   {CC"isSharedInternedString", CC"(Ljava/lang/String;)Z", (void*)&WB_IsSharedInternedString },
2709   {CC"isSharedClass",      CC"(Ljava/lang/Class;)Z",  (void*)&WB_IsSharedClass },
2710   {CC"areSharedStringsMapped",            CC"()Z",    (void*)&WB_AreSharedStringsMapped },
2711   {CC"getResolvedReferences", CC"(Ljava/lang/Class;)Ljava/lang/Object;", (void*)&WB_GetResolvedReferences},
2712   {CC"linkClass",          CC"(Ljava/lang/Class;)V",  (void*)&WB_LinkClass},
2713   {CC"areOpenArchiveHeapObjectsMapped",   CC"()Z",    (void*)&WB_AreOpenArchiveHeapObjectsMapped},
2714   {CC"isCDSIncluded",                     CC"()Z",    (void*)&WB_IsCDSIncluded },
2715   {CC"isJFRIncluded",                     CC"()Z",    (void*)&WB_IsJFRIncluded },
2716   {CC"isDTraceIncluded",                  CC"()Z",    (void*)&WB_IsDTraceIncluded },
2717   {CC"isC2OrJVMCIIncluded",               CC"()Z",    (void*)&WB_isC2OrJVMCIIncluded },
2718   {CC"isJVMCISupportedByGC",              CC"()Z",    (void*)&WB_IsJVMCISupportedByGC},
2719   {CC"canWriteJavaHeapArchive",           CC"()Z",    (void*)&WB_CanWriteJavaHeapArchive },
2720   {CC"cdsMemoryMappingFailed",            CC"()Z",    (void*)&WB_CDSMemoryMappingFailed },
2721 
2722   {CC"clearInlineCaches0",  CC"(Z)V",                 (void*)&WB_ClearInlineCaches },
2723   {CC"handshakeReadMonitors", CC"(Ljava/lang/Thread;)Z", (void*)&WB_HandshakeReadMonitors },
2724   {CC"handshakeWalkStack", CC"(Ljava/lang/Thread;Z)I", (void*)&WB_HandshakeWalkStack },
2725   {CC"asyncHandshakeWalkStack", CC"(Ljava/lang/Thread;)V", (void*)&WB_AsyncHandshakeWalkStack },
2726   {CC"lockAndBlock", CC"(Z)V",                        (void*)&WB_LockAndBlock},
2727   {CC"checkThreadObjOfTerminatingThread", CC"(Ljava/lang/Thread;)V", (void*)&WB_CheckThreadObjOfTerminatingThread },
2728   {CC"verifyFrames",                CC"(ZZ)V",            (void*)&WB_VerifyFrames },
2729   {CC"addCompilerDirective",    CC"(Ljava/lang/String;)I",
2730                                                       (void*)&WB_AddCompilerDirective },
2731   {CC"removeCompilerDirective",   CC"(I)V",           (void*)&WB_RemoveCompilerDirective },
2732   {CC"isGCSupported",             CC"(I)Z",           (void*)&WB_IsGCSupported},
2733   {CC"isGCSupportedByJVMCICompiler", CC"(I)Z",        (void*)&WB_IsGCSupportedByJVMCICompiler},
2734   {CC"isGCSelected",              CC"(I)Z",           (void*)&WB_IsGCSelected},
2735   {CC"isGCSelectedErgonomically", CC"()Z",            (void*)&WB_IsGCSelectedErgonomically},
2736   {CC"supportsConcurrentGCBreakpoints", CC"()Z",      (void*)&WB_SupportsConcurrentGCBreakpoints},
2737   {CC"concurrentGCAcquireControl0", CC"()V",          (void*)&WB_ConcurrentGCAcquireControl},
2738   {CC"concurrentGCReleaseControl0", CC"()V",          (void*)&WB_ConcurrentGCReleaseControl},
2739   {CC"concurrentGCRunToIdle0",    CC"()V",            (void*)&WB_ConcurrentGCRunToIdle},
2740   {CC"concurrentGCRunTo0",        CC"(Ljava/lang/String;)Z",
2741                                                       (void*)&WB_ConcurrentGCRunTo},
2742   {CC"checkLibSpecifiesNoexecstack", CC"(Ljava/lang/String;)Z",
2743                                                       (void*)&WB_CheckLibSpecifiesNoexecstack},
2744   {CC"isContainerized",           CC"()Z",            (void*)&WB_IsContainerized },
2745   {CC"validateCgroup",
2746       CC"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I",
2747                                                       (void*)&WB_ValidateCgroup },
2748   {CC"printOsInfo",               CC"()V",            (void*)&WB_PrintOsInfo },
2749   {CC"disableElfSectionCache",    CC"()V",            (void*)&WB_DisableElfSectionCache },
2750   {CC"resolvedMethodItemsCount",  CC"()J",            (void*)&WB_ResolvedMethodItemsCount },
2751   {CC"protectionDomainRemovedCount",   CC"()I",       (void*)&WB_ProtectionDomainRemovedCount },
2752   {CC"getKlassMetadataSize", CC"(Ljava/lang/Class;)I",(void*)&WB_GetKlassMetadataSize},
2753 
2754   {CC"createMetaspaceTestContext", CC"(JJ)J",         (void*)&WB_CreateMetaspaceTestContext},
2755   {CC"destroyMetaspaceTestContext", CC"(J)V",         (void*)&WB_DestroyMetaspaceTestContext},
2756   {CC"purgeMetaspaceTestContext", CC"(J)V",           (void*)&WB_PurgeMetaspaceTestContext},
2757   {CC"printMetaspaceTestContext", CC"(J)V",           (void*)&WB_PrintMetaspaceTestContext},
2758   {CC"getTotalCommittedWordsInMetaspaceTestContext", CC"(J)J",(void*)&WB_GetTotalCommittedWordsInMetaspaceTestContext},
2759   {CC"getTotalUsedWordsInMetaspaceTestContext", CC"(J)J", (void*)&WB_GetTotalUsedWordsInMetaspaceTestContext},
2760   {CC"createArenaInTestContext", CC"(JZ)J",           (void*)&WB_CreateArenaInTestContext},
2761   {CC"destroyMetaspaceTestArena", CC"(J)V",           (void*)&WB_DestroyMetaspaceTestArena},
2762   {CC"allocateFromMetaspaceTestArena", CC"(JJ)J",     (void*)&WB_AllocateFromMetaspaceTestArena},
2763   {CC"deallocateToMetaspaceTestArena", CC"(JJJ)V",    (void*)&WB_DeallocateToMetaspaceTestArena},
2764   {CC"maxMetaspaceAllocationSize", CC"()J",           (void*)&WB_GetMaxMetaspaceAllocationSize},
2765 
2766   {CC"isJVMTIIncluded", CC"()Z",                      (void*)&WB_IsJVMTIIncluded},
2767   {CC"waitUnsafe", CC"(I)V",                          (void*)&WB_WaitUnsafe},
2768   {CC"getLibcName",     CC"()Ljava/lang/String;",     (void*)&WB_GetLibcName},
2769 
2770   {CC"lockCritical",    CC"()V",                      (void*)&WB_LockCritical},
2771   {CC"unlockCritical",  CC"()V",                      (void*)&WB_UnlockCritical},
2772 };
2773 
2774 
2775 #undef CC
2776 
2777 JVM_ENTRY(void, JVM_RegisterWhiteBoxMethods(JNIEnv* env, jclass wbclass))
2778   {
2779     if (WhiteBoxAPI) {
2780       // Make sure that wbclass is loaded by the null classloader
2781       InstanceKlass* ik = InstanceKlass::cast(java_lang_Class::as_Klass(JNIHandles::resolve(wbclass)));
2782       Handle loader(THREAD, ik->class_loader());
2783       if (loader.is_null()) {
2784         WhiteBox::register_methods(env, wbclass, thread, methods, sizeof(methods) / sizeof(methods[0]));
2785         WhiteBox::set_used();
2786       }
2787     }
2788   }
2789 JVM_END