products/Sources/formale Sprachen/Java/openjdk-20-36_src/src/hotspot/share/prims image not shown  

Quellcode-Bibliothek

© Kompilation durch diese Firma

[Weder Korrektheit noch Funktionsfähigkeit der Software werden zugesichert.]

Datei: whitebox.cpp   Sprache: C

/*
 * Copyright (c) 2012, 2022, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 *
 */


#include "precompiled.hpp"
#include "cds.h"
#include "cds/archiveHeapLoader.hpp"
#include "cds/cdsConstants.hpp"
#include "cds/filemap.hpp"
#include "cds/heapShared.hpp"
#include "cds/metaspaceShared.hpp"
#include "classfile/classLoaderDataGraph.hpp"
#include "classfile/classLoaderStats.hpp"
#include "classfile/javaClasses.inline.hpp"
#include "classfile/modules.hpp"
#include "classfile/protectionDomainCache.hpp"
#include "classfile/stringTable.hpp"
#include "classfile/symbolTable.hpp"
#include "classfile/systemDictionary.hpp"
#include "classfile/vmSymbols.hpp"
#include "code/codeCache.hpp"
#include "compiler/compilationPolicy.hpp"
#include "compiler/directivesParser.hpp"
#include "compiler/methodMatcher.hpp"
#include "gc/shared/concurrentGCBreakpoints.hpp"
#include "gc/shared/gcConfig.hpp"
#include "gc/shared/gcLocker.inline.hpp"
#include "gc/shared/genArguments.hpp"
#include "gc/shared/genCollectedHeap.hpp"
#include "jvmtifiles/jvmtiEnv.hpp"
#include "logging/log.hpp"
#include "memory/iterator.hpp"
#include "memory/metadataFactory.hpp"
#include "memory/metaspace/testHelpers.hpp"
#include "memory/metaspaceUtils.hpp"
#include "memory/oopFactory.hpp"
#include "memory/resourceArea.hpp"
#include "memory/universe.hpp"
#include "oops/array.hpp"
#include "oops/compressedOops.hpp"
#include "oops/constantPool.inline.hpp"
#include "oops/klass.inline.hpp"
#include "oops/method.inline.hpp"
#include "oops/objArrayKlass.hpp"
#include "oops/objArrayOop.inline.hpp"
#include "oops/oop.inline.hpp"
#include "oops/typeArrayOop.inline.hpp"
#include "prims/resolvedMethodTable.hpp"
#include "prims/wbtestmethods/parserTests.hpp"
#include "prims/whitebox.inline.hpp"
#include "runtime/arguments.hpp"
#include "runtime/atomic.hpp"
#include "runtime/deoptimization.hpp"
#include "runtime/fieldDescriptor.inline.hpp"
#include "runtime/flags/jvmFlag.hpp"
#include "runtime/flags/jvmFlagAccess.hpp"
#include "runtime/frame.inline.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/handshake.hpp"
#include "runtime/interfaceSupport.inline.hpp"
#include "runtime/javaCalls.hpp"
#include "runtime/javaThread.inline.hpp"
#include "runtime/jniHandles.inline.hpp"
#include "runtime/os.hpp"
#include "runtime/stackFrameStream.inline.hpp"
#include "runtime/synchronizer.hpp"
#include "runtime/threadSMR.hpp"
#include "runtime/vframe.hpp"
#include "runtime/vm_version.hpp"
#include "services/mallocSiteTable.hpp"
#include "services/memoryService.hpp"
#include "services/memTracker.hpp"
#include "utilities/align.hpp"
#include "utilities/debug.hpp"
#include "utilities/elfFile.hpp"
#include "utilities/exceptions.hpp"
#include "utilities/macros.hpp"
#include "utilities/nativeCallStack.hpp"
#include "utilities/ostream.hpp"
#if INCLUDE_G1GC
#include "gc/g1/g1Arguments.hpp"
#include "gc/g1/g1CollectedHeap.inline.hpp"
#include "gc/g1/g1ConcurrentMark.hpp"
#include "gc/g1/g1ConcurrentMarkThread.inline.hpp"
#include "gc/g1/heapRegionManager.hpp"
#include "gc/g1/heapRegionRemSet.inline.hpp"
#endif // INCLUDE_G1GC
#if INCLUDE_PARALLELGC
#include "gc/parallel/parallelScavengeHeap.inline.hpp"
#endif // INCLUDE_PARALLELGC
#if INCLUDE_JVMCI
#include "jvmci/jvmciEnv.hpp"
#include "jvmci/jvmciRuntime.hpp"
#endif
#ifdef LINUX
#include "osContainer_linux.hpp"
#include "cgroupSubsystem_linux.hpp"
#endif

#define SIZE_T_MAX_VALUE ((size_t) -1)

#define CHECK_JNI_EXCEPTION_(env, value)                               \
  do {                                                                 \
    JavaThread* THREAD = JavaThread::thread_from_jni_environment(env); \
    THREAD->clear_pending_jni_exception_check();                       \
    if (HAS_PENDING_EXCEPTION) {                                       \
      return(value);                                                   \
    }                                                                  \
  } while (0)

#define CHECK_JNI_EXCEPTION(env)                                       \
  do {                                                                 \
    JavaThread* THREAD = JavaThread::thread_from_jni_environment(env); \
    THREAD->clear_pending_jni_exception_check();                       \
    if (HAS_PENDING_EXCEPTION) {                                       \
      return;                                                          \
    }                                                                  \
  } while (0)

bool WhiteBox::_used = false;
volatile bool WhiteBox::compilation_locked = false;

class VM_WhiteBoxOperation : public VM_Operation {
 public:
  VM_WhiteBoxOperation()                         { }
  VMOp_Type type()                  const        { return VMOp_WhiteBoxOperation; }
  bool allow_nested_vm_operations() const        { return true; }
};


WB_ENTRY(jlong, WB_GetObjectAddress(JNIEnv* env, jobject o, jobject obj))
  return (jlong)(void*)JNIHandles::resolve(obj);
WB_END

WB_ENTRY(jint, WB_GetHeapOopSize(JNIEnv* env, jobject o))
  return heapOopSize;
WB_END

WB_ENTRY(jint, WB_GetVMPageSize(JNIEnv* env, jobject o))
  return os::vm_page_size();
WB_END

WB_ENTRY(jlong, WB_GetVMAllocationGranularity(JNIEnv* env, jobject o))
  return os::vm_allocation_granularity();
WB_END

WB_ENTRY(jlong, WB_GetVMLargePageSize(JNIEnv* env, jobject o))
  return os::large_page_size();
WB_END

class WBIsKlassAliveClosure : public LockedClassesDo {
    Symbol* _name;
    int _count;
public:
    WBIsKlassAliveClosure(Symbol* name) : _name(name), _count(0) {}

    void do_klass(Klass* k) {
      Symbol* ksym = k->name();
      if (ksym->fast_compare(_name) == 0) {
        _count++;
      } else if (k->is_instance_klass()) {
        // Need special handling for hidden classes because the JVM
        // appends "+<hex-address>" to hidden class names.
        InstanceKlass *ik = InstanceKlass::cast(k);
        if (ik->is_hidden()) {
          ResourceMark rm;
          char* k_name = ksym->as_C_string();
          // Find the first '+' char and truncate the string at that point.
          // NOTE: This will not work correctly if the original hidden class
          // name contains a '+'.
          char* plus_char = strchr(k_name, '+');
          if (plus_char != NULL) {
            *plus_char = 0;
            char* c_name = _name->as_C_string();
            if (strcmp(c_name, k_name) == 0) {
              _count++;
            }
          }
        }
      }
    }

    int count() const {
        return _count;
    }
};

WB_ENTRY(jint, WB_CountAliveClasses(JNIEnv* env, jobject target, jstring name))
  oop h_name = JNIHandles::resolve(name);
  if (h_name == NULL) return false;
  Symbol* sym = java_lang_String::as_symbol(h_name);
  TempNewSymbol tsym(sym); // Make sure to decrement reference count on sym on return

  WBIsKlassAliveClosure closure(sym);
  ClassLoaderDataGraph::classes_do(&closure);

  // Return the count of alive classes with this name.
  return closure.count();
WB_END

WB_ENTRY(jint, WB_GetSymbolRefcount(JNIEnv* env, jobject unused, jstring name))
  oop h_name = JNIHandles::resolve(name);
  if (h_name == NULL) return false;
  Symbol* sym = java_lang_String::as_symbol(h_name);
  TempNewSymbol tsym(sym); // Make sure to decrement reference count on sym on return
  return (jint)sym->refcount();
WB_END


WB_ENTRY(void, WB_AddToBootstrapClassLoaderSearch(JNIEnv* env, jobject o, jstring segment)) {
#if INCLUDE_JVMTI
  ResourceMark rm;
  const char* seg = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(segment));
  JvmtiEnv* jvmti_env = JvmtiEnv::create_a_jvmti(JVMTI_VERSION);
  jvmtiError err = jvmti_env->AddToBootstrapClassLoaderSearch(seg);
  assert(err == JVMTI_ERROR_NONE, "must not fail");
#endif
}
WB_END

WB_ENTRY(void, WB_AddToSystemClassLoaderSearch(JNIEnv* env, jobject o, jstring segment)) {
#if INCLUDE_JVMTI
  ResourceMark rm;
  const char* seg = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(segment));
  JvmtiEnv* jvmti_env = JvmtiEnv::create_a_jvmti(JVMTI_VERSION);
  jvmtiError err = jvmti_env->AddToSystemClassLoaderSearch(seg);
  assert(err == JVMTI_ERROR_NONE, "must not fail");
#endif
}
WB_END


WB_ENTRY(jlong, WB_GetCompressedOopsMaxHeapSize(JNIEnv* env, jobject o)) {
  return (jlong)Arguments::max_heap_for_compressed_oops();
}
WB_END

WB_ENTRY(void, WB_PrintHeapSizes(JNIEnv* env, jobject o)) {
  tty->print_cr("Minimum heap " SIZE_FORMAT " Initial heap " SIZE_FORMAT " "
                "Maximum heap " SIZE_FORMAT " Space alignment " SIZE_FORMAT " Heap alignment " SIZE_FORMAT,
                MinHeapSize,
                InitialHeapSize,
                MaxHeapSize,
                SpaceAlignment,
                HeapAlignment);
}
WB_END

WB_ENTRY(void, WB_ReadFromNoaccessArea(JNIEnv* env, jobject o))
  size_t granularity = os::vm_allocation_granularity();
  ReservedHeapSpace rhs(100 * granularity, granularity, os::vm_page_size());
  VirtualSpace vs;
  vs.initialize(rhs, 50 * granularity);

  // Check if constraints are complied
  if (!( UseCompressedOops && rhs.base() != NULL &&
         CompressedOops::base() != NULL &&
         CompressedOops::use_implicit_null_checks() )) {
    tty->print_cr("WB_ReadFromNoaccessArea method is useless:\n "
                  "\tUseCompressedOops is %d\n"
                  "\trhs.base() is " PTR_FORMAT "\n"
                  "\tCompressedOops::base() is " PTR_FORMAT "\n"
                  "\tCompressedOops::use_implicit_null_checks() is %d",
                  UseCompressedOops,
                  p2i(rhs.base()),
                  p2i(CompressedOops::base()),
                  CompressedOops::use_implicit_null_checks());
    return;
  }
  tty->print_cr("Reading from no access area... ");
  tty->print_cr("*(vs.low_boundary() - rhs.noaccess_prefix() / 2 ) = %c",
                *(vs.low_boundary() - rhs.noaccess_prefix() / 2 ));
WB_END

static jint wb_stress_virtual_space_resize(size_t reserved_space_size,
                                           size_t magnitude, size_t iterations) {
  size_t granularity = os::vm_allocation_granularity();
  ReservedHeapSpace rhs(reserved_space_size * granularity, granularity, os::vm_page_size());
  VirtualSpace vs;
  if (!vs.initialize(rhs, 0)) {
    tty->print_cr("Failed to initialize VirtualSpace. Can't proceed.");
    return 3;
  }

  int seed = os::random();
  tty->print_cr("Random seed is %d", seed);

  for (size_t i = 0; i < iterations; i++) {

    // Whether we will shrink or grow
    bool shrink = os::random() % 2L == 0;

    // Get random delta to resize virtual space
    size_t delta = (size_t)os::random() % magnitude;

    // If we are about to shrink virtual space below zero, then expand instead
    if (shrink && vs.committed_size() < delta) {
      shrink = false;
    }

    // Resizing by delta
    if (shrink) {
      vs.shrink_by(delta);
    } else {
      // If expanding fails expand_by will silently return false
      vs.expand_by(delta, true);
    }
  }
  return 0;
}

WB_ENTRY(jint, WB_StressVirtualSpaceResize(JNIEnv* env, jobject o,
        jlong reserved_space_size, jlong magnitude, jlong iterations))
  tty->print_cr("reservedSpaceSize=" JLONG_FORMAT ", magnitude=" JLONG_FORMAT ", "
                "iterations=" JLONG_FORMAT "\n", reserved_space_size, magnitude,
                iterations);
  if (reserved_space_size < 0 || magnitude < 0 || iterations < 0) {
    tty->print_cr("One of variables printed above is negative. Can't proceed.\n");
    return 1;
  }

  // sizeof(size_t) depends on whether OS is 32bit or 64bit. sizeof(jlong) is
  // always 8 byte. That's why we should avoid overflow in case of 32bit platform.
  if (sizeof(size_t) < sizeof(jlong)) {
    jlong size_t_max_value = (jlong) SIZE_T_MAX_VALUE;
    if (reserved_space_size > size_t_max_value || magnitude > size_t_max_value
        || iterations > size_t_max_value) {
      tty->print_cr("One of variables printed above overflows size_t. Can't proceed.\n");
      return 2;
    }
  }

  return wb_stress_virtual_space_resize((size_t) reserved_space_size,
                                        (size_t) magnitude, (size_t) iterations);
WB_END

WB_ENTRY(jboolean, WB_IsGCSupported(JNIEnv* env, jobject o, jint name))
  return GCConfig::is_gc_supported((CollectedHeap::Name)name);
WB_END

WB_ENTRY(jboolean, WB_IsGCSupportedByJVMCICompiler(JNIEnv* env, jobject o, jint name))
#if INCLUDE_JVMCI
  if (EnableJVMCI) {
    JVMCIEnv jvmciEnv(thread, env, __FILE__, __LINE__);
    return jvmciEnv.runtime()->is_gc_supported(&jvmciEnv, (CollectedHeap::Name)name);
  }
#endif
  return false;
WB_END

WB_ENTRY(jboolean, WB_IsGCSelected(JNIEnv* env, jobject o, jint name))
  return GCConfig::is_gc_selected((CollectedHeap::Name)name);
WB_END

WB_ENTRY(jboolean, WB_IsGCSelectedErgonomically(JNIEnv* env, jobject o))
  return GCConfig::is_gc_selected_ergonomically();
WB_END

WB_ENTRY(jboolean, WB_isObjectInOldGen(JNIEnv* env, jobject o, jobject obj))
  oop p = JNIHandles::resolve(obj);
#if INCLUDE_G1GC
  if (UseG1GC) {
    G1CollectedHeap* g1h = G1CollectedHeap::heap();
    const HeapRegion* hr = g1h->heap_region_containing(p);
    return !(hr->is_young());
  }
#endif
#if INCLUDE_PARALLELGC
  if (UseParallelGC) {
    ParallelScavengeHeap* psh = ParallelScavengeHeap::heap();
    return !psh->is_in_young(p);
  }
#endif
#if INCLUDE_ZGC
  if (UseZGC) {
    return Universe::heap()->is_in(p);
  }
#endif
#if INCLUDE_SHENANDOAHGC
  if (UseShenandoahGC) {
    return Universe::heap()->is_in(p);
  }
#endif
  GenCollectedHeap* gch = GenCollectedHeap::heap();
  return !gch->is_in_young(p);
WB_END

WB_ENTRY(jlong, WB_GetObjectSize(JNIEnv* env, jobject o, jobject obj))
  oop p = JNIHandles::resolve(obj);
  return p->size() * HeapWordSize;
WB_END

WB_ENTRY(jlong, WB_GetHeapSpaceAlignment(JNIEnv* env, jobject o))
  return (jlong)SpaceAlignment;
WB_END

WB_ENTRY(jlong, WB_GetHeapAlignment(JNIEnv* env, jobject o))
  return (jlong)HeapAlignment;
WB_END

WB_ENTRY(jboolean, WB_SupportsConcurrentGCBreakpoints(JNIEnv* env, jobject o))
  return Universe::heap()->supports_concurrent_gc_breakpoints();
WB_END

WB_ENTRY(void, WB_ConcurrentGCAcquireControl(JNIEnv* env, jobject o))
  ConcurrentGCBreakpoints::acquire_control();
WB_END

WB_ENTRY(void, WB_ConcurrentGCReleaseControl(JNIEnv* env, jobject o))
  ConcurrentGCBreakpoints::release_control();
WB_END

WB_ENTRY(void, WB_ConcurrentGCRunToIdle(JNIEnv* env, jobject o))
  ConcurrentGCBreakpoints::run_to_idle();
WB_END

WB_ENTRY(jboolean, WB_ConcurrentGCRunTo(JNIEnv* env, jobject o, jobject at))
  Handle h_name(THREAD, JNIHandles::resolve(at));
  ResourceMark rm;
  const char* c_name = java_lang_String::as_utf8_string(h_name());
  return ConcurrentGCBreakpoints::run_to(c_name);
WB_END

#if INCLUDE_G1GC

WB_ENTRY(jboolean, WB_G1IsHumongous(JNIEnv* env, jobject o, jobject obj))
  if (UseG1GC) {
    G1CollectedHeap* g1h = G1CollectedHeap::heap();
    oop result = JNIHandles::resolve(obj);
    const HeapRegion* hr = g1h->heap_region_containing(result);
    return hr->is_humongous();
  }
  THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_G1IsHumongous: G1 GC is not enabled");
WB_END

WB_ENTRY(jboolean, WB_G1BelongsToHumongousRegion(JNIEnv* env, jobject o, jlong addr))
  if (UseG1GC) {
    G1CollectedHeap* g1h = G1CollectedHeap::heap();
    const HeapRegion* hr = g1h->heap_region_containing((void*) addr);
    return hr->is_humongous();
  }
  THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_G1BelongsToHumongousRegion: G1 GC is not enabled");
WB_END

WB_ENTRY(jboolean, WB_G1BelongsToFreeRegion(JNIEnv* env, jobject o, jlong addr))
  if (UseG1GC) {
    G1CollectedHeap* g1h = G1CollectedHeap::heap();
    const HeapRegion* hr = g1h->heap_region_containing((void*) addr);
    return hr->is_free();
  }
  THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_G1BelongsToFreeRegion: G1 GC is not enabled");
WB_END

WB_ENTRY(jlong, WB_G1NumMaxRegions(JNIEnv* env, jobject o))
  if (UseG1GC) {
    G1CollectedHeap* g1h = G1CollectedHeap::heap();
    size_t nr = g1h->max_regions();
    return (jlong)nr;
  }
  THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_G1NumMaxRegions: G1 GC is not enabled");
WB_END

WB_ENTRY(jlong, WB_G1NumFreeRegions(JNIEnv* env, jobject o))
  if (UseG1GC) {
    G1CollectedHeap* g1h = G1CollectedHeap::heap();
    size_t nr = g1h->num_free_regions();
    return (jlong)nr;
  }
  THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_G1NumFreeRegions: G1 GC is not enabled");
WB_END

WB_ENTRY(jboolean, WB_G1InConcurrentMark(JNIEnv* env, jobject o))
  if (UseG1GC) {
    G1CollectedHeap* g1h = G1CollectedHeap::heap();
    return g1h->concurrent_mark()->cm_thread()->in_progress();
  }
  THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_G1InConcurrentMark: G1 GC is not enabled");
WB_END

WB_ENTRY(jint, WB_G1CompletedConcurrentMarkCycles(JNIEnv* env, jobject o))
  if (UseG1GC) {
    G1CollectedHeap* g1h = G1CollectedHeap::heap();
    G1ConcurrentMark* cm = g1h->concurrent_mark();
    return cm->completed_mark_cycles();
  }
  THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_G1CompletedConcurrentMarkCycles: G1 GC is not enabled");
WB_END

WB_ENTRY(jint, WB_G1RegionSize(JNIEnv* env, jobject o))
  if (UseG1GC) {
    return (jint)HeapRegion::GrainBytes;
  }
  THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_G1RegionSize: G1 GC is not enabled");
WB_END

WB_ENTRY(jboolean, WB_G1HasRegionsToUncommit(JNIEnv* env, jobject o))
  if (UseG1GC) {
    return G1CollectedHeap::heap()->has_uncommittable_regions();
  }
  THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_G1HasRegionsToUncommit: G1 GC is not enabled");
WB_END

#endif // INCLUDE_G1GC

#if INCLUDE_PARALLELGC

WB_ENTRY(jlong, WB_PSVirtualSpaceAlignment(JNIEnv* env, jobject o))
  if (UseParallelGC) {
    return GenAlignment;
  }
  THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_PSVirtualSpaceAlignment: Parallel GC is not enabled");
WB_END

WB_ENTRY(jlong, WB_PSHeapGenerationAlignment(JNIEnv* env, jobject o))
  if (UseParallelGC) {
    return GenAlignment;
  }
  THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_PSHeapGenerationAlignment: Parallel GC is not enabled");
WB_END

#endif // INCLUDE_PARALLELGC

#if INCLUDE_G1GC

WB_ENTRY(jobject, WB_G1AuxiliaryMemoryUsage(JNIEnv* env))
  if (UseG1GC) {
    ResourceMark rm(THREAD);
    G1CollectedHeap* g1h = G1CollectedHeap::heap();
    MemoryUsage usage = g1h->get_auxiliary_data_memory_usage();
    Handle h = MemoryService::create_MemoryUsage_obj(usage, CHECK_NULL);
    return JNIHandles::make_local(THREAD, h());
  }
  THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_G1AuxiliaryMemoryUsage: G1 GC is not enabled");
WB_END

WB_ENTRY(jint, WB_G1ActiveMemoryNodeCount(JNIEnv* env, jobject o))
  if (UseG1GC) {
    G1NUMA* numa = G1NUMA::numa();
    return (jint)numa->num_active_nodes();
  }
  THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_G1ActiveMemoryNodeCount: G1 GC is not enabled");
WB_END

WB_ENTRY(jintArray, WB_G1MemoryNodeIds(JNIEnv* env, jobject o))
  if (UseG1GC) {
    G1NUMA* numa = G1NUMA::numa();
    int num_node_ids = (int)numa->num_active_nodes();
    const int* node_ids = numa->node_ids();

    typeArrayOop result = oopFactory::new_intArray(num_node_ids, CHECK_NULL);
    for (int i = 0; i < num_node_ids; i++) {
      result->int_at_put(i, (jint)node_ids[i]);
    }
    return (jintArray) JNIHandles::make_local(THREAD, result);
  }
  THROW_MSG_NULL(vmSymbols::java_lang_UnsupportedOperationException(), "WB_G1MemoryNodeIds: G1 GC is not enabled");
WB_END

class OldRegionsLivenessClosure: public HeapRegionClosure {

 private:
  const int _liveness;
  size_t _total_count;
  size_t _total_memory;
  size_t _total_memory_to_free;

 public:
  OldRegionsLivenessClosure(int liveness) :
    _liveness(liveness),
    _total_count(0),
    _total_memory(0),
    _total_memory_to_free(0) { }

    size_t total_count() { return _total_count; }
    size_t total_memory() { return _total_memory; }
    size_t total_memory_to_free() { return _total_memory_to_free; }

  bool do_heap_region(HeapRegion* r) {
    if (r->is_old()) {
      size_t live = r->live_bytes();
      size_t size = r->used();
      size_t reg_size = HeapRegion::GrainBytes;
      if (size > 0 && ((int)(live * 100 / size) < _liveness)) {
        _total_memory += size;
        ++_total_count;
        if (size == reg_size) {
          // We don't include non-full regions since they are unlikely included in mixed gc
          // for testing purposes it's enough to have lowest estimation of total memory that is expected to be freed
          _total_memory_to_free += size - live;
        }
      }
    }
    return false;
  }
};


WB_ENTRY(jlongArray, WB_G1GetMixedGCInfo(JNIEnv* env, jobject o, jint liveness))
  if (!UseG1GC) {
    THROW_MSG_NULL(vmSymbols::java_lang_UnsupportedOperationException(), "WB_G1GetMixedGCInfo: G1 GC is not enabled");
  }
  if (liveness < 0) {
    THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), "liveness value should be non-negative");
  }

  G1CollectedHeap* g1h = G1CollectedHeap::heap();
  OldRegionsLivenessClosure rli(liveness);
  g1h->heap_region_iterate(&rli);

  typeArrayOop result = oopFactory::new_longArray(3, CHECK_NULL);
  result->long_at_put(0, rli.total_count());
  result->long_at_put(1, rli.total_memory());
  result->long_at_put(2, rli.total_memory_to_free());
  return (jlongArray) JNIHandles::make_local(THREAD, result);
WB_END

#endif // INCLUDE_G1GC

// Alloc memory using the test memory type so that we can use that to see if
// NMT picks it up correctly
WB_ENTRY(jlong, WB_NMTMalloc(JNIEnv* env, jobject o, jlong size))
  jlong addr = 0;
  addr = (jlong)(uintptr_t)os::malloc(size, mtTest);
  return addr;
WB_END

// Alloc memory with pseudo call stack. The test can create pseudo malloc
// allocation site to stress the malloc tracking.
WB_ENTRY(jlong, WB_NMTMallocWithPseudoStack(JNIEnv* env, jobject o, jlong size, jint pseudo_stack))
  address pc = (address)(size_t)pseudo_stack;
  NativeCallStack stack(&pc, 1);
  return (jlong)(uintptr_t)os::malloc(size, mtTest, stack);
WB_END

// Alloc memory with pseudo call stack and specific memory type.
WB_ENTRY(jlong, WB_NMTMallocWithPseudoStackAndType(JNIEnv* env, jobject o, jlong size, jint pseudo_stack, jint type))
  address pc = (address)(size_t)pseudo_stack;
  NativeCallStack stack(&pc, 1);
  return (jlong)(uintptr_t)os::malloc(size, (MEMFLAGS)type, stack);
WB_END

// Free the memory allocated by NMTAllocTest
WB_ENTRY(void, WB_NMTFree(JNIEnv* env, jobject o, jlong mem))
  os::free((void*)(uintptr_t)mem);
WB_END

WB_ENTRY(jlong, WB_NMTReserveMemory(JNIEnv* env, jobject o, jlong size))
  jlong addr = 0;

  addr = (jlong)(uintptr_t)os::reserve_memory(size);
  MemTracker::record_virtual_memory_type((address)addr, mtTest);

  return addr;
WB_END

WB_ENTRY(jlong, WB_NMTAttemptReserveMemoryAt(JNIEnv* env, jobject o, jlong addr, jlong size))
  addr = (jlong)(uintptr_t)os::attempt_reserve_memory_at((char*)(uintptr_t)addr, (size_t)size);
  MemTracker::record_virtual_memory_type((address)addr, mtTest);

  return addr;
WB_END

WB_ENTRY(void, WB_NMTCommitMemory(JNIEnv* env, jobject o, jlong addr, jlong size))
  os::commit_memory((char *)(uintptr_t)addr, size, !ExecMem);
  MemTracker::record_virtual_memory_type((address)(uintptr_t)addr, mtTest);
WB_END

WB_ENTRY(void, WB_NMTUncommitMemory(JNIEnv* env, jobject o, jlong addr, jlong size))
  os::uncommit_memory((char *)(uintptr_t)addr, size);
WB_END

WB_ENTRY(void, WB_NMTReleaseMemory(JNIEnv* env, jobject o, jlong addr, jlong size))
  os::release_memory((char *)(uintptr_t)addr, size);
WB_END

WB_ENTRY(jint, WB_NMTGetHashSize(JNIEnv* env, jobject o))
  int hash_size = MallocSiteTable::hash_buckets();
  assert(hash_size > 0, "NMT hash_size should be > 0");
  return (jint)hash_size;
WB_END

WB_ENTRY(jlong, WB_NMTNewArena(JNIEnv* env, jobject o, jlong init_size))
  Arena* arena =  new (mtTest) Arena(mtTest, size_t(init_size));
  return (jlong)arena;
WB_END

WB_ENTRY(void, WB_NMTFreeArena(JNIEnv* env, jobject o, jlong arena))
  Arena* a = (Arena*)arena;
  delete a;
WB_END

WB_ENTRY(void, WB_NMTArenaMalloc(JNIEnv* env, jobject o, jlong arena, jlong size))
  Arena* a = (Arena*)arena;
  a->Amalloc(size_t(size));
WB_END

static jmethodID reflected_method_to_jmid(JavaThread* thread, JNIEnv* env, jobject method) {
  assert(method != NULL, "method should not be null");
  ThreadToNativeFromVM ttn(thread);
  return env->FromReflectedMethod(method);
}

// Deoptimizes all compiled frames and makes nmethods not entrant if it's requested
class VM_WhiteBoxDeoptimizeFrames : public VM_WhiteBoxOperation {
 private:
  int _result;
  const bool _make_not_entrant;
 public:
  VM_WhiteBoxDeoptimizeFrames(bool make_not_entrant) :
        _result(0), _make_not_entrant(make_not_entrant) { }
  int  result() const { return _result; }

  void doit() {
    for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) {
      if (t->has_last_Java_frame()) {
        for (StackFrameStream fst(t, false /* update */, true /* process_frames */); !fst.is_done(); fst.next()) {
          frame* f = fst.current();
          if (f->can_be_deoptimized() && !f->is_deoptimized_frame()) {
            Deoptimization::deoptimize(t, *f);
            if (_make_not_entrant) {
                CompiledMethod* cm = CodeCache::find_compiled(f->pc());
                assert(cm != NULL, "sanity check");
                cm->make_not_entrant();
            }
            ++_result;
          }
        }
      }
    }
  }
};

WB_ENTRY(jint, WB_DeoptimizeFrames(JNIEnv* env, jobject o, jboolean make_not_entrant))
  VM_WhiteBoxDeoptimizeFrames op(make_not_entrant == JNI_TRUE);
  VMThread::execute(&op);
  return op.result();
WB_END

WB_ENTRY(jboolean, WB_IsFrameDeoptimized(JNIEnv* env, jobject o, jint depth))
  bool result = false;
  if (thread->has_last_Java_frame()) {
    RegisterMap reg_map(thread,
                        RegisterMap::UpdateMap::include,
                        RegisterMap::ProcessFrames::include,
                        RegisterMap::WalkContinuation::skip);
    javaVFrame *jvf = thread->last_java_vframe(®_map);
    for (jint d = 0; d < depth && jvf != NULL; d++) {
      jvf = jvf->java_sender();
    }
    result = jvf != NULL && jvf->fr().is_deoptimized_frame();
  }
  return result;
WB_END

WB_ENTRY(void, WB_DeoptimizeAll(JNIEnv* env, jobject o))
  CodeCache::mark_all_nmethods_for_deoptimization();
  Deoptimization::deoptimize_all_marked();
WB_END

WB_ENTRY(jint, WB_DeoptimizeMethod(JNIEnv* env, jobject o, jobject method, jboolean is_osr))
  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
  int result = 0;
  CHECK_JNI_EXCEPTION_(env, result);
  MutexLocker mu(Compile_lock);
  methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
  if (is_osr) {
    result += mh->mark_osr_nmethods();
  } else if (mh->code() != NULL) {
    mh->code()->mark_for_deoptimization();
    ++result;
  }
  result += CodeCache::mark_for_deoptimization(mh());
  if (result > 0) {
    Deoptimization::deoptimize_all_marked();
  }
  return result;
WB_END

WB_ENTRY(jboolean, WB_IsMethodCompiled(JNIEnv* env, jobject o, jobject method, jboolean is_osr))
  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
  CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
  MutexLocker mu(Compile_lock);
  methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
  CompiledMethod* code = is_osr ? mh->lookup_osr_nmethod_for(InvocationEntryBci, CompLevel_none, false) : mh->code();
  if (code == NULL) {
    return JNI_FALSE;
  }
  return !code->is_marked_for_deoptimization();
WB_END

static bool is_excluded_for_compiler(AbstractCompiler* comp, methodHandle& mh) {
  if (comp == NULL) {
    return true;
  }
  DirectiveSet* directive = DirectivesStack::getMatchingDirective(mh, comp);
  if (directive->ExcludeOption) {
    return true;
  }
  return false;
}

static bool can_be_compiled_at_level(methodHandle& mh, jboolean is_osr, int level) {
  if (is_osr) {
    return CompilationPolicy::can_be_osr_compiled(mh, level);
  } else {
    return CompilationPolicy::can_be_compiled(mh, level);
  }
}

WB_ENTRY(jboolean, WB_IsMethodCompilable(JNIEnv* env, jobject o, jobject method, jint comp_level, jboolean is_osr))
  if (method == NULL || comp_level > CompilationPolicy::highest_compile_level()) {
    return false;
  }
  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
  CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
  MutexLocker mu(Compile_lock);
  methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));

  // The ExcludeOption directive is evaluated lazily upon compilation attempt. If a method was not tried to be compiled by
  // a compiler, yet, the method object is not set to be not compilable by that compiler. Thus, evaluate the compiler directive
  // to exclude a compilation of 'method'.
  if (comp_level == CompLevel_any) {
    // Both compilers could have ExcludeOption set. Check all combinations.
    bool excluded_c1 = is_excluded_for_compiler(CompileBroker::compiler1(), mh);
    bool excluded_c2 = is_excluded_for_compiler(CompileBroker::compiler2(), mh);
    if (excluded_c1 && excluded_c2) {
      // Compilation of 'method' excluded by both compilers.
      return false;
    }

    if (excluded_c1) {
      // C1 only has ExcludeOption set: Check if compilable with C2.
      return can_be_compiled_at_level(mh, is_osr, CompLevel_full_optimization);
    } else if (excluded_c2) {
      // C2 only has ExcludeOption set: Check if compilable with C1.
      return can_be_compiled_at_level(mh, is_osr, CompLevel_simple);
    }
  } else if (comp_level > CompLevel_none && is_excluded_for_compiler(CompileBroker::compiler((int)comp_level), mh)) {
    // Compilation of 'method' excluded by compiler used for 'comp_level'.
    return false;
  }

  return can_be_compiled_at_level(mh, is_osr, (int)comp_level);
WB_END

WB_ENTRY(jboolean, WB_IsMethodQueuedForCompilation(JNIEnv* env, jobject o, jobject method))
  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
  CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
  MutexLocker mu(Compile_lock);
  methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
  return mh->queued_for_compilation();
WB_END

WB_ENTRY(jboolean, WB_IsIntrinsicAvailable(JNIEnv* env, jobject o, jobject method, jobject compilation_context, jint compLevel))
  if (compLevel < CompLevel_none || compLevel > CompilationPolicy::highest_compile_level()) {
    return false// Intrinsic is not available on a non-existent compilation level.
  }
  jmethodID method_id, compilation_context_id;
  method_id = reflected_method_to_jmid(thread, env, method);
  CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
  methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(method_id));

  DirectiveSet* directive;
  AbstractCompiler* comp = CompileBroker::compiler((int)compLevel);
  assert(comp != NULL, "compiler not available");
  if (compilation_context != NULL) {
    compilation_context_id = reflected_method_to_jmid(thread, env, compilation_context);
    CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
    methodHandle cch(THREAD, Method::checked_resolve_jmethod_id(compilation_context_id));
    directive = DirectivesStack::getMatchingDirective(cch, comp);
  } else {
    // Calling with NULL matches default directive
    directive = DirectivesStack::getDefaultDirective(comp);
  }
  bool result = comp->is_intrinsic_available(mh, directive);
  DirectivesStack::release(directive);
  return result;
WB_END

WB_ENTRY(jint, WB_GetMethodCompilationLevel(JNIEnv* env, jobject o, jobject method, jboolean is_osr))
  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
  CHECK_JNI_EXCEPTION_(env, CompLevel_none);
  methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
  CompiledMethod* code = is_osr ? mh->lookup_osr_nmethod_for(InvocationEntryBci, CompLevel_none, false) : mh->code();
  return (code != NULL ? code->comp_level() : CompLevel_none);
WB_END

WB_ENTRY(void, WB_MakeMethodNotCompilable(JNIEnv* env, jobject o, jobject method, jint comp_level, jboolean is_osr))
  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
  CHECK_JNI_EXCEPTION(env);
  methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
  if (is_osr) {
    mh->set_not_osr_compilable("WhiteBox", comp_level);
  } else {
    mh->set_not_compilable("WhiteBox", comp_level);
  }
WB_END

WB_ENTRY(jint, WB_GetMethodDecompileCount(JNIEnv* env, jobject o, jobject method))
  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
  CHECK_JNI_EXCEPTION_(env, 0);
  methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
  uint cnt = 0;
  MethodData* mdo = mh->method_data();
  if (mdo != NULL) {
    cnt = mdo->decompile_count();
  }
  return cnt;
WB_END

// Get the trap count of a method for a specific reason. If the trap count for
// that reason did overflow, this includes the overflow trap count of the method.
// If 'reason' is NULL, the sum of the traps for all reasons will be returned.
// This number includes the overflow trap count if the trap count for any reason
// did overflow.
WB_ENTRY(jint, WB_GetMethodTrapCount(JNIEnv* env, jobject o, jobject method, jstring reason_obj))
  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
  CHECK_JNI_EXCEPTION_(env, 0);
  methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
  uint cnt = 0;
  MethodData* mdo = mh->method_data();
  if (mdo != NULL) {
    ResourceMark rm(THREAD);
    char* reason_str = (reason_obj == NULL) ?
      NULL : java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(reason_obj));
    bool overflow = false;
    for (uint reason = 0; reason < mdo->trap_reason_limit(); reason++) {
      if (reason_str != NULL && !strcmp(reason_str, Deoptimization::trap_reason_name(reason))) {
        cnt = mdo->trap_count(reason);
        // Count in the overflow trap count on overflow
        if (cnt == (uint)-1) {
          cnt = mdo->trap_count_limit() + mdo->overflow_trap_count();
        }
        break;
      } else if (reason_str == NULL) {
        uint c = mdo->trap_count(reason);
        if (c == (uint)-1) {
          c = mdo->trap_count_limit();
          if (!overflow) {
            // Count overflow trap count just once
            overflow = true;
            c += mdo->overflow_trap_count();
          }
        }
        cnt += c;
      }
    }
  }
  return cnt;
WB_END

WB_ENTRY(jint, WB_GetDeoptCount(JNIEnv* env, jobject o, jstring reason_obj, jstring action_obj))
  if (reason_obj == NULL && action_obj == NULL) {
    return Deoptimization::total_deoptimization_count();
  }
  ResourceMark rm(THREAD);
  const char *reason_str = (reason_obj == NULL) ?
    NULL : java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(reason_obj));
  const char *action_str = (action_obj == NULL) ?
    NULL : java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(action_obj));

  return Deoptimization::deoptimization_count(reason_str, action_str);
WB_END

WB_ENTRY(jint, WB_GetMethodEntryBci(JNIEnv* env, jobject o, jobject method))
  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
  CHECK_JNI_EXCEPTION_(env, InvocationEntryBci);
  methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
  CompiledMethod* code = mh->lookup_osr_nmethod_for(InvocationEntryBci, CompLevel_none, false);
  return (code != NULL && code->is_osr_method() ? code->osr_entry_bci() : InvocationEntryBci);
WB_END

WB_ENTRY(jboolean, WB_TestSetDontInlineMethod(JNIEnv* env, jobject o, jobject method, jboolean value))
  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
  CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
  methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
  bool result = mh->dont_inline();
  mh->set_dont_inline(value == JNI_TRUE);
  return result;
WB_END

WB_ENTRY(jint, WB_GetCompileQueueSize(JNIEnv* env, jobject o, jint comp_level))
  if (comp_level == CompLevel_any) {
    return CompileBroker::queue_size(CompLevel_full_optimization) /* C2 */ +
        CompileBroker::queue_size(CompLevel_full_profile) /* C1 */;
  } else {
    return CompileBroker::queue_size(comp_level);
  }
WB_END

WB_ENTRY(jboolean, WB_TestSetForceInlineMethod(JNIEnv* env, jobject o, jobject method, jboolean value))
  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
  CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
  methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
  bool result = mh->force_inline();
  mh->set_force_inline(value == JNI_TRUE);
  return result;
WB_END

#ifdef LINUX
bool WhiteBox::validate_cgroup(const char* proc_cgroups,
                               const char* proc_self_cgroup,
                               const char* proc_self_mountinfo,
                               u1* cg_flags) {
  CgroupInfo cg_infos[CG_INFO_LENGTH];
  return CgroupSubsystemFactory::determine_type(cg_infos, proc_cgroups,
                                                    proc_self_cgroup,
                                                    proc_self_mountinfo, cg_flags);
}
#endif

bool WhiteBox::compile_method(Method* method, int comp_level, int bci, JavaThread* THREAD) {
  // Screen for unavailable/bad comp level or null method
  AbstractCompiler* comp = CompileBroker::compiler(comp_level);
  if (method == NULL) {
    tty->print_cr("WB error: request to compile NULL method");
    return false;
  }
  if (comp_level > CompilationPolicy::highest_compile_level()) {
    tty->print_cr("WB error: invalid compilation level %d", comp_level);
    return false;
  }
  if (comp == NULL) {
    tty->print_cr("WB error: no compiler for requested compilation level %d", comp_level);
    return false;
  }

  // Check if compilation is blocking
  methodHandle mh(THREAD, method);
  DirectiveSet* directive = DirectivesStack::getMatchingDirective(mh, comp);
  bool is_blocking = !directive->BackgroundCompilationOption;
  DirectivesStack::release(directive);

  // Compile method and check result
  nmethod* nm = CompileBroker::compile_method(mh, bci, comp_level, mh, mh->invocation_count(), CompileTask::Reason_Whitebox, CHECK_false);
  MutexLocker mu(THREAD, Compile_lock);
  bool is_queued = mh->queued_for_compilation();
  if ((!is_blocking && is_queued) || nm != NULL) {
    return true;
  }
  // Check code again because compilation may be finished before Compile_lock is acquired.
  if (bci == InvocationEntryBci) {
    CompiledMethod* code = mh->code();
    if (code != NULL && code->as_nmethod_or_null() != NULL) {
      return true;
    }
  } else if (mh->lookup_osr_nmethod_for(bci, comp_level, false) != NULL) {
    return true;
  }
  tty->print("WB error: failed to %s compile at level %d method ", is_blocking ? "blocking" : "", comp_level);
  mh->print_short_name(tty);
  tty->cr();
  if (is_blocking && is_queued) {
    tty->print_cr("WB error: blocking compilation is still in queue!");
  }
  return false;
}

WB_ENTRY(jboolean, WB_EnqueueMethodForCompilation(JNIEnv* env, jobject o, jobject method, jint comp_level, jint bci))
  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
  CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
  return WhiteBox::compile_method(Method::checked_resolve_jmethod_id(jmid), comp_level, bci, THREAD);
WB_END

WB_ENTRY(jboolean, WB_EnqueueInitializerForCompilation(JNIEnv* env, jobject o, jclass klass, jint comp_level))
  InstanceKlass* ik = InstanceKlass::cast(java_lang_Class::as_Klass(JNIHandles::resolve(klass)));
  Method* clinit = ik->class_initializer();
  if (clinit == NULL || clinit->method_holder()->is_not_initialized()) {
    return false;
  }
  return WhiteBox::compile_method(clinit, comp_level, InvocationEntryBci, THREAD);
WB_END

WB_ENTRY(jboolean, WB_ShouldPrintAssembly(JNIEnv* env, jobject o, jobject method, jint comp_level))
  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
  CHECK_JNI_EXCEPTION_(env, JNI_FALSE);

  methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
  DirectiveSet* directive = DirectivesStack::getMatchingDirective(mh, CompileBroker::compiler(comp_level));
  bool result = directive->PrintAssemblyOption;
  DirectivesStack::release(directive);

  return result;
WB_END

WB_ENTRY(jint, WB_MatchesInline(JNIEnv* env, jobject o, jobject method, jstring pattern))
  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
  CHECK_JNI_EXCEPTION_(env, JNI_FALSE);

  methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));

  ResourceMark rm(THREAD);
  const char* error_msg = NULL;
  char* method_str = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(pattern));
  InlineMatcher* m = InlineMatcher::parse_inline_pattern(method_str, error_msg);

  if (m == NULL) {
    assert(error_msg != NULL, "Always have an error message");
    tty->print_cr("Got error: %s", error_msg);
    return -1; // Pattern failed
  }

  // Pattern works - now check if it matches
  int result;
  if (m->match(mh, InlineMatcher::force_inline)) {
    result = 2; // Force inline match
  } else if (m->match(mh, InlineMatcher::dont_inline)) {
    result = 1; // Dont inline match
  } else {
    result = 0; // No match
  }
  delete m;
  return result;
WB_END

WB_ENTRY(jint, WB_MatchesMethod(JNIEnv* env, jobject o, jobject method, jstring pattern))
  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
  CHECK_JNI_EXCEPTION_(env, JNI_FALSE);

  methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));

  ResourceMark rm;
  char* method_str = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(pattern));

  const char* error_msg = NULL;

  BasicMatcher* m = BasicMatcher::parse_method_pattern(method_str, error_msg, false);
  if (m == NULL) {
    assert(error_msg != NULL, "Must have error_msg");
    tty->print_cr("Got error: %s", error_msg);
    return -1;
  }

  // Pattern works - now check if it matches
  int result = m->matches(mh);
  delete m;
  assert(result == 0 || result == 1, "Result out of range");
  return result;
WB_END

WB_ENTRY(void, WB_MarkMethodProfiled(JNIEnv* env, jobject o, jobject method))
  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
  CHECK_JNI_EXCEPTION(env);
  methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));

  MethodData* mdo = mh->method_data();
  if (mdo == NULL) {
    Method::build_profiling_method_data(mh, CHECK_AND_CLEAR);
    mdo = mh->method_data();
  }
  mdo->init();
  InvocationCounter* icnt = mdo->invocation_counter();
  InvocationCounter* bcnt = mdo->backedge_counter();
  // set i-counter according to CompilationPolicy::is_method_profiled
  icnt->set(Tier4MinInvocationThreshold);
  bcnt->set(Tier4CompileThreshold);
WB_END

WB_ENTRY(void, WB_ClearMethodState(JNIEnv* env, jobject o, jobject method))
  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
  CHECK_JNI_EXCEPTION(env);
  methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
  MutexLocker mu(THREAD, Compile_lock);
  MethodData* mdo = mh->method_data();
  MethodCounters* mcs = mh->method_counters();

  if (mdo != NULL) {
    mdo->init();
    ResourceMark rm(THREAD);
    int arg_count = mdo->method()->size_of_parameters();
    for (int i = 0; i < arg_count; i++) {
      mdo->set_arg_modified(i, 0);
    }
    MutexLocker mu(THREAD, mdo->extra_data_lock());
    mdo->clean_method_data(/*always_clean*/true);
  }

  mh->clear_not_c1_compilable();
  mh->clear_not_c2_compilable();
  mh->clear_not_c2_osr_compilable();
  NOT_PRODUCT(mh->set_compiled_invocation_count(0));
  if (mcs != NULL) {
    mcs->clear_counters();
  }
WB_END

template <typename T, int type_enum>
static bool GetVMFlag(JavaThread* thread, JNIEnv* env, jstring name, T* value) {
  if (name == NULL) {
    return false;
  }
  ThreadToNativeFromVM ttnfv(thread);   // can't be in VM when we call JNI
  const char* flag_name = env->GetStringUTFChars(name, NULL);
  CHECK_JNI_EXCEPTION_(env, false);
  const JVMFlag* flag = JVMFlag::find_declared_flag(flag_name);
  JVMFlag::Error result = JVMFlagAccess::get<T, type_enum>(flag, value);
  env->ReleaseStringUTFChars(name, flag_name);
  return (result == JVMFlag::SUCCESS);
}

template <typename T, int type_enum>
static bool SetVMFlag(JavaThread* thread, JNIEnv* env, jstring name, T* value) {
  if (name == NULL) {
    return false;
  }
  ThreadToNativeFromVM ttnfv(thread);   // can't be in VM when we call JNI
  const char* flag_name = env->GetStringUTFChars(name, NULL);
  CHECK_JNI_EXCEPTION_(env, false);
  JVMFlag* flag = JVMFlag::find_flag(flag_name);
  JVMFlag::Error result = JVMFlagAccess::set<T, type_enum>(flag, value, JVMFlagOrigin::INTERNAL);
  env->ReleaseStringUTFChars(name, flag_name);
  return (result == JVMFlag::SUCCESS);
}

template <typename T>
static jobject box(JavaThread* thread, JNIEnv* env, Symbol* name, Symbol* sig, T value) {
  ResourceMark rm(thread);
  jclass clazz = env->FindClass(name->as_C_string());
  CHECK_JNI_EXCEPTION_(env, NULL);
  jmethodID methodID = env->GetStaticMethodID(clazz,
        vmSymbols::valueOf_name()->as_C_string(),
        sig->as_C_string());
  CHECK_JNI_EXCEPTION_(env, NULL);
  jobject result = env->CallStaticObjectMethod(clazz, methodID, value);
  CHECK_JNI_EXCEPTION_(env, NULL);
  return result;
}

static jobject booleanBox(JavaThread* thread, JNIEnv* env, jboolean value) {
  return box(thread, env, vmSymbols::java_lang_Boolean(), vmSymbols::Boolean_valueOf_signature(), value);
}
static jobject integerBox(JavaThread* thread, JNIEnv* env, jint value) {
  return box(thread, env, vmSymbols::java_lang_Integer(), vmSymbols::Integer_valueOf_signature(), value);
}
static jobject longBox(JavaThread* thread, JNIEnv* env, jlong value) {
  return box(thread, env, vmSymbols::java_lang_Long(), vmSymbols::Long_valueOf_signature(), value);
}
/* static jobject floatBox(JavaThread* thread, JNIEnv* env, jfloat value) {
  return box(thread, env, vmSymbols::java_lang_Float(), vmSymbols::Float_valueOf_signature(), value);
}*/

static jobject doubleBox(JavaThread* thread, JNIEnv* env, jdouble value) {
  return box(thread, env, vmSymbols::java_lang_Double(), vmSymbols::Double_valueOf_signature(), value);
}

static const JVMFlag* getVMFlag(JavaThread* thread, JNIEnv* env, jstring name) {
  ThreadToNativeFromVM ttnfv(thread);   // can't be in VM when we call JNI
  const char* flag_name = env->GetStringUTFChars(name, NULL);
  CHECK_JNI_EXCEPTION_(env, NULL);
  const JVMFlag* result = JVMFlag::find_declared_flag(flag_name);
  env->ReleaseStringUTFChars(name, flag_name);
  return result;
}

WB_ENTRY(jboolean, WB_IsConstantVMFlag(JNIEnv* env, jobject o, jstring name))
  const JVMFlag* flag = getVMFlag(thread, env, name);
  return (flag != NULL) && flag->is_constant_in_binary();
WB_END

WB_ENTRY(jboolean, WB_IsLockedVMFlag(JNIEnv* env, jobject o, jstring name))
  const JVMFlag* flag = getVMFlag(thread, env, name);
  return (flag != NULL) && !(flag->is_unlocked() || flag->is_unlocker());
WB_END

WB_ENTRY(jobject, WB_GetBooleanVMFlag(JNIEnv* env, jobject o, jstring name))
  bool result;
  if (GetVMFlag <JVM_FLAG_TYPE(bool)> (thread, env, name, &result)) {
    ThreadToNativeFromVM ttnfv(thread);   // can't be in VM when we call JNI
    return booleanBox(thread, env, result);
  }
  return NULL;
WB_END

template <typename T, int type_enum>
jobject GetVMFlag_longBox(JNIEnv* env, JavaThread* thread, jstring name) {
  T result;
  if (GetVMFlag <T, type_enum> (thread, env, name, &result)) {
    ThreadToNativeFromVM ttnfv(thread);   // can't be in VM when we call JNI
    return longBox(thread, env, result);
  }
  return NULL;
}

WB_ENTRY(jobject, WB_GetIntVMFlag(JNIEnv* env, jobject o, jstring name))
  return GetVMFlag_longBox<JVM_FLAG_TYPE(int)>(env, thread, name);
WB_END

WB_ENTRY(jobject, WB_GetUintVMFlag(JNIEnv* env, jobject o, jstring name))
  return GetVMFlag_longBox<JVM_FLAG_TYPE(uint)>(env, thread, name);
WB_END

WB_ENTRY(jobject, WB_GetIntxVMFlag(JNIEnv* env, jobject o, jstring name))
  return GetVMFlag_longBox<JVM_FLAG_TYPE(intx)>(env, thread, name);
WB_END

WB_ENTRY(jobject, WB_GetUintxVMFlag(JNIEnv* env, jobject o, jstring name))
  return GetVMFlag_longBox<JVM_FLAG_TYPE(uintx)>(env, thread, name);
WB_END

WB_ENTRY(jobject, WB_GetUint64VMFlag(JNIEnv* env, jobject o, jstring name))
  return GetVMFlag_longBox<JVM_FLAG_TYPE(uint64_t)>(env, thread, name);
WB_END

WB_ENTRY(jobject, WB_GetSizeTVMFlag(JNIEnv* env, jobject o, jstring name))
  return GetVMFlag_longBox<JVM_FLAG_TYPE(size_t)>(env, thread, name);
WB_END

WB_ENTRY(jobject, WB_GetDoubleVMFlag(JNIEnv* env, jobject o, jstring name))
  double result;
  if (GetVMFlag <JVM_FLAG_TYPE(double)> (thread, env, name, &result)) {
    ThreadToNativeFromVM ttnfv(thread);   // can't be in VM when we call JNI
    return doubleBox(thread, env, result);
  }
  return NULL;
WB_END

WB_ENTRY(jstring, WB_GetStringVMFlag(JNIEnv* env, jobject o, jstring name))
  ccstr ccstrResult;
  if (GetVMFlag <JVM_FLAG_TYPE(ccstr)> (thread, env, name, &ccstrResult)) {
    ThreadToNativeFromVM ttnfv(thread);   // can't be in VM when we call JNI
    jstring result = env->NewStringUTF(ccstrResult);
    CHECK_JNI_EXCEPTION_(env, NULL);
    return result;
  }
  return NULL;
WB_END

WB_ENTRY(void, WB_SetBooleanVMFlag(JNIEnv* env, jobject o, jstring name, jboolean value))
  bool result = value == JNI_TRUE ? true : false;
  SetVMFlag <JVM_FLAG_TYPE(bool)> (thread, env, name, &result);
WB_END

WB_ENTRY(void, WB_SetIntVMFlag(JNIEnv* env, jobject o, jstring name, jlong value))
  int result = value;
  SetVMFlag <JVM_FLAG_TYPE(int)> (thread, env, name, &result);
WB_END

WB_ENTRY(void, WB_SetUintVMFlag(JNIEnv* env, jobject o, jstring name, jlong value))
  uint result = value;
  SetVMFlag <JVM_FLAG_TYPE(uint)> (thread, env, name, &result);
WB_END

WB_ENTRY(void, WB_SetIntxVMFlag(JNIEnv* env, jobject o, jstring name, jlong value))
  intx result = value;
  SetVMFlag <JVM_FLAG_TYPE(intx)> (thread, env, name, &result);
WB_END

WB_ENTRY(void, WB_SetUintxVMFlag(JNIEnv* env, jobject o, jstring name, jlong value))
  uintx result = value;
  SetVMFlag <JVM_FLAG_TYPE(uintx)> (thread, env, name, &result);
WB_END

WB_ENTRY(void, WB_SetUint64VMFlag(JNIEnv* env, jobject o, jstring name, jlong value))
  uint64_t result = value;
  SetVMFlag <JVM_FLAG_TYPE(uint64_t)> (thread, env, name, &result);
WB_END

WB_ENTRY(void, WB_SetSizeTVMFlag(JNIEnv* env, jobject o, jstring name, jlong value))
  size_t result = value;
  SetVMFlag <JVM_FLAG_TYPE(size_t)> (thread, env, name, &result);
WB_END

WB_ENTRY(void, WB_SetDoubleVMFlag(JNIEnv* env, jobject o, jstring name, jdouble value))
  double result = value;
  SetVMFlag <JVM_FLAG_TYPE(double)> (thread, env, name, &result);
WB_END

WB_ENTRY(void, WB_SetStringVMFlag(JNIEnv* env, jobject o, jstring name, jstring value))
  ThreadToNativeFromVM ttnfv(thread);   // can't be in VM when we call JNI
  const char* ccstrValue;
  if (value == NULL) {
    ccstrValue = NULL;
  }
  else {
    ccstrValue = env->GetStringUTFChars(value, NULL);
    CHECK_JNI_EXCEPTION(env);
  }
  {
    ccstr param = ccstrValue;
    ThreadInVMfromNative ttvfn(thread); // back to VM
    if (SetVMFlag <JVM_FLAG_TYPE(ccstr)> (thread, env, name, ¶m)) {
      assert(param == NULL, "old value is freed automatically and not returned");
    }
  }
  if (value != NULL) {
    env->ReleaseStringUTFChars(value, ccstrValue);
  }
WB_END

WB_ENTRY(void, WB_LockCompilation(JNIEnv* env, jobject o, jlong timeout))
  WhiteBox::compilation_locked = true;
WB_END

WB_ENTRY(void, WB_UnlockCompilation(JNIEnv* env, jobject o))
  MonitorLocker mo(Compilation_lock, Mutex::_no_safepoint_check_flag);
  WhiteBox::compilation_locked = false;
  mo.notify_all();
WB_END

WB_ENTRY(jboolean, WB_IsInStringTable(JNIEnv* env, jobject o, jstring javaString))
  ResourceMark rm(THREAD);
  int len;
  jchar* name = java_lang_String::as_unicode_string(JNIHandles::resolve(javaString), len, CHECK_false);
  return (StringTable::lookup(name, len) != NULL);
WB_END

WB_ENTRY(void, WB_FullGC(JNIEnv* env, jobject o))
  Universe::heap()->soft_ref_policy()->set_should_clear_all_soft_refs(true);
  Universe::heap()->collect(GCCause::_wb_full_gc);
#if INCLUDE_G1GC
  if (UseG1GC) {
    // Needs to be cleared explicitly for G1
    Universe::heap()->soft_ref_policy()->set_should_clear_all_soft_refs(false);
  }
#endif // INCLUDE_G1GC
WB_END

WB_ENTRY(void, WB_YoungGC(JNIEnv* env, jobject o))
  Universe::heap()->collect(GCCause::_wb_young_gc);
WB_END

WB_ENTRY(void, WB_ReadReservedMemory(JNIEnv* env, jobject o))
  // static+volatile in order to force the read to happen
  // (not be eliminated by the compiler)
  static char c;
  static volatile char* p;

  p = os::reserve_memory(os::vm_allocation_granularity());
  if (p == NULL) {
    THROW_MSG(vmSymbols::java_lang_OutOfMemoryError(), "Failed to reserve memory");
  }

  c = *p;
WB_END

WB_ENTRY(jstring, WB_GetCPUFeatures(JNIEnv* env, jobject o))
  const char* features = VM_Version::features_string();
  ThreadToNativeFromVM ttn(thread);
  jstring features_string = env->NewStringUTF(features);

  CHECK_JNI_EXCEPTION_(env, NULL);

  return features_string;
WB_END

CodeBlobType WhiteBox::get_blob_type(const CodeBlob* code) {
  guarantee(WhiteBoxAPI, "internal testing API :: WhiteBox has to be enabled");
  return CodeCache::get_code_heap(code)->code_blob_type();
}

CodeHeap* WhiteBox::get_code_heap(CodeBlobType blob_type) {
  guarantee(WhiteBoxAPI, "internal testing API :: WhiteBox has to be enabled");
  return CodeCache::get_code_heap(blob_type);
}

struct CodeBlobStub {
  CodeBlobStub(const CodeBlob* blob) :
      name(os::strdup(blob->name())),
      size(blob->size()),
      blob_type(static_cast<jint>(WhiteBox::get_blob_type(blob))),
      address((jlong) blob) { }
  ~CodeBlobStub() { os::free((void*) name); }
  const charconst name;
  const jint        size;
  const jint        blob_type;
  const jlong       address;
};

static jobjectArray codeBlob2objectArray(JavaThread* thread, JNIEnv* env, CodeBlobStub* cb) {
  ResourceMark rm;
  jclass clazz = env->FindClass(vmSymbols::java_lang_Object()->as_C_string());
  CHECK_JNI_EXCEPTION_(env, NULL);
  jobjectArray result = env->NewObjectArray(4, clazz, NULL);

  jstring name = env->NewStringUTF(cb->name);
  CHECK_JNI_EXCEPTION_(env, NULL);
  env->SetObjectArrayElement(result, 0, name);

  jobject obj = integerBox(thread, env, cb->size);
  CHECK_JNI_EXCEPTION_(env, NULL);
  env->SetObjectArrayElement(result, 1, obj);

  obj = integerBox(thread, env, cb->blob_type);
  CHECK_JNI_EXCEPTION_(env, NULL);
  env->SetObjectArrayElement(result, 2, obj);

  obj = longBox(thread, env, cb->address);
  CHECK_JNI_EXCEPTION_(env, NULL);
  env->SetObjectArrayElement(result, 3, obj);

  return result;
}

WB_ENTRY(jobjectArray, WB_GetNMethod(JNIEnv* env, jobject o, jobject method, jboolean is_osr))
  ResourceMark rm(THREAD);
  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
  CHECK_JNI_EXCEPTION_(env, NULL);
  methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
  CompiledMethod* code = is_osr ? mh->lookup_osr_nmethod_for(InvocationEntryBci, CompLevel_none, false) : mh->code();
  jobjectArray result = NULL;
  if (code == NULL) {
    return result;
  }
  int comp_level = code->comp_level();
  int insts_size = code->insts_size();

  ThreadToNativeFromVM ttn(thread);
  jclass clazz = env->FindClass(vmSymbols::java_lang_Object()->as_C_string());
  CHECK_JNI_EXCEPTION_(env, NULL);
  result = env->NewObjectArray(5, clazz, NULL);
  if (result == NULL) {
    return result;
  }

  CodeBlobStub stub(code);
  jobjectArray codeBlob = codeBlob2objectArray(thread, env, &stub);
  CHECK_JNI_EXCEPTION_(env, NULL);
  env->SetObjectArrayElement(result, 0, codeBlob);

  jobject level = integerBox(thread, env, comp_level);
  CHECK_JNI_EXCEPTION_(env, NULL);
  env->SetObjectArrayElement(result, 1, level);

  jbyteArray insts = env->NewByteArray(insts_size);
  CHECK_JNI_EXCEPTION_(env, NULL);
  env->SetByteArrayRegion(insts, 0, insts_size, (jbyte*) code->insts_begin());
  env->SetObjectArrayElement(result, 2, insts);

  jobject id = integerBox(thread, env, code->compile_id());
  CHECK_JNI_EXCEPTION_(env, NULL);
  env->SetObjectArrayElement(result, 3, id);

  jobject entry_point = longBox(thread, env, (jlong) code->entry_point());
  CHECK_JNI_EXCEPTION_(env, NULL);
  env->SetObjectArrayElement(result, 4, entry_point);

  return result;
WB_END

CodeBlob* WhiteBox::allocate_code_blob(int size, CodeBlobType blob_type) {
  guarantee(WhiteBoxAPI, "internal testing API :: WhiteBox has to be enabled");
  BufferBlob* blob;
  int full_size = CodeBlob::align_code_offset(sizeof(BufferBlob));
  if (full_size < size) {
    full_size += align_up(size - full_size, oopSize);
  }
  {
    MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
    blob = (BufferBlob*) CodeCache::allocate(full_size, blob_type);
    if (blob != NULL) {
      ::new (blob) BufferBlob("WB::DummyBlob", full_size);
    }
  }
  // Track memory usage statistic after releasing CodeCache_lock
  MemoryService::track_code_cache_memory_usage();
  return blob;
}

WB_ENTRY(jlong, WB_AllocateCodeBlob(JNIEnv* env, jobject o, jint size, jint blob_type))
  if (size < 0) {
    THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
      err_msg("WB_AllocateCodeBlob: size is negative: " INT32_FORMAT, size));
  }
  return (jlong) WhiteBox::allocate_code_blob(size, static_cast<CodeBlobType>(blob_type));
WB_END

WB_ENTRY(void, WB_FreeCodeBlob(JNIEnv* env, jobject o, jlong addr))
  if (addr == 0) {
    return;
  }
  BufferBlob::free((BufferBlob*) addr);
WB_END

WB_ENTRY(jobjectArray, WB_GetCodeHeapEntries(JNIEnv* env, jobject o, jint blob_type))
  ResourceMark rm;
  GrowableArray<CodeBlobStub*> blobs;
  {
    MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
    CodeHeap* heap = WhiteBox::get_code_heap(static_cast<CodeBlobType>(blob_type));
    if (heap == NULL) {
      return NULL;
    }
    for (CodeBlob* cb = (CodeBlob*) heap->first();
         cb != NULL; cb = (CodeBlob*) heap->next(cb)) {
      CodeBlobStub* stub = NEW_RESOURCE_OBJ(CodeBlobStub);
      new (stub) CodeBlobStub(cb);
      blobs.append(stub);
    }
  }
  ThreadToNativeFromVM ttn(thread);
  jobjectArray result = NULL;
  jclass clazz = env->FindClass(vmSymbols::java_lang_Object()->as_C_string());
  CHECK_JNI_EXCEPTION_(env, NULL);
  result = env->NewObjectArray(blobs.length(), clazz, NULL);
  CHECK_JNI_EXCEPTION_(env, NULL);
  if (result == NULL) {
    return result;
  }
  int i = 0;
  for (GrowableArrayIterator<CodeBlobStub*> it = blobs.begin();
       it != blobs.end(); ++it) {
    jobjectArray obj = codeBlob2objectArray(thread, env, *it);
    CHECK_JNI_EXCEPTION_(env, NULL);
    env->SetObjectArrayElement(result, i, obj);
    CHECK_JNI_EXCEPTION_(env, NULL);
    ++i;
  }
  return result;
WB_END

WB_ENTRY(jint, WB_GetCompilationActivityMode(JNIEnv* env, jobject o))
  return CompileBroker::get_compilation_activity_mode();
WB_END

WB_ENTRY(jobjectArray, WB_GetCodeBlob(JNIEnv* env, jobject o, jlong addr))
  if (addr == 0) {
    THROW_MSG_NULL(vmSymbols::java_lang_NullPointerException(),
      "WB_GetCodeBlob: addr is null");
  }
  ThreadToNativeFromVM ttn(thread);
  CodeBlobStub stub((CodeBlob*) addr);
  return codeBlob2objectArray(thread, env, &stub);
WB_END

WB_ENTRY(jlong, WB_GetMethodData(JNIEnv* env, jobject wv, jobject method))
  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
  CHECK_JNI_EXCEPTION_(env, 0);
  methodHandle mh(thread, Method::checked_resolve_jmethod_id(jmid));
  return (jlong) mh->method_data();
WB_END

WB_ENTRY(jlong, WB_GetThreadStackSize(JNIEnv* env, jobject o))
  return (jlong) thread->stack_size();
WB_END

WB_ENTRY(jlong, WB_GetThreadRemainingStackSize(JNIEnv* env, jobject o))
  return (jlong) thread->stack_overflow_state()->stack_available(
                   os::current_stack_pointer()) - (jlong)StackOverflow::stack_shadow_zone_size();
WB_END


int WhiteBox::array_bytes_to_length(size_t bytes) {
  return Array<u1>::bytes_to_length(bytes);
}

///////////////
// MetaspaceTestContext and MetaspaceTestArena
WB_ENTRY(jlong, WB_CreateMetaspaceTestContext(JNIEnv* env, jobject wb, jlong commit_limit, jlong reserve_limit))
  metaspace::MetaspaceTestContext* context =
      new metaspace::MetaspaceTestContext("whitebox-metaspace-context", (size_t) commit_limit, (size_t) reserve_limit);
  return (jlong)p2i(context);
WB_END

WB_ENTRY(void, WB_DestroyMetaspaceTestContext(JNIEnv* env, jobject wb, jlong context))
  delete (metaspace::MetaspaceTestContext*) context;
WB_END

WB_ENTRY(void, WB_PurgeMetaspaceTestContext(JNIEnv* env, jobject wb, jlong context))
  metaspace::MetaspaceTestContext* context0 = (metaspace::MetaspaceTestContext*) context;
  context0->purge_area();
WB_END

WB_ENTRY(void, WB_PrintMetaspaceTestContext(JNIEnv* env, jobject wb, jlong context))
  metaspace::MetaspaceTestContext* context0 = (metaspace::MetaspaceTestContext*) context;
  context0->print_on(tty);
WB_END

WB_ENTRY(jlong, WB_GetTotalCommittedWordsInMetaspaceTestContext(JNIEnv* env, jobject wb, jlong context))
  metaspace::MetaspaceTestContext* context0 = (metaspace::MetaspaceTestContext*) context;
  return context0->committed_words();
WB_END

WB_ENTRY(jlong, WB_GetTotalUsedWordsInMetaspaceTestContext(JNIEnv* env, jobject wb, jlong context))
  metaspace::MetaspaceTestContext* context0 = (metaspace::MetaspaceTestContext*) context;
  return context0->used_words();
WB_END

WB_ENTRY(jlong, WB_CreateArenaInTestContext(JNIEnv* env, jobject wb, jlong context, jboolean is_micro))
  const Metaspace::MetaspaceType type = is_micro ? Metaspace::ReflectionMetaspaceType : Metaspace::StandardMetaspaceType;
  metaspace::MetaspaceTestContext* context0 = (metaspace::MetaspaceTestContext*) context;
  return (jlong)p2i(context0->create_arena(type));
WB_END

WB_ENTRY(void, WB_DestroyMetaspaceTestArena(JNIEnv* env, jobject wb, jlong arena))
  delete (metaspace::MetaspaceTestArena*) arena;
WB_END

WB_ENTRY(jlong, WB_AllocateFromMetaspaceTestArena(JNIEnv* env, jobject wb, jlong arena, jlong word_size))
  metaspace::MetaspaceTestArena* arena0 = (metaspace::MetaspaceTestArena*) arena;
  MetaWord* p = arena0->allocate((size_t) word_size);
  return (jlong)p2i(p);
WB_END

WB_ENTRY(void, WB_DeallocateToMetaspaceTestArena(JNIEnv* env, jobject wb, jlong arena, jlong p, jlong word_size))
  metaspace::MetaspaceTestArena* arena0 = (metaspace::MetaspaceTestArena*) arena;
  arena0->deallocate((MetaWord*)p, (size_t) word_size);
WB_END

WB_ENTRY(jlong, WB_GetMaxMetaspaceAllocationSize(JNIEnv* env, jobject wb))
  return (jlong) Metaspace::max_allocation_word_size() * BytesPerWord;
WB_END

//////////////

WB_ENTRY(jlong, WB_AllocateMetaspace(JNIEnv* env, jobject wb, jobject class_loader, jlong size))
  if (size < 0) {
    THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
        err_msg("WB_AllocateMetaspace: size is negative: " JLONG_FORMAT, size));
  }

  oop class_loader_oop = JNIHandles::resolve(class_loader);
  ClassLoaderData* cld = class_loader_oop != NULL
      ? java_lang_ClassLoader::loader_data_acquire(class_loader_oop)
      : ClassLoaderData::the_null_class_loader_data();

  void* metadata = MetadataFactory::new_array<u1>(cld, WhiteBox::array_bytes_to_length((size_t)size), thread);

  return (jlong)(uintptr_t)metadata;
WB_END

WB_ENTRY(void, WB_DefineModule(JNIEnv* env, jobject o, jobject module, jboolean is_open,
                                jstring version, jstring location, jobjectArray packages))
  Handle h_module (THREAD, JNIHandles::resolve(module));
  Modules::define_module(h_module, is_open, version, location, packages, CHECK);
WB_END

WB_ENTRY(void, WB_AddModuleExports(JNIEnv* env, jobject o, jobject from_module, jstring package, jobject to_module))
  Handle h_from_module (THREAD, JNIHandles::resolve(from_module));
  Handle h_to_module (THREAD, JNIHandles::resolve(to_module));
  Modules::add_module_exports_qualified(h_from_module, package, h_to_module, CHECK);
WB_END

WB_ENTRY(void, WB_AddModuleExportsToAllUnnamed(JNIEnv* env, jobject o, jclass module, jstring package))
  Handle h_module (THREAD, JNIHandles::resolve(module));
  Modules::add_module_exports_to_all_unnamed(h_module, package, CHECK);
WB_END

WB_ENTRY(void, WB_AddModuleExportsToAll(JNIEnv* env, jobject o, jclass module, jstring package))
--> --------------------

--> maximum size reached

--> --------------------

¤ Dauer der Verarbeitung: 0.864 Sekunden  (vorverarbeitet)  ¤





Download des
Quellennavigators
Download des
sprechenden Kalenders

in der Quellcodebibliothek suchen




Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.


Bemerkung:

Die farbliche Syntaxdarstellung ist noch experimentell.


Bot Zugriff