whitebox.cpp revision 7462:a0dd995271c4
1216295Ssyrinx/*
2216295Ssyrinx * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
3216295Ssyrinx * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4216295Ssyrinx *
5216295Ssyrinx * This code is free software; you can redistribute it and/or modify it
6216295Ssyrinx * under the terms of the GNU General Public License version 2 only, as
7216295Ssyrinx * published by the Free Software Foundation.
8216295Ssyrinx *
9216295Ssyrinx * This code is distributed in the hope that it will be useful, but WITHOUT
10216295Ssyrinx * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11216295Ssyrinx * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12216295Ssyrinx * version 2 for more details (a copy is included in the LICENSE file that
13216295Ssyrinx * accompanied this code).
14216295Ssyrinx *
15216295Ssyrinx * You should have received a copy of the GNU General Public License version
16216295Ssyrinx * 2 along with this work; if not, write to the Free Software Foundation,
17216295Ssyrinx * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18216295Ssyrinx *
19216295Ssyrinx * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20216295Ssyrinx * or visit www.oracle.com if you need additional information or have any
21216295Ssyrinx * questions.
22216295Ssyrinx *
23216295Ssyrinx */
24216295Ssyrinx
25216295Ssyrinx#include "precompiled.hpp"
26216295Ssyrinx
27216295Ssyrinx#include <new>
28216295Ssyrinx
29216295Ssyrinx#include "code/codeCache.hpp"
30216295Ssyrinx#include "memory/metadataFactory.hpp"
31216295Ssyrinx#include "memory/universe.hpp"
32216295Ssyrinx#include "oops/oop.inline.hpp"
33216295Ssyrinx
34216295Ssyrinx#include "classfile/stringTable.hpp"
35216295Ssyrinx#include "classfile/classLoaderData.hpp"
36216295Ssyrinx
37216295Ssyrinx#include "prims/whitebox.hpp"
38216295Ssyrinx#include "prims/wbtestmethods/parserTests.hpp"
39216295Ssyrinx
40216295Ssyrinx#include "runtime/thread.hpp"
41216295Ssyrinx#include "runtime/arguments.hpp"
42216295Ssyrinx#include "runtime/deoptimization.hpp"
43216295Ssyrinx#include "runtime/interfaceSupport.hpp"
44216295Ssyrinx#include "runtime/os.hpp"
45216295Ssyrinx#include "runtime/vm_version.hpp"
46216295Ssyrinx#include "runtime/sweeper.hpp"
47216295Ssyrinx
48216295Ssyrinx#include "utilities/array.hpp"
49216295Ssyrinx#include "utilities/debug.hpp"
50216295Ssyrinx#include "utilities/macros.hpp"
51216295Ssyrinx#include "utilities/exceptions.hpp"
52216295Ssyrinx
53216295Ssyrinx#if INCLUDE_ALL_GCS
54216295Ssyrinx#include "gc_implementation/parallelScavenge/parallelScavengeHeap.inline.hpp"
55216295Ssyrinx#include "gc_implementation/g1/concurrentMark.hpp"
56216295Ssyrinx#include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
57216295Ssyrinx#include "gc_implementation/g1/heapRegionRemSet.hpp"
58216295Ssyrinx#endif // INCLUDE_ALL_GCS
59216295Ssyrinx
60216295Ssyrinx#if INCLUDE_NMT
61216295Ssyrinx#include "services/mallocSiteTable.hpp"
62216295Ssyrinx#include "services/memTracker.hpp"
63216295Ssyrinx#include "utilities/nativeCallStack.hpp"
64216295Ssyrinx#endif // INCLUDE_NMT
65216295Ssyrinx
66216295Ssyrinx#include "compiler/compileBroker.hpp"
67216295Ssyrinx#include "jvmtifiles/jvmtiEnv.hpp"
68216295Ssyrinx#include "runtime/compilationPolicy.hpp"
69216295Ssyrinx
70216295SsyrinxPRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
71216295Ssyrinx
72216295Ssyrinx#define SIZE_T_MAX_VALUE ((size_t) -1)
73216295Ssyrinx
74216295Ssyrinxbool WhiteBox::_used = false;
75216295Ssyrinxvolatile bool WhiteBox::compilation_locked = false;
76216295Ssyrinx
77216295SsyrinxWB_ENTRY(jlong, WB_GetObjectAddress(JNIEnv* env, jobject o, jobject obj))
78216295Ssyrinx  return (jlong)(void*)JNIHandles::resolve(obj);
79216295SsyrinxWB_END
80216295Ssyrinx
81216295SsyrinxWB_ENTRY(jint, WB_GetHeapOopSize(JNIEnv* env, jobject o))
82216295Ssyrinx  return heapOopSize;
83216295SsyrinxWB_END
84216295Ssyrinx
85216295SsyrinxWB_ENTRY(jint, WB_GetVMPageSize(JNIEnv* env, jobject o))
86216295Ssyrinx  return os::vm_page_size();
87216295SsyrinxWB_END
88216295Ssyrinx
89216295Ssyrinxclass WBIsKlassAliveClosure : public KlassClosure {
90228990Suqs    Symbol* _name;
91216295Ssyrinx    bool _found;
92216295Ssyrinxpublic:
93216295Ssyrinx    WBIsKlassAliveClosure(Symbol* name) : _name(name), _found(false) {}
94216295Ssyrinx
95216295Ssyrinx    void do_klass(Klass* k) {
96216295Ssyrinx      if (_found) return;
97216295Ssyrinx      Symbol* ksym = k->name();
98216295Ssyrinx      if (ksym->fast_compare(_name) == 0) {
99216295Ssyrinx        _found = true;
100216295Ssyrinx      }
101216295Ssyrinx    }
102216295Ssyrinx
103216295Ssyrinx    bool found() const {
104216295Ssyrinx        return _found;
105216295Ssyrinx    }
106216295Ssyrinx};
107216295Ssyrinx
108216295SsyrinxWB_ENTRY(jboolean, WB_IsClassAlive(JNIEnv* env, jobject target, jstring name))
109216295Ssyrinx  Handle h_name = JNIHandles::resolve(name);
110216295Ssyrinx  if (h_name.is_null()) return false;
111216295Ssyrinx  Symbol* sym = java_lang_String::as_symbol(h_name, CHECK_false);
112216295Ssyrinx  TempNewSymbol tsym(sym); // Make sure to decrement reference count on sym on return
113216295Ssyrinx
114216295Ssyrinx  WBIsKlassAliveClosure closure(sym);
115216295Ssyrinx  ClassLoaderDataGraph::classes_do(&closure);
116216295Ssyrinx
117216295Ssyrinx  return closure.found();
118216295SsyrinxWB_END
119216295Ssyrinx
120216295SsyrinxWB_ENTRY(void, WB_AddToBootstrapClassLoaderSearch(JNIEnv* env, jobject o, jstring segment)) {
121216295Ssyrinx#if INCLUDE_JVMTI
122216295Ssyrinx  ResourceMark rm;
123216295Ssyrinx  const char* seg = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(segment));
124216295Ssyrinx  JvmtiEnv* jvmti_env = JvmtiEnv::create_a_jvmti(JVMTI_VERSION);
125216295Ssyrinx  jvmtiError err = jvmti_env->AddToBootstrapClassLoaderSearch(seg);
126216295Ssyrinx  assert(err == JVMTI_ERROR_NONE, "must not fail");
127216295Ssyrinx#endif
128216295Ssyrinx}
129216295SsyrinxWB_END
130216295Ssyrinx
131216295SsyrinxWB_ENTRY(void, WB_AddToSystemClassLoaderSearch(JNIEnv* env, jobject o, jstring segment)) {
132216295Ssyrinx#if INCLUDE_JVMTI
133216295Ssyrinx  ResourceMark rm;
134216295Ssyrinx  const char* seg = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(segment));
135229933Ssyrinx  JvmtiEnv* jvmti_env = JvmtiEnv::create_a_jvmti(JVMTI_VERSION);
136216295Ssyrinx  jvmtiError err = jvmti_env->AddToSystemClassLoaderSearch(seg);
137216295Ssyrinx  assert(err == JVMTI_ERROR_NONE, "must not fail");
138216295Ssyrinx#endif
139216295Ssyrinx}
140216295SsyrinxWB_END
141216295Ssyrinx
142216295Ssyrinx
143216295SsyrinxWB_ENTRY(jlong, WB_GetCompressedOopsMaxHeapSize(JNIEnv* env, jobject o)) {
144216295Ssyrinx  return (jlong)Arguments::max_heap_for_compressed_oops();
145216295Ssyrinx}
146216295SsyrinxWB_END
147216295Ssyrinx
148216295SsyrinxWB_ENTRY(void, WB_PrintHeapSizes(JNIEnv* env, jobject o)) {
149216295Ssyrinx  CollectorPolicy * p = Universe::heap()->collector_policy();
150216295Ssyrinx  gclog_or_tty->print_cr("Minimum heap "SIZE_FORMAT" Initial heap "
151216295Ssyrinx    SIZE_FORMAT" Maximum heap "SIZE_FORMAT" Space alignment "SIZE_FORMAT" Heap alignment "SIZE_FORMAT,
152216295Ssyrinx    p->min_heap_byte_size(), p->initial_heap_byte_size(), p->max_heap_byte_size(),
153216295Ssyrinx    p->space_alignment(), p->heap_alignment());
154216295Ssyrinx}
155216295SsyrinxWB_END
156216295Ssyrinx
157216295Ssyrinx#ifndef PRODUCT
158216295Ssyrinx// Forward declaration
159216295Ssyrinxvoid TestReservedSpace_test();
160216295Ssyrinxvoid TestReserveMemorySpecial_test();
161216295Ssyrinxvoid TestVirtualSpace_test();
162216295Ssyrinxvoid TestMetaspaceAux_test();
163216295Ssyrinx#endif
164216295Ssyrinx
165216295SsyrinxWB_ENTRY(void, WB_RunMemoryUnitTests(JNIEnv* env, jobject o))
166216295Ssyrinx#ifndef PRODUCT
167216295Ssyrinx  TestReservedSpace_test();
168216295Ssyrinx  TestReserveMemorySpecial_test();
169216295Ssyrinx  TestVirtualSpace_test();
170216295Ssyrinx  TestMetaspaceAux_test();
171216295Ssyrinx#endif
172216295SsyrinxWB_END
173216295Ssyrinx
174216295SsyrinxWB_ENTRY(void, WB_ReadFromNoaccessArea(JNIEnv* env, jobject o))
175216295Ssyrinx  size_t granularity = os::vm_allocation_granularity();
176216295Ssyrinx  ReservedHeapSpace rhs(100 * granularity, granularity, false, NULL);
177216295Ssyrinx  VirtualSpace vs;
178216295Ssyrinx  vs.initialize(rhs, 50 * granularity);
179216295Ssyrinx
180216295Ssyrinx  //Check if constraints are complied
181216295Ssyrinx  if (!( UseCompressedOops && rhs.base() != NULL &&
182216295Ssyrinx         Universe::narrow_oop_base() != NULL &&
183216295Ssyrinx         Universe::narrow_oop_use_implicit_null_checks() )) {
184216295Ssyrinx    tty->print_cr("WB_ReadFromNoaccessArea method is useless:\n "
185216295Ssyrinx                  "\tUseCompressedOops is %d\n"
186216295Ssyrinx                  "\trhs.base() is "PTR_FORMAT"\n"
187216295Ssyrinx                  "\tUniverse::narrow_oop_base() is "PTR_FORMAT"\n"
188216295Ssyrinx                  "\tUniverse::narrow_oop_use_implicit_null_checks() is %d",
189216295Ssyrinx                  UseCompressedOops,
190216295Ssyrinx                  rhs.base(),
191216295Ssyrinx                  Universe::narrow_oop_base(),
192216295Ssyrinx                  Universe::narrow_oop_use_implicit_null_checks());
193216295Ssyrinx    return;
194216295Ssyrinx  }
195216295Ssyrinx  tty->print_cr("Reading from no access area... ");
196216295Ssyrinx  tty->print_cr("*(vs.low_boundary() - rhs.noaccess_prefix() / 2 ) = %c",
197216295Ssyrinx                *(vs.low_boundary() - rhs.noaccess_prefix() / 2 ));
198216295SsyrinxWB_END
199216295Ssyrinx
200216295Ssyrinxstatic jint wb_stress_virtual_space_resize(size_t reserved_space_size,
201216295Ssyrinx                                           size_t magnitude, size_t iterations) {
202216295Ssyrinx  size_t granularity = os::vm_allocation_granularity();
203216295Ssyrinx  ReservedHeapSpace rhs(reserved_space_size * granularity, granularity, false, NULL);
204216295Ssyrinx  VirtualSpace vs;
205216295Ssyrinx  if (!vs.initialize(rhs, 0)) {
206216295Ssyrinx    tty->print_cr("Failed to initialize VirtualSpace. Can't proceed.");
207216295Ssyrinx    return 3;
208216295Ssyrinx  }
209216295Ssyrinx
210216295Ssyrinx  long seed = os::random();
211216295Ssyrinx  tty->print_cr("Random seed is %ld", seed);
212216295Ssyrinx  os::init_random(seed);
213216295Ssyrinx
214216295Ssyrinx  for (size_t i = 0; i < iterations; i++) {
215216295Ssyrinx
216216295Ssyrinx    // Whether we will shrink or grow
217216295Ssyrinx    bool shrink = os::random() % 2L == 0;
218216295Ssyrinx
219216295Ssyrinx    // Get random delta to resize virtual space
220216295Ssyrinx    size_t delta = (size_t)os::random() % magnitude;
221216295Ssyrinx
222216295Ssyrinx    // If we are about to shrink virtual space below zero, then expand instead
223216295Ssyrinx    if (shrink && vs.committed_size() < delta) {
224216295Ssyrinx      shrink = false;
225216295Ssyrinx    }
226216295Ssyrinx
227216295Ssyrinx    // Resizing by delta
228216295Ssyrinx    if (shrink) {
229216295Ssyrinx      vs.shrink_by(delta);
230216295Ssyrinx    } else {
231228990Suqs      // If expanding fails expand_by will silently return false
232216295Ssyrinx      vs.expand_by(delta, true);
233216295Ssyrinx    }
234216295Ssyrinx  }
235216295Ssyrinx  return 0;
236228990Suqs}
237216295Ssyrinx
238216295SsyrinxWB_ENTRY(jint, WB_StressVirtualSpaceResize(JNIEnv* env, jobject o,
239216295Ssyrinx        jlong reserved_space_size, jlong magnitude, jlong iterations))
240216295Ssyrinx  tty->print_cr("reservedSpaceSize="JLONG_FORMAT", magnitude="JLONG_FORMAT", "
241216295Ssyrinx                "iterations="JLONG_FORMAT"\n", reserved_space_size, magnitude,
242216295Ssyrinx                iterations);
243216295Ssyrinx  if (reserved_space_size < 0 || magnitude < 0 || iterations < 0) {
244216295Ssyrinx    tty->print_cr("One of variables printed above is negative. Can't proceed.\n");
245216295Ssyrinx    return 1;
246216295Ssyrinx  }
247216295Ssyrinx
248216295Ssyrinx  // sizeof(size_t) depends on whether OS is 32bit or 64bit. sizeof(jlong) is
249216295Ssyrinx  // always 8 byte. That's why we should avoid overflow in case of 32bit platform.
250216295Ssyrinx  if (sizeof(size_t) < sizeof(jlong)) {
251216295Ssyrinx    jlong size_t_max_value = (jlong) SIZE_T_MAX_VALUE;
252216295Ssyrinx    if (reserved_space_size > size_t_max_value || magnitude > size_t_max_value
253216295Ssyrinx        || iterations > size_t_max_value) {
254216295Ssyrinx      tty->print_cr("One of variables printed above overflows size_t. Can't proceed.\n");
255216295Ssyrinx      return 2;
256216295Ssyrinx    }
257216295Ssyrinx  }
258216295Ssyrinx
259216295Ssyrinx  return wb_stress_virtual_space_resize((size_t) reserved_space_size,
260216295Ssyrinx                                        (size_t) magnitude, (size_t) iterations);
261216295SsyrinxWB_END
262216295Ssyrinx
263216295SsyrinxWB_ENTRY(jboolean, WB_isObjectInOldGen(JNIEnv* env, jobject o, jobject obj))
264216295Ssyrinx  oop p = JNIHandles::resolve(obj);
265216295Ssyrinx#if INCLUDE_ALL_GCS
266216295Ssyrinx  if (UseG1GC) {
267216295Ssyrinx    G1CollectedHeap* g1 = G1CollectedHeap::heap();
268216295Ssyrinx    const HeapRegion* hr = g1->heap_region_containing(p);
269216295Ssyrinx    if (hr == NULL) {
270216295Ssyrinx      return false;
271216295Ssyrinx    }
272216295Ssyrinx    return !(hr->is_young());
273216295Ssyrinx  } else if (UseParallelGC) {
274216295Ssyrinx    ParallelScavengeHeap* psh = ParallelScavengeHeap::heap();
275216295Ssyrinx    return !psh->is_in_young(p);
276216295Ssyrinx  }
277216295Ssyrinx#endif // INCLUDE_ALL_GCS
278216295Ssyrinx  GenCollectedHeap* gch = GenCollectedHeap::heap();
279216295Ssyrinx  return !gch->is_in_young(p);
280216295SsyrinxWB_END
281216295Ssyrinx
282216295SsyrinxWB_ENTRY(jlong, WB_GetObjectSize(JNIEnv* env, jobject o, jobject obj))
283216295Ssyrinx  oop p = JNIHandles::resolve(obj);
284216295Ssyrinx  return p->size() * HeapWordSize;
285216295SsyrinxWB_END
286216295Ssyrinx
287216295Ssyrinx#if INCLUDE_ALL_GCS
288216295SsyrinxWB_ENTRY(jboolean, WB_G1IsHumongous(JNIEnv* env, jobject o, jobject obj))
289216295Ssyrinx  G1CollectedHeap* g1 = G1CollectedHeap::heap();
290216295Ssyrinx  oop result = JNIHandles::resolve(obj);
291216295Ssyrinx  const HeapRegion* hr = g1->heap_region_containing(result);
292216295Ssyrinx  return hr->is_humongous();
293216295SsyrinxWB_END
294216295Ssyrinx
295216295SsyrinxWB_ENTRY(jlong, WB_G1NumFreeRegions(JNIEnv* env, jobject o))
296216295Ssyrinx  G1CollectedHeap* g1 = G1CollectedHeap::heap();
297216295Ssyrinx  size_t nr = g1->num_free_regions();
298216295Ssyrinx  return (jlong)nr;
299216295SsyrinxWB_END
300216295Ssyrinx
301216295SsyrinxWB_ENTRY(jboolean, WB_G1InConcurrentMark(JNIEnv* env, jobject o))
302216295Ssyrinx  G1CollectedHeap* g1 = G1CollectedHeap::heap();
303216295Ssyrinx  ConcurrentMark* cm = g1->concurrent_mark();
304216295Ssyrinx  return cm->concurrent_marking_in_progress();
305216295SsyrinxWB_END
306216295Ssyrinx
307216295SsyrinxWB_ENTRY(jint, WB_G1RegionSize(JNIEnv* env, jobject o))
308216295Ssyrinx  return (jint)HeapRegion::GrainBytes;
309216295SsyrinxWB_END
310216295Ssyrinx#endif // INCLUDE_ALL_GCS
311216295Ssyrinx
312216295Ssyrinx#if INCLUDE_NMT
313216295Ssyrinx// Alloc memory using the test memory type so that we can use that to see if
314216295Ssyrinx// NMT picks it up correctly
315216295SsyrinxWB_ENTRY(jlong, WB_NMTMalloc(JNIEnv* env, jobject o, jlong size))
316216295Ssyrinx  jlong addr = 0;
317216295Ssyrinx  addr = (jlong)(uintptr_t)os::malloc(size, mtTest);
318216295Ssyrinx  return addr;
319216295SsyrinxWB_END
320216295Ssyrinx
321216295Ssyrinx// Alloc memory with pseudo call stack. The test can create psudo malloc
322216295Ssyrinx// allocation site to stress the malloc tracking.
323216295SsyrinxWB_ENTRY(jlong, WB_NMTMallocWithPseudoStack(JNIEnv* env, jobject o, jlong size, jint pseudo_stack))
324216295Ssyrinx  address pc = (address)(size_t)pseudo_stack;
325216295Ssyrinx  NativeCallStack stack(&pc, 1);
326216295Ssyrinx  return (jlong)(uintptr_t)os::malloc(size, mtTest, stack);
327216295SsyrinxWB_END
328216295Ssyrinx
329216295Ssyrinx// Free the memory allocated by NMTAllocTest
330216295SsyrinxWB_ENTRY(void, WB_NMTFree(JNIEnv* env, jobject o, jlong mem))
331216295Ssyrinx  os::free((void*)(uintptr_t)mem);
332216295SsyrinxWB_END
333216295Ssyrinx
334216295SsyrinxWB_ENTRY(jlong, WB_NMTReserveMemory(JNIEnv* env, jobject o, jlong size))
335216295Ssyrinx  jlong addr = 0;
336216295Ssyrinx
337216295Ssyrinx  addr = (jlong)(uintptr_t)os::reserve_memory(size);
338216295Ssyrinx  MemTracker::record_virtual_memory_type((address)addr, mtTest);
339216295Ssyrinx
340216295Ssyrinx  return addr;
341216295SsyrinxWB_END
342216295Ssyrinx
343216295SsyrinxWB_ENTRY(void, WB_NMTCommitMemory(JNIEnv* env, jobject o, jlong addr, jlong size))
344216295Ssyrinx  os::commit_memory((char *)(uintptr_t)addr, size, !ExecMem);
345216295Ssyrinx  MemTracker::record_virtual_memory_type((address)(uintptr_t)addr, mtTest);
346216295SsyrinxWB_END
347216295Ssyrinx
348216295SsyrinxWB_ENTRY(void, WB_NMTUncommitMemory(JNIEnv* env, jobject o, jlong addr, jlong size))
349216295Ssyrinx  os::uncommit_memory((char *)(uintptr_t)addr, size);
350216295SsyrinxWB_END
351216295Ssyrinx
352216295SsyrinxWB_ENTRY(void, WB_NMTReleaseMemory(JNIEnv* env, jobject o, jlong addr, jlong size))
353216295Ssyrinx  os::release_memory((char *)(uintptr_t)addr, size);
354216295SsyrinxWB_END
355216295Ssyrinx
356216295SsyrinxWB_ENTRY(jboolean, WB_NMTIsDetailSupported(JNIEnv* env))
357216295Ssyrinx  return MemTracker::tracking_level() == NMT_detail;
358216295SsyrinxWB_END
359216295Ssyrinx
360216295SsyrinxWB_ENTRY(jboolean, WB_NMTChangeTrackingLevel(JNIEnv* env))
361216295Ssyrinx  // Test that we can downgrade NMT levels but not upgrade them.
362216295Ssyrinx  if (MemTracker::tracking_level() == NMT_off) {
363216295Ssyrinx    MemTracker::transition_to(NMT_off);
364216295Ssyrinx    return MemTracker::tracking_level() == NMT_off;
365216295Ssyrinx  } else {
366216295Ssyrinx    assert(MemTracker::tracking_level() == NMT_detail, "Should start out as detail tracking");
367216295Ssyrinx    MemTracker::transition_to(NMT_summary);
368216295Ssyrinx    assert(MemTracker::tracking_level() == NMT_summary, "Should be summary now");
369216295Ssyrinx
370216295Ssyrinx    // Can't go to detail once NMT is set to summary.
371216295Ssyrinx    MemTracker::transition_to(NMT_detail);
372216295Ssyrinx    assert(MemTracker::tracking_level() == NMT_summary, "Should still be summary now");
373216295Ssyrinx
374216295Ssyrinx    // Shutdown sets tracking level to minimal.
375216295Ssyrinx    MemTracker::shutdown();
376216295Ssyrinx    assert(MemTracker::tracking_level() == NMT_minimal, "Should be minimal now");
377216295Ssyrinx
378216295Ssyrinx    // Once the tracking level is minimal, we cannot increase to summary.
379216295Ssyrinx    // The code ignores this request instead of asserting because if the malloc site
380216295Ssyrinx    // table overflows in another thread, it tries to change the code to summary.
381216295Ssyrinx    MemTracker::transition_to(NMT_summary);
382216295Ssyrinx    assert(MemTracker::tracking_level() == NMT_minimal, "Should still be minimal now");
383216295Ssyrinx
384216295Ssyrinx    // Really can never go up to detail, verify that the code would never do this.
385216295Ssyrinx    MemTracker::transition_to(NMT_detail);
386216295Ssyrinx    assert(MemTracker::tracking_level() == NMT_minimal, "Should still be minimal now");
387216295Ssyrinx    return MemTracker::tracking_level() == NMT_minimal;
388216295Ssyrinx  }
389216295SsyrinxWB_END
390216295Ssyrinx
391216295SsyrinxWB_ENTRY(jint, WB_NMTGetHashSize(JNIEnv* env, jobject o))
392216295Ssyrinx  int hash_size = MallocSiteTable::hash_buckets();
393216295Ssyrinx  assert(hash_size > 0, "NMT hash_size should be > 0");
394216295Ssyrinx  return (jint)hash_size;
395216295SsyrinxWB_END
396216295Ssyrinx#endif // INCLUDE_NMT
397216295Ssyrinx
398216295Ssyrinxstatic jmethodID reflected_method_to_jmid(JavaThread* thread, JNIEnv* env, jobject method) {
399216295Ssyrinx  assert(method != NULL, "method should not be null");
400216295Ssyrinx  ThreadToNativeFromVM ttn(thread);
401216295Ssyrinx  return env->FromReflectedMethod(method);
402216295Ssyrinx}
403216295Ssyrinx
404216295SsyrinxWB_ENTRY(void, WB_DeoptimizeAll(JNIEnv* env, jobject o))
405216295Ssyrinx  MutexLockerEx mu(Compile_lock);
406216295Ssyrinx  CodeCache::mark_all_nmethods_for_deoptimization();
407216295Ssyrinx  VM_Deoptimize op;
408216295Ssyrinx  VMThread::execute(&op);
409216295SsyrinxWB_END
410216295Ssyrinx
411216295SsyrinxWB_ENTRY(jint, WB_DeoptimizeMethod(JNIEnv* env, jobject o, jobject method, jboolean is_osr))
412216295Ssyrinx  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
413216295Ssyrinx  int result = 0;
414216295Ssyrinx  CHECK_JNI_EXCEPTION_(env, result);
415216295Ssyrinx  MutexLockerEx mu(Compile_lock);
416216295Ssyrinx  methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
417216295Ssyrinx  if (is_osr) {
418216295Ssyrinx    result += mh->mark_osr_nmethods();
419216295Ssyrinx  } else if (mh->code() != NULL) {
420216295Ssyrinx    mh->code()->mark_for_deoptimization();
421216295Ssyrinx    ++result;
422216295Ssyrinx  }
423216295Ssyrinx  result += CodeCache::mark_for_deoptimization(mh());
424216295Ssyrinx  if (result > 0) {
425216295Ssyrinx    VM_Deoptimize op;
426216295Ssyrinx    VMThread::execute(&op);
427216295Ssyrinx  }
428216295Ssyrinx  return result;
429216295SsyrinxWB_END
430216295Ssyrinx
431216295SsyrinxWB_ENTRY(jboolean, WB_IsMethodCompiled(JNIEnv* env, jobject o, jobject method, jboolean is_osr))
432216295Ssyrinx  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
433216295Ssyrinx  CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
434216295Ssyrinx  MutexLockerEx mu(Compile_lock);
435216295Ssyrinx  methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
436216295Ssyrinx  nmethod* code = is_osr ? mh->lookup_osr_nmethod_for(InvocationEntryBci, CompLevel_none, false) : mh->code();
437216295Ssyrinx  if (code == NULL) {
438216295Ssyrinx    return JNI_FALSE;
439216295Ssyrinx  }
440216295Ssyrinx  return (code->is_alive() && !code->is_marked_for_deoptimization());
441216295SsyrinxWB_END
442216295Ssyrinx
443216295SsyrinxWB_ENTRY(jboolean, WB_IsMethodCompilable(JNIEnv* env, jobject o, jobject method, jint comp_level, jboolean is_osr))
444216295Ssyrinx  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
445216295Ssyrinx  CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
446216295Ssyrinx  MutexLockerEx mu(Compile_lock);
447216295Ssyrinx  methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
448216295Ssyrinx  if (is_osr) {
449216295Ssyrinx    return CompilationPolicy::can_be_osr_compiled(mh, comp_level);
450216295Ssyrinx  } else {
451216295Ssyrinx    return CompilationPolicy::can_be_compiled(mh, comp_level);
452216295Ssyrinx  }
453228990SuqsWB_END
454216295Ssyrinx
455216295SsyrinxWB_ENTRY(jboolean, WB_IsMethodQueuedForCompilation(JNIEnv* env, jobject o, jobject method))
456216295Ssyrinx  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
457216295Ssyrinx  CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
458216295Ssyrinx  MutexLockerEx mu(Compile_lock);
459216295Ssyrinx  methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
460216295Ssyrinx  return mh->queued_for_compilation();
461216295SsyrinxWB_END
462216295Ssyrinx
463216295SsyrinxWB_ENTRY(jint, WB_GetMethodCompilationLevel(JNIEnv* env, jobject o, jobject method, jboolean is_osr))
464216295Ssyrinx  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
465216295Ssyrinx  CHECK_JNI_EXCEPTION_(env, CompLevel_none);
466216295Ssyrinx  methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
467216295Ssyrinx  nmethod* code = is_osr ? mh->lookup_osr_nmethod_for(InvocationEntryBci, CompLevel_none, false) : mh->code();
468216295Ssyrinx  return (code != NULL ? code->comp_level() : CompLevel_none);
469216295SsyrinxWB_END
470216295Ssyrinx
471216295SsyrinxWB_ENTRY(void, WB_MakeMethodNotCompilable(JNIEnv* env, jobject o, jobject method, jint comp_level, jboolean is_osr))
472228990Suqs  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
473216295Ssyrinx  CHECK_JNI_EXCEPTION(env);
474216295Ssyrinx  methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
475216295Ssyrinx  if (is_osr) {
476216295Ssyrinx    mh->set_not_osr_compilable(comp_level, true /* report */, "WhiteBox");
477216295Ssyrinx  } else {
478216295Ssyrinx    mh->set_not_compilable(comp_level, true /* report */, "WhiteBox");
479216295Ssyrinx  }
480216295SsyrinxWB_END
481216295Ssyrinx
482216295SsyrinxWB_ENTRY(jint, WB_GetMethodEntryBci(JNIEnv* env, jobject o, jobject method))
483216295Ssyrinx  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
484216295Ssyrinx  CHECK_JNI_EXCEPTION_(env, InvocationEntryBci);
485216295Ssyrinx  methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
486216295Ssyrinx  nmethod* code = mh->lookup_osr_nmethod_for(InvocationEntryBci, CompLevel_none, false);
487216295Ssyrinx  return (code != NULL && code->is_osr_method() ? code->osr_entry_bci() : InvocationEntryBci);
488216295SsyrinxWB_END
489216295Ssyrinx
490216295SsyrinxWB_ENTRY(jboolean, WB_TestSetDontInlineMethod(JNIEnv* env, jobject o, jobject method, jboolean value))
491216295Ssyrinx  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
492216295Ssyrinx  CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
493216295Ssyrinx  methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
494216295Ssyrinx  bool result = mh->dont_inline();
495216295Ssyrinx  mh->set_dont_inline(value == JNI_TRUE);
496216295Ssyrinx  return result;
497216295SsyrinxWB_END
498216295Ssyrinx
499216295SsyrinxWB_ENTRY(jint, WB_GetCompileQueueSize(JNIEnv* env, jobject o, jint comp_level))
500216295Ssyrinx  if (comp_level == CompLevel_any) {
501216295Ssyrinx    return CompileBroker::queue_size(CompLevel_full_optimization) /* C2 */ +
502216295Ssyrinx        CompileBroker::queue_size(CompLevel_full_profile) /* C1 */;
503216295Ssyrinx  } else {
504216295Ssyrinx    return CompileBroker::queue_size(comp_level);
505216295Ssyrinx  }
506216295SsyrinxWB_END
507216295Ssyrinx
508216295SsyrinxWB_ENTRY(jboolean, WB_TestSetForceInlineMethod(JNIEnv* env, jobject o, jobject method, jboolean value))
509216295Ssyrinx  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
510216295Ssyrinx  CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
511216295Ssyrinx  methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
512216295Ssyrinx  bool result = mh->force_inline();
513216295Ssyrinx  mh->set_force_inline(value == JNI_TRUE);
514216295Ssyrinx  return result;
515216295SsyrinxWB_END
516216295Ssyrinx
517216295SsyrinxWB_ENTRY(jboolean, WB_EnqueueMethodForCompilation(JNIEnv* env, jobject o, jobject method, jint comp_level, jint bci))
518216295Ssyrinx  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
519216295Ssyrinx  CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
520216295Ssyrinx  methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
521216295Ssyrinx  nmethod* nm = CompileBroker::compile_method(mh, bci, comp_level, mh, mh->invocation_count(), "WhiteBox", THREAD);
522216295Ssyrinx  MutexLockerEx mu(Compile_lock);
523216295Ssyrinx  return (mh->queued_for_compilation() || nm != NULL);
524216295SsyrinxWB_END
525216295Ssyrinx
526216295Ssyrinxclass VM_WhiteBoxOperation : public VM_Operation {
527216295Ssyrinx public:
528216295Ssyrinx  VM_WhiteBoxOperation()                         { }
529216295Ssyrinx  VMOp_Type type()                  const        { return VMOp_WhiteBoxOperation; }
530216295Ssyrinx  bool allow_nested_vm_operations() const        { return true; }
531216295Ssyrinx};
532216295Ssyrinx
533216295Ssyrinxclass AlwaysFalseClosure : public BoolObjectClosure {
534216295Ssyrinx public:
535216295Ssyrinx  bool do_object_b(oop p) { return false; }
536216295Ssyrinx};
537216295Ssyrinx
538216295Ssyrinxstatic AlwaysFalseClosure always_false;
539216295Ssyrinx
540216295SsyrinxWB_ENTRY(void, WB_ClearMethodState(JNIEnv* env, jobject o, jobject method))
541216295Ssyrinx  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
542216295Ssyrinx  CHECK_JNI_EXCEPTION(env);
543216295Ssyrinx  methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
544216295Ssyrinx  MutexLockerEx mu(Compile_lock);
545216295Ssyrinx  MethodData* mdo = mh->method_data();
546216295Ssyrinx  MethodCounters* mcs = mh->method_counters();
547216295Ssyrinx
548216295Ssyrinx  if (mdo != NULL) {
549216295Ssyrinx    mdo->init();
550216295Ssyrinx    ResourceMark rm;
551216295Ssyrinx    int arg_count = mdo->method()->size_of_parameters();
552216295Ssyrinx    for (int i = 0; i < arg_count; i++) {
553216295Ssyrinx      mdo->set_arg_modified(i, 0);
554216295Ssyrinx    }
555216295Ssyrinx    MutexLockerEx mu(mdo->extra_data_lock());
556216295Ssyrinx    mdo->clean_method_data(&always_false);
557216295Ssyrinx  }
558216295Ssyrinx
559216295Ssyrinx  mh->clear_not_c1_compilable();
560216295Ssyrinx  mh->clear_not_c2_compilable();
561216295Ssyrinx  mh->clear_not_c2_osr_compilable();
562216295Ssyrinx  NOT_PRODUCT(mh->set_compiled_invocation_count(0));
563216295Ssyrinx  if (mcs != NULL) {
564216295Ssyrinx    mcs->backedge_counter()->init();
565216295Ssyrinx    mcs->invocation_counter()->init();
566216295Ssyrinx    mcs->set_interpreter_invocation_count(0);
567216295Ssyrinx    mcs->set_interpreter_throwout_count(0);
568216295Ssyrinx
569216295Ssyrinx#ifdef TIERED
570216295Ssyrinx    mcs->set_rate(0.0F);
571216295Ssyrinx    mh->set_prev_event_count(0);
572216295Ssyrinx    mh->set_prev_time(0);
573216295Ssyrinx#endif
574216295Ssyrinx  }
575216295SsyrinxWB_END
576216295Ssyrinx
577216295Ssyrinxtemplate <typename T>
578216295Ssyrinxstatic bool GetVMFlag(JavaThread* thread, JNIEnv* env, jstring name, T* value, bool (*TAt)(const char*, T*, bool, bool)) {
579216295Ssyrinx  if (name == NULL) {
580216295Ssyrinx    return false;
581216295Ssyrinx  }
582216295Ssyrinx  ThreadToNativeFromVM ttnfv(thread);   // can't be in VM when we call JNI
583216295Ssyrinx  const char* flag_name = env->GetStringUTFChars(name, NULL);
584216295Ssyrinx  bool result = (*TAt)(flag_name, value, true, true);
585216295Ssyrinx  env->ReleaseStringUTFChars(name, flag_name);
586216295Ssyrinx  return result;
587216295Ssyrinx}
588216295Ssyrinx
589216295Ssyrinxtemplate <typename T>
590216295Ssyrinxstatic bool SetVMFlag(JavaThread* thread, JNIEnv* env, jstring name, T* value, bool (*TAtPut)(const char*, T*, Flag::Flags)) {
591216295Ssyrinx  if (name == NULL) {
592216295Ssyrinx    return false;
593216295Ssyrinx  }
594216295Ssyrinx  ThreadToNativeFromVM ttnfv(thread);   // can't be in VM when we call JNI
595216295Ssyrinx  const char* flag_name = env->GetStringUTFChars(name, NULL);
596216295Ssyrinx  bool result = (*TAtPut)(flag_name, value, Flag::INTERNAL);
597216295Ssyrinx  env->ReleaseStringUTFChars(name, flag_name);
598216295Ssyrinx  return result;
599216295Ssyrinx}
600216295Ssyrinx
601216295Ssyrinxtemplate <typename T>
602216295Ssyrinxstatic jobject box(JavaThread* thread, JNIEnv* env, Symbol* name, Symbol* sig, T value) {
603216295Ssyrinx  ResourceMark rm(thread);
604216295Ssyrinx  jclass clazz = env->FindClass(name->as_C_string());
605216295Ssyrinx  CHECK_JNI_EXCEPTION_(env, NULL);
606216295Ssyrinx  jmethodID methodID = env->GetStaticMethodID(clazz,
607216295Ssyrinx        vmSymbols::valueOf_name()->as_C_string(),
608216295Ssyrinx        sig->as_C_string());
609216295Ssyrinx  CHECK_JNI_EXCEPTION_(env, NULL);
610216295Ssyrinx  jobject result = env->CallStaticObjectMethod(clazz, methodID, value);
611216295Ssyrinx  CHECK_JNI_EXCEPTION_(env, NULL);
612216295Ssyrinx  return result;
613216295Ssyrinx}
614216295Ssyrinx
615216295Ssyrinxstatic jobject booleanBox(JavaThread* thread, JNIEnv* env, jboolean value) {
616216295Ssyrinx  return box(thread, env, vmSymbols::java_lang_Boolean(), vmSymbols::Boolean_valueOf_signature(), value);
617216295Ssyrinx}
618216295Ssyrinxstatic jobject integerBox(JavaThread* thread, JNIEnv* env, jint value) {
619216295Ssyrinx  return box(thread, env, vmSymbols::java_lang_Integer(), vmSymbols::Integer_valueOf_signature(), value);
620216295Ssyrinx}
621216295Ssyrinxstatic jobject longBox(JavaThread* thread, JNIEnv* env, jlong value) {
622216295Ssyrinx  return box(thread, env, vmSymbols::java_lang_Long(), vmSymbols::Long_valueOf_signature(), value);
623216295Ssyrinx}
624216295Ssyrinx/* static jobject floatBox(JavaThread* thread, JNIEnv* env, jfloat value) {
625216295Ssyrinx  return box(thread, env, vmSymbols::java_lang_Float(), vmSymbols::Float_valueOf_signature(), value);
626216295Ssyrinx}*/
627216295Ssyrinxstatic jobject doubleBox(JavaThread* thread, JNIEnv* env, jdouble value) {
628216295Ssyrinx  return box(thread, env, vmSymbols::java_lang_Double(), vmSymbols::Double_valueOf_signature(), value);
629216295Ssyrinx}
630216295Ssyrinx
631216295Ssyrinxstatic Flag* getVMFlag(JavaThread* thread, JNIEnv* env, jstring name) {
632216295Ssyrinx  ThreadToNativeFromVM ttnfv(thread);   // can't be in VM when we call JNI
633216295Ssyrinx  const char* flag_name = env->GetStringUTFChars(name, NULL);
634216295Ssyrinx  Flag* result = Flag::find_flag(flag_name, strlen(flag_name), true, true);
635216295Ssyrinx  env->ReleaseStringUTFChars(name, flag_name);
636216295Ssyrinx  return result;
637216295Ssyrinx}
638216295Ssyrinx
639216295SsyrinxWB_ENTRY(jboolean, WB_IsConstantVMFlag(JNIEnv* env, jobject o, jstring name))
640216295Ssyrinx  Flag* flag = getVMFlag(thread, env, name);
641216295Ssyrinx  return (flag != NULL) && flag->is_constant_in_binary();
642216295SsyrinxWB_END
643216295Ssyrinx
644216295SsyrinxWB_ENTRY(jboolean, WB_IsLockedVMFlag(JNIEnv* env, jobject o, jstring name))
645216295Ssyrinx  Flag* flag = getVMFlag(thread, env, name);
646216295Ssyrinx  return (flag != NULL) && !(flag->is_unlocked() || flag->is_unlocker());
647216295SsyrinxWB_END
648216295Ssyrinx
649216295SsyrinxWB_ENTRY(jobject, WB_GetBooleanVMFlag(JNIEnv* env, jobject o, jstring name))
650216295Ssyrinx  bool result;
651216295Ssyrinx  if (GetVMFlag <bool> (thread, env, name, &result, &CommandLineFlags::boolAt)) {
652216295Ssyrinx    ThreadToNativeFromVM ttnfv(thread);   // can't be in VM when we call JNI
653216295Ssyrinx    return booleanBox(thread, env, result);
654216295Ssyrinx  }
655216295Ssyrinx  return NULL;
656216295SsyrinxWB_END
657216295Ssyrinx
658216295SsyrinxWB_ENTRY(jobject, WB_GetIntxVMFlag(JNIEnv* env, jobject o, jstring name))
659216295Ssyrinx  intx result;
660216295Ssyrinx  if (GetVMFlag <intx> (thread, env, name, &result, &CommandLineFlags::intxAt)) {
661216295Ssyrinx    ThreadToNativeFromVM ttnfv(thread);   // can't be in VM when we call JNI
662216295Ssyrinx    return longBox(thread, env, result);
663216295Ssyrinx  }
664216295Ssyrinx  return NULL;
665216295SsyrinxWB_END
666216295Ssyrinx
667216295SsyrinxWB_ENTRY(jobject, WB_GetUintxVMFlag(JNIEnv* env, jobject o, jstring name))
668216295Ssyrinx  uintx result;
669216295Ssyrinx  if (GetVMFlag <uintx> (thread, env, name, &result, &CommandLineFlags::uintxAt)) {
670216295Ssyrinx    ThreadToNativeFromVM ttnfv(thread);   // can't be in VM when we call JNI
671216295Ssyrinx    return longBox(thread, env, result);
672216295Ssyrinx  }
673216295Ssyrinx  return NULL;
674216295SsyrinxWB_END
675216295Ssyrinx
676216295SsyrinxWB_ENTRY(jobject, WB_GetUint64VMFlag(JNIEnv* env, jobject o, jstring name))
677216295Ssyrinx  uint64_t result;
678216295Ssyrinx  if (GetVMFlag <uint64_t> (thread, env, name, &result, &CommandLineFlags::uint64_tAt)) {
679216295Ssyrinx    ThreadToNativeFromVM ttnfv(thread);   // can't be in VM when we call JNI
680216295Ssyrinx    return longBox(thread, env, result);
681216295Ssyrinx  }
682216295Ssyrinx  return NULL;
683216295SsyrinxWB_END
684216295Ssyrinx
685216295SsyrinxWB_ENTRY(jobject, WB_GetSizeTVMFlag(JNIEnv* env, jobject o, jstring name))
686216295Ssyrinx  uintx result;
687216295Ssyrinx  if (GetVMFlag <size_t> (thread, env, name, &result, &CommandLineFlags::size_tAt)) {
688216295Ssyrinx    ThreadToNativeFromVM ttnfv(thread);   // can't be in VM when we call JNI
689216295Ssyrinx    return longBox(thread, env, result);
690216295Ssyrinx  }
691216295Ssyrinx  return NULL;
692216295SsyrinxWB_END
693216295Ssyrinx
694216295SsyrinxWB_ENTRY(jobject, WB_GetDoubleVMFlag(JNIEnv* env, jobject o, jstring name))
695216295Ssyrinx  double result;
696216295Ssyrinx  if (GetVMFlag <double> (thread, env, name, &result, &CommandLineFlags::doubleAt)) {
697216295Ssyrinx    ThreadToNativeFromVM ttnfv(thread);   // can't be in VM when we call JNI
698216295Ssyrinx    return doubleBox(thread, env, result);
699216295Ssyrinx  }
700216295Ssyrinx  return NULL;
701216295SsyrinxWB_END
702216295Ssyrinx
703216295SsyrinxWB_ENTRY(jstring, WB_GetStringVMFlag(JNIEnv* env, jobject o, jstring name))
704216295Ssyrinx  ccstr ccstrResult;
705216295Ssyrinx  if (GetVMFlag <ccstr> (thread, env, name, &ccstrResult, &CommandLineFlags::ccstrAt)) {
706216295Ssyrinx    ThreadToNativeFromVM ttnfv(thread);   // can't be in VM when we call JNI
707216295Ssyrinx    jstring result = env->NewStringUTF(ccstrResult);
708216295Ssyrinx    CHECK_JNI_EXCEPTION_(env, NULL);
709216295Ssyrinx    return result;
710216295Ssyrinx  }
711216295Ssyrinx  return NULL;
712216295SsyrinxWB_END
713216295Ssyrinx
714216295SsyrinxWB_ENTRY(void, WB_SetBooleanVMFlag(JNIEnv* env, jobject o, jstring name, jboolean value))
715216295Ssyrinx  bool result = value == JNI_TRUE ? true : false;
716216295Ssyrinx  SetVMFlag <bool> (thread, env, name, &result, &CommandLineFlags::boolAtPut);
717216295SsyrinxWB_END
718216295Ssyrinx
719216295SsyrinxWB_ENTRY(void, WB_SetIntxVMFlag(JNIEnv* env, jobject o, jstring name, jlong value))
720216295Ssyrinx  intx result = value;
721216295Ssyrinx  SetVMFlag <intx> (thread, env, name, &result, &CommandLineFlags::intxAtPut);
722216295SsyrinxWB_END
723216295Ssyrinx
724216295SsyrinxWB_ENTRY(void, WB_SetUintxVMFlag(JNIEnv* env, jobject o, jstring name, jlong value))
725216295Ssyrinx  uintx result = value;
726216295Ssyrinx  SetVMFlag <uintx> (thread, env, name, &result, &CommandLineFlags::uintxAtPut);
727216295SsyrinxWB_END
728216295Ssyrinx
729216295SsyrinxWB_ENTRY(void, WB_SetUint64VMFlag(JNIEnv* env, jobject o, jstring name, jlong value))
730216295Ssyrinx  uint64_t result = value;
731216295Ssyrinx  SetVMFlag <uint64_t> (thread, env, name, &result, &CommandLineFlags::uint64_tAtPut);
732216295SsyrinxWB_END
733216295Ssyrinx
734216295SsyrinxWB_ENTRY(void, WB_SetSizeTVMFlag(JNIEnv* env, jobject o, jstring name, jlong value))
735216295Ssyrinx  size_t result = value;
736216295Ssyrinx  SetVMFlag <size_t> (thread, env, name, &result, &CommandLineFlags::size_tAtPut);
737216295SsyrinxWB_END
738216295Ssyrinx
739216295SsyrinxWB_ENTRY(void, WB_SetDoubleVMFlag(JNIEnv* env, jobject o, jstring name, jdouble value))
740216295Ssyrinx  double result = value;
741216295Ssyrinx  SetVMFlag <double> (thread, env, name, &result, &CommandLineFlags::doubleAtPut);
742216295SsyrinxWB_END
743216295Ssyrinx
744216295SsyrinxWB_ENTRY(void, WB_SetStringVMFlag(JNIEnv* env, jobject o, jstring name, jstring value))
745216295Ssyrinx  ThreadToNativeFromVM ttnfv(thread);   // can't be in VM when we call JNI
746216295Ssyrinx  const char* ccstrValue = (value == NULL) ? NULL : env->GetStringUTFChars(value, NULL);
747216295Ssyrinx  ccstr ccstrResult = ccstrValue;
748216295Ssyrinx  bool needFree;
749216295Ssyrinx  {
750216295Ssyrinx    ThreadInVMfromNative ttvfn(thread); // back to VM
751216295Ssyrinx    needFree = SetVMFlag <ccstr> (thread, env, name, &ccstrResult, &CommandLineFlags::ccstrAtPut);
752216295Ssyrinx  }
753216295Ssyrinx  if (value != NULL) {
754216295Ssyrinx    env->ReleaseStringUTFChars(value, ccstrValue);
755216295Ssyrinx  }
756216295Ssyrinx  if (needFree) {
757216295Ssyrinx    FREE_C_HEAP_ARRAY(char, ccstrResult);
758216295Ssyrinx  }
759216295SsyrinxWB_END
760216295Ssyrinx
761216295Ssyrinx
762216295SsyrinxWB_ENTRY(void, WB_LockCompilation(JNIEnv* env, jobject o, jlong timeout))
763216295Ssyrinx  WhiteBox::compilation_locked = true;
764216295SsyrinxWB_END
765216295Ssyrinx
766216295SsyrinxWB_ENTRY(void, WB_UnlockCompilation(JNIEnv* env, jobject o))
767216295Ssyrinx  MonitorLockerEx mo(Compilation_lock, Mutex::_no_safepoint_check_flag);
768216295Ssyrinx  WhiteBox::compilation_locked = false;
769216295Ssyrinx  mo.notify_all();
770216295SsyrinxWB_END
771216295Ssyrinx
772216295Ssyrinxvoid WhiteBox::force_sweep() {
773216295Ssyrinx  guarantee(WhiteBoxAPI, "internal testing API :: WhiteBox has to enabled");
774216295Ssyrinx  {
775216295Ssyrinx    MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
776216295Ssyrinx    NMethodSweeper::_should_sweep = true;
777216295Ssyrinx  }
778216295Ssyrinx  NMethodSweeper::possibly_sweep();
779216295Ssyrinx}
780216295Ssyrinx
781216295SsyrinxWB_ENTRY(void, WB_ForceNMethodSweep(JNIEnv* env, jobject o))
782216295Ssyrinx  WhiteBox::force_sweep();
783216295SsyrinxWB_END
784216295Ssyrinx
785216295SsyrinxWB_ENTRY(jboolean, WB_IsInStringTable(JNIEnv* env, jobject o, jstring javaString))
786216295Ssyrinx  ResourceMark rm(THREAD);
787216295Ssyrinx  int len;
788216295Ssyrinx  jchar* name = java_lang_String::as_unicode_string(JNIHandles::resolve(javaString), len, CHECK_false);
789216295Ssyrinx  return (StringTable::lookup(name, len) != NULL);
790216295SsyrinxWB_END
791216295Ssyrinx
792216295SsyrinxWB_ENTRY(void, WB_FullGC(JNIEnv* env, jobject o))
793216295Ssyrinx  Universe::heap()->collector_policy()->set_should_clear_all_soft_refs(true);
794216295Ssyrinx  Universe::heap()->collect(GCCause::_last_ditch_collection);
795216295Ssyrinx#if INCLUDE_ALL_GCS
796216295Ssyrinx  if (UseG1GC) {
797216295Ssyrinx    // Needs to be cleared explicitly for G1
798216295Ssyrinx    Universe::heap()->collector_policy()->set_should_clear_all_soft_refs(false);
799216295Ssyrinx  }
800216295Ssyrinx#endif // INCLUDE_ALL_GCS
801216295SsyrinxWB_END
802216295Ssyrinx
803216295SsyrinxWB_ENTRY(void, WB_YoungGC(JNIEnv* env, jobject o))
804216295Ssyrinx  Universe::heap()->collect(GCCause::_wb_young_gc);
805216295SsyrinxWB_END
806216295Ssyrinx
807216295SsyrinxWB_ENTRY(void, WB_ReadReservedMemory(JNIEnv* env, jobject o))
808216295Ssyrinx  // static+volatile in order to force the read to happen
809216295Ssyrinx  // (not be eliminated by the compiler)
810216295Ssyrinx  static char c;
811216295Ssyrinx  static volatile char* p;
812216295Ssyrinx
813216295Ssyrinx  p = os::reserve_memory(os::vm_allocation_granularity(), NULL, 0);
814216295Ssyrinx  if (p == NULL) {
815216295Ssyrinx    THROW_MSG(vmSymbols::java_lang_OutOfMemoryError(), "Failed to reserve memory");
816216295Ssyrinx  }
817216295Ssyrinx
818216295Ssyrinx  c = *p;
819216295SsyrinxWB_END
820216295Ssyrinx
821216295SsyrinxWB_ENTRY(jstring, WB_GetCPUFeatures(JNIEnv* env, jobject o))
822216295Ssyrinx  const char* cpu_features = VM_Version::cpu_features();
823216295Ssyrinx  ThreadToNativeFromVM ttn(thread);
824216295Ssyrinx  jstring features_string = env->NewStringUTF(cpu_features);
825216295Ssyrinx
826216295Ssyrinx  CHECK_JNI_EXCEPTION_(env, NULL);
827216295Ssyrinx
828216295Ssyrinx  return features_string;
829216295SsyrinxWB_END
830216295Ssyrinx
831216295Ssyrinxint WhiteBox::get_blob_type(const CodeBlob* code) {
832216295Ssyrinx  guarantee(WhiteBoxAPI, "internal testing API :: WhiteBox has to enabled");
833216295Ssyrinx  return CodeCache::get_code_heap(code)->code_blob_type();
834216295Ssyrinx}
835216295Ssyrinx
836216295SsyrinxCodeHeap* WhiteBox::get_code_heap(int blob_type) {
837216295Ssyrinx  guarantee(WhiteBoxAPI, "internal testing API :: WhiteBox has to enabled");
838216295Ssyrinx  return CodeCache::get_code_heap(blob_type);
839216295Ssyrinx}
840216295Ssyrinx
841216295Ssyrinxstruct CodeBlobStub {
842216295Ssyrinx  CodeBlobStub(const CodeBlob* blob) :
843216295Ssyrinx      name(os::strdup(blob->name())),
844216295Ssyrinx      size(blob->size()),
845216295Ssyrinx      blob_type(WhiteBox::get_blob_type(blob)) { }
846216295Ssyrinx  ~CodeBlobStub() { os::free((void*) name); }
847216295Ssyrinx  const char* const name;
848216295Ssyrinx  const int         size;
849216295Ssyrinx  const int         blob_type;
850216295Ssyrinx};
851216295Ssyrinx
852216295Ssyrinxstatic jobjectArray codeBlob2objectArray(JavaThread* thread, JNIEnv* env, CodeBlobStub* cb) {
853216295Ssyrinx  jclass clazz = env->FindClass(vmSymbols::java_lang_Object()->as_C_string());
854216295Ssyrinx  CHECK_JNI_EXCEPTION_(env, NULL);
855216295Ssyrinx  jobjectArray result = env->NewObjectArray(3, clazz, NULL);
856216295Ssyrinx
857216295Ssyrinx  jstring name = env->NewStringUTF(cb->name);
858216295Ssyrinx  CHECK_JNI_EXCEPTION_(env, NULL);
859216295Ssyrinx  env->SetObjectArrayElement(result, 0, name);
860216295Ssyrinx
861216295Ssyrinx  jobject obj = integerBox(thread, env, cb->size);
862216295Ssyrinx  CHECK_JNI_EXCEPTION_(env, NULL);
863216295Ssyrinx  env->SetObjectArrayElement(result, 1, obj);
864216295Ssyrinx
865216295Ssyrinx  obj = integerBox(thread, env, cb->blob_type);
866216295Ssyrinx  CHECK_JNI_EXCEPTION_(env, NULL);
867216295Ssyrinx  env->SetObjectArrayElement(result, 2, obj);
868216295Ssyrinx
869216295Ssyrinx  return result;
870216295Ssyrinx}
871216295Ssyrinx
872216295SsyrinxWB_ENTRY(jobjectArray, WB_GetNMethod(JNIEnv* env, jobject o, jobject method, jboolean is_osr))
873216295Ssyrinx  ResourceMark rm(THREAD);
874216295Ssyrinx  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
875216295Ssyrinx  CHECK_JNI_EXCEPTION_(env, NULL);
876216295Ssyrinx  methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
877216295Ssyrinx  nmethod* code = is_osr ? mh->lookup_osr_nmethod_for(InvocationEntryBci, CompLevel_none, false) : mh->code();
878216295Ssyrinx  jobjectArray result = NULL;
879216295Ssyrinx  if (code == NULL) {
880216295Ssyrinx    return result;
881216295Ssyrinx  }
882216295Ssyrinx  int insts_size = code->insts_size();
883216295Ssyrinx
884216295Ssyrinx  ThreadToNativeFromVM ttn(thread);
885216295Ssyrinx  jclass clazz = env->FindClass(vmSymbols::java_lang_Object()->as_C_string());
886216295Ssyrinx  CHECK_JNI_EXCEPTION_(env, NULL);
887216295Ssyrinx  result = env->NewObjectArray(4, clazz, NULL);
888216295Ssyrinx  if (result == NULL) {
889216295Ssyrinx    return result;
890216295Ssyrinx  }
891216295Ssyrinx
892216295Ssyrinx  CodeBlobStub stub(code);
893216295Ssyrinx  jobjectArray codeBlob = codeBlob2objectArray(thread, env, &stub);
894216295Ssyrinx  env->SetObjectArrayElement(result, 0, codeBlob);
895216295Ssyrinx
896216295Ssyrinx  jobject level = integerBox(thread, env, code->comp_level());
897216295Ssyrinx  CHECK_JNI_EXCEPTION_(env, NULL);
898216295Ssyrinx  env->SetObjectArrayElement(result, 1, level);
899216295Ssyrinx
900216295Ssyrinx  jbyteArray insts = env->NewByteArray(insts_size);
901216295Ssyrinx  CHECK_JNI_EXCEPTION_(env, NULL);
902216295Ssyrinx  env->SetByteArrayRegion(insts, 0, insts_size, (jbyte*) code->insts_begin());
903216295Ssyrinx  env->SetObjectArrayElement(result, 2, insts);
904216295Ssyrinx
905216295Ssyrinx  jobject id = integerBox(thread, env, code->compile_id());
906216295Ssyrinx  CHECK_JNI_EXCEPTION_(env, NULL);
907216295Ssyrinx  env->SetObjectArrayElement(result, 3, id);
908216295Ssyrinx
909216295Ssyrinx  return result;
910216295SsyrinxWB_END
911216295Ssyrinx
912216295SsyrinxCodeBlob* WhiteBox::allocate_code_blob(int size, int blob_type) {
913216295Ssyrinx  guarantee(WhiteBoxAPI, "internal testing API :: WhiteBox has to enabled");
914216295Ssyrinx  BufferBlob* blob;
915216295Ssyrinx  int full_size = CodeBlob::align_code_offset(sizeof(BufferBlob));
916216295Ssyrinx  if (full_size < size) {
917216295Ssyrinx    full_size += round_to(size - full_size, oopSize);
918216295Ssyrinx  }
919216295Ssyrinx  {
920216295Ssyrinx    MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
921216295Ssyrinx    blob = (BufferBlob*) CodeCache::allocate(full_size, blob_type);
922216295Ssyrinx  }
923216295Ssyrinx  // Track memory usage statistic after releasing CodeCache_lock
924216295Ssyrinx  MemoryService::track_code_cache_memory_usage();
925216295Ssyrinx  ::new (blob) BufferBlob("WB::DummyBlob", full_size);
926216295Ssyrinx  return blob;
927216295Ssyrinx}
928216295Ssyrinx
929216295SsyrinxWB_ENTRY(jlong, WB_AllocateCodeBlob(JNIEnv* env, jobject o, jint size, jint blob_type))
930216295Ssyrinx    return (jlong) WhiteBox::allocate_code_blob(size, blob_type);
931216295SsyrinxWB_END
932216295Ssyrinx
933216295SsyrinxWB_ENTRY(void, WB_FreeCodeBlob(JNIEnv* env, jobject o, jlong addr))
934216295Ssyrinx    BufferBlob::free((BufferBlob*) addr);
935216295SsyrinxWB_END
936216295Ssyrinx
937216295SsyrinxWB_ENTRY(jobjectArray, WB_GetCodeHeapEntries(JNIEnv* env, jobject o, jint blob_type))
938216295Ssyrinx  ResourceMark rm;
939216295Ssyrinx  GrowableArray<CodeBlobStub*> blobs;
940216295Ssyrinx  {
941216295Ssyrinx    MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
942216295Ssyrinx    CodeHeap* heap = WhiteBox::get_code_heap(blob_type);
943216295Ssyrinx    if (heap == NULL) {
944216295Ssyrinx      return NULL;
945216295Ssyrinx    }
946216295Ssyrinx    for (CodeBlob* cb = (CodeBlob*) heap->first();
947216295Ssyrinx         cb != NULL; cb = (CodeBlob*) heap->next(cb)) {
948216295Ssyrinx      CodeBlobStub* stub = NEW_RESOURCE_OBJ(CodeBlobStub);
949216295Ssyrinx      new (stub) CodeBlobStub(cb);
950216295Ssyrinx      blobs.append(stub);
951216295Ssyrinx    }
952216295Ssyrinx  }
953216295Ssyrinx  if (blobs.length() == 0) {
954216295Ssyrinx    return NULL;
955216295Ssyrinx  }
956216295Ssyrinx  ThreadToNativeFromVM ttn(thread);
957216295Ssyrinx  jobjectArray result = NULL;
958216295Ssyrinx  jclass clazz = env->FindClass(vmSymbols::java_lang_Object()->as_C_string());
959216295Ssyrinx  CHECK_JNI_EXCEPTION_(env, NULL);
960216295Ssyrinx  result = env->NewObjectArray(blobs.length(), clazz, NULL);
961216295Ssyrinx  if (result == NULL) {
962216295Ssyrinx    return result;
963216295Ssyrinx  }
964216295Ssyrinx  int i = 0;
965216295Ssyrinx  for (GrowableArrayIterator<CodeBlobStub*> it = blobs.begin();
966216295Ssyrinx       it != blobs.end(); ++it) {
967216295Ssyrinx    jobjectArray obj = codeBlob2objectArray(thread, env, *it);
968216295Ssyrinx    env->SetObjectArrayElement(result, i, obj);
969216295Ssyrinx    ++i;
970216295Ssyrinx  }
971216295Ssyrinx  return result;
972216295SsyrinxWB_END
973216295Ssyrinx
974216295SsyrinxWB_ENTRY(jlong, WB_GetThreadStackSize(JNIEnv* env, jobject o))
975216295Ssyrinx  return (jlong) Thread::current()->stack_size();
976216295SsyrinxWB_END
977216295Ssyrinx
978216295SsyrinxWB_ENTRY(jlong, WB_GetThreadRemainingStackSize(JNIEnv* env, jobject o))
979216295Ssyrinx  JavaThread* t = JavaThread::current();
980216295Ssyrinx  return (jlong) t->stack_available(os::current_stack_pointer()) - (jlong) StackShadowPages * os::vm_page_size();
981216295SsyrinxWB_END
982216295Ssyrinx
983216295Ssyrinxint WhiteBox::array_bytes_to_length(size_t bytes) {
984216295Ssyrinx  return Array<u1>::bytes_to_length(bytes);
985216295Ssyrinx}
986216295Ssyrinx
987216295SsyrinxWB_ENTRY(jlong, WB_AllocateMetaspace(JNIEnv* env, jobject wb, jobject class_loader, jlong size))
988216295Ssyrinx  if (size < 0) {
989216295Ssyrinx    THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
990216295Ssyrinx        err_msg("WB_AllocateMetaspace: size is negative: " JLONG_FORMAT, size));
991216295Ssyrinx  }
992216295Ssyrinx
993216295Ssyrinx  oop class_loader_oop = JNIHandles::resolve(class_loader);
994216295Ssyrinx  ClassLoaderData* cld = class_loader_oop != NULL
995216295Ssyrinx      ? java_lang_ClassLoader::loader_data(class_loader_oop)
996216295Ssyrinx      : ClassLoaderData::the_null_class_loader_data();
997216295Ssyrinx
998216295Ssyrinx  void* metadata = MetadataFactory::new_writeable_array<u1>(cld, WhiteBox::array_bytes_to_length((size_t)size), thread);
999216295Ssyrinx
1000216295Ssyrinx  return (jlong)(uintptr_t)metadata;
1001216295SsyrinxWB_END
1002216295Ssyrinx
1003216295SsyrinxWB_ENTRY(void, WB_FreeMetaspace(JNIEnv* env, jobject wb, jobject class_loader, jlong addr, jlong size))
1004216295Ssyrinx  oop class_loader_oop = JNIHandles::resolve(class_loader);
1005216295Ssyrinx  ClassLoaderData* cld = class_loader_oop != NULL
1006216295Ssyrinx      ? java_lang_ClassLoader::loader_data(class_loader_oop)
1007216295Ssyrinx      : ClassLoaderData::the_null_class_loader_data();
1008216295Ssyrinx
1009216295Ssyrinx  MetadataFactory::free_array(cld, (Array<u1>*)(uintptr_t)addr);
1010216295SsyrinxWB_END
1011216295Ssyrinx
1012216295SsyrinxWB_ENTRY(jlong, WB_IncMetaspaceCapacityUntilGC(JNIEnv* env, jobject wb, jlong inc))
1013216295Ssyrinx  if (inc < 0) {
1014216295Ssyrinx    THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
1015216295Ssyrinx        err_msg("WB_IncMetaspaceCapacityUntilGC: inc is negative: " JLONG_FORMAT, inc));
1016216295Ssyrinx  }
1017216295Ssyrinx
1018216295Ssyrinx  jlong max_size_t = (jlong) ((size_t) -1);
1019216295Ssyrinx  if (inc > max_size_t) {
1020216295Ssyrinx    THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
1021216295Ssyrinx        err_msg("WB_IncMetaspaceCapacityUntilGC: inc does not fit in size_t: " JLONG_FORMAT, inc));
1022216295Ssyrinx  }
1023216295Ssyrinx
1024216295Ssyrinx  size_t new_cap_until_GC = 0;
1025216295Ssyrinx  size_t aligned_inc = align_size_down((size_t) inc, Metaspace::commit_alignment());
1026216295Ssyrinx  bool success = MetaspaceGC::inc_capacity_until_GC(aligned_inc, &new_cap_until_GC);
1027216295Ssyrinx  if (!success) {
1028216295Ssyrinx    THROW_MSG_0(vmSymbols::java_lang_IllegalStateException(),
1029216295Ssyrinx                "WB_IncMetaspaceCapacityUntilGC: could not increase capacity until GC "
1030216295Ssyrinx                "due to contention with another thread");
1031216295Ssyrinx  }
1032216295Ssyrinx  return (jlong) new_cap_until_GC;
1033216295SsyrinxWB_END
1034216295Ssyrinx
1035216295SsyrinxWB_ENTRY(jlong, WB_MetaspaceCapacityUntilGC(JNIEnv* env, jobject wb))
1036216295Ssyrinx  return (jlong) MetaspaceGC::capacity_until_GC();
1037216295SsyrinxWB_END
1038216295Ssyrinx
1039216295Ssyrinx//Some convenience methods to deal with objects from java
1040216295Ssyrinxint WhiteBox::offset_for_field(const char* field_name, oop object,
1041216295Ssyrinx    Symbol* signature_symbol) {
1042216295Ssyrinx  assert(field_name != NULL && strlen(field_name) > 0, "Field name not valid");
1043216295Ssyrinx  Thread* THREAD = Thread::current();
1044216295Ssyrinx
1045216295Ssyrinx  //Get the class of our object
1046216295Ssyrinx  Klass* arg_klass = object->klass();
1047216295Ssyrinx  //Turn it into an instance-klass
1048216295Ssyrinx  InstanceKlass* ik = InstanceKlass::cast(arg_klass);
1049216295Ssyrinx
1050216295Ssyrinx  //Create symbols to look for in the class
1051216295Ssyrinx  TempNewSymbol name_symbol = SymbolTable::lookup(field_name, (int) strlen(field_name),
1052216295Ssyrinx      THREAD);
1053216295Ssyrinx
1054216295Ssyrinx  //To be filled in with an offset of the field we're looking for
1055216295Ssyrinx  fieldDescriptor fd;
1056216295Ssyrinx
1057216295Ssyrinx  Klass* res = ik->find_field(name_symbol, signature_symbol, &fd);
1058216295Ssyrinx  if (res == NULL) {
1059216295Ssyrinx    tty->print_cr("Invalid layout of %s at %s", ik->external_name(),
1060216295Ssyrinx        name_symbol->as_C_string());
1061216295Ssyrinx    fatal("Invalid layout of preloaded class");
1062216295Ssyrinx  }
1063216295Ssyrinx
1064216295Ssyrinx  //fetch the field at the offset we've found
1065216295Ssyrinx  int dest_offset = fd.offset();
1066216295Ssyrinx
1067216295Ssyrinx  return dest_offset;
1068216295Ssyrinx}
1069216295Ssyrinx
1070216295Ssyrinx
1071216295Ssyrinxconst char* WhiteBox::lookup_jstring(const char* field_name, oop object) {
1072216295Ssyrinx  int offset = offset_for_field(field_name, object,
1073216295Ssyrinx      vmSymbols::string_signature());
1074216295Ssyrinx  oop string = object->obj_field(offset);
1075216295Ssyrinx  if (string == NULL) {
1076216295Ssyrinx    return NULL;
1077216295Ssyrinx  }
1078216295Ssyrinx  const char* ret = java_lang_String::as_utf8_string(string);
1079216295Ssyrinx  return ret;
1080216295Ssyrinx}
1081216295Ssyrinx
1082216295Ssyrinxbool WhiteBox::lookup_bool(const char* field_name, oop object) {
1083216295Ssyrinx  int offset =
1084216295Ssyrinx      offset_for_field(field_name, object, vmSymbols::bool_signature());
1085216295Ssyrinx  bool ret = (object->bool_field(offset) == JNI_TRUE);
1086216295Ssyrinx  return ret;
1087216295Ssyrinx}
1088216295Ssyrinx
1089216295Ssyrinxvoid WhiteBox::register_methods(JNIEnv* env, jclass wbclass, JavaThread* thread, JNINativeMethod* method_array, int method_count) {
1090216295Ssyrinx  ResourceMark rm;
1091216295Ssyrinx  ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
1092216295Ssyrinx
1093216295Ssyrinx  //  one by one registration natives for exception catching
1094216295Ssyrinx  jclass no_such_method_error_klass = env->FindClass(vmSymbols::java_lang_NoSuchMethodError()->as_C_string());
1095216295Ssyrinx  CHECK_JNI_EXCEPTION(env);
1096216295Ssyrinx  for (int i = 0, n = method_count; i < n; ++i) {
1097216295Ssyrinx    // Skip dummy entries
1098216295Ssyrinx    if (method_array[i].fnPtr == NULL) continue;
1099216295Ssyrinx    if (env->RegisterNatives(wbclass, &method_array[i], 1) != 0) {
1100216295Ssyrinx      jthrowable throwable_obj = env->ExceptionOccurred();
1101216295Ssyrinx      if (throwable_obj != NULL) {
1102216295Ssyrinx        env->ExceptionClear();
1103216295Ssyrinx        if (env->IsInstanceOf(throwable_obj, no_such_method_error_klass)) {
1104216295Ssyrinx          // NoSuchMethodError is thrown when a method can't be found or a method is not native.
1105216295Ssyrinx          // Ignoring the exception since it is not preventing use of other WhiteBox methods.
1106216295Ssyrinx          tty->print_cr("Warning: 'NoSuchMethodError' on register of sun.hotspot.WhiteBox::%s%s",
1107216295Ssyrinx              method_array[i].name, method_array[i].signature);
1108216295Ssyrinx        }
1109216295Ssyrinx      } else {
1110216295Ssyrinx        // Registration failed unexpectedly.
1111216295Ssyrinx        tty->print_cr("Warning: unexpected error on register of sun.hotspot.WhiteBox::%s%s. All methods will be unregistered",
1112216295Ssyrinx            method_array[i].name, method_array[i].signature);
1113216295Ssyrinx        env->UnregisterNatives(wbclass);
1114216295Ssyrinx        break;
1115216295Ssyrinx      }
1116216295Ssyrinx    }
1117216295Ssyrinx  }
1118216295Ssyrinx}
1119216295Ssyrinx
1120216295Ssyrinx#define CC (char*)
1121216295Ssyrinx
1122216295Ssyrinxstatic JNINativeMethod methods[] = {
1123216295Ssyrinx  {CC"getObjectAddress",   CC"(Ljava/lang/Object;)J", (void*)&WB_GetObjectAddress  },
1124216295Ssyrinx  {CC"getObjectSize",      CC"(Ljava/lang/Object;)J", (void*)&WB_GetObjectSize     },
1125216295Ssyrinx  {CC"isObjectInOldGen",   CC"(Ljava/lang/Object;)Z", (void*)&WB_isObjectInOldGen  },
1126216295Ssyrinx  {CC"getHeapOopSize",     CC"()I",                   (void*)&WB_GetHeapOopSize    },
1127216295Ssyrinx  {CC"getVMPageSize",      CC"()I",                   (void*)&WB_GetVMPageSize     },
1128216295Ssyrinx  {CC"isClassAlive0",      CC"(Ljava/lang/String;)Z", (void*)&WB_IsClassAlive      },
1129216295Ssyrinx  {CC"parseCommandLine",
1130216295Ssyrinx      CC"(Ljava/lang/String;C[Lsun/hotspot/parser/DiagnosticCommand;)[Ljava/lang/Object;",
1131216295Ssyrinx      (void*) &WB_ParseCommandLine
1132216295Ssyrinx  },
1133216295Ssyrinx  {CC"addToBootstrapClassLoaderSearch", CC"(Ljava/lang/String;)V",
1134216295Ssyrinx                                                      (void*)&WB_AddToBootstrapClassLoaderSearch},
1135216295Ssyrinx  {CC"addToSystemClassLoaderSearch",    CC"(Ljava/lang/String;)V",
1136216295Ssyrinx                                                      (void*)&WB_AddToSystemClassLoaderSearch},
1137216295Ssyrinx  {CC"getCompressedOopsMaxHeapSize", CC"()J",
1138216295Ssyrinx      (void*)&WB_GetCompressedOopsMaxHeapSize},
1139216295Ssyrinx  {CC"printHeapSizes",     CC"()V",                   (void*)&WB_PrintHeapSizes    },
1140216295Ssyrinx  {CC"runMemoryUnitTests", CC"()V",                   (void*)&WB_RunMemoryUnitTests},
1141216295Ssyrinx  {CC"readFromNoaccessArea",CC"()V",                  (void*)&WB_ReadFromNoaccessArea},
1142216295Ssyrinx  {CC"stressVirtualSpaceResize",CC"(JJJ)I",           (void*)&WB_StressVirtualSpaceResize},
1143216295Ssyrinx#if INCLUDE_ALL_GCS
1144216295Ssyrinx  {CC"g1InConcurrentMark", CC"()Z",                   (void*)&WB_G1InConcurrentMark},
1145216295Ssyrinx  {CC"g1IsHumongous",      CC"(Ljava/lang/Object;)Z", (void*)&WB_G1IsHumongous     },
1146216295Ssyrinx  {CC"g1NumFreeRegions",   CC"()J",                   (void*)&WB_G1NumFreeRegions  },
1147216295Ssyrinx  {CC"g1RegionSize",       CC"()I",                   (void*)&WB_G1RegionSize      },
1148216295Ssyrinx#endif // INCLUDE_ALL_GCS
1149216295Ssyrinx#if INCLUDE_NMT
1150216295Ssyrinx  {CC"NMTMalloc",           CC"(J)J",                 (void*)&WB_NMTMalloc          },
1151216295Ssyrinx  {CC"NMTMallocWithPseudoStack", CC"(JI)J",           (void*)&WB_NMTMallocWithPseudoStack},
1152216295Ssyrinx  {CC"NMTFree",             CC"(J)V",                 (void*)&WB_NMTFree            },
1153216295Ssyrinx  {CC"NMTReserveMemory",    CC"(J)J",                 (void*)&WB_NMTReserveMemory   },
1154216295Ssyrinx  {CC"NMTCommitMemory",     CC"(JJ)V",                (void*)&WB_NMTCommitMemory    },
1155216295Ssyrinx  {CC"NMTUncommitMemory",   CC"(JJ)V",                (void*)&WB_NMTUncommitMemory  },
1156216295Ssyrinx  {CC"NMTReleaseMemory",    CC"(JJ)V",                (void*)&WB_NMTReleaseMemory   },
1157216295Ssyrinx  {CC"NMTIsDetailSupported",CC"()Z",                  (void*)&WB_NMTIsDetailSupported},
1158216295Ssyrinx  {CC"NMTChangeTrackingLevel", CC"()Z",               (void*)&WB_NMTChangeTrackingLevel},
1159216295Ssyrinx  {CC"NMTGetHashSize",      CC"()I",                  (void*)&WB_NMTGetHashSize     },
1160216295Ssyrinx#endif // INCLUDE_NMT
1161216295Ssyrinx  {CC"deoptimizeAll",      CC"()V",                   (void*)&WB_DeoptimizeAll     },
1162216295Ssyrinx  {CC"deoptimizeMethod",   CC"(Ljava/lang/reflect/Executable;Z)I",
1163216295Ssyrinx                                                      (void*)&WB_DeoptimizeMethod  },
1164216295Ssyrinx  {CC"isMethodCompiled",   CC"(Ljava/lang/reflect/Executable;Z)Z",
1165216295Ssyrinx                                                      (void*)&WB_IsMethodCompiled  },
1166216295Ssyrinx  {CC"isMethodCompilable", CC"(Ljava/lang/reflect/Executable;IZ)Z",
1167216295Ssyrinx                                                      (void*)&WB_IsMethodCompilable},
1168216295Ssyrinx  {CC"isMethodQueuedForCompilation",
1169216295Ssyrinx      CC"(Ljava/lang/reflect/Executable;)Z",          (void*)&WB_IsMethodQueuedForCompilation},
1170216295Ssyrinx  {CC"makeMethodNotCompilable",
1171216295Ssyrinx      CC"(Ljava/lang/reflect/Executable;IZ)V",        (void*)&WB_MakeMethodNotCompilable},
1172216295Ssyrinx  {CC"testSetDontInlineMethod",
1173216295Ssyrinx      CC"(Ljava/lang/reflect/Executable;Z)Z",         (void*)&WB_TestSetDontInlineMethod},
1174216295Ssyrinx  {CC"getMethodCompilationLevel",
1175216295Ssyrinx      CC"(Ljava/lang/reflect/Executable;Z)I",         (void*)&WB_GetMethodCompilationLevel},
1176216295Ssyrinx  {CC"getMethodEntryBci",
1177216295Ssyrinx      CC"(Ljava/lang/reflect/Executable;)I",          (void*)&WB_GetMethodEntryBci},
1178216295Ssyrinx  {CC"getCompileQueueSize",
1179216295Ssyrinx      CC"(I)I",                                       (void*)&WB_GetCompileQueueSize},
1180216295Ssyrinx  {CC"testSetForceInlineMethod",
1181216295Ssyrinx      CC"(Ljava/lang/reflect/Executable;Z)Z",         (void*)&WB_TestSetForceInlineMethod},
1182216295Ssyrinx  {CC"enqueueMethodForCompilation",
1183216295Ssyrinx      CC"(Ljava/lang/reflect/Executable;II)Z",        (void*)&WB_EnqueueMethodForCompilation},
1184216295Ssyrinx  {CC"clearMethodState",
1185216295Ssyrinx      CC"(Ljava/lang/reflect/Executable;)V",          (void*)&WB_ClearMethodState},
1186216295Ssyrinx  {CC"lockCompilation",    CC"()V",                   (void*)&WB_LockCompilation},
1187216295Ssyrinx  {CC"unlockCompilation",  CC"()V",                   (void*)&WB_UnlockCompilation},
1188216295Ssyrinx  {CC"isConstantVMFlag",   CC"(Ljava/lang/String;)Z", (void*)&WB_IsConstantVMFlag},
1189216295Ssyrinx  {CC"isLockedVMFlag",     CC"(Ljava/lang/String;)Z", (void*)&WB_IsLockedVMFlag},
1190216295Ssyrinx  {CC"setBooleanVMFlag",   CC"(Ljava/lang/String;Z)V",(void*)&WB_SetBooleanVMFlag},
1191216295Ssyrinx  {CC"setIntxVMFlag",      CC"(Ljava/lang/String;J)V",(void*)&WB_SetIntxVMFlag},
1192216295Ssyrinx  {CC"setUintxVMFlag",     CC"(Ljava/lang/String;J)V",(void*)&WB_SetUintxVMFlag},
1193216295Ssyrinx  {CC"setUint64VMFlag",    CC"(Ljava/lang/String;J)V",(void*)&WB_SetUint64VMFlag},
1194216295Ssyrinx  {CC"setSizeTVMFlag",     CC"(Ljava/lang/String;J)V",(void*)&WB_SetSizeTVMFlag},
1195216295Ssyrinx  {CC"setDoubleVMFlag",    CC"(Ljava/lang/String;D)V",(void*)&WB_SetDoubleVMFlag},
1196216295Ssyrinx  {CC"setStringVMFlag",    CC"(Ljava/lang/String;Ljava/lang/String;)V",
1197216295Ssyrinx                                                      (void*)&WB_SetStringVMFlag},
1198216295Ssyrinx  {CC"getBooleanVMFlag",   CC"(Ljava/lang/String;)Ljava/lang/Boolean;",
1199216295Ssyrinx                                                      (void*)&WB_GetBooleanVMFlag},
1200216295Ssyrinx  {CC"getIntxVMFlag",      CC"(Ljava/lang/String;)Ljava/lang/Long;",
1201216295Ssyrinx                                                      (void*)&WB_GetIntxVMFlag},
1202216295Ssyrinx  {CC"getUintxVMFlag",     CC"(Ljava/lang/String;)Ljava/lang/Long;",
1203216295Ssyrinx                                                      (void*)&WB_GetUintxVMFlag},
1204216295Ssyrinx  {CC"getUint64VMFlag",    CC"(Ljava/lang/String;)Ljava/lang/Long;",
1205216295Ssyrinx                                                      (void*)&WB_GetUint64VMFlag},
1206216295Ssyrinx  {CC"getSizeTVMFlag",     CC"(Ljava/lang/String;)Ljava/lang/Long;",
1207216295Ssyrinx                                                      (void*)&WB_GetSizeTVMFlag},
1208216295Ssyrinx  {CC"getDoubleVMFlag",    CC"(Ljava/lang/String;)Ljava/lang/Double;",
1209216295Ssyrinx                                                      (void*)&WB_GetDoubleVMFlag},
1210216295Ssyrinx  {CC"getStringVMFlag",    CC"(Ljava/lang/String;)Ljava/lang/String;",
1211216295Ssyrinx                                                      (void*)&WB_GetStringVMFlag},
1212216295Ssyrinx  {CC"isInStringTable",    CC"(Ljava/lang/String;)Z", (void*)&WB_IsInStringTable  },
1213216295Ssyrinx  {CC"fullGC",   CC"()V",                             (void*)&WB_FullGC },
1214216295Ssyrinx  {CC"youngGC",  CC"()V",                             (void*)&WB_YoungGC },
1215216295Ssyrinx  {CC"readReservedMemory", CC"()V",                   (void*)&WB_ReadReservedMemory },
1216216295Ssyrinx  {CC"allocateMetaspace",
1217216295Ssyrinx     CC"(Ljava/lang/ClassLoader;J)J",                 (void*)&WB_AllocateMetaspace },
1218216295Ssyrinx  {CC"freeMetaspace",
1219216295Ssyrinx     CC"(Ljava/lang/ClassLoader;JJ)V",                (void*)&WB_FreeMetaspace },
1220216295Ssyrinx  {CC"incMetaspaceCapacityUntilGC", CC"(J)J",         (void*)&WB_IncMetaspaceCapacityUntilGC },
1221216295Ssyrinx  {CC"metaspaceCapacityUntilGC", CC"()J",             (void*)&WB_MetaspaceCapacityUntilGC },
1222216295Ssyrinx  {CC"getCPUFeatures",     CC"()Ljava/lang/String;",  (void*)&WB_GetCPUFeatures     },
1223216295Ssyrinx  {CC"getNMethod",         CC"(Ljava/lang/reflect/Executable;Z)[Ljava/lang/Object;",
1224216295Ssyrinx                                                      (void*)&WB_GetNMethod         },
1225216295Ssyrinx  {CC"forceNMethodSweep",  CC"()V",                   (void*)&WB_ForceNMethodSweep  },
1226216295Ssyrinx  {CC"allocateCodeBlob",   CC"(II)J",                 (void*)&WB_AllocateCodeBlob   },
1227216295Ssyrinx  {CC"freeCodeBlob",       CC"(J)V",                  (void*)&WB_FreeCodeBlob       },
1228216295Ssyrinx  {CC"getCodeHeapEntries", CC"(I)[Ljava/lang/Object;",(void*)&WB_GetCodeHeapEntries },
1229216295Ssyrinx  {CC"getThreadStackSize", CC"()J",                   (void*)&WB_GetThreadStackSize },
1230216295Ssyrinx  {CC"getThreadRemainingStackSize", CC"()J",          (void*)&WB_GetThreadRemainingStackSize },
1231216295Ssyrinx};
1232216295Ssyrinx
1233216295Ssyrinx#undef CC
1234216295Ssyrinx
1235216295SsyrinxJVM_ENTRY(void, JVM_RegisterWhiteBoxMethods(JNIEnv* env, jclass wbclass))
1236216295Ssyrinx  {
1237216295Ssyrinx    if (WhiteBoxAPI) {
1238216295Ssyrinx      // Make sure that wbclass is loaded by the null classloader
1239216295Ssyrinx      instanceKlassHandle ikh = instanceKlassHandle(JNIHandles::resolve(wbclass)->klass());
1240216295Ssyrinx      Handle loader(ikh->class_loader());
1241216295Ssyrinx      if (loader.is_null()) {
1242216295Ssyrinx        WhiteBox::register_methods(env, wbclass, thread, methods, sizeof(methods) / sizeof(methods[0]));
1243216295Ssyrinx        WhiteBox::register_extended(env, wbclass, thread);
1244216295Ssyrinx        WhiteBox::set_used();
1245216295Ssyrinx      }
1246216295Ssyrinx    }
1247216295Ssyrinx  }
1248216295SsyrinxJVM_END
1249216295Ssyrinx