mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-26 14:24:46 +02:00
8059624: Test task: WhiteBox API for testing segmented codecache feature
Reviewed-by: kvn, thartmann
This commit is contained in:
parent
80830d4932
commit
bdac822811
18 changed files with 687 additions and 35 deletions
|
@ -43,7 +43,7 @@
|
||||||
#include "c1/c1_Runtime1.hpp"
|
#include "c1/c1_Runtime1.hpp"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
unsigned int align_code_offset(int offset) {
|
unsigned int CodeBlob::align_code_offset(int offset) {
|
||||||
// align the size to CodeEntryAlignment
|
// align the size to CodeEntryAlignment
|
||||||
return
|
return
|
||||||
((offset + (int)CodeHeap::header_size() + (CodeEntryAlignment-1)) & ~(CodeEntryAlignment-1))
|
((offset + (int)CodeHeap::header_size() + (CodeEntryAlignment-1)) & ~(CodeEntryAlignment-1))
|
||||||
|
|
|
@ -83,6 +83,7 @@ class CodeBlob VALUE_OBJ_CLASS_SPEC {
|
||||||
public:
|
public:
|
||||||
// Returns the space needed for CodeBlob
|
// Returns the space needed for CodeBlob
|
||||||
static unsigned int allocation_size(CodeBuffer* cb, int header_size);
|
static unsigned int allocation_size(CodeBuffer* cb, int header_size);
|
||||||
|
static unsigned int align_code_offset(int offset);
|
||||||
|
|
||||||
// Creation
|
// Creation
|
||||||
// a) simple CodeBlob
|
// a) simple CodeBlob
|
||||||
|
@ -207,7 +208,7 @@ class CodeBlob VALUE_OBJ_CLASS_SPEC {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class WhiteBox;
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
// BufferBlob: used to hold non-relocatable machine code such as the interpreter, stubroutines, etc.
|
// BufferBlob: used to hold non-relocatable machine code such as the interpreter, stubroutines, etc.
|
||||||
|
|
||||||
|
@ -215,6 +216,7 @@ class BufferBlob: public CodeBlob {
|
||||||
friend class VMStructs;
|
friend class VMStructs;
|
||||||
friend class AdapterBlob;
|
friend class AdapterBlob;
|
||||||
friend class MethodHandlesAdapterBlob;
|
friend class MethodHandlesAdapterBlob;
|
||||||
|
friend class WhiteBox;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Creation support
|
// Creation support
|
||||||
|
|
|
@ -305,7 +305,7 @@ void CodeCache::add_heap(ReservedSpace rs, const char* name, size_t size_initial
|
||||||
MemoryService::add_code_heap_memory_pool(heap, name);
|
MemoryService::add_code_heap_memory_pool(heap, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
CodeHeap* CodeCache::get_code_heap(CodeBlob* cb) {
|
CodeHeap* CodeCache::get_code_heap(const CodeBlob* cb) {
|
||||||
assert(cb != NULL, "CodeBlob is null");
|
assert(cb != NULL, "CodeBlob is null");
|
||||||
FOR_ALL_HEAPS(heap) {
|
FOR_ALL_HEAPS(heap) {
|
||||||
if ((*heap)->contains(cb)) {
|
if ((*heap)->contains(cb)) {
|
||||||
|
|
|
@ -77,6 +77,7 @@ class DepChange;
|
||||||
class CodeCache : AllStatic {
|
class CodeCache : AllStatic {
|
||||||
friend class VMStructs;
|
friend class VMStructs;
|
||||||
friend class NMethodIterator;
|
friend class NMethodIterator;
|
||||||
|
friend class WhiteBox;
|
||||||
private:
|
private:
|
||||||
// CodeHeaps of the cache
|
// CodeHeaps of the cache
|
||||||
static GrowableArray<CodeHeap*>* _heaps;
|
static GrowableArray<CodeHeap*>* _heaps;
|
||||||
|
@ -98,7 +99,7 @@ class CodeCache : AllStatic {
|
||||||
static void initialize_heaps(); // Initializes the CodeHeaps
|
static void initialize_heaps(); // Initializes the CodeHeaps
|
||||||
// Creates a new heap with the given name and size, containing CodeBlobs of the given type
|
// Creates a new heap with the given name and size, containing CodeBlobs of the given type
|
||||||
static void add_heap(ReservedSpace rs, const char* name, size_t size_initial, int code_blob_type);
|
static void add_heap(ReservedSpace rs, const char* name, size_t size_initial, int code_blob_type);
|
||||||
static CodeHeap* get_code_heap(CodeBlob* cb); // Returns the CodeHeap for the given CodeBlob
|
static CodeHeap* get_code_heap(const CodeBlob* cb); // Returns the CodeHeap for the given CodeBlob
|
||||||
static CodeHeap* get_code_heap(int code_blob_type); // Returns the CodeHeap for the given CodeBlobType
|
static CodeHeap* get_code_heap(int code_blob_type); // Returns the CodeHeap for the given CodeBlobType
|
||||||
// Returns the name of the VM option to set the size of the corresponding CodeHeap
|
// Returns the name of the VM option to set the size of the corresponding CodeHeap
|
||||||
static const char* get_code_heap_flag_name(int code_blob_type);
|
static const char* get_code_heap_flag_name(int code_blob_type);
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
#include "oops/method.hpp"
|
#include "oops/method.hpp"
|
||||||
#include "oops/oop.inline.hpp"
|
#include "oops/oop.inline.hpp"
|
||||||
#include "prims/nativeLookup.hpp"
|
#include "prims/nativeLookup.hpp"
|
||||||
|
#include "prims/whitebox.hpp"
|
||||||
#include "runtime/arguments.hpp"
|
#include "runtime/arguments.hpp"
|
||||||
#include "runtime/atomic.inline.hpp"
|
#include "runtime/atomic.inline.hpp"
|
||||||
#include "runtime/compilationPolicy.hpp"
|
#include "runtime/compilationPolicy.hpp"
|
||||||
|
@ -1963,6 +1964,12 @@ void CompileBroker::invoke_compiler_on_method(CompileTask* task) {
|
||||||
if (comp == NULL) {
|
if (comp == NULL) {
|
||||||
ci_env.record_method_not_compilable("no compiler", !TieredCompilation);
|
ci_env.record_method_not_compilable("no compiler", !TieredCompilation);
|
||||||
} else {
|
} else {
|
||||||
|
if (WhiteBoxAPI && WhiteBox::compilation_locked) {
|
||||||
|
MonitorLockerEx locker(Compilation_lock, Mutex::_no_safepoint_check_flag);
|
||||||
|
while (WhiteBox::compilation_locked) {
|
||||||
|
locker.wait(Mutex::_no_safepoint_check_flag);
|
||||||
|
}
|
||||||
|
}
|
||||||
comp->compile_method(&ci_env, target, osr_bci);
|
comp->compile_method(&ci_env, target, osr_bci);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,8 @@
|
||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
|
||||||
#include "code/codeCache.hpp"
|
#include "code/codeCache.hpp"
|
||||||
#include "memory/metadataFactory.hpp"
|
#include "memory/metadataFactory.hpp"
|
||||||
#include "memory/universe.hpp"
|
#include "memory/universe.hpp"
|
||||||
|
@ -37,9 +39,11 @@
|
||||||
|
|
||||||
#include "runtime/thread.hpp"
|
#include "runtime/thread.hpp"
|
||||||
#include "runtime/arguments.hpp"
|
#include "runtime/arguments.hpp"
|
||||||
|
#include "runtime/deoptimization.hpp"
|
||||||
#include "runtime/interfaceSupport.hpp"
|
#include "runtime/interfaceSupport.hpp"
|
||||||
#include "runtime/os.hpp"
|
#include "runtime/os.hpp"
|
||||||
#include "runtime/vm_version.hpp"
|
#include "runtime/vm_version.hpp"
|
||||||
|
#include "runtime/sweeper.hpp"
|
||||||
|
|
||||||
#include "utilities/array.hpp"
|
#include "utilities/array.hpp"
|
||||||
#include "utilities/debug.hpp"
|
#include "utilities/debug.hpp"
|
||||||
|
@ -67,6 +71,7 @@ PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
|
||||||
#define SIZE_T_MAX_VALUE ((size_t) -1)
|
#define SIZE_T_MAX_VALUE ((size_t) -1)
|
||||||
|
|
||||||
bool WhiteBox::_used = false;
|
bool WhiteBox::_used = false;
|
||||||
|
volatile bool WhiteBox::compilation_locked = false;
|
||||||
|
|
||||||
WB_ENTRY(jlong, WB_GetObjectAddress(JNIEnv* env, jobject o, jobject obj))
|
WB_ENTRY(jlong, WB_GetObjectAddress(JNIEnv* env, jobject o, jobject obj))
|
||||||
return (jlong)(void*)JNIHandles::resolve(obj);
|
return (jlong)(void*)JNIHandles::resolve(obj);
|
||||||
|
@ -302,13 +307,12 @@ WB_END
|
||||||
WB_ENTRY(jlong, WB_NMTReserveMemory(JNIEnv* env, jobject o, jlong size))
|
WB_ENTRY(jlong, WB_NMTReserveMemory(JNIEnv* env, jobject o, jlong size))
|
||||||
jlong addr = 0;
|
jlong addr = 0;
|
||||||
|
|
||||||
addr = (jlong)(uintptr_t)os::reserve_memory(size);
|
addr = (jlong)(uintptr_t)os::reserve_memory(size);
|
||||||
MemTracker::record_virtual_memory_type((address)addr, mtTest);
|
MemTracker::record_virtual_memory_type((address)addr, mtTest);
|
||||||
|
|
||||||
return addr;
|
return addr;
|
||||||
WB_END
|
WB_END
|
||||||
|
|
||||||
|
|
||||||
WB_ENTRY(void, WB_NMTCommitMemory(JNIEnv* env, jobject o, jlong addr, jlong size))
|
WB_ENTRY(void, WB_NMTCommitMemory(JNIEnv* env, jobject o, jlong addr, jlong size))
|
||||||
os::commit_memory((char *)(uintptr_t)addr, size, !ExecMem);
|
os::commit_memory((char *)(uintptr_t)addr, size, !ExecMem);
|
||||||
MemTracker::record_virtual_memory_type((address)(uintptr_t)addr, mtTest);
|
MemTracker::record_virtual_memory_type((address)(uintptr_t)addr, mtTest);
|
||||||
|
@ -728,6 +732,29 @@ WB_ENTRY(void, WB_SetStringVMFlag(JNIEnv* env, jobject o, jstring name, jstring
|
||||||
WB_END
|
WB_END
|
||||||
|
|
||||||
|
|
||||||
|
WB_ENTRY(void, WB_LockCompilation(JNIEnv* env, jobject o, jlong timeout))
|
||||||
|
WhiteBox::compilation_locked = true;
|
||||||
|
WB_END
|
||||||
|
|
||||||
|
WB_ENTRY(void, WB_UnlockCompilation(JNIEnv* env, jobject o))
|
||||||
|
MonitorLockerEx mo(Compilation_lock, Mutex::_no_safepoint_check_flag);
|
||||||
|
WhiteBox::compilation_locked = false;
|
||||||
|
mo.notify_all();
|
||||||
|
WB_END
|
||||||
|
|
||||||
|
void WhiteBox::force_sweep() {
|
||||||
|
guarantee(WhiteBoxAPI, "internal testing API :: WhiteBox has to enabled");
|
||||||
|
{
|
||||||
|
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
|
||||||
|
NMethodSweeper::_should_sweep = true;
|
||||||
|
}
|
||||||
|
NMethodSweeper::possibly_sweep();
|
||||||
|
}
|
||||||
|
|
||||||
|
WB_ENTRY(void, WB_ForceNMethodSweep(JNIEnv* env, jobject o))
|
||||||
|
WhiteBox::force_sweep();
|
||||||
|
WB_END
|
||||||
|
|
||||||
WB_ENTRY(jboolean, WB_IsInStringTable(JNIEnv* env, jobject o, jstring javaString))
|
WB_ENTRY(jboolean, WB_IsInStringTable(JNIEnv* env, jobject o, jstring javaString))
|
||||||
ResourceMark rm(THREAD);
|
ResourceMark rm(THREAD);
|
||||||
int len;
|
int len;
|
||||||
|
@ -774,6 +801,46 @@ WB_ENTRY(jstring, WB_GetCPUFeatures(JNIEnv* env, jobject o))
|
||||||
return features_string;
|
return features_string;
|
||||||
WB_END
|
WB_END
|
||||||
|
|
||||||
|
int WhiteBox::get_blob_type(const CodeBlob* code) {
|
||||||
|
guarantee(WhiteBoxAPI, "internal testing API :: WhiteBox has to enabled");
|
||||||
|
return CodeCache::get_code_heap(code)->code_blob_type();
|
||||||
|
}
|
||||||
|
|
||||||
|
CodeHeap* WhiteBox::get_code_heap(int blob_type) {
|
||||||
|
guarantee(WhiteBoxAPI, "internal testing API :: WhiteBox has to enabled");
|
||||||
|
return CodeCache::get_code_heap(blob_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct CodeBlobStub {
|
||||||
|
CodeBlobStub(const CodeBlob* blob) :
|
||||||
|
name(os::strdup(blob->name())),
|
||||||
|
size(blob->size()),
|
||||||
|
blob_type(WhiteBox::get_blob_type(blob)) { }
|
||||||
|
~CodeBlobStub() { os::free((void*) name); }
|
||||||
|
const char* const name;
|
||||||
|
const int size;
|
||||||
|
const int blob_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
static jobjectArray codeBlob2objectArray(JavaThread* thread, JNIEnv* env, CodeBlobStub* cb) {
|
||||||
|
jclass clazz = env->FindClass(vmSymbols::java_lang_Object()->as_C_string());
|
||||||
|
CHECK_JNI_EXCEPTION_(env, NULL);
|
||||||
|
jobjectArray result = env->NewObjectArray(3, clazz, NULL);
|
||||||
|
|
||||||
|
jstring name = env->NewStringUTF(cb->name);
|
||||||
|
CHECK_JNI_EXCEPTION_(env, NULL);
|
||||||
|
env->SetObjectArrayElement(result, 0, name);
|
||||||
|
|
||||||
|
jobject obj = integerBox(thread, env, cb->size);
|
||||||
|
CHECK_JNI_EXCEPTION_(env, NULL);
|
||||||
|
env->SetObjectArrayElement(result, 1, obj);
|
||||||
|
|
||||||
|
obj = integerBox(thread, env, cb->blob_type);
|
||||||
|
CHECK_JNI_EXCEPTION_(env, NULL);
|
||||||
|
env->SetObjectArrayElement(result, 2, obj);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
WB_ENTRY(jobjectArray, WB_GetNMethod(JNIEnv* env, jobject o, jobject method, jboolean is_osr))
|
WB_ENTRY(jobjectArray, WB_GetNMethod(JNIEnv* env, jobject o, jobject method, jboolean is_osr))
|
||||||
ResourceMark rm(THREAD);
|
ResourceMark rm(THREAD);
|
||||||
|
@ -790,27 +857,93 @@ WB_ENTRY(jobjectArray, WB_GetNMethod(JNIEnv* env, jobject o, jobject method, jbo
|
||||||
ThreadToNativeFromVM ttn(thread);
|
ThreadToNativeFromVM ttn(thread);
|
||||||
jclass clazz = env->FindClass(vmSymbols::java_lang_Object()->as_C_string());
|
jclass clazz = env->FindClass(vmSymbols::java_lang_Object()->as_C_string());
|
||||||
CHECK_JNI_EXCEPTION_(env, NULL);
|
CHECK_JNI_EXCEPTION_(env, NULL);
|
||||||
result = env->NewObjectArray(3, clazz, NULL);
|
result = env->NewObjectArray(4, clazz, NULL);
|
||||||
if (result == NULL) {
|
if (result == NULL) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CodeBlobStub stub(code);
|
||||||
|
jobjectArray codeBlob = codeBlob2objectArray(thread, env, &stub);
|
||||||
|
env->SetObjectArrayElement(result, 0, codeBlob);
|
||||||
|
|
||||||
jobject level = integerBox(thread, env, code->comp_level());
|
jobject level = integerBox(thread, env, code->comp_level());
|
||||||
CHECK_JNI_EXCEPTION_(env, NULL);
|
CHECK_JNI_EXCEPTION_(env, NULL);
|
||||||
env->SetObjectArrayElement(result, 0, level);
|
env->SetObjectArrayElement(result, 1, level);
|
||||||
|
|
||||||
jbyteArray insts = env->NewByteArray(insts_size);
|
jbyteArray insts = env->NewByteArray(insts_size);
|
||||||
CHECK_JNI_EXCEPTION_(env, NULL);
|
CHECK_JNI_EXCEPTION_(env, NULL);
|
||||||
env->SetByteArrayRegion(insts, 0, insts_size, (jbyte*) code->insts_begin());
|
env->SetByteArrayRegion(insts, 0, insts_size, (jbyte*) code->insts_begin());
|
||||||
env->SetObjectArrayElement(result, 1, insts);
|
env->SetObjectArrayElement(result, 2, insts);
|
||||||
|
|
||||||
jobject id = integerBox(thread, env, code->compile_id());
|
jobject id = integerBox(thread, env, code->compile_id());
|
||||||
CHECK_JNI_EXCEPTION_(env, NULL);
|
CHECK_JNI_EXCEPTION_(env, NULL);
|
||||||
env->SetObjectArrayElement(result, 2, id);
|
env->SetObjectArrayElement(result, 3, id);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
WB_END
|
WB_END
|
||||||
|
|
||||||
|
CodeBlob* WhiteBox::allocate_code_blob(int size, int blob_type) {
|
||||||
|
guarantee(WhiteBoxAPI, "internal testing API :: WhiteBox has to enabled");
|
||||||
|
BufferBlob* blob;
|
||||||
|
int full_size = CodeBlob::align_code_offset(sizeof(BufferBlob));
|
||||||
|
if (full_size < size) {
|
||||||
|
full_size += round_to(size - full_size, oopSize);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
|
||||||
|
blob = (BufferBlob*) CodeCache::allocate(full_size, blob_type);
|
||||||
|
}
|
||||||
|
// Track memory usage statistic after releasing CodeCache_lock
|
||||||
|
MemoryService::track_code_cache_memory_usage();
|
||||||
|
::new (blob) BufferBlob("WB::DummyBlob", full_size);
|
||||||
|
return blob;
|
||||||
|
}
|
||||||
|
|
||||||
|
WB_ENTRY(jlong, WB_AllocateCodeBlob(JNIEnv* env, jobject o, jint size, jint blob_type))
|
||||||
|
return (jlong) WhiteBox::allocate_code_blob(size, blob_type);
|
||||||
|
WB_END
|
||||||
|
|
||||||
|
WB_ENTRY(void, WB_FreeCodeBlob(JNIEnv* env, jobject o, jlong addr))
|
||||||
|
BufferBlob::free((BufferBlob*) addr);
|
||||||
|
WB_END
|
||||||
|
|
||||||
|
WB_ENTRY(jobjectArray, WB_GetCodeHeapEntries(JNIEnv* env, jobject o, jint blob_type))
|
||||||
|
ResourceMark rm;
|
||||||
|
GrowableArray<CodeBlobStub*> blobs;
|
||||||
|
{
|
||||||
|
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
|
||||||
|
CodeHeap* heap = WhiteBox::get_code_heap(blob_type);
|
||||||
|
if (heap == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
for (CodeBlob* cb = (CodeBlob*) heap->first();
|
||||||
|
cb != NULL; cb = (CodeBlob*) heap->next(cb)) {
|
||||||
|
CodeBlobStub* stub = NEW_RESOURCE_OBJ(CodeBlobStub);
|
||||||
|
new (stub) CodeBlobStub(cb);
|
||||||
|
blobs.append(stub);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (blobs.length() == 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
ThreadToNativeFromVM ttn(thread);
|
||||||
|
jobjectArray result = NULL;
|
||||||
|
jclass clazz = env->FindClass(vmSymbols::java_lang_Object()->as_C_string());
|
||||||
|
CHECK_JNI_EXCEPTION_(env, NULL);
|
||||||
|
result = env->NewObjectArray(blobs.length(), clazz, NULL);
|
||||||
|
if (result == NULL) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
int i = 0;
|
||||||
|
for (GrowableArrayIterator<CodeBlobStub*> it = blobs.begin();
|
||||||
|
it != blobs.end(); ++it) {
|
||||||
|
jobjectArray obj = codeBlob2objectArray(thread, env, *it);
|
||||||
|
env->SetObjectArrayElement(result, i, obj);
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
WB_END
|
||||||
|
|
||||||
WB_ENTRY(jlong, WB_GetThreadStackSize(JNIEnv* env, jobject o))
|
WB_ENTRY(jlong, WB_GetThreadStackSize(JNIEnv* env, jobject o))
|
||||||
return (jlong) Thread::current()->stack_size();
|
return (jlong) Thread::current()->stack_size();
|
||||||
WB_END
|
WB_END
|
||||||
|
@ -1018,6 +1151,8 @@ static JNINativeMethod methods[] = {
|
||||||
CC"(Ljava/lang/reflect/Executable;II)Z", (void*)&WB_EnqueueMethodForCompilation},
|
CC"(Ljava/lang/reflect/Executable;II)Z", (void*)&WB_EnqueueMethodForCompilation},
|
||||||
{CC"clearMethodState",
|
{CC"clearMethodState",
|
||||||
CC"(Ljava/lang/reflect/Executable;)V", (void*)&WB_ClearMethodState},
|
CC"(Ljava/lang/reflect/Executable;)V", (void*)&WB_ClearMethodState},
|
||||||
|
{CC"lockCompilation", CC"()V", (void*)&WB_LockCompilation},
|
||||||
|
{CC"unlockCompilation", CC"()V", (void*)&WB_UnlockCompilation},
|
||||||
{CC"isConstantVMFlag", CC"(Ljava/lang/String;)Z", (void*)&WB_IsConstantVMFlag},
|
{CC"isConstantVMFlag", CC"(Ljava/lang/String;)Z", (void*)&WB_IsConstantVMFlag},
|
||||||
{CC"isLockedVMFlag", CC"(Ljava/lang/String;)Z", (void*)&WB_IsLockedVMFlag},
|
{CC"isLockedVMFlag", CC"(Ljava/lang/String;)Z", (void*)&WB_IsLockedVMFlag},
|
||||||
{CC"setBooleanVMFlag", CC"(Ljava/lang/String;Z)V",(void*)&WB_SetBooleanVMFlag},
|
{CC"setBooleanVMFlag", CC"(Ljava/lang/String;Z)V",(void*)&WB_SetBooleanVMFlag},
|
||||||
|
@ -1055,6 +1190,10 @@ static JNINativeMethod methods[] = {
|
||||||
{CC"getCPUFeatures", CC"()Ljava/lang/String;", (void*)&WB_GetCPUFeatures },
|
{CC"getCPUFeatures", CC"()Ljava/lang/String;", (void*)&WB_GetCPUFeatures },
|
||||||
{CC"getNMethod", CC"(Ljava/lang/reflect/Executable;Z)[Ljava/lang/Object;",
|
{CC"getNMethod", CC"(Ljava/lang/reflect/Executable;Z)[Ljava/lang/Object;",
|
||||||
(void*)&WB_GetNMethod },
|
(void*)&WB_GetNMethod },
|
||||||
|
{CC"forceNMethodSweep", CC"()V", (void*)&WB_ForceNMethodSweep },
|
||||||
|
{CC"allocateCodeBlob", CC"(II)J", (void*)&WB_AllocateCodeBlob },
|
||||||
|
{CC"freeCodeBlob", CC"(J)V", (void*)&WB_FreeCodeBlob },
|
||||||
|
{CC"getCodeHeapEntries", CC"(I)[Ljava/lang/Object;",(void*)&WB_GetCodeHeapEntries },
|
||||||
{CC"getThreadStackSize", CC"()J", (void*)&WB_GetThreadStackSize },
|
{CC"getThreadStackSize", CC"()J", (void*)&WB_GetThreadStackSize },
|
||||||
{CC"getThreadRemainingStackSize", CC"()J", (void*)&WB_GetThreadRemainingStackSize },
|
{CC"getThreadRemainingStackSize", CC"()J", (void*)&WB_GetThreadRemainingStackSize },
|
||||||
};
|
};
|
||||||
|
|
|
@ -54,17 +54,24 @@
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
class CodeBlob;
|
||||||
|
class CodeHeap;
|
||||||
|
|
||||||
class WhiteBox : public AllStatic {
|
class WhiteBox : public AllStatic {
|
||||||
private:
|
private:
|
||||||
static bool _used;
|
static bool _used;
|
||||||
public:
|
public:
|
||||||
|
static volatile bool compilation_locked;
|
||||||
static bool used() { return _used; }
|
static bool used() { return _used; }
|
||||||
static void set_used() { _used = true; }
|
static void set_used() { _used = true; }
|
||||||
static int offset_for_field(const char* field_name, oop object,
|
static int offset_for_field(const char* field_name, oop object,
|
||||||
Symbol* signature_symbol);
|
Symbol* signature_symbol);
|
||||||
static const char* lookup_jstring(const char* field_name, oop object);
|
static const char* lookup_jstring(const char* field_name, oop object);
|
||||||
static bool lookup_bool(const char* field_name, oop object);
|
static bool lookup_bool(const char* field_name, oop object);
|
||||||
|
static void force_sweep();
|
||||||
|
static int get_blob_type(const CodeBlob* code);
|
||||||
|
static CodeHeap* get_code_heap(int blob_type);
|
||||||
|
static CodeBlob* allocate_code_blob(int blob_type, int size);
|
||||||
static int array_bytes_to_length(size_t bytes);
|
static int array_bytes_to_length(size_t bytes);
|
||||||
static void register_methods(JNIEnv* env, jclass wbclass, JavaThread* thread,
|
static void register_methods(JNIEnv* env, jclass wbclass, JavaThread* thread,
|
||||||
JNINativeMethod* method_array, int method_count);
|
JNINativeMethod* method_array, int method_count);
|
||||||
|
|
|
@ -88,6 +88,7 @@ Mutex* DerivedPointerTableGC_lock = NULL;
|
||||||
Mutex* Compile_lock = NULL;
|
Mutex* Compile_lock = NULL;
|
||||||
Monitor* MethodCompileQueue_lock = NULL;
|
Monitor* MethodCompileQueue_lock = NULL;
|
||||||
Monitor* CompileThread_lock = NULL;
|
Monitor* CompileThread_lock = NULL;
|
||||||
|
Monitor* Compilation_lock = NULL;
|
||||||
Mutex* CompileTaskAlloc_lock = NULL;
|
Mutex* CompileTaskAlloc_lock = NULL;
|
||||||
Mutex* CompileStatistics_lock = NULL;
|
Mutex* CompileStatistics_lock = NULL;
|
||||||
Mutex* MultiArray_lock = NULL;
|
Mutex* MultiArray_lock = NULL;
|
||||||
|
@ -278,7 +279,9 @@ void mutex_init() {
|
||||||
def(ProfileVM_lock , Monitor, special, false); // used for profiling of the VMThread
|
def(ProfileVM_lock , Monitor, special, false); // used for profiling of the VMThread
|
||||||
def(CompileThread_lock , Monitor, nonleaf+5, false );
|
def(CompileThread_lock , Monitor, nonleaf+5, false );
|
||||||
def(PeriodicTask_lock , Monitor, nonleaf+5, true);
|
def(PeriodicTask_lock , Monitor, nonleaf+5, true);
|
||||||
|
if (WhiteBoxAPI) {
|
||||||
|
def(Compilation_lock , Monitor, leaf, false );
|
||||||
|
}
|
||||||
#ifdef INCLUDE_TRACE
|
#ifdef INCLUDE_TRACE
|
||||||
def(JfrMsg_lock , Monitor, leaf, true);
|
def(JfrMsg_lock , Monitor, leaf, true);
|
||||||
def(JfrBuffer_lock , Mutex, leaf, true);
|
def(JfrBuffer_lock , Mutex, leaf, true);
|
||||||
|
|
|
@ -91,6 +91,7 @@ extern Mutex* EvacFailureStack_lock; // guards the evac failure scan
|
||||||
extern Mutex* Compile_lock; // a lock held when Compilation is updating code (used to block CodeCache traversal, CHA updates, etc)
|
extern Mutex* Compile_lock; // a lock held when Compilation is updating code (used to block CodeCache traversal, CHA updates, etc)
|
||||||
extern Monitor* MethodCompileQueue_lock; // a lock held when method compilations are enqueued, dequeued
|
extern Monitor* MethodCompileQueue_lock; // a lock held when method compilations are enqueued, dequeued
|
||||||
extern Monitor* CompileThread_lock; // a lock held by compile threads during compilation system initialization
|
extern Monitor* CompileThread_lock; // a lock held by compile threads during compilation system initialization
|
||||||
|
extern Monitor* Compilation_lock; // a lock used to pause compilation
|
||||||
extern Mutex* CompileTaskAlloc_lock; // a lock held when CompileTasks are allocated
|
extern Mutex* CompileTaskAlloc_lock; // a lock held when CompileTasks are allocated
|
||||||
extern Mutex* CompileStatistics_lock; // a lock held when updating compilation statistics
|
extern Mutex* CompileStatistics_lock; // a lock held when updating compilation statistics
|
||||||
extern Mutex* MultiArray_lock; // a lock used to guard allocation of multi-dim arrays
|
extern Mutex* MultiArray_lock; // a lock used to guard allocation of multi-dim arrays
|
||||||
|
|
|
@ -25,6 +25,8 @@
|
||||||
#ifndef SHARE_VM_RUNTIME_SWEEPER_HPP
|
#ifndef SHARE_VM_RUNTIME_SWEEPER_HPP
|
||||||
#define SHARE_VM_RUNTIME_SWEEPER_HPP
|
#define SHARE_VM_RUNTIME_SWEEPER_HPP
|
||||||
|
|
||||||
|
class WhiteBox;
|
||||||
|
|
||||||
#include "utilities/ticks.hpp"
|
#include "utilities/ticks.hpp"
|
||||||
// An NmethodSweeper is an incremental cleaner for:
|
// An NmethodSweeper is an incremental cleaner for:
|
||||||
// - cleanup inline caches
|
// - cleanup inline caches
|
||||||
|
@ -52,6 +54,8 @@
|
||||||
// nmethod's space is freed.
|
// nmethod's space is freed.
|
||||||
|
|
||||||
class NMethodSweeper : public AllStatic {
|
class NMethodSweeper : public AllStatic {
|
||||||
|
friend class WhiteBox;
|
||||||
|
private:
|
||||||
static long _traversals; // Stack scan count, also sweep ID.
|
static long _traversals; // Stack scan count, also sweep ID.
|
||||||
static long _total_nof_code_cache_sweeps; // Total number of full sweeps of the code cache
|
static long _total_nof_code_cache_sweeps; // Total number of full sweeps of the code cache
|
||||||
static long _time_counter; // Virtual time used to periodically invoke sweeper
|
static long _time_counter; // Virtual time used to periodically invoke sweeper
|
||||||
|
@ -88,7 +92,6 @@ class NMethodSweeper : public AllStatic {
|
||||||
static void handle_safepoint_request();
|
static void handle_safepoint_request();
|
||||||
static void do_stack_scanning();
|
static void do_stack_scanning();
|
||||||
static void possibly_sweep();
|
static void possibly_sweep();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static long traversal_count() { return _traversals; }
|
static long traversal_count() { return _traversals; }
|
||||||
static int total_nof_methods_reclaimed() { return _total_nof_methods_reclaimed; }
|
static int total_nof_methods_reclaimed() { return _total_nof_methods_reclaimed; }
|
||||||
|
|
128
hotspot/test/compiler/whitebox/AllocationCodeBlobTest.java
Normal file
128
hotspot/test/compiler/whitebox/AllocationCodeBlobTest.java
Normal file
|
@ -0,0 +1,128 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.lang.management.MemoryPoolMXBean;
|
||||||
|
import java.util.EnumSet;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import sun.hotspot.WhiteBox;
|
||||||
|
import sun.hotspot.code.BlobType;
|
||||||
|
import com.oracle.java.testlibrary.Asserts;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test AllocationCodeBlobTest
|
||||||
|
* @bug 8059624
|
||||||
|
* @library /testlibrary /testlibrary/whitebox
|
||||||
|
* @build AllocationCodeBlobTest
|
||||||
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
|
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
||||||
|
* -XX:+WhiteBoxAPI -XX:CompileCommand=compileonly,null::*
|
||||||
|
* -XX:-SegmentedCodeCache AllocationCodeBlobTest
|
||||||
|
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
||||||
|
* -XX:+WhiteBoxAPI -XX:CompileCommand=compileonly,null::*
|
||||||
|
* -XX:+SegmentedCodeCache AllocationCodeBlobTest
|
||||||
|
* @summary testing of WB::allocate/freeCodeBlob()
|
||||||
|
*/
|
||||||
|
public class AllocationCodeBlobTest {
|
||||||
|
private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
|
||||||
|
private static final long CODE_CACHE_SIZE
|
||||||
|
= WHITE_BOX.getUintxVMFlag("ReservedCodeCacheSize");
|
||||||
|
private static final int SIZE = 1;
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
// check that Sweeper handels dummy blobs correctly
|
||||||
|
new ForcedSweeper(500).start();
|
||||||
|
EnumSet<BlobType> blobTypes = BlobType.getAvailable();
|
||||||
|
for (BlobType type : blobTypes) {
|
||||||
|
new AllocationCodeBlobTest(type).test();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final BlobType type;
|
||||||
|
private final MemoryPoolMXBean bean;
|
||||||
|
private AllocationCodeBlobTest(BlobType type) {
|
||||||
|
this.type = type;
|
||||||
|
bean = type.getMemoryPool();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void test() {
|
||||||
|
System.out.printf("type %s%n", type);
|
||||||
|
long start = getUsage();
|
||||||
|
long addr = WHITE_BOX.allocateCodeBlob(SIZE, type.id);
|
||||||
|
Asserts.assertNE(0, addr, "allocation failed");
|
||||||
|
|
||||||
|
long firstAllocation = getUsage();
|
||||||
|
Asserts.assertLTE(start + SIZE, firstAllocation,
|
||||||
|
"allocation should increase memory usage: "
|
||||||
|
+ start + " + " + SIZE + " <= " + firstAllocation);
|
||||||
|
|
||||||
|
WHITE_BOX.freeCodeBlob(addr);
|
||||||
|
long firstFree = getUsage();
|
||||||
|
Asserts.assertLTE(firstFree, firstAllocation,
|
||||||
|
"free shouldn't increase memory usage: "
|
||||||
|
+ firstFree + " <= " + firstAllocation);
|
||||||
|
|
||||||
|
addr = WHITE_BOX.allocateCodeBlob(SIZE, type.id);
|
||||||
|
Asserts.assertNE(0, addr, "allocation failed");
|
||||||
|
|
||||||
|
long secondAllocation = getUsage();
|
||||||
|
Asserts.assertEQ(firstAllocation, secondAllocation);
|
||||||
|
|
||||||
|
WHITE_BOX.freeCodeBlob(addr);
|
||||||
|
System.out.println("allocating till possible...");
|
||||||
|
ArrayList<Long> blobs = new ArrayList<>();
|
||||||
|
int size = (int) (CODE_CACHE_SIZE >> 7);
|
||||||
|
while ((addr = WHITE_BOX.allocateCodeBlob(size, type.id)) != 0) {
|
||||||
|
blobs.add(addr);
|
||||||
|
}
|
||||||
|
for (Long blob : blobs) {
|
||||||
|
WHITE_BOX.freeCodeBlob(blob);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private long getUsage() {
|
||||||
|
return bean.getUsage().getUsed();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ForcedSweeper extends Thread {
|
||||||
|
private final int millis;
|
||||||
|
public ForcedSweeper(int millis) {
|
||||||
|
super("ForcedSweeper");
|
||||||
|
setDaemon(true);
|
||||||
|
this.millis = millis;
|
||||||
|
}
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
while (true) {
|
||||||
|
WHITE_BOX.forceNMethodSweep();
|
||||||
|
Thread.sleep(millis);
|
||||||
|
}
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
throw new Error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
95
hotspot/test/compiler/whitebox/GetCodeHeapEntriesTest.java
Normal file
95
hotspot/test/compiler/whitebox/GetCodeHeapEntriesTest.java
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.EnumSet;
|
||||||
|
|
||||||
|
import sun.hotspot.WhiteBox;
|
||||||
|
import sun.hotspot.code.CodeBlob;
|
||||||
|
import sun.hotspot.code.BlobType;
|
||||||
|
import com.oracle.java.testlibrary.Asserts;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test GetCodeHeapEntriesTest
|
||||||
|
* @bug 8059624
|
||||||
|
* @library /testlibrary /testlibrary/whitebox
|
||||||
|
* @build GetCodeHeapEntriesTest
|
||||||
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
|
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
||||||
|
* -XX:+WhiteBoxAPI -XX:-SegmentedCodeCache
|
||||||
|
* GetCodeHeapEntriesTest
|
||||||
|
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
||||||
|
* -XX:+WhiteBoxAPI -XX:+SegmentedCodeCache
|
||||||
|
* GetCodeHeapEntriesTest
|
||||||
|
* @summary testing of WB::getCodeHeapEntries()
|
||||||
|
*/
|
||||||
|
public class GetCodeHeapEntriesTest {
|
||||||
|
private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
|
||||||
|
private static final int SIZE = 1024;
|
||||||
|
private static final String DUMMY_NAME = "WB::DummyBlob";
|
||||||
|
private static EnumSet<BlobType> SEGMENTED_TYPES
|
||||||
|
= EnumSet.complementOf(EnumSet.of(BlobType.All));
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
EnumSet<BlobType> blobTypes = BlobType.getAvailable();
|
||||||
|
for (BlobType type : blobTypes) {
|
||||||
|
new GetCodeHeapEntriesTest(type).test();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final BlobType type;
|
||||||
|
private GetCodeHeapEntriesTest(BlobType type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void test() {
|
||||||
|
System.out.printf("type %s%n", type);
|
||||||
|
long addr = WHITE_BOX.allocateCodeBlob(SIZE, type.id);
|
||||||
|
Asserts.assertNE(0, addr, "allocation failed");
|
||||||
|
CodeBlob[] blobs = CodeBlob.getCodeBlobs(type);
|
||||||
|
Asserts.assertNotNull(blobs);
|
||||||
|
CodeBlob blob = Arrays.stream(blobs)
|
||||||
|
.filter(GetCodeHeapEntriesTest::filter)
|
||||||
|
.findAny()
|
||||||
|
.get();
|
||||||
|
Asserts.assertNotNull(blob);
|
||||||
|
Asserts.assertEQ(blob.code_blob_type, type);
|
||||||
|
Asserts.assertGTE(blob.size, SIZE);
|
||||||
|
|
||||||
|
WHITE_BOX.freeCodeBlob(addr);
|
||||||
|
blobs = CodeBlob.getCodeBlobs(type);
|
||||||
|
long count = Arrays.stream(blobs)
|
||||||
|
.filter(GetCodeHeapEntriesTest::filter)
|
||||||
|
.count();
|
||||||
|
Asserts.assertEQ(0L, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean filter(CodeBlob blob) {
|
||||||
|
if (blob == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return DUMMY_NAME.equals(blob.name);
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,7 +22,9 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import sun.hotspot.code.BlobType;
|
||||||
import sun.hotspot.code.NMethod;
|
import sun.hotspot.code.NMethod;
|
||||||
|
import com.oracle.java.testlibrary.Asserts;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @test GetNMethodTest
|
* @test GetNMethodTest
|
||||||
|
@ -52,21 +54,46 @@ public class GetNMethodTest extends CompilerWhiteBoxTest {
|
||||||
|
|
||||||
compile();
|
compile();
|
||||||
checkCompiled();
|
checkCompiled();
|
||||||
|
|
||||||
NMethod nmethod = NMethod.get(method, testCase.isOsr());
|
NMethod nmethod = NMethod.get(method, testCase.isOsr());
|
||||||
if (IS_VERBOSE) {
|
if (IS_VERBOSE) {
|
||||||
System.out.println("nmethod = " + nmethod);
|
System.out.println("nmethod = " + nmethod);
|
||||||
}
|
}
|
||||||
if (nmethod == null) {
|
Asserts.assertNotNull(nmethod,
|
||||||
throw new RuntimeException("nmethod of compiled method is null");
|
"nmethod of compiled method is null");
|
||||||
}
|
Asserts.assertNotNull(nmethod.insts,
|
||||||
if (nmethod.insts.length == 0) {
|
"nmethod.insts of compiled method is null");
|
||||||
throw new RuntimeException("compiled method's instructions is empty");
|
Asserts.assertGT(nmethod.insts.length, 0,
|
||||||
|
"compiled method's instructions is empty");
|
||||||
|
Asserts.assertNotNull(nmethod.code_blob_type, "blob type is null");
|
||||||
|
if (WHITE_BOX.getBooleanVMFlag("SegmentedCodeCache")) {
|
||||||
|
Asserts.assertNE(nmethod.code_blob_type, BlobType.All);
|
||||||
|
switch (nmethod.comp_level) {
|
||||||
|
case 1:
|
||||||
|
case 4:
|
||||||
|
checkBlockType(nmethod, BlobType.MethodNonProfiled);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
case 3:
|
||||||
|
checkBlockType(nmethod, BlobType.MethodNonProfiled);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Error("unexpected comp level " + nmethod);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Asserts.assertEQ(nmethod.code_blob_type, BlobType.All);
|
||||||
}
|
}
|
||||||
|
|
||||||
deoptimize();
|
deoptimize();
|
||||||
checkNotCompiled();
|
checkNotCompiled();
|
||||||
nmethod = NMethod.get(method, testCase.isOsr());
|
nmethod = NMethod.get(method, testCase.isOsr());
|
||||||
if (nmethod != null) {
|
Asserts.assertNull(nmethod,
|
||||||
throw new RuntimeException("nmethod of non-compiled method isn't null");
|
"nmethod of non-compiled method isn't null");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void checkBlockType(NMethod nmethod, BlobType expectedType) {
|
||||||
|
Asserts.assertEQ(nmethod.code_blob_type, expectedType,
|
||||||
|
String.format("blob_type[%s] for %d level isn't %s",
|
||||||
|
nmethod.code_blob_type, nmethod.comp_level, expectedType));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
91
hotspot/test/compiler/whitebox/LockCompilationTest.java
Normal file
91
hotspot/test/compiler/whitebox/LockCompilationTest.java
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test LockCompilationTest
|
||||||
|
* @bug 8059624
|
||||||
|
* @library /testlibrary /testlibrary/whitebox
|
||||||
|
* @build LockCompilationTest
|
||||||
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
|
* @run main/othervm/timeout=600 -Xbootclasspath/a:. -Xmixed -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:CompileCommand=compileonly,SimpleTestCase$Helper::* LockCompilationTest
|
||||||
|
* @summary testing of WB::lock/unlockCompilation()
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.util.concurrent.BrokenBarrierException;
|
||||||
|
import java.util.concurrent.CyclicBarrier;
|
||||||
|
|
||||||
|
import com.oracle.java.testlibrary.Asserts;
|
||||||
|
|
||||||
|
public class LockCompilationTest extends CompilerWhiteBoxTest {
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
CompilerWhiteBoxTest.main(LockCompilationTest::new, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
private LockCompilationTest(TestCase testCase) {
|
||||||
|
super(testCase);
|
||||||
|
// to prevent inlining of #method
|
||||||
|
WHITE_BOX.testSetDontInlineMethod(method, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void test() throws Exception {
|
||||||
|
checkNotCompiled();
|
||||||
|
|
||||||
|
System.out.println("locking compilation");
|
||||||
|
WHITE_BOX.lockCompilation();
|
||||||
|
|
||||||
|
try {
|
||||||
|
System.out.println("trying to compile");
|
||||||
|
compile();
|
||||||
|
// to check if it works correctly w/ safepoints
|
||||||
|
System.out.println("going to safepoint");
|
||||||
|
WHITE_BOX.fullGC();
|
||||||
|
waitBackgroundCompilation();
|
||||||
|
Asserts.assertTrue(
|
||||||
|
WHITE_BOX.isMethodQueuedForCompilation(method),
|
||||||
|
method + " must be in queue");
|
||||||
|
Asserts.assertFalse(
|
||||||
|
WHITE_BOX.isMethodCompiled(method, false),
|
||||||
|
method + " must be not compiled");
|
||||||
|
Asserts.assertEQ(
|
||||||
|
WHITE_BOX.getMethodCompilationLevel(method, false), 0,
|
||||||
|
method + " comp_level must be == 0");
|
||||||
|
Asserts.assertFalse(
|
||||||
|
WHITE_BOX.isMethodCompiled(method, true),
|
||||||
|
method + " must be not osr_compiled");
|
||||||
|
Asserts.assertEQ(
|
||||||
|
WHITE_BOX.getMethodCompilationLevel(method, true), 0,
|
||||||
|
method + " osr_comp_level must be == 0");
|
||||||
|
} finally {
|
||||||
|
System.out.println("unlocking compilation");
|
||||||
|
WHITE_BOX.unlockCompilation();
|
||||||
|
}
|
||||||
|
waitBackgroundCompilation();
|
||||||
|
Asserts.assertFalse(
|
||||||
|
WHITE_BOX.isMethodQueuedForCompilation(method),
|
||||||
|
method + " must not be in queue");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -143,8 +143,14 @@ public class WhiteBox {
|
||||||
}
|
}
|
||||||
public native boolean enqueueMethodForCompilation(Executable method, int compLevel, int entry_bci);
|
public native boolean enqueueMethodForCompilation(Executable method, int compLevel, int entry_bci);
|
||||||
public native void clearMethodState(Executable method);
|
public native void clearMethodState(Executable method);
|
||||||
|
public native void lockCompilation();
|
||||||
|
public native void unlockCompilation();
|
||||||
public native int getMethodEntryBci(Executable method);
|
public native int getMethodEntryBci(Executable method);
|
||||||
public native Object[] getNMethod(Executable method, boolean isOsr);
|
public native Object[] getNMethod(Executable method, boolean isOsr);
|
||||||
|
public native long allocateCodeBlob(int size, int type);
|
||||||
|
public native void freeCodeBlob(long addr);
|
||||||
|
public native void forceNMethodSweep();
|
||||||
|
public native Object[] getCodeHeapEntries(int type);
|
||||||
|
|
||||||
// Intered strings
|
// Intered strings
|
||||||
public native boolean isInStringTable(String str);
|
public native boolean isInStringTable(String str);
|
||||||
|
|
|
@ -0,0 +1,79 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package sun.hotspot.code;
|
||||||
|
|
||||||
|
import java.lang.management.ManagementFactory;
|
||||||
|
import java.lang.management.MemoryPoolMXBean;
|
||||||
|
import java.util.EnumSet;
|
||||||
|
|
||||||
|
import sun.hotspot.WhiteBox;
|
||||||
|
|
||||||
|
public enum BlobType {
|
||||||
|
// Execution level 1 and 4 (non-profiled) nmethods (including native nmethods)
|
||||||
|
MethodNonProfiled(0, "CodeHeap 'non-profiled nmethods'"),
|
||||||
|
// Execution level 2 and 3 (profiled) nmethods
|
||||||
|
MethodProfiled(1, "CodeHeap 'profiled nmethods'"),
|
||||||
|
// Non-nmethods like Buffers, Adapters and Runtime Stubs
|
||||||
|
NonNMethod(2, "CodeHeap 'non-nmethods'"),
|
||||||
|
// All types (No code cache segmentation)
|
||||||
|
All(3, "CodeCache");
|
||||||
|
|
||||||
|
public final int id;
|
||||||
|
private final String beanName;
|
||||||
|
|
||||||
|
private BlobType(int id, String beanName) {
|
||||||
|
this.id = id;
|
||||||
|
this.beanName = beanName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MemoryPoolMXBean getMemoryPool() {
|
||||||
|
for (MemoryPoolMXBean bean : ManagementFactory.getMemoryPoolMXBeans()) {
|
||||||
|
String name = bean.getName();
|
||||||
|
if (beanName.equals(name)) {
|
||||||
|
return bean;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
public static EnumSet<BlobType> getAvailable() {
|
||||||
|
WhiteBox whiteBox = WhiteBox.getWhiteBox();
|
||||||
|
if (!whiteBox.getBooleanVMFlag("SegmentedCodeCache")) {
|
||||||
|
// only All for non segmented world
|
||||||
|
return EnumSet.of(All);
|
||||||
|
}
|
||||||
|
if (System.getProperty("java.vm.info").startsWith("interpreted ")) {
|
||||||
|
// only NonNMethod for -Xint
|
||||||
|
return EnumSet.of(NonNMethod);
|
||||||
|
}
|
||||||
|
|
||||||
|
EnumSet<BlobType> result = EnumSet.complementOf(EnumSet.of(All));
|
||||||
|
if (!whiteBox.getBooleanVMFlag("TieredCompilation")
|
||||||
|
|| whiteBox.getIntxVMFlag("TieredStopAtLevel") <= 1) {
|
||||||
|
// there is no MethodProfiled in non tiered world or pure C1
|
||||||
|
result.remove(MethodProfiled);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package sun.hotspot.code;
|
||||||
|
|
||||||
|
import sun.hotspot.WhiteBox;
|
||||||
|
|
||||||
|
public class CodeBlob {
|
||||||
|
private static final WhiteBox WB = WhiteBox.getWhiteBox();
|
||||||
|
public static CodeBlob[] getCodeBlobs(BlobType type) {
|
||||||
|
Object[] obj = WB.getCodeHeapEntries(type.id);
|
||||||
|
if (obj == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
CodeBlob[] result = new CodeBlob[obj.length];
|
||||||
|
for (int i = 0, n = result.length; i < n; ++i) {
|
||||||
|
result[i] = new CodeBlob((Object[]) obj[i]);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
protected CodeBlob(Object[] obj) {
|
||||||
|
assert obj.length == 3;
|
||||||
|
name = (String) obj[0];
|
||||||
|
size = (Integer) obj[1];
|
||||||
|
code_blob_type = BlobType.values()[(Integer) obj[2]];
|
||||||
|
assert code_blob_type.id == (Integer) obj[2];
|
||||||
|
}
|
||||||
|
public final String name;
|
||||||
|
public final int size;
|
||||||
|
public final BlobType code_blob_type;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "CodeBlob{"
|
||||||
|
+ "name=" + name
|
||||||
|
+ ", size=" + size
|
||||||
|
+ ", code_blob_type=" + code_blob_type
|
||||||
|
+ '}';
|
||||||
|
}
|
||||||
|
}
|
|
@ -27,28 +27,30 @@ package sun.hotspot.code;
|
||||||
import java.lang.reflect.Executable;
|
import java.lang.reflect.Executable;
|
||||||
import sun.hotspot.WhiteBox;
|
import sun.hotspot.WhiteBox;
|
||||||
|
|
||||||
public class NMethod {
|
public class NMethod extends CodeBlob {
|
||||||
private static final WhiteBox wb = WhiteBox.getWhiteBox();
|
private static final WhiteBox wb = WhiteBox.getWhiteBox();
|
||||||
public static NMethod get(Executable method, boolean isOsr) {
|
public static NMethod get(Executable method, boolean isOsr) {
|
||||||
Object[] obj = wb.getNMethod(method, isOsr);
|
Object[] obj = wb.getNMethod(method, isOsr);
|
||||||
return obj == null ? null : new NMethod(obj);
|
return obj == null ? null : new NMethod(obj);
|
||||||
}
|
}
|
||||||
private NMethod(Object[] obj) {
|
private NMethod(Object[] obj) {
|
||||||
assert obj.length == 3;
|
super((Object[])obj[0]);
|
||||||
comp_level = (Integer) obj[0];
|
assert obj.length == 4;
|
||||||
insts = (byte[]) obj[1];
|
comp_level = (Integer) obj[1];
|
||||||
compile_id = (Integer) obj[2];
|
insts = (byte[]) obj[2];
|
||||||
|
compile_id = (Integer) obj[3];
|
||||||
}
|
}
|
||||||
public byte[] insts;
|
public final byte[] insts;
|
||||||
public int comp_level;
|
public final int comp_level;
|
||||||
public int compile_id;
|
public final int compile_id;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "NMethod{" +
|
return "NMethod{"
|
||||||
"insts=" + insts +
|
+ super.toString()
|
||||||
", comp_level=" + comp_level +
|
+ ", insts=" + insts
|
||||||
", compile_id=" + compile_id +
|
+ ", comp_level=" + comp_level
|
||||||
'}';
|
+ ", compile_id=" + compile_id
|
||||||
|
+ '}';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue