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