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