# HG changeset patch # User thartmann # Date 1415176502 0 # Node ID d4562805b0304240e47386dede429562f691cc60 # Parent 468850e35e481e7c7433be3d3b4c090bf3be702a# Parent 4cb90023bf2bd4fdef1d160868bbc1b734a67d28 Merge diff -r 468850e35e48 -r d4562805b030 make/bsd/makefiles/mapfile-vers-debug --- a/make/bsd/makefiles/mapfile-vers-debug Fri Oct 31 12:16:20 2014 +0100 +++ b/make/bsd/makefiles/mapfile-vers-debug Wed Nov 05 08:35:02 2014 +0000 @@ -187,6 +187,9 @@ _JVM_IsSupportedJNIVersion _JVM_IsThreadAlive _JVM_IsVMGeneratedMethodIx + _JVM_KnownToNotExist + _JVM_GetResourceLookupCacheURLs + _JVM_GetResourceLookupCache _JVM_LatestUserDefinedLoader _JVM_Listen _JVM_LoadClass0 diff -r 468850e35e48 -r d4562805b030 make/bsd/makefiles/mapfile-vers-product --- a/make/bsd/makefiles/mapfile-vers-product Fri Oct 31 12:16:20 2014 +0100 +++ b/make/bsd/makefiles/mapfile-vers-product Wed Nov 05 08:35:02 2014 +0000 @@ -187,6 +187,9 @@ _JVM_IsSupportedJNIVersion _JVM_IsThreadAlive _JVM_IsVMGeneratedMethodIx + _JVM_KnownToNotExist + _JVM_GetResourceLookupCacheURLs + _JVM_GetResourceLookupCache _JVM_LatestUserDefinedLoader _JVM_Listen _JVM_LoadClass0 diff -r 468850e35e48 -r d4562805b030 make/linux/makefiles/mapfile-vers-debug --- a/make/linux/makefiles/mapfile-vers-debug Fri Oct 31 12:16:20 2014 +0100 +++ b/make/linux/makefiles/mapfile-vers-debug Wed Nov 05 08:35:02 2014 +0000 @@ -217,6 +217,9 @@ JVM_RegisterSignal; JVM_ReleaseUTF; JVM_ResolveClass; + JVM_KnownToNotExist; + JVM_GetResourceLookupCacheURLs; + JVM_GetResourceLookupCache; JVM_ResumeThread; JVM_Send; JVM_SendTo; diff -r 468850e35e48 -r d4562805b030 make/linux/makefiles/mapfile-vers-product --- a/make/linux/makefiles/mapfile-vers-product Fri Oct 31 12:16:20 2014 +0100 +++ b/make/linux/makefiles/mapfile-vers-product Wed Nov 05 08:35:02 2014 +0000 @@ -217,6 +217,9 @@ JVM_RegisterSignal; JVM_ReleaseUTF; JVM_ResolveClass; + JVM_KnownToNotExist; + JVM_GetResourceLookupCacheURLs; + JVM_GetResourceLookupCache; JVM_ResumeThread; JVM_Send; JVM_SendTo; diff -r 468850e35e48 -r d4562805b030 make/solaris/makefiles/mapfile-vers --- a/make/solaris/makefiles/mapfile-vers Fri Oct 31 12:16:20 2014 +0100 +++ b/make/solaris/makefiles/mapfile-vers Wed Nov 05 08:35:02 2014 +0000 @@ -189,6 +189,9 @@ JVM_IsSupportedJNIVersion; JVM_IsThreadAlive; JVM_IsVMGeneratedMethodIx; + JVM_KnownToNotExist; + JVM_GetResourceLookupCacheURLs; + JVM_GetResourceLookupCache; JVM_LatestUserDefinedLoader; JVM_Listen; JVM_LoadClass0; diff -r 468850e35e48 -r d4562805b030 src/share/vm/classfile/classLoader.cpp --- a/src/share/vm/classfile/classLoader.cpp Fri Oct 31 12:16:20 2014 +0100 +++ b/src/share/vm/classfile/classLoader.cpp Wed Nov 05 08:35:02 2014 +0000 @@ -610,7 +610,7 @@ } #endif -void ClassLoader::setup_search_path(const char *class_path) { +void ClassLoader::setup_search_path(const char *class_path, bool canonicalize) { int offset = 0; int len = (int)strlen(class_path); int end = 0; @@ -625,7 +625,13 @@ char* path = NEW_RESOURCE_ARRAY(char, end - start + 1); strncpy(path, &class_path[start], end - start); path[end - start] = '\0'; - update_class_path_entry_list(path, false); + if (canonicalize) { + char* canonical_path = NEW_RESOURCE_ARRAY(char, JVM_MAXPATHLEN + 1); + if (get_canonical_path(path, canonical_path, JVM_MAXPATHLEN)) { + path = canonical_path; + } + } + update_class_path_entry_list(path, /*check_for_duplicates=*/canonicalize); #if INCLUDE_CDS if (DumpSharedSpaces) { check_shared_classpath(path); diff -r 468850e35e48 -r d4562805b030 src/share/vm/classfile/classLoader.hpp --- a/src/share/vm/classfile/classLoader.hpp Fri Oct 31 12:16:20 2014 +0100 +++ b/src/share/vm/classfile/classLoader.hpp Wed Nov 05 08:35:02 2014 +0000 @@ -129,8 +129,8 @@ bool _has_error; bool _throw_exception; volatile ClassPathEntry* _resolved_entry; + public: ClassPathEntry* resolve_entry(TRAPS); - public: bool is_jar_file(); const char* name() { return _path; } LazyClassPathEntry(const char* path, const struct stat* st, bool throw_exception); @@ -218,7 +218,7 @@ static void setup_meta_index(const char* meta_index_path, const char* meta_index_dir, int start_index); static void setup_bootstrap_search_path(); - static void setup_search_path(const char *class_path); + static void setup_search_path(const char *class_path, bool canonicalize=false); static void load_zip_library(); static ClassPathEntry* create_class_path_entry(const char *path, const struct stat* st, @@ -329,6 +329,10 @@ return e; } + static int num_classpath_entries() { + return _num_entries; + } + #if INCLUDE_CDS // Sharing dump and restore static void copy_package_info_buckets(char** top, char* end); diff -r 468850e35e48 -r d4562805b030 src/share/vm/classfile/classLoaderExt.hpp --- a/src/share/vm/classfile/classLoaderExt.hpp Fri Oct 31 12:16:20 2014 +0100 +++ b/src/share/vm/classfile/classLoaderExt.hpp Wed Nov 05 08:35:02 2014 +0000 @@ -64,6 +64,15 @@ ClassLoader::add_to_list(new_entry); } static void setup_search_paths() {} + + static void init_lookup_cache(TRAPS) {} + static void copy_lookup_cache_to_archive(char** top, char* end) {} + static char* restore_lookup_cache_from_archive(char* buffer) {return buffer;} + static inline bool is_lookup_cache_enabled() {return false;} + + static bool known_to_not_exist(JNIEnv *env, jobject loader, const char *classname, TRAPS) {return false;} + static jobjectArray get_lookup_cache_urls(JNIEnv *env, jobject loader, TRAPS) {return NULL;} + static jintArray get_lookup_cache(JNIEnv *env, jobject loader, const char *pkgname, TRAPS) {return NULL;} }; #endif // SHARE_VM_CLASSFILE_CLASSLOADEREXT_HPP diff -r 468850e35e48 -r d4562805b030 src/share/vm/classfile/systemDictionary.hpp --- a/src/share/vm/classfile/systemDictionary.hpp Fri Oct 31 12:16:20 2014 +0100 +++ b/src/share/vm/classfile/systemDictionary.hpp Wed Nov 05 08:35:02 2014 +0000 @@ -175,6 +175,8 @@ do_klass(URL_klass, java_net_URL, Pre ) \ do_klass(Jar_Manifest_klass, java_util_jar_Manifest, Pre ) \ do_klass(sun_misc_Launcher_klass, sun_misc_Launcher, Pre ) \ + do_klass(sun_misc_Launcher_AppClassLoader_klass, sun_misc_Launcher_AppClassLoader, Pre ) \ + do_klass(sun_misc_Launcher_ExtClassLoader_klass, sun_misc_Launcher_ExtClassLoader, Pre ) \ do_klass(CodeSource_klass, java_security_CodeSource, Pre ) \ \ /* It's NULL in non-1.4 JDKs. */ \ diff -r 468850e35e48 -r d4562805b030 src/share/vm/classfile/vmSymbols.hpp --- a/src/share/vm/classfile/vmSymbols.hpp Fri Oct 31 12:16:20 2014 +0100 +++ b/src/share/vm/classfile/vmSymbols.hpp Wed Nov 05 08:35:02 2014 +0000 @@ -116,6 +116,7 @@ template(java_lang_AssertionStatusDirectives, "java/lang/AssertionStatusDirectives") \ template(getBootClassPathEntryForClass_name, "getBootClassPathEntryForClass") \ template(sun_misc_PostVMInitHook, "sun/misc/PostVMInitHook") \ + template(sun_misc_Launcher_AppClassLoader, "sun/misc/Launcher$AppClassLoader") \ template(sun_misc_Launcher_ExtClassLoader, "sun/misc/Launcher$ExtClassLoader") \ \ /* Java runtime version access */ \ diff -r 468850e35e48 -r d4562805b030 src/share/vm/memory/metadataFactory.hpp --- a/src/share/vm/memory/metadataFactory.hpp Fri Oct 31 12:16:20 2014 +0100 +++ b/src/share/vm/memory/metadataFactory.hpp Wed Nov 05 08:35:02 2014 +0000 @@ -64,6 +64,12 @@ template static void free_array(ClassLoaderData* loader_data, Array* data) { + if (DumpSharedSpaces) { + // FIXME: the freeing code is buggy, especially when PrintSharedSpaces is enabled. + // Disable for now -- this means if you specify bad classes in your classlist you + // may have wasted space inside the archive. + return; + } if (data != NULL) { assert(loader_data != NULL, "shouldn't pass null"); assert(!data->is_shared(), "cannot deallocate array in shared spaces"); diff -r 468850e35e48 -r d4562805b030 src/share/vm/memory/metaspaceShared.cpp --- a/src/share/vm/memory/metaspaceShared.cpp Fri Oct 31 12:16:20 2014 +0100 +++ b/src/share/vm/memory/metaspaceShared.cpp Wed Nov 05 08:35:02 2014 +0000 @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "classfile/dictionary.hpp" +#include "classfile/classLoaderExt.hpp" #include "classfile/loaderConstraints.hpp" #include "classfile/placeholders.hpp" #include "classfile/sharedClassUtil.hpp" @@ -39,6 +40,7 @@ #include "runtime/signature.hpp" #include "runtime/vm_operations.hpp" #include "runtime/vmThread.hpp" +#include "utilities/hashtable.hpp" #include "utilities/hashtable.inline.hpp" PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC @@ -533,6 +535,8 @@ ClassLoader::copy_package_info_table(&md_top, md_end); ClassLoader::verify(); + ClassLoaderExt::copy_lookup_cache_to_archive(&md_top, md_end); + // Write the other data to the output array. WriteClosure wc(md_top, md_end); MetaspaceShared::serialize(&wc); @@ -745,6 +749,8 @@ } tty->print_cr("Loading classes to share: done."); + ClassLoaderExt::init_lookup_cache(THREAD); + if (PrintSharedSpaces) { tty->print_cr("Shared spaces: preloaded %d classes", class_count); } @@ -1056,6 +1062,8 @@ buffer += sizeof(intptr_t); buffer += len; + buffer = ClassLoaderExt::restore_lookup_cache_from_archive(buffer); + intptr_t* array = (intptr_t*)buffer; ReadClosure rc(&array); serialize(&rc); diff -r 468850e35e48 -r d4562805b030 src/share/vm/memory/metaspaceShared.hpp --- a/src/share/vm/memory/metaspaceShared.hpp Fri Oct 31 12:16:20 2014 +0100 +++ b/src/share/vm/memory/metaspaceShared.hpp Wed Nov 05 08:35:02 2014 +0000 @@ -32,9 +32,9 @@ #define LargeSharedArchiveSize (300*M) #define HugeSharedArchiveSize (800*M) -#define ReadOnlyRegionPercentage 0.4 -#define ReadWriteRegionPercentage 0.55 -#define MiscDataRegionPercentage 0.03 +#define ReadOnlyRegionPercentage 0.39 +#define ReadWriteRegionPercentage 0.50 +#define MiscDataRegionPercentage 0.09 #define MiscCodeRegionPercentage 0.02 #define LargeThresholdClassCount 5000 #define HugeThresholdClassCount 40000 diff -r 468850e35e48 -r d4562805b030 src/share/vm/prims/jvm.cpp --- a/src/share/vm/prims/jvm.cpp Fri Oct 31 12:16:20 2014 +0100 +++ b/src/share/vm/prims/jvm.cpp Wed Nov 05 08:35:02 2014 +0000 @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "classfile/classLoader.hpp" +#include "classfile/classLoaderExt.hpp" #include "classfile/javaAssertions.hpp" #include "classfile/javaClasses.hpp" #include "classfile/symbolTable.hpp" @@ -393,6 +394,14 @@ } } + const char* enableSharedLookupCache = "false"; +#if INCLUDE_CDS + if (ClassLoaderExt::is_lookup_cache_enabled()) { + enableSharedLookupCache = "true"; + } +#endif + PUTPROP(props, "sun.cds.enableSharedLookupCache", enableSharedLookupCache); + return properties; JVM_END @@ -766,6 +775,36 @@ JVM_END +JVM_ENTRY(jboolean, JVM_KnownToNotExist(JNIEnv *env, jobject loader, const char *classname)) + JVMWrapper("JVM_KnownToNotExist"); +#if INCLUDE_CDS + return ClassLoaderExt::known_to_not_exist(env, loader, classname, CHECK_(false)); +#else + return false; +#endif +JVM_END + + +JVM_ENTRY(jobjectArray, JVM_GetResourceLookupCacheURLs(JNIEnv *env, jobject loader)) + JVMWrapper("JVM_GetResourceLookupCacheURLs"); +#if INCLUDE_CDS + return ClassLoaderExt::get_lookup_cache_urls(env, loader, CHECK_NULL); +#else + return NULL; +#endif +JVM_END + + +JVM_ENTRY(jintArray, JVM_GetResourceLookupCache(JNIEnv *env, jobject loader, const char *resource_name)) + JVMWrapper("JVM_GetResourceLookupCache"); +#if INCLUDE_CDS + return ClassLoaderExt::get_lookup_cache(env, loader, resource_name, CHECK_NULL); +#else + return NULL; +#endif +JVM_END + + // Returns a class loaded by the bootstrap class loader; or null // if not found. ClassNotFoundException is not thrown. // diff -r 468850e35e48 -r d4562805b030 src/share/vm/prims/jvm.h --- a/src/share/vm/prims/jvm.h Fri Oct 31 12:16:20 2014 +0100 +++ b/src/share/vm/prims/jvm.h Wed Nov 05 08:35:02 2014 +0000 @@ -1548,6 +1548,31 @@ JNIEXPORT jobjectArray JNICALL JVM_GetThreadStateNames(JNIEnv* env, jint javaThreadState, jintArray values); +/* + * Returns true if the JVM's lookup cache indicates that this class is + * known to NOT exist for the given loader. + */ +JNIEXPORT jboolean JNICALL +JVM_KnownToNotExist(JNIEnv *env, jobject loader, const char *classname); + +/* + * Returns an array of all URLs that are stored in the JVM's lookup cache + * for the given loader. NULL if the lookup cache is unavailable. + */ +JNIEXPORT jobjectArray JNICALL +JVM_GetResourceLookupCacheURLs(JNIEnv *env, jobject loader); + +/* + * Returns an array of all URLs that *may* contain the resource_name for the + * given loader. This function returns an integer array, each element + * of which can be used to index into the array returned by + * JVM_GetResourceLookupCacheURLs of the same loader to determine the + * URLs. + */ +JNIEXPORT jintArray JNICALL +JVM_GetResourceLookupCache(JNIEnv *env, jobject loader, const char *resource_name); + + /* ========================================================================= * The following defines a private JVM interface that the JDK can query * for the JVM version and capabilities. sun.misc.Version defines diff -r 468850e35e48 -r d4562805b030 src/share/vm/prims/whitebox.cpp --- a/src/share/vm/prims/whitebox.cpp Fri Oct 31 12:16:20 2014 +0100 +++ b/src/share/vm/prims/whitebox.cpp Wed Nov 05 08:35:02 2014 +0000 @@ -104,6 +104,28 @@ return closure.found(); WB_END +WB_ENTRY(jboolean, WB_ClassKnownToNotExist(JNIEnv* env, jobject o, jobject loader, jstring name)) + ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI + const char* class_name = env->GetStringUTFChars(name, NULL); + jboolean result = JVM_KnownToNotExist(env, loader, class_name); + env->ReleaseStringUTFChars(name, class_name); + return result; +WB_END + +WB_ENTRY(jobjectArray, WB_GetLookupCacheURLs(JNIEnv* env, jobject o, jobject loader)) + ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI + return JVM_GetResourceLookupCacheURLs(env, loader); +WB_END + +WB_ENTRY(jintArray, WB_GetLookupCacheMatches(JNIEnv* env, jobject o, jobject loader, jstring name)) + ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI + const char* resource_name = env->GetStringUTFChars(name, NULL); + jintArray result = JVM_GetResourceLookupCache(env, loader, resource_name); + + env->ReleaseStringUTFChars(name, resource_name); + return result; +WB_END + WB_ENTRY(jlong, WB_GetCompressedOopsMaxHeapSize(JNIEnv* env, jobject o)) { return (jlong)Arguments::max_heap_for_compressed_oops(); } @@ -939,6 +961,11 @@ {CC"isObjectInOldGen", CC"(Ljava/lang/Object;)Z", (void*)&WB_isObjectInOldGen }, {CC"getHeapOopSize", CC"()I", (void*)&WB_GetHeapOopSize }, {CC"isClassAlive0", CC"(Ljava/lang/String;)Z", (void*)&WB_IsClassAlive }, + {CC"classKnownToNotExist", + CC"(Ljava/lang/ClassLoader;Ljava/lang/String;)Z",(void*)&WB_ClassKnownToNotExist}, + {CC"getLookupCacheURLs", CC"(Ljava/lang/ClassLoader;)[Ljava/net/URL;", (void*)&WB_GetLookupCacheURLs}, + {CC"getLookupCacheMatches", CC"(Ljava/lang/ClassLoader;Ljava/lang/String;)[I", + (void*)&WB_GetLookupCacheMatches}, {CC"parseCommandLine", CC"(Ljava/lang/String;[Lsun/hotspot/parser/DiagnosticCommand;)[Ljava/lang/Object;", (void*) &WB_ParseCommandLine diff -r 468850e35e48 -r d4562805b030 test/compiler/whitebox/CompilerWhiteBoxTest.java --- a/test/compiler/whitebox/CompilerWhiteBoxTest.java Fri Oct 31 12:16:20 2014 +0100 +++ b/test/compiler/whitebox/CompilerWhiteBoxTest.java Wed Nov 05 08:35:02 2014 +0000 @@ -72,9 +72,9 @@ /** Flag for verbose output, true if {@code -Dverbose} specified */ protected static final boolean IS_VERBOSE = System.getProperty("verbose") != null; - /** count of invocation to triger compilation */ + /** invocation count to trigger compilation */ protected static final int THRESHOLD; - /** count of invocation to triger OSR compilation */ + /** invocation count to trigger OSR compilation */ protected static final long BACKEDGE_THRESHOLD; /** Value of {@code java.vm.info} (interpreted|mixed|comp mode) */ protected static final String MODE = System.getProperty("java.vm.info"); @@ -206,7 +206,6 @@ * is compiled, or if {@linkplain #method} has zero * compilation level. */ - protected final void checkNotCompiled(int compLevel) { if (WHITE_BOX.isMethodQueuedForCompilation(method)) { throw new RuntimeException(method + " must not be in queue"); @@ -227,20 +226,30 @@ * compilation level. */ protected final void checkNotCompiled() { + checkNotCompiled(true); + checkNotCompiled(false); + } + + /** + * Checks, that {@linkplain #method} is not (OSR-)compiled. + * + * @param isOsr Check for OSR compilation if true + * @throws RuntimeException if {@linkplain #method} is in compiler queue or + * is compiled, or if {@linkplain #method} has zero + * compilation level. + */ + protected final void checkNotCompiled(boolean isOsr) { + waitBackgroundCompilation(); if (WHITE_BOX.isMethodQueuedForCompilation(method)) { throw new RuntimeException(method + " must not be in queue"); } - if (WHITE_BOX.isMethodCompiled(method, false)) { - throw new RuntimeException(method + " must be not compiled"); - } - if (WHITE_BOX.getMethodCompilationLevel(method, false) != 0) { - throw new RuntimeException(method + " comp_level must be == 0"); + if (WHITE_BOX.isMethodCompiled(method, isOsr)) { + throw new RuntimeException(method + " must not be " + + (isOsr ? "osr_" : "") + "compiled"); } - if (WHITE_BOX.isMethodCompiled(method, true)) { - throw new RuntimeException(method + " must be not osr_compiled"); - } - if (WHITE_BOX.getMethodCompilationLevel(method, true) != 0) { - throw new RuntimeException(method + " osr_comp_level must be == 0"); + if (WHITE_BOX.getMethodCompilationLevel(method, isOsr) != 0) { + throw new RuntimeException(method + (isOsr ? " osr_" : " ") + + "comp_level must be == 0"); } } @@ -306,12 +315,21 @@ * Waits for completion of background compilation of {@linkplain #method}. */ protected final void waitBackgroundCompilation() { + waitBackgroundCompilation(method); + } + + /** + * Waits for completion of background compilation of the given executable. + * + * @param executable Executable + */ + protected static final void waitBackgroundCompilation(Executable executable) { if (!BACKGROUND_COMPILATION) { return; } final Object obj = new Object(); for (int i = 0; i < 10 - && WHITE_BOX.isMethodQueuedForCompilation(method); ++i) { + && WHITE_BOX.isMethodQueuedForCompilation(executable); ++i) { synchronized (obj) { try { obj.wait(1000); @@ -425,14 +443,14 @@ /** constructor test case */ CONSTRUCTOR_TEST(Helper.CONSTRUCTOR, Helper.CONSTRUCTOR_CALLABLE, false), /** method test case */ - METOD_TEST(Helper.METHOD, Helper.METHOD_CALLABLE, false), + METHOD_TEST(Helper.METHOD, Helper.METHOD_CALLABLE, false), /** static method test case */ STATIC_TEST(Helper.STATIC, Helper.STATIC_CALLABLE, false), /** OSR constructor test case */ OSR_CONSTRUCTOR_TEST(Helper.OSR_CONSTRUCTOR, Helper.OSR_CONSTRUCTOR_CALLABLE, true), /** OSR method test case */ - OSR_METOD_TEST(Helper.OSR_METHOD, Helper.OSR_METHOD_CALLABLE, true), + OSR_METHOD_TEST(Helper.OSR_METHOD, Helper.OSR_METHOD_CALLABLE, true), /** OSR static method test case */ OSR_STATIC_TEST(Helper.OSR_STATIC, Helper.OSR_STATIC_CALLABLE, true); @@ -494,7 +512,7 @@ = new Callable() { @Override public Integer call() throws Exception { - return new Helper(null).hashCode(); + return new Helper(null, CompilerWhiteBoxTest.BACKEDGE_THRESHOLD).hashCode(); } }; @@ -504,7 +522,7 @@ @Override public Integer call() throws Exception { - return helper.osrMethod(); + return helper.osrMethod(CompilerWhiteBoxTest.BACKEDGE_THRESHOLD); } }; @@ -512,7 +530,7 @@ = new Callable() { @Override public Integer call() throws Exception { - return osrStaticMethod(); + return osrStaticMethod(CompilerWhiteBoxTest.BACKEDGE_THRESHOLD); } }; @@ -532,25 +550,24 @@ } try { OSR_CONSTRUCTOR = Helper.class.getDeclaredConstructor( - Object.class); + Object.class, long.class); } catch (NoSuchMethodException | SecurityException e) { throw new RuntimeException( - "exception on getting method Helper.(Object)", e); + "exception on getting method Helper.(Object, long)", e); } METHOD = getMethod("method"); STATIC = getMethod("staticMethod"); - OSR_METHOD = getMethod("osrMethod"); - OSR_STATIC = getMethod("osrStaticMethod"); + OSR_METHOD = getMethod("osrMethod", long.class); + OSR_STATIC = getMethod("osrStaticMethod", long.class); } - private static Method getMethod(String name) { + private static Method getMethod(String name, Class... parameterTypes) { try { - return Helper.class.getDeclaredMethod(name); + return Helper.class.getDeclaredMethod(name, parameterTypes); } catch (NoSuchMethodException | SecurityException e) { throw new RuntimeException( "exception on getting method Helper." + name, e); } - } private static int staticMethod() { @@ -561,17 +578,84 @@ return 42; } - private static int osrStaticMethod() { + /** + * Deoptimizes all non-osr versions of the given executable after + * compilation finished. + * + * @param e Executable + * @throws Exception + */ + private static void waitAndDeoptimize(Executable e) { + CompilerWhiteBoxTest.waitBackgroundCompilation(e); + if (WhiteBox.getWhiteBox().isMethodQueuedForCompilation(e)) { + throw new RuntimeException(e + " must not be in queue"); + } + // Deoptimize non-osr versions of executable + WhiteBox.getWhiteBox().deoptimizeMethod(e, false); + } + + /** + * Executes the method multiple times to make sure we have + * enough profiling information before triggering an OSR + * compilation. Otherwise the C2 compiler may add uncommon traps. + * + * @param m Method to be executed + * @return Number of times the method was executed + * @throws Exception + */ + private static int warmup(Method m) throws Exception { + waitAndDeoptimize(m); + Helper helper = new Helper(); int result = 0; - for (long i = 0; i < CompilerWhiteBoxTest.BACKEDGE_THRESHOLD; ++i) { + for (long i = 0; i < CompilerWhiteBoxTest.THRESHOLD; ++i) { + result += (int)m.invoke(helper, 1); + } + // Wait to make sure OSR compilation is not blocked by + // non-OSR compilation in the compile queue + CompilerWhiteBoxTest.waitBackgroundCompilation(m); + return result; + } + + /** + * Executes the constructor multiple times to make sure we + * have enough profiling information before triggering an OSR + * compilation. Otherwise the C2 compiler may add uncommon traps. + * + * @param c Constructor to be executed + * @return Number of times the constructor was executed + * @throws Exception + */ + private static int warmup(Constructor c) throws Exception { + waitAndDeoptimize(c); + int result = 0; + for (long i = 0; i < CompilerWhiteBoxTest.THRESHOLD; ++i) { + result += c.newInstance(null, 1).hashCode(); + } + // Wait to make sure OSR compilation is not blocked by + // non-OSR compilation in the compile queue + CompilerWhiteBoxTest.waitBackgroundCompilation(c); + return result; + } + + private static int osrStaticMethod(long limit) throws Exception { + int result = 0; + if (limit != 1) { + result = warmup(OSR_STATIC); + } + // Trigger osr compilation + for (long i = 0; i < limit; ++i) { result += staticMethod(); } return result; } - private int osrMethod() { + private int osrMethod(long limit) throws Exception { int result = 0; - for (long i = 0; i < CompilerWhiteBoxTest.BACKEDGE_THRESHOLD; ++i) { + if (limit != 1) { + result = warmup(OSR_METHOD); + } + // Trigger osr compilation + for (long i = 0; i < limit; ++i) { result += method(); } return result; @@ -585,9 +669,13 @@ } // for OSR constructor test case - private Helper(Object o) { + private Helper(Object o, long limit) throws Exception { int result = 0; - for (long i = 0; i < CompilerWhiteBoxTest.BACKEDGE_THRESHOLD; ++i) { + if (limit != 1) { + result = warmup(OSR_CONSTRUCTOR); + } + // Trigger osr compilation + for (long i = 0; i < limit; ++i) { result += method(); } x = result; diff -r 468850e35e48 -r d4562805b030 test/compiler/whitebox/MakeMethodNotCompilableTest.java --- a/test/compiler/whitebox/MakeMethodNotCompilableTest.java Fri Oct 31 12:16:20 2014 +0100 +++ b/test/compiler/whitebox/MakeMethodNotCompilableTest.java Wed Nov 05 08:35:02 2014 +0000 @@ -131,14 +131,15 @@ throw new RuntimeException(method + " is not compilable after clearMethodState()"); } - + // Make method not (OSR-)compilable (depending on testCase.isOsr()) makeNotCompilable(); if (isCompilable()) { throw new RuntimeException(method + " must be not compilable"); } - + // Try to (OSR-)compile method compile(); - checkNotCompiled(); + // Method should not be (OSR-)compiled + checkNotCompiled(testCase.isOsr()); if (isCompilable()) { throw new RuntimeException(method + " must be not compilable"); } diff -r 468850e35e48 -r d4562805b030 test/testlibrary/whitebox/sun/hotspot/WhiteBox.java --- a/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java Fri Oct 31 12:16:20 2014 +0100 +++ b/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java Wed Nov 05 08:35:02 2014 +0000 @@ -30,6 +30,7 @@ import java.util.function.Function; import java.util.stream.Stream; import java.security.BasicPermission; +import java.net.URL; import sun.hotspot.parser.DiagnosticCommand; @@ -84,6 +85,11 @@ } private native boolean isClassAlive0(String name); + // Resource/Class Lookup Cache + public native boolean classKnownToNotExist(ClassLoader loader, String name); + public native URL[] getLookupCacheURLs(ClassLoader loader); + public native int[] getLookupCacheMatches(ClassLoader loader, String name); + // G1 public native boolean g1InConcurrentMark(); public native boolean g1IsHumongous(Object o);