mgerdin@3619: /* hseigel@4987: * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. mgerdin@3619: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. mgerdin@3619: * mgerdin@3619: * This code is free software; you can redistribute it and/or modify it mgerdin@3619: * under the terms of the GNU General Public License version 2 only, as mgerdin@3619: * published by the Free Software Foundation. mgerdin@3619: * mgerdin@3619: * This code is distributed in the hope that it will be useful, but WITHOUT mgerdin@3619: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or mgerdin@3619: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License mgerdin@3619: * version 2 for more details (a copy is included in the LICENSE file that mgerdin@3619: * accompanied this code). mgerdin@3619: * mgerdin@3619: * You should have received a copy of the GNU General Public License version mgerdin@3619: * 2 along with this work; if not, write to the Free Software Foundation, mgerdin@3619: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. mgerdin@3619: * mgerdin@3619: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA mgerdin@3619: * or visit www.oracle.com if you need additional information or have any mgerdin@3619: * questions. mgerdin@3619: * mgerdin@3619: */ mgerdin@3619: mgerdin@3619: #include "precompiled.hpp" mgerdin@3619: mgerdin@3619: #include "memory/universe.hpp" mgerdin@3619: #include "oops/oop.inline.hpp" nloodin@3681: nloodin@3681: #include "classfile/symbolTable.hpp" coleenp@4037: #include "classfile/classLoaderData.hpp" nloodin@3681: mgerdin@3619: #include "prims/whitebox.hpp" nloodin@3681: #include "prims/wbtestmethods/parserTests.hpp" nloodin@3681: tschatzl@5701: #include "runtime/arguments.hpp" mgerdin@3619: #include "runtime/interfaceSupport.hpp" mgerdin@3619: #include "runtime/os.hpp" mgerdin@3619: #include "utilities/debug.hpp" jprovino@4542: #include "utilities/macros.hpp" mikael@5174: #include "utilities/exceptions.hpp" mgerdin@3619: jprovino@4542: #if INCLUDE_ALL_GCS mgerdin@3619: #include "gc_implementation/g1/concurrentMark.hpp" mgerdin@3619: #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" mgerdin@3619: #include "gc_implementation/g1/heapRegionRemSet.hpp" jprovino@4542: #endif // INCLUDE_ALL_GCS mgerdin@3619: ctornqvi@4512: #ifdef INCLUDE_NMT ctornqvi@4512: #include "services/memTracker.hpp" ctornqvi@4512: #endif // INCLUDE_NMT ctornqvi@4512: iignatyev@4592: #include "compiler/compileBroker.hpp" iignatyev@4908: #include "runtime/compilationPolicy.hpp" iignatyev@4592: mgerdin@6078: #define SIZE_T_MAX_VALUE ((size_t) -1) mgerdin@6078: mgerdin@3619: bool WhiteBox::_used = false; mgerdin@3619: mgerdin@3619: WB_ENTRY(jlong, WB_GetObjectAddress(JNIEnv* env, jobject o, jobject obj)) mgerdin@3619: return (jlong)(void*)JNIHandles::resolve(obj); mgerdin@3619: WB_END mgerdin@3619: mgerdin@3619: WB_ENTRY(jint, WB_GetHeapOopSize(JNIEnv* env, jobject o)) mgerdin@3619: return heapOopSize; mgerdin@3619: WB_END mgerdin@3619: coleenp@4037: coleenp@4037: class WBIsKlassAliveClosure : public KlassClosure { coleenp@4037: Symbol* _name; coleenp@4037: bool _found; coleenp@4037: public: coleenp@4037: WBIsKlassAliveClosure(Symbol* name) : _name(name), _found(false) {} coleenp@4037: coleenp@4037: void do_klass(Klass* k) { coleenp@4037: if (_found) return; coleenp@4037: Symbol* ksym = k->name(); coleenp@4037: if (ksym->fast_compare(_name) == 0) { coleenp@4037: _found = true; coleenp@4037: } coleenp@4037: } coleenp@4037: coleenp@4037: bool found() const { coleenp@4037: return _found; coleenp@4037: } coleenp@4037: }; coleenp@4037: coleenp@4037: WB_ENTRY(jboolean, WB_IsClassAlive(JNIEnv* env, jobject target, jstring name)) coleenp@4037: Handle h_name = JNIHandles::resolve(name); coleenp@4037: if (h_name.is_null()) return false; coleenp@4037: Symbol* sym = java_lang_String::as_symbol(h_name, CHECK_false); coleenp@4037: TempNewSymbol tsym(sym); // Make sure to decrement reference count on sym on return coleenp@4037: coleenp@4037: WBIsKlassAliveClosure closure(sym); coleenp@4037: ClassLoaderDataGraph::classes_do(&closure); coleenp@4037: coleenp@4037: return closure.found(); coleenp@4037: WB_END coleenp@4037: tschatzl@5701: WB_ENTRY(jlong, WB_GetCompressedOopsMaxHeapSize(JNIEnv* env, jobject o)) { tschatzl@5701: return (jlong)Arguments::max_heap_for_compressed_oops(); tschatzl@5701: } tschatzl@5701: WB_END tschatzl@5701: tschatzl@5073: WB_ENTRY(void, WB_PrintHeapSizes(JNIEnv* env, jobject o)) { tschatzl@5073: CollectorPolicy * p = Universe::heap()->collector_policy(); tschatzl@5073: gclog_or_tty->print_cr("Minimum heap "SIZE_FORMAT" Initial heap " tschatzl@5073: SIZE_FORMAT" Maximum heap "SIZE_FORMAT" Min alignment "SIZE_FORMAT" Max alignment "SIZE_FORMAT, tschatzl@5073: p->min_heap_byte_size(), p->initial_heap_byte_size(), p->max_heap_byte_size(), jwilhelm@6085: p->space_alignment(), p->heap_alignment()); tschatzl@5073: } tschatzl@5073: WB_END tschatzl@5073: mgerdin@6078: #ifndef PRODUCT mgerdin@6078: // Forward declaration mgerdin@6078: void TestReservedSpace_test(); mgerdin@6078: void TestReserveMemorySpecial_test(); mgerdin@6078: void TestVirtualSpace_test(); mgerdin@6078: void TestMetaspaceAux_test(); mgerdin@6078: #endif mgerdin@6078: mgerdin@6078: WB_ENTRY(void, WB_RunMemoryUnitTests(JNIEnv* env, jobject o)) mgerdin@6078: #ifndef PRODUCT mgerdin@6078: TestReservedSpace_test(); mgerdin@6078: TestReserveMemorySpecial_test(); mgerdin@6078: TestVirtualSpace_test(); mgerdin@6078: TestMetaspaceAux_test(); mgerdin@6078: #endif mgerdin@6078: WB_END mgerdin@6078: mgerdin@6078: WB_ENTRY(void, WB_ReadFromNoaccessArea(JNIEnv* env, jobject o)) mgerdin@6078: size_t granularity = os::vm_allocation_granularity(); mgerdin@6078: ReservedHeapSpace rhs(100 * granularity, granularity, false, NULL); mgerdin@6078: VirtualSpace vs; mgerdin@6078: vs.initialize(rhs, 50 * granularity); mgerdin@6078: mgerdin@6078: //Check if constraints are complied mgerdin@6078: if (!( UseCompressedOops && rhs.base() != NULL && mgerdin@6078: Universe::narrow_oop_base() != NULL && mgerdin@6078: Universe::narrow_oop_use_implicit_null_checks() )) { mgerdin@6078: tty->print_cr("WB_ReadFromNoaccessArea method is useless:\n " mgerdin@6078: "\tUseCompressedOops is %d\n" mgerdin@6078: "\trhs.base() is "PTR_FORMAT"\n" mgerdin@6078: "\tUniverse::narrow_oop_base() is "PTR_FORMAT"\n" mgerdin@6078: "\tUniverse::narrow_oop_use_implicit_null_checks() is %d", mgerdin@6078: UseCompressedOops, mgerdin@6078: rhs.base(), mgerdin@6078: Universe::narrow_oop_base(), mgerdin@6078: Universe::narrow_oop_use_implicit_null_checks()); mgerdin@6078: return; mgerdin@6078: } mgerdin@6078: tty->print_cr("Reading from no access area... "); mgerdin@6078: tty->print_cr("*(vs.low_boundary() - rhs.noaccess_prefix() / 2 ) = %c", mgerdin@6078: *(vs.low_boundary() - rhs.noaccess_prefix() / 2 )); mgerdin@6078: WB_END mgerdin@6078: mgerdin@6078: static jint wb_stress_virtual_space_resize(size_t reserved_space_size, mgerdin@6078: size_t magnitude, size_t iterations) { mgerdin@6078: size_t granularity = os::vm_allocation_granularity(); mgerdin@6078: ReservedHeapSpace rhs(reserved_space_size * granularity, granularity, false, NULL); mgerdin@6078: VirtualSpace vs; mgerdin@6078: if (!vs.initialize(rhs, 0)) { mgerdin@6078: tty->print_cr("Failed to initialize VirtualSpace. Can't proceed."); mgerdin@6078: return 3; mgerdin@6078: } mgerdin@6078: mgerdin@6078: long seed = os::random(); mgerdin@6078: tty->print_cr("Random seed is %ld", seed); mgerdin@6078: os::init_random(seed); mgerdin@6078: mgerdin@6078: for (size_t i = 0; i < iterations; i++) { mgerdin@6078: mgerdin@6078: // Whether we will shrink or grow mgerdin@6078: bool shrink = os::random() % 2L == 0; mgerdin@6078: mgerdin@6078: // Get random delta to resize virtual space mgerdin@6078: size_t delta = (size_t)os::random() % magnitude; mgerdin@6078: mgerdin@6078: // If we are about to shrink virtual space below zero, then expand instead mgerdin@6078: if (shrink && vs.committed_size() < delta) { mgerdin@6078: shrink = false; mgerdin@6078: } mgerdin@6078: mgerdin@6078: // Resizing by delta mgerdin@6078: if (shrink) { mgerdin@6078: vs.shrink_by(delta); mgerdin@6078: } else { mgerdin@6078: // If expanding fails expand_by will silently return false mgerdin@6078: vs.expand_by(delta, true); mgerdin@6078: } mgerdin@6078: } mgerdin@6078: return 0; mgerdin@6078: } mgerdin@6078: mgerdin@6078: WB_ENTRY(jint, WB_StressVirtualSpaceResize(JNIEnv* env, jobject o, mgerdin@6078: jlong reserved_space_size, jlong magnitude, jlong iterations)) mgerdin@6078: tty->print_cr("reservedSpaceSize="JLONG_FORMAT", magnitude="JLONG_FORMAT", " mgerdin@6078: "iterations="JLONG_FORMAT"\n", reserved_space_size, magnitude, mgerdin@6078: iterations); mgerdin@6078: if (reserved_space_size < 0 || magnitude < 0 || iterations < 0) { mgerdin@6078: tty->print_cr("One of variables printed above is negative. Can't proceed.\n"); mgerdin@6078: return 1; mgerdin@6078: } mgerdin@6078: mgerdin@6078: // sizeof(size_t) depends on whether OS is 32bit or 64bit. sizeof(jlong) is mgerdin@6078: // always 8 byte. That's why we should avoid overflow in case of 32bit platform. mgerdin@6078: if (sizeof(size_t) < sizeof(jlong)) { mgerdin@6078: jlong size_t_max_value = (jlong) SIZE_T_MAX_VALUE; mgerdin@6078: if (reserved_space_size > size_t_max_value || magnitude > size_t_max_value mgerdin@6078: || iterations > size_t_max_value) { mgerdin@6078: tty->print_cr("One of variables printed above overflows size_t. Can't proceed.\n"); mgerdin@6078: return 2; mgerdin@6078: } mgerdin@6078: } mgerdin@6078: mgerdin@6078: return wb_stress_virtual_space_resize((size_t) reserved_space_size, mgerdin@6078: (size_t) magnitude, (size_t) iterations); mgerdin@6078: WB_END mgerdin@6078: jprovino@4542: #if INCLUDE_ALL_GCS mgerdin@3619: WB_ENTRY(jboolean, WB_G1IsHumongous(JNIEnv* env, jobject o, jobject obj)) mgerdin@3619: G1CollectedHeap* g1 = G1CollectedHeap::heap(); mgerdin@3619: oop result = JNIHandles::resolve(obj); mgerdin@3619: const HeapRegion* hr = g1->heap_region_containing(result); mgerdin@3619: return hr->isHumongous(); mgerdin@3619: WB_END mgerdin@3619: mgerdin@3619: WB_ENTRY(jlong, WB_G1NumFreeRegions(JNIEnv* env, jobject o)) mgerdin@3619: G1CollectedHeap* g1 = G1CollectedHeap::heap(); mgerdin@3619: size_t nr = g1->free_regions(); mgerdin@3619: return (jlong)nr; mgerdin@3619: WB_END mgerdin@3619: mgerdin@3619: WB_ENTRY(jboolean, WB_G1InConcurrentMark(JNIEnv* env, jobject o)) mgerdin@3619: G1CollectedHeap* g1 = G1CollectedHeap::heap(); mgerdin@3619: ConcurrentMark* cm = g1->concurrent_mark(); mgerdin@3619: return cm->concurrent_marking_in_progress(); mgerdin@3619: WB_END mgerdin@3619: mgerdin@3619: WB_ENTRY(jint, WB_G1RegionSize(JNIEnv* env, jobject o)) mgerdin@3619: return (jint)HeapRegion::GrainBytes; mgerdin@3619: WB_END jprovino@4542: #endif // INCLUDE_ALL_GCS mgerdin@3619: cjplummer@5586: #if INCLUDE_NMT ctornqvi@4512: // Alloc memory using the test memory type so that we can use that to see if ctornqvi@4512: // NMT picks it up correctly ctornqvi@4885: WB_ENTRY(jlong, WB_NMTMalloc(JNIEnv* env, jobject o, jlong size)) ctornqvi@4885: jlong addr = 0; ctornqvi@4512: ctornqvi@4885: if (MemTracker::is_on() && !MemTracker::shutdown_in_progress()) { ctornqvi@4885: addr = (jlong)(uintptr_t)os::malloc(size, mtTest); ctornqvi@4512: } ctornqvi@4512: ctornqvi@4885: return addr; ctornqvi@4512: WB_END ctornqvi@4512: ctornqvi@4512: // Free the memory allocated by NMTAllocTest ctornqvi@4885: WB_ENTRY(void, WB_NMTFree(JNIEnv* env, jobject o, jlong mem)) ctornqvi@4885: os::free((void*)(uintptr_t)mem, mtTest); ctornqvi@4885: WB_END ctornqvi@4512: ctornqvi@4885: WB_ENTRY(jlong, WB_NMTReserveMemory(JNIEnv* env, jobject o, jlong size)) ctornqvi@4885: jlong addr = 0; ctornqvi@4885: ctornqvi@4885: if (MemTracker::is_on() && !MemTracker::shutdown_in_progress()) { ctornqvi@4885: addr = (jlong)(uintptr_t)os::reserve_memory(size); ctornqvi@4885: MemTracker::record_virtual_memory_type((address)addr, mtTest); ctornqvi@4512: } ctornqvi@4512: ctornqvi@4885: return addr; ctornqvi@4885: WB_END ctornqvi@4512: ctornqvi@4885: ctornqvi@4885: WB_ENTRY(void, WB_NMTCommitMemory(JNIEnv* env, jobject o, jlong addr, jlong size)) dcubed@5255: os::commit_memory((char *)(uintptr_t)addr, size, !ExecMem); ctornqvi@4885: MemTracker::record_virtual_memory_type((address)(uintptr_t)addr, mtTest); ctornqvi@4885: WB_END ctornqvi@4885: ctornqvi@4885: WB_ENTRY(void, WB_NMTUncommitMemory(JNIEnv* env, jobject o, jlong addr, jlong size)) ctornqvi@4885: os::uncommit_memory((char *)(uintptr_t)addr, size); ctornqvi@4885: WB_END ctornqvi@4885: ctornqvi@4885: WB_ENTRY(void, WB_NMTReleaseMemory(JNIEnv* env, jobject o, jlong addr, jlong size)) ctornqvi@4885: os::release_memory((char *)(uintptr_t)addr, size); ctornqvi@4512: WB_END ctornqvi@4512: ctornqvi@4512: // Block until the current generation of NMT data to be merged, used to reliably test the NMT feature ctornqvi@4512: WB_ENTRY(jboolean, WB_NMTWaitForDataMerge(JNIEnv* env)) ctornqvi@4512: ctornqvi@4512: if (!MemTracker::is_on() || MemTracker::shutdown_in_progress()) { ctornqvi@4512: return false; ctornqvi@4512: } ctornqvi@4512: ctornqvi@4512: return MemTracker::wbtest_wait_for_data_merge(); ctornqvi@4512: WB_END ctornqvi@4512: cjplummer@5586: WB_ENTRY(jboolean, WB_NMTIsDetailSupported(JNIEnv* env)) cjplummer@5586: return MemTracker::tracking_level() == MemTracker::NMT_detail; cjplummer@5586: WB_END cjplummer@5586: ctornqvi@4512: #endif // INCLUDE_NMT ctornqvi@4512: iignatyev@4592: static jmethodID reflected_method_to_jmid(JavaThread* thread, JNIEnv* env, jobject method) { iignatyev@4592: assert(method != NULL, "method should not be null"); iignatyev@4592: ThreadToNativeFromVM ttn(thread); iignatyev@4592: return env->FromReflectedMethod(method); iignatyev@4592: } iignatyev@4592: iignatyev@4592: WB_ENTRY(void, WB_DeoptimizeAll(JNIEnv* env, jobject o)) iignatyev@4592: MutexLockerEx mu(Compile_lock); iignatyev@4592: CodeCache::mark_all_nmethods_for_deoptimization(); iignatyev@4592: VM_Deoptimize op; iignatyev@4592: VMThread::execute(&op); iignatyev@4592: WB_END iignatyev@4592: iignatyev@5541: WB_ENTRY(jint, WB_DeoptimizeMethod(JNIEnv* env, jobject o, jobject method, jboolean is_osr)) iignatyev@4592: jmethodID jmid = reflected_method_to_jmid(thread, env, method); iignatyev@4592: MutexLockerEx mu(Compile_lock); iignatyev@4592: methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid)); iignatyev@4592: int result = 0; iignatyev@5541: nmethod* code; iignatyev@5541: if (is_osr) { iignatyev@5541: int bci = InvocationEntryBci; iignatyev@5541: while ((code = mh->lookup_osr_nmethod_for(bci, CompLevel_none, false)) != NULL) { iignatyev@5541: code->mark_for_deoptimization(); iignatyev@5541: ++result; iignatyev@5541: bci = code->osr_entry_bci() + 1; iignatyev@5541: } iignatyev@5541: } else { iignatyev@5541: code = mh->code(); iignatyev@5541: } iignatyev@4592: if (code != NULL) { iignatyev@4592: code->mark_for_deoptimization(); iignatyev@4592: ++result; iignatyev@4592: } iignatyev@4592: result += CodeCache::mark_for_deoptimization(mh()); iignatyev@4592: if (result > 0) { iignatyev@4592: VM_Deoptimize op; iignatyev@4592: VMThread::execute(&op); iignatyev@4592: } iignatyev@4592: return result; iignatyev@4592: WB_END iignatyev@4592: iignatyev@5541: WB_ENTRY(jboolean, WB_IsMethodCompiled(JNIEnv* env, jobject o, jobject method, jboolean is_osr)) iignatyev@4592: jmethodID jmid = reflected_method_to_jmid(thread, env, method); iignatyev@4592: MutexLockerEx mu(Compile_lock); iignatyev@4592: methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid)); iignatyev@5541: nmethod* code = is_osr ? mh->lookup_osr_nmethod_for(InvocationEntryBci, CompLevel_none, false) : mh->code(); iignatyev@4592: if (code == NULL) { iignatyev@4592: return JNI_FALSE; iignatyev@4592: } iignatyev@4592: return (code->is_alive() && !code->is_marked_for_deoptimization()); iignatyev@4592: WB_END iignatyev@4592: iignatyev@5541: WB_ENTRY(jboolean, WB_IsMethodCompilable(JNIEnv* env, jobject o, jobject method, jint comp_level, jboolean is_osr)) iignatyev@4592: jmethodID jmid = reflected_method_to_jmid(thread, env, method); iignatyev@4592: MutexLockerEx mu(Compile_lock); iignatyev@4592: methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid)); iignatyev@5541: if (is_osr) { iignatyev@5541: return CompilationPolicy::can_be_osr_compiled(mh, comp_level); iignatyev@5541: } else { iignatyev@5541: return CompilationPolicy::can_be_compiled(mh, comp_level); iignatyev@5541: } iignatyev@4592: WB_END iignatyev@4592: iignatyev@4592: WB_ENTRY(jboolean, WB_IsMethodQueuedForCompilation(JNIEnv* env, jobject o, jobject method)) iignatyev@4592: jmethodID jmid = reflected_method_to_jmid(thread, env, method); iignatyev@4592: MutexLockerEx mu(Compile_lock); iignatyev@4592: methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid)); iignatyev@4592: return mh->queued_for_compilation(); iignatyev@4592: WB_END iignatyev@4592: iignatyev@5541: WB_ENTRY(jint, WB_GetMethodCompilationLevel(JNIEnv* env, jobject o, jobject method, jboolean is_osr)) iignatyev@4592: jmethodID jmid = reflected_method_to_jmid(thread, env, method); iignatyev@4592: methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid)); iignatyev@5541: nmethod* code = is_osr ? mh->lookup_osr_nmethod_for(InvocationEntryBci, CompLevel_none, false) : mh->code(); iignatyev@4592: return (code != NULL ? code->comp_level() : CompLevel_none); iignatyev@4592: WB_END iignatyev@4592: iignatyev@5541: WB_ENTRY(void, WB_MakeMethodNotCompilable(JNIEnv* env, jobject o, jobject method, jint comp_level, jboolean is_osr)) iignatyev@4592: jmethodID jmid = reflected_method_to_jmid(thread, env, method); iignatyev@4592: methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid)); iignatyev@5541: if (is_osr) { iignatyev@5541: mh->set_not_osr_compilable(comp_level, true /* report */, "WhiteBox"); iignatyev@5541: } else { iignatyev@5541: mh->set_not_compilable(comp_level, true /* report */, "WhiteBox"); iignatyev@5541: } iignatyev@5541: WB_END iignatyev@5541: iignatyev@5541: WB_ENTRY(jint, WB_GetMethodEntryBci(JNIEnv* env, jobject o, jobject method)) iignatyev@5541: jmethodID jmid = reflected_method_to_jmid(thread, env, method); iignatyev@5541: methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid)); iignatyev@5541: nmethod* code = mh->lookup_osr_nmethod_for(InvocationEntryBci, CompLevel_none, false); iignatyev@5541: return (code != NULL && code->is_osr_method() ? code->osr_entry_bci() : InvocationEntryBci); iignatyev@4592: WB_END iignatyev@4592: iignatyev@4908: WB_ENTRY(jboolean, WB_TestSetDontInlineMethod(JNIEnv* env, jobject o, jobject method, jboolean value)) iignatyev@4592: jmethodID jmid = reflected_method_to_jmid(thread, env, method); iignatyev@4592: methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid)); iignatyev@4592: bool result = mh->dont_inline(); iignatyev@4592: mh->set_dont_inline(value == JNI_TRUE); iignatyev@4592: return result; iignatyev@4592: WB_END iignatyev@4592: iignatyev@5541: WB_ENTRY(jint, WB_GetCompileQueueSize(JNIEnv* env, jobject o, jint comp_level)) iignatyev@5541: if (comp_level == CompLevel_any) { iignatyev@5541: return CompileBroker::queue_size(CompLevel_full_optimization) /* C2 */ + iignatyev@5541: CompileBroker::queue_size(CompLevel_full_profile) /* C1 */; iignatyev@5541: } else { iignatyev@5541: return CompileBroker::queue_size(comp_level); iignatyev@5541: } iignatyev@4592: WB_END iignatyev@4592: iignatyev@4908: WB_ENTRY(jboolean, WB_TestSetForceInlineMethod(JNIEnv* env, jobject o, jobject method, jboolean value)) iignatyev@4908: jmethodID jmid = reflected_method_to_jmid(thread, env, method); iignatyev@4908: methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid)); iignatyev@4908: bool result = mh->force_inline(); iignatyev@4908: mh->set_force_inline(value == JNI_TRUE); iignatyev@4908: return result; iignatyev@4908: WB_END iignatyev@4908: iignatyev@5541: WB_ENTRY(jboolean, WB_EnqueueMethodForCompilation(JNIEnv* env, jobject o, jobject method, jint comp_level, jint bci)) iignatyev@4908: jmethodID jmid = reflected_method_to_jmid(thread, env, method); iignatyev@4908: methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid)); iignatyev@5541: nmethod* nm = CompileBroker::compile_method(mh, bci, comp_level, mh, mh->invocation_count(), "WhiteBox", THREAD); iignatyev@4908: MutexLockerEx mu(Compile_lock); iignatyev@4908: return (mh->queued_for_compilation() || nm != NULL); iignatyev@4908: WB_END iignatyev@4908: iignatyev@4908: WB_ENTRY(void, WB_ClearMethodState(JNIEnv* env, jobject o, jobject method)) iignatyev@4908: jmethodID jmid = reflected_method_to_jmid(thread, env, method); iignatyev@4908: methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid)); iignatyev@4908: MutexLockerEx mu(Compile_lock); iignatyev@4908: MethodData* mdo = mh->method_data(); jiangli@4938: MethodCounters* mcs = mh->method_counters(); iignatyev@4908: iignatyev@4908: if (mdo != NULL) { iignatyev@4908: mdo->init(); iignatyev@4908: ResourceMark rm; iignatyev@4908: int arg_count = mdo->method()->size_of_parameters(); iignatyev@4908: for (int i = 0; i < arg_count; i++) { iignatyev@4908: mdo->set_arg_modified(i, 0); iignatyev@4908: } iignatyev@4908: } iignatyev@4908: iignatyev@4908: mh->clear_not_c1_compilable(); iignatyev@4908: mh->clear_not_c2_compilable(); iignatyev@4908: mh->clear_not_c2_osr_compilable(); iignatyev@4908: NOT_PRODUCT(mh->set_compiled_invocation_count(0)); jiangli@4938: if (mcs != NULL) { jiangli@4938: mcs->backedge_counter()->init(); jiangli@4938: mcs->invocation_counter()->init(); jiangli@4938: mcs->set_interpreter_invocation_count(0); jiangli@4938: mcs->set_interpreter_throwout_count(0); iignatyev@4908: iignatyev@4908: #ifdef TIERED jiangli@4938: mcs->set_rate(0.0F); jiangli@4938: mh->set_prev_event_count(0, THREAD); jiangli@4938: mh->set_prev_time(0, THREAD); iignatyev@4908: #endif jiangli@4938: } iignatyev@4908: WB_END iignatyev@4908: mgerdin@4850: WB_ENTRY(jboolean, WB_IsInStringTable(JNIEnv* env, jobject o, jstring javaString)) mgerdin@4850: ResourceMark rm(THREAD); mgerdin@4850: int len; hseigel@4987: jchar* name = java_lang_String::as_unicode_string(JNIHandles::resolve(javaString), len, CHECK_false); hseigel@4987: return (StringTable::lookup(name, len) != NULL); mgerdin@4850: WB_END mgerdin@4850: mgerdin@4850: WB_ENTRY(void, WB_FullGC(JNIEnv* env, jobject o)) mgerdin@4850: Universe::heap()->collector_policy()->set_should_clear_all_soft_refs(true); mgerdin@4850: Universe::heap()->collect(GCCause::_last_ditch_collection); mgerdin@4850: WB_END mgerdin@4850: mikael@4989: mikael@5174: WB_ENTRY(void, WB_ReadReservedMemory(JNIEnv* env, jobject o)) mikael@5174: // static+volatile in order to force the read to happen mikael@5174: // (not be eliminated by the compiler) mikael@5174: static char c; mikael@5174: static volatile char* p; mikael@5174: mikael@5174: p = os::reserve_memory(os::vm_allocation_granularity(), NULL, 0); mikael@5174: if (p == NULL) { mikael@5174: THROW_MSG(vmSymbols::java_lang_OutOfMemoryError(), "Failed to reserve memory"); mikael@5174: } mikael@5174: mikael@5174: c = *p; mikael@4989: WB_END mikael@4989: nloodin@3681: //Some convenience methods to deal with objects from java nloodin@3681: int WhiteBox::offset_for_field(const char* field_name, oop object, nloodin@3681: Symbol* signature_symbol) { nloodin@3681: assert(field_name != NULL && strlen(field_name) > 0, "Field name not valid"); nloodin@3681: Thread* THREAD = Thread::current(); nloodin@3681: nloodin@3681: //Get the class of our object coleenp@4037: Klass* arg_klass = object->klass(); nloodin@3681: //Turn it into an instance-klass coleenp@4037: InstanceKlass* ik = InstanceKlass::cast(arg_klass); nloodin@3681: nloodin@3681: //Create symbols to look for in the class nloodin@3681: TempNewSymbol name_symbol = SymbolTable::lookup(field_name, (int) strlen(field_name), nloodin@3681: THREAD); nloodin@3681: nloodin@3681: //To be filled in with an offset of the field we're looking for nloodin@3681: fieldDescriptor fd; nloodin@3681: coleenp@4037: Klass* res = ik->find_field(name_symbol, signature_symbol, &fd); nloodin@3681: if (res == NULL) { nloodin@3681: tty->print_cr("Invalid layout of %s at %s", ik->external_name(), nloodin@3681: name_symbol->as_C_string()); nloodin@3681: fatal("Invalid layout of preloaded class"); nloodin@3681: } nloodin@3681: nloodin@3681: //fetch the field at the offset we've found nloodin@3681: int dest_offset = fd.offset(); nloodin@3681: nloodin@3681: return dest_offset; nloodin@3681: } nloodin@3681: nloodin@3681: nloodin@3681: const char* WhiteBox::lookup_jstring(const char* field_name, oop object) { nloodin@3681: int offset = offset_for_field(field_name, object, nloodin@3681: vmSymbols::string_signature()); nloodin@3681: oop string = object->obj_field(offset); sla@3905: if (string == NULL) { sla@3905: return NULL; sla@3905: } nloodin@3681: const char* ret = java_lang_String::as_utf8_string(string); nloodin@3681: return ret; nloodin@3681: } nloodin@3681: nloodin@3681: bool WhiteBox::lookup_bool(const char* field_name, oop object) { nloodin@3681: int offset = nloodin@3681: offset_for_field(field_name, object, vmSymbols::bool_signature()); nloodin@3681: bool ret = (object->bool_field(offset) == JNI_TRUE); nloodin@3681: return ret; nloodin@3681: } nloodin@3681: nloodin@3681: mgerdin@3619: #define CC (char*) mgerdin@3619: mgerdin@3619: static JNINativeMethod methods[] = { mgerdin@3619: {CC"getObjectAddress", CC"(Ljava/lang/Object;)J", (void*)&WB_GetObjectAddress }, mgerdin@3619: {CC"getHeapOopSize", CC"()I", (void*)&WB_GetHeapOopSize }, iignatyev@4592: {CC"isClassAlive0", CC"(Ljava/lang/String;)Z", (void*)&WB_IsClassAlive }, iignatyev@4592: {CC"parseCommandLine", iignatyev@4592: CC"(Ljava/lang/String;[Lsun/hotspot/parser/DiagnosticCommand;)[Ljava/lang/Object;", nloodin@3681: (void*) &WB_ParseCommandLine nloodin@3681: }, tschatzl@5701: {CC"getCompressedOopsMaxHeapSize", CC"()J", tschatzl@5701: (void*)&WB_GetCompressedOopsMaxHeapSize}, tschatzl@5073: {CC"printHeapSizes", CC"()V", (void*)&WB_PrintHeapSizes }, mgerdin@6078: {CC"runMemoryUnitTests", CC"()V", (void*)&WB_RunMemoryUnitTests}, mgerdin@6078: {CC"readFromNoaccessArea",CC"()V", (void*)&WB_ReadFromNoaccessArea}, mgerdin@6078: {CC"stressVirtualSpaceResize",CC"(JJJ)I", (void*)&WB_StressVirtualSpaceResize}, jprovino@4542: #if INCLUDE_ALL_GCS mgerdin@3619: {CC"g1InConcurrentMark", CC"()Z", (void*)&WB_G1InConcurrentMark}, mgerdin@3619: {CC"g1IsHumongous", CC"(Ljava/lang/Object;)Z", (void*)&WB_G1IsHumongous }, mgerdin@3619: {CC"g1NumFreeRegions", CC"()J", (void*)&WB_G1NumFreeRegions }, mgerdin@3619: {CC"g1RegionSize", CC"()I", (void*)&WB_G1RegionSize }, jprovino@4542: #endif // INCLUDE_ALL_GCS cjplummer@5586: #if INCLUDE_NMT ctornqvi@4885: {CC"NMTMalloc", CC"(J)J", (void*)&WB_NMTMalloc }, ctornqvi@4885: {CC"NMTFree", CC"(J)V", (void*)&WB_NMTFree }, ctornqvi@4885: {CC"NMTReserveMemory", CC"(J)J", (void*)&WB_NMTReserveMemory }, ctornqvi@4885: {CC"NMTCommitMemory", CC"(JJ)V", (void*)&WB_NMTCommitMemory }, ctornqvi@4885: {CC"NMTUncommitMemory", CC"(JJ)V", (void*)&WB_NMTUncommitMemory }, ctornqvi@4885: {CC"NMTReleaseMemory", CC"(JJ)V", (void*)&WB_NMTReleaseMemory }, ctornqvi@4885: {CC"NMTWaitForDataMerge", CC"()Z", (void*)&WB_NMTWaitForDataMerge}, cjplummer@5586: {CC"NMTIsDetailSupported",CC"()Z", (void*)&WB_NMTIsDetailSupported}, ctornqvi@4512: #endif // INCLUDE_NMT iignatyev@4592: {CC"deoptimizeAll", CC"()V", (void*)&WB_DeoptimizeAll }, iignatyev@5541: {CC"deoptimizeMethod", CC"(Ljava/lang/reflect/Executable;Z)I", iignatyev@4592: (void*)&WB_DeoptimizeMethod }, iignatyev@5541: {CC"isMethodCompiled", CC"(Ljava/lang/reflect/Executable;Z)Z", iignatyev@4592: (void*)&WB_IsMethodCompiled }, iignatyev@5541: {CC"isMethodCompilable", CC"(Ljava/lang/reflect/Executable;IZ)Z", iignatyev@4592: (void*)&WB_IsMethodCompilable}, iignatyev@4592: {CC"isMethodQueuedForCompilation", iignatyev@4951: CC"(Ljava/lang/reflect/Executable;)Z", (void*)&WB_IsMethodQueuedForCompilation}, iignatyev@4592: {CC"makeMethodNotCompilable", iignatyev@5541: CC"(Ljava/lang/reflect/Executable;IZ)V", (void*)&WB_MakeMethodNotCompilable}, iignatyev@4908: {CC"testSetDontInlineMethod", iignatyev@4951: CC"(Ljava/lang/reflect/Executable;Z)Z", (void*)&WB_TestSetDontInlineMethod}, iignatyev@4592: {CC"getMethodCompilationLevel", iignatyev@5541: CC"(Ljava/lang/reflect/Executable;Z)I", (void*)&WB_GetMethodCompilationLevel}, iignatyev@5541: {CC"getMethodEntryBci", iignatyev@5541: CC"(Ljava/lang/reflect/Executable;)I", (void*)&WB_GetMethodEntryBci}, iignatyev@5541: {CC"getCompileQueueSize", iignatyev@5541: CC"(I)I", (void*)&WB_GetCompileQueueSize}, iignatyev@4908: {CC"testSetForceInlineMethod", iignatyev@4951: CC"(Ljava/lang/reflect/Executable;Z)Z", (void*)&WB_TestSetForceInlineMethod}, iignatyev@4908: {CC"enqueueMethodForCompilation", iignatyev@5541: CC"(Ljava/lang/reflect/Executable;II)Z", (void*)&WB_EnqueueMethodForCompilation}, iignatyev@4908: {CC"clearMethodState", iignatyev@4951: CC"(Ljava/lang/reflect/Executable;)V", (void*)&WB_ClearMethodState}, mgerdin@4850: {CC"isInStringTable", CC"(Ljava/lang/String;)Z", (void*)&WB_IsInStringTable }, mgerdin@4850: {CC"fullGC", CC"()V", (void*)&WB_FullGC }, mikael@5174: {CC"readReservedMemory", CC"()V", (void*)&WB_ReadReservedMemory }, mgerdin@3619: }; mgerdin@3619: mgerdin@3619: #undef CC mgerdin@3619: mgerdin@3619: JVM_ENTRY(void, JVM_RegisterWhiteBoxMethods(JNIEnv* env, jclass wbclass)) mgerdin@3619: { mgerdin@3619: if (WhiteBoxAPI) { mgerdin@3619: // Make sure that wbclass is loaded by the null classloader mgerdin@3619: instanceKlassHandle ikh = instanceKlassHandle(JNIHandles::resolve(wbclass)->klass()); mgerdin@3619: Handle loader(ikh->class_loader()); mgerdin@3619: if (loader.is_null()) { iignatyev@5028: ResourceMark rm; mgerdin@3619: ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI iignatyev@5028: bool result = true; iignatyev@5028: // one by one registration natives for exception catching iignatyev@5028: jclass exceptionKlass = env->FindClass(vmSymbols::java_lang_NoSuchMethodError()->as_C_string()); iignatyev@5028: for (int i = 0, n = sizeof(methods) / sizeof(methods[0]); i < n; ++i) { iignatyev@5028: if (env->RegisterNatives(wbclass, methods + i, 1) != 0) { iignatyev@5028: result = false; iignatyev@5028: if (env->ExceptionCheck() && env->IsInstanceOf(env->ExceptionOccurred(), exceptionKlass)) { iignatyev@5028: // j.l.NoSuchMethodError is thrown when a method can't be found or a method is not native iignatyev@5028: // ignoring the exception iignatyev@5028: tty->print_cr("Warning: 'NoSuchMethodError' on register of sun.hotspot.WhiteBox::%s%s", methods[i].name, methods[i].signature); iignatyev@5028: env->ExceptionClear(); iignatyev@5028: } else { iignatyev@5028: // register is failed w/o exception or w/ unexpected exception iignatyev@5028: tty->print_cr("Warning: unexpected error on register of sun.hotspot.WhiteBox::%s%s. All methods will be unregistered", methods[i].name, methods[i].signature); iignatyev@5028: env->UnregisterNatives(wbclass); iignatyev@5028: break; iignatyev@5028: } iignatyev@5028: } iignatyev@5028: } iignatyev@5028: iignatyev@5028: if (result) { mgerdin@3619: WhiteBox::set_used(); mgerdin@3619: } mgerdin@3619: } mgerdin@3619: } mgerdin@3619: } mgerdin@3619: JVM_END