# HG changeset patch # User lana # Date 1497548636 0 # Node ID 232d93f11c49016675abd964d07903a86f211383 # Parent ca47dcfdd35129fe3ab2dab71b2601d7a0ff07c0# Parent 5e54f0bcf4efd7f7235d861bc9c8282d069d7d1a Merge diff -r ca47dcfdd351 -r 232d93f11c49 make/test/JtregNative.gmk --- a/make/test/JtregNative.gmk Thu Jun 15 17:24:10 2017 +0000 +++ b/make/test/JtregNative.gmk Thu Jun 15 17:43:56 2017 +0000 @@ -56,6 +56,7 @@ $(HOTSPOT_TOPDIR)/test/compiler/floatingpoint/ \ $(HOTSPOT_TOPDIR)/test/compiler/calls \ $(HOTSPOT_TOPDIR)/test/serviceability/jvmti/GetNamedModule \ + $(HOTSPOT_TOPDIR)/test/serviceability/jvmti/IsModifiableModule \ $(HOTSPOT_TOPDIR)/test/serviceability/jvmti/AddModuleReads \ $(HOTSPOT_TOPDIR)/test/serviceability/jvmti/AddModuleExportsAndOpens \ $(HOTSPOT_TOPDIR)/test/serviceability/jvmti/AddModuleUsesAndProvides \ @@ -85,6 +86,7 @@ BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_liboverflow := -lc BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libSimpleClassFileLoadHook := -lc BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libGetNamedModuleTest := -lc + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libIsModifiableModuleTest := -lc BUILD_HOTSPOT_JTREG_LIBRARIES_LDFLAGS_libAddModuleReadsTest := -lc BUILD_HOTSPOT_JTREG_LIBRARIES_LDFLAGS_libAddModuleExportsAndOpensTest := -lc BUILD_HOTSPOT_JTREG_LIBRARIES_LDFLAGS_libAddModuleUsesAndProvidesTest := -lc diff -r ca47dcfdd351 -r 232d93f11c49 src/cpu/aarch64/vm/vtableStubs_aarch64.cpp --- a/src/cpu/aarch64/vm/vtableStubs_aarch64.cpp Thu Jun 15 17:24:10 2017 +0000 +++ b/src/cpu/aarch64/vm/vtableStubs_aarch64.cpp Thu Jun 15 17:43:56 2017 +0000 @@ -51,6 +51,11 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) { const int aarch64_code_length = VtableStub::pd_code_size_limit(true); VtableStub* s = new(aarch64_code_length) VtableStub(true, vtable_index); + // Can be NULL if there is no free space in the code cache. + if (s == NULL) { + return NULL; + } + ResourceMark rm; CodeBuffer cb(s->entry_point(), aarch64_code_length); MacroAssembler* masm = new MacroAssembler(&cb); diff -r ca47dcfdd351 -r 232d93f11c49 src/share/vm/code/codeCache.cpp --- a/src/share/vm/code/codeCache.cpp Thu Jun 15 17:24:10 2017 +0000 +++ b/src/share/vm/code/codeCache.cpp Thu Jun 15 17:43:56 2017 +0000 @@ -130,6 +130,7 @@ // Iterate over all CodeHeaps #define FOR_ALL_HEAPS(heap) for (GrowableArrayIterator heap = _heaps->begin(); heap != _heaps->end(); ++heap) #define FOR_ALL_NMETHOD_HEAPS(heap) for (GrowableArrayIterator heap = _nmethod_heaps->begin(); heap != _nmethod_heaps->end(); ++heap) +#define FOR_ALL_ALLOCABLE_HEAPS(heap) for (GrowableArrayIterator heap = _allocable_heaps->begin(); heap != _allocable_heaps->end(); ++heap) // Iterate over all CodeBlobs (cb) on the given CodeHeap #define FOR_ALL_BLOBS(cb, heap) for (CodeBlob* cb = first_blob(heap); cb != NULL; cb = next_blob(heap, cb)) @@ -140,10 +141,11 @@ bool CodeCache::_needs_cache_clean = false; nmethod* CodeCache::_scavenge_root_nmethods = NULL; -// Initialize array of CodeHeaps +// Initialize arrays of CodeHeap subsets GrowableArray* CodeCache::_heaps = new(ResourceObj::C_HEAP, mtCode) GrowableArray (CodeBlobType::All, true); GrowableArray* CodeCache::_compiled_heaps = new(ResourceObj::C_HEAP, mtCode) GrowableArray (CodeBlobType::All, true); GrowableArray* CodeCache::_nmethod_heaps = new(ResourceObj::C_HEAP, mtCode) GrowableArray (CodeBlobType::All, true); +GrowableArray* CodeCache::_allocable_heaps = new(ResourceObj::C_HEAP, mtCode) GrowableArray (CodeBlobType::All, true); void CodeCache::check_heap_sizes(size_t non_nmethod_size, size_t profiled_size, size_t non_profiled_size, size_t cache_size, bool all_set) { size_t total_size = non_nmethod_size + profiled_size + non_profiled_size; @@ -338,6 +340,7 @@ return rs; } +// Heaps available for allocation bool CodeCache::heap_available(int code_blob_type) { if (!SegmentedCodeCache) { // No segmentation: use a single code heap @@ -391,6 +394,9 @@ if (code_blob_type_accepts_nmethod(type)) { _nmethod_heaps->insert_sorted(heap); } + if (code_blob_type_accepts_allocable(type)) { + _allocable_heaps->insert_sorted(heap); + } } void CodeCache::add_heap(ReservedSpace rs, const char* name, int code_blob_type) { @@ -620,7 +626,7 @@ void CodeCache::blobs_do(void f(CodeBlob* nm)) { assert_locked_or_safepoint(CodeCache_lock); - FOR_ALL_NMETHOD_HEAPS(heap) { + FOR_ALL_HEAPS(heap) { FOR_ALL_BLOBS(cb, *heap) { f(cb); } @@ -663,7 +669,7 @@ void CodeCache::blobs_do(CodeBlobClosure* f) { assert_locked_or_safepoint(CodeCache_lock); - FOR_ALL_NMETHOD_HEAPS(heap) { + FOR_ALL_ALLOCABLE_HEAPS(heap) { FOR_ALL_BLOBS(cb, *heap) { if (cb->is_alive()) { f->do_code_blob(cb); @@ -960,7 +966,7 @@ size_t CodeCache::capacity() { size_t cap = 0; - FOR_ALL_NMETHOD_HEAPS(heap) { + FOR_ALL_ALLOCABLE_HEAPS(heap) { cap += (*heap)->capacity(); } return cap; @@ -973,7 +979,7 @@ size_t CodeCache::unallocated_capacity() { size_t unallocated_cap = 0; - FOR_ALL_NMETHOD_HEAPS(heap) { + FOR_ALL_ALLOCABLE_HEAPS(heap) { unallocated_cap += (*heap)->unallocated_capacity(); } return unallocated_cap; @@ -981,7 +987,7 @@ size_t CodeCache::max_capacity() { size_t max_cap = 0; - FOR_ALL_NMETHOD_HEAPS(heap) { + FOR_ALL_ALLOCABLE_HEAPS(heap) { max_cap += (*heap)->max_capacity(); } return max_cap; @@ -1007,7 +1013,7 @@ size_t CodeCache::bytes_allocated_in_freelists() { size_t allocated_bytes = 0; - FOR_ALL_NMETHOD_HEAPS(heap) { + FOR_ALL_ALLOCABLE_HEAPS(heap) { allocated_bytes += (*heap)->allocated_in_freelist(); } return allocated_bytes; @@ -1015,7 +1021,7 @@ int CodeCache::allocated_segments() { int number_of_segments = 0; - FOR_ALL_NMETHOD_HEAPS(heap) { + FOR_ALL_ALLOCABLE_HEAPS(heap) { number_of_segments += (*heap)->allocated_segments(); } return number_of_segments; @@ -1023,7 +1029,7 @@ size_t CodeCache::freelists_length() { size_t length = 0; - FOR_ALL_NMETHOD_HEAPS(heap) { + FOR_ALL_ALLOCABLE_HEAPS(heap) { length += (*heap)->freelist_length(); } return length; @@ -1354,7 +1360,7 @@ void CodeCache::print_memory_overhead() { size_t wasted_bytes = 0; - FOR_ALL_NMETHOD_HEAPS(heap) { + FOR_ALL_ALLOCABLE_HEAPS(heap) { CodeHeap* curr_heap = *heap; for (CodeBlob* cb = (CodeBlob*)curr_heap->first(); cb != NULL; cb = (CodeBlob*)curr_heap->next(cb)) { HeapBlock* heap_block = ((HeapBlock*)cb) - 1; @@ -1400,7 +1406,7 @@ ResourceMark rm; int i = 0; - FOR_ALL_NMETHOD_HEAPS(heap) { + FOR_ALL_ALLOCABLE_HEAPS(heap) { if ((_nmethod_heaps->length() >= 1) && Verbose) { tty->print_cr("-- %s --", (*heap)->name()); } @@ -1497,7 +1503,7 @@ CodeBlob_sizes live; CodeBlob_sizes dead; - FOR_ALL_NMETHOD_HEAPS(heap) { + FOR_ALL_ALLOCABLE_HEAPS(heap) { FOR_ALL_BLOBS(cb, *heap) { if (!cb->is_alive()) { dead.add(cb); @@ -1523,7 +1529,7 @@ int number_of_blobs = 0; int number_of_oop_maps = 0; int map_size = 0; - FOR_ALL_NMETHOD_HEAPS(heap) { + FOR_ALL_ALLOCABLE_HEAPS(heap) { FOR_ALL_BLOBS(cb, *heap) { if (cb->is_alive()) { number_of_blobs++; diff -r ca47dcfdd351 -r 232d93f11c49 src/share/vm/code/codeCache.hpp --- a/src/share/vm/code/codeCache.hpp Thu Jun 15 17:24:10 2017 +0000 +++ b/src/share/vm/code/codeCache.hpp Thu Jun 15 17:43:56 2017 +0000 @@ -85,6 +85,7 @@ static GrowableArray* _heaps; static GrowableArray* _compiled_heaps; static GrowableArray* _nmethod_heaps; + static GrowableArray* _allocable_heaps; static address _low_bound; // Lower bound of CodeHeap addresses static address _high_bound; // Upper bound of CodeHeap addresses @@ -237,6 +238,11 @@ return type == CodeBlobType::All || type <= CodeBlobType::MethodProfiled; } + static bool code_blob_type_accepts_allocable(int type) { + return type <= CodeBlobType::All; + } + + // Returns the CodeBlobType for the given compilation level static int get_code_blob_type(int comp_level) { if (comp_level == CompLevel_none || diff -r ca47dcfdd351 -r 232d93f11c49 src/share/vm/compiler/compileBroker.cpp --- a/src/share/vm/compiler/compileBroker.cpp Thu Jun 15 17:24:10 2017 +0000 +++ b/src/share/vm/compiler/compileBroker.cpp Thu Jun 15 17:43:56 2017 +0000 @@ -1557,7 +1557,7 @@ // First thread to get here will initialize the compiler interface - if (!ciObjectFactory::is_initialized()) { + { ASSERT_IN_VM; MutexLocker only_one (CompileThread_lock, thread); if (!ciObjectFactory::is_initialized()) { diff -r ca47dcfdd351 -r 232d93f11c49 test/serviceability/jvmti/GetNamedModule/MyPackage/GetNamedModuleTest.java --- a/test/serviceability/jvmti/GetNamedModule/MyPackage/GetNamedModuleTest.java Thu Jun 15 17:24:10 2017 +0000 +++ b/test/serviceability/jvmti/GetNamedModule/MyPackage/GetNamedModuleTest.java Thu Jun 15 17:43:56 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, 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 @@ -26,6 +26,7 @@ /** * @test * @summary Verifies the JVMTI GetNamedModule API + * @modules jdk.jdi * @compile GetNamedModuleTest.java * @run main/othervm/native -agentlib:GetNamedModuleTest MyPackage.GetNamedModuleTest */ diff -r ca47dcfdd351 -r 232d93f11c49 test/serviceability/jvmti/IsModifiableModule/MyPackage/IsModifiableModuleTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/serviceability/jvmti/IsModifiableModule/MyPackage/IsModifiableModuleTest.java Thu Jun 15 17:43:56 2017 +0000 @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2017, 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 MyPackage; + +/** + * @test + * @summary Verifies the JVMTI IsModifiableModule API + * @modules jdk.jdi + * @compile IsModifiableModuleTest.java + * @run main/othervm/native -agentlib:IsModifiableModuleTest MyPackage.IsModifiableModuleTest + */ + +import java.io.PrintStream; + +public class IsModifiableModuleTest { + + static { + try { + System.loadLibrary("IsModifiableModuleTest"); + } catch (UnsatisfiedLinkError ule) { + System.err.println("Could not load IsModifiableModuleTest library"); + System.err.println("java.library.path: " + + System.getProperty("java.library.path")); + throw ule; + } + } + + native static int check(); + + public static void main(String args[]) { + int status = check(); + if (status != 0) { + throw new RuntimeException("Non-zero status returned from the agent: " + status); + } + } +} diff -r ca47dcfdd351 -r 232d93f11c49 test/serviceability/jvmti/IsModifiableModule/libIsModifiableModuleTest.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/serviceability/jvmti/IsModifiableModule/libIsModifiableModuleTest.c Thu Jun 15 17:43:56 2017 +0000 @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2017, 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. + */ + +#include +#include +#include "jvmti.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef JNI_ENV_ARG + +#ifdef __cplusplus +#define JNI_ENV_ARG(x, y) y +#define JNI_ENV_PTR(x) x +#else +#define JNI_ENV_ARG(x,y) x, y +#define JNI_ENV_PTR(x) (*x) +#endif + +#endif + +#define TranslateError(err) "JVMTI error" + +#define PASSED 0 +#define FAILED 2 + +static const char *EXC_CNAME = "java/lang/AssertionError"; + +static jvmtiEnv *jvmti = NULL; +static jint result = PASSED; +static jboolean printdump = JNI_FALSE; + +static jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved); + +JNIEXPORT +jint JNICALL Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) { + return Agent_Initialize(jvm, options, reserved); +} + +JNIEXPORT +jint JNICALL Agent_OnAttach(JavaVM *jvm, char *options, void *reserved) { + return Agent_Initialize(jvm, options, reserved); +} + +JNIEXPORT +jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) { + return JNI_VERSION_1_8; +} + +static +jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) { + jint res; + + if (options != NULL && strcmp(options, "printdump") == 0) { + printdump = JNI_TRUE; + } + + res = JNI_ENV_PTR(jvm)->GetEnv(JNI_ENV_ARG(jvm, (void **) &jvmti), + JVMTI_VERSION_9); + if (res != JNI_OK || jvmti == NULL) { + printf(" Error: wrong result of a valid call to GetEnv!\n"); + return JNI_ERR; + } + + return JNI_OK; +} + +static +jclass find_class(JNIEnv *env, const char* cname) { + jclass cls = JNI_ENV_PTR(env)->FindClass(JNI_ENV_ARG(env, cname)); + + if (cls == NULL) { + printf("find_class: Error: FindClass(env, \"%s\") returned NULL\n", cname); + } + return cls; +} + +static +jint throw_exc(JNIEnv *env, char *msg) { + jclass exc_class = find_class(env, EXC_CNAME); + + if (exc_class == NULL) { + printf("throw_exc: Error in find_class(env, \"%s\")\n", EXC_CNAME); + return -1; + } + return JNI_ENV_PTR(env)->ThrowNew(JNI_ENV_ARG(env, exc_class), msg); +} + +static jobject get_module_by_class_name(JNIEnv *env, const char* cname) { + jobject module = NULL; + jclass cls = find_class(env, cname); + + printf(">>> getting module by class name: \"%s\"\n", cname); + if (cls == NULL) { + printf("get_module_by_class_name: Error in find_class(env, \"%s\")\n", cname); + return NULL; + } + module = JNI_ENV_PTR(env)->GetModule(JNI_ENV_ARG(env, cls)); + if (module == NULL) { + printf("get_module_by_class_name: Error in GetModule for class \"%s\"\n", cname); + } + return module; +} + +static +jint check_is_modifiable_error_codes(jobject module, jobject not_a_module) { + jvmtiError err = JVMTI_ERROR_NONE; + jboolean is_modifiable = JNI_FALSE; + + printf(">>> passing a bad module argument to JVMTI IsModifiableModule\n"); + err = (*jvmti)->IsModifiableModule(jvmti, not_a_module, &is_modifiable); + if (err != JVMTI_ERROR_INVALID_MODULE) { + printf(" Error #EC0: Did not get expected INVALID_MODULE error code from" + " IsModifiableModule: %s (%d)\n", TranslateError(err), err); + return FAILED; + } + printf(">>> passing NULL module argument to JVMTI IsModifiableModule\n"); + err = (*jvmti)->IsModifiableModule(jvmti, NULL, &is_modifiable); + if (err != JVMTI_ERROR_NULL_POINTER) { + printf(" Error #EC1: Did not get expected NULL_POINTER error code from" + " IsModifiableModule: %s (%d)\n", TranslateError(err), err); + return FAILED; + } + printf(">>> passing NULL status pointer to JVMTI IsModifiableModule\n"); + err = (*jvmti)->IsModifiableModule(jvmti, module, NULL); + if (err != JVMTI_ERROR_NULL_POINTER) { + printf(" Error #EC2: Did not get expected NULL_POINTER error code from" + " IsModifiableModule: %s (%d)\n", TranslateError(err), err); + return FAILED; + } + return PASSED; +} + +static +jint check_is_modifiable(jobject module) { + jvmtiError err = JVMTI_ERROR_NONE; + jboolean is_modifiable = JNI_FALSE; + + printf(">>> checking module %p is modifiable\n", module); + err = (*jvmti)->IsModifiableModule(jvmti, module, &is_modifiable); + if (err != JVMTI_ERROR_NONE) { + printf(" Error in IsModifiableModule for module %p: %s (%d)\n", + module, TranslateError(err), err); + return FAILED; + } + if (is_modifiable == JNI_FALSE) { + printf(" unexpected non-modifiable status for module: %p\n", module); + return FAILED; + } + return PASSED; +} + +JNIEXPORT jint JNICALL +Java_MyPackage_IsModifiableModuleTest_check(JNIEnv *env, jclass cls) { + jobject module = NULL; + + if (jvmti == NULL) { + throw_exc(env, "JVMTI client was not properly loaded!\n"); + return FAILED; + } + + printf("\n*** Testing IsModifiableModule ***\n\n"); + + if (check_is_modifiable_error_codes(module, cls) == FAILED) { + throw_exc(env, "check #MM0: failed to return expected error code from " + "a bad call to JVMTI IsModifiableModule"); + return FAILED; + } + + module = get_module_by_class_name(env, "java/lang/Class"); + if (check_is_modifiable(module) == FAILED) { + throw_exc(env, "check #MM1: failed to return modifiable module status"); + return FAILED; + } + + module = get_module_by_class_name(env, "com/sun/jdi/VirtualMachine"); + if (check_is_modifiable(module) == FAILED) { + throw_exc(env, "check #MM2: failed to return modifiable module status"); + return FAILED; + } + + module = get_module_by_class_name(env, "MyPackage/IsModifiableModuleTest"); + if (check_is_modifiable(module) == FAILED) { + throw_exc(env, "check #MM3: failed to return modifiable module status"); + return FAILED; + } + + return PASSED; +} + +#ifdef __cplusplus +} +#endif