--- a/hotspot/make/test/JtregNative.gmk Thu Jun 15 17:24:10 2017 +0000
+++ b/hotspot/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
--- a/hotspot/src/cpu/aarch64/vm/vtableStubs_aarch64.cpp Thu Jun 15 17:24:10 2017 +0000
+++ b/hotspot/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);
--- a/hotspot/src/share/vm/code/codeCache.cpp Thu Jun 15 17:24:10 2017 +0000
+++ b/hotspot/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<CodeHeap*> heap = _heaps->begin(); heap != _heaps->end(); ++heap)
#define FOR_ALL_NMETHOD_HEAPS(heap) for (GrowableArrayIterator<CodeHeap*> heap = _nmethod_heaps->begin(); heap != _nmethod_heaps->end(); ++heap)
+#define FOR_ALL_ALLOCABLE_HEAPS(heap) for (GrowableArrayIterator<CodeHeap*> 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<CodeHeap*>* CodeCache::_heaps = new(ResourceObj::C_HEAP, mtCode) GrowableArray<CodeHeap*> (CodeBlobType::All, true);
GrowableArray<CodeHeap*>* CodeCache::_compiled_heaps = new(ResourceObj::C_HEAP, mtCode) GrowableArray<CodeHeap*> (CodeBlobType::All, true);
GrowableArray<CodeHeap*>* CodeCache::_nmethod_heaps = new(ResourceObj::C_HEAP, mtCode) GrowableArray<CodeHeap*> (CodeBlobType::All, true);
+GrowableArray<CodeHeap*>* CodeCache::_allocable_heaps = new(ResourceObj::C_HEAP, mtCode) GrowableArray<CodeHeap*> (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<code_heap_compare>(heap);
}
+ if (code_blob_type_accepts_allocable(type)) {
+ _allocable_heaps->insert_sorted<code_heap_compare>(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++;
--- a/hotspot/src/share/vm/code/codeCache.hpp Thu Jun 15 17:24:10 2017 +0000
+++ b/hotspot/src/share/vm/code/codeCache.hpp Thu Jun 15 17:43:56 2017 +0000
@@ -85,6 +85,7 @@
static GrowableArray<CodeHeap*>* _heaps;
static GrowableArray<CodeHeap*>* _compiled_heaps;
static GrowableArray<CodeHeap*>* _nmethod_heaps;
+ static GrowableArray<CodeHeap*>* _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 ||
--- a/hotspot/src/share/vm/compiler/compileBroker.cpp Thu Jun 15 17:24:10 2017 +0000
+++ b/hotspot/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()) {
--- a/hotspot/test/serviceability/jvmti/GetNamedModule/MyPackage/GetNamedModuleTest.java Thu Jun 15 17:24:10 2017 +0000
+++ b/hotspot/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
*/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/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);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/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 <stdio.h>
+#include <string.h>
+#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