--- old/src/share/vm/code/codeBlob.cpp 2019-08-12 15:02:48.672449365 +0800 +++ new/src/share/vm/code/codeBlob.cpp 2019-08-12 15:02:48.494454517 +0800 @@ -58,7 +58,7 @@ #include "c1/c1_Runtime1.hpp" #endif -unsigned int align_code_offset(int offset) { +unsigned int CodeBlob::align_code_offset(int offset) { // align the size to CodeEntryAlignment return ((offset + (int)CodeHeap::header_size() + (CodeEntryAlignment-1)) & ~(CodeEntryAlignment-1)) --- old/src/share/vm/code/codeBlob.hpp 2019-08-12 15:02:49.647421145 +0800 +++ new/src/share/vm/code/codeBlob.hpp 2019-08-12 15:02:49.480425979 +0800 @@ -30,6 +30,15 @@ #include "runtime/frame.hpp" #include "runtime/handles.hpp" +// CodeBlob Types +// Used in the CodeCache to assign CodeBlobs to different CodeHeaps +struct CodeBlobType { + enum { + All = 0, // All types (No code cache segmentation) + NumTypes = 1 // Number of CodeBlobTypes + }; +}; + // CodeBlob - superclass for all entries in the CodeCache. // // Suptypes are: @@ -71,6 +80,7 @@ public: // Returns the space needed for CodeBlob static unsigned int allocation_size(CodeBuffer* cb, int header_size); + static unsigned int align_code_offset(int offset); // Creation // a) simple CodeBlob @@ -205,6 +215,7 @@ friend class AdapterBlob; friend class VtableBlob; friend class MethodHandlesAdapterBlob; + friend class WhiteBox; private: // Creation support --- old/src/share/vm/code/codeCache.cpp 2019-08-12 15:02:50.560394720 +0800 +++ new/src/share/vm/code/codeCache.cpp 2019-08-12 15:02:50.395399495 +0800 @@ -189,6 +189,12 @@ if (cb != NULL) break; if (!_heap->expand_by(CodeCacheExpansionSize)) { // Expansion failed + if (CodeCache_lock->owned_by_self()) { + MutexUnlockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); + report_codemem_full(); + } else { + report_codemem_full(); + } return NULL; } if (PrintCodeCacheExtension) { @@ -758,6 +764,7 @@ _codemem_full_count++; EventCodeCacheFull event; if (event.should_commit()) { + event.set_codeBlobType((u1)CodeBlobType::All); event.set_startAddress((u8)low_bound()); event.set_commitedTopAddress((u8)high()); event.set_reservedTopAddress((u8)high_bound()); --- old/src/share/vm/jfr/recorder/checkpoint/types/jfrType.cpp 2019-08-12 15:02:51.476368208 +0800 +++ new/src/share/vm/jfr/recorder/checkpoint/types/jfrType.cpp 2019-08-12 15:02:51.312372954 +0800 @@ -279,13 +279,10 @@ } void CodeBlobTypeConstant::serialize(JfrCheckpointWriter& writer) { - // XXX no code blob types. need to send any stub value? -// static const u4 nof_entries = CodeBlobType::NumTypes; -// writer.write_count(nof_entries); -// for (u4 i = 0; i < nof_entries; ++i) { -// writer.write_key(i); -// writer.write(CodeCache::get_code_heap_name(i)); -// } + static const u4 nof_entries = CodeBlobType::NumTypes; + writer.write_count(nof_entries); + writer.write_key((u4)CodeBlobType::All); + writer.write("CodeCache"); }; void VMOperationTypeConstant::serialize(JfrCheckpointWriter& writer) { --- old/src/share/vm/prims/whitebox.cpp 2019-08-12 15:02:52.398341522 +0800 +++ new/src/share/vm/prims/whitebox.cpp 2019-08-12 15:02:52.226346500 +0800 @@ -39,6 +39,7 @@ #include "runtime/interfaceSupport.hpp" #include "runtime/os.hpp" #include "utilities/array.hpp" +#include "utilities/align.hpp" #include "utilities/debug.hpp" #include "utilities/macros.hpp" #include "utilities/exceptions.hpp" @@ -631,13 +632,13 @@ WB_END template -static bool GetVMFlag(JavaThread* thread, JNIEnv* env, jstring name, T* value, bool (*TAt)(const char*, T*)) { +static bool GetVMFlag(JavaThread* thread, JNIEnv* env, jstring name, T* value, bool (*TAt)(const char*, T*, bool, bool)) { if (name == NULL) { return false; } ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI const char* flag_name = env->GetStringUTFChars(name, NULL); - bool result = (*TAt)(flag_name, value); + bool result = (*TAt)(flag_name, value, true, true); env->ReleaseStringUTFChars(name, flag_name); return result; } @@ -829,6 +830,47 @@ return features_string; WB_END +int WhiteBox::get_blob_type(const CodeBlob* code) { + guarantee(WhiteBoxAPI, "internal testing API :: WhiteBox has to be enabled"); + return CodeBlobType::All;; +} + +struct CodeBlobStub { + CodeBlobStub(const CodeBlob* blob) : + name(os::strdup(blob->name())), + size(blob->size()), + blob_type(WhiteBox::get_blob_type(blob)), + address((jlong) blob) { } + ~CodeBlobStub() { os::free((void*) name); } + const char* const name; + const jint size; + const jint blob_type; + const jlong address; +}; + +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(4, 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); + + obj = longBox(thread, env, cb->address); + CHECK_JNI_EXCEPTION_(env, NULL); + env->SetObjectArrayElement(result, 3, obj); + + return result; +} WB_ENTRY(jobjectArray, WB_GetNMethod(JNIEnv* env, jobject o, jobject method, jboolean is_osr)) ResourceMark rm(THREAD); @@ -862,6 +904,47 @@ return result; WB_END +CodeBlob* WhiteBox::allocate_code_blob(int size, int blob_type) { + guarantee(WhiteBoxAPI, "internal testing API :: WhiteBox has to be enabled"); + BufferBlob* blob; + int full_size = CodeBlob::align_code_offset(sizeof(BufferBlob)); + if (full_size < size) { + full_size += align_up(size - full_size, oopSize); + } + { + MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); + blob = (BufferBlob*) CodeCache::allocate(full_size); + ::new (blob) BufferBlob("WB::DummyBlob", full_size); + } + // Track memory usage statistic after releasing CodeCache_lock + MemoryService::track_code_cache_memory_usage(); + return blob; +} + +WB_ENTRY(jlong, WB_AllocateCodeBlob(JNIEnv* env, jobject o, jint size, jint blob_type)) + if (size < 0) { + THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), + err_msg("WB_AllocateCodeBlob: size is negative: " INT32_FORMAT, size)); + } + return (jlong) WhiteBox::allocate_code_blob(size, blob_type); +WB_END + +WB_ENTRY(void, WB_FreeCodeBlob(JNIEnv* env, jobject o, jlong addr)) + if (addr == 0) { + return; + } + BufferBlob::free((BufferBlob*) addr); +WB_END + +WB_ENTRY(jobjectArray, WB_GetCodeBlob(JNIEnv* env, jobject o, jlong addr)) + if (addr == 0) { + THROW_MSG_NULL(vmSymbols::java_lang_NullPointerException(), + "WB_GetCodeBlob: addr is null"); + } + ThreadToNativeFromVM ttn(thread); + CodeBlobStub stub((CodeBlob*) addr); + return codeBlob2objectArray(thread, env, &stub); +WB_END int WhiteBox::array_bytes_to_length(size_t bytes) { return Array::bytes_to_length(bytes); @@ -1138,6 +1221,9 @@ {CC"fullGC", CC"()V", (void*)&WB_FullGC }, {CC"youngGC", CC"()V", (void*)&WB_YoungGC }, {CC"readReservedMemory", CC"()V", (void*)&WB_ReadReservedMemory }, + {CC"allocateCodeBlob", CC"(II)J", (void*)&WB_AllocateCodeBlob }, + {CC"freeCodeBlob", CC"(J)V", (void*)&WB_FreeCodeBlob }, + {CC"getCodeBlob", CC"(J)[Ljava/lang/Object;",(void*)&WB_GetCodeBlob }, {CC"allocateMetaspace", CC"(Ljava/lang/ClassLoader;J)J", (void*)&WB_AllocateMetaspace }, {CC"freeMetaspace", --- old/src/share/vm/prims/whitebox.hpp 2019-08-12 15:02:53.369313418 +0800 +++ new/src/share/vm/prims/whitebox.hpp 2019-08-12 15:02:53.199318338 +0800 @@ -64,7 +64,8 @@ Symbol* signature_symbol); static const char* lookup_jstring(const char* field_name, oop object); static bool lookup_bool(const char* field_name, oop object); - + static int get_blob_type(const CodeBlob* code); + static CodeBlob* allocate_code_blob(int size, int blob_type); static int array_bytes_to_length(size_t bytes); static void register_methods(JNIEnv* env, jclass wbclass, JavaThread* thread, JNINativeMethod* method_array, int method_count); --- old/src/share/vm/runtime/globals.cpp 2019-08-12 15:02:54.321285864 +0800 +++ new/src/share/vm/runtime/globals.cpp 2019-08-12 15:02:54.142291045 +0800 @@ -616,8 +616,8 @@ e.commit(); } -bool CommandLineFlags::boolAt(const char* name, size_t len, bool* value) { - Flag* result = Flag::find_flag(name, len); +bool CommandLineFlags::boolAt(const char* name, size_t len, bool* value, bool allow_locked, bool return_flag) { + Flag* result = Flag::find_flag(name, len, allow_locked, return_flag); if (result == NULL) return false; if (!result->is_bool()) return false; *value = result->get_bool(); @@ -644,8 +644,8 @@ faddr->set_origin(origin); } -bool CommandLineFlags::intxAt(const char* name, size_t len, intx* value) { - Flag* result = Flag::find_flag(name, len); +bool CommandLineFlags::intxAt(const char* name, size_t len, intx* value, bool allow_locked, bool return_flag) { + Flag* result = Flag::find_flag(name, len, allow_locked, return_flag); if (result == NULL) return false; if (!result->is_intx()) return false; *value = result->get_intx(); @@ -672,8 +672,8 @@ faddr->set_origin(origin); } -bool CommandLineFlags::uintxAt(const char* name, size_t len, uintx* value) { - Flag* result = Flag::find_flag(name, len); +bool CommandLineFlags::uintxAt(const char* name, size_t len, uintx* value, bool allow_locked, bool return_flag) { + Flag* result = Flag::find_flag(name, len, allow_locked, return_flag); if (result == NULL) return false; if (!result->is_uintx()) return false; *value = result->get_uintx(); @@ -700,8 +700,8 @@ faddr->set_origin(origin); } -bool CommandLineFlags::uint64_tAt(const char* name, size_t len, uint64_t* value) { - Flag* result = Flag::find_flag(name, len); +bool CommandLineFlags::uint64_tAt(const char* name, size_t len, uint64_t* value, bool allow_locked, bool return_flag) { + Flag* result = Flag::find_flag(name, len, allow_locked, return_flag); if (result == NULL) return false; if (!result->is_uint64_t()) return false; *value = result->get_uint64_t(); @@ -728,8 +728,8 @@ faddr->set_origin(origin); } -bool CommandLineFlags::doubleAt(const char* name, size_t len, double* value) { - Flag* result = Flag::find_flag(name, len); +bool CommandLineFlags::doubleAt(const char* name, size_t len, double* value, bool allow_locked, bool return_flag) { + Flag* result = Flag::find_flag(name, len, allow_locked, return_flag); if (result == NULL) return false; if (!result->is_double()) return false; *value = result->get_double(); @@ -756,8 +756,8 @@ faddr->set_origin(origin); } -bool CommandLineFlags::ccstrAt(const char* name, size_t len, ccstr* value) { - Flag* result = Flag::find_flag(name, len); +bool CommandLineFlags::ccstrAt(const char* name, size_t len, ccstr* value, bool allow_locked, bool return_flag) { + Flag* result = Flag::find_flag(name, len, allow_locked, return_flag); if (result == NULL) return false; if (!result->is_ccstr()) return false; *value = result->get_ccstr(); --- old/src/share/vm/runtime/globals.hpp 2019-08-12 15:02:55.496251855 +0800 +++ new/src/share/vm/runtime/globals.hpp 2019-08-12 15:02:55.315257094 +0800 @@ -369,33 +369,33 @@ class CommandLineFlags { public: - static bool boolAt(const char* name, size_t len, bool* value); - static bool boolAt(const char* name, bool* value) { return boolAt(name, strlen(name), value); } + static bool boolAt(const char* name, size_t len, bool* value, bool allow_locked = false, bool return_flag = false); + static bool boolAt(const char* name, bool* value, bool allow_locked = false, bool return_flag = false) { return boolAt(name, strlen(name), value, allow_locked, return_flag); } static bool boolAtPut(const char* name, size_t len, bool* value, Flag::Flags origin); static bool boolAtPut(const char* name, bool* value, Flag::Flags origin) { return boolAtPut(name, strlen(name), value, origin); } - static bool intxAt(const char* name, size_t len, intx* value); - static bool intxAt(const char* name, intx* value) { return intxAt(name, strlen(name), value); } + static bool intxAt(const char* name, size_t len, intx* value, bool allow_locked = false, bool return_flag = false); + static bool intxAt(const char* name, intx* value, bool allow_locked = false, bool return_flag = false) { return intxAt(name, strlen(name), value, allow_locked, return_flag); } static bool intxAtPut(const char* name, size_t len, intx* value, Flag::Flags origin); static bool intxAtPut(const char* name, intx* value, Flag::Flags origin) { return intxAtPut(name, strlen(name), value, origin); } - static bool uintxAt(const char* name, size_t len, uintx* value); - static bool uintxAt(const char* name, uintx* value) { return uintxAt(name, strlen(name), value); } + static bool uintxAt(const char* name, size_t len, uintx* value, bool allow_locked = false, bool return_flag = false); + static bool uintxAt(const char* name, uintx* value, bool allow_locked = false, bool return_flag = false) { return uintxAt(name, strlen(name), value, allow_locked, return_flag); } static bool uintxAtPut(const char* name, size_t len, uintx* value, Flag::Flags origin); static bool uintxAtPut(const char* name, uintx* value, Flag::Flags origin) { return uintxAtPut(name, strlen(name), value, origin); } - static bool uint64_tAt(const char* name, size_t len, uint64_t* value); - static bool uint64_tAt(const char* name, uint64_t* value) { return uint64_tAt(name, strlen(name), value); } + static bool uint64_tAt(const char* name, size_t len, uint64_t* value, bool allow_locked = false, bool return_flag = false); + static bool uint64_tAt(const char* name, uint64_t* value, bool allow_locked = false, bool return_flag = false) { return uint64_tAt(name, strlen(name), value, allow_locked, return_flag); } static bool uint64_tAtPut(const char* name, size_t len, uint64_t* value, Flag::Flags origin); static bool uint64_tAtPut(const char* name, uint64_t* value, Flag::Flags origin) { return uint64_tAtPut(name, strlen(name), value, origin); } - static bool doubleAt(const char* name, size_t len, double* value); - static bool doubleAt(const char* name, double* value) { return doubleAt(name, strlen(name), value); } + static bool doubleAt(const char* name, size_t len, double* value, bool allow_locked = false, bool return_flag = false); + static bool doubleAt(const char* name, double* value, bool allow_locked = false, bool return_flag = false) { return doubleAt(name, strlen(name), value, allow_locked, return_flag); } static bool doubleAtPut(const char* name, size_t len, double* value, Flag::Flags origin); static bool doubleAtPut(const char* name, double* value, Flag::Flags origin) { return doubleAtPut(name, strlen(name), value, origin); } - static bool ccstrAt(const char* name, size_t len, ccstr* value); - static bool ccstrAt(const char* name, ccstr* value) { return ccstrAt(name, strlen(name), value); } + static bool ccstrAt(const char* name, size_t len, ccstr* value, bool allow_locked = false, bool return_flag = false); + static bool ccstrAt(const char* name, ccstr* value, bool allow_locked = false, bool return_flag = false) { return ccstrAt(name, strlen(name), value, allow_locked, return_flag); } // Contract: Flag will make private copy of the incoming value. // Outgoing value is always malloc-ed, and caller MUST call free. static bool ccstrAtPut(const char* name, size_t len, ccstr* value, Flag::Flags origin);