diff --git a/048cebd17f73.tar.bz2 b/048cebd17f73.tar.bz2 new file mode 100644 index 0000000..ecb4029 --- /dev/null +++ b/048cebd17f73.tar.bz2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:34444b79de79068b833f491b810084693df337442c4771ea99416b807dec0961 +size 2730451 diff --git a/06c52e8fd6d3.tar.bz2 b/06c52e8fd6d3.tar.bz2 deleted file mode 100644 index 38ae458..0000000 --- a/06c52e8fd6d3.tar.bz2 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:23775a2663fb016724982bcb3dde2406692e7fc961d9087636c4fb2e698b397e -size 8024458 diff --git a/0ee548a1cda0.tar.bz2 b/0ee548a1cda0.tar.bz2 deleted file mode 100644 index 71a9c92..0000000 --- a/0ee548a1cda0.tar.bz2 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f4ad54bff47e12b6d8993272507638b1e59893e2abe4bababf9132f2554cae31 -size 7746642 diff --git a/44142a22d60f.tar.bz2 b/44142a22d60f.tar.bz2 new file mode 100644 index 0000000..eac89f0 --- /dev/null +++ b/44142a22d60f.tar.bz2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:604eec48791228b6761a76dda0836d838f03f85d49c53253b6eb78688f8b2c74 +size 8049687 diff --git a/472aa5bae0e7.tar.bz2 b/472aa5bae0e7.tar.bz2 new file mode 100644 index 0000000..3324d4d --- /dev/null +++ b/472aa5bae0e7.tar.bz2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f38f4effd39754fd2d211f293ffbb9c06f820fa2231c20de94a04a4a63043fcc +size 1019625 diff --git a/4c7421f74674.tar.bz2 b/4c7421f74674.tar.bz2 deleted file mode 100644 index 263ea1e..0000000 --- a/4c7421f74674.tar.bz2 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:187d46899c5b15df984245404e4e1f4c3858a901a1e397ffd1cc4f11e9078561 -size 1019737 diff --git a/54a13451ce24.tar.bz2 b/54a13451ce24.tar.bz2 deleted file mode 100644 index aba843a..0000000 --- a/54a13451ce24.tar.bz2 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:131b7320b7b2002b2b397f19c1e2d3fea34fb5713f0461cfa7d5f83983295720 -size 2729901 diff --git a/5b37e6757d7c.tar.bz2 b/5b37e6757d7c.tar.bz2 new file mode 100644 index 0000000..0f84a8d --- /dev/null +++ b/5b37e6757d7c.tar.bz2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6c026b3e3c3e8e3f41e4f1867f4b3f96f98f0857723887dd4b5f57bc7a6a6510 +size 396212 diff --git a/5fbbfd66643e.tar.bz2 b/5fbbfd66643e.tar.bz2 new file mode 100644 index 0000000..284b791 --- /dev/null +++ b/5fbbfd66643e.tar.bz2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5bd07f61b5fbc0af200aa793d0a6837d268ef05cc26e66809432a2699bf7d241 +size 2530794 diff --git a/6e928fd91525.tar.bz2 b/6e928fd91525.tar.bz2 deleted file mode 100644 index 86378e2..0000000 --- a/6e928fd91525.tar.bz2 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:7bb9fdc5be0a5c691fcaad0486088896306371a6aa797117d391e714541c5e0d -size 2530625 diff --git a/79177246b3db.tar.bz2 b/79177246b3db.tar.bz2 deleted file mode 100644 index 054cb1a..0000000 --- a/79177246b3db.tar.bz2 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:19cb949c13e12041118540c7b01695caa57f5785eece3cbfece303c69e1628b7 -size 2375049 diff --git a/9d903721276c.tar.bz2 b/9d903721276c.tar.bz2 new file mode 100644 index 0000000..72ba601 --- /dev/null +++ b/9d903721276c.tar.bz2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bc16c36ef742c82e4415fe78ba6defe17db5112300785bac965b38623e88068c +size 45393269 diff --git a/aarch64-b12tob22.patch b/aarch64-b12tob22.patch deleted file mode 100644 index 665545d..0000000 --- a/aarch64-b12tob22.patch +++ /dev/null @@ -1,9092 +0,0 @@ ---- jdk8/hotspot/make/hotspot_version 2015-01-27 08:42:53.903819833 +0100 -+++ jdk8/hotspot/make/hotspot_version 2015-01-27 08:43:45.224625549 +0100 -@@ -31,11 +31,11 @@ - # - - # Don't put quotes (fail windows build). --HOTSPOT_VM_COPYRIGHT=Copyright 2014 -+HOTSPOT_VM_COPYRIGHT=Copyright 2015 - - HS_MAJOR_VER=25 - HS_MINOR_VER=40 --HS_BUILD_NUMBER=16 -+HS_BUILD_NUMBER=25 - - JDK_MAJOR_VER=1 - JDK_MINOR_VER=8 ---- jdk8/hotspot/make/linux/makefiles/adjust-mflags.sh 2015-01-27 08:42:53.903819833 +0100 -+++ jdk8/hotspot/make/linux/makefiles/adjust-mflags.sh 2015-01-27 08:43:45.224625549 +0100 -@@ -64,7 +64,7 @@ - echo "$MFLAGS" \ - | sed ' - s/^-/ -/ -- s/ -\([^ ][^ ]*\)j/ -\1 -j/ -+ s/ -\([^ I][^ I]*\)j/ -\1 -j/ - s/ -j[0-9][0-9]*/ -j/ - s/ -j\([^ ]\)/ -j -\1/ - s/ -j/ -j'${HOTSPOT_BUILD_JOBS:-${default_build_jobs}}'/ ---- jdk8/hotspot/make/linux/makefiles/mapfile-vers-debug 2015-01-27 08:42:53.903819833 +0100 -+++ jdk8/hotspot/make/linux/makefiles/mapfile-vers-debug 2015-01-27 08:43:45.225625525 +0100 -@@ -217,6 +217,9 @@ - JVM_RegisterSignal; - JVM_ReleaseUTF; - JVM_ResolveClass; -+ JVM_KnownToNotExist; -+ JVM_GetResourceLookupCacheURLs; -+ JVM_GetResourceLookupCache; - JVM_ResumeThread; - JVM_Send; - JVM_SendTo; ---- jdk8/hotspot/make/linux/makefiles/mapfile-vers-product 2015-01-27 08:42:53.903819833 +0100 -+++ jdk8/hotspot/make/linux/makefiles/mapfile-vers-product 2015-01-27 08:43:45.225625525 +0100 -@@ -217,6 +217,9 @@ - JVM_RegisterSignal; - JVM_ReleaseUTF; - JVM_ResolveClass; -+ JVM_KnownToNotExist; -+ JVM_GetResourceLookupCacheURLs; -+ JVM_GetResourceLookupCache; - JVM_ResumeThread; - JVM_Send; - JVM_SendTo; ---- jdk8/hotspot/src/os/linux/vm/perfMemory_linux.cpp 2015-01-27 08:42:53.926819297 +0100 -+++ jdk8/hotspot/src/os/linux/vm/perfMemory_linux.cpp 2015-01-27 08:43:45.226625502 +0100 -@@ -197,7 +197,38 @@ - } - - --// check if the given path is considered a secure directory for -+// Check if the given statbuf is considered a secure directory for -+// the backing store files. Returns true if the directory is considered -+// a secure location. Returns false if the statbuf is a symbolic link or -+// if an error occurred. -+// -+static bool is_statbuf_secure(struct stat *statp) { -+ if (S_ISLNK(statp->st_mode) || !S_ISDIR(statp->st_mode)) { -+ // The path represents a link or some non-directory file type, -+ // which is not what we expected. Declare it insecure. -+ // -+ return false; -+ } -+ // We have an existing directory, check if the permissions are safe. -+ // -+ if ((statp->st_mode & (S_IWGRP|S_IWOTH)) != 0) { -+ // The directory is open for writing and could be subjected -+ // to a symlink or a hard link attack. Declare it insecure. -+ // -+ return false; -+ } -+ // See if the uid of the directory matches the effective uid of the process. -+ // -+ if (statp->st_uid != geteuid()) { -+ // The directory was not created by this user, declare it insecure. -+ // -+ return false; -+ } -+ return true; -+} -+ -+ -+// Check if the given path is considered a secure directory for - // the backing store files. Returns true if the directory exists - // and is considered a secure location. Returns false if the path - // is a symbolic link or if an error occurred. -@@ -211,22 +242,180 @@ - return false; - } - -- // the path exists, now check it's mode -- if (S_ISLNK(statbuf.st_mode) || !S_ISDIR(statbuf.st_mode)) { -- // the path represents a link or some non-directory file type, -- // which is not what we expected. declare it insecure. -+ // The path exists, see if it is secure. -+ return is_statbuf_secure(&statbuf); -+} -+ -+ -+// Check if the given directory file descriptor is considered a secure -+// directory for the backing store files. Returns true if the directory -+// exists and is considered a secure location. Returns false if the path -+// is a symbolic link or if an error occurred. - // -+static bool is_dirfd_secure(int dir_fd) { -+ struct stat statbuf; -+ int result = 0; -+ -+ RESTARTABLE(::fstat(dir_fd, &statbuf), result); -+ if (result == OS_ERR) { - return false; - } -- else { -- // we have an existing directory, check if the permissions are safe. -+ -+ // The path exists, now check its mode. -+ return is_statbuf_secure(&statbuf); -+} -+ -+ -+// Check to make sure fd1 and fd2 are referencing the same file system object. - // -- if ((statbuf.st_mode & (S_IWGRP|S_IWOTH)) != 0) { -- // the directory is open for writing and could be subjected -- // to a symlnk attack. declare it insecure. -+static bool is_same_fsobject(int fd1, int fd2) { -+ struct stat statbuf1; -+ struct stat statbuf2; -+ int result = 0; -+ -+ RESTARTABLE(::fstat(fd1, &statbuf1), result); -+ if (result == OS_ERR) { -+ return false; -+ } -+ RESTARTABLE(::fstat(fd2, &statbuf2), result); -+ if (result == OS_ERR) { -+ return false; -+ } -+ -+ if ((statbuf1.st_ino == statbuf2.st_ino) && -+ (statbuf1.st_dev == statbuf2.st_dev)) { -+ return true; -+ } else { -+ return false; -+ } -+} -+ -+ -+// Open the directory of the given path and validate it. -+// Return a DIR * of the open directory. -+// -+static DIR *open_directory_secure(const char* dirname) { -+ // Open the directory using open() so that it can be verified -+ // to be secure by calling is_dirfd_secure(), opendir() and then check -+ // to see if they are the same file system object. This method does not -+ // introduce a window of opportunity for the directory to be attacked that -+ // calling opendir() and is_directory_secure() does. -+ int result; -+ DIR *dirp = NULL; -+ RESTARTABLE(::open(dirname, O_RDONLY|O_NOFOLLOW), result); -+ if (result == OS_ERR) { -+ if (PrintMiscellaneous && Verbose) { -+ if (errno == ELOOP) { -+ warning("directory %s is a symlink and is not secure\n", dirname); -+ } else { -+ warning("could not open directory %s: %s\n", dirname, strerror(errno)); -+ } -+ } -+ return dirp; -+ } -+ int fd = result; -+ -+ // Determine if the open directory is secure. -+ if (!is_dirfd_secure(fd)) { -+ // The directory is not a secure directory. -+ os::close(fd); -+ return dirp; -+ } -+ -+ // Open the directory. -+ dirp = ::opendir(dirname); -+ if (dirp == NULL) { -+ // The directory doesn't exist, close fd and return. -+ os::close(fd); -+ return dirp; -+ } -+ -+ // Check to make sure fd and dirp are referencing the same file system object. -+ if (!is_same_fsobject(fd, dirfd(dirp))) { -+ // The directory is not secure. -+ os::close(fd); -+ os::closedir(dirp); -+ dirp = NULL; -+ return dirp; -+ } -+ -+ // Close initial open now that we know directory is secure -+ os::close(fd); -+ -+ return dirp; -+} -+ -+// NOTE: The code below uses fchdir(), open() and unlink() because -+// fdopendir(), openat() and unlinkat() are not supported on all -+// versions. Once the support for fdopendir(), openat() and unlinkat() -+// is available on all supported versions the code can be changed -+// to use these functions. -+ -+// Open the directory of the given path, validate it and set the -+// current working directory to it. -+// Return a DIR * of the open directory and the saved cwd fd. - // -+static DIR *open_directory_secure_cwd(const char* dirname, int *saved_cwd_fd) { -+ -+ // Open the directory. -+ DIR* dirp = open_directory_secure(dirname); -+ if (dirp == NULL) { -+ // Directory doesn't exist or is insecure, so there is nothing to cleanup. -+ return dirp; -+ } -+ int fd = dirfd(dirp); -+ -+ // Open a fd to the cwd and save it off. -+ int result; -+ RESTARTABLE(::open(".", O_RDONLY), result); -+ if (result == OS_ERR) { -+ *saved_cwd_fd = -1; -+ } else { -+ *saved_cwd_fd = result; -+ } -+ -+ // Set the current directory to dirname by using the fd of the directory. -+ result = fchdir(fd); -+ -+ return dirp; -+} -+ -+// Close the directory and restore the current working directory. -+// -+static void close_directory_secure_cwd(DIR* dirp, int saved_cwd_fd) { -+ -+ int result; -+ // If we have a saved cwd change back to it and close the fd. -+ if (saved_cwd_fd != -1) { -+ result = fchdir(saved_cwd_fd); -+ ::close(saved_cwd_fd); -+ } -+ -+ // Close the directory. -+ os::closedir(dirp); -+} -+ -+// Check if the given file descriptor is considered a secure. -+// -+static bool is_file_secure(int fd, const char *filename) { -+ -+ int result; -+ struct stat statbuf; -+ -+ // Determine if the file is secure. -+ RESTARTABLE(::fstat(fd, &statbuf), result); -+ if (result == OS_ERR) { -+ if (PrintMiscellaneous && Verbose) { -+ warning("fstat failed on %s: %s\n", filename, strerror(errno)); -+ } - return false; - } -+ if (statbuf.st_nlink > 1) { -+ // A file with multiple links is not expected. -+ if (PrintMiscellaneous && Verbose) { -+ warning("file %s has multiple links\n", filename); -+ } -+ return false; - } - return true; - } -@@ -317,9 +506,11 @@ - - const char* tmpdirname = os::get_temp_directory(); - -+ // open the temp directory - DIR* tmpdirp = os::opendir(tmpdirname); - - if (tmpdirp == NULL) { -+ // Cannot open the directory to get the user name, return. - return NULL; - } - -@@ -344,7 +535,8 @@ - strcat(usrdir_name, "/"); - strcat(usrdir_name, dentry->d_name); - -- DIR* subdirp = os::opendir(usrdir_name); -+ // open the user directory -+ DIR* subdirp = open_directory_secure(usrdir_name); - - if (subdirp == NULL) { - FREE_C_HEAP_ARRAY(char, usrdir_name, mtInternal); -@@ -465,26 +657,6 @@ - } - - --// remove file --// --// this method removes the file with the given file name in the --// named directory. --// --static void remove_file(const char* dirname, const char* filename) { -- -- size_t nbytes = strlen(dirname) + strlen(filename) + 2; -- char* path = NEW_C_HEAP_ARRAY(char, nbytes, mtInternal); -- -- strcpy(path, dirname); -- strcat(path, "/"); -- strcat(path, filename); -- -- remove_file(path); -- -- FREE_C_HEAP_ARRAY(char, path, mtInternal); --} -- -- - // cleanup stale shared memory resources - // - // This method attempts to remove all stale shared memory files in -@@ -496,16 +668,11 @@ - // - static void cleanup_sharedmem_resources(const char* dirname) { - -- // open the user temp directory -- DIR* dirp = os::opendir(dirname); -- -+ int saved_cwd_fd; -+ // open the directory -+ DIR* dirp = open_directory_secure_cwd(dirname, &saved_cwd_fd); - if (dirp == NULL) { -- // directory doesn't exist, so there is nothing to cleanup -- return; -- } -- -- if (!is_directory_secure(dirname)) { -- // the directory is not a secure directory -+ // directory doesn't exist or is insecure, so there is nothing to cleanup - return; - } - -@@ -527,9 +695,8 @@ - if (pid == 0) { - - if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) { -- - // attempt to remove all unexpected files, except "." and ".." -- remove_file(dirname, entry->d_name); -+ unlink(entry->d_name); - } - - errno = 0; -@@ -551,12 +718,14 @@ - // - if ((pid == os::current_process_id()) || - (kill(pid, 0) == OS_ERR && (errno == ESRCH || errno == EPERM))) { -- -- remove_file(dirname, entry->d_name); -+ unlink(entry->d_name); - } - errno = 0; - } -- os::closedir(dirp); -+ -+ // close the directory and reset the current working directory -+ close_directory_secure_cwd(dirp, saved_cwd_fd); -+ - FREE_C_HEAP_ARRAY(char, dbuf, mtInternal); - } - -@@ -613,19 +782,54 @@ - return -1; - } - -- int result; -+ int saved_cwd_fd; -+ // open the directory and set the current working directory to it -+ DIR* dirp = open_directory_secure_cwd(dirname, &saved_cwd_fd); -+ if (dirp == NULL) { -+ // Directory doesn't exist or is insecure, so cannot create shared -+ // memory file. -+ return -1; -+ } - -- RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_TRUNC, S_IREAD|S_IWRITE), result); -+ // Open the filename in the current directory. -+ // Cannot use O_TRUNC here; truncation of an existing file has to happen -+ // after the is_file_secure() check below. -+ int result; -+ RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_NOFOLLOW, S_IREAD|S_IWRITE), result); - if (result == OS_ERR) { - if (PrintMiscellaneous && Verbose) { -+ if (errno == ELOOP) { -+ warning("file %s is a symlink and is not secure\n", filename); -+ } else { - warning("could not create file %s: %s\n", filename, strerror(errno)); - } -+ } -+ // close the directory and reset the current working directory -+ close_directory_secure_cwd(dirp, saved_cwd_fd); -+ - return -1; - } -+ // close the directory and reset the current working directory -+ close_directory_secure_cwd(dirp, saved_cwd_fd); - - // save the file descriptor - int fd = result; - -+ // check to see if the file is secure -+ if (!is_file_secure(fd, filename)) { -+ ::close(fd); -+ return -1; -+ } -+ -+ // truncate the file to get rid of any existing data -+ RESTARTABLE(::ftruncate(fd, (off_t)0), result); -+ if (result == OS_ERR) { -+ if (PrintMiscellaneous && Verbose) { -+ warning("could not truncate shared memory file: %s\n", strerror(errno)); -+ } -+ ::close(fd); -+ return -1; -+ } - // set the file size - RESTARTABLE(::ftruncate(fd, (off_t)size), result); - if (result == OS_ERR) { -@@ -683,8 +887,15 @@ - THROW_MSG_(vmSymbols::java_io_IOException(), strerror(errno), OS_ERR); - } - } -+ int fd = result; - -- return result; -+ // check to see if the file is secure -+ if (!is_file_secure(fd, filename)) { -+ ::close(fd); -+ return -1; -+ } -+ -+ return fd; - } - - // create a named shared memory region. returns the address of the -@@ -715,6 +926,13 @@ - - char* dirname = get_user_tmp_dir(user_name); - char* filename = get_sharedmem_filename(dirname, vmid); -+ // get the short filename -+ char* short_filename = strrchr(filename, '/'); -+ if (short_filename == NULL) { -+ short_filename = filename; -+ } else { -+ short_filename++; -+ } - - // cleanup any stale shared memory files - cleanup_sharedmem_resources(dirname); -@@ -722,7 +940,7 @@ - assert(((size > 0) && (size % os::vm_page_size() == 0)), - "unexpected PerfMemory region size"); - -- fd = create_sharedmem_resources(dirname, filename, size); -+ fd = create_sharedmem_resources(dirname, short_filename, size); - - FREE_C_HEAP_ARRAY(char, user_name, mtInternal); - FREE_C_HEAP_ARRAY(char, dirname, mtInternal); -@@ -837,12 +1055,12 @@ - // constructs for the file and the shared memory mapping. - if (mode == PerfMemory::PERF_MODE_RO) { - mmap_prot = PROT_READ; -- file_flags = O_RDONLY; -+ file_flags = O_RDONLY | O_NOFOLLOW; - } - else if (mode == PerfMemory::PERF_MODE_RW) { - #ifdef LATER - mmap_prot = PROT_READ | PROT_WRITE; -- file_flags = O_RDWR; -+ file_flags = O_RDWR | O_NOFOLLOW; - #else - THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), - "Unsupported access mode"); ---- jdk8/hotspot/src/share/vm/c1/c1_globals.hpp 2015-01-27 08:42:53.977818111 +0100 -+++ jdk8/hotspot/src/share/vm/c1/c1_globals.hpp 2015-01-27 08:43:45.226625502 +0100 -@@ -290,9 +290,6 @@ - develop(bool, InstallMethods, true, \ - "Install methods at the end of successful compilations") \ - \ -- product(intx, CompilationRepeat, 0, \ -- "Number of times to recompile method before returning result") \ -- \ - develop(intx, NMethodSizeLimit, (64*K)*wordSize, \ - "Maximum size of a compiled method.") \ - \ ---- jdk8/hotspot/src/share/vm/ci/bcEscapeAnalyzer.cpp 2015-01-27 08:42:53.977818111 +0100 -+++ jdk8/hotspot/src/share/vm/ci/bcEscapeAnalyzer.cpp 2015-01-27 08:43:45.227625479 +0100 -@@ -89,8 +89,8 @@ - public: - ArgumentMap *_vars; - ArgumentMap *_stack; -- short _stack_height; -- short _max_stack; -+ int _stack_height; -+ int _max_stack; - bool _initialized; - ArgumentMap empty_map; - ---- jdk8/hotspot/src/share/vm/ci/ciEnv.cpp 2015-01-27 08:42:53.977818111 +0100 -+++ jdk8/hotspot/src/share/vm/ci/ciEnv.cpp 2015-01-27 08:43:45.227625479 +0100 -@@ -559,8 +559,13 @@ - oop obj = cpool->resolved_references()->obj_at(cache_index); - if (obj != NULL) { - ciObject* ciobj = get_object(obj); -+ if (ciobj->is_array()) { -+ return ciConstant(T_ARRAY, ciobj); -+ } else { -+ assert(ciobj->is_instance(), "should be an instance"); - return ciConstant(T_OBJECT, ciobj); - } -+ } - index = cpool->object_to_cp_index(cache_index); - } - constantTag tag = cpool->tag_at(index); -@@ -586,8 +591,12 @@ - } - } - ciObject* constant = get_object(string); -+ if (constant->is_array()) { -+ return ciConstant(T_ARRAY, constant); -+ } else { - assert (constant->is_instance(), "must be an instance, or not? "); - return ciConstant(T_OBJECT, constant); -+ } - } else if (tag.is_klass() || tag.is_unresolved_klass()) { - // 4881222: allow ldc to take a class type - ciKlass* klass = get_klass_by_index_impl(cpool, index, ignore_will_link, accessor); ---- jdk8/hotspot/src/share/vm/ci/ciMethod.cpp 2015-01-27 08:42:53.978818087 +0100 -+++ jdk8/hotspot/src/share/vm/ci/ciMethod.cpp 2015-01-27 08:43:45.228625455 +0100 -@@ -68,7 +68,10 @@ - // ciMethod::ciMethod - // - // Loaded method. --ciMethod::ciMethod(methodHandle h_m) : ciMetadata(h_m()) { -+ciMethod::ciMethod(methodHandle h_m, ciInstanceKlass* holder) : -+ ciMetadata(h_m()), -+ _holder(holder) -+{ - assert(h_m() != NULL, "no null method"); - - // These fields are always filled in in loaded methods. -@@ -124,7 +127,6 @@ - // generating _signature may allow GC and therefore move m. - // These fields are always filled in. - _name = env->get_symbol(h_m()->name()); -- _holder = env->get_instance_klass(h_m()->method_holder()); - ciSymbol* sig_symbol = env->get_symbol(h_m()->signature()); - constantPoolHandle cpool = h_m()->constants(); - _signature = new (env->arena()) ciSignature(_holder, cpool, sig_symbol); ---- jdk8/hotspot/src/share/vm/ci/ciMethod.hpp 2015-01-27 08:42:53.978818087 +0100 -+++ jdk8/hotspot/src/share/vm/ci/ciMethod.hpp 2015-01-27 08:43:45.228625455 +0100 -@@ -90,7 +90,7 @@ - BCEscapeAnalyzer* _bcea; - #endif - -- ciMethod(methodHandle h_m); -+ ciMethod(methodHandle h_m, ciInstanceKlass* holder); - ciMethod(ciInstanceKlass* holder, ciSymbol* name, ciSymbol* signature, ciInstanceKlass* accessor); - - Method* get_Method() const { ---- jdk8/hotspot/src/share/vm/ci/ciObjectFactory.cpp 2015-01-27 08:42:53.978818087 +0100 -+++ jdk8/hotspot/src/share/vm/ci/ciObjectFactory.cpp 2015-01-27 08:43:45.229625432 +0100 -@@ -239,7 +239,7 @@ - ciObject* ciObjectFactory::get(oop key) { - ASSERT_IN_VM; - -- assert(key == NULL || Universe::heap()->is_in_reserved(key), "must be"); -+ assert(Universe::heap()->is_in_reserved(key), "must be"); - - NonPermObject* &bucket = find_non_perm(key); - if (bucket != NULL) { -@@ -260,10 +260,10 @@ - } - - // ------------------------------------------------------------------ --// ciObjectFactory::get -+// ciObjectFactory::get_metadata - // --// Get the ciObject corresponding to some oop. If the ciObject has --// already been created, it is returned. Otherwise, a new ciObject -+// Get the ciMetadata corresponding to some Metadata. If the ciMetadata has -+// already been created, it is returned. Otherwise, a new ciMetadata - // is created. - ciMetadata* ciObjectFactory::get_metadata(Metadata* key) { - ASSERT_IN_VM; -@@ -290,9 +290,9 @@ - } - #endif - if (!is_found_at(index, key, _ci_metadata)) { -- // The ciObject does not yet exist. Create it and insert it -+ // The ciMetadata does not yet exist. Create it and insert it - // into the cache. -- ciMetadata* new_object = create_new_object(key); -+ ciMetadata* new_object = create_new_metadata(key); - init_ident_of(new_object); - assert(new_object->is_metadata(), "must be"); - -@@ -344,15 +344,28 @@ - } - - // ------------------------------------------------------------------ --// ciObjectFactory::create_new_object -+// ciObjectFactory::create_new_metadata - // --// Create a new ciObject from a Metadata*. -+// Create a new ciMetadata from a Metadata*. - // --// Implementation note: this functionality could be virtual behavior --// of the oop itself. For now, we explicitly marshal the object. --ciMetadata* ciObjectFactory::create_new_object(Metadata* o) { -+// Implementation note: in order to keep Metadata live, an auxiliary ciObject -+// is used, which points to it's holder. -+ciMetadata* ciObjectFactory::create_new_metadata(Metadata* o) { - EXCEPTION_CONTEXT; - -+ // Hold metadata from unloading by keeping it's holder alive. -+ if (_initialized && o->is_klass()) { -+ Klass* holder = ((Klass*)o); -+ if (holder->oop_is_instance() && InstanceKlass::cast(holder)->is_anonymous()) { -+ // Though ciInstanceKlass records class loader oop, it's not enough to keep -+ // VM anonymous classes alive (loader == NULL). Klass holder should be used instead. -+ // It is enough to record a ciObject, since cached elements are never removed -+ // during ciObjectFactory lifetime. ciObjectFactory itself is created for -+ // every compilation and lives for the whole duration of the compilation. -+ ciObject* h = get(holder->klass_holder()); -+ } -+ } -+ - if (o->is_klass()) { - KlassHandle h_k(THREAD, (Klass*)o); - Klass* k = (Klass*)o; -@@ -365,14 +378,16 @@ - } - } else if (o->is_method()) { - methodHandle h_m(THREAD, (Method*)o); -- return new (arena()) ciMethod(h_m); -+ ciEnv *env = CURRENT_THREAD_ENV; -+ ciInstanceKlass* holder = env->get_instance_klass(h_m()->method_holder()); -+ return new (arena()) ciMethod(h_m, holder); - } else if (o->is_methodData()) { - // Hold methodHandle alive - might not be necessary ??? - methodHandle h_m(THREAD, ((MethodData*)o)->method()); - return new (arena()) ciMethodData((MethodData*)o); - } - -- // The oop is of some type not supported by the compiler interface. -+ // The Metadata* is of some type not supported by the compiler interface. - ShouldNotReachHere(); - return NULL; - } -@@ -701,7 +716,7 @@ - // If there is no entry in the cache corresponding to this oop, return - // the null tail of the bucket into which the oop should be inserted. - ciObjectFactory::NonPermObject* &ciObjectFactory::find_non_perm(oop key) { -- assert(Universe::heap()->is_in_reserved_or_null(key), "must be"); -+ assert(Universe::heap()->is_in_reserved(key), "must be"); - ciMetadata* klass = get_metadata(key->klass()); - NonPermObject* *bp = &_non_perm_bucket[(unsigned) klass->hash() % NON_PERM_BUCKETS]; - for (NonPermObject* p; (p = (*bp)) != NULL; bp = &p->next()) { ---- jdk8/hotspot/src/share/vm/ci/ciObjectFactory.hpp 2015-01-27 08:42:53.978818087 +0100 -+++ jdk8/hotspot/src/share/vm/ci/ciObjectFactory.hpp 2015-01-27 08:43:45.229625432 +0100 -@@ -73,7 +73,7 @@ - void insert(int index, ciMetadata* obj, GrowableArray* objects); - - ciObject* create_new_object(oop o); -- ciMetadata* create_new_object(Metadata* o); -+ ciMetadata* create_new_metadata(Metadata* o); - - void ensure_metadata_alive(ciMetadata* m); - ---- jdk8/hotspot/src/share/vm/ci/ciTypeFlow.cpp 2015-01-27 08:42:53.978818087 +0100 -+++ jdk8/hotspot/src/share/vm/ci/ciTypeFlow.cpp 2015-01-27 08:43:45.230625409 +0100 -@@ -35,6 +35,7 @@ - #include "interpreter/bytecode.hpp" - #include "interpreter/bytecodes.hpp" - #include "memory/allocation.inline.hpp" -+#include "opto/compile.hpp" - #include "runtime/deoptimization.hpp" - #include "utilities/growableArray.hpp" - -@@ -730,7 +731,7 @@ - if (obj->is_null_object()) { - push_null(); - } else { -- assert(obj->is_instance(), "must be java_mirror of klass"); -+ assert(obj->is_instance() || obj->is_array(), "must be java_mirror of klass"); - push_object(obj->klass()); - } - } else { -@@ -2646,7 +2647,7 @@ - assert (!blk->has_pre_order(), ""); - blk->set_next_pre_order(); - -- if (_next_pre_order >= MaxNodeLimit / 2) { -+ if (_next_pre_order >= (int)Compile::current()->max_node_limit() / 2) { - // Too many basic blocks. Bail out. - // This can happen when try/finally constructs are nested to depth N, - // and there is O(2**N) cloning of jsr bodies. See bug 4697245! ---- jdk8/hotspot/src/share/vm/classfile/classFileParser.cpp 2015-01-27 08:42:53.979818064 +0100 -+++ jdk8/hotspot/src/share/vm/classfile/classFileParser.cpp 2015-01-27 08:43:45.231625386 +0100 -@@ -2529,7 +2529,7 @@ - Array* ClassFileParser::parse_methods(bool is_interface, - AccessFlags* promoted_flags, - bool* has_final_method, -- bool* has_default_methods, -+ bool* declares_default_methods, - TRAPS) { - ClassFileStream* cfs = stream(); - cfs->guarantee_more(2, CHECK_NULL); // length -@@ -2548,11 +2548,11 @@ - if (method->is_final()) { - *has_final_method = true; - } -- if (is_interface && !(*has_default_methods) -- && !method->is_abstract() && !method->is_static() -- && !method->is_private()) { -- // default method -- *has_default_methods = true; -+ // declares_default_methods: declares concrete instance methods, any access flags -+ // used for interface initialization, and default method inheritance analysis -+ if (is_interface && !(*declares_default_methods) -+ && !method->is_abstract() && !method->is_static()) { -+ *declares_default_methods = true; - } - _methods->at_put(index, method()); - } -@@ -3058,21 +3058,39 @@ - } - } - --// Transfer ownership of metadata allocated to the InstanceKlass. --void ClassFileParser::apply_parsed_class_metadata( -- instanceKlassHandle this_klass, -- int java_fields_count, TRAPS) { -- // Assign annotations if needed -- if (_annotations != NULL || _type_annotations != NULL || -- _fields_annotations != NULL || _fields_type_annotations != NULL) { -+// Create the Annotations object that will -+// hold the annotations array for the Klass. -+void ClassFileParser::create_combined_annotations(TRAPS) { -+ if (_annotations == NULL && -+ _type_annotations == NULL && -+ _fields_annotations == NULL && -+ _fields_type_annotations == NULL) { -+ // Don't create the Annotations object unnecessarily. -+ return; -+ } -+ - Annotations* annotations = Annotations::allocate(_loader_data, CHECK); - annotations->set_class_annotations(_annotations); - annotations->set_class_type_annotations(_type_annotations); - annotations->set_fields_annotations(_fields_annotations); - annotations->set_fields_type_annotations(_fields_type_annotations); -- this_klass->set_annotations(annotations); -+ -+ // This is the Annotations object that will be -+ // assigned to InstanceKlass being constructed. -+ _combined_annotations = annotations; -+ -+ // The annotations arrays below has been transfered the -+ // _combined_annotations so these fields can now be cleared. -+ _annotations = NULL; -+ _type_annotations = NULL; -+ _fields_annotations = NULL; -+ _fields_type_annotations = NULL; - } - -+// Transfer ownership of metadata allocated to the InstanceKlass. -+void ClassFileParser::apply_parsed_class_metadata( -+ instanceKlassHandle this_klass, -+ int java_fields_count, TRAPS) { - _cp->set_pool_holder(this_klass()); - this_klass->set_constants(_cp); - this_klass->set_fields(_fields, java_fields_count); -@@ -3080,6 +3098,7 @@ - this_klass->set_inner_classes(_inner_classes); - this_klass->set_local_interfaces(_local_interfaces); - this_klass->set_transitive_interfaces(_transitive_interfaces); -+ this_klass->set_annotations(_combined_annotations); - - // Clear out these fields so they don't get deallocated by the destructor - clear_class_metadata(); -@@ -3691,6 +3710,7 @@ - JvmtiCachedClassFileData *cached_class_file = NULL; - Handle class_loader(THREAD, loader_data->class_loader()); - bool has_default_methods = false; -+ bool declares_default_methods = false; - ResourceMark rm(THREAD); - - ClassFileStream* cfs = stream(); -@@ -3928,13 +3948,20 @@ - Array* methods = parse_methods(access_flags.is_interface(), - &promoted_flags, - &has_final_method, -- &has_default_methods, -+ &declares_default_methods, - CHECK_(nullHandle)); -+ if (declares_default_methods) { -+ has_default_methods = true; -+ } - - // Additional attributes - ClassAnnotationCollector parsed_annotations; - parse_classfile_attributes(&parsed_annotations, CHECK_(nullHandle)); - -+ // Finalize the Annotations metadata object, -+ // now that all annotation arrays have been created. -+ create_combined_annotations(CHECK_(nullHandle)); -+ - // Make sure this is the end of class file stream - guarantee_property(cfs->at_eos(), "Extra bytes at the end of class file %s", CHECK_(nullHandle)); - -@@ -4072,6 +4099,7 @@ - this_klass->set_minor_version(minor_version); - this_klass->set_major_version(major_version); - this_klass->set_has_default_methods(has_default_methods); -+ this_klass->set_declares_default_methods(declares_default_methods); - - if (!host_klass.is_null()) { - assert (this_klass->is_anonymous(), "should be the same"); -@@ -4234,10 +4262,27 @@ - InstanceKlass::deallocate_interfaces(_loader_data, _super_klass(), - _local_interfaces, _transitive_interfaces); - -+ if (_combined_annotations != NULL) { -+ // After all annotations arrays have been created, they are installed into the -+ // Annotations object that will be assigned to the InstanceKlass being created. -+ -+ // Deallocate the Annotations object and the installed annotations arrays. -+ _combined_annotations->deallocate_contents(_loader_data); -+ -+ // If the _combined_annotations pointer is non-NULL, -+ // then the other annotations fields should have been cleared. -+ assert(_annotations == NULL, "Should have been cleared"); -+ assert(_type_annotations == NULL, "Should have been cleared"); -+ assert(_fields_annotations == NULL, "Should have been cleared"); -+ assert(_fields_type_annotations == NULL, "Should have been cleared"); -+ } else { -+ // If the annotations arrays were not installed into the Annotations object, -+ // then they have to be deallocated explicitly. - MetadataFactory::free_array(_loader_data, _annotations); - MetadataFactory::free_array(_loader_data, _type_annotations); - Annotations::free_contents(_loader_data, _fields_annotations); - Annotations::free_contents(_loader_data, _fields_type_annotations); -+ } - - clear_class_metadata(); - ---- jdk8/hotspot/src/share/vm/classfile/classFileParser.hpp 2015-01-27 08:42:53.979818064 +0100 -+++ jdk8/hotspot/src/share/vm/classfile/classFileParser.hpp 2015-01-27 08:43:45.232625362 +0100 -@@ -75,6 +75,7 @@ - Array* _inner_classes; - Array* _local_interfaces; - Array* _transitive_interfaces; -+ Annotations* _combined_annotations; - AnnotationArray* _annotations; - AnnotationArray* _type_annotations; - Array* _fields_annotations; -@@ -86,6 +87,8 @@ - void set_class_generic_signature_index(u2 x) { _generic_signature_index = x; } - void set_class_sde_buffer(char* x, int len) { _sde_buffer = x; _sde_length = len; } - -+ void create_combined_annotations(TRAPS); -+ - void init_parsed_class_attributes(ClassLoaderData* loader_data) { - _loader_data = loader_data; - _synthetic_flag = false; -@@ -110,6 +113,7 @@ - _inner_classes = NULL; - _local_interfaces = NULL; - _transitive_interfaces = NULL; -+ _combined_annotations = NULL; - _annotations = _type_annotations = NULL; - _fields_annotations = _fields_type_annotations = NULL; - } -@@ -247,7 +251,7 @@ - Array* parse_methods(bool is_interface, - AccessFlags* promoted_flags, - bool* has_final_method, -- bool* has_default_method, -+ bool* declares_default_methods, - TRAPS); - intArray* sort_methods(Array* methods); - ---- jdk8/hotspot/src/share/vm/classfile/classLoader.cpp 2015-01-27 08:42:53.979818064 +0100 -+++ jdk8/hotspot/src/share/vm/classfile/classLoader.cpp 2015-01-27 08:43:45.232625362 +0100 -@@ -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); -@@ -1131,7 +1137,7 @@ - h = context.record_result(classpath_index, e, result, THREAD); - } else { - if (DumpSharedSpaces) { -- tty->print_cr("Preload Error: Cannot find %s", class_name); -+ tty->print_cr("Preload Warning: Cannot find %s", class_name); - } - } - ---- jdk8/hotspot/src/share/vm/classfile/classLoaderData.cpp 2015-01-27 08:42:53.979818064 +0100 -+++ jdk8/hotspot/src/share/vm/classfile/classLoaderData.cpp 2015-01-27 08:43:45.233625339 +0100 -@@ -747,7 +746,7 @@ - - // Move class loader data from main list to the unloaded list for unloading - // and deallocation later. --bool ClassLoaderDataGraph::do_unloading(BoolObjectClosure* is_alive_closure) { -+bool ClassLoaderDataGraph::do_unloading(BoolObjectClosure* is_alive_closure, bool clean_alive) { - ClassLoaderData* data = _head; - ClassLoaderData* prev = NULL; - bool seen_dead_loader = false; -@@ -756,16 +755,8 @@ - // purging and we don't want to rewalk the previously unloaded class loader data. - _saved_unloading = _unloading; - -- // mark metadata seen on the stack and code cache so we can delete -- // unneeded entries. -- bool has_redefined_a_class = JvmtiExport::has_redefined_a_class(); -- MetadataOnStackMark md_on_stack; - while (data != NULL) { - if (data->is_alive(is_alive_closure)) { -- if (has_redefined_a_class) { -- data->classes_do(InstanceKlass::purge_previous_versions); -- } -- data->free_deallocate_list(); - prev = data; - data = data->next(); - continue; -@@ -787,6 +778,11 @@ - _unloading = dead; - } - -+ if (clean_alive) { -+ // Clean previous versions and the deallocate list. -+ ClassLoaderDataGraph::clean_metaspaces(); -+ } -+ - if (seen_dead_loader) { - post_class_unload_events(); - } -@@ -794,6 +790,26 @@ - return seen_dead_loader; - } - -+void ClassLoaderDataGraph::clean_metaspaces() { -+ // mark metadata seen on the stack and code cache so we can delete unneeded entries. -+ bool has_redefined_a_class = JvmtiExport::has_redefined_a_class(); -+ MetadataOnStackMark md_on_stack(has_redefined_a_class); -+ -+ if (has_redefined_a_class) { -+ // purge_previous_versions also cleans weak method links. Because -+ // one method's MDO can reference another method from another -+ // class loader, we need to first clean weak method links for all -+ // class loaders here. Below, we can then free redefined methods -+ // for all class loaders. -+ for (ClassLoaderData* data = _head; data != NULL; data = data->next()) { -+ data->classes_do(InstanceKlass::purge_previous_versions); -+ } -+ } -+ -+ // Need to purge the previous version before deallocating. -+ free_deallocate_lists(); -+} -+ - void ClassLoaderDataGraph::purge() { - assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint!"); - ClassLoaderData* list = _unloading; -@@ -821,6 +837,14 @@ - #endif - } - -+void ClassLoaderDataGraph::free_deallocate_lists() { -+ for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) { -+ // We need to keep this data until InstanceKlass::purge_previous_version has been -+ // called on all alive classes. See the comment in ClassLoaderDataGraph::clean_metaspaces. -+ cld->free_deallocate_list(); -+ } -+} -+ - // CDS support - - // Global metaspaces for writing information to the shared archive. When -@@ -959,4 +983,4 @@ - event.commit(); - } - --#endif /* INCLUDE_TRACE */ -+#endif // INCLUDE_TRACE ---- jdk8/hotspot/src/share/vm/classfile/classLoaderData.hpp 2015-01-27 08:42:53.979818064 +0100 -+++ jdk8/hotspot/src/share/vm/classfile/classLoaderData.hpp 2015-01-27 08:43:45.234625316 +0100 -@@ -31,6 +31,7 @@ - #include "memory/metaspaceCounters.hpp" - #include "runtime/mutex.hpp" - #include "utilities/growableArray.hpp" -+#include "utilities/macros.hpp" - #if INCLUDE_TRACE - # include "utilities/ticks.hpp" - #endif -@@ -71,6 +72,7 @@ - - static ClassLoaderData* add(Handle class_loader, bool anonymous, TRAPS); - static void post_class_unload_events(void); -+ static void clean_metaspaces(); - public: - static ClassLoaderData* find_or_create(Handle class_loader, TRAPS); - static void purge(); -@@ -89,7 +91,7 @@ - static void classes_do(void f(Klass* const)); - static void loaded_classes_do(KlassClosure* klass_closure); - static void classes_unloading_do(void f(Klass* const)); -- static bool do_unloading(BoolObjectClosure* is_alive); -+ static bool do_unloading(BoolObjectClosure* is_alive, bool clean_alive); - - // CMS support. - static void remember_new_clds(bool remember) { _saved_head = (remember ? _head : NULL); } -@@ -105,6 +107,8 @@ - } - } - -+ static void free_deallocate_lists(); -+ - static void dump_on(outputStream * const out) PRODUCT_RETURN; - static void dump() { dump_on(tty); } - static void verify(); ---- jdk8/hotspot/src/share/vm/classfile/classLoaderExt.hpp 2015-01-27 08:42:53.979818064 +0100 -+++ jdk8/hotspot/src/share/vm/classfile/classLoaderExt.hpp 2015-01-27 08:43:45.234625316 +0100 -@@ -63,7 +63,19 @@ - ClassPathEntry* new_entry) { - ClassLoader::add_to_list(new_entry); - } -+ static void append_boot_classpath(ClassPathEntry* new_entry) { -+ 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 ---- jdk8/hotspot/src/share/vm/classfile/classLoader.hpp 2015-01-27 08:42:53.979818064 +0100 -+++ jdk8/hotspot/src/share/vm/classfile/classLoader.hpp 2015-01-27 08:43:45.233625339 +0100 -@@ -129,8 +129,8 @@ - bool _has_error; - bool _throw_exception; - volatile ClassPathEntry* _resolved_entry; -- ClassPathEntry* resolve_entry(TRAPS); - public: -+ ClassPathEntry* resolve_entry(TRAPS); - 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); ---- jdk8/hotspot/src/share/vm/classfile/dictionary.cpp 2015-01-27 08:42:53.979818064 +0100 -+++ jdk8/hotspot/src/share/vm/classfile/dictionary.cpp 2015-01-27 08:43:45.234625316 +0100 -@@ -223,7 +223,7 @@ - } - free_entry(probe); - ResourceMark rm; -- tty->print_cr("Removed error class: %s", ik->external_name()); -+ tty->print_cr("Preload Warning: Removed error class: %s", ik->external_name()); - continue; - } - ---- jdk8/hotspot/src/share/vm/classfile/javaClasses.cpp 2015-01-27 08:42:53.980818041 +0100 -+++ jdk8/hotspot/src/share/vm/classfile/javaClasses.cpp 2015-01-27 08:43:45.235625293 +0100 -@@ -41,6 +41,7 @@ - #include "oops/method.hpp" - #include "oops/symbol.hpp" - #include "oops/typeArrayOop.hpp" -+#include "prims/jvmtiRedefineClassesTrace.hpp" - #include "runtime/fieldDescriptor.hpp" - #include "runtime/handles.inline.hpp" - #include "runtime/interfaceSupport.hpp" -@@ -2775,12 +2776,35 @@ - return (Metadata*)mname->address_field(_vmtarget_offset); - } - -+bool java_lang_invoke_MemberName::is_method(oop mname) { -+ assert(is_instance(mname), "must be MemberName"); -+ return (flags(mname) & (MN_IS_METHOD | MN_IS_CONSTRUCTOR)) > 0; -+} -+ - #if INCLUDE_JVMTI - // Can be executed on VM thread only --void java_lang_invoke_MemberName::adjust_vmtarget(oop mname, Metadata* ref) { -- assert((is_instance(mname) && (flags(mname) & (MN_IS_METHOD | MN_IS_CONSTRUCTOR)) > 0), "wrong type"); -+void java_lang_invoke_MemberName::adjust_vmtarget(oop mname, Method* old_method, -+ Method* new_method, bool* trace_name_printed) { -+ assert(is_method(mname), "wrong type"); - assert(Thread::current()->is_VM_thread(), "not VM thread"); -- mname->address_field_put(_vmtarget_offset, (address)ref); -+ -+ Method* target = (Method*)mname->address_field(_vmtarget_offset); -+ if (target == old_method) { -+ mname->address_field_put(_vmtarget_offset, (address)new_method); -+ -+ if (RC_TRACE_IN_RANGE(0x00100000, 0x00400000)) { -+ if (!(*trace_name_printed)) { -+ // RC_TRACE_MESG macro has an embedded ResourceMark -+ RC_TRACE_MESG(("adjust: name=%s", -+ old_method->method_holder()->external_name())); -+ *trace_name_printed = true; -+ } -+ // RC_TRACE macro has an embedded ResourceMark -+ RC_TRACE(0x00400000, ("MemberName method update: %s(%s)", -+ new_method->name()->as_C_string(), -+ new_method->signature()->as_C_string())); -+ } -+ } - } - #endif // INCLUDE_JVMTI - ---- jdk8/hotspot/src/share/vm/classfile/javaClasses.hpp 2015-01-27 08:42:53.980818041 +0100 -+++ jdk8/hotspot/src/share/vm/classfile/javaClasses.hpp 2015-01-27 08:43:45.236625269 +0100 -@@ -1096,7 +1096,8 @@ - static Metadata* vmtarget(oop mname); - static void set_vmtarget(oop mname, Metadata* target); - #if INCLUDE_JVMTI -- static void adjust_vmtarget(oop mname, Metadata* target); -+ static void adjust_vmtarget(oop mname, Method* old_method, Method* new_method, -+ bool* trace_name_printed); - #endif // INCLUDE_JVMTI - - static intptr_t vmindex(oop mname); -@@ -1110,6 +1111,8 @@ - return obj != NULL && is_subclass(obj->klass()); - } - -+ static bool is_method(oop obj); -+ - // Relevant integer codes (keep these in synch. with MethodHandleNatives.Constants): - enum { - MN_IS_METHOD = 0x00010000, // method (not constructor) ---- jdk8/hotspot/src/share/vm/classfile/metadataOnStackMark.cpp 2015-01-27 08:42:53.980818041 +0100 -+++ jdk8/hotspot/src/share/vm/classfile/metadataOnStackMark.cpp 2015-01-27 08:43:45.236625269 +0100 -@@ -31,25 +31,23 @@ - #include "runtime/synchronizer.hpp" - #include "runtime/thread.hpp" - #include "services/threadService.hpp" --#include "utilities/growableArray.hpp" -+#include "utilities/chunkedList.hpp" - -+volatile MetadataOnStackBuffer* MetadataOnStackMark::_used_buffers = NULL; -+volatile MetadataOnStackBuffer* MetadataOnStackMark::_free_buffers = NULL; - --// Keep track of marked on-stack metadata so it can be cleared. --GrowableArray* _marked_objects = NULL; - NOT_PRODUCT(bool MetadataOnStackMark::_is_active = false;) - - // Walk metadata on the stack and mark it so that redefinition doesn't delete - // it. Class unloading also walks the previous versions and might try to - // delete it, so this class is used by class unloading also. --MetadataOnStackMark::MetadataOnStackMark() { -+MetadataOnStackMark::MetadataOnStackMark(bool visit_code_cache) { - assert(SafepointSynchronize::is_at_safepoint(), "sanity check"); -+ assert(_used_buffers == NULL, "sanity check"); - NOT_PRODUCT(_is_active = true;) -- if (_marked_objects == NULL) { -- _marked_objects = new (ResourceObj::C_HEAP, mtClass) GrowableArray(1000, true); -- } - - Threads::metadata_do(Metadata::mark_on_stack); -- if (JvmtiExport::has_redefined_a_class()) { -+ if (visit_code_cache) { - CodeCache::alive_nmethods_do(nmethod::mark_on_stack); - } - CompileBroker::mark_on_stack(); -@@ -62,15 +60,93 @@ - // Unmark everything that was marked. Can't do the same walk because - // redefine classes messes up the code cache so the set of methods - // might not be the same. -- for (int i = 0; i< _marked_objects->length(); i++) { -- _marked_objects->at(i)->set_on_stack(false); -+ -+ retire_buffer_for_thread(Thread::current()); -+ -+ MetadataOnStackBuffer* buffer = const_cast(_used_buffers); -+ while (buffer != NULL) { -+ // Clear on stack state for all metadata. -+ size_t size = buffer->size(); -+ for (size_t i = 0; i < size; i++) { -+ Metadata* md = buffer->at(i); -+ md->set_on_stack(false); -+ } -+ -+ MetadataOnStackBuffer* next = buffer->next_used(); -+ -+ // Move the buffer to the free list. -+ buffer->clear(); -+ buffer->set_next_used(NULL); -+ buffer->set_next_free(const_cast(_free_buffers)); -+ _free_buffers = buffer; -+ -+ // Step to next used buffer. -+ buffer = next; - } -- _marked_objects->clear(); // reuse growable array for next time. -+ -+ _used_buffers = NULL; -+ - NOT_PRODUCT(_is_active = false;) - } - -+void MetadataOnStackMark::retire_buffer(MetadataOnStackBuffer* buffer) { -+ if (buffer == NULL) { -+ return; -+ } -+ -+ MetadataOnStackBuffer* old_head; -+ -+ do { -+ old_head = const_cast(_used_buffers); -+ buffer->set_next_used(old_head); -+ } while (Atomic::cmpxchg_ptr(buffer, &_used_buffers, old_head) != old_head); -+} -+ -+void MetadataOnStackMark::retire_buffer_for_thread(Thread* thread) { -+ retire_buffer(thread->metadata_on_stack_buffer()); -+ thread->set_metadata_on_stack_buffer(NULL); -+} -+ -+bool MetadataOnStackMark::has_buffer_for_thread(Thread* thread) { -+ return thread->metadata_on_stack_buffer() != NULL; -+} -+ -+MetadataOnStackBuffer* MetadataOnStackMark::allocate_buffer() { -+ MetadataOnStackBuffer* allocated; -+ MetadataOnStackBuffer* new_head; -+ -+ do { -+ allocated = const_cast(_free_buffers); -+ if (allocated == NULL) { -+ break; -+ } -+ new_head = allocated->next_free(); -+ } while (Atomic::cmpxchg_ptr(new_head, &_free_buffers, allocated) != allocated); -+ -+ if (allocated == NULL) { -+ allocated = new MetadataOnStackBuffer(); -+ } -+ -+ assert(!allocated->is_full(), err_msg("Should not be full: " PTR_FORMAT, p2i(allocated))); -+ -+ return allocated; -+} -+ - // Record which objects are marked so we can unmark the same objects. --void MetadataOnStackMark::record(Metadata* m) { -+void MetadataOnStackMark::record(Metadata* m, Thread* thread) { - assert(_is_active, "metadata on stack marking is active"); -- _marked_objects->push(m); -+ -+ MetadataOnStackBuffer* buffer = thread->metadata_on_stack_buffer(); -+ -+ if (buffer != NULL && buffer->is_full()) { -+ retire_buffer(buffer); -+ buffer = NULL; -+ } -+ -+ if (buffer == NULL) { -+ buffer = allocate_buffer(); -+ thread->set_metadata_on_stack_buffer(buffer); -+ } -+ -+ buffer->push(m); - } ---- jdk8/hotspot/src/share/vm/classfile/metadataOnStackMark.hpp 2015-01-27 08:42:53.980818041 +0100 -+++ jdk8/hotspot/src/share/vm/classfile/metadataOnStackMark.hpp 2015-01-27 08:43:45.237625246 +0100 -@@ -26,9 +26,12 @@ - #define SHARE_VM_CLASSFILE_METADATAONSTACKMARK_HPP - - #include "memory/allocation.hpp" -+#include "utilities/chunkedList.hpp" - - class Metadata; - -+typedef ChunkedList MetadataOnStackBuffer; -+ - // Helper class to mark and unmark metadata used on the stack as either handles - // or executing methods, so that it can't be deleted during class redefinition - // and class unloading. -@@ -36,10 +39,20 @@ - // metadata during parsing, relocated methods, and methods in backtraces. - class MetadataOnStackMark : public StackObj { - NOT_PRODUCT(static bool _is_active;) -+ -+ static volatile MetadataOnStackBuffer* _used_buffers; -+ static volatile MetadataOnStackBuffer* _free_buffers; -+ -+ static MetadataOnStackBuffer* allocate_buffer(); -+ static void retire_buffer(MetadataOnStackBuffer* buffer); -+ - public: -- MetadataOnStackMark(); -+ MetadataOnStackMark(bool visit_code_cache); - ~MetadataOnStackMark(); -- static void record(Metadata* m); -+ -+ static void record(Metadata* m, Thread* thread); -+ static void retire_buffer_for_thread(Thread* thread); -+ static bool has_buffer_for_thread(Thread* thread); - }; - - #endif // SHARE_VM_CLASSFILE_METADATAONSTACKMARK_HPP ---- jdk8/hotspot/src/share/vm/classfile/systemDictionary.cpp 2015-01-27 08:42:53.980818041 +0100 -+++ jdk8/hotspot/src/share/vm/classfile/systemDictionary.cpp 2015-01-27 08:43:45.238625223 +0100 -@@ -1691,9 +1690,9 @@ - - // Assumes classes in the SystemDictionary are only unloaded at a safepoint - // Note: anonymous classes are not in the SD. --bool SystemDictionary::do_unloading(BoolObjectClosure* is_alive) { -+bool SystemDictionary::do_unloading(BoolObjectClosure* is_alive, bool clean_alive) { - // First, mark for unload all ClassLoaderData referencing a dead class loader. -- bool unloading_occurred = ClassLoaderDataGraph::do_unloading(is_alive); -+ bool unloading_occurred = ClassLoaderDataGraph::do_unloading(is_alive, clean_alive); - if (unloading_occurred) { - dictionary()->do_unloading(); - constraints()->purge_loader_constraints(); -@@ -1908,11 +1907,12 @@ - InstanceKlass::cast(WK_KLASS(Reference_klass))->set_reference_type(REF_OTHER); - InstanceRefKlass::update_nonstatic_oop_maps(WK_KLASS(Reference_klass)); - -- initialize_wk_klasses_through(WK_KLASS_ENUM_NAME(PhantomReference_klass), scan, CHECK); -+ initialize_wk_klasses_through(WK_KLASS_ENUM_NAME(Cleaner_klass), scan, CHECK); - InstanceKlass::cast(WK_KLASS(SoftReference_klass))->set_reference_type(REF_SOFT); - InstanceKlass::cast(WK_KLASS(WeakReference_klass))->set_reference_type(REF_WEAK); - InstanceKlass::cast(WK_KLASS(FinalReference_klass))->set_reference_type(REF_FINAL); - InstanceKlass::cast(WK_KLASS(PhantomReference_klass))->set_reference_type(REF_PHANTOM); -+ InstanceKlass::cast(WK_KLASS(Cleaner_klass))->set_reference_type(REF_CLEANER); - - // JSR 292 classes - WKID jsr292_group_start = WK_KLASS_ENUM_NAME(MethodHandle_klass); -@@ -2664,7 +2664,7 @@ - class_loader->klass() : (Klass*)NULL); - event.commit(); - } --#endif /* INCLUDE_TRACE */ -+#endif // INCLUDE_TRACE - } - - #ifndef PRODUCT ---- jdk8/hotspot/src/share/vm/classfile/systemDictionary.hpp 2015-01-27 08:42:53.980818041 +0100 -+++ jdk8/hotspot/src/share/vm/classfile/systemDictionary.hpp 2015-01-27 08:43:45.238625223 +0100 -@@ -128,6 +128,7 @@ - do_klass(WeakReference_klass, java_lang_ref_WeakReference, Pre ) \ - do_klass(FinalReference_klass, java_lang_ref_FinalReference, Pre ) \ - do_klass(PhantomReference_klass, java_lang_ref_PhantomReference, Pre ) \ -+ do_klass(Cleaner_klass, sun_misc_Cleaner, Pre ) \ - do_klass(Finalizer_klass, java_lang_ref_Finalizer, Pre ) \ - \ - do_klass(Thread_klass, java_lang_Thread, Pre ) \ -@@ -175,6 +176,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. */ \ -@@ -339,7 +342,7 @@ - - // Unload (that is, break root links to) all unmarked classes and - // loaders. Returns "true" iff something was unloaded. -- static bool do_unloading(BoolObjectClosure* is_alive); -+ static bool do_unloading(BoolObjectClosure* is_alive, bool clean_alive = true); - - // Used by DumpSharedSpaces only to remove classes that failed verification - static void remove_classes_in_error_state(); ---- jdk8/hotspot/src/share/vm/classfile/verifier.cpp 2015-01-27 08:42:53.980818041 +0100 -+++ jdk8/hotspot/src/share/vm/classfile/verifier.cpp 2015-01-27 08:43:45.239625200 +0100 -@@ -1556,14 +1556,14 @@ - case Bytecodes::_invokespecial : - case Bytecodes::_invokestatic : - verify_invoke_instructions( -- &bcs, code_length, ¤t_frame, -- &this_uninit, return_type, cp, CHECK_VERIFY(this)); -+ &bcs, code_length, ¤t_frame, (bci >= ex_min && bci < ex_max), -+ &this_uninit, return_type, cp, &stackmap_table, CHECK_VERIFY(this)); - no_control_flow = false; break; - case Bytecodes::_invokeinterface : - case Bytecodes::_invokedynamic : - verify_invoke_instructions( -- &bcs, code_length, ¤t_frame, -- &this_uninit, return_type, cp, CHECK_VERIFY(this)); -+ &bcs, code_length, ¤t_frame, (bci >= ex_min && bci < ex_max), -+ &this_uninit, return_type, cp, &stackmap_table, CHECK_VERIFY(this)); - no_control_flow = false; break; - case Bytecodes::_new : - { -@@ -2411,8 +2411,9 @@ - - void ClassVerifier::verify_invoke_init( - RawBytecodeStream* bcs, u2 ref_class_index, VerificationType ref_class_type, -- StackMapFrame* current_frame, u4 code_length, bool *this_uninit, -- constantPoolHandle cp, TRAPS) { -+ StackMapFrame* current_frame, u4 code_length, bool in_try_block, -+ bool *this_uninit, constantPoolHandle cp, StackMapTable* stackmap_table, -+ TRAPS) { - u2 bci = bcs->bci(); - VerificationType type = current_frame->pop_stack( - VerificationType::reference_check(), CHECK_VERIFY(this)); -@@ -2428,9 +2429,10 @@ - return; - } - -- // Check if this call is done from inside of a TRY block. If so, make -- // sure that all catch clause paths end in a throw. Otherwise, this -- // can result in returning an incomplete object. -+ // If this invokespecial call is done from inside of a TRY block then make -+ // sure that all catch clause paths end in a throw. Otherwise, this can -+ // result in returning an incomplete object. -+ if (in_try_block) { - ExceptionTable exhandlers(_method()); - int exlength = exhandlers.length(); - for(int i = 0; i < exlength; i++) { -@@ -2451,6 +2453,13 @@ - } - } - -+ // Check the exception handler target stackmaps with the locals from the -+ // incoming stackmap (before initialize_object() changes them to outgoing -+ // state). -+ verify_exception_handler_targets(bci, true, current_frame, -+ stackmap_table, CHECK_VERIFY(this)); -+ } // in_try_block -+ - current_frame->initialize_object(type, current_type()); - *this_uninit = true; - } else if (type.is_uninitialized()) { -@@ -2503,6 +2512,13 @@ - } - } - } -+ // Check the exception handler target stackmaps with the locals from the -+ // incoming stackmap (before initialize_object() changes them to outgoing -+ // state). -+ if (in_try_block) { -+ verify_exception_handler_targets(bci, *this_uninit, current_frame, -+ stackmap_table, CHECK_VERIFY(this)); -+ } - current_frame->initialize_object(type, new_class_type); - } else { - verify_error(ErrorContext::bad_type(bci, current_frame->stack_top_ctx()), -@@ -2531,8 +2547,8 @@ - - void ClassVerifier::verify_invoke_instructions( - RawBytecodeStream* bcs, u4 code_length, StackMapFrame* current_frame, -- bool *this_uninit, VerificationType return_type, -- constantPoolHandle cp, TRAPS) { -+ bool in_try_block, bool *this_uninit, VerificationType return_type, -+ constantPoolHandle cp, StackMapTable* stackmap_table, TRAPS) { - // Make sure the constant pool item is the right type - u2 index = bcs->get_index_u2(); - Bytecodes::Code opcode = bcs->raw_code(); -@@ -2702,7 +2718,8 @@ - opcode != Bytecodes::_invokedynamic) { - if (method_name == vmSymbols::object_initializer_name()) { // method - verify_invoke_init(bcs, index, ref_class_type, current_frame, -- code_length, this_uninit, cp, CHECK_VERIFY(this)); -+ code_length, in_try_block, this_uninit, cp, stackmap_table, -+ CHECK_VERIFY(this)); - } else { // other methods - // Ensures that target class is assignable to method class. - if (opcode == Bytecodes::_invokespecial) { ---- jdk8/hotspot/src/share/vm/classfile/verifier.hpp 2015-01-27 08:42:53.981818018 +0100 -+++ jdk8/hotspot/src/share/vm/classfile/verifier.hpp 2015-01-27 08:43:45.240625176 +0100 -@@ -301,8 +301,9 @@ - - void verify_invoke_init( - RawBytecodeStream* bcs, u2 ref_index, VerificationType ref_class_type, -- StackMapFrame* current_frame, u4 code_length, bool* this_uninit, -- constantPoolHandle cp, TRAPS); -+ StackMapFrame* current_frame, u4 code_length, bool in_try_block, -+ bool* this_uninit, constantPoolHandle cp, StackMapTable* stackmap_table, -+ TRAPS); - - // Used by ends_in_athrow() to push all handlers that contain bci onto - // the handler_stack, if the handler is not already on the stack. -@@ -316,8 +317,8 @@ - - void verify_invoke_instructions( - RawBytecodeStream* bcs, u4 code_length, StackMapFrame* current_frame, -- bool* this_uninit, VerificationType return_type, -- constantPoolHandle cp, TRAPS); -+ bool in_try_block, bool* this_uninit, VerificationType return_type, -+ constantPoolHandle cp, StackMapTable* stackmap_table, TRAPS); - - VerificationType get_newarray_type(u2 index, u2 bci, TRAPS); - void verify_anewarray(u2 bci, u2 index, constantPoolHandle cp, ---- jdk8/hotspot/src/share/vm/classfile/vmSymbols.hpp 2015-01-27 08:42:53.981818018 +0100 -+++ jdk8/hotspot/src/share/vm/classfile/vmSymbols.hpp 2015-01-27 08:43:45.240625176 +0100 -@@ -79,6 +79,7 @@ - template(java_lang_ref_WeakReference, "java/lang/ref/WeakReference") \ - template(java_lang_ref_FinalReference, "java/lang/ref/FinalReference") \ - template(java_lang_ref_PhantomReference, "java/lang/ref/PhantomReference") \ -+ template(sun_misc_Cleaner, "sun/misc/Cleaner") \ - template(java_lang_ref_Finalizer, "java/lang/ref/Finalizer") \ - template(java_lang_reflect_AccessibleObject, "java/lang/reflect/AccessibleObject") \ - template(java_lang_reflect_Method, "java/lang/reflect/Method") \ -@@ -116,6 +117,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 */ \ ---- jdk8/hotspot/src/share/vm/code/dependencies.cpp 2015-01-27 08:42:53.981818018 +0100 -+++ jdk8/hotspot/src/share/vm/code/dependencies.cpp 2015-01-27 08:43:45.241625153 +0100 -@@ -560,7 +560,7 @@ - put_star = !Dependencies::is_concrete_klass((Klass*)arg.metadata_value()); - } else if (arg.is_method()) { - what = "method "; -- put_star = !Dependencies::is_concrete_method((Method*)arg.metadata_value()); -+ put_star = !Dependencies::is_concrete_method((Method*)arg.metadata_value(), NULL); - } else if (arg.is_klass()) { - what = "class "; - } else { -@@ -845,8 +845,8 @@ - // Static methods don't override non-static so punt - return true; - } -- if ( !Dependencies::is_concrete_method(lm) -- && !Dependencies::is_concrete_method(m) -+ if ( !Dependencies::is_concrete_method(lm, k) -+ && !Dependencies::is_concrete_method(m, ctxk) - && lm->method_holder()->is_subtype_of(m->method_holder())) - // Method m is overridden by lm, but both are non-concrete. - return true; -@@ -879,9 +879,20 @@ - bool is_witness(Klass* k) { - if (doing_subtype_search()) { - return Dependencies::is_concrete_klass(k); -+ } else if (!k->oop_is_instance()) { -+ return false; // no methods to find in an array type - } else { -- Method* m = InstanceKlass::cast(k)->find_method(_name, _signature); -- if (m == NULL || !Dependencies::is_concrete_method(m)) return false; -+ // Search class hierarchy first. -+ Method* m = InstanceKlass::cast(k)->find_instance_method(_name, _signature); -+ if (!Dependencies::is_concrete_method(m, k)) { -+ // Check interface defaults also, if any exist. -+ Array* default_methods = InstanceKlass::cast(k)->default_methods(); -+ if (default_methods == NULL) -+ return false; -+ m = InstanceKlass::cast(k)->find_method(default_methods, _name, _signature); -+ if (!Dependencies::is_concrete_method(m, NULL)) -+ return false; -+ } - _found_methods[_num_participants] = m; - // Note: If add_participant(k) is called, - // the method m will already be memoized for it. -@@ -1085,7 +1096,7 @@ - Klass* chain; // scratch variable - #define ADD_SUBCLASS_CHAIN(k) { \ - assert(chaini < CHAINMAX, "oob"); \ -- chain = InstanceKlass::cast(k)->subklass(); \ -+ chain = k->subklass(); \ - if (chain != NULL) chains[chaini++] = chain; } - - // Look for non-abstract subclasses. -@@ -1096,6 +1107,7 @@ - // (Their subclasses are additional indirect implementors. - // See InstanceKlass::add_implementor.) - // (Note: nof_implementors is always zero for non-interfaces.) -+ if (top_level_call) { - int nof_impls = InstanceKlass::cast(context_type)->nof_implementors(); - if (nof_impls > 1) { - // Avoid this case: *I.m > { A.m, C }; B.m > C -@@ -1127,6 +1139,7 @@ - ADD_SUBCLASS_CHAIN(impl); - } - } -+ } - - // Recursively process each non-trivial sibling chain. - while (chaini > 0) { -@@ -1172,15 +1185,17 @@ - return true; - } - --bool Dependencies::is_concrete_method(Method* m) { -- // Statics are irrelevant to virtual call sites. -- if (m->is_static()) return false; -- -- // We could also return false if m does not yet appear to be -- // executed, if the VM version supports this distinction also. -- // Default methods are considered "concrete" as well. -- return !m->is_abstract() && -- !m->is_overpass(); // error functions aren't concrete -+bool Dependencies::is_concrete_method(Method* m, Klass * k) { -+ // NULL is not a concrete method, -+ // statics are irrelevant to virtual call sites, -+ // abstract methods are not concrete, -+ // overpass (error) methods are not concrete if k is abstract -+ // -+ // note "true" is conservative answer -- -+ // overpass clause is false if k == NULL, implies return true if -+ // answer depends on overpass clause. -+ return ! ( m == NULL || m -> is_static() || m -> is_abstract() || -+ m->is_overpass() && k != NULL && k -> is_abstract() ); - } - - -@@ -1205,16 +1220,6 @@ - return true; - } - --bool Dependencies::is_concrete_method(ciMethod* m) { -- // Statics are irrelevant to virtual call sites. -- if (m->is_static()) return false; -- -- // We could also return false if m does not yet appear to be -- // executed, if the VM version supports this distinction also. -- return !m->is_abstract(); --} -- -- - bool Dependencies::has_finalizable_subclass(ciInstanceKlass* k) { - return k->has_finalizable_subclass(); - } -@@ -1428,7 +1433,7 @@ - Klass* wit = wf.find_witness_definer(ctxk); - if (wit != NULL) return NULL; // Too many witnesses. - Method* fm = wf.found_method(0); // Will be NULL if num_parts == 0. -- if (Dependencies::is_concrete_method(m)) { -+ if (Dependencies::is_concrete_method(m, ctxk)) { - if (fm == NULL) { - // It turns out that m was always the only implementation. - fm = m; -@@ -1458,61 +1463,6 @@ - return wf.find_witness_definer(ctxk, changes); - } - --// Find the set of all non-abstract methods under ctxk that match m[0]. --// (The method m[0] must be defined or inherited in ctxk.) --// Include m itself in the set, unless it is abstract. --// Fill the given array m[0..(mlen-1)] with this set, and return the length. --// (The length may be zero if no concrete methods are found anywhere.) --// If there are too many concrete methods to fit in marray, return -1. --int Dependencies::find_exclusive_concrete_methods(Klass* ctxk, -- int mlen, -- Method* marray[]) { -- Method* m0 = marray[0]; -- ClassHierarchyWalker wf(m0); -- assert(wf.check_method_context(ctxk, m0), "proper context"); -- wf.record_witnesses(mlen); -- bool participants_hide_witnesses = true; -- Klass* wit = wf.find_witness_definer(ctxk); -- if (wit != NULL) return -1; // Too many witnesses. -- int num = wf.num_participants(); -- assert(num <= mlen, "oob"); -- // Keep track of whether m is also part of the result set. -- int mfill = 0; -- assert(marray[mfill] == m0, "sanity"); -- if (Dependencies::is_concrete_method(m0)) -- mfill++; // keep m0 as marray[0], the first result -- for (int i = 0; i < num; i++) { -- Method* fm = wf.found_method(i); -- if (fm == m0) continue; // Already put this guy in the list. -- if (mfill == mlen) { -- return -1; // Oops. Too many methods after all! -- } -- marray[mfill++] = fm; -- } --#ifndef PRODUCT -- // Make sure the dependency mechanism will pass this discovery: -- if (VerifyDependencies) { -- // Turn off dependency tracing while actually testing deps. -- FlagSetting fs(TraceDependencies, false); -- switch (mfill) { -- case 1: -- guarantee(NULL == (void *)check_unique_concrete_method(ctxk, marray[0]), -- "verify dep."); -- break; -- case 2: -- guarantee(NULL == (void *) -- check_exclusive_concrete_methods(ctxk, marray[0], marray[1]), -- "verify dep."); -- break; -- default: -- ShouldNotReachHere(); // mlen > 2 yet supported -- } -- } --#endif //PRODUCT -- return mfill; --} -- -- - Klass* Dependencies::check_has_no_finalizable_subclasses(Klass* ctxk, KlassDepChange* changes) { - Klass* search_at = ctxk; - if (changes != NULL) ---- jdk8/hotspot/src/share/vm/code/dependencies.hpp 2015-01-27 08:42:53.981818018 +0100 -+++ jdk8/hotspot/src/share/vm/code/dependencies.hpp 2015-01-27 08:43:45.242625130 +0100 -@@ -287,7 +287,7 @@ - // In that case, there would be a middle ground between concrete - // and abstract (as defined by the Java language and VM). - static bool is_concrete_klass(Klass* k); // k is instantiable -- static bool is_concrete_method(Method* m); // m is invocable -+ static bool is_concrete_method(Method* m, Klass* k); // m is invocable - static Klass* find_finalizable_subclass(Klass* k); - - // These versions of the concreteness queries work through the CI. -@@ -301,7 +301,6 @@ - // not go back into the VM to get their value; they must cache the - // bit in the CI, either eagerly or lazily.) - static bool is_concrete_klass(ciInstanceKlass* k); // k appears instantiable -- static bool is_concrete_method(ciMethod* m); // m appears invocable - static bool has_finalizable_subclass(ciInstanceKlass* k); - - // As a general rule, it is OK to compile under the assumption that -@@ -348,7 +347,6 @@ - static Klass* find_unique_concrete_subtype(Klass* ctxk); - static Method* find_unique_concrete_method(Klass* ctxk, Method* m); - static int find_exclusive_concrete_subtypes(Klass* ctxk, int klen, Klass* k[]); -- static int find_exclusive_concrete_methods(Klass* ctxk, int mlen, Method* m[]); - - // Create the encoding which will be stored in an nmethod. - void encode_content_bytes(); ---- jdk8/hotspot/src/share/vm/code/nmethod.cpp 2015-01-27 08:42:53.981818018 +0100 -+++ jdk8/hotspot/src/share/vm/code/nmethod.cpp 2015-01-27 08:43:45.243625106 +0100 -@@ -1741,11 +1741,17 @@ - set_unload_reported(); - } - --void static clean_ic_if_metadata_is_dead(CompiledIC *ic, BoolObjectClosure *is_alive) { -+void static clean_ic_if_metadata_is_dead(CompiledIC *ic, BoolObjectClosure *is_alive, bool mark_on_stack) { - if (ic->is_icholder_call()) { - // The only exception is compiledICHolder oops which may - // yet be marked below. (We check this further below). - CompiledICHolder* cichk_oop = ic->cached_icholder(); -+ -+ if (mark_on_stack) { -+ Metadata::mark_on_stack(cichk_oop->holder_method()); -+ Metadata::mark_on_stack(cichk_oop->holder_klass()); -+ } -+ - if (cichk_oop->holder_method()->method_holder()->is_loader_alive(is_alive) && - cichk_oop->holder_klass()->is_loader_alive(is_alive)) { - return; -@@ -1753,6 +1759,10 @@ - } else { - Metadata* ic_oop = ic->cached_metadata(); - if (ic_oop != NULL) { -+ if (mark_on_stack) { -+ Metadata::mark_on_stack(ic_oop); -+ } -+ - if (ic_oop->is_klass()) { - if (((Klass*)ic_oop)->is_loader_alive(is_alive)) { - return; -@@ -1813,7 +1823,7 @@ - while(iter.next()) { - if (iter.type() == relocInfo::virtual_call_type) { - CompiledIC *ic = CompiledIC_at(&iter); -- clean_ic_if_metadata_is_dead(ic, is_alive); -+ clean_ic_if_metadata_is_dead(ic, is_alive, false); - } - } - } -@@ -1881,6 +1891,53 @@ - return clean_if_nmethod_is_unloaded(csc, csc->destination(), is_alive, from); - } - -+bool nmethod::unload_if_dead_at(RelocIterator* iter_at_oop, BoolObjectClosure *is_alive, bool unloading_occurred) { -+ assert(iter_at_oop->type() == relocInfo::oop_type, "Wrong relocation type"); -+ -+ oop_Relocation* r = iter_at_oop->oop_reloc(); -+ // Traverse those oops directly embedded in the code. -+ // Other oops (oop_index>0) are seen as part of scopes_oops. -+ assert(1 == (r->oop_is_immediate()) + -+ (r->oop_addr() >= oops_begin() && r->oop_addr() < oops_end()), -+ "oop must be found in exactly one place"); -+ if (r->oop_is_immediate() && r->oop_value() != NULL) { -+ // Unload this nmethod if the oop is dead. -+ if (can_unload(is_alive, r->oop_addr(), unloading_occurred)) { -+ return true;; -+ } -+ } -+ -+ return false; -+} -+ -+void nmethod::mark_metadata_on_stack_at(RelocIterator* iter_at_metadata) { -+ assert(iter_at_metadata->type() == relocInfo::metadata_type, "Wrong relocation type"); -+ -+ metadata_Relocation* r = iter_at_metadata->metadata_reloc(); -+ // In this metadata, we must only follow those metadatas directly embedded in -+ // the code. Other metadatas (oop_index>0) are seen as part of -+ // the metadata section below. -+ assert(1 == (r->metadata_is_immediate()) + -+ (r->metadata_addr() >= metadata_begin() && r->metadata_addr() < metadata_end()), -+ "metadata must be found in exactly one place"); -+ if (r->metadata_is_immediate() && r->metadata_value() != NULL) { -+ Metadata* md = r->metadata_value(); -+ if (md != _method) Metadata::mark_on_stack(md); -+ } -+} -+ -+void nmethod::mark_metadata_on_stack_non_relocs() { -+ // Visit the metadata section -+ for (Metadata** p = metadata_begin(); p < metadata_end(); p++) { -+ if (*p == Universe::non_oop_word() || *p == NULL) continue; // skip non-oops -+ Metadata* md = *p; -+ Metadata::mark_on_stack(md); -+ } -+ -+ // Visit metadata not embedded in the other places. -+ if (_method != NULL) Metadata::mark_on_stack(_method); -+} -+ - bool nmethod::do_unloading_parallel(BoolObjectClosure* is_alive, bool unloading_occurred) { - ResourceMark rm; - -@@ -1910,6 +1967,11 @@ - unloading_occurred = true; - } - -+ // When class redefinition is used all metadata in the CodeCache has to be recorded, -+ // so that unused "previous versions" can be purged. Since walking the CodeCache can -+ // be expensive, the "mark on stack" is piggy-backed on this parallel unloading code. -+ bool mark_metadata_on_stack = a_class_was_redefined; -+ - // Exception cache - clean_exception_cache(is_alive); - -@@ -1925,7 +1987,7 @@ - if (unloading_occurred) { - // If class unloading occurred we first iterate over all inline caches and - // clear ICs where the cached oop is referring to an unloaded klass or method. -- clean_ic_if_metadata_is_dead(CompiledIC_at(&iter), is_alive); -+ clean_ic_if_metadata_is_dead(CompiledIC_at(&iter), is_alive, mark_metadata_on_stack); - } - - postponed |= clean_if_nmethod_is_unloaded(CompiledIC_at(&iter), is_alive, this); -@@ -1941,23 +2003,20 @@ - - case relocInfo::oop_type: - if (!is_unloaded) { -- // Unload check -- oop_Relocation* r = iter.oop_reloc(); -- // Traverse those oops directly embedded in the code. -- // Other oops (oop_index>0) are seen as part of scopes_oops. -- assert(1 == (r->oop_is_immediate()) + -- (r->oop_addr() >= oops_begin() && r->oop_addr() < oops_end()), -- "oop must be found in exactly one place"); -- if (r->oop_is_immediate() && r->oop_value() != NULL) { -- if (can_unload(is_alive, r->oop_addr(), unloading_occurred)) { -- is_unloaded = true; -- } -- } -+ is_unloaded = unload_if_dead_at(&iter, is_alive, unloading_occurred); - } - break; - -+ case relocInfo::metadata_type: -+ if (mark_metadata_on_stack) { -+ mark_metadata_on_stack_at(&iter); - } - } -+ } -+ -+ if (mark_metadata_on_stack) { -+ mark_metadata_on_stack_non_relocs(); -+ } - - if (is_unloaded) { - return postponed; -@@ -2106,7 +2165,7 @@ - while (iter.next()) { - if (iter.type() == relocInfo::metadata_type ) { - metadata_Relocation* r = iter.metadata_reloc(); -- // In this lmetadata, we must only follow those metadatas directly embedded in -+ // In this metadata, we must only follow those metadatas directly embedded in - // the code. Other metadatas (oop_index>0) are seen as part of - // the metadata section below. - assert(1 == (r->metadata_is_immediate()) + -@@ -2140,7 +2199,7 @@ - f(md); - } - -- // Call function Method*, not embedded in these other places. -+ // Visit metadata not embedded in the other places. - if (_method != NULL) f(_method); - } - ---- jdk8/hotspot/src/share/vm/code/nmethod.hpp 2015-01-27 08:42:53.982817994 +0100 -+++ jdk8/hotspot/src/share/vm/code/nmethod.hpp 2015-01-27 08:43:45.243625106 +0100 -@@ -614,9 +614,16 @@ - // The parallel versions are used by G1. - bool do_unloading_parallel(BoolObjectClosure* is_alive, bool unloading_occurred); - void do_unloading_parallel_postponed(BoolObjectClosure* is_alive, bool unloading_occurred); -+ -+ private: - // Unload a nmethod if the *root object is dead. - bool can_unload(BoolObjectClosure* is_alive, oop* root, bool unloading_occurred); -+ bool unload_if_dead_at(RelocIterator *iter_at_oop, BoolObjectClosure* is_alive, bool unloading_occurred); -+ -+ void mark_metadata_on_stack_at(RelocIterator* iter_at_metadata); -+ void mark_metadata_on_stack_non_relocs(); - -+ public: - void preserve_callee_argument_oops(frame fr, const RegisterMap *reg_map, - OopClosure* f); - void oops_do(OopClosure* f) { oops_do(f, false); } ---- jdk8/hotspot/src/share/vm/compiler/compileBroker.cpp 2015-01-27 08:42:53.982817994 +0100 -+++ jdk8/hotspot/src/share/vm/compiler/compileBroker.cpp 2015-01-27 08:43:45.245625060 +0100 -@@ -183,9 +183,8 @@ - - long CompileBroker::_peak_compilation_time = 0; - --CompileQueue* CompileBroker::_c2_method_queue = NULL; --CompileQueue* CompileBroker::_c1_method_queue = NULL; --CompileTask* CompileBroker::_task_free_list = NULL; -+CompileQueue* CompileBroker::_c2_compile_queue = NULL; -+CompileQueue* CompileBroker::_c1_compile_queue = NULL; - - GrowableArray* CompileBroker::_compiler_threads = NULL; - -@@ -253,13 +252,56 @@ - - // By convention, the compiling thread is responsible for - // recycling a non-blocking CompileTask. -- CompileBroker::free_task(task); -+ CompileTask::free(task); - } - } - - --// ------------------------------------------------------------------ --// CompileTask::initialize -+CompileTask* CompileTask::_task_free_list = NULL; -+#ifdef ASSERT -+int CompileTask::_num_allocated_tasks = 0; -+#endif -+/** -+ * Allocate a CompileTask, from the free list if possible. -+ */ -+CompileTask* CompileTask::allocate() { -+ MutexLocker locker(CompileTaskAlloc_lock); -+ CompileTask* task = NULL; -+ -+ if (_task_free_list != NULL) { -+ task = _task_free_list; -+ _task_free_list = task->next(); -+ task->set_next(NULL); -+ } else { -+ task = new CompileTask(); -+ DEBUG_ONLY(_num_allocated_tasks++;) -+ assert (_num_allocated_tasks < 10000, "Leaking compilation tasks?"); -+ task->set_next(NULL); -+ task->set_is_free(true); -+ } -+ assert(task->is_free(), "Task must be free."); -+ task->set_is_free(false); -+ return task; -+} -+ -+ -+/** -+ * Add a task to the free list. -+ */ -+void CompileTask::free(CompileTask* task) { -+ MutexLocker locker(CompileTaskAlloc_lock); -+ if (!task->is_free()) { -+ task->set_code(NULL); -+ assert(!task->lock()->is_locked(), "Should not be locked when freed"); -+ JNIHandles::destroy_global(task->_method_holder); -+ JNIHandles::destroy_global(task->_hot_method_holder); -+ -+ task->set_is_free(true); -+ task->set_next(_task_free_list); -+ _task_free_list = task; -+ } -+} -+ - void CompileTask::initialize(int compile_id, - methodHandle method, - int osr_bci, -@@ -318,15 +360,6 @@ - if (nm == NULL) _code_handle = NULL; // drop the handle also - } - --// ------------------------------------------------------------------ --// CompileTask::free --void CompileTask::free() { -- set_code(NULL); -- assert(!_lock->is_locked(), "Should not be locked when freed"); -- JNIHandles::destroy_global(_method_holder); -- JNIHandles::destroy_global(_hot_method_holder); --} -- - - void CompileTask::mark_on_stack() { - // Mark these methods as something redefine classes cannot remove. -@@ -594,9 +627,12 @@ - - - --// Add a CompileTask to a CompileQueue -+/** -+ * Add a CompileTask to a CompileQueue -+ */ - void CompileQueue::add(CompileTask* task) { - assert(lock()->owned_by_self(), "must own lock"); -+ assert(!CompileBroker::is_compilation_disabled_forever(), "Do not add task if compilation is turned off forever"); - - task->set_next(NULL); - task->set_prev(NULL); -@@ -618,9 +654,7 @@ - // Mark the method as being in the compile queue. - task->method()->set_queued_for_compilation(); - -- if (CIPrintCompileQueue) { -- print(); -- } -+ NOT_PRODUCT(print();) - - if (LogCompilation && xtty != NULL) { - task->log_task_queued(); -@@ -630,14 +664,32 @@ - lock()->notify_all(); - } - --void CompileQueue::delete_all() { -- assert(lock()->owned_by_self(), "must own lock"); -- if (_first != NULL) { -- for (CompileTask* task = _first; task != NULL; task = task->next()) { -- delete task; -+/** -+ * Empties compilation queue by putting all compilation tasks onto -+ * a freelist. Furthermore, the method wakes up all threads that are -+ * waiting on a compilation task to finish. This can happen if background -+ * compilation is disabled. -+ */ -+void CompileQueue::free_all() { -+ MutexLocker mu(lock()); -+ CompileTask* next = _first; -+ -+ // Iterate over all tasks in the compile queue -+ while (next != NULL) { -+ CompileTask* current = next; -+ next = current->next(); -+ { -+ // Wake up thread that blocks on the compile task. -+ MutexLocker ct_lock(current->lock()); -+ current->lock()->notify(); - } -- _first = NULL; -+ // Put the task back on the freelist. -+ CompileTask::free(current); - } -+ _first = NULL; -+ -+ // Wake up all threads that block on the queue. -+ lock()->notify_all(); - } - - // ------------------------------------------------------------------ -@@ -767,9 +819,13 @@ - } - } - --// ------------------------------------------------------------------ --// CompileQueue::print -+#ifndef PRODUCT -+/** -+ * Print entire compilation queue. -+ */ - void CompileQueue::print() { -+ if (CIPrintCompileQueue) { -+ ttyLocker ttyl; - tty->print_cr("Contents of %s", name()); - tty->print_cr("----------------------"); - CompileTask* task = _first; -@@ -779,6 +835,8 @@ - } - tty->print_cr("----------------------"); - } -+} -+#endif // PRODUCT - - CompilerCounters::CompilerCounters(const char* thread_name, int instance, TRAPS) { - -@@ -851,9 +909,6 @@ - _compilers[1] = new SharkCompiler(); - #endif // SHARK - -- // Initialize the CompileTask free list -- _task_free_list = NULL; -- - // Start the CompilerThreads - init_compiler_threads(c1_count, c2_count); - // totalTime performance counter is always created as it is required -@@ -1046,11 +1101,11 @@ - #endif // !ZERO && !SHARK - // Initialize the compilation queue - if (c2_compiler_count > 0) { -- _c2_method_queue = new CompileQueue("C2MethodQueue", MethodCompileQueue_lock); -+ _c2_compile_queue = new CompileQueue("C2 CompileQueue", MethodCompileQueue_lock); - _compilers[1]->set_num_compiler_threads(c2_compiler_count); - } - if (c1_compiler_count > 0) { -- _c1_method_queue = new CompileQueue("C1MethodQueue", MethodCompileQueue_lock); -+ _c1_compile_queue = new CompileQueue("C1 CompileQueue", MethodCompileQueue_lock); - _compilers[0]->set_num_compiler_threads(c1_compiler_count); - } - -@@ -1065,7 +1120,7 @@ - sprintf(name_buffer, "C2 CompilerThread%d", i); - CompilerCounters* counters = new CompilerCounters("compilerThread", i, CHECK); - // Shark and C2 -- CompilerThread* new_thread = make_compiler_thread(name_buffer, _c2_method_queue, counters, _compilers[1], CHECK); -+ CompilerThread* new_thread = make_compiler_thread(name_buffer, _c2_compile_queue, counters, _compilers[1], CHECK); - _compiler_threads->append(new_thread); - } - -@@ -1074,7 +1129,7 @@ - sprintf(name_buffer, "C1 CompilerThread%d", i); - CompilerCounters* counters = new CompilerCounters("compilerThread", i, CHECK); - // C1 -- CompilerThread* new_thread = make_compiler_thread(name_buffer, _c1_method_queue, counters, _compilers[0], CHECK); -+ CompilerThread* new_thread = make_compiler_thread(name_buffer, _c1_compile_queue, counters, _compilers[0], CHECK); - _compiler_threads->append(new_thread); - } - -@@ -1084,14 +1139,19 @@ - } - - --// Set the methods on the stack as on_stack so that redefine classes doesn't --// reclaim them -+/** -+ * Set the methods on the stack as on_stack so that redefine classes doesn't -+ * reclaim them. This method is executed at a safepoint. -+ */ - void CompileBroker::mark_on_stack() { -- if (_c2_method_queue != NULL) { -- _c2_method_queue->mark_on_stack(); -+ assert(SafepointSynchronize::is_at_safepoint(), "sanity check"); -+ // Since we are at a safepoint, we do not need a lock to access -+ // the compile queues. -+ if (_c2_compile_queue != NULL) { -+ _c2_compile_queue->mark_on_stack(); - } -- if (_c1_method_queue != NULL) { -- _c1_method_queue->mark_on_stack(); -+ if (_c1_compile_queue != NULL) { -+ _c1_compile_queue->mark_on_stack(); - } - } - -@@ -1154,7 +1214,7 @@ - - // If this method is already in the compile queue, then - // we do not block the current thread. -- if (compilation_is_in_queue(method, osr_bci)) { -+ if (compilation_is_in_queue(method)) { - // We may want to decay our counter a bit here to prevent - // multiple denied requests for compilation. This is an - // open compilation policy issue. Note: The other possibility, -@@ -1193,7 +1253,7 @@ - // Make sure the method has not slipped into the queues since - // last we checked; note that those checks were "fast bail-outs". - // Here we need to be more careful, see 14012000 below. -- if (compilation_is_in_queue(method, osr_bci)) { -+ if (compilation_is_in_queue(method)) { - return; - } - -@@ -1214,7 +1274,7 @@ - } - - // Should this thread wait for completion of the compile? -- blocking = is_compile_blocking(method, osr_bci); -+ blocking = is_compile_blocking(); - - // We will enter the compilation in the queue. - // 14012000: Note that this sets the queued_for_compile bits in -@@ -1406,19 +1466,17 @@ - } - - --// ------------------------------------------------------------------ --// CompileBroker::compilation_is_in_queue --// --// See if this compilation is already requested. --// --// Implementation note: there is only a single "is in queue" bit --// for each method. This means that the check below is overly --// conservative in the sense that an osr compilation in the queue --// will block a normal compilation from entering the queue (and vice --// versa). This can be remedied by a full queue search to disambiguate --// cases. If it is deemed profitible, this may be done. --bool CompileBroker::compilation_is_in_queue(methodHandle method, -- int osr_bci) { -+/** -+ * See if this compilation is already requested. -+ * -+ * Implementation note: there is only a single "is in queue" bit -+ * for each method. This means that the check below is overly -+ * conservative in the sense that an osr compilation in the queue -+ * will block a normal compilation from entering the queue (and vice -+ * versa). This can be remedied by a full queue search to disambiguate -+ * cases. If it is deemed profitable, this may be done. -+ */ -+bool CompileBroker::compilation_is_in_queue(methodHandle method) { - return method->queued_for_compilation(); - } - -@@ -1498,13 +1556,11 @@ - #endif - } - -- --// ------------------------------------------------------------------ --// CompileBroker::is_compile_blocking --// --// Should the current thread be blocked until this compilation request --// has been fulfilled? --bool CompileBroker::is_compile_blocking(methodHandle method, int osr_bci) { -+/** -+ * Should the current thread block until this compilation request -+ * has been fulfilled? -+ */ -+bool CompileBroker::is_compile_blocking() { - assert(!InstanceRefKlass::owns_pending_list_lock(JavaThread::current()), "possible deadlock"); - return !BackgroundCompilation; - } -@@ -1532,7 +1588,7 @@ - int hot_count, - const char* comment, - bool blocking) { -- CompileTask* new_task = allocate_task(); -+ CompileTask* new_task = CompileTask::allocate(); - new_task->initialize(compile_id, method, osr_bci, comp_level, - hot_method, hot_count, comment, - blocking); -@@ -1541,43 +1597,12 @@ - } - - --// ------------------------------------------------------------------ --// CompileBroker::allocate_task --// --// Allocate a CompileTask, from the free list if possible. --CompileTask* CompileBroker::allocate_task() { -- MutexLocker locker(CompileTaskAlloc_lock); -- CompileTask* task = NULL; -- if (_task_free_list != NULL) { -- task = _task_free_list; -- _task_free_list = task->next(); -- task->set_next(NULL); -- } else { -- task = new CompileTask(); -- task->set_next(NULL); -- } -- return task; --} -- -- --// ------------------------------------------------------------------ --// CompileBroker::free_task --// --// Add a task to the free list. --void CompileBroker::free_task(CompileTask* task) { -- MutexLocker locker(CompileTaskAlloc_lock); -- task->free(); -- task->set_next(_task_free_list); -- _task_free_list = task; --} -- -- --// ------------------------------------------------------------------ --// CompileBroker::wait_for_completion --// --// Wait for the given method CompileTask to complete. -+/** -+ * Wait for the compilation task to complete. -+ */ - void CompileBroker::wait_for_completion(CompileTask* task) { - if (CIPrintCompileQueue) { -+ ttyLocker ttyl; - tty->print_cr("BLOCKING FOR COMPILE"); - } - -@@ -1590,26 +1615,34 @@ - { - MutexLocker waiter(task->lock(), thread); - -- while (!task->is_complete()) -+ while (!task->is_complete() && !is_compilation_disabled_forever()) { - task->lock()->wait(); - } -+ } -+ -+ thread->set_blocked_on_compilation(false); -+ if (is_compilation_disabled_forever()) { -+ CompileTask::free(task); -+ return; -+ } -+ - // It is harmless to check this status without the lock, because - // completion is a stable property (until the task object is recycled). - assert(task->is_complete(), "Compilation should have completed"); - assert(task->code_handle() == NULL, "must be reset"); - -- thread->set_blocked_on_compilation(false); -- - // By convention, the waiter is responsible for recycling a - // blocking CompileTask. Since there is only one waiter ever - // waiting on a CompileTask, we know that no one else will - // be using this CompileTask; we can free it. -- free_task(task); -+ CompileTask::free(task); - } - --// Initialize compiler thread(s) + compiler object(s). The postcondition --// of this function is that the compiler runtimes are initialized and that --//compiler threads can start compiling. -+/** -+ * Initialize compiler thread(s) + compiler object(s). The postcondition -+ * of this function is that the compiler runtimes are initialized and that -+ * compiler threads can start compiling. -+ */ - bool CompileBroker::init_compiler_runtime() { - CompilerThread* thread = CompilerThread::current(); - AbstractCompiler* comp = thread->compiler(); -@@ -1660,9 +1692,11 @@ - return true; - } - --// If C1 and/or C2 initialization failed, we shut down all compilation. --// We do this to keep things simple. This can be changed if it ever turns out to be --// a problem. -+/** -+ * If C1 and/or C2 initialization failed, we shut down all compilation. -+ * We do this to keep things simple. This can be changed if it ever turns -+ * out to be a problem. -+ */ - void CompileBroker::shutdown_compiler_runtime(AbstractCompiler* comp, CompilerThread* thread) { - // Free buffer blob, if allocated - if (thread->get_buffer_blob() != NULL) { -@@ -1674,28 +1708,25 @@ - // There are two reasons for shutting down the compiler - // 1) compiler runtime initialization failed - // 2) The code cache is full and the following flag is set: -XX:-UseCodeCacheFlushing -- warning("Shutting down compiler %s (no space to run compilers)", comp->name()); -+ warning("%s initialization failed. Shutting down all compilers", comp->name()); - - // Only one thread per compiler runtime object enters here - // Set state to shut down - comp->set_shut_down(); - -- MutexLocker mu(MethodCompileQueue_lock, thread); -- CompileQueue* queue; -- if (_c1_method_queue != NULL) { -- _c1_method_queue->delete_all(); -- queue = _c1_method_queue; -- _c1_method_queue = NULL; -- delete _c1_method_queue; -+ // Delete all queued compilation tasks to make compiler threads exit faster. -+ if (_c1_compile_queue != NULL) { -+ _c1_compile_queue->free_all(); - } - -- if (_c2_method_queue != NULL) { -- _c2_method_queue->delete_all(); -- queue = _c2_method_queue; -- _c2_method_queue = NULL; -- delete _c2_method_queue; -+ if (_c2_compile_queue != NULL) { -+ _c2_compile_queue->free_all(); - } - -+ // Set flags so that we continue execution with using interpreter only. -+ UseCompiler = false; -+ UseInterpreter = true; -+ - // We could delete compiler runtimes also. However, there are references to - // the compiler runtime(s) (e.g., nmethod::is_compiled_by_c1()) which then - // fail. This can be done later if necessary. -@@ -1781,22 +1812,6 @@ - if (method()->number_of_breakpoints() == 0) { - // Compile the method. - if ((UseCompiler || AlwaysCompileLoopMethods) && CompileBroker::should_compile_new_jobs()) { --#ifdef COMPILER1 -- // Allow repeating compilations for the purpose of benchmarking -- // compile speed. This is not useful for customers. -- if (CompilationRepeat != 0) { -- int compile_count = CompilationRepeat; -- while (compile_count > 0) { -- invoke_compiler_on_method(task); -- nmethod* nm = method->code(); -- if (nm != NULL) { -- nm->make_zombie(); -- method->clear_code(); -- } -- compile_count--; -- } -- } --#endif /* COMPILER1 */ - invoke_compiler_on_method(task); - } else { - // After compilation is disabled, remove remaining methods from queue -@@ -1830,7 +1845,7 @@ - os::file_separator(), thread_id, os::current_process_id()); - } - -- fp = fopen(file_name, "at"); -+ fp = fopen(file_name, "wt"); - if (fp != NULL) { - if (LogCompilation && Verbose) { - tty->print_cr("Opening compilation log %s", file_name); ---- jdk8/hotspot/src/share/vm/compiler/compileBroker.hpp 2015-01-27 08:42:53.982817994 +0100 -+++ jdk8/hotspot/src/share/vm/compiler/compileBroker.hpp 2015-01-27 08:43:45.245625060 +0100 -@@ -40,6 +40,11 @@ - friend class VMStructs; - - private: -+ static CompileTask* _task_free_list; -+#ifdef ASSERT -+ static int _num_allocated_tasks; -+#endif -+ - Monitor* _lock; - uint _compile_id; - Method* _method; -@@ -52,7 +57,7 @@ - int _num_inlined_bytecodes; - nmethodLocker* _code_handle; // holder of eventual result - CompileTask* _next, *_prev; -- -+ bool _is_free; - // Fields used for logging why the compilation was initiated: - jlong _time_queued; // in units of os::elapsed_counter() - Method* _hot_method; // which method actually triggered this task -@@ -70,7 +75,8 @@ - methodHandle hot_method, int hot_count, const char* comment, - bool is_blocking); - -- void free(); -+ static CompileTask* allocate(); -+ static void free(CompileTask* task); - - int compile_id() const { return _compile_id; } - Method* method() const { return _method; } -@@ -99,6 +105,8 @@ - void set_next(CompileTask* next) { _next = next; } - CompileTask* prev() const { return _prev; } - void set_prev(CompileTask* prev) { _prev = prev; } -+ bool is_free() const { return _is_free; } -+ void set_is_free(bool val) { _is_free = val; } - - private: - static void print_compilation_impl(outputStream* st, Method* method, int compile_id, int comp_level, -@@ -225,8 +233,8 @@ - - // Redefine Classes support - void mark_on_stack(); -- void delete_all(); -- void print(); -+ void free_all(); -+ NOT_PRODUCT (void print();) - - ~CompileQueue() { - assert (is_empty(), " Compile Queue must be empty"); -@@ -279,9 +287,8 @@ - static int _last_compile_level; - static char _last_method_compiled[name_buffer_length]; - -- static CompileQueue* _c2_method_queue; -- static CompileQueue* _c1_method_queue; -- static CompileTask* _task_free_list; -+ static CompileQueue* _c2_compile_queue; -+ static CompileQueue* _c1_compile_queue; - - static GrowableArray* _compiler_threads; - -@@ -334,7 +341,7 @@ - static void init_compiler_threads(int c1_compiler_count, int c2_compiler_count); - static bool compilation_is_complete (methodHandle method, int osr_bci, int comp_level); - static bool compilation_is_prohibited(methodHandle method, int osr_bci, int comp_level); -- static bool is_compile_blocking (methodHandle method, int osr_bci); -+ static bool is_compile_blocking (); - static void preload_classes (methodHandle method, TRAPS); - - static CompileTask* create_compile_task(CompileQueue* queue, -@@ -346,8 +353,6 @@ - int hot_count, - const char* comment, - bool blocking); -- static CompileTask* allocate_task(); -- static void free_task(CompileTask* task); - static void wait_for_completion(CompileTask* task); - - static void invoke_compiler_on_method(CompileTask* task); -@@ -365,8 +370,8 @@ - const char* comment, - Thread* thread); - static CompileQueue* compile_queue(int comp_level) { -- if (is_c2_compile(comp_level)) return _c2_method_queue; -- if (is_c1_compile(comp_level)) return _c1_method_queue; -+ if (is_c2_compile(comp_level)) return _c2_compile_queue; -+ if (is_c1_compile(comp_level)) return _c1_compile_queue; - return NULL; - } - static bool init_compiler_runtime(); -@@ -384,7 +389,7 @@ - return NULL; - } - -- static bool compilation_is_in_queue(methodHandle method, int osr_bci); -+ static bool compilation_is_in_queue(methodHandle method); - static int queue_size(int comp_level) { - CompileQueue *q = compile_queue(comp_level); - return q != NULL ? q->size() : 0; ---- jdk8/hotspot/src/share/vm/compiler/compileLog.cpp 2015-01-27 08:42:53.982817994 +0100 -+++ jdk8/hotspot/src/share/vm/compiler/compileLog.cpp 2015-01-27 08:43:45.245625060 +0100 -@@ -55,8 +55,10 @@ - } - - CompileLog::~CompileLog() { -- delete _out; -+ delete _out; // Close fd in fileStream::~fileStream() - _out = NULL; -+ // Remove partial file after merging in CompileLog::finish_log_on_error -+ unlink(_file); - FREE_C_HEAP_ARRAY(char, _identities, mtCompiler); - FREE_C_HEAP_ARRAY(char, _file, mtCompiler); - } -@@ -268,10 +270,9 @@ - } - file->print_raw_cr(""); - close(partial_fd); -- unlink(partial_file); - } - CompileLog* next_log = log->_next; -- delete log; -+ delete log; // Removes partial file - log = next_log; - } - _first = NULL; ---- jdk8/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp 2015-01-27 08:42:53.983817971 +0100 -+++ jdk8/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp 2015-01-27 08:43:45.246625037 +0100 -@@ -2641,7 +2641,7 @@ - // Get the #blocks we want to claim - size_t n_blks = (size_t)_blocks_to_claim[word_sz].average(); - assert(n_blks > 0, "Error"); -- assert(ResizePLAB || n_blks == OldPLABSize, "Error"); -+ assert(ResizeOldPLAB || n_blks == OldPLABSize, "Error"); - // In some cases, when the application has a phase change, - // there may be a sudden and sharp shift in the object survival - // profile, and updating the counts at the end of a scavenge ---- jdk8/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp 2015-01-27 08:42:53.983817971 +0100 -+++ jdk8/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp 2015-01-27 08:43:45.248624990 +0100 -@@ -738,7 +738,7 @@ - // Support for parallelizing survivor space rescan - if ((CMSParallelRemarkEnabled && CMSParallelSurvivorRemarkEnabled) || CMSParallelInitialMarkEnabled) { - const size_t max_plab_samples = -- ((DefNewGeneration*)_young_gen)->max_survivor_size()/MinTLABSize; -+ ((DefNewGeneration*)_young_gen)->max_survivor_size() / plab_sample_minimum_size(); - - _survivor_plab_array = NEW_C_HEAP_ARRAY(ChunkArray, ParallelGCThreads, mtGC); - _survivor_chunk_array = NEW_C_HEAP_ARRAY(HeapWord*, 2*max_plab_samples, mtGC); -@@ -796,6 +796,12 @@ - _inter_sweep_timer.start(); // start of time - } - -+size_t CMSCollector::plab_sample_minimum_size() { -+ // The default value of MinTLABSize is 2k, but there is -+ // no way to get the default value if the flag has been overridden. -+ return MAX2(ThreadLocalAllocBuffer::min_size() * HeapWordSize, 2 * K); -+} -+ - const char* ConcurrentMarkSweepGeneration::name() const { - return "concurrent mark-sweep generation"; - } ---- jdk8/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp 2015-01-27 08:42:53.983817971 +0100 -+++ jdk8/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp 2015-01-27 08:43:45.249624967 +0100 -@@ -764,6 +764,10 @@ - size_t* _cursor; - ChunkArray* _survivor_plab_array; - -+ // A bounded minimum size of PLABs, should not return too small values since -+ // this will affect the size of the data structures used for parallel young gen rescan -+ size_t plab_sample_minimum_size(); -+ - // Support for marking stack overflow handling - bool take_from_overflow_list(size_t num, CMSMarkStack* to_stack); - bool par_take_from_overflow_list(size_t num, ---- jdk8/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/vmCMSOperations.cpp 2015-01-27 08:42:53.984817948 +0100 -+++ jdk8/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/vmCMSOperations.cpp 2015-01-27 08:43:45.249624967 +0100 -@@ -50,8 +50,12 @@ - void VM_CMS_Operation::acquire_pending_list_lock() { - // The caller may block while communicating - // with the SLT thread in order to acquire/release the PLL. -- ConcurrentMarkSweepThread::slt()-> -- manipulatePLL(SurrogateLockerThread::acquirePLL); -+ SurrogateLockerThread* slt = ConcurrentMarkSweepThread::slt(); -+ if (slt != NULL) { -+ slt->manipulatePLL(SurrogateLockerThread::acquirePLL); -+ } else { -+ SurrogateLockerThread::report_missing_slt(); -+ } - } - - void VM_CMS_Operation::release_and_notify_pending_list_lock() { ---- jdk8/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp 2015-01-27 08:42:53.984817948 +0100 -+++ jdk8/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp 2015-01-27 08:43:45.249624967 +0100 -@@ -23,6 +23,7 @@ - */ - - #include "precompiled.hpp" -+#include "classfile/metadataOnStackMark.hpp" - #include "classfile/symbolTable.hpp" - #include "code/codeCache.hpp" - #include "gc_implementation/g1/concurrentMark.inline.hpp" -@@ -2174,6 +2175,7 @@ - // We reclaimed old regions so we should calculate the sizes to make - // sure we update the old gen/space data. - g1h->g1mm()->update_sizes(); -+ g1h->allocation_context_stats().update_after_mark(); - - g1h->trace_heap_after_concurrent_cycle(); - } -@@ -2602,17 +2604,27 @@ - G1RemarkGCTraceTime trace("Unloading", G1Log::finer()); - - if (ClassUnloadingWithConcurrentMark) { -+ // Cleaning of klasses depends on correct information from MetadataMarkOnStack. The CodeCache::mark_on_stack -+ // part is too slow to be done serially, so it is handled during the weakRefsWorkParallelPart phase. -+ // Defer the cleaning until we have complete on_stack data. -+ MetadataOnStackMark md_on_stack(false /* Don't visit the code cache at this point */); -+ - bool purged_classes; - - { - G1RemarkGCTraceTime trace("System Dictionary Unloading", G1Log::finest()); -- purged_classes = SystemDictionary::do_unloading(&g1_is_alive); -+ purged_classes = SystemDictionary::do_unloading(&g1_is_alive, false /* Defer klass cleaning */); - } - - { - G1RemarkGCTraceTime trace("Parallel Unloading", G1Log::finest()); - weakRefsWorkParallelPart(&g1_is_alive, purged_classes); - } -+ -+ { -+ G1RemarkGCTraceTime trace("Deallocate Metadata", G1Log::finest()); -+ ClassLoaderDataGraph::free_deallocate_lists(); -+ } - } - - if (G1StringDedup::is_enabled()) { -@@ -3335,7 +3347,6 @@ - } else { - g1_par_agg_task.work(0); - } -- _g1h->allocation_context_stats().update_at_remark(); - } - - // Clear the per-worker arrays used to store the per-region counting data ---- jdk8/hotspot/src/share/vm/gc_implementation/g1/dirtyCardQueue.hpp 2015-01-27 08:42:53.984817948 +0100 -+++ jdk8/hotspot/src/share/vm/gc_implementation/g1/dirtyCardQueue.hpp 2015-01-27 08:43:45.250624944 +0100 -@@ -47,6 +47,13 @@ - // active field set to true. - PtrQueue(qset_, perm, true /* active */) { } - -+ // Flush before destroying; queue may be used to capture pending work while -+ // doing something else, with auto-flush on completion. -+ ~DirtyCardQueue() { if (!is_permanent()) flush(); } -+ -+ // Process queue entries and release resources. -+ void flush() { flush_impl(); } -+ - // Apply the closure to all elements, and reset the index to make the - // buffer empty. If a closure application returns "false", return - // "false" immediately, halting the iteration. If "consume" is true, ---- jdk8/hotspot/src/share/vm/gc_implementation/g1/g1AllocationContext.hpp 2015-01-27 08:42:53.985817924 +0100 -+++ jdk8/hotspot/src/share/vm/gc_implementation/g1/g1AllocationContext.hpp 2015-01-27 08:43:45.250624944 +0100 -@@ -45,7 +45,7 @@ - public: - inline void clear() { } - inline void update(bool full_gc) { } -- inline void update_at_remark() { } -+ inline void update_after_mark() { } - inline bool available() { return false; } - }; - ---- jdk8/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp 2015-01-27 08:42:53.985817924 +0100 -+++ jdk8/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp 2015-01-27 08:43:45.251624920 +0100 -@@ -27,6 +27,7 @@ - #endif - - #include "precompiled.hpp" -+#include "classfile/metadataOnStackMark.hpp" - #include "code/codeCache.hpp" - #include "code/icBuffer.hpp" - #include "gc_implementation/g1/bufferingOopClosure.hpp" -@@ -2478,6 +2479,7 @@ - - unsigned int gc_count_before; - unsigned int old_marking_count_before; -+ unsigned int full_gc_count_before; - bool retry_gc; - - do { -@@ -2488,6 +2490,7 @@ - - // Read the GC count while holding the Heap_lock - gc_count_before = total_collections(); -+ full_gc_count_before = total_full_collections(); - old_marking_count_before = _old_marking_cycles_started; - } - -@@ -2532,7 +2535,7 @@ - VMThread::execute(&op); - } else { - // Schedule a Full GC. -- VM_G1CollectFull op(gc_count_before, old_marking_count_before, cause); -+ VM_G1CollectFull op(gc_count_before, full_gc_count_before, cause); - VMThread::execute(&op); - } - } -@@ -5131,6 +5134,10 @@ - clean_nmethod(claimed_nmethods[i]); - } - } -+ -+ // The nmethod cleaning helps out and does the CodeCache part of MetadataOnStackMark. -+ // Need to retire the buffers now that this thread has stopped cleaning nmethods. -+ MetadataOnStackMark::retire_buffer_for_thread(Thread::current()); - } - - void work_second_pass(uint worker_id) { -@@ -5183,6 +5190,9 @@ - // G1 specific cleanup work that has - // been moved here to be done in parallel. - ik->clean_dependent_nmethods(); -+ if (JvmtiExport::has_redefined_a_class()) { -+ InstanceKlass::purge_previous_versions(ik); -+ } - } - - void work() { -@@ -5217,8 +5227,20 @@ - _klass_cleaning_task(is_alive) { - } - -+ void pre_work_verification() { -+ // The VM Thread will have registered Metadata during the single-threaded phase of MetadataStackOnMark. -+ assert(Thread::current()->is_VM_thread() -+ || !MetadataOnStackMark::has_buffer_for_thread(Thread::current()), "Should be empty"); -+ } -+ -+ void post_work_verification() { -+ assert(!MetadataOnStackMark::has_buffer_for_thread(Thread::current()), "Should be empty"); -+ } -+ - // The parallel work done by all worker threads. - void work(uint worker_id) { -+ pre_work_verification(); -+ - // Do first pass of code cache cleaning. - _code_cache_task.work_first_pass(worker_id); - -@@ -5237,6 +5259,8 @@ - - // Clean all klasses that were not unloaded. - _klass_cleaning_task.work(); -+ -+ post_work_verification(); - } - }; - ---- jdk8/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap_ext.cpp 2015-01-27 08:42:53.985817924 +0100 -+++ jdk8/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap_ext.cpp 2015-01-27 08:43:45.251624920 +0100 -@@ -25,8 +25,9 @@ - #include "precompiled.hpp" - #include "gc_implementation/g1/g1CollectedHeap.hpp" - --void G1CollectedHeap::copy_allocation_context_stats(const jint* contexts, -+bool G1CollectedHeap::copy_allocation_context_stats(const jint* contexts, - jlong* totals, - jbyte* accuracy, - jint len) { -+ return false; - } ---- jdk8/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp 2015-01-27 08:42:53.985817924 +0100 -+++ jdk8/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp 2015-01-27 08:43:45.251624920 +0100 -@@ -1249,7 +1249,7 @@ - // The same as above but assume that the caller holds the Heap_lock. - void collect_locked(GCCause::Cause cause); - -- virtual void copy_allocation_context_stats(const jint* contexts, -+ virtual bool copy_allocation_context_stats(const jint* contexts, - jlong* totals, - jbyte* accuracy, - jint len); ---- jdk8/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp 2015-01-27 08:42:53.985817924 +0100 -+++ jdk8/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp 2015-01-27 08:43:45.252624897 +0100 -@@ -1425,6 +1425,18 @@ - #endif // PRODUCT - } - -+bool G1CollectorPolicy::is_young_list_full() { -+ uint young_list_length = _g1->young_list()->length(); -+ uint young_list_target_length = _young_list_target_length; -+ return young_list_length >= young_list_target_length; -+} -+ -+bool G1CollectorPolicy::can_expand_young_list() { -+ uint young_list_length = _g1->young_list()->length(); -+ uint young_list_max_length = _young_list_max_length; -+ return young_list_length < young_list_max_length; -+} -+ - uint G1CollectorPolicy::max_regions(int purpose) { - switch (purpose) { - case GCAllocForSurvived: ---- jdk8/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy_ext.hpp 1970-01-01 01:00:00.000000000 +0100 -+++ jdk8/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy_ext.hpp 2015-01-27 08:43:45.252624897 +0100 -@@ -0,0 +1,32 @@ -+/* -+ * 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. -+ * -+ */ -+ -+#ifndef SHARE_VM_GC_IMPLEMENTATION_G1_G1COLLECTORPOLICY_EXT_HPP -+#define SHARE_VM_GC_IMPLEMENTATION_G1_G1COLLECTORPOLICY_EXT_HPP -+ -+#include "gc_implementation/g1/g1CollectorPolicy.hpp" -+ -+class G1CollectorPolicyExt : public G1CollectorPolicy { }; -+ -+#endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1COLLECTORPOLICY_EXT_HPP ---- jdk8/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp 2015-01-27 08:42:53.985817924 +0100 -+++ jdk8/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp 2015-01-27 08:43:45.252624897 +0100 -@@ -26,6 +26,7 @@ - #define SHARE_VM_GC_IMPLEMENTATION_G1_G1COLLECTORPOLICY_HPP - - #include "gc_implementation/g1/collectionSetChooser.hpp" -+#include "gc_implementation/g1/g1Allocator.hpp" - #include "gc_implementation/g1/g1MMUTracker.hpp" - #include "memory/collectorPolicy.hpp" - -@@ -803,7 +804,7 @@ - - // If an expansion would be appropriate, because recent GC overhead had - // exceeded the desired limit, return an amount to expand by. -- size_t expansion_amount(); -+ virtual size_t expansion_amount(); - - // Print tracing information. - void print_tracing_info() const; -@@ -822,17 +823,9 @@ - - size_t young_list_target_length() const { return _young_list_target_length; } - -- bool is_young_list_full() { -- uint young_list_length = _g1->young_list()->length(); -- uint young_list_target_length = _young_list_target_length; -- return young_list_length >= young_list_target_length; -- } -+ bool is_young_list_full(); - -- bool can_expand_young_list() { -- uint young_list_length = _g1->young_list()->length(); -- uint young_list_max_length = _young_list_max_length; -- return young_list_length < young_list_max_length; -- } -+ bool can_expand_young_list(); - - uint young_list_max_length() { - return _young_list_max_length; ---- jdk8/hotspot/src/share/vm/gc_implementation/g1/g1PageBasedVirtualSpace.cpp 2015-01-27 08:42:53.986817901 +0100 -+++ jdk8/hotspot/src/share/vm/gc_implementation/g1/g1PageBasedVirtualSpace.cpp 2015-01-27 08:43:45.252624897 +0100 -@@ -45,7 +45,8 @@ - #include "utilities/bitMap.inline.hpp" - - G1PageBasedVirtualSpace::G1PageBasedVirtualSpace() : _low_boundary(NULL), -- _high_boundary(NULL), _committed(), _page_size(0), _special(false), _executable(false) { -+ _high_boundary(NULL), _committed(), _page_size(0), _special(false), -+ _dirty(), _executable(false) { - } - - bool G1PageBasedVirtualSpace::initialize_with_granularity(ReservedSpace rs, size_t page_size) { -@@ -66,6 +67,9 @@ - assert(_committed.size() == 0, "virtual space initialized more than once"); - uintx size_in_bits = rs.size() / page_size; - _committed.resize(size_in_bits, /* in_resource_area */ false); -+ if (_special) { -+ _dirty.resize(size_in_bits, /* in_resource_area */ false); -+ } - - return true; - } -@@ -84,6 +88,7 @@ - _executable = false; - _page_size = 0; - _committed.resize(0, false); -+ _dirty.resize(0, false); - } - - size_t G1PageBasedVirtualSpace::committed_size() const { -@@ -120,31 +125,40 @@ - return num * _page_size; - } - --MemRegion G1PageBasedVirtualSpace::commit(uintptr_t start, size_t size_in_pages) { -+bool G1PageBasedVirtualSpace::commit(uintptr_t start, size_t size_in_pages) { - // We need to make sure to commit all pages covered by the given area. - guarantee(is_area_uncommitted(start, size_in_pages), "Specified area is not uncommitted"); - -- if (!_special) { -+ bool zero_filled = true; -+ uintptr_t end = start + size_in_pages; -+ -+ if (_special) { -+ // Check for dirty pages and update zero_filled if any found. -+ if (_dirty.get_next_one_offset(start,end) < end) { -+ zero_filled = false; -+ _dirty.clear_range(start, end); -+ } -+ } else { - os::commit_memory_or_exit(page_start(start), byte_size_for_pages(size_in_pages), _executable, - err_msg("Failed to commit pages from "SIZE_FORMAT" of length "SIZE_FORMAT, start, size_in_pages)); - } -- _committed.set_range(start, start + size_in_pages); -+ _committed.set_range(start, end); - -- MemRegion result((HeapWord*)page_start(start), byte_size_for_pages(size_in_pages) / HeapWordSize); -- return result; -+ return zero_filled; - } - --MemRegion G1PageBasedVirtualSpace::uncommit(uintptr_t start, size_t size_in_pages) { -+void G1PageBasedVirtualSpace::uncommit(uintptr_t start, size_t size_in_pages) { - guarantee(is_area_committed(start, size_in_pages), "checking"); - -- if (!_special) { -+ if (_special) { -+ // Mark that memory is dirty. If committed again the memory might -+ // need to be cleared explicitly. -+ _dirty.set_range(start, start + size_in_pages); -+ } else { - os::uncommit_memory(page_start(start), byte_size_for_pages(size_in_pages)); - } - - _committed.clear_range(start, start + size_in_pages); -- -- MemRegion result((HeapWord*)page_start(start), byte_size_for_pages(size_in_pages) / HeapWordSize); -- return result; - } - - bool G1PageBasedVirtualSpace::contains(const void* p) const { -@@ -154,7 +168,7 @@ - #ifndef PRODUCT - void G1PageBasedVirtualSpace::print_on(outputStream* out) { - out->print ("Virtual space:"); -- if (special()) out->print(" (pinned in memory)"); -+ if (_special) out->print(" (pinned in memory)"); - out->cr(); - out->print_cr(" - committed: " SIZE_FORMAT, committed_size()); - out->print_cr(" - reserved: " SIZE_FORMAT, reserved_size()); ---- jdk8/hotspot/src/share/vm/gc_implementation/g1/g1PageBasedVirtualSpace.hpp 2015-01-27 08:42:53.986817901 +0100 -+++ jdk8/hotspot/src/share/vm/gc_implementation/g1/g1PageBasedVirtualSpace.hpp 2015-01-27 08:43:45.252624897 +0100 -@@ -49,6 +49,12 @@ - // Bitmap used for verification of commit/uncommit operations. - BitMap _committed; - -+ // Bitmap used to keep track of which pages are dirty or not for _special -+ // spaces. This is needed because for those spaces the underlying memory -+ // will only be zero filled the first time it is committed. Calls to commit -+ // will use this bitmap and return whether or not the memory is zero filled. -+ BitMap _dirty; -+ - // Indicates that the entire space has been committed and pinned in memory, - // os::commit_memory() or os::uncommit_memory() have no function. - bool _special; -@@ -71,12 +77,11 @@ - public: - - // Commit the given area of pages starting at start being size_in_pages large. -- MemRegion commit(uintptr_t start, size_t size_in_pages); -+ // Returns true if the given area is zero filled upon completion. -+ bool commit(uintptr_t start, size_t size_in_pages); - - // Uncommit the given area of pages starting at start being size_in_pages large. -- MemRegion uncommit(uintptr_t start, size_t size_in_pages); -- -- bool special() const { return _special; } -+ void uncommit(uintptr_t start, size_t size_in_pages); - - // Initialization - G1PageBasedVirtualSpace(); ---- jdk8/hotspot/src/share/vm/gc_implementation/g1/g1RegionToSpaceMapper.cpp 2015-01-27 08:42:53.986817901 +0100 -+++ jdk8/hotspot/src/share/vm/gc_implementation/g1/g1RegionToSpaceMapper.cpp 2015-01-27 08:43:45.253624874 +0100 -@@ -67,9 +67,9 @@ - } - - virtual void commit_regions(uintptr_t start_idx, size_t num_regions) { -- _storage.commit(start_idx * _pages_per_region, num_regions * _pages_per_region); -+ bool zero_filled = _storage.commit(start_idx * _pages_per_region, num_regions * _pages_per_region); - _commit_map.set_range(start_idx, start_idx + num_regions); -- fire_on_commit(start_idx, num_regions, true); -+ fire_on_commit(start_idx, num_regions, zero_filled); - } - - virtual void uncommit_regions(uintptr_t start_idx, size_t num_regions) { -@@ -117,8 +117,7 @@ - uint old_refcount = _refcounts.get_by_index(idx); - bool zero_filled = false; - if (old_refcount == 0) { -- _storage.commit(idx, 1); -- zero_filled = true; -+ zero_filled = _storage.commit(idx, 1); - } - _refcounts.set_by_index(idx, old_refcount + 1); - _commit_map.set_bit(i); ---- jdk8/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp 2015-01-27 08:42:53.987817878 +0100 -+++ jdk8/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp 2015-01-27 08:43:45.253624874 +0100 -@@ -1015,11 +1015,14 @@ - HeapWord* G1OffsetTableContigSpace::saved_mark_word() const { - G1CollectedHeap* g1h = G1CollectedHeap::heap(); - assert( _gc_time_stamp <= g1h->get_gc_time_stamp(), "invariant" ); -- if (_gc_time_stamp < g1h->get_gc_time_stamp()) -- return top(); -- else -+ HeapWord* local_top = top(); -+ OrderAccess::loadload(); -+ if (_gc_time_stamp < g1h->get_gc_time_stamp()) { -+ return local_top; -+ } else { - return Space::saved_mark_word(); - } -+} - - void G1OffsetTableContigSpace::record_top_and_timestamp() { - G1CollectedHeap* g1h = G1CollectedHeap::heap(); ---- jdk8/hotspot/src/share/vm/gc_implementation/g1/ptrQueue.cpp 2015-01-27 08:42:53.987817878 +0100 -+++ jdk8/hotspot/src/share/vm/gc_implementation/g1/ptrQueue.cpp 2015-01-27 08:43:45.253624874 +0100 -@@ -31,11 +31,15 @@ - #include "runtime/thread.inline.hpp" - - PtrQueue::PtrQueue(PtrQueueSet* qset, bool perm, bool active) : -- _qset(qset), _buf(NULL), _index(0), _active(active), -+ _qset(qset), _buf(NULL), _index(0), _sz(0), _active(active), - _perm(perm), _lock(NULL) - {} - --void PtrQueue::flush() { -+PtrQueue::~PtrQueue() { -+ assert(_perm || (_buf == NULL), "queue must be flushed before delete"); -+} -+ -+void PtrQueue::flush_impl() { - if (!_perm && _buf != NULL) { - if (_index == _sz) { - // No work to do. ---- jdk8/hotspot/src/share/vm/gc_implementation/g1/ptrQueue.hpp 2015-01-27 08:42:53.987817878 +0100 -+++ jdk8/hotspot/src/share/vm/gc_implementation/g1/ptrQueue.hpp 2015-01-27 08:43:45.253624874 +0100 -@@ -65,15 +65,18 @@ - Mutex* _lock; - - PtrQueueSet* qset() { return _qset; } -+ bool is_permanent() const { return _perm; } -+ -+ // Process queue entries and release resources, if not permanent. -+ void flush_impl(); - - public: - // Initialize this queue to contain a null buffer, and be part of the - // given PtrQueueSet. - PtrQueue(PtrQueueSet* qset, bool perm = false, bool active = false); -- // Release any contained resources. -- virtual void flush(); -- // Calls flush() when destroyed. -- ~PtrQueue() { flush(); } -+ -+ // Requires queue flushed or permanent. -+ ~PtrQueue(); - - // Associate a lock with a ptr queue. - void set_lock(Mutex* lock) { _lock = lock; } ---- jdk8/hotspot/src/share/vm/gc_implementation/g1/satbQueue.cpp 2015-01-27 08:42:53.987817878 +0100 -+++ jdk8/hotspot/src/share/vm/gc_implementation/g1/satbQueue.cpp 2015-01-27 08:43:45.253624874 +0100 -@@ -39,7 +39,7 @@ - // first before we flush it, otherwise we might end up with an - // enqueued buffer with refs into the CSet which breaks our invariants. - filter(); -- PtrQueue::flush(); -+ flush_impl(); - } - - // This method removes entries from an SATB buffer that will not be ---- jdk8/hotspot/src/share/vm/gc_implementation/g1/satbQueue.hpp 2015-01-27 08:42:53.987817878 +0100 -+++ jdk8/hotspot/src/share/vm/gc_implementation/g1/satbQueue.hpp 2015-01-27 08:43:45.253624874 +0100 -@@ -60,9 +60,8 @@ - // field to true. This is done in JavaThread::initialize_queues(). - PtrQueue(qset, perm, false /* active */) { } - -- // Overrides PtrQueue::flush() so that it can filter the buffer -- // before it is flushed. -- virtual void flush(); -+ // Process queue entries and free resources. -+ void flush(); - - // Overrides PtrQueue::should_enqueue_buffer(). See the method's - // definition for more information. ---- jdk8/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp 2015-01-27 08:42:53.987817878 +0100 -+++ jdk8/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp 2015-01-27 08:43:45.254624850 +0100 -@@ -213,8 +213,12 @@ - assert(_needs_pll, "don't call this otherwise"); - // The caller may block while communicating - // with the SLT thread in order to acquire/release the PLL. -- ConcurrentMarkThread::slt()-> -- manipulatePLL(SurrogateLockerThread::acquirePLL); -+ SurrogateLockerThread* slt = ConcurrentMarkThread::slt(); -+ if (slt != NULL) { -+ slt->manipulatePLL(SurrogateLockerThread::acquirePLL); -+ } else { -+ SurrogateLockerThread::report_missing_slt(); -+ } - } - - void VM_CGC_Operation::release_and_notify_pending_list_lock() { ---- jdk8/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.hpp 2015-01-27 08:42:53.987817878 +0100 -+++ jdk8/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.hpp 2015-01-27 08:43:45.254624850 +0100 -@@ -60,7 +60,7 @@ - VM_G1CollectFull(unsigned int gc_count_before, - unsigned int full_gc_count_before, - GCCause::Cause cause) -- : VM_GC_Operation(gc_count_before, cause, full_gc_count_before) { } -+ : VM_GC_Operation(gc_count_before, cause, full_gc_count_before, true) { } - virtual VMOp_Type type() const { return VMOp_G1CollectFull; } - virtual void doit(); - virtual const char* name() const { ---- jdk8/hotspot/src/share/vm/gc_implementation/shared/concurrentGCThread.cpp 2015-01-27 08:42:53.990817808 +0100 -+++ jdk8/hotspot/src/share/vm/gc_implementation/shared/concurrentGCThread.cpp 2015-01-27 08:43:45.254624850 +0100 -@@ -137,6 +137,13 @@ - return res; - } - -+void SurrogateLockerThread::report_missing_slt() { -+ vm_exit_during_initialization( -+ "GC before GC support fully initialized: " -+ "SLT is needed but has not yet been created."); -+ ShouldNotReachHere(); -+} -+ - void SurrogateLockerThread::manipulatePLL(SLT_msg_type msg) { - MutexLockerEx x(&_monitor, Mutex::_no_safepoint_check_flag); - assert(_buffer == empty, "Should be empty"); ---- jdk8/hotspot/src/share/vm/gc_implementation/shared/concurrentGCThread.hpp 2015-01-27 08:42:53.990817808 +0100 -+++ jdk8/hotspot/src/share/vm/gc_implementation/shared/concurrentGCThread.hpp 2015-01-27 08:43:45.254624850 +0100 -@@ -93,6 +93,9 @@ - public: - static SurrogateLockerThread* make(TRAPS); - -+ // Terminate VM with error message that SLT needed but not yet created. -+ static void report_missing_slt(); -+ - SurrogateLockerThread(); - - bool is_hidden_from_external_view() const { return true; } ---- jdk8/hotspot/src/share/vm/gc_implementation/shared/objectCountEventSender.cpp 2015-01-27 08:42:53.991817785 +0100 -+++ jdk8/hotspot/src/share/vm/gc_implementation/shared/objectCountEventSender.cpp 2015-01-27 08:43:45.254624850 +0100 -@@ -29,8 +29,8 @@ - #include "memory/heapInspection.hpp" - #include "trace/tracing.hpp" - #include "utilities/globalDefinitions.hpp" -+#include "utilities/macros.hpp" - #include "utilities/ticks.hpp" -- - #if INCLUDE_SERVICES - - void ObjectCountEventSender::send(const KlassInfoEntry* entry, GCId gc_id, const Ticks& timestamp) { ---- jdk8/hotspot/src/share/vm/gc_implementation/shared/parGCAllocBuffer.hpp 2015-01-27 08:42:53.991817785 +0100 -+++ jdk8/hotspot/src/share/vm/gc_implementation/shared/parGCAllocBuffer.hpp 2015-01-27 08:43:45.254624850 +0100 -@@ -63,7 +63,8 @@ - virtual ~ParGCAllocBuffer() {} - - static const size_t min_size() { -- return ThreadLocalAllocBuffer::min_size(); -+ // Make sure that we return something that is larger than AlignmentReserve -+ return align_object_size(MAX2(MinTLABSize / HeapWordSize, (uintx)oopDesc::header_size())) + AlignmentReserve; - } - - static const size_t max_size() { ---- jdk8/hotspot/src/share/vm/gc_interface/collectedHeap.hpp 2015-01-27 08:42:53.991817785 +0100 -+++ jdk8/hotspot/src/share/vm/gc_interface/collectedHeap.hpp 2015-01-27 08:43:45.254624850 +0100 -@@ -641,10 +641,13 @@ - // For each context in contexts, set the corresponding entries in the totals - // and accuracy arrays to the current values held by the statistics. Each - // array should be of length len. -- virtual void copy_allocation_context_stats(const jint* contexts, -+ // Returns true if there are more stats available. -+ virtual bool copy_allocation_context_stats(const jint* contexts, - jlong* totals, - jbyte* accuracy, -- jint len) { } -+ jint len) { -+ return false; -+ } - - /////////////// Unit tests /////////////// - ---- jdk8/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp 2015-01-27 08:42:53.992817762 +0100 -+++ jdk8/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp 2015-01-27 08:43:45.255624827 +0100 -@@ -2813,11 +2813,11 @@ - if (TraceExceptions) { - ttyLocker ttyl; - ResourceMark rm; -- tty->print_cr("Exception <%s> (" INTPTR_FORMAT ")", except_oop->print_value_string(), (void*)except_oop()); -+ tty->print_cr("Exception <%s> (" INTPTR_FORMAT ")", except_oop->print_value_string(), p2i(except_oop())); - tty->print_cr(" thrown in interpreter method <%s>", METHOD->print_value_string()); - tty->print_cr(" at bci %d, continuing at %d for thread " INTPTR_FORMAT, -- istate->bcp() - (intptr_t)METHOD->code_base(), -- continuation_bci, THREAD); -+ (int)(istate->bcp() - METHOD->code_base()), -+ (int)continuation_bci, p2i(THREAD)); - } - // for AbortVMOnException flag - NOT_PRODUCT(Exceptions::debug_check_abort(except_oop)); -@@ -2829,11 +2829,11 @@ - if (TraceExceptions) { - ttyLocker ttyl; - ResourceMark rm; -- tty->print_cr("Exception <%s> (" INTPTR_FORMAT ")", except_oop->print_value_string(), (void*)except_oop()); -+ tty->print_cr("Exception <%s> (" INTPTR_FORMAT ")", except_oop->print_value_string(), p2i(except_oop())); - tty->print_cr(" thrown in interpreter method <%s>", METHOD->print_value_string()); - tty->print_cr(" at bci %d, unwinding for thread " INTPTR_FORMAT, -- istate->bcp() - (intptr_t)METHOD->code_base(), -- THREAD); -+ (int)(istate->bcp() - METHOD->code_base()), -+ p2i(THREAD)); - } - // for AbortVMOnException flag - NOT_PRODUCT(Exceptions::debug_check_abort(except_oop)); -@@ -3432,7 +3432,7 @@ - tty->print_cr("osr._osr_buf: " INTPTR_FORMAT, (uintptr_t) this->_result._osr._osr_buf); - tty->print_cr("osr._osr_entry: " INTPTR_FORMAT, (uintptr_t) this->_result._osr._osr_entry); - tty->print_cr("prev_link: " INTPTR_FORMAT, (uintptr_t) this->_prev_link); -- tty->print_cr("native_mirror: " INTPTR_FORMAT, (void*) this->_oop_temp); -+ tty->print_cr("native_mirror: " INTPTR_FORMAT, (uintptr_t) this->_oop_temp); - tty->print_cr("stack_base: " INTPTR_FORMAT, (uintptr_t) this->_stack_base); - tty->print_cr("stack_limit: " INTPTR_FORMAT, (uintptr_t) this->_stack_limit); - tty->print_cr("monitor_base: " INTPTR_FORMAT, (uintptr_t) this->_monitor_base); ---- jdk8/hotspot/src/share/vm/interpreter/bytecodeInterpreterProfiling.hpp 2015-01-27 08:42:53.992817762 +0100 -+++ jdk8/hotspot/src/share/vm/interpreter/bytecodeInterpreterProfiling.hpp 2015-01-27 08:43:45.255624827 +0100 -@@ -86,11 +86,11 @@ - " \t-> " PTR_FORMAT "(%d)", \ - (int) THREAD->osthread()->thread_id(), \ - BCI(), \ -- MDX(), \ -+ p2i(MDX()), \ - (MDX() == NULL \ - ? 0 \ - : istate->method()->method_data()->dp_to_di((address)MDX())), \ -- mdx, \ -+ p2i(mdx), \ - istate->method()->method_data()->dp_to_di((address)mdx) \ - ); \ - }; \ -@@ -107,7 +107,7 @@ - MethodData *md = istate->method()->method_data(); \ - tty->cr(); \ - tty->print("method data at mdx " PTR_FORMAT "(0) for", \ -- md->data_layout_at(md->bci_to_di(0))); \ -+ p2i(md->data_layout_at(md->bci_to_di(0)))); \ - istate->method()->print_short_name(tty); \ - tty->cr(); \ - if (md != NULL) { \ -@@ -115,7 +115,7 @@ - address mdx = (address) MDX(); \ - if (mdx != NULL) { \ - tty->print_cr("current mdx " PTR_FORMAT "(%d)", \ -- mdx, \ -+ p2i(mdx), \ - istate->method()->method_data()->dp_to_di(mdx)); \ - } \ - } else { \ ---- jdk8/hotspot/src/share/vm/interpreter/bytecodes.hpp 2015-01-27 08:42:53.992817762 +0100 -+++ jdk8/hotspot/src/share/vm/interpreter/bytecodes.hpp 2015-01-27 08:43:45.255624827 +0100 -@@ -423,8 +423,10 @@ - static bool is_astore (Code code) { return (code == _astore || code == _astore_0 || code == _astore_1 - || code == _astore_2 || code == _astore_3); } - -+ static bool is_const (Code code) { return (_aconst_null <= code && code <= _ldc2_w); } - static bool is_zero_const (Code code) { return (code == _aconst_null || code == _iconst_0 - || code == _fconst_0 || code == _dconst_0); } -+ static bool is_return (Code code) { return (_ireturn <= code && code <= _return); } - static bool is_invoke (Code code) { return (_invokevirtual <= code && code <= _invokedynamic); } - static bool has_receiver (Code code) { assert(is_invoke(code), ""); return code == _invokevirtual || - code == _invokespecial || ---- jdk8/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp 2015-01-27 08:42:53.992817762 +0100 -+++ jdk8/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp 2015-01-27 08:43:45.256624804 +0100 -@@ -401,6 +401,18 @@ - int handler_bci; - int current_bci = bci(thread); - -+ if (thread->frames_to_pop_failed_realloc() > 0) { -+ // Allocation of scalar replaced object used in this frame -+ // failed. Unconditionally pop the frame. -+ thread->dec_frames_to_pop_failed_realloc(); -+ thread->set_vm_result(h_exception()); -+ // If the method is synchronized we already unlocked the monitor -+ // during deoptimization so the interpreter needs to skip it when -+ // the frame is popped. -+ thread->set_do_not_unlock_if_synchronized(true); -+ return Interpreter::remove_activation_entry(); -+ } -+ - // Need to do this check first since when _do_not_unlock_if_synchronized - // is set, we don't want to trigger any classloading which may make calls - // into java, or surprisingly find a matching exception handler for bci 0 ---- jdk8/hotspot/src/share/vm/interpreter/linkResolver.cpp 2015-01-27 08:42:53.992817762 +0100 -+++ jdk8/hotspot/src/share/vm/interpreter/linkResolver.cpp 2015-01-27 08:43:45.256624804 +0100 -@@ -320,7 +320,7 @@ - // First check in default method array - if (!resolved_method->is_abstract() && - (InstanceKlass::cast(klass())->default_methods() != NULL)) { -- int index = InstanceKlass::find_method_index(InstanceKlass::cast(klass())->default_methods(), name, signature, false); -+ int index = InstanceKlass::find_method_index(InstanceKlass::cast(klass())->default_methods(), name, signature, false, false); - if (index >= 0 ) { - vtable_index = InstanceKlass::cast(klass())->default_vtable_indices()->at(index); - } ---- jdk8/hotspot/src/share/vm/memory/collectorPolicy.cpp 2015-01-27 08:42:53.994817715 +0100 -+++ jdk8/hotspot/src/share/vm/memory/collectorPolicy.cpp 2015-01-27 08:43:45.256624804 +0100 -@@ -183,13 +183,9 @@ - // Requirements of any new remembered set implementations must be added here. - size_t alignment = GenRemSet::max_alignment_constraint(GenRemSet::CardTable); - -- // Parallel GC does its own alignment of the generations to avoid requiring a -- // large page (256M on some platforms) for the permanent generation. The -- // other collectors should also be updated to do their own alignment and then -- // this use of lcm() should be removed. -- if (UseLargePages && !UseParallelGC) { -- // in presence of large pages we have to make sure that our -- // alignment is large page aware -+ if (UseLargePages) { -+ // In presence of large pages we have to make sure that our -+ // alignment is large page aware. - alignment = lcm(os::large_page_size(), alignment); - } - ---- jdk8/hotspot/src/share/vm/memory/filemap.cpp 2015-01-27 08:42:53.994817715 +0100 -+++ jdk8/hotspot/src/share/vm/memory/filemap.cpp 2015-01-27 08:43:45.257624781 +0100 -@@ -97,12 +97,12 @@ - tty->print_cr("UseSharedSpaces: %s", msg); - } - } -- } -- va_end(ap); - UseSharedSpaces = false; - assert(current_info() != NULL, "singleton must be registered"); - current_info()->close(); - } -+ va_end(ap); -+} - - // Fill in the fileMapInfo structure with data about this VM instance. - ---- jdk8/hotspot/src/share/vm/memory/metadataFactory.hpp 2015-01-27 08:42:53.995817692 +0100 -+++ jdk8/hotspot/src/share/vm/memory/metadataFactory.hpp 2015-01-27 08:43:45.257624781 +0100 -@@ -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"); ---- jdk8/hotspot/src/share/vm/memory/metaspace.cpp 2015-01-27 08:42:53.995817692 +0100 -+++ jdk8/hotspot/src/share/vm/memory/metaspace.cpp 2015-01-27 08:43:45.257624781 +0100 -@@ -3181,7 +3181,7 @@ - MetaspaceGC::initialize(); - - // Initialize the alignment for shared spaces. -- int max_alignment = os::vm_page_size(); -+ int max_alignment = os::vm_allocation_granularity(); - size_t cds_total = 0; - - MetaspaceShared::set_max_alignment(max_alignment); -@@ -3195,6 +3195,16 @@ - SharedMiscDataSize = align_size_up(SharedMiscDataSize, max_alignment); - SharedMiscCodeSize = align_size_up(SharedMiscCodeSize, max_alignment); - -+ // the min_misc_code_size estimate is based on MetaspaceShared::generate_vtable_methods() -+ uintx min_misc_code_size = align_size_up( -+ (MetaspaceShared::num_virtuals * MetaspaceShared::vtbl_list_size) * -+ (sizeof(void*) + MetaspaceShared::vtbl_method_size) + MetaspaceShared::vtbl_common_code_size, -+ max_alignment); -+ -+ if (SharedMiscCodeSize < min_misc_code_size) { -+ report_out_of_shared_space(SharedMiscCode); -+ } -+ - // Initialize with the sum of the shared space sizes. The read-only - // and read write metaspace chunks will be allocated out of this and the - // remainder is the misc code and data chunks. ---- jdk8/hotspot/src/share/vm/memory/metaspaceShared.cpp 2015-01-27 08:42:53.995817692 +0100 -+++ jdk8/hotspot/src/share/vm/memory/metaspaceShared.cpp 2015-01-27 08:43:45.258624758 +0100 -@@ -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); - } -@@ -845,7 +851,7 @@ - ik->link_class(THREAD); - if (HAS_PENDING_EXCEPTION) { - ResourceMark rm; -- tty->print_cr("Preload Error: Verification failed for %s", -+ tty->print_cr("Preload Warning: Verification failed for %s", - ik->external_name()); - CLEAR_PENDING_EXCEPTION; - ik->set_in_error_state(); -@@ -961,7 +967,7 @@ - #endif - // If -Xshare:on is specified, print out the error message and exit VM, - // otherwise, set UseSharedSpaces to false and continue. -- if (RequireSharedSpaces) { -+ if (RequireSharedSpaces || PrintSharedArchiveAndExit) { - vm_exit_during_initialization("Unable to use shared archive.", "Failed map_region for using -Xshare:on."); - } else { - FLAG_SET_DEFAULT(UseSharedSpaces, false); -@@ -1060,6 +1066,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); ---- jdk8/hotspot/src/share/vm/memory/metaspaceShared.hpp 2015-01-27 08:42:53.995817692 +0100 -+++ jdk8/hotspot/src/share/vm/memory/metaspaceShared.hpp 2015-01-27 08:43:45.258624758 +0100 -@@ -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 -@@ -58,10 +58,15 @@ - public: - enum { - vtbl_list_size = 17, // number of entries in the shared space vtable list. -- num_virtuals = 200 // maximum number of virtual functions -+ num_virtuals = 200, // maximum number of virtual functions - // If virtual functions are added to Metadata, - // this number needs to be increased. Also, - // SharedMiscCodeSize will need to be increased. -+ // The following 2 sizes were based on -+ // MetaspaceShared::generate_vtable_methods() -+ vtbl_method_size = 16, // conservative size of the mov1 and jmp instructions -+ // for the x64 platform -+ vtbl_common_code_size = (1*K) // conservative size of the "common_code" for the x64 platform - }; - - enum { ---- jdk8/hotspot/src/share/vm/memory/referenceProcessor.cpp 2015-01-27 08:42:53.995817692 +0100 -+++ jdk8/hotspot/src/share/vm/memory/referenceProcessor.cpp 2015-01-27 08:43:45.258624758 +0100 -@@ -118,6 +118,7 @@ - _discoveredWeakRefs = &_discoveredSoftRefs[_max_num_q]; - _discoveredFinalRefs = &_discoveredWeakRefs[_max_num_q]; - _discoveredPhantomRefs = &_discoveredFinalRefs[_max_num_q]; -+ _discoveredCleanerRefs = &_discoveredPhantomRefs[_max_num_q]; - - // Initialize all entries to NULL - for (uint i = 0; i < _max_num_q * number_of_subclasses_of_ref(); i++) { -@@ -246,6 +247,13 @@ - phantom_count = - process_discovered_reflist(_discoveredPhantomRefs, NULL, false, - is_alive, keep_alive, complete_gc, task_executor); -+ -+ // Process cleaners, but include them in phantom statistics. We expect -+ // Cleaner references to be temporary, and don't want to deal with -+ // possible incompatibilities arising from making it more visible. -+ phantom_count += -+ process_discovered_reflist(_discoveredCleanerRefs, NULL, false, -+ is_alive, keep_alive, complete_gc, task_executor); - } - - // Weak global JNI references. It would make more sense (semantically) to -@@ -883,6 +891,7 @@ - balance_queues(_discoveredWeakRefs); - balance_queues(_discoveredFinalRefs); - balance_queues(_discoveredPhantomRefs); -+ balance_queues(_discoveredCleanerRefs); - } - - size_t -@@ -1042,6 +1051,9 @@ - case REF_PHANTOM: - list = &_discoveredPhantomRefs[id]; - break; -+ case REF_CLEANER: -+ list = &_discoveredCleanerRefs[id]; -+ break; - case REF_NONE: - // we should not reach here if we are an InstanceRefKlass - default: -@@ -1307,6 +1319,17 @@ - preclean_discovered_reflist(_discoveredPhantomRefs[i], is_alive, - keep_alive, complete_gc, yield); - } -+ -+ // Cleaner references. Included in timing for phantom references. We -+ // expect Cleaner references to be temporary, and don't want to deal with -+ // possible incompatibilities arising from making it more visible. -+ for (uint i = 0; i < _max_num_q; i++) { -+ if (yield->should_return()) { -+ return; -+ } -+ preclean_discovered_reflist(_discoveredCleanerRefs[i], is_alive, -+ keep_alive, complete_gc, yield); -+ } - } - } - -@@ -1375,6 +1398,7 @@ - case 1: return "WeakRef"; - case 2: return "FinalRef"; - case 3: return "PhantomRef"; -+ case 4: return "CleanerRef"; - } - ShouldNotReachHere(); - return NULL; ---- jdk8/hotspot/src/share/vm/memory/referenceProcessor.hpp 2015-01-27 08:42:53.995817692 +0100 -+++ jdk8/hotspot/src/share/vm/memory/referenceProcessor.hpp 2015-01-27 08:43:45.258624758 +0100 -@@ -264,9 +264,10 @@ - DiscoveredList* _discoveredWeakRefs; - DiscoveredList* _discoveredFinalRefs; - DiscoveredList* _discoveredPhantomRefs; -+ DiscoveredList* _discoveredCleanerRefs; - - public: -- static int number_of_subclasses_of_ref() { return (REF_PHANTOM - REF_OTHER); } -+ static int number_of_subclasses_of_ref() { return (REF_CLEANER - REF_OTHER); } - - uint num_q() { return _num_q; } - uint max_num_q() { return _max_num_q; } ---- jdk8/hotspot/src/share/vm/memory/referenceType.hpp 2015-01-27 08:42:53.995817692 +0100 -+++ jdk8/hotspot/src/share/vm/memory/referenceType.hpp 2015-01-27 08:43:45.259624734 +0100 -@@ -35,7 +35,8 @@ - REF_SOFT, // Subclass of java/lang/ref/SoftReference - REF_WEAK, // Subclass of java/lang/ref/WeakReference - REF_FINAL, // Subclass of java/lang/ref/FinalReference -- REF_PHANTOM // Subclass of java/lang/ref/PhantomReference -+ REF_PHANTOM, // Subclass of java/lang/ref/PhantomReference -+ REF_CLEANER // Subclass of sun/misc/Cleaner - }; - - #endif // SHARE_VM_MEMORY_REFRERENCETYPE_HPP ---- jdk8/hotspot/src/share/vm/memory/threadLocalAllocBuffer.cpp 2015-01-27 08:42:53.996817669 +0100 -+++ jdk8/hotspot/src/share/vm/memory/threadLocalAllocBuffer.cpp 2015-01-27 08:43:45.259624734 +0100 -@@ -235,22 +235,19 @@ - } - - size_t ThreadLocalAllocBuffer::initial_desired_size() { -- size_t init_sz; -+ size_t init_sz = 0; - - if (TLABSize > 0) { -- init_sz = MIN2(TLABSize / HeapWordSize, max_size()); -- } else if (global_stats() == NULL) { -- // Startup issue - main thread initialized before heap initialized. -- init_sz = min_size(); -- } else { -+ init_sz = TLABSize / HeapWordSize; -+ } else if (global_stats() != NULL) { - // Initial size is a function of the average number of allocating threads. - unsigned nof_threads = global_stats()->allocating_threads_avg(); - - init_sz = (Universe::heap()->tlab_capacity(myThread()) / HeapWordSize) / - (nof_threads * target_refills()); - init_sz = align_object_size(init_sz); -- init_sz = MIN2(MAX2(init_sz, min_size()), max_size()); - } -+ init_sz = MIN2(MAX2(init_sz, min_size()), max_size()); - return init_sz; - } - ---- jdk8/hotspot/src/share/vm/memory/threadLocalAllocBuffer.hpp 2015-01-27 08:42:53.996817669 +0100 -+++ jdk8/hotspot/src/share/vm/memory/threadLocalAllocBuffer.hpp 2015-01-27 08:43:45.259624734 +0100 -@@ -105,7 +105,7 @@ - // do nothing. tlabs must be inited by initialize() calls - } - -- static const size_t min_size() { return align_object_size(MinTLABSize / HeapWordSize); } -+ static const size_t min_size() { return align_object_size(MinTLABSize / HeapWordSize) + alignment_reserve(); } - static const size_t max_size() { assert(_max_size != 0, "max_size not set up"); return _max_size; } - static void set_max_size(size_t max_size) { _max_size = max_size; } - ---- jdk8/hotspot/src/share/vm/memory/universe.cpp 2015-01-27 08:42:53.996817669 +0100 -+++ jdk8/hotspot/src/share/vm/memory/universe.cpp 2015-01-27 08:43:45.259624734 +0100 -@@ -78,7 +78,7 @@ - #include "gc_implementation/concurrentMarkSweep/cmsAdaptiveSizePolicy.hpp" - #include "gc_implementation/concurrentMarkSweep/cmsCollectorPolicy.hpp" - #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" --#include "gc_implementation/g1/g1CollectorPolicy.hpp" -+#include "gc_implementation/g1/g1CollectorPolicy_ext.hpp" - #include "gc_implementation/parallelScavenge/parallelScavengeHeap.hpp" - #endif // INCLUDE_ALL_GCS - -@@ -119,6 +119,7 @@ - oop Universe::_out_of_memory_error_class_metaspace = NULL; - oop Universe::_out_of_memory_error_array_size = NULL; - oop Universe::_out_of_memory_error_gc_overhead_limit = NULL; -+oop Universe::_out_of_memory_error_realloc_objects = NULL; - objArrayOop Universe::_preallocated_out_of_memory_error_array = NULL; - volatile jint Universe::_preallocated_out_of_memory_error_avail_count = 0; - bool Universe::_verify_in_progress = false; -@@ -190,6 +191,7 @@ - f->do_oop((oop*)&_out_of_memory_error_class_metaspace); - f->do_oop((oop*)&_out_of_memory_error_array_size); - f->do_oop((oop*)&_out_of_memory_error_gc_overhead_limit); -+ f->do_oop((oop*)&_out_of_memory_error_realloc_objects); - f->do_oop((oop*)&_preallocated_out_of_memory_error_array); - f->do_oop((oop*)&_null_ptr_exception_instance); - f->do_oop((oop*)&_arithmetic_exception_instance); -@@ -574,7 +576,8 @@ - (throwable() != Universe::_out_of_memory_error_metaspace) && - (throwable() != Universe::_out_of_memory_error_class_metaspace) && - (throwable() != Universe::_out_of_memory_error_array_size) && -- (throwable() != Universe::_out_of_memory_error_gc_overhead_limit)); -+ (throwable() != Universe::_out_of_memory_error_gc_overhead_limit) && -+ (throwable() != Universe::_out_of_memory_error_realloc_objects)); - } - - -@@ -798,7 +801,7 @@ - - } else if (UseG1GC) { - #if INCLUDE_ALL_GCS -- G1CollectorPolicy* g1p = new G1CollectorPolicy(); -+ G1CollectorPolicyExt* g1p = new G1CollectorPolicyExt(); - g1p->initialize_all(); - G1CollectedHeap* g1h = new G1CollectedHeap(g1p); - Universe::_collectedHeap = g1h; -@@ -1044,6 +1047,7 @@ - Universe::_out_of_memory_error_array_size = k_h->allocate_instance(CHECK_false); - Universe::_out_of_memory_error_gc_overhead_limit = - k_h->allocate_instance(CHECK_false); -+ Universe::_out_of_memory_error_realloc_objects = k_h->allocate_instance(CHECK_false); - - // Setup preallocated NullPointerException - // (this is currently used for a cheap & dirty solution in compiler exception handling) -@@ -1083,6 +1087,9 @@ - msg = java_lang_String::create_from_str("GC overhead limit exceeded", CHECK_false); - java_lang_Throwable::set_message(Universe::_out_of_memory_error_gc_overhead_limit, msg()); - -+ msg = java_lang_String::create_from_str("Java heap space: failed reallocation of scalar replaced objects", CHECK_false); -+ java_lang_Throwable::set_message(Universe::_out_of_memory_error_realloc_objects, msg()); -+ - msg = java_lang_String::create_from_str("/ by zero", CHECK_false); - java_lang_Throwable::set_message(Universe::_arithmetic_exception_instance, msg()); - ---- jdk8/hotspot/src/share/vm/memory/universe.hpp 2015-01-27 08:42:53.996817669 +0100 -+++ jdk8/hotspot/src/share/vm/memory/universe.hpp 2015-01-27 08:43:45.259624734 +0100 -@@ -157,6 +157,7 @@ - static oop _out_of_memory_error_class_metaspace; - static oop _out_of_memory_error_array_size; - static oop _out_of_memory_error_gc_overhead_limit; -+ static oop _out_of_memory_error_realloc_objects; - - static Array* _the_empty_int_array; // Canonicalized int array - static Array* _the_empty_short_array; // Canonicalized short array -@@ -328,6 +329,7 @@ - static oop out_of_memory_error_class_metaspace() { return gen_out_of_memory_error(_out_of_memory_error_class_metaspace); } - static oop out_of_memory_error_array_size() { return gen_out_of_memory_error(_out_of_memory_error_array_size); } - static oop out_of_memory_error_gc_overhead_limit() { return gen_out_of_memory_error(_out_of_memory_error_gc_overhead_limit); } -+ static oop out_of_memory_error_realloc_objects() { return gen_out_of_memory_error(_out_of_memory_error_realloc_objects); } - - // Accessors needed for fast allocation - static Klass** boolArrayKlassObj_addr() { return &_boolArrayKlassObj; } ---- jdk8/hotspot/src/share/vm/oops/constantPool.cpp 2015-01-27 08:42:53.996817669 +0100 -+++ jdk8/hotspot/src/share/vm/oops/constantPool.cpp 2015-01-27 08:43:45.260624711 +0100 -@@ -1817,11 +1817,22 @@ - - void ConstantPool::set_on_stack(const bool value) { - if (value) { -- _flags |= _on_stack; -+ int old_flags = *const_cast(&_flags); -+ while ((old_flags & _on_stack) == 0) { -+ int new_flags = old_flags | _on_stack; -+ int result = Atomic::cmpxchg(new_flags, &_flags, old_flags); -+ -+ if (result == old_flags) { -+ // Succeeded. -+ MetadataOnStackMark::record(this, Thread::current()); -+ return; -+ } -+ old_flags = result; -+ } - } else { -+ // Clearing is done single-threadedly. - _flags &= ~_on_stack; - } -- if (value) MetadataOnStackMark::record(this); - } - - // JSR 292 support for patching constant pool oops after the class is linked and ---- jdk8/hotspot/src/share/vm/oops/instanceKlass.cpp 2015-01-27 08:42:53.997817645 +0100 -+++ jdk8/hotspot/src/share/vm/oops/instanceKlass.cpp 2015-01-27 08:43:45.261624688 +0100 -@@ -780,6 +780,41 @@ - } - } - -+// Eagerly initialize superinterfaces that declare default methods (concrete instance: any access) -+void InstanceKlass::initialize_super_interfaces(instanceKlassHandle this_oop, TRAPS) { -+ if (this_oop->has_default_methods()) { -+ for (int i = 0; i < this_oop->local_interfaces()->length(); ++i) { -+ Klass* iface = this_oop->local_interfaces()->at(i); -+ InstanceKlass* ik = InstanceKlass::cast(iface); -+ if (ik->should_be_initialized()) { -+ if (ik->has_default_methods()) { -+ ik->initialize_super_interfaces(ik, THREAD); -+ } -+ // Only initialize() interfaces that "declare" concrete methods. -+ // has_default_methods drives searching superinterfaces since it -+ // means has_default_methods in its superinterface hierarchy -+ if (!HAS_PENDING_EXCEPTION && ik->declares_default_methods()) { -+ ik->initialize(THREAD); -+ } -+ if (HAS_PENDING_EXCEPTION) { -+ Handle e(THREAD, PENDING_EXCEPTION); -+ CLEAR_PENDING_EXCEPTION; -+ { -+ EXCEPTION_MARK; -+ // Locks object, set state, and notify all waiting threads -+ this_oop->set_initialization_state_and_notify( -+ initialization_error, THREAD); -+ -+ // ignore any exception thrown, superclass initialization error is -+ // thrown below -+ CLEAR_PENDING_EXCEPTION; -+ } -+ THROW_OOP(e()); -+ } -+ } -+ } -+ } -+} - - void InstanceKlass::initialize_impl(instanceKlassHandle this_oop, TRAPS) { - // Make sure klass is linked (verified) before initialization -@@ -859,33 +894,11 @@ - } - } - -+ // Recursively initialize any superinterfaces that declare default methods -+ // Only need to recurse if has_default_methods which includes declaring and -+ // inheriting default methods - if (this_oop->has_default_methods()) { -- // Step 7.5: initialize any interfaces which have default methods -- for (int i = 0; i < this_oop->local_interfaces()->length(); ++i) { -- Klass* iface = this_oop->local_interfaces()->at(i); -- InstanceKlass* ik = InstanceKlass::cast(iface); -- if (ik->has_default_methods() && ik->should_be_initialized()) { -- ik->initialize(THREAD); -- -- if (HAS_PENDING_EXCEPTION) { -- Handle e(THREAD, PENDING_EXCEPTION); -- CLEAR_PENDING_EXCEPTION; -- { -- EXCEPTION_MARK; -- // Locks object, set state, and notify all waiting threads -- this_oop->set_initialization_state_and_notify( -- initialization_error, THREAD); -- -- // ignore any exception thrown, superclass initialization error is -- // thrown below -- CLEAR_PENDING_EXCEPTION; -- } -- DTRACE_CLASSINIT_PROBE_WAIT( -- super__failed, InstanceKlass::cast(this_oop()), -1, wait); -- THROW_OOP(e()); -- } -- } -- } -+ this_oop->initialize_super_interfaces(this_oop, CHECK); - } - - // Step 8 -@@ -1440,32 +1453,41 @@ - } - - Method* InstanceKlass::find_method_impl(Symbol* name, Symbol* signature, bool skipping_overpass) const { -- return InstanceKlass::find_method_impl(methods(), name, signature, skipping_overpass); -+ return InstanceKlass::find_method_impl(methods(), name, signature, skipping_overpass, false); - } - - // find_instance_method looks up the name/signature in the local methods array - // and skips over static methods - Method* InstanceKlass::find_instance_method( - Array* methods, Symbol* name, Symbol* signature) { -- Method* meth = InstanceKlass::find_method(methods, name, signature); -- if (meth != NULL && meth->is_static()) { -- meth = NULL; -- } -+ Method* meth = InstanceKlass::find_method_impl(methods, name, signature, false, true); - return meth; - } - -+// find_instance_method looks up the name/signature in the local methods array -+// and skips over static methods -+Method* InstanceKlass::find_instance_method(Symbol* name, Symbol* signature) { -+ return InstanceKlass::find_instance_method(methods(), name, signature); -+} -+ - // find_method looks up the name/signature in the local methods array - Method* InstanceKlass::find_method( - Array* methods, Symbol* name, Symbol* signature) { -- return InstanceKlass::find_method_impl(methods, name, signature, false); -+ return InstanceKlass::find_method_impl(methods, name, signature, false, false); - } - - Method* InstanceKlass::find_method_impl( -- Array* methods, Symbol* name, Symbol* signature, bool skipping_overpass) { -- int hit = find_method_index(methods, name, signature, skipping_overpass); -+ Array* methods, Symbol* name, Symbol* signature, bool skipping_overpass, bool skipping_static) { -+ int hit = find_method_index(methods, name, signature, skipping_overpass, skipping_static); - return hit >= 0 ? methods->at(hit): NULL; - } - -+bool InstanceKlass::method_matches(Method* m, Symbol* signature, bool skipping_overpass, bool skipping_static) { -+ return (m->signature() == signature) && -+ (!skipping_overpass || !m->is_overpass()) && -+ (!skipping_static || !m->is_static()); -+} -+ - // Used directly for default_methods to find the index into the - // default_vtable_indices, and indirectly by find_method - // find_method_index looks in the local methods array to return the index -@@ -1474,7 +1496,7 @@ - // is important during method resolution to prefer a static method, for example, - // over an overpass method. - int InstanceKlass::find_method_index( -- Array* methods, Symbol* name, Symbol* signature, bool skipping_overpass) { -+ Array* methods, Symbol* name, Symbol* signature, bool skipping_overpass, bool skipping_static) { - int hit = binary_search(methods, name); - if (hit != -1) { - Method* m = methods->at(hit); -@@ -1478,9 +1500,10 @@ - int hit = binary_search(methods, name); - if (hit != -1) { - Method* m = methods->at(hit); -+ - // Do linear search to find matching signature. First, quick check - // for common case, ignoring overpasses if requested. -- if ((m->signature() == signature) && (!skipping_overpass || !m->is_overpass())) return hit; -+ if (method_matches(m, signature, skipping_overpass, skipping_static)) return hit; - - // search downwards through overloaded methods - int i; -@@ -1488,18 +1511,18 @@ - Method* m = methods->at(i); - assert(m->is_method(), "must be method"); - if (m->name() != name) break; -- if ((m->signature() == signature) && (!skipping_overpass || !m->is_overpass())) return i; -+ if (method_matches(m, signature, skipping_overpass, skipping_static)) return i; - } - // search upwards - for (i = hit + 1; i < methods->length(); ++i) { - Method* m = methods->at(i); - assert(m->is_method(), "must be method"); - if (m->name() != name) break; -- if ((m->signature() == signature) && (!skipping_overpass || !m->is_overpass())) return i; -+ if (method_matches(m, signature, skipping_overpass, skipping_static)) return i; - } - // not found - #ifdef ASSERT -- int index = skipping_overpass ? -1 : linear_search(methods, name, signature); -+ int index = skipping_overpass || skipping_static ? -1 : linear_search(methods, name, signature); - assert(index == -1, err_msg("binary search should have found entry %d", index)); - #endif - } -@@ -2877,6 +2900,22 @@ - OsrList_lock->unlock(); - } - -+int InstanceKlass::mark_osr_nmethods(const Method* m) { -+ // This is a short non-blocking critical region, so the no safepoint check is ok. -+ MutexLockerEx ml(OsrList_lock, Mutex::_no_safepoint_check_flag); -+ nmethod* osr = osr_nmethods_head(); -+ int found = 0; -+ while (osr != NULL) { -+ assert(osr->is_osr_method(), "wrong kind of nmethod found in chain"); -+ if (osr->method() == m) { -+ osr->mark_for_deoptimization(); -+ found++; -+ } -+ osr = osr->osr_link(); -+ } -+ return found; -+} -+ - nmethod* InstanceKlass::lookup_osr_nmethod(const Method* m, int bci, int comp_level, bool match_level) const { - // This is a short non-blocking critical region, so the no safepoint check is ok. - OsrList_lock->lock_without_safepoint_check(); -@@ -2918,28 +2957,27 @@ - return NULL; - } - --void InstanceKlass::add_member_name(int index, Handle mem_name) { -+bool InstanceKlass::add_member_name(Handle mem_name) { - jweak mem_name_wref = JNIHandles::make_weak_global(mem_name); - MutexLocker ml(MemberNameTable_lock); -- assert(0 <= index && index < idnum_allocated_count(), "index is out of bounds"); - DEBUG_ONLY(No_Safepoint_Verifier nsv); - -- if (_member_names == NULL) { -- _member_names = new (ResourceObj::C_HEAP, mtClass) MemberNameTable(idnum_allocated_count()); -- } -- _member_names->add_member_name(index, mem_name_wref); -+ // Check if method has been redefined while taking out MemberNameTable_lock, if so -+ // return false. We cannot cache obsolete methods. They will crash when the function -+ // is called! -+ Method* method = (Method*)java_lang_invoke_MemberName::vmtarget(mem_name()); -+ if (method->is_obsolete()) { -+ return false; -+ } else if (method->is_old()) { -+ // Replace method with redefined version -+ java_lang_invoke_MemberName::set_vmtarget(mem_name(), method_with_idnum(method->method_idnum())); - } - --oop InstanceKlass::get_member_name(int index) { -- MutexLocker ml(MemberNameTable_lock); -- assert(0 <= index && index < idnum_allocated_count(), "index is out of bounds"); -- DEBUG_ONLY(No_Safepoint_Verifier nsv); -- - if (_member_names == NULL) { -- return NULL; -+ _member_names = new (ResourceObj::C_HEAP, mtClass) MemberNameTable(idnum_allocated_count()); - } -- oop mem_name =_member_names->get_member_name(index); -- return mem_name; -+ _member_names->add_member_name(mem_name_wref); -+ return true; - } - - // ----------------------------------------------------------------------------------------------------- ---- jdk8/hotspot/src/share/vm/oops/instanceKlass.hpp 2015-01-27 08:42:53.997817645 +0100 -+++ jdk8/hotspot/src/share/vm/oops/instanceKlass.hpp 2015-01-27 08:43:45.261624688 +0100 -@@ -234,7 +234,8 @@ - _misc_should_verify_class = 1 << 2, // allow caching of preverification - _misc_is_anonymous = 1 << 3, // has embedded _host_klass field - _misc_is_contended = 1 << 4, // marked with contended annotation -- _misc_has_default_methods = 1 << 5 // class/superclass/implemented interfaces has default methods -+ _misc_has_default_methods = 1 << 5, // class/superclass/implemented interfaces has default methods -+ _misc_declares_default_methods = 1 << 6 // directly declares default methods (any access) - }; - u2 _misc_flags; - u2 _minor_version; // minor version number of class file -@@ -519,10 +520,16 @@ - // find a local method (returns NULL if not found) - Method* find_method(Symbol* name, Symbol* signature) const; - static Method* find_method(Array* methods, Symbol* name, Symbol* signature); -+ -+ // find a local method, but skip static methods -+ Method* find_instance_method(Symbol* name, Symbol* signature); - static Method* find_instance_method(Array* methods, Symbol* name, Symbol* signature); - -+ // true if method matches signature and conforms to skipping_X conditions. -+ static bool method_matches(Method* m, Symbol* signature, bool skipping_overpass, bool skipping_static); -+ - // find a local method index in default_methods (returns -1 if not found) -- static int find_method_index(Array* methods, Symbol* name, Symbol* signature, bool skipping_overpass); -+ static int find_method_index(Array* methods, Symbol* name, Symbol* signature, bool skipping_overpass, bool skipping_static); - - // lookup operation (returns NULL if not found) - Method* uncached_lookup_method(Symbol* name, Symbol* signature, MethodLookupMode mode) const; -@@ -680,6 +687,17 @@ - } - } - -+ bool declares_default_methods() const { -+ return (_misc_flags & _misc_declares_default_methods) != 0; -+ } -+ void set_declares_default_methods(bool b) { -+ if (b) { -+ _misc_flags |= _misc_declares_default_methods; -+ } else { -+ _misc_flags &= ~_misc_declares_default_methods; -+ } -+ } -+ - // for adding methods, ConstMethod::UNSET_IDNUM means no more ids available - inline u2 next_method_idnum(); - void set_initial_method_idnum(u2 value) { _idnum_allocated_count = value; } -@@ -771,6 +789,7 @@ - void set_osr_nmethods_head(nmethod* h) { _osr_nmethods_head = h; }; - void add_osr_nmethod(nmethod* n); - void remove_osr_nmethod(nmethod* n); -+ int mark_osr_nmethods(const Method* m); - nmethod* lookup_osr_nmethod(const Method* m, int bci, int level, bool match_level) const; - - // Breakpoint support (see methods on Method* for details) -@@ -1046,6 +1065,7 @@ - static bool link_class_impl (instanceKlassHandle this_oop, bool throw_verifyerror, TRAPS); - static bool verify_code (instanceKlassHandle this_oop, bool throw_verifyerror, TRAPS); - static void initialize_impl (instanceKlassHandle this_oop, TRAPS); -+ static void initialize_super_interfaces (instanceKlassHandle this_oop, TRAPS); - static void eager_initialize_impl (instanceKlassHandle this_oop); - static void set_initialization_state_and_notify_impl (instanceKlassHandle this_oop, ClassState state, TRAPS); - static void call_class_initializer_impl (instanceKlassHandle this_oop, TRAPS); -@@ -1062,7 +1082,7 @@ - - // find a local method (returns NULL if not found) - Method* find_method_impl(Symbol* name, Symbol* signature, bool skipping_overpass) const; -- static Method* find_method_impl(Array* methods, Symbol* name, Symbol* signature, bool skipping_overpass); -+ static Method* find_method_impl(Array* methods, Symbol* name, Symbol* signature, bool skipping_overpass, bool skipping_static); - - // Free CHeap allocated fields. - void release_C_heap_structures(); -@@ -1077,8 +1097,7 @@ - // JSR-292 support - MemberNameTable* member_names() { return _member_names; } - void set_member_names(MemberNameTable* member_names) { _member_names = member_names; } -- void add_member_name(int index, Handle member_name); -- oop get_member_name(int index); -+ bool add_member_name(Handle member_name); - - public: - // JVMTI support ---- jdk8/hotspot/src/share/vm/oops/method.cpp 2015-01-27 08:42:53.997817645 +0100 -+++ jdk8/hotspot/src/share/vm/oops/method.cpp 2015-01-27 08:43:45.261624688 +0100 -@@ -563,6 +563,15 @@ - return true; - } - -+bool Method::is_constant_getter() const { -+ int last_index = code_size() - 1; -+ // Check if the first 1-3 bytecodes are a constant push -+ // and the last bytecode is a return. -+ return (2 <= code_size() && code_size() <= 4 && -+ Bytecodes::is_const(java_code_at(0)) && -+ Bytecodes::length_for(java_code_at(0)) == last_index && -+ Bytecodes::is_return(java_code_at(last_index))); -+} - - bool Method::is_initializer() const { - return name() == vmSymbols::object_initializer_name() || is_static_initializer(); -@@ -1880,9 +1889,12 @@ - void Method::set_on_stack(const bool value) { - // Set both the method itself and its constant pool. The constant pool - // on stack means some method referring to it is also on the stack. -- _access_flags.set_on_stack(value); - constants()->set_on_stack(value); -- if (value) MetadataOnStackMark::record(this); -+ -+ bool succeeded = _access_flags.set_on_stack(value); -+ if (value && succeeded) { -+ MetadataOnStackMark::record(this, Thread::current()); -+ } - } - - // Called when the class loader is unloaded to make all methods weak. ---- jdk8/hotspot/src/share/vm/oops/methodData.cpp 2015-01-27 08:42:53.998817622 +0100 -+++ jdk8/hotspot/src/share/vm/oops/methodData.cpp 2015-01-27 08:43:45.262624664 +0100 -@@ -1153,7 +1153,7 @@ - _backedge_counter_start = 0; - _num_loops = 0; - _num_blocks = 0; -- _would_profile = true; -+ _would_profile = unknown; - - #if INCLUDE_RTM_OPT - _rtm_state = NoRTM; // No RTM lock eliding by default ---- jdk8/hotspot/src/share/vm/oops/methodData.hpp 2015-01-27 08:42:53.998817622 +0100 -+++ jdk8/hotspot/src/share/vm/oops/methodData.hpp 2015-01-27 08:43:45.262624664 +0100 -@@ -2099,7 +2099,8 @@ - short _num_loops; - short _num_blocks; - // Does this method contain anything worth profiling? -- bool _would_profile; -+ enum WouldProfile {unknown, no_profile, profile}; -+ WouldProfile _would_profile; - - // Size of _data array in bytes. (Excludes header and extra_data fields.) - int _data_size; -@@ -2268,8 +2269,8 @@ - } - #endif - -- void set_would_profile(bool p) { _would_profile = p; } -- bool would_profile() const { return _would_profile; } -+ void set_would_profile(bool p) { _would_profile = p ? profile : no_profile; } -+ bool would_profile() const { return _would_profile != no_profile; } - - int num_loops() const { return _num_loops; } - void set_num_loops(int n) { _num_loops = n; } ---- jdk8/hotspot/src/share/vm/oops/method.hpp 2015-01-27 08:42:53.997817645 +0100 -+++ jdk8/hotspot/src/share/vm/oops/method.hpp 2015-01-27 08:43:45.262624664 +0100 -@@ -624,6 +624,9 @@ - // returns true if the method is an accessor function (setter/getter). - bool is_accessor() const; - -+ // returns true if the method does nothing but return a constant of primitive type -+ bool is_constant_getter() const; -+ - // returns true if the method is an initializer ( or ). - bool is_initializer() const; - -@@ -798,6 +801,10 @@ - return method_holder()->lookup_osr_nmethod(this, InvocationEntryBci, level, match_level) != NULL; - } - -+ int mark_osr_nmethods() { -+ return method_holder()->mark_osr_nmethods(this); -+ } -+ - nmethod* lookup_osr_nmethod_for(int bci, int level, bool match_level) { - return method_holder()->lookup_osr_nmethod(this, bci, level, match_level); - } ---- jdk8/hotspot/src/share/vm/oops/objArrayOop.hpp 2015-01-27 08:42:53.998817622 +0100 -+++ jdk8/hotspot/src/share/vm/oops/objArrayOop.hpp 2015-01-27 08:43:45.263624641 +0100 -@@ -45,9 +45,10 @@ - private: - // Give size of objArrayOop in HeapWords minus the header - static int array_size(int length) { -- const int OopsPerHeapWord = HeapWordSize/heapOopSize; -+ const uint OopsPerHeapWord = HeapWordSize/heapOopSize; - assert(OopsPerHeapWord >= 1 && (HeapWordSize % heapOopSize == 0), - "Else the following (new) computation would be in error"); -+ uint res = ((uint)length + OopsPerHeapWord - 1)/OopsPerHeapWord; - #ifdef ASSERT - // The old code is left in for sanity-checking; it'll - // go away pretty soon. XXX -@@ -55,16 +56,15 @@ - // oop->length() * HeapWordsPerOop; - // With narrowOops, HeapWordsPerOop is 1/2 or equal 0 as an integer. - // The oop elements are aligned up to wordSize -- const int HeapWordsPerOop = heapOopSize/HeapWordSize; -- int old_res; -+ const uint HeapWordsPerOop = heapOopSize/HeapWordSize; -+ uint old_res; - if (HeapWordsPerOop > 0) { - old_res = length * HeapWordsPerOop; - } else { -- old_res = align_size_up(length, OopsPerHeapWord)/OopsPerHeapWord; -+ old_res = align_size_up((uint)length, OopsPerHeapWord)/OopsPerHeapWord; - } --#endif // ASSERT -- int res = ((uint)length + OopsPerHeapWord - 1)/OopsPerHeapWord; - assert(res == old_res, "Inconsistency between old and new."); -+#endif // ASSERT - return res; - } - ---- jdk8/hotspot/src/share/vm/oops/typeArrayOop.hpp 2015-01-27 08:42:53.998817622 +0100 -+++ jdk8/hotspot/src/share/vm/oops/typeArrayOop.hpp 2015-01-27 08:43:45.263624641 +0100 -@@ -150,7 +150,7 @@ - DEBUG_ONLY(BasicType etype = Klass::layout_helper_element_type(lh)); - assert(length <= arrayOopDesc::max_array_length(etype), "no overflow"); - -- julong size_in_bytes = length; -+ julong size_in_bytes = (juint)length; - size_in_bytes <<= element_shift; - size_in_bytes += instance_header_size; - julong size_in_words = ((size_in_bytes + (HeapWordSize-1)) >> LogHeapWordSize); ---- jdk8/hotspot/src/share/vm/opto/c2_globals.hpp 2015-01-27 08:42:53.999817599 +0100 -+++ jdk8/hotspot/src/share/vm/opto/c2_globals.hpp 2015-01-27 08:43:45.263624641 +0100 -@@ -476,6 +476,9 @@ - product(bool, DoEscapeAnalysis, true, \ - "Perform escape analysis") \ - \ -+ product(double, EscapeAnalysisTimeout, 20. DEBUG_ONLY(+40.), \ -+ "Abort EA when it reaches time limit (in sec)") \ -+ \ - develop(bool, ExitEscapeAnalysisOnTimeout, true, \ - "Exit or throw assert in EA when it reaches time limit") \ - \ -@@ -647,7 +650,7 @@ - develop(bool, AlwaysIncrementalInline, false, \ - "do all inlining incrementally") \ - \ -- product(intx, LiveNodeCountInliningCutoff, 20000, \ -+ product(intx, LiveNodeCountInliningCutoff, 40000, \ - "max number of live nodes in a method") \ - \ - diagnostic(bool, OptimizeExpensiveOps, true, \ ---- jdk8/hotspot/src/share/vm/opto/callGenerator.cpp 2015-01-27 08:42:53.999817599 +0100 -+++ jdk8/hotspot/src/share/vm/opto/callGenerator.cpp 2015-01-27 08:43:45.263624641 +0100 -@@ -862,7 +862,7 @@ - call_does_dispatch, vtable_index); // out-parameters - // We lack profiling at this call but type speculation may - // provide us with a type -- speculative_receiver_type = receiver_type->speculative_type(); -+ speculative_receiver_type = (receiver_type != NULL) ? receiver_type->speculative_type() : NULL; - } - - CallGenerator* cg = C->call_generator(target, vtable_index, call_does_dispatch, jvms, true, PROB_ALWAYS, speculative_receiver_type, true, true); ---- jdk8/hotspot/src/share/vm/opto/coalesce.cpp 2015-01-27 08:42:53.999817599 +0100 -+++ jdk8/hotspot/src/share/vm/opto/coalesce.cpp 2015-01-27 08:43:45.263624641 +0100 -@@ -281,8 +281,10 @@ - Block *pred = _phc._cfg.get_block_for_node(b->pred(j)); - Node *copy; - assert(!m->is_Con() || m->is_Mach(), "all Con must be Mach"); -- // Rematerialize constants instead of copying them -- if( m->is_Mach() && m->as_Mach()->is_Con() && -+ // Rematerialize constants instead of copying them. -+ // We do this only for immediate constants, we avoid constant table loads -+ // because that will unsafely extend the live range of the constant table base. -+ if (m->is_Mach() && m->as_Mach()->is_Con() && !m->as_Mach()->is_MachConstant() && - m->as_Mach()->rematerialize() ) { - copy = m->clone(); - // Insert the copy in the predecessor basic block -@@ -317,7 +319,7 @@ - assert(!m->is_Con() || m->is_Mach(), "all Con must be Mach"); - // At this point it is unsafe to extend live ranges (6550579). - // Rematerialize only constants as we do for Phi above. -- if(m->is_Mach() && m->as_Mach()->is_Con() && -+ if (m->is_Mach() && m->as_Mach()->is_Con() && !m->as_Mach()->is_MachConstant() && - m->as_Mach()->rematerialize()) { - copy = m->clone(); - // Insert the copy in the basic block, just before us ---- jdk8/hotspot/src/share/vm/opto/compile.cpp 2015-01-27 08:42:53.999817599 +0100 -+++ jdk8/hotspot/src/share/vm/opto/compile.cpp 2015-01-27 08:43:45.264624618 +0100 -@@ -685,7 +685,8 @@ - _inlining_incrementally(false), - _print_inlining_list(NULL), - _print_inlining_idx(0), -- _interpreter_frame_size(0) { -+ _interpreter_frame_size(0), -+ _max_node_limit(MaxNodeLimit) { - C = this; - - CompileWrapper cw(this); -@@ -1027,7 +1028,8 @@ - _print_inlining_list(NULL), - _print_inlining_idx(0), - _allowed_reasons(0), -- _interpreter_frame_size(0) { -+ _interpreter_frame_size(0), -+ _max_node_limit(MaxNodeLimit) { - C = this; - - #ifndef PRODUCT -@@ -1137,6 +1139,7 @@ - set_do_count_invocations(false); - set_do_method_data_update(false); - set_rtm_state(NoRTM); // No RTM lock eliding by default -+ method_has_option_value("MaxNodeLimit", _max_node_limit); - #if INCLUDE_RTM_OPT - if (UseRTMLocking && has_method() && (method()->method_data_or_null() != NULL)) { - int rtm_state = method()->method_data()->rtm_state(); ---- jdk8/hotspot/src/share/vm/opto/compile.hpp 2015-01-27 08:42:53.999817599 +0100 -+++ jdk8/hotspot/src/share/vm/opto/compile.hpp 2015-01-27 08:43:45.264624618 +0100 -@@ -290,6 +290,7 @@ - int _freq_inline_size; // Max hot method inline size for this compilation - int _fixed_slots; // count of frame slots not allocated by the register - // allocator i.e. locks, original deopt pc, etc. -+ uintx _max_node_limit; // Max unique node count during a single compilation. - // For deopt - int _orig_pc_slot; - int _orig_pc_slot_offset_in_bytes; -@@ -594,6 +595,9 @@ - void set_rtm_state(RTMState s) { _rtm_state = s; } - bool use_rtm() const { return (_rtm_state & NoRTM) == 0; } - bool profile_rtm() const { return _rtm_state == ProfileRTM; } -+ uint max_node_limit() const { return (uint)_max_node_limit; } -+ void set_max_node_limit(uint n) { _max_node_limit = n; } -+ - // check the CompilerOracle for special behaviours for this compile - bool method_has_option(const char * option) { - return method() != NULL && method()->has_option(option); -@@ -723,7 +727,7 @@ - record_method_not_compilable(reason, true); - } - bool check_node_count(uint margin, const char* reason) { -- if (live_nodes() + margin > (uint)MaxNodeLimit) { -+ if (live_nodes() + margin > max_node_limit()) { - record_method_not_compilable(reason); - return true; - } else { ---- jdk8/hotspot/src/share/vm/opto/connode.cpp 2015-01-27 08:42:53.999817599 +0100 -+++ jdk8/hotspot/src/share/vm/opto/connode.cpp 2015-01-27 08:43:45.265624595 +0100 -@@ -441,6 +441,102 @@ - return this; - } - -+uint CastIINode::size_of() const { -+ return sizeof(*this); -+} -+ -+uint CastIINode::cmp(const Node &n) const { -+ return TypeNode::cmp(n) && ((CastIINode&)n)._carry_dependency == _carry_dependency; -+} -+ -+Node *CastIINode::Identity(PhaseTransform *phase) { -+ if (_carry_dependency) { -+ return this; -+ } -+ return ConstraintCastNode::Identity(phase); -+} -+ -+const Type *CastIINode::Value(PhaseTransform *phase) const { -+ const Type *res = ConstraintCastNode::Value(phase); -+ -+ // Try to improve the type of the CastII if we recognize a CmpI/If -+ // pattern. -+ if (_carry_dependency) { -+ if (in(0) != NULL && in(0)->in(0) != NULL && in(0)->in(0)->is_If()) { -+ assert(in(0)->is_IfFalse() || in(0)->is_IfTrue(), "should be If proj"); -+ Node* proj = in(0); -+ if (proj->in(0)->in(1)->is_Bool()) { -+ Node* b = proj->in(0)->in(1); -+ if (b->in(1)->Opcode() == Op_CmpI) { -+ Node* cmp = b->in(1); -+ if (cmp->in(1) == in(1) && phase->type(cmp->in(2))->isa_int()) { -+ const TypeInt* in2_t = phase->type(cmp->in(2))->is_int(); -+ const Type* t = TypeInt::INT; -+ BoolTest test = b->as_Bool()->_test; -+ if (proj->is_IfFalse()) { -+ test = test.negate(); -+ } -+ BoolTest::mask m = test._test; -+ jlong lo_long = min_jint; -+ jlong hi_long = max_jint; -+ if (m == BoolTest::le || m == BoolTest::lt) { -+ hi_long = in2_t->_hi; -+ if (m == BoolTest::lt) { -+ hi_long -= 1; -+ } -+ } else if (m == BoolTest::ge || m == BoolTest::gt) { -+ lo_long = in2_t->_lo; -+ if (m == BoolTest::gt) { -+ lo_long += 1; -+ } -+ } else if (m == BoolTest::eq) { -+ lo_long = in2_t->_lo; -+ hi_long = in2_t->_hi; -+ } else if (m == BoolTest::ne) { -+ // can't do any better -+ } else { -+ stringStream ss; -+ test.dump_on(&ss); -+ fatal(err_msg_res("unexpected comparison %s", ss.as_string())); -+ } -+ int lo_int = (int)lo_long; -+ int hi_int = (int)hi_long; -+ -+ if (lo_long != (jlong)lo_int) { -+ lo_int = min_jint; -+ } -+ if (hi_long != (jlong)hi_int) { -+ hi_int = max_jint; -+ } -+ -+ t = TypeInt::make(lo_int, hi_int, Type::WidenMax); -+ -+ res = res->filter_speculative(t); -+ -+ return res; -+ } -+ } -+ } -+ } -+ } -+ return res; -+} -+ -+Node *CastIINode::Ideal_DU_postCCP(PhaseCCP *ccp) { -+ if (_carry_dependency) { -+ return NULL; -+ } -+ return ConstraintCastNode::Ideal_DU_postCCP(ccp); -+} -+ -+#ifndef PRODUCT -+void CastIINode::dump_spec(outputStream *st) const { -+ TypeNode::dump_spec(st); -+ if (_carry_dependency) { -+ st->print(" carry dependency"); -+ } -+} -+#endif - - //============================================================================= - ---- jdk8/hotspot/src/share/vm/opto/connode.hpp 2015-01-27 08:42:53.999817599 +0100 -+++ jdk8/hotspot/src/share/vm/opto/connode.hpp 2015-01-27 08:43:45.265624595 +0100 -@@ -241,10 +241,25 @@ - //------------------------------CastIINode------------------------------------- - // cast integer to integer (different range) - class CastIINode: public ConstraintCastNode { -+ private: -+ // Can this node be removed post CCP or does it carry a required dependency? -+ const bool _carry_dependency; -+ -+ protected: -+ virtual uint cmp( const Node &n ) const; -+ virtual uint size_of() const; -+ - public: -- CastIINode (Node *n, const Type *t ): ConstraintCastNode(n,t) {} -+ CastIINode(Node *n, const Type *t, bool carry_dependency = false) -+ : ConstraintCastNode(n,t), _carry_dependency(carry_dependency) {} - virtual int Opcode() const; - virtual uint ideal_reg() const { return Op_RegI; } -+ virtual Node *Identity( PhaseTransform *phase ); -+ virtual const Type *Value( PhaseTransform *phase ) const; -+ virtual Node *Ideal_DU_postCCP( PhaseCCP * ); -+#ifndef PRODUCT -+ virtual void dump_spec(outputStream *st) const; -+#endif - }; - - //------------------------------CastPPNode------------------------------------- ---- jdk8/hotspot/src/share/vm/opto/doCall.cpp 2015-01-27 08:42:54.000817575 +0100 -+++ jdk8/hotspot/src/share/vm/opto/doCall.cpp 2015-01-27 08:43:45.265624595 +0100 -@@ -410,6 +410,11 @@ - ciInstanceKlass* klass = ciEnv::get_instance_klass_for_declared_method_holder(holder); - assert(declared_signature != NULL, "cannot be null"); - -+ // Bump max node limit for JSR292 users -+ if (bc() == Bytecodes::_invokedynamic || orig_callee->is_method_handle_intrinsic()) { -+ C->set_max_node_limit(3*MaxNodeLimit); -+ } -+ - // uncommon-trap when callee is unloaded, uninitialized or will not link - // bailout when too many arguments for register representation - if (!will_link || can_not_compile_call_site(orig_callee, klass)) { -@@ -791,7 +796,7 @@ - Node* ex_klass_node = NULL; - if (has_ex_handler() && !ex_type->klass_is_exact()) { - Node* p = basic_plus_adr( ex_node, ex_node, oopDesc::klass_offset_in_bytes()); -- ex_klass_node = _gvn.transform( LoadKlassNode::make(_gvn, immutable_memory(), p, TypeInstPtr::KLASS, TypeKlassPtr::OBJECT) ); -+ ex_klass_node = _gvn.transform(LoadKlassNode::make(_gvn, NULL, immutable_memory(), p, TypeInstPtr::KLASS, TypeKlassPtr::OBJECT)); - - // Compute the exception klass a little more cleverly. - // Obvious solution is to simple do a LoadKlass from the 'ex_node'. -@@ -809,7 +814,7 @@ - continue; - } - Node* p = basic_plus_adr(ex_in, ex_in, oopDesc::klass_offset_in_bytes()); -- Node* k = _gvn.transform( LoadKlassNode::make(_gvn, immutable_memory(), p, TypeInstPtr::KLASS, TypeKlassPtr::OBJECT) ); -+ Node* k = _gvn.transform(LoadKlassNode::make(_gvn, NULL, immutable_memory(), p, TypeInstPtr::KLASS, TypeKlassPtr::OBJECT)); - ex_klass_node->init_req( i, k ); - } - _gvn.set_type(ex_klass_node, TypeKlassPtr::OBJECT); ---- jdk8/hotspot/src/share/vm/opto/escape.cpp 2015-01-27 08:42:54.000817575 +0100 -+++ jdk8/hotspot/src/share/vm/opto/escape.cpp 2015-01-27 08:43:45.266624571 +0100 -@@ -37,6 +37,8 @@ - - ConnectionGraph::ConnectionGraph(Compile * C, PhaseIterGVN *igvn) : - _nodes(C->comp_arena(), C->unique(), C->unique(), NULL), -+ _in_worklist(C->comp_arena()), -+ _next_pidx(0), - _collecting(true), - _verify(false), - _compile(C), -@@ -124,13 +126,19 @@ - if (C->root() != NULL) { - ideal_nodes.push(C->root()); - } -+ // Processed ideal nodes are unique on ideal_nodes list -+ // but several ideal nodes are mapped to the phantom_obj. -+ // To avoid duplicated entries on the following worklists -+ // add the phantom_obj only once to them. -+ ptnodes_worklist.append(phantom_obj); -+ java_objects_worklist.append(phantom_obj); - for( uint next = 0; next < ideal_nodes.size(); ++next ) { - Node* n = ideal_nodes.at(next); - // Create PointsTo nodes and add them to Connection Graph. Called - // only once per ideal node since ideal_nodes is Unique_Node list. - add_node_to_connection_graph(n, &delayed_worklist); - PointsToNode* ptn = ptnode_adr(n->_idx); -- if (ptn != NULL) { -+ if (ptn != NULL && ptn != phantom_obj) { - ptnodes_worklist.append(ptn); - if (ptn->is_JavaObject()) { - java_objects_worklist.append(ptn->as_JavaObject()); -@@ -414,7 +422,7 @@ - } - case Op_CreateEx: { - // assume that all exception objects globally escape -- add_java_object(n, PointsToNode::GlobalEscape); -+ map_ideal_node(n, phantom_obj); - break; - } - case Op_LoadKlass: -@@ -1065,13 +1073,8 @@ - // on graph complexity. Observed 8 passes in jvm2008 compiler.compiler. - // Set limit to 20 to catch situation when something did go wrong and - // bailout Escape Analysis. -- // Also limit build time to 30 sec (60 in debug VM). -+ // Also limit build time to 20 sec (60 in debug VM), EscapeAnalysisTimeout flag. - #define CG_BUILD_ITER_LIMIT 20 --#ifdef ASSERT --#define CG_BUILD_TIME_LIMIT 60.0 --#else --#define CG_BUILD_TIME_LIMIT 30.0 --#endif - - // Propagate GlobalEscape and ArgEscape escape states and check that - // we still have non-escaping objects. The method pushs on _worklist -@@ -1082,12 +1085,13 @@ - // Now propagate references to all JavaObject nodes. - int java_objects_length = java_objects_worklist.length(); - elapsedTimer time; -+ bool timeout = false; - int new_edges = 1; - int iterations = 0; - do { - while ((new_edges > 0) && -- (iterations++ < CG_BUILD_ITER_LIMIT) && -- (time.seconds() < CG_BUILD_TIME_LIMIT)) { -+ (iterations++ < CG_BUILD_ITER_LIMIT)) { -+ double start_time = time.seconds(); - time.start(); - new_edges = 0; - // Propagate references to phantom_object for nodes pushed on _worklist -@@ -1096,7 +1100,29 @@ - for (int next = 0; next < java_objects_length; ++next) { - JavaObjectNode* ptn = java_objects_worklist.at(next); - new_edges += add_java_object_edges(ptn, true); -+ -+#define SAMPLE_SIZE 4 -+ if ((next % SAMPLE_SIZE) == 0) { -+ // Each 4 iterations calculate how much time it will take -+ // to complete graph construction. -+ time.stop(); -+ // Poll for requests from shutdown mechanism to quiesce compiler -+ // because Connection graph construction may take long time. -+ CompileBroker::maybe_block(); -+ double stop_time = time.seconds(); -+ double time_per_iter = (stop_time - start_time) / (double)SAMPLE_SIZE; -+ double time_until_end = time_per_iter * (double)(java_objects_length - next); -+ if ((start_time + time_until_end) >= EscapeAnalysisTimeout) { -+ timeout = true; -+ break; // Timeout - } -+ start_time = stop_time; -+ time.start(); -+ } -+#undef SAMPLE_SIZE -+ -+ } -+ if (timeout) break; - if (new_edges > 0) { - // Update escape states on each iteration if graph was updated. - if (!find_non_escaped_objects(ptnodes_worklist, non_escaped_worklist)) { -@@ -1104,9 +1130,12 @@ - } - } - time.stop(); -+ if (time.seconds() >= EscapeAnalysisTimeout) { -+ timeout = true; -+ break; - } -- if ((iterations < CG_BUILD_ITER_LIMIT) && -- (time.seconds() < CG_BUILD_TIME_LIMIT)) { -+ } -+ if ((iterations < CG_BUILD_ITER_LIMIT) && !timeout) { - time.start(); - // Find fields which have unknown value. - int fields_length = oop_fields_worklist.length(); -@@ -1119,18 +1148,21 @@ - } - } - time.stop(); -+ if (time.seconds() >= EscapeAnalysisTimeout) { -+ timeout = true; -+ break; -+ } - } else { - new_edges = 0; // Bailout - } - } while (new_edges > 0); - - // Bailout if passed limits. -- if ((iterations >= CG_BUILD_ITER_LIMIT) || -- (time.seconds() >= CG_BUILD_TIME_LIMIT)) { -+ if ((iterations >= CG_BUILD_ITER_LIMIT) || timeout) { - Compile* C = _compile; - if (C->log() != NULL) { - C->log()->begin_elem("connectionGraph_bailout reason='reached "); -- C->log()->text("%s", (iterations >= CG_BUILD_ITER_LIMIT) ? "iterations" : "time"); -+ C->log()->text("%s", timeout ? "time" : "iterations"); - C->log()->end_elem(" limit'"); - } - assert(ExitEscapeAnalysisOnTimeout, err_msg_res("infinite EA connection graph build (%f sec, %d iterations) with %d nodes and worklist size %d", -@@ -1147,7 +1179,6 @@ - #endif - - #undef CG_BUILD_ITER_LIMIT --#undef CG_BUILD_TIME_LIMIT - - // Find fields initialized by NULL for non-escaping Allocations. - int non_escaped_length = non_escaped_worklist.length(); -@@ -1271,8 +1302,8 @@ - } - } - } -- while(_worklist.length() > 0) { -- PointsToNode* use = _worklist.pop(); -+ for (int l = 0; l < _worklist.length(); l++) { -+ PointsToNode* use = _worklist.at(l); - if (PointsToNode::is_base_use(use)) { - // Add reference from jobj to field and from field to jobj (field's base). - use = PointsToNode::get_use_node(use)->as_Field(); -@@ -1319,6 +1350,8 @@ - add_field_uses_to_worklist(use->as_Field()); - } - } -+ _worklist.clear(); -+ _in_worklist.Reset(); - return new_edges; - } - -@@ -1898,7 +1931,7 @@ - return; - } - Compile* C = _compile; -- ptadr = new (C->comp_arena()) LocalVarNode(C, n, es); -+ ptadr = new (C->comp_arena()) LocalVarNode(this, n, es); - _nodes.at_put(n->_idx, ptadr); - } - -@@ -1909,7 +1942,7 @@ - return; - } - Compile* C = _compile; -- ptadr = new (C->comp_arena()) JavaObjectNode(C, n, es); -+ ptadr = new (C->comp_arena()) JavaObjectNode(this, n, es); - _nodes.at_put(n->_idx, ptadr); - } - -@@ -1925,7 +1958,7 @@ - es = PointsToNode::GlobalEscape; - } - Compile* C = _compile; -- FieldNode* field = new (C->comp_arena()) FieldNode(C, n, es, offset, is_oop); -+ FieldNode* field = new (C->comp_arena()) FieldNode(this, n, es, offset, is_oop); - _nodes.at_put(n->_idx, field); - } - -@@ -1939,7 +1972,7 @@ - return; - } - Compile* C = _compile; -- ptadr = new (C->comp_arena()) ArraycopyNode(C, n, es); -+ ptadr = new (C->comp_arena()) ArraycopyNode(this, n, es); - _nodes.at_put(n->_idx, ptadr); - // Add edge from arraycopy node to source object. - (void)add_edge(ptadr, src); -@@ -2379,7 +2412,7 @@ - } - } - } -- if ((int) (C->live_nodes() + 2*NodeLimitFudgeFactor) > MaxNodeLimit) { -+ if (C->live_nodes() + 2*NodeLimitFudgeFactor > C->max_node_limit()) { - if (C->do_escape_analysis() == true && !C->failing()) { - // Retry compilation without escape analysis. - // If this is the first failure, the sentinel string will "stick" -@@ -2839,6 +2872,13 @@ - continue; - } - } -+ -+ const TypeOopPtr *t = igvn->type(n)->isa_oopptr(); -+ if (t == NULL) -+ continue; // not a TypeOopPtr -+ if (!t->klass_is_exact()) -+ continue; // not an unique type -+ - if (alloc->is_Allocate()) { - // Set the scalar_replaceable flag for allocation - // so it could be eliminated. -@@ -2857,10 +2897,7 @@ - // - not determined to be ineligible by escape analysis - set_map(alloc, n); - set_map(n, alloc); -- const TypeOopPtr *t = igvn->type(n)->isa_oopptr(); -- if (t == NULL) -- continue; // not a TypeOopPtr -- const TypeOopPtr* tinst = t->cast_to_exactness(true)->is_oopptr()->cast_to_instance_id(ni); -+ const TypeOopPtr* tinst = t->cast_to_instance_id(ni); - igvn->hash_delete(n); - igvn->set_type(n, tinst); - n->raise_bottom_type(tinst); ---- jdk8/hotspot/src/share/vm/opto/escape.hpp 2015-01-27 08:42:54.000817575 +0100 -+++ jdk8/hotspot/src/share/vm/opto/escape.hpp 2015-01-27 08:43:45.266624571 +0100 -@@ -125,6 +125,8 @@ - class FieldNode; - class ArraycopyNode; - -+class ConnectionGraph; -+ - // ConnectionGraph nodes - class PointsToNode : public ResourceObj { - GrowableArray _edges; // List of nodes this node points to -@@ -137,6 +139,7 @@ - - Node* const _node; // Ideal node corresponding to this PointsTo node. - const int _idx; // Cached ideal node's _idx -+ const uint _pidx; // Index of this node - - public: - typedef enum { -@@ -165,17 +168,9 @@ - } NodeFlags; - - -- PointsToNode(Compile *C, Node* n, EscapeState es, NodeType type): -- _edges(C->comp_arena(), 2, 0, NULL), -- _uses (C->comp_arena(), 2, 0, NULL), -- _node(n), -- _idx(n->_idx), -- _type((u1)type), -- _escape((u1)es), -- _fields_escape((u1)es), -- _flags(ScalarReplaceable) { -- assert(n != NULL && es != UnknownEscape, "sanity"); -- } -+ inline PointsToNode(ConnectionGraph* CG, Node* n, EscapeState es, NodeType type); -+ -+ uint pidx() const { return _pidx; } - - Node* ideal_node() const { return _node; } - int idx() const { return _idx; } -@@ -243,14 +238,14 @@ - - class LocalVarNode: public PointsToNode { - public: -- LocalVarNode(Compile *C, Node* n, EscapeState es): -- PointsToNode(C, n, es, LocalVar) {} -+ LocalVarNode(ConnectionGraph *CG, Node* n, EscapeState es): -+ PointsToNode(CG, n, es, LocalVar) {} - }; - - class JavaObjectNode: public PointsToNode { - public: -- JavaObjectNode(Compile *C, Node* n, EscapeState es): -- PointsToNode(C, n, es, JavaObject) { -+ JavaObjectNode(ConnectionGraph *CG, Node* n, EscapeState es): -+ PointsToNode(CG, n, es, JavaObject) { - if (es > NoEscape) - set_scalar_replaceable(false); - } -@@ -262,8 +257,8 @@ - const bool _is_oop; // Field points to object - bool _has_unknown_base; // Has phantom_object base - public: -- FieldNode(Compile *C, Node* n, EscapeState es, int offs, bool is_oop): -- PointsToNode(C, n, es, Field), -+ FieldNode(ConnectionGraph *CG, Node* n, EscapeState es, int offs, bool is_oop): -+ PointsToNode(CG, n, es, Field), - _offset(offs), _is_oop(is_oop), - _has_unknown_base(false) {} - -@@ -284,8 +279,8 @@ - - class ArraycopyNode: public PointsToNode { - public: -- ArraycopyNode(Compile *C, Node* n, EscapeState es): -- PointsToNode(C, n, es, Arraycopy) {} -+ ArraycopyNode(ConnectionGraph *CG, Node* n, EscapeState es): -+ PointsToNode(CG, n, es, Arraycopy) {} - }; - - // Iterators for PointsTo node's edges: -@@ -323,11 +318,14 @@ - - - class ConnectionGraph: public ResourceObj { -+ friend class PointsToNode; - private: - GrowableArray _nodes; // Map from ideal nodes to - // ConnectionGraph nodes. - - GrowableArray _worklist; // Nodes to be processed -+ VectorSet _in_worklist; -+ uint _next_pidx; - - bool _collecting; // Indicates whether escape information - // is still being collected. If false, -@@ -353,6 +351,8 @@ - } - uint nodes_size() const { return _nodes.length(); } - -+ uint next_pidx() { return _next_pidx++; } -+ - // Add nodes to ConnectionGraph. - void add_local_var(Node* n, PointsToNode::EscapeState es); - void add_java_object(Node* n, PointsToNode::EscapeState es); -@@ -396,15 +396,26 @@ - int add_java_object_edges(JavaObjectNode* jobj, bool populate_worklist); - - // Put node on worklist if it is (or was) not there. -- void add_to_worklist(PointsToNode* pt) { -- _worklist.push(pt); -- return; -+ inline void add_to_worklist(PointsToNode* pt) { -+ PointsToNode* ptf = pt; -+ uint pidx_bias = 0; -+ if (PointsToNode::is_base_use(pt)) { -+ // Create a separate entry in _in_worklist for a marked base edge -+ // because _worklist may have an entry for a normal edge pointing -+ // to the same node. To separate them use _next_pidx as bias. -+ ptf = PointsToNode::get_use_node(pt)->as_Field(); -+ pidx_bias = _next_pidx; -+ } -+ if (!_in_worklist.test_set(ptf->pidx() + pidx_bias)) { -+ _worklist.append(pt); -+ } - } - - // Put on worklist all uses of this node. -- void add_uses_to_worklist(PointsToNode* pt) { -- for (UseIterator i(pt); i.has_next(); i.next()) -- _worklist.push(i.get()); -+ inline void add_uses_to_worklist(PointsToNode* pt) { -+ for (UseIterator i(pt); i.has_next(); i.next()) { -+ add_to_worklist(i.get()); -+ } - } - - // Put on worklist all field's uses and related field nodes. -@@ -587,4 +598,17 @@ - #endif - }; - -+inline PointsToNode::PointsToNode(ConnectionGraph *CG, Node* n, EscapeState es, NodeType type): -+ _edges(CG->_compile->comp_arena(), 2, 0, NULL), -+ _uses (CG->_compile->comp_arena(), 2, 0, NULL), -+ _node(n), -+ _idx(n->_idx), -+ _pidx(CG->next_pidx()), -+ _type((u1)type), -+ _escape((u1)es), -+ _fields_escape((u1)es), -+ _flags(ScalarReplaceable) { -+ assert(n != NULL && es != UnknownEscape, "sanity"); -+} -+ - #endif // SHARE_VM_OPTO_ESCAPE_HPP ---- jdk8/hotspot/src/share/vm/opto/graphKit.cpp 2015-01-27 08:42:54.000817575 +0100 -+++ jdk8/hotspot/src/share/vm/opto/graphKit.cpp 2015-01-27 08:43:45.267624548 +0100 -@@ -1150,7 +1150,7 @@ - Node* akls = AllocateNode::Ideal_klass(obj, &_gvn); - if (akls != NULL) return akls; - Node* k_adr = basic_plus_adr(obj, oopDesc::klass_offset_in_bytes()); -- return _gvn.transform( LoadKlassNode::make(_gvn, immutable_memory(), k_adr, TypeInstPtr::KLASS) ); -+ return _gvn.transform(LoadKlassNode::make(_gvn, NULL, immutable_memory(), k_adr, TypeInstPtr::KLASS)); - } - - //-------------------------load_array_length----------------------------------- -@@ -2542,7 +2542,7 @@ - // cache which is mutable so can't use immutable memory. Other - // types load from the super-class display table which is immutable. - Node *kmem = might_be_cache ? memory(p2) : immutable_memory(); -- Node *nkls = _gvn.transform( LoadKlassNode::make( _gvn, kmem, p2, _gvn.type(p2)->is_ptr(), TypeKlassPtr::OBJECT_OR_NULL ) ); -+ Node* nkls = _gvn.transform(LoadKlassNode::make(_gvn, NULL, kmem, p2, _gvn.type(p2)->is_ptr(), TypeKlassPtr::OBJECT_OR_NULL)); - - // Compile speed common case: ARE a subtype and we canNOT fail - if( superklass == nkls ) ---- jdk8/hotspot/src/share/vm/opto/ifg.cpp 2015-01-27 08:42:54.000817575 +0100 -+++ jdk8/hotspot/src/share/vm/opto/ifg.cpp 2015-01-27 08:43:45.267624548 +0100 -@@ -541,6 +541,25 @@ - if( !n->is_Proj() || - // Could also be a flags-projection of a dead ADD or such. - (_lrg_map.live_range_id(def) && !liveout.member(_lrg_map.live_range_id(def)))) { -+ bool remove = true; -+ if (n->is_MachProj()) { -+ // Don't remove KILL projections if their "defining" nodes have -+ // memory effects (have SCMemProj projection node) - -+ // they are not dead even when their result is not used. -+ // For example, compareAndSwapL (and other CAS) and EncodeISOArray nodes. -+ // The method add_input_to_liveout() keeps such nodes alive (put them on liveout list) -+ // when it sees SCMemProj node in a block. Unfortunately SCMemProj node could be placed -+ // in block in such order that KILL MachProj nodes are processed first. -+ uint cnt = def->outcnt(); -+ for (uint i = 0; i < cnt; i++) { -+ Node* proj = def->raw_out(i); -+ if (proj->Opcode() == Op_SCMemProj) { -+ remove = false; -+ break; -+ } -+ } -+ } -+ if (remove) { - block->remove_node(j - 1); - if (lrgs(r)._def == n) { - lrgs(r)._def = 0; -@@ -553,6 +572,7 @@ - hrp_index[1]--; - continue; - } -+ } - - // Fat-projections kill many registers which cannot be used to - // hold live ranges. ---- jdk8/hotspot/src/share/vm/opto/ifnode.cpp 2015-01-27 08:42:54.000817575 +0100 -+++ jdk8/hotspot/src/share/vm/opto/ifnode.cpp 2015-01-27 08:43:45.267624548 +0100 -@@ -820,6 +820,11 @@ - - static IfNode* idealize_test(PhaseGVN* phase, IfNode* iff); - -+struct RangeCheck { -+ Node* ctl; -+ jint off; -+}; -+ - //------------------------------Ideal------------------------------------------ - // Return a node which is more "ideal" than the current node. Strip out - // control copies -@@ -861,23 +866,25 @@ - jint offset1; - int flip1 = is_range_check(range1, index1, offset1); - if( flip1 ) { -- Node *first_prev_dom = NULL; -- - // Try to remove extra range checks. All 'up_one_dom' gives up at merges - // so all checks we inspect post-dominate the top-most check we find. - // If we are going to fail the current check and we reach the top check - // then we are guaranteed to fail, so just start interpreting there. -- // We 'expand' the top 2 range checks to include all post-dominating -+ // We 'expand' the top 3 range checks to include all post-dominating - // checks. - -- // The top 2 range checks seen -- Node *prev_chk1 = NULL; -- Node *prev_chk2 = NULL; -+ // The top 3 range checks seen -+ const int NRC =3; -+ RangeCheck prev_checks[NRC]; -+ int nb_checks = 0; -+ - // Low and high offsets seen so far - jint off_lo = offset1; - jint off_hi = offset1; - -- // Scan for the top 2 checks and collect range of offsets -+ bool found_immediate_dominator = false; -+ -+ // Scan for the top checks and collect range of offsets - for( int dist = 0; dist < 999; dist++ ) { // Range-Check scan limit - if( dom->Opcode() == Op_If && // Not same opcode? - prev_dom->in(0) == dom ) { // One path of test does dominate? -@@ -890,16 +897,21 @@ - // the same array bounds. - if( flip2 == flip1 && range2 == range1 && index2 == index1 && - dom->outcnt() == 2 ) { -+ if (nb_checks == 0 && dom->in(1) == in(1)) { -+ // Found an immediately dominating test at the same offset. -+ // This kind of back-to-back test can be eliminated locally, -+ // and there is no need to search further for dominating tests. -+ assert(offset2 == offset1, "Same test but different offsets"); -+ found_immediate_dominator = true; -+ break; -+ } - // Gather expanded bounds - off_lo = MIN2(off_lo,offset2); - off_hi = MAX2(off_hi,offset2); -- // Record top 2 range checks -- prev_chk2 = prev_chk1; -- prev_chk1 = prev_dom; -- // If we match the test exactly, then the top test covers -- // both our lower and upper bounds. -- if( dom->in(1) == in(1) ) -- prev_chk2 = prev_chk1; -+ // Record top NRC range checks -+ prev_checks[nb_checks%NRC].ctl = prev_dom; -+ prev_checks[nb_checks%NRC].off = offset2; -+ nb_checks++; - } - } - prev_dom = dom; -@@ -907,36 +919,87 @@ - if( !dom ) break; - } - -- -+ if (!found_immediate_dominator) { - // Attempt to widen the dominating range check to cover some later - // ones. Since range checks "fail" by uncommon-trapping to the -- // interpreter, widening a check can make us speculative enter the -- // interpreter. If we see range-check deopt's, do not widen! -+ // interpreter, widening a check can make us speculatively enter -+ // the interpreter. If we see range-check deopt's, do not widen! - if (!phase->C->allow_range_check_smearing()) return NULL; - -+ // Didn't find prior covering check, so cannot remove anything. -+ if (nb_checks == 0) { -+ return NULL; -+ } - // Constant indices only need to check the upper bound. -- // Non-constance indices must check both low and high. -+ // Non-constant indices must check both low and high. -+ int chk0 = (nb_checks - 1) % NRC; - if( index1 ) { -- // Didn't find 2 prior covering checks, so cannot remove anything. -- if( !prev_chk2 ) return NULL; -- // 'Widen' the offsets of the 1st and 2nd covering check -- adjust_check( prev_chk1, range1, index1, flip1, off_lo, igvn ); -- // Do not call adjust_check twice on the same projection -- // as the first call may have transformed the BoolNode to a ConI -- if( prev_chk1 != prev_chk2 ) { -- adjust_check( prev_chk2, range1, index1, flip1, off_hi, igvn ); -+ if (nb_checks == 1) { -+ return NULL; -+ } else { -+ // If the top range check's constant is the min or max of -+ // all constants we widen the next one to cover the whole -+ // range of constants. -+ RangeCheck rc0 = prev_checks[chk0]; -+ int chk1 = (nb_checks - 2) % NRC; -+ RangeCheck rc1 = prev_checks[chk1]; -+ if (rc0.off == off_lo) { -+ adjust_check(rc1.ctl, range1, index1, flip1, off_hi, igvn); -+ prev_dom = rc1.ctl; -+ } else if (rc0.off == off_hi) { -+ adjust_check(rc1.ctl, range1, index1, flip1, off_lo, igvn); -+ prev_dom = rc1.ctl; -+ } else { -+ // If the top test's constant is not the min or max of all -+ // constants, we need 3 range checks. We must leave the -+ // top test unchanged because widening it would allow the -+ // accesses it protects to successfully read/write out of -+ // bounds. -+ if (nb_checks == 2) { -+ return NULL; - } -- // Test is now covered by prior checks, dominate it out -- prev_dom = prev_chk2; -+ int chk2 = (nb_checks - 3) % NRC; -+ RangeCheck rc2 = prev_checks[chk2]; -+ // The top range check a+i covers interval: -a <= i < length-a -+ // The second range check b+i covers interval: -b <= i < length-b -+ if (rc1.off <= rc0.off) { -+ // if b <= a, we change the second range check to: -+ // -min_of_all_constants <= i < length-min_of_all_constants -+ // Together top and second range checks now cover: -+ // -min_of_all_constants <= i < length-a -+ // which is more restrictive than -b <= i < length-b: -+ // -b <= -min_of_all_constants <= i < length-a <= length-b -+ // The third check is then changed to: -+ // -max_of_all_constants <= i < length-max_of_all_constants -+ // so 2nd and 3rd checks restrict allowed values of i to: -+ // -min_of_all_constants <= i < length-max_of_all_constants -+ adjust_check(rc1.ctl, range1, index1, flip1, off_lo, igvn); -+ adjust_check(rc2.ctl, range1, index1, flip1, off_hi, igvn); - } else { -- // Didn't find prior covering check, so cannot remove anything. -- if( !prev_chk1 ) return NULL; -+ // if b > a, we change the second range check to: -+ // -max_of_all_constants <= i < length-max_of_all_constants -+ // Together top and second range checks now cover: -+ // -a <= i < length-max_of_all_constants -+ // which is more restrictive than -b <= i < length-b: -+ // -b < -a <= i < length-max_of_all_constants <= length-b -+ // The third check is then changed to: -+ // -max_of_all_constants <= i < length-max_of_all_constants -+ // so 2nd and 3rd checks restrict allowed values of i to: -+ // -min_of_all_constants <= i < length-max_of_all_constants -+ adjust_check(rc1.ctl, range1, index1, flip1, off_hi, igvn); -+ adjust_check(rc2.ctl, range1, index1, flip1, off_lo, igvn); -+ } -+ prev_dom = rc2.ctl; -+ } -+ } -+ } else { -+ RangeCheck rc0 = prev_checks[chk0]; - // 'Widen' the offset of the 1st and only covering check -- adjust_check( prev_chk1, range1, index1, flip1, off_hi, igvn ); -+ adjust_check(rc0.ctl, range1, index1, flip1, off_hi, igvn); - // Test is now covered by prior checks, dominate it out -- prev_dom = prev_chk1; -+ prev_dom = rc0.ctl; -+ } - } -- - - } else { // Scan for an equivalent test - ---- jdk8/hotspot/src/share/vm/opto/lcm.cpp 2015-01-27 08:42:54.000817575 +0100 -+++ jdk8/hotspot/src/share/vm/opto/lcm.cpp 2015-01-27 08:43:45.268624525 +0100 -@@ -487,9 +487,7 @@ - iop == Op_CreateEx || // Create-exception must start block - iop == Op_CheckCastPP - ) { -- // select the node n -- // remove n from worklist and retain the order of remaining nodes -- worklist.remove((uint)i); -+ worklist.map(i,worklist.pop()); - return n; - } - -@@ -575,9 +573,7 @@ - assert(idx >= 0, "index should be set"); - Node *n = worklist[(uint)idx]; // Get the winner - -- // select the node n -- // remove n from worklist and retain the order of remaining nodes -- worklist.remove((uint)idx); -+ worklist.map((uint)idx, worklist.pop()); // Compress worklist - return n; - } - ---- jdk8/hotspot/src/share/vm/opto/library_call.cpp 2015-01-27 08:42:54.001817552 +0100 -+++ jdk8/hotspot/src/share/vm/opto/library_call.cpp 2015-01-27 08:43:45.269624501 +0100 -@@ -3398,7 +3398,7 @@ - if (region == NULL) never_see_null = true; - Node* p = basic_plus_adr(mirror, offset); - const TypeKlassPtr* kls_type = TypeKlassPtr::OBJECT_OR_NULL; -- Node* kls = _gvn.transform( LoadKlassNode::make(_gvn, immutable_memory(), p, TypeRawPtr::BOTTOM, kls_type)); -+ Node* kls = _gvn.transform(LoadKlassNode::make(_gvn, NULL, immutable_memory(), p, TypeRawPtr::BOTTOM, kls_type)); - Node* null_ctl = top(); - kls = null_check_oop(kls, &null_ctl, never_see_null); - if (region != NULL) { -@@ -3574,7 +3574,7 @@ - phi->add_req(makecon(TypeInstPtr::make(env()->Object_klass()->java_mirror()))); - // If we fall through, it's a plain class. Get its _super. - p = basic_plus_adr(kls, in_bytes(Klass::super_offset())); -- kls = _gvn.transform( LoadKlassNode::make(_gvn, immutable_memory(), p, TypeRawPtr::BOTTOM, TypeKlassPtr::OBJECT_OR_NULL)); -+ kls = _gvn.transform(LoadKlassNode::make(_gvn, NULL, immutable_memory(), p, TypeRawPtr::BOTTOM, TypeKlassPtr::OBJECT_OR_NULL)); - null_ctl = top(); - kls = null_check_oop(kls, &null_ctl); - if (null_ctl != top()) { -@@ -3656,7 +3656,7 @@ - args[which_arg] = arg; - - Node* p = basic_plus_adr(arg, class_klass_offset); -- Node* kls = LoadKlassNode::make(_gvn, immutable_memory(), p, adr_type, kls_type); -+ Node* kls = LoadKlassNode::make(_gvn, NULL, immutable_memory(), p, adr_type, kls_type); - klasses[which_arg] = _gvn.transform(kls); - } - -@@ -5172,7 +5172,7 @@ - // (At this point we can assume disjoint_bases, since types differ.) - int ek_offset = in_bytes(ObjArrayKlass::element_klass_offset()); - Node* p1 = basic_plus_adr(dest_klass, ek_offset); -- Node* n1 = LoadKlassNode::make(_gvn, immutable_memory(), p1, TypeRawPtr::BOTTOM); -+ Node* n1 = LoadKlassNode::make(_gvn, NULL, immutable_memory(), p1, TypeRawPtr::BOTTOM); - Node* dest_elem_klass = _gvn.transform(n1); - Node* cv = generate_checkcast_arraycopy(adr_type, - dest_elem_klass, ---- jdk8/hotspot/src/share/vm/opto/loopnode.hpp 2015-01-27 08:42:54.001817552 +0100 -+++ jdk8/hotspot/src/share/vm/opto/loopnode.hpp 2015-01-27 08:43:45.270624478 +0100 -@@ -602,6 +602,8 @@ - return ctrl; - } - -+ bool cast_incr_before_loop(Node* incr, Node* ctrl, Node* loop); -+ - public: - bool has_node( Node* n ) const { - guarantee(n != NULL, "No Node."); ---- jdk8/hotspot/src/share/vm/opto/loopopts.cpp 2015-01-27 08:42:54.001817552 +0100 -+++ jdk8/hotspot/src/share/vm/opto/loopopts.cpp 2015-01-27 08:43:45.270624478 +0100 -@@ -239,8 +239,13 @@ - ProjNode* dp_proj = dp->as_Proj(); - ProjNode* unc_proj = iff->as_If()->proj_out(1 - dp_proj->_con)->as_Proj(); - if (exclude_loop_predicate && -- unc_proj->is_uncommon_trap_proj(Deoptimization::Reason_predicate)) -+ (unc_proj->is_uncommon_trap_proj(Deoptimization::Reason_predicate) || -+ unc_proj->is_uncommon_trap_proj(Deoptimization::Reason_range_check))) { -+ // If this is a range check (IfNode::is_range_check), do not -+ // reorder because Compile::allow_range_check_smearing might have -+ // changed the check. - return; // Let IGVN transformation change control dependence. -+ } - - IdealLoopTree *old_loop = get_loop(dp); - -@@ -734,7 +739,7 @@ - for (DUIterator_Fast imax, i = region->fast_outs(imax); i < imax; i++) { - weight += region->fast_out(i)->outcnt(); - } -- int nodes_left = MaxNodeLimit - C->live_nodes(); -+ int nodes_left = C->max_node_limit() - C->live_nodes(); - if (weight * 8 > nodes_left) { - #ifndef PRODUCT - if (PrintOpto) -@@ -900,7 +905,7 @@ - Node *bol = n->in(1); - uint max = bol->outcnt(); - // Check for same test used more than once? -- if( n_op == Op_If && max > 1 && bol->is_Bool() ) { -+ if (max > 1 && bol->is_Bool()) { - // Search up IDOMs to see if this IF is dominated. - Node *cutoff = get_ctrl(bol); - ---- jdk8/hotspot/src/share/vm/opto/loopTransform.cpp 2015-01-27 08:42:54.001817552 +0100 -+++ jdk8/hotspot/src/share/vm/opto/loopTransform.cpp 2015-01-27 08:43:45.269624501 +0100 -@@ -269,10 +269,9 @@ - bool IdealLoopTree::policy_peeling( PhaseIdealLoop *phase ) const { - Node *test = ((IdealLoopTree*)this)->tail(); - int body_size = ((IdealLoopTree*)this)->_body.size(); -- int live_node_count = phase->C->live_nodes(); - // Peeling does loop cloning which can result in O(N^2) node construction - if( body_size > 255 /* Prevent overflow for large body_size */ -- || (body_size * body_size + live_node_count > MaxNodeLimit) ) { -+ || (body_size * body_size + phase->C->live_nodes()) > phase->C->max_node_limit() ) { - return false; // too large to safely clone - } - while( test != _head ) { // Scan till run off top of loop -@@ -601,7 +600,7 @@ - return false; - if (new_body_size > unroll_limit || - // Unrolling can result in a large amount of node construction -- new_body_size >= MaxNodeLimit - (uint) phase->C->live_nodes()) { -+ new_body_size >= phase->C->max_node_limit() - phase->C->live_nodes()) { - return false; - } - -@@ -882,6 +881,20 @@ - return n; - } - -+bool PhaseIdealLoop::cast_incr_before_loop(Node* incr, Node* ctrl, Node* loop) { -+ Node* castii = new (C) CastIINode(incr, TypeInt::INT, true); -+ castii->set_req(0, ctrl); -+ register_new_node(castii, ctrl); -+ for (DUIterator_Fast imax, i = incr->fast_outs(imax); i < imax; i++) { -+ Node* n = incr->fast_out(i); -+ if (n->is_Phi() && n->in(0) == loop) { -+ int nrep = n->replace_edge(incr, castii); -+ return true; -+ } -+ } -+ return false; -+} -+ - //------------------------------insert_pre_post_loops-------------------------- - // Insert pre and post loops. If peel_only is set, the pre-loop can not have - // more iterations added. It acts as a 'peel' only, no lower-bound RCE, no -@@ -1080,6 +1093,24 @@ - } - } - -+ // Nodes inside the loop may be control dependent on a predicate -+ // that was moved before the preloop. If the back branch of the main -+ // or post loops becomes dead, those nodes won't be dependent on the -+ // test that guards that loop nest anymore which could lead to an -+ // incorrect array access because it executes independently of the -+ // test that was guarding the loop nest. We add a special CastII on -+ // the if branch that enters the loop, between the input induction -+ // variable value and the induction variable Phi to preserve correct -+ // dependencies. -+ -+ // CastII for the post loop: -+ bool inserted = cast_incr_before_loop(zer_opaq->in(1), zer_taken, post_head); -+ assert(inserted, "no castII inserted"); -+ -+ // CastII for the main loop: -+ inserted = cast_incr_before_loop(pre_incr, min_taken, main_head); -+ assert(inserted, "no castII inserted"); -+ - // Step B4: Shorten the pre-loop to run only 1 iteration (for now). - // RCE and alignment may change this later. - Node *cmp_end = pre_end->cmp_node(); -@@ -2287,8 +2318,8 @@ - - // Skip next optimizations if running low on nodes. Note that - // policy_unswitching and policy_maximally_unroll have this check. -- uint nodes_left = MaxNodeLimit - (uint) phase->C->live_nodes(); -- if ((2 * _body.size()) > nodes_left) { -+ int nodes_left = phase->C->max_node_limit() - phase->C->live_nodes(); -+ if ((int)(2 * _body.size()) > nodes_left) { - return true; - } - ---- jdk8/hotspot/src/share/vm/opto/loopUnswitch.cpp 2015-01-27 08:42:54.001817552 +0100 -+++ jdk8/hotspot/src/share/vm/opto/loopUnswitch.cpp 2015-01-27 08:43:45.269624501 +0100 -@@ -59,8 +59,8 @@ - if (!_head->is_Loop()) { - return false; - } -- uint nodes_left = MaxNodeLimit - phase->C->live_nodes(); -- if (2 * _body.size() > nodes_left) { -+ int nodes_left = phase->C->max_node_limit() - phase->C->live_nodes(); -+ if ((int)(2 * _body.size()) > nodes_left) { - return false; // Too speculative if running low on nodes. - } - LoopNode* head = _head->as_Loop(); ---- jdk8/hotspot/src/share/vm/opto/macro.cpp 2015-01-27 08:42:54.001817552 +0100 -+++ jdk8/hotspot/src/share/vm/opto/macro.cpp 2015-01-27 08:43:45.271624455 +0100 -@@ -964,7 +964,11 @@ - } - - bool PhaseMacroExpand::eliminate_allocate_node(AllocateNode *alloc) { -- if (!EliminateAllocations || !alloc->_is_non_escaping) { -+ // Don't do scalar replacement if the frame can be popped by JVMTI: -+ // if reallocation fails during deoptimization we'll pop all -+ // interpreter frames for this compiled frame and that won't play -+ // nice with JVMTI popframe. -+ if (!EliminateAllocations || JvmtiExport::can_pop_frame() || !alloc->_is_non_escaping) { - return false; - } - Node* klass = alloc->in(AllocateNode::KlassNode); -@@ -2194,7 +2198,7 @@ - Node* klass_node = AllocateNode::Ideal_klass(obj, &_igvn); - if (klass_node == NULL) { - Node* k_adr = basic_plus_adr(obj, oopDesc::klass_offset_in_bytes()); -- klass_node = transform_later( LoadKlassNode::make(_igvn, mem, k_adr, _igvn.type(k_adr)->is_ptr()) ); -+ klass_node = transform_later(LoadKlassNode::make(_igvn, NULL, mem, k_adr, _igvn.type(k_adr)->is_ptr())); - #ifdef _LP64 - if (UseCompressedClassPointers && klass_node->is_DecodeNKlass()) { - assert(klass_node->in(1)->Opcode() == Op_LoadNKlass, "sanity"); ---- jdk8/hotspot/src/share/vm/opto/memnode.cpp 2015-01-27 08:42:54.002817529 +0100 -+++ jdk8/hotspot/src/share/vm/opto/memnode.cpp 2015-01-27 08:43:45.271624455 +0100 -@@ -870,6 +870,10 @@ - - - //============================================================================= -+// Should LoadNode::Ideal() attempt to remove control edges? -+bool LoadNode::can_remove_control() const { -+ return true; -+} - uint LoadNode::size_of() const { return sizeof(*this); } - uint LoadNode::cmp( const Node &n ) const - { return !Type::cmp( _type, ((LoadNode&)n)._type ); } -@@ -1262,6 +1266,16 @@ - result = new (phase->C) ConvI2LNode(phase->transform(result)); - } - #endif -+ // Boxing/unboxing can be done from signed & unsigned loads (e.g. LoadUB -> ... -> LoadB pair). -+ // Need to preserve unboxing load type if it is unsigned. -+ switch(this->Opcode()) { -+ case Op_LoadUB: -+ result = new (phase->C) AndINode(phase->transform(result), phase->intcon(0xFF)); -+ break; -+ case Op_LoadUS: -+ result = new (phase->C) AndINode(phase->transform(result), phase->intcon(0xFFFF)); -+ break; -+ } - return result; - } - } -@@ -1466,7 +1480,7 @@ - } - - //------------------------------Ideal------------------------------------------ --// If the load is from Field memory and the pointer is non-null, we can -+// If the load is from Field memory and the pointer is non-null, it might be possible to - // zero out the control input. - // If the offset is constant and the base is an object allocation, - // try to hook me up to the exact initializing store. -@@ -1491,6 +1505,7 @@ - && phase->C->get_alias_index(phase->type(address)->is_ptr()) != Compile::AliasIdxRaw) { - // Check for useless control edge in some common special cases - if (in(MemNode::Control) != NULL -+ && can_remove_control() - && phase->type(base)->higher_equal(TypePtr::NOTNULL) - && all_controls_dominate(base, phase->C->start())) { - // A method-invariant, non-null address (constant or 'this' argument). -@@ -2018,9 +2033,8 @@ - //============================================================================= - //----------------------------LoadKlassNode::make------------------------------ - // Polymorphic factory method: --Node *LoadKlassNode::make( PhaseGVN& gvn, Node *mem, Node *adr, const TypePtr* at, const TypeKlassPtr *tk ) { -+Node* LoadKlassNode::make(PhaseGVN& gvn, Node* ctl, Node *mem, Node *adr, const TypePtr* at, const TypeKlassPtr *tk) { - Compile* C = gvn.C; -- Node *ctl = NULL; - // sanity check the alias category against the created node type - const TypePtr *adr_type = adr->bottom_type()->isa_ptr(); - assert(adr_type != NULL, "expecting TypeKlassPtr"); -@@ -2040,6 +2054,12 @@ - return klass_value_common(phase); - } - -+// In most cases, LoadKlassNode does not have the control input set. If the control -+// input is set, it must not be removed (by LoadNode::Ideal()). -+bool LoadKlassNode::can_remove_control() const { -+ return false; -+} -+ - const Type *LoadNode::klass_value_common( PhaseTransform *phase ) const { - // Either input is TOP ==> the result is TOP - const Type *t1 = phase->type( in(MemNode::Memory) ); ---- jdk8/hotspot/src/share/vm/opto/memnode.hpp 2015-01-27 08:42:54.002817529 +0100 -+++ jdk8/hotspot/src/share/vm/opto/memnode.hpp 2015-01-27 08:43:45.272624432 +0100 -@@ -151,6 +151,8 @@ - protected: - virtual uint cmp(const Node &n) const; - virtual uint size_of() const; // Size is bigger -+ // Should LoadNode::Ideal() attempt to remove control edges? -+ virtual bool can_remove_control() const; - const Type* const _type; // What kind of value is loaded? - public: - -@@ -174,8 +176,10 @@ - // we are equivalent to. We look for Load of a Store. - virtual Node *Identity( PhaseTransform *phase ); - -- // If the load is from Field memory and the pointer is non-null, we can -+ // If the load is from Field memory and the pointer is non-null, it might be possible to - // zero out the control input. -+ // If the offset is constant and the base is an object allocation, -+ // try to hook me up to the exact initializing store. - virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); - - // Split instance field load through Phi. -@@ -416,6 +420,10 @@ - //------------------------------LoadKlassNode---------------------------------- - // Load a Klass from an object - class LoadKlassNode : public LoadPNode { -+protected: -+ // In most cases, LoadKlassNode does not have the control input set. If the control -+ // input is set, it must not be removed (by LoadNode::Ideal()). -+ virtual bool can_remove_control() const; - public: - LoadKlassNode(Node *c, Node *mem, Node *adr, const TypePtr *at, const TypeKlassPtr *tk, MemOrd mo) - : LoadPNode(c, mem, adr, at, tk, mo) {} -@@ -425,7 +433,7 @@ - virtual bool depends_only_on_test() const { return true; } - - // Polymorphic factory method: -- static Node* make( PhaseGVN& gvn, Node *mem, Node *adr, const TypePtr* at, -+ static Node* make(PhaseGVN& gvn, Node* ctl, Node* mem, Node* adr, const TypePtr* at, - const TypeKlassPtr *tk = TypeKlassPtr::OBJECT ); - }; - ---- jdk8/hotspot/src/share/vm/opto/node.cpp 2015-01-27 08:42:54.002817529 +0100 -+++ jdk8/hotspot/src/share/vm/opto/node.cpp 2015-01-27 08:43:45.272624432 +0100 -@@ -69,7 +69,7 @@ - Compile::set_debug_idx(new_debug_idx); - set_debug_idx( new_debug_idx ); - assert(Compile::current()->unique() < (INT_MAX - 1), "Node limit exceeded INT_MAX"); -- assert(Compile::current()->live_nodes() < (uint)MaxNodeLimit, "Live Node limit exceeded limit"); -+ assert(Compile::current()->live_nodes() < Compile::current()->max_node_limit(), "Live Node limit exceeded limit"); - if (BreakAtNode != 0 && (_debug_idx == BreakAtNode || (int)_idx == BreakAtNode)) { - tty->print_cr("BreakAtNode: _idx=%d _debug_idx=%d", _idx, _debug_idx); - BREAKPOINT; -@@ -326,7 +326,7 @@ - Node::Node(uint req) - : _idx(IDX_INIT(req)) - { -- assert( req < (uint)(MaxNodeLimit - NodeLimitFudgeFactor), "Input limit exceeded" ); -+ assert( req < Compile::current()->max_node_limit() - NodeLimitFudgeFactor, "Input limit exceeded" ); - debug_only( verify_construction() ); - NOT_PRODUCT(nodes_created++); - if (req == 0) { ---- jdk8/hotspot/src/share/vm/opto/parse1.cpp 2015-01-27 08:42:54.002817529 +0100 -+++ jdk8/hotspot/src/share/vm/opto/parse1.cpp 2015-01-27 08:43:45.273624408 +0100 -@@ -1958,7 +1958,7 @@ - // finalization. In general this will fold up since the concrete - // class is often visible so the access flags are constant. - Node* klass_addr = basic_plus_adr( receiver, receiver, oopDesc::klass_offset_in_bytes() ); -- Node* klass = _gvn.transform( LoadKlassNode::make(_gvn, immutable_memory(), klass_addr, TypeInstPtr::KLASS) ); -+ Node* klass = _gvn.transform(LoadKlassNode::make(_gvn, NULL, immutable_memory(), klass_addr, TypeInstPtr::KLASS)); - - Node* access_flags_addr = basic_plus_adr(klass, klass, in_bytes(Klass::access_flags_offset())); - Node* access_flags = make_load(NULL, access_flags_addr, TypeInt::INT, T_INT, MemNode::unordered); ---- jdk8/hotspot/src/share/vm/opto/parseHelper.cpp 2015-01-27 08:42:54.003817506 +0100 -+++ jdk8/hotspot/src/share/vm/opto/parseHelper.cpp 2015-01-27 08:43:45.273624408 +0100 -@@ -156,22 +156,43 @@ - int klass_offset = oopDesc::klass_offset_in_bytes(); - Node* p = basic_plus_adr( ary, ary, klass_offset ); - // p's type is array-of-OOPS plus klass_offset -- Node* array_klass = _gvn.transform( LoadKlassNode::make(_gvn, immutable_memory(), p, TypeInstPtr::KLASS) ); -+ Node* array_klass = _gvn.transform(LoadKlassNode::make(_gvn, NULL, immutable_memory(), p, TypeInstPtr::KLASS)); - // Get the array klass - const TypeKlassPtr *tak = _gvn.type(array_klass)->is_klassptr(); - -- // array_klass's type is generally INexact array-of-oop. Heroically -- // cast the array klass to EXACT array and uncommon-trap if the cast -- // fails. -+ // The type of array_klass is usually INexact array-of-oop. Heroically -+ // cast array_klass to EXACT array and uncommon-trap if the cast fails. -+ // Make constant out of the inexact array klass, but use it only if the cast -+ // succeeds. - bool always_see_exact_class = false; - if (MonomorphicArrayCheck -- && !too_many_traps(Deoptimization::Reason_array_check)) { -+ && !too_many_traps(Deoptimization::Reason_array_check) -+ && !tak->klass_is_exact() -+ && tak != TypeKlassPtr::OBJECT) { -+ // Regarding the fourth condition in the if-statement from above: -+ // -+ // If the compiler has determined that the type of array 'ary' (represented -+ // by 'array_klass') is java/lang/Object, the compiler must not assume that -+ // the array 'ary' is monomorphic. -+ // -+ // If 'ary' were of type java/lang/Object, this arraystore would have to fail, -+ // because it is not possible to perform a arraystore into an object that is not -+ // a "proper" array. -+ // -+ // Therefore, let's obtain at runtime the type of 'ary' and check if we can still -+ // successfully perform the store. -+ // -+ // The implementation reasons for the condition are the following: -+ // -+ // java/lang/Object is the superclass of all arrays, but it is represented by the VM -+ // as an InstanceKlass. The checks generated by gen_checkcast() (see below) expect -+ // 'array_klass' to be ObjArrayKlass, which can result in invalid memory accesses. -+ // -+ // See issue JDK-8057622 for details. -+ - always_see_exact_class = true; - // (If no MDO at all, hope for the best, until a trap actually occurs.) -- } - -- // Is the array klass is exactly its defined type? -- if (always_see_exact_class && !tak->klass_is_exact()) { - // Make a constant out of the inexact array klass - const TypeKlassPtr *extak = tak->cast_to_exactness(true)->is_klassptr(); - Node* con = makecon(extak); -@@ -202,7 +223,11 @@ - // Extract the array element class - int element_klass_offset = in_bytes(ObjArrayKlass::element_klass_offset()); - Node *p2 = basic_plus_adr(array_klass, array_klass, element_klass_offset); -- Node *a_e_klass = _gvn.transform( LoadKlassNode::make(_gvn, immutable_memory(), p2, tak) ); -+ // We are allowed to use the constant type only if cast succeeded. If always_see_exact_class is true, -+ // we must set a control edge from the IfTrue node created by the uncommon_trap above to the -+ // LoadKlassNode. -+ Node* a_e_klass = _gvn.transform(LoadKlassNode::make(_gvn, always_see_exact_class ? control() : NULL, -+ immutable_memory(), p2, tak)); - - // Check (the hard way) and throw if not a subklass. - // Result is ignored, we just need the CFG effects. ---- jdk8/hotspot/src/share/vm/opto/phaseX.cpp 2015-01-27 08:42:54.003817506 +0100 -+++ jdk8/hotspot/src/share/vm/opto/phaseX.cpp 2015-01-27 08:43:45.273624408 +0100 -@@ -1340,15 +1340,27 @@ - } - } - -+ uint use_op = use->Opcode(); - if( use->is_Cmp() ) { // Enable CMP/BOOL optimization - add_users_to_worklist(use); // Put Bool on worklist -- // Look for the 'is_x2logic' pattern: "x ? : 0 : 1" and put the -- // phi merging either 0 or 1 onto the worklist - if (use->outcnt() > 0) { - Node* bol = use->raw_out(0); - if (bol->outcnt() > 0) { - Node* iff = bol->raw_out(0); -- if (iff->outcnt() == 2) { -+ if (use_op == Op_CmpI && -+ iff->is_CountedLoopEnd()) { -+ CountedLoopEndNode* cle = iff->as_CountedLoopEnd(); -+ if (cle->limit() == n && cle->phi() != NULL) { -+ // If an opaque node feeds into the limit condition of a -+ // CountedLoop, we need to process the Phi node for the -+ // induction variable when the opaque node is removed: -+ // the range of values taken by the Phi is now known and -+ // so its type is also known. -+ _worklist.push(cle->phi()); -+ } -+ } else if (iff->outcnt() == 2) { -+ // Look for the 'is_x2logic' pattern: "x ? : 0 : 1" and put the -+ // phi merging either 0 or 1 onto the worklist - Node* ifproj0 = iff->raw_out(0); - Node* ifproj1 = iff->raw_out(1); - if (ifproj0->outcnt() > 0 && ifproj1->outcnt() > 0) { -@@ -1360,9 +1372,26 @@ - } - } - } -+ if (use_op == Op_CmpI) { -+ Node* in1 = use->in(1); -+ for (uint i = 0; i < in1->outcnt(); i++) { -+ if (in1->raw_out(i)->Opcode() == Op_CastII) { -+ Node* castii = in1->raw_out(i); -+ if (castii->in(0) != NULL && castii->in(0)->in(0) != NULL && castii->in(0)->in(0)->is_If()) { -+ Node* ifnode = castii->in(0)->in(0); -+ if (ifnode->in(1) != NULL && ifnode->in(1)->is_Bool() && ifnode->in(1)->in(1) == use) { -+ // Reprocess a CastII node that may depend on an -+ // opaque node value when the opaque node is -+ // removed. In case it carries a dependency we can do -+ // a better job of computing its type. -+ _worklist.push(castii); -+ } -+ } -+ } -+ } -+ } - } - -- uint use_op = use->Opcode(); - // If changed Cast input, check Phi users for simple cycles - if( use->is_ConstraintCast() || use->is_CheckCastPP() ) { - for (DUIterator_Fast i2max, i2 = use->fast_outs(i2max); i2 < i2max; i2++) { ---- jdk8/hotspot/src/share/vm/opto/subnode.cpp 2015-01-27 08:42:54.003817506 +0100 -+++ jdk8/hotspot/src/share/vm/opto/subnode.cpp 2015-01-27 08:43:45.274624385 +0100 -@@ -1147,12 +1147,10 @@ - - //------------------------------dump_spec------------------------------------- - // Print special per-node info --#ifndef PRODUCT - void BoolTest::dump_on(outputStream *st) const { - const char *msg[] = {"eq","gt","of","lt","ne","le","nof","ge"}; - st->print("%s", msg[_test]); - } --#endif - - //============================================================================= - uint BoolNode::hash() const { return (Node::hash() << 3)|(_test._test+1); } ---- jdk8/hotspot/src/share/vm/opto/subnode.hpp 2015-01-27 08:42:54.004817482 +0100 -+++ jdk8/hotspot/src/share/vm/opto/subnode.hpp 2015-01-27 08:43:45.274624385 +0100 -@@ -275,9 +275,7 @@ - mask commute( ) const { return mask("032147658"[_test]-'0'); } - mask negate( ) const { return mask(_test^4); } - bool is_canonical( ) const { return (_test == BoolTest::ne || _test == BoolTest::lt || _test == BoolTest::le || _test == BoolTest::overflow); } --#ifndef PRODUCT - void dump_on(outputStream *st) const; --#endif - }; - - //------------------------------BoolNode--------------------------------------- ---- jdk8/hotspot/src/share/vm/prims/jni.cpp 2015-01-27 08:42:54.004817482 +0100 -+++ jdk8/hotspot/src/share/vm/prims/jni.cpp 2015-01-27 08:43:45.275624362 +0100 -@@ -5080,6 +5080,7 @@ - void TestNewSize_test(); - void TestKlass_test(); - void Test_linked_list(); -+void TestChunkedList_test(); - #if INCLUDE_ALL_GCS - void TestOldFreeSpaceCalculation_test(); - void TestG1BiasedArray_test(); -@@ -5108,6 +5109,7 @@ - run_unit_test(TestNewSize_test()); - run_unit_test(TestKlass_test()); - run_unit_test(Test_linked_list()); -+ run_unit_test(TestChunkedList_test()); - #if INCLUDE_VM_STRUCTS - run_unit_test(VMStructs::test()); - #endif ---- jdk8/hotspot/src/share/vm/prims/jvm.cpp 2015-01-27 08:42:54.005817459 +0100 -+++ jdk8/hotspot/src/share/vm/prims/jvm.cpp 2015-01-27 08:43:45.275624362 +0100 -@@ -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 - -@@ -594,13 +603,14 @@ - - // Make shallow object copy - const int size = obj->size(); -- oop new_obj = NULL; -+ oop new_obj_oop = NULL; - if (obj->is_array()) { - const int length = ((arrayOop)obj())->length(); -- new_obj = CollectedHeap::array_allocate(klass, size, length, CHECK_NULL); -+ new_obj_oop = CollectedHeap::array_allocate(klass, size, length, CHECK_NULL); - } else { -- new_obj = CollectedHeap::obj_allocate(klass, size, CHECK_NULL); -+ new_obj_oop = CollectedHeap::obj_allocate(klass, size, CHECK_NULL); - } -+ - // 4839641 (4840070): We must do an oop-atomic copy, because if another thread - // is modifying a reference field in the clonee, a non-oop-atomic copy might - // be suspended in the middle of copying the pointer and end up with parts -@@ -611,24 +621,41 @@ - // The same is true of StubRoutines::object_copy and the various oop_copy - // variants, and of the code generated by the inline_native_clone intrinsic. - assert(MinObjAlignmentInBytes >= BytesPerLong, "objects misaligned"); -- Copy::conjoint_jlongs_atomic((jlong*)obj(), (jlong*)new_obj, -+ Copy::conjoint_jlongs_atomic((jlong*)obj(), (jlong*)new_obj_oop, - (size_t)align_object_size(size) / HeapWordsPerLong); - // Clear the header -- new_obj->init_mark(); -+ new_obj_oop->init_mark(); - - // Store check (mark entire object and let gc sort it out) - BarrierSet* bs = Universe::heap()->barrier_set(); - assert(bs->has_write_region_opt(), "Barrier set does not have write_region"); -- bs->write_region(MemRegion((HeapWord*)new_obj, size)); -+ bs->write_region(MemRegion((HeapWord*)new_obj_oop, size)); -+ -+ Handle new_obj(THREAD, new_obj_oop); -+ // Special handling for MemberNames. Since they contain Method* metadata, they -+ // must be registered so that RedefineClasses can fix metadata contained in them. -+ if (java_lang_invoke_MemberName::is_instance(new_obj()) && -+ java_lang_invoke_MemberName::is_method(new_obj())) { -+ Method* method = (Method*)java_lang_invoke_MemberName::vmtarget(new_obj()); -+ // MemberName may be unresolved, so doesn't need registration until resolved. -+ if (method != NULL) { -+ methodHandle m(THREAD, method); -+ // This can safepoint and redefine method, so need both new_obj and method -+ // in a handle, for two different reasons. new_obj can move, method can be -+ // deleted if nothing is using it on the stack. -+ m->method_holder()->add_member_name(new_obj()); -+ } -+ } - - // Caution: this involves a java upcall, so the clone should be - // "gc-robust" by this stage. - if (klass->has_finalizer()) { - assert(obj->is_instance(), "should be instanceOop"); -- new_obj = InstanceKlass::register_finalizer(instanceOop(new_obj), CHECK_NULL); -+ new_obj_oop = InstanceKlass::register_finalizer(instanceOop(new_obj()), CHECK_NULL); -+ new_obj = Handle(THREAD, new_obj_oop); - } - -- return JNIHandles::make_local(env, oop(new_obj)); -+ return JNIHandles::make_local(env, new_obj()); - JVM_END - - // java.lang.Compiler //////////////////////////////////////////////////// -@@ -766,6 +793,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. - // -@@ -4497,7 +4554,7 @@ - - JVM_ENTRY(void, JVM_GetVersionInfo(JNIEnv* env, jvm_version_info* info, size_t info_size)) - { -- memset(info, 0, sizeof(info_size)); -+ memset(info, 0, info_size); - - info->jvm_version = Abstract_VM_Version::jvm_version(); - info->update_version = 0; /* 0 in HotSpot Express VM */ ---- jdk8/hotspot/src/share/vm/prims/jvm.h 2015-01-27 08:42:54.005817459 +0100 -+++ jdk8/hotspot/src/share/vm/prims/jvm.h 2015-01-27 08:43:45.276624339 +0100 -@@ -1553,6 +1553,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 ---- jdk8/hotspot/src/share/vm/prims/jvmtiClassFileReconstituter.cpp 2015-01-27 08:42:54.005817459 +0100 -+++ jdk8/hotspot/src/share/vm/prims/jvmtiClassFileReconstituter.cpp 2015-01-27 08:43:45.276624339 +0100 -@@ -57,6 +57,7 @@ - void JvmtiClassFileReconstituter::write_field_infos() { - HandleMark hm(thread()); - Array* fields_anno = ikh()->fields_annotations(); -+ Array* fields_type_anno = ikh()->fields_type_annotations(); - - // Compute the real number of Java fields - int java_fields = ikh()->java_fields_count(); -@@ -71,6 +72,7 @@ - // int offset = ikh()->field_offset( index ); - int generic_signature_index = fs.generic_signature_index(); - AnnotationArray* anno = fields_anno == NULL ? NULL : fields_anno->at(fs.index()); -+ AnnotationArray* type_anno = fields_type_anno == NULL ? NULL : fields_type_anno->at(fs.index()); - - // JVMSpec| field_info { - // JVMSpec| u2 access_flags; -@@ -96,6 +98,9 @@ - if (anno != NULL) { - ++attr_count; // has RuntimeVisibleAnnotations attribute - } -+ if (type_anno != NULL) { -+ ++attr_count; // has RuntimeVisibleTypeAnnotations attribute -+ } - - write_u2(attr_count); - -@@ -113,6 +118,9 @@ - if (anno != NULL) { - write_annotations_attribute("RuntimeVisibleAnnotations", anno); - } -+ if (type_anno != NULL) { -+ write_annotations_attribute("RuntimeVisibleTypeAnnotations", type_anno); -+ } - } - } - -@@ -553,6 +561,7 @@ - AnnotationArray* anno = method->annotations(); - AnnotationArray* param_anno = method->parameter_annotations(); - AnnotationArray* default_anno = method->annotation_default(); -+ AnnotationArray* type_anno = method->type_annotations(); - - // skip generated default interface methods - if (method->is_overpass()) { -@@ -588,6 +597,9 @@ - if (param_anno != NULL) { - ++attr_count; // has RuntimeVisibleParameterAnnotations attribute - } -+ if (type_anno != NULL) { -+ ++attr_count; // has RuntimeVisibleTypeAnnotations attribute -+ } - - write_u2(attr_count); - if (const_method->code_size() > 0) { -@@ -612,6 +624,9 @@ - if (param_anno != NULL) { - write_annotations_attribute("RuntimeVisibleParameterAnnotations", param_anno); - } -+ if (type_anno != NULL) { -+ write_annotations_attribute("RuntimeVisibleTypeAnnotations", type_anno); -+ } - } - - // Write the class attributes portion of ClassFile structure -@@ -621,6 +636,7 @@ - u2 inner_classes_length = inner_classes_attribute_length(); - Symbol* generic_signature = ikh()->generic_signature(); - AnnotationArray* anno = ikh()->class_annotations(); -+ AnnotationArray* type_anno = ikh()->class_type_annotations(); - - int attr_count = 0; - if (generic_signature != NULL) { -@@ -638,6 +654,9 @@ - if (anno != NULL) { - ++attr_count; // has RuntimeVisibleAnnotations attribute - } -+ if (type_anno != NULL) { -+ ++attr_count; // has RuntimeVisibleTypeAnnotations attribute -+ } - if (cpool()->operands() != NULL) { - ++attr_count; - } -@@ -659,6 +678,9 @@ - if (anno != NULL) { - write_annotations_attribute("RuntimeVisibleAnnotations", anno); - } -+ if (type_anno != NULL) { -+ write_annotations_attribute("RuntimeVisibleTypeAnnotations", type_anno); -+ } - if (cpool()->operands() != NULL) { - write_bootstrapmethod_attribute(); - } ---- jdk8/hotspot/src/share/vm/prims/jvmtiEnv.cpp 2015-01-27 08:42:54.006817436 +0100 -+++ jdk8/hotspot/src/share/vm/prims/jvmtiEnv.cpp 2015-01-27 08:43:45.276624339 +0100 -@@ -23,6 +23,7 @@ - */ - - #include "precompiled.hpp" -+#include "classfile/classLoaderExt.hpp" - #include "classfile/systemDictionary.hpp" - #include "classfile/vmSymbols.hpp" - #include "interpreter/bytecodeStream.hpp" -@@ -475,7 +476,7 @@ - if (TraceClassLoading) { - tty->print_cr("[Opened %s]", zip_entry->name()); - } -- ClassLoader::add_to_list(zip_entry); -+ ClassLoaderExt::append_boot_classpath(zip_entry); - return JVMTI_ERROR_NONE; - } else { - return JVMTI_ERROR_WRONG_PHASE; ---- jdk8/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp 2015-01-27 08:42:54.008817389 +0100 -+++ jdk8/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp 2015-01-27 08:43:45.277624315 +0100 -@@ -135,7 +135,7 @@ - - // Mark methods seen on stack and everywhere else so old methods are not - // cleaned up if they're on the stack. -- MetadataOnStackMark md_on_stack; -+ MetadataOnStackMark md_on_stack(true); - HandleMark hm(thread); // make sure any handles created are deleted - // before the stack walk again. - -@@ -1569,6 +1569,29 @@ - return false; - } - -+ // rewrite constant pool references in the class_type_annotations: -+ if (!rewrite_cp_refs_in_class_type_annotations(scratch_class, THREAD)) { -+ // propagate failure back to caller -+ return false; -+ } -+ -+ // rewrite constant pool references in the fields_type_annotations: -+ if (!rewrite_cp_refs_in_fields_type_annotations(scratch_class, THREAD)) { -+ // propagate failure back to caller -+ return false; -+ } -+ -+ // rewrite constant pool references in the methods_type_annotations: -+ if (!rewrite_cp_refs_in_methods_type_annotations(scratch_class, THREAD)) { -+ // propagate failure back to caller -+ return false; -+ } -+ -+ // There can be type annotations in the Code part of a method_info attribute. -+ // These annotations are not accessible, even by reflection. -+ // Currently they are not even parsed by the ClassFileParser. -+ // If runtime access is added they will also need to be rewritten. -+ - // rewrite source file name index: - u2 source_file_name_idx = scratch_class->source_file_name_index(); - if (source_file_name_idx != 0) { -@@ -2239,6 +2262,588 @@ - } // end rewrite_cp_refs_in_methods_default_annotations() - - -+// Rewrite constant pool references in a class_type_annotations field. -+bool VM_RedefineClasses::rewrite_cp_refs_in_class_type_annotations( -+ instanceKlassHandle scratch_class, TRAPS) { -+ -+ AnnotationArray* class_type_annotations = scratch_class->class_type_annotations(); -+ if (class_type_annotations == NULL || class_type_annotations->length() == 0) { -+ // no class_type_annotations so nothing to do -+ return true; -+ } -+ -+ RC_TRACE_WITH_THREAD(0x02000000, THREAD, -+ ("class_type_annotations length=%d", class_type_annotations->length())); -+ -+ int byte_i = 0; // byte index into class_type_annotations -+ return rewrite_cp_refs_in_type_annotations_typeArray(class_type_annotations, -+ byte_i, "ClassFile", THREAD); -+} // end rewrite_cp_refs_in_class_type_annotations() -+ -+ -+// Rewrite constant pool references in a fields_type_annotations field. -+bool VM_RedefineClasses::rewrite_cp_refs_in_fields_type_annotations( -+ instanceKlassHandle scratch_class, TRAPS) { -+ -+ Array* fields_type_annotations = scratch_class->fields_type_annotations(); -+ if (fields_type_annotations == NULL || fields_type_annotations->length() == 0) { -+ // no fields_type_annotations so nothing to do -+ return true; -+ } -+ -+ RC_TRACE_WITH_THREAD(0x02000000, THREAD, -+ ("fields_type_annotations length=%d", fields_type_annotations->length())); -+ -+ for (int i = 0; i < fields_type_annotations->length(); i++) { -+ AnnotationArray* field_type_annotations = fields_type_annotations->at(i); -+ if (field_type_annotations == NULL || field_type_annotations->length() == 0) { -+ // this field does not have any annotations so skip it -+ continue; -+ } -+ -+ int byte_i = 0; // byte index into field_type_annotations -+ if (!rewrite_cp_refs_in_type_annotations_typeArray(field_type_annotations, -+ byte_i, "field_info", THREAD)) { -+ RC_TRACE_WITH_THREAD(0x02000000, THREAD, -+ ("bad field_type_annotations at %d", i)); -+ // propagate failure back to caller -+ return false; -+ } -+ } -+ -+ return true; -+} // end rewrite_cp_refs_in_fields_type_annotations() -+ -+ -+// Rewrite constant pool references in a methods_type_annotations field. -+bool VM_RedefineClasses::rewrite_cp_refs_in_methods_type_annotations( -+ instanceKlassHandle scratch_class, TRAPS) { -+ -+ for (int i = 0; i < scratch_class->methods()->length(); i++) { -+ Method* m = scratch_class->methods()->at(i); -+ AnnotationArray* method_type_annotations = m->constMethod()->type_annotations(); -+ -+ if (method_type_annotations == NULL || method_type_annotations->length() == 0) { -+ // this method does not have any annotations so skip it -+ continue; -+ } -+ -+ RC_TRACE_WITH_THREAD(0x02000000, THREAD, -+ ("methods type_annotations length=%d", method_type_annotations->length())); -+ -+ int byte_i = 0; // byte index into method_type_annotations -+ if (!rewrite_cp_refs_in_type_annotations_typeArray(method_type_annotations, -+ byte_i, "method_info", THREAD)) { -+ RC_TRACE_WITH_THREAD(0x02000000, THREAD, -+ ("bad method_type_annotations at %d", i)); -+ // propagate failure back to caller -+ return false; -+ } -+ } -+ -+ return true; -+} // end rewrite_cp_refs_in_methods_type_annotations() -+ -+ -+// Rewrite constant pool references in a type_annotations -+// field. This "structure" is adapted from the -+// RuntimeVisibleTypeAnnotations_attribute described in -+// section 4.7.20 of the Java SE 8 Edition of the VM spec: -+// -+// type_annotations_typeArray { -+// u2 num_annotations; -+// type_annotation annotations[num_annotations]; -+// } -+// -+bool VM_RedefineClasses::rewrite_cp_refs_in_type_annotations_typeArray( -+ AnnotationArray* type_annotations_typeArray, int &byte_i_ref, -+ const char * location_mesg, TRAPS) { -+ -+ if ((byte_i_ref + 2) > type_annotations_typeArray->length()) { -+ // not enough room for num_annotations field -+ RC_TRACE_WITH_THREAD(0x02000000, THREAD, -+ ("length() is too small for num_annotations field")); -+ return false; -+ } -+ -+ u2 num_annotations = Bytes::get_Java_u2((address) -+ type_annotations_typeArray->adr_at(byte_i_ref)); -+ byte_i_ref += 2; -+ -+ RC_TRACE_WITH_THREAD(0x02000000, THREAD, -+ ("num_type_annotations=%d", num_annotations)); -+ -+ int calc_num_annotations = 0; -+ for (; calc_num_annotations < num_annotations; calc_num_annotations++) { -+ if (!rewrite_cp_refs_in_type_annotation_struct(type_annotations_typeArray, -+ byte_i_ref, location_mesg, THREAD)) { -+ RC_TRACE_WITH_THREAD(0x02000000, THREAD, -+ ("bad type_annotation_struct at %d", calc_num_annotations)); -+ // propagate failure back to caller -+ return false; -+ } -+ } -+ assert(num_annotations == calc_num_annotations, "sanity check"); -+ -+ if (byte_i_ref != type_annotations_typeArray->length()) { -+ RC_TRACE_WITH_THREAD(0x02000000, THREAD, -+ ("read wrong amount of bytes at end of processing " -+ "type_annotations_typeArray (%d of %d bytes were read)", -+ byte_i_ref, type_annotations_typeArray->length())); -+ return false; -+ } -+ -+ return true; -+} // end rewrite_cp_refs_in_type_annotations_typeArray() -+ -+ -+// Rewrite constant pool references in a type_annotation -+// field. This "structure" is adapted from the -+// RuntimeVisibleTypeAnnotations_attribute described in -+// section 4.7.20 of the Java SE 8 Edition of the VM spec: -+// -+// type_annotation { -+// u1 target_type; -+// union { -+// type_parameter_target; -+// supertype_target; -+// type_parameter_bound_target; -+// empty_target; -+// method_formal_parameter_target; -+// throws_target; -+// localvar_target; -+// catch_target; -+// offset_target; -+// type_argument_target; -+// } target_info; -+// type_path target_path; -+// annotation anno; -+// } -+// -+bool VM_RedefineClasses::rewrite_cp_refs_in_type_annotation_struct( -+ AnnotationArray* type_annotations_typeArray, int &byte_i_ref, -+ const char * location_mesg, TRAPS) { -+ -+ if (!skip_type_annotation_target(type_annotations_typeArray, -+ byte_i_ref, location_mesg, THREAD)) { -+ return false; -+ } -+ -+ if (!skip_type_annotation_type_path(type_annotations_typeArray, -+ byte_i_ref, THREAD)) { -+ return false; -+ } -+ -+ if (!rewrite_cp_refs_in_annotation_struct(type_annotations_typeArray, -+ byte_i_ref, THREAD)) { -+ return false; -+ } -+ -+ return true; -+} // end rewrite_cp_refs_in_type_annotation_struct() -+ -+ -+// Read, verify and skip over the target_type and target_info part -+// so that rewriting can continue in the later parts of the struct. -+// -+// u1 target_type; -+// union { -+// type_parameter_target; -+// supertype_target; -+// type_parameter_bound_target; -+// empty_target; -+// method_formal_parameter_target; -+// throws_target; -+// localvar_target; -+// catch_target; -+// offset_target; -+// type_argument_target; -+// } target_info; -+// -+bool VM_RedefineClasses::skip_type_annotation_target( -+ AnnotationArray* type_annotations_typeArray, int &byte_i_ref, -+ const char * location_mesg, TRAPS) { -+ -+ if ((byte_i_ref + 1) > type_annotations_typeArray->length()) { -+ // not enough room for a target_type let alone the rest of a type_annotation -+ RC_TRACE_WITH_THREAD(0x02000000, THREAD, -+ ("length() is too small for a target_type")); -+ return false; -+ } -+ -+ u1 target_type = type_annotations_typeArray->at(byte_i_ref); -+ byte_i_ref += 1; -+ RC_TRACE_WITH_THREAD(0x02000000, THREAD, ("target_type=0x%.2x", target_type)); -+ RC_TRACE_WITH_THREAD(0x02000000, THREAD, ("location=%s", location_mesg)); -+ -+ // Skip over target_info -+ switch (target_type) { -+ case 0x00: -+ // kind: type parameter declaration of generic class or interface -+ // location: ClassFile -+ case 0x01: -+ // kind: type parameter declaration of generic method or constructor -+ // location: method_info -+ -+ { -+ // struct: -+ // type_parameter_target { -+ // u1 type_parameter_index; -+ // } -+ // -+ if ((byte_i_ref + 1) > type_annotations_typeArray->length()) { -+ RC_TRACE_WITH_THREAD(0x02000000, THREAD, -+ ("length() is too small for a type_parameter_target")); -+ return false; -+ } -+ -+ u1 type_parameter_index = type_annotations_typeArray->at(byte_i_ref); -+ byte_i_ref += 1; -+ -+ RC_TRACE_WITH_THREAD(0x02000000, THREAD, -+ ("type_parameter_target: type_parameter_index=%d", -+ type_parameter_index)); -+ } break; -+ -+ case 0x10: -+ // kind: type in extends clause of class or interface declaration -+ // (including the direct superclass of an anonymous class declaration), -+ // or in implements clause of interface declaration -+ // location: ClassFile -+ -+ { -+ // struct: -+ // supertype_target { -+ // u2 supertype_index; -+ // } -+ // -+ if ((byte_i_ref + 2) > type_annotations_typeArray->length()) { -+ RC_TRACE_WITH_THREAD(0x02000000, THREAD, -+ ("length() is too small for a supertype_target")); -+ return false; -+ } -+ -+ u2 supertype_index = Bytes::get_Java_u2((address) -+ type_annotations_typeArray->adr_at(byte_i_ref)); -+ byte_i_ref += 2; -+ -+ RC_TRACE_WITH_THREAD(0x02000000, THREAD, -+ ("supertype_target: supertype_index=%d", supertype_index)); -+ } break; -+ -+ case 0x11: -+ // kind: type in bound of type parameter declaration of generic class or interface -+ // location: ClassFile -+ case 0x12: -+ // kind: type in bound of type parameter declaration of generic method or constructor -+ // location: method_info -+ -+ { -+ // struct: -+ // type_parameter_bound_target { -+ // u1 type_parameter_index; -+ // u1 bound_index; -+ // } -+ // -+ if ((byte_i_ref + 2) > type_annotations_typeArray->length()) { -+ RC_TRACE_WITH_THREAD(0x02000000, THREAD, -+ ("length() is too small for a type_parameter_bound_target")); -+ return false; -+ } -+ -+ u1 type_parameter_index = type_annotations_typeArray->at(byte_i_ref); -+ byte_i_ref += 1; -+ u1 bound_index = type_annotations_typeArray->at(byte_i_ref); -+ byte_i_ref += 1; -+ -+ RC_TRACE_WITH_THREAD(0x02000000, THREAD, -+ ("type_parameter_bound_target: type_parameter_index=%d, bound_index=%d", -+ type_parameter_index, bound_index)); -+ } break; -+ -+ case 0x13: -+ // kind: type in field declaration -+ // location: field_info -+ case 0x14: -+ // kind: return type of method, or type of newly constructed object -+ // location: method_info -+ case 0x15: -+ // kind: receiver type of method or constructor -+ // location: method_info -+ -+ { -+ // struct: -+ // empty_target { -+ // } -+ // -+ RC_TRACE_WITH_THREAD(0x02000000, THREAD, -+ ("empty_target")); -+ } break; -+ -+ case 0x16: -+ // kind: type in formal parameter declaration of method, constructor, or lambda expression -+ // location: method_info -+ -+ { -+ // struct: -+ // formal_parameter_target { -+ // u1 formal_parameter_index; -+ // } -+ // -+ if ((byte_i_ref + 1) > type_annotations_typeArray->length()) { -+ RC_TRACE_WITH_THREAD(0x02000000, THREAD, -+ ("length() is too small for a formal_parameter_target")); -+ return false; -+ } -+ -+ u1 formal_parameter_index = type_annotations_typeArray->at(byte_i_ref); -+ byte_i_ref += 1; -+ -+ RC_TRACE_WITH_THREAD(0x02000000, THREAD, -+ ("formal_parameter_target: formal_parameter_index=%d", -+ formal_parameter_index)); -+ } break; -+ -+ case 0x17: -+ // kind: type in throws clause of method or constructor -+ // location: method_info -+ -+ { -+ // struct: -+ // throws_target { -+ // u2 throws_type_index -+ // } -+ // -+ if ((byte_i_ref + 2) > type_annotations_typeArray->length()) { -+ RC_TRACE_WITH_THREAD(0x02000000, THREAD, -+ ("length() is too small for a throws_target")); -+ return false; -+ } -+ -+ u2 throws_type_index = Bytes::get_Java_u2((address) -+ type_annotations_typeArray->adr_at(byte_i_ref)); -+ byte_i_ref += 2; -+ -+ RC_TRACE_WITH_THREAD(0x02000000, THREAD, -+ ("throws_target: throws_type_index=%d", throws_type_index)); -+ } break; -+ -+ case 0x40: -+ // kind: type in local variable declaration -+ // location: Code -+ case 0x41: -+ // kind: type in resource variable declaration -+ // location: Code -+ -+ { -+ // struct: -+ // localvar_target { -+ // u2 table_length; -+ // struct { -+ // u2 start_pc; -+ // u2 length; -+ // u2 index; -+ // } table[table_length]; -+ // } -+ // -+ if ((byte_i_ref + 2) > type_annotations_typeArray->length()) { -+ // not enough room for a table_length let alone the rest of a localvar_target -+ RC_TRACE_WITH_THREAD(0x02000000, THREAD, -+ ("length() is too small for a localvar_target table_length")); -+ return false; -+ } -+ -+ u2 table_length = Bytes::get_Java_u2((address) -+ type_annotations_typeArray->adr_at(byte_i_ref)); -+ byte_i_ref += 2; -+ -+ RC_TRACE_WITH_THREAD(0x02000000, THREAD, -+ ("localvar_target: table_length=%d", table_length)); -+ -+ int table_struct_size = 2 + 2 + 2; // 3 u2 variables per table entry -+ int table_size = table_length * table_struct_size; -+ -+ if ((byte_i_ref + table_size) > type_annotations_typeArray->length()) { -+ // not enough room for a table -+ RC_TRACE_WITH_THREAD(0x02000000, THREAD, -+ ("length() is too small for a table array of length %d", table_length)); -+ return false; -+ } -+ -+ // Skip over table -+ byte_i_ref += table_size; -+ } break; -+ -+ case 0x42: -+ // kind: type in exception parameter declaration -+ // location: Code -+ -+ { -+ // struct: -+ // catch_target { -+ // u2 exception_table_index; -+ // } -+ // -+ if ((byte_i_ref + 2) > type_annotations_typeArray->length()) { -+ RC_TRACE_WITH_THREAD(0x02000000, THREAD, -+ ("length() is too small for a catch_target")); -+ return false; -+ } -+ -+ u2 exception_table_index = Bytes::get_Java_u2((address) -+ type_annotations_typeArray->adr_at(byte_i_ref)); -+ byte_i_ref += 2; -+ -+ RC_TRACE_WITH_THREAD(0x02000000, THREAD, -+ ("catch_target: exception_table_index=%d", exception_table_index)); -+ } break; -+ -+ case 0x43: -+ // kind: type in instanceof expression -+ // location: Code -+ case 0x44: -+ // kind: type in new expression -+ // location: Code -+ case 0x45: -+ // kind: type in method reference expression using ::new -+ // location: Code -+ case 0x46: -+ // kind: type in method reference expression using ::Identifier -+ // location: Code -+ -+ { -+ // struct: -+ // offset_target { -+ // u2 offset; -+ // } -+ // -+ if ((byte_i_ref + 2) > type_annotations_typeArray->length()) { -+ RC_TRACE_WITH_THREAD(0x02000000, THREAD, -+ ("length() is too small for a offset_target")); -+ return false; -+ } -+ -+ u2 offset = Bytes::get_Java_u2((address) -+ type_annotations_typeArray->adr_at(byte_i_ref)); -+ byte_i_ref += 2; -+ -+ RC_TRACE_WITH_THREAD(0x02000000, THREAD, -+ ("offset_target: offset=%d", offset)); -+ } break; -+ -+ case 0x47: -+ // kind: type in cast expression -+ // location: Code -+ case 0x48: -+ // kind: type argument for generic constructor in new expression or -+ // explicit constructor invocation statement -+ // location: Code -+ case 0x49: -+ // kind: type argument for generic method in method invocation expression -+ // location: Code -+ case 0x4A: -+ // kind: type argument for generic constructor in method reference expression using ::new -+ // location: Code -+ case 0x4B: -+ // kind: type argument for generic method in method reference expression using ::Identifier -+ // location: Code -+ -+ { -+ // struct: -+ // type_argument_target { -+ // u2 offset; -+ // u1 type_argument_index; -+ // } -+ // -+ if ((byte_i_ref + 3) > type_annotations_typeArray->length()) { -+ RC_TRACE_WITH_THREAD(0x02000000, THREAD, -+ ("length() is too small for a type_argument_target")); -+ return false; -+ } -+ -+ u2 offset = Bytes::get_Java_u2((address) -+ type_annotations_typeArray->adr_at(byte_i_ref)); -+ byte_i_ref += 2; -+ u1 type_argument_index = type_annotations_typeArray->at(byte_i_ref); -+ byte_i_ref += 1; -+ -+ RC_TRACE_WITH_THREAD(0x02000000, THREAD, -+ ("type_argument_target: offset=%d, type_argument_index=%d", -+ offset, type_argument_index)); -+ } break; -+ -+ default: -+ RC_TRACE_WITH_THREAD(0x02000000, THREAD, -+ ("unknown target_type")); -+#ifdef ASSERT -+ ShouldNotReachHere(); -+#endif -+ return false; -+ } -+ -+ return true; -+} // end skip_type_annotation_target() -+ -+ -+// Read, verify and skip over the type_path part so that rewriting -+// can continue in the later parts of the struct. -+// -+// type_path { -+// u1 path_length; -+// { -+// u1 type_path_kind; -+// u1 type_argument_index; -+// } path[path_length]; -+// } -+// -+bool VM_RedefineClasses::skip_type_annotation_type_path( -+ AnnotationArray* type_annotations_typeArray, int &byte_i_ref, TRAPS) { -+ -+ if ((byte_i_ref + 1) > type_annotations_typeArray->length()) { -+ // not enough room for a path_length let alone the rest of the type_path -+ RC_TRACE_WITH_THREAD(0x02000000, THREAD, -+ ("length() is too small for a type_path")); -+ return false; -+ } -+ -+ u1 path_length = type_annotations_typeArray->at(byte_i_ref); -+ byte_i_ref += 1; -+ -+ RC_TRACE_WITH_THREAD(0x02000000, THREAD, -+ ("type_path: path_length=%d", path_length)); -+ -+ int calc_path_length = 0; -+ for (; calc_path_length < path_length; calc_path_length++) { -+ if ((byte_i_ref + 1 + 1) > type_annotations_typeArray->length()) { -+ // not enough room for a path -+ RC_TRACE_WITH_THREAD(0x02000000, THREAD, -+ ("length() is too small for path entry %d of %d", -+ calc_path_length, path_length)); -+ return false; -+ } -+ -+ u1 type_path_kind = type_annotations_typeArray->at(byte_i_ref); -+ byte_i_ref += 1; -+ u1 type_argument_index = type_annotations_typeArray->at(byte_i_ref); -+ byte_i_ref += 1; -+ -+ RC_TRACE_WITH_THREAD(0x02000000, THREAD, -+ ("type_path: path[%d]: type_path_kind=%d, type_argument_index=%d", -+ calc_path_length, type_path_kind, type_argument_index)); -+ -+ if (type_path_kind > 3 || (type_path_kind != 3 && type_argument_index != 0)) { -+ // not enough room for a path -+ RC_TRACE_WITH_THREAD(0x02000000, THREAD, -+ ("inconsistent type_path values")); -+ return false; -+ } -+ } -+ assert(path_length == calc_path_length, "sanity check"); -+ -+ return true; -+} // end skip_type_annotation_type_path() -+ -+ - // Rewrite constant pool references in the method's stackmap table. - // These "structures" are adapted from the StackMapTable_attribute that - // is described in section 4.8.4 of the 6.0 version of the VM spec -@@ -3223,23 +3828,6 @@ - - void VM_RedefineClasses::swap_annotations(instanceKlassHandle the_class, - instanceKlassHandle scratch_class) { -- // Since there is currently no rewriting of type annotations indexes -- // into the CP, we null out type annotations on scratch_class before -- // we swap annotations with the_class rather than facing the -- // possibility of shipping annotations with broken indexes to -- // Java-land. -- ClassLoaderData* loader_data = scratch_class->class_loader_data(); -- AnnotationArray* new_class_type_annotations = scratch_class->class_type_annotations(); -- if (new_class_type_annotations != NULL) { -- MetadataFactory::free_array(loader_data, new_class_type_annotations); -- scratch_class->annotations()->set_class_type_annotations(NULL); -- } -- Array* new_field_type_annotations = scratch_class->fields_type_annotations(); -- if (new_field_type_annotations != NULL) { -- Annotations::free_contents(loader_data, new_field_type_annotations); -- scratch_class->annotations()->set_fields_type_annotations(NULL); -- } -- - // Swap annotation fields values - Annotations* old_annotations = the_class->annotations(); - the_class->set_annotations(scratch_class->annotations()); ---- jdk8/hotspot/src/share/vm/prims/jvmtiRedefineClasses.hpp 2015-01-27 08:42:54.008817389 +0100 -+++ jdk8/hotspot/src/share/vm/prims/jvmtiRedefineClasses.hpp 2015-01-27 08:43:45.278624292 +0100 -@@ -457,6 +457,17 @@ - instanceKlassHandle scratch_class, TRAPS); - bool rewrite_cp_refs_in_element_value( - AnnotationArray* class_annotations, int &byte_i_ref, TRAPS); -+ bool rewrite_cp_refs_in_type_annotations_typeArray( -+ AnnotationArray* type_annotations_typeArray, int &byte_i_ref, -+ const char * location_mesg, TRAPS); -+ bool rewrite_cp_refs_in_type_annotation_struct( -+ AnnotationArray* type_annotations_typeArray, int &byte_i_ref, -+ const char * location_mesg, TRAPS); -+ bool skip_type_annotation_target( -+ AnnotationArray* type_annotations_typeArray, int &byte_i_ref, -+ const char * location_mesg, TRAPS); -+ bool skip_type_annotation_type_path( -+ AnnotationArray* type_annotations_typeArray, int &byte_i_ref, TRAPS); - bool rewrite_cp_refs_in_fields_annotations( - instanceKlassHandle scratch_class, TRAPS); - void rewrite_cp_refs_in_method(methodHandle method, -@@ -468,6 +479,12 @@ - instanceKlassHandle scratch_class, TRAPS); - bool rewrite_cp_refs_in_methods_parameter_annotations( - instanceKlassHandle scratch_class, TRAPS); -+ bool rewrite_cp_refs_in_class_type_annotations( -+ instanceKlassHandle scratch_class, TRAPS); -+ bool rewrite_cp_refs_in_fields_type_annotations( -+ instanceKlassHandle scratch_class, TRAPS); -+ bool rewrite_cp_refs_in_methods_type_annotations( -+ instanceKlassHandle scratch_class, TRAPS); - void rewrite_cp_refs_in_stack_map_table(methodHandle method, TRAPS); - void rewrite_cp_refs_in_verification_type_info( - address& stackmap_addr_ref, address stackmap_end, u2 frame_i, ---- jdk8/hotspot/src/share/vm/prims/methodHandles.cpp 2015-01-27 08:42:54.008817389 +0100 -+++ jdk8/hotspot/src/share/vm/prims/methodHandles.cpp 2015-01-27 08:43:45.278624292 +0100 -@@ -29,7 +29,6 @@ - #include "interpreter/oopMapCache.hpp" - #include "memory/allocation.inline.hpp" - #include "memory/oopFactory.hpp" --#include "prims/jvmtiRedefineClassesTrace.hpp" - #include "prims/methodHandles.hpp" - #include "runtime/compilationPolicy.hpp" - #include "runtime/javaCalls.hpp" -@@ -271,9 +270,12 @@ - // This is done eagerly, since it is readily available without - // constructing any new objects. - // TO DO: maybe intern mname_oop -- m->method_holder()->add_member_name(m->method_idnum(), mname); -- -+ if (m->method_holder()->add_member_name(mname)) { - return mname(); -+ } else { -+ // Redefinition caused this to fail. Return NULL (and an exception?) -+ return NULL; -+ } - } - - oop MethodHandles::init_field_MemberName(Handle mname, fieldDescriptor& fd, bool is_setter) { -@@ -946,63 +948,27 @@ - } - } - --void MemberNameTable::add_member_name(int index, jweak mem_name_wref) { -+void MemberNameTable::add_member_name(jweak mem_name_wref) { - assert_locked_or_safepoint(MemberNameTable_lock); -- this->at_put_grow(index, mem_name_wref); --} -- --// Return a member name oop or NULL. --oop MemberNameTable::get_member_name(int index) { -- assert_locked_or_safepoint(MemberNameTable_lock); -- -- jweak ref = this->at(index); -- oop mem_name = JNIHandles::resolve(ref); -- return mem_name; -+ this->push(mem_name_wref); - } - - #if INCLUDE_JVMTI --oop MemberNameTable::find_member_name_by_method(Method* old_method) { -- assert_locked_or_safepoint(MemberNameTable_lock); -- oop found = NULL; -- int len = this->length(); -- -- for (int idx = 0; idx < len; idx++) { -- oop mem_name = JNIHandles::resolve(this->at(idx)); -- if (mem_name == NULL) { -- continue; -- } -- Method* method = (Method*)java_lang_invoke_MemberName::vmtarget(mem_name); -- if (method == old_method) { -- found = mem_name; -- break; -- } -- } -- return found; --} -- --// It is called at safepoint only -+// It is called at safepoint only for RedefineClasses - void MemberNameTable::adjust_method_entries(Method** old_methods, Method** new_methods, - int methods_length, bool *trace_name_printed) { - assert(SafepointSynchronize::is_at_safepoint(), "only called at safepoint"); -- // search the MemberNameTable for uses of either obsolete or EMCP methods -+ // For each redefined method - for (int j = 0; j < methods_length; j++) { - Method* old_method = old_methods[j]; - Method* new_method = new_methods[j]; -- oop mem_name = find_member_name_by_method(old_method); -- if (mem_name != NULL) { -- java_lang_invoke_MemberName::adjust_vmtarget(mem_name, new_method); - -- if (RC_TRACE_IN_RANGE(0x00100000, 0x00400000)) { -- if (!(*trace_name_printed)) { -- // RC_TRACE_MESG macro has an embedded ResourceMark -- RC_TRACE_MESG(("adjust: name=%s", -- old_method->method_holder()->external_name())); -- *trace_name_printed = true; -- } -- // RC_TRACE macro has an embedded ResourceMark -- RC_TRACE(0x00400000, ("MemberName method update: %s(%s)", -- new_method->name()->as_C_string(), -- new_method->signature()->as_C_string())); -+ // search the MemberNameTable for uses of either obsolete or EMCP methods -+ for (int idx = 0; idx < length(); idx++) { -+ oop mem_name = JNIHandles::resolve(this->at(idx)); -+ if (mem_name != NULL) { -+ java_lang_invoke_MemberName::adjust_vmtarget(mem_name, old_method, new_method, -+ trace_name_printed); - } - } - } ---- jdk8/hotspot/src/share/vm/prims/methodHandles.hpp 2015-01-27 08:42:54.008817389 +0100 -+++ jdk8/hotspot/src/share/vm/prims/methodHandles.hpp 2015-01-27 08:43:45.278624292 +0100 -@@ -239,18 +239,14 @@ - public: - MemberNameTable(int methods_cnt); - ~MemberNameTable(); -- void add_member_name(int index, jweak mem_name_ref); -- oop get_member_name(int index); -+ void add_member_name(jweak mem_name_ref); - - #if INCLUDE_JVMTI -- public: - // RedefineClasses() API support: - // If a MemberName refers to old_method then update it - // to refer to new_method. - void adjust_method_entries(Method** old_methods, Method** new_methods, - int methods_length, bool *trace_name_printed); -- private: -- oop find_member_name_by_method(Method* old_method); - #endif // INCLUDE_JVMTI - }; - ---- jdk8/hotspot/src/share/vm/prims/whitebox.cpp 2015-01-27 08:42:54.009817366 +0100 -+++ jdk8/hotspot/src/share/vm/prims/whitebox.cpp 2015-01-27 08:43:45.278624292 +0100 -@@ -56,6 +56,7 @@ - #endif // INCLUDE_NMT - - #include "compiler/compileBroker.hpp" -+#include "jvmtifiles/jvmtiEnv.hpp" - #include "runtime/compilationPolicy.hpp" - - PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC -@@ -104,6 +105,51 @@ - 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(void, WB_AddToBootstrapClassLoaderSearch(JNIEnv* env, jobject o, jstring segment)) { -+#if INCLUDE_JVMTI -+ ResourceMark rm; -+ const char* seg = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(segment)); -+ JvmtiEnv* jvmti_env = JvmtiEnv::create_a_jvmti(JVMTI_VERSION); -+ jvmtiError err = jvmti_env->AddToBootstrapClassLoaderSearch(seg); -+ assert(err == JVMTI_ERROR_NONE, "must not fail"); -+#endif -+} -+WB_END -+ -+WB_ENTRY(void, WB_AddToSystemClassLoaderSearch(JNIEnv* env, jobject o, jstring segment)) { -+#if INCLUDE_JVMTI -+ ResourceMark rm; -+ const char* seg = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(segment)); -+ JvmtiEnv* jvmti_env = JvmtiEnv::create_a_jvmti(JVMTI_VERSION); -+ jvmtiError err = jvmti_env->AddToSystemClassLoaderSearch(seg); -+ assert(err == JVMTI_ERROR_NONE, "must not fail"); -+#endif -+} -+WB_END -+ -+ - WB_ENTRY(jlong, WB_GetCompressedOopsMaxHeapSize(JNIEnv* env, jobject o)) { - return (jlong)Arguments::max_heap_for_compressed_oops(); - } -@@ -287,7 +333,7 @@ - WB_ENTRY(jlong, WB_NMTMallocWithPseudoStack(JNIEnv* env, jobject o, jlong size, jint pseudo_stack)) - address pc = (address)(size_t)pseudo_stack; - NativeCallStack stack(&pc, 1); -- return (jlong)os::malloc(size, mtTest, stack); -+ return (jlong)(uintptr_t)os::malloc(size, mtTest, stack); - WB_END - - // Free the memory allocated by NMTAllocTest -@@ -322,15 +368,6 @@ - return MemTracker::tracking_level() == NMT_detail; - WB_END - --WB_ENTRY(void, WB_NMTOverflowHashBucket(JNIEnv* env, jobject o, jlong num)) -- address pc = (address)1; -- for (jlong index = 0; index < num; index ++) { -- NativeCallStack stack(&pc, 1); -- os::malloc(0, mtTest, stack); -- pc += MallocSiteTable::hash_buckets(); -- } --WB_END -- - WB_ENTRY(jboolean, WB_NMTChangeTrackingLevel(JNIEnv* env)) - // Test that we can downgrade NMT levels but not upgrade them. - if (MemTracker::tracking_level() == NMT_off) { -@@ -361,6 +398,12 @@ - return MemTracker::tracking_level() == NMT_minimal; - } - WB_END -+ -+WB_ENTRY(jint, WB_NMTGetHashSize(JNIEnv* env, jobject o)) -+ int hash_size = MallocSiteTable::hash_buckets(); -+ assert(hash_size > 0, "NMT hash_size should be > 0"); -+ return (jint)hash_size; -+WB_END - #endif // INCLUDE_NMT - - static jmethodID reflected_method_to_jmid(JavaThread* thread, JNIEnv* env, jobject method) { -@@ -382,19 +425,10 @@ - CHECK_JNI_EXCEPTION_(env, result); - MutexLockerEx mu(Compile_lock); - methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid)); -- nmethod* code; - if (is_osr) { -- int bci = InvocationEntryBci; -- while ((code = mh->lookup_osr_nmethod_for(bci, CompLevel_none, false)) != NULL) { -- code->mark_for_deoptimization(); -- ++result; -- bci = code->osr_entry_bci() + 1; -- } -- } else { -- code = mh->code(); -- } -- if (code != NULL) { -- code->mark_for_deoptimization(); -+ result += mh->mark_osr_nmethods(); -+ } else if (mh->code() != NULL) { -+ mh->code()->mark_for_deoptimization(); - ++result; - } - result += CodeCache::mark_for_deoptimization(mh()); -@@ -939,10 +973,19 @@ - {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 - }, -+ {CC"addToBootstrapClassLoaderSearch", CC"(Ljava/lang/String;)V", -+ (void*)&WB_AddToBootstrapClassLoaderSearch}, -+ {CC"addToSystemClassLoaderSearch", CC"(Ljava/lang/String;)V", -+ (void*)&WB_AddToSystemClassLoaderSearch}, - {CC"getCompressedOopsMaxHeapSize", CC"()J", - (void*)&WB_GetCompressedOopsMaxHeapSize}, - {CC"printHeapSizes", CC"()V", (void*)&WB_PrintHeapSizes }, -@@ -963,9 +1006,9 @@ - {CC"NMTCommitMemory", CC"(JJ)V", (void*)&WB_NMTCommitMemory }, - {CC"NMTUncommitMemory", CC"(JJ)V", (void*)&WB_NMTUncommitMemory }, - {CC"NMTReleaseMemory", CC"(JJ)V", (void*)&WB_NMTReleaseMemory }, -- {CC"NMTOverflowHashBucket", CC"(J)V", (void*)&WB_NMTOverflowHashBucket}, - {CC"NMTIsDetailSupported",CC"()Z", (void*)&WB_NMTIsDetailSupported}, - {CC"NMTChangeTrackingLevel", CC"()Z", (void*)&WB_NMTChangeTrackingLevel}, -+ {CC"NMTGetHashSize", CC"()I", (void*)&WB_NMTGetHashSize }, - #endif // INCLUDE_NMT - {CC"deoptimizeAll", CC"()V", (void*)&WB_DeoptimizeAll }, - {CC"deoptimizeMethod", CC"(Ljava/lang/reflect/Executable;Z)I", ---- jdk8/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp 2015-01-27 08:42:54.009817366 +0100 -+++ jdk8/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp 2015-01-27 08:43:45.279624269 +0100 -@@ -316,8 +316,8 @@ - * c. 0 -> (3->2) -> 4. - * In this case we enqueue a method for compilation at level 3, but the C1 queue is long enough - * to enable the profiling to fully occur at level 0. In this case we change the compilation level -- * of the method to 2, because it'll allow it to run much faster without full profiling while c2 -- * is compiling. -+ * of the method to 2 while the request is still in-queue, because it'll allow it to run much faster -+ * without full profiling while c2 is compiling. - * - * d. 0 -> 3 -> 1 or 0 -> 2 -> 1. - * After a method was once compiled with C1 it can be identified as trivial and be compiled to -@@ -451,7 +451,7 @@ - if (should_create_mdo(mh(), level)) { - create_mdo(mh, thread); - } -- if (is_compilation_enabled() && !CompileBroker::compilation_is_in_queue(mh, InvocationEntryBci)) { -+ if (is_compilation_enabled() && !CompileBroker::compilation_is_in_queue(mh)) { - CompLevel next_level = call_event(mh(), level); - if (next_level != level) { - compile(mh, InvocationEntryBci, next_level, thread); -@@ -475,7 +475,7 @@ - CompLevel next_osr_level = loop_event(imh(), level); - CompLevel max_osr_level = (CompLevel)imh->highest_osr_comp_level(); - // At the very least compile the OSR version -- if (!CompileBroker::compilation_is_in_queue(imh, bci) && next_osr_level != level) { -+ if (!CompileBroker::compilation_is_in_queue(imh) && (next_osr_level != level)) { - compile(imh, bci, next_osr_level, thread); - } - -@@ -509,7 +509,7 @@ - nm->make_not_entrant(); - } - } -- if (!CompileBroker::compilation_is_in_queue(mh, InvocationEntryBci)) { -+ if (!CompileBroker::compilation_is_in_queue(mh)) { - // Fix up next_level if necessary to avoid deopts - if (next_level == CompLevel_limited_profile && max_osr_level == CompLevel_full_profile) { - next_level = CompLevel_full_profile; -@@ -521,7 +521,7 @@ - } else { - cur_level = comp_level(imh()); - next_level = call_event(imh(), cur_level); -- if (!CompileBroker::compilation_is_in_queue(imh, bci) && next_level != cur_level) { -+ if (!CompileBroker::compilation_is_in_queue(imh) && (next_level != cur_level)) { - compile(imh, InvocationEntryBci, next_level, thread); - } - } ---- jdk8/hotspot/src/share/vm/runtime/arguments.cpp 2015-01-27 08:42:54.009817366 +0100 -+++ jdk8/hotspot/src/share/vm/runtime/arguments.cpp 2015-01-27 08:43:45.280624246 +0100 -@@ -66,7 +66,7 @@ - #endif // INCLUDE_ALL_GCS - - // Note: This is a special bug reporting site for the JVM --#define DEFAULT_VENDOR_URL_BUG "http://bugreport.sun.com/bugreport/crash.jsp" -+#define DEFAULT_VENDOR_URL_BUG "http://bugreport.java.com/bugreport/crash.jsp" - #define DEFAULT_JAVA_LAUNCHER "generic" - - // Disable options not supported in this release, with a warning if they -@@ -300,6 +300,7 @@ - { "UseStringCache", JDK_Version::jdk(8), JDK_Version::jdk(9) }, - { "UseOldInlining", JDK_Version::jdk(9), JDK_Version::jdk(10) }, - { "AutoShutdownNMT", JDK_Version::jdk(9), JDK_Version::jdk(10) }, -+ { "CompilationRepeat", JDK_Version::jdk(8), JDK_Version::jdk(9) }, - #ifdef PRODUCT - { "DesiredMethodLimit", - JDK_Version::jdk_update(7, 2), JDK_Version::jdk(8) }, -@@ -1146,6 +1147,32 @@ - } - } - -+/** -+ * Returns the minimum number of compiler threads needed to run the JVM. The following -+ * configurations are possible. -+ * -+ * 1) The JVM is build using an interpreter only. As a result, the minimum number of -+ * compiler threads is 0. -+ * 2) The JVM is build using the compiler(s) and tiered compilation is disabled. As -+ * a result, either C1 or C2 is used, so the minimum number of compiler threads is 1. -+ * 3) The JVM is build using the compiler(s) and tiered compilation is enabled. However, -+ * the option "TieredStopAtLevel < CompLevel_full_optimization". As a result, only -+ * C1 can be used, so the minimum number of compiler threads is 1. -+ * 4) The JVM is build using the compilers and tiered compilation is enabled. The option -+ * 'TieredStopAtLevel = CompLevel_full_optimization' (the default value). As a result, -+ * the minimum number of compiler threads is 2. -+ */ -+int Arguments::get_min_number_of_compiler_threads() { -+#if !defined(COMPILER1) && !defined(COMPILER2) && !defined(SHARK) -+ return 0; // case 1 -+#else -+ if (!TieredCompilation || (TieredStopAtLevel < CompLevel_full_optimization)) { -+ return 1; // case 2 or case 3 -+ } -+ return 2; // case 4 (tiered) -+#endif -+} -+ - #if INCLUDE_ALL_GCS - static void disable_adaptive_size_policy(const char* collector_name) { - if (UseAdaptiveSizePolicy) { -@@ -2207,7 +2234,7 @@ - FLAG_SET_DEFAULT(UseGCOverheadLimit, false); - } - -- status = status && ArgumentsExt::check_gc_consistency_user(); -+ status = status && check_gc_consistency_user(); - status = status && check_stack_pages(); - - if (CMSIncrementalMode) { -@@ -2462,6 +2489,12 @@ - status &= verify_interval(SafepointPollOffset, 0, os::vm_page_size() - BytesPerWord, "SafepointPollOffset"); - #endif - -+ int min_number_of_compiler_threads = get_min_number_of_compiler_threads(); -+ // The default CICompilerCount's value is CI_COMPILER_COUNT. -+ assert(min_number_of_compiler_threads <= CI_COMPILER_COUNT, "minimum should be less or equal default number"); -+ // Check the minimum number of compiler threads -+ status &=verify_min_value(CICompilerCount, min_number_of_compiler_threads, "CICompilerCount"); -+ - return status; - } - -@@ -2930,6 +2963,23 @@ - #endif - // -D - } else if (match_option(option, "-D", &tail)) { -+ if (CheckEndorsedAndExtDirs) { -+ if (match_option(option, "-Djava.endorsed.dirs=", &tail)) { -+ // abort if -Djava.endorsed.dirs is set -+ jio_fprintf(defaultStream::output_stream(), -+ "-Djava.endorsed.dirs will not be supported in a future release.\n" -+ "Refer to JEP 220 for details (http://openjdk.java.net/jeps/220).\n"); -+ return JNI_EINVAL; -+ } -+ if (match_option(option, "-Djava.ext.dirs=", &tail)) { -+ // abort if -Djava.ext.dirs is set -+ jio_fprintf(defaultStream::output_stream(), -+ "-Djava.ext.dirs will not be supported in a future release.\n" -+ "Refer to JEP 220 for details (http://openjdk.java.net/jeps/220).\n"); -+ return JNI_EINVAL; -+ } -+ } -+ - if (!add_property(tail)) { - return JNI_ENOMEM; - } -@@ -3363,6 +3413,146 @@ - } - } - -+static bool has_jar_files(const char* directory) { -+ DIR* dir = os::opendir(directory); -+ if (dir == NULL) return false; -+ -+ struct dirent *entry; -+ char *dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(directory), mtInternal); -+ bool hasJarFile = false; -+ while (!hasJarFile && (entry = os::readdir(dir, (dirent *) dbuf)) != NULL) { -+ const char* name = entry->d_name; -+ const char* ext = name + strlen(name) - 4; -+ hasJarFile = ext > name && (os::file_name_strcmp(ext, ".jar") == 0); -+ } -+ FREE_C_HEAP_ARRAY(char, dbuf, mtInternal); -+ os::closedir(dir); -+ return hasJarFile ; -+} -+ -+// returns the number of directories in the given path containing JAR files -+// If the skip argument is not NULL, it will skip that directory -+static int check_non_empty_dirs(const char* path, const char* type, const char* skip) { -+ const char separator = *os::path_separator(); -+ const char* const end = path + strlen(path); -+ int nonEmptyDirs = 0; -+ while (path < end) { -+ const char* tmp_end = strchr(path, separator); -+ if (tmp_end == NULL) { -+ if ((skip == NULL || strcmp(path, skip) != 0) && has_jar_files(path)) { -+ nonEmptyDirs++; -+ jio_fprintf(defaultStream::output_stream(), -+ "Non-empty %s directory: %s\n", type, path); -+ } -+ path = end; -+ } else { -+ char* dirpath = NEW_C_HEAP_ARRAY(char, tmp_end - path + 1, mtInternal); -+ memcpy(dirpath, path, tmp_end - path); -+ dirpath[tmp_end - path] = '\0'; -+ if ((skip == NULL || strcmp(dirpath, skip) != 0) && has_jar_files(dirpath)) { -+ nonEmptyDirs++; -+ jio_fprintf(defaultStream::output_stream(), -+ "Non-empty %s directory: %s\n", type, dirpath); -+ } -+ FREE_C_HEAP_ARRAY(char, dirpath, mtInternal); -+ path = tmp_end + 1; -+ } -+ } -+ return nonEmptyDirs; -+} -+ -+// Returns true if endorsed standards override mechanism and extension mechanism -+// are not used. -+static bool check_endorsed_and_ext_dirs() { -+ if (!CheckEndorsedAndExtDirs) -+ return true; -+ -+ char endorsedDir[JVM_MAXPATHLEN]; -+ char extDir[JVM_MAXPATHLEN]; -+ const char* fileSep = os::file_separator(); -+ jio_snprintf(endorsedDir, sizeof(endorsedDir), "%s%slib%sendorsed", -+ Arguments::get_java_home(), fileSep, fileSep); -+ jio_snprintf(extDir, sizeof(extDir), "%s%slib%sext", -+ Arguments::get_java_home(), fileSep, fileSep); -+ -+ // check endorsed directory -+ int nonEmptyDirs = check_non_empty_dirs(Arguments::get_endorsed_dir(), "endorsed", NULL); -+ -+ // check the extension directories but skip the default lib/ext directory -+ nonEmptyDirs += check_non_empty_dirs(Arguments::get_ext_dirs(), "extension", extDir); -+ -+ // List of JAR files installed in the default lib/ext directory. -+ // -XX:+CheckEndorsedAndExtDirs checks if any non-JDK file installed -+ static const char* jdk_ext_jars[] = { -+ "access-bridge-32.jar", -+ "access-bridge-64.jar", -+ "access-bridge.jar", -+ "cldrdata.jar", -+ "dnsns.jar", -+ "jaccess.jar", -+ "jfxrt.jar", -+ "localedata.jar", -+ "nashorn.jar", -+ "sunec.jar", -+ "sunjce_provider.jar", -+ "sunmscapi.jar", -+ "sunpkcs11.jar", -+ "ucrypto.jar", -+ "zipfs.jar", -+ NULL -+ }; -+ -+ // check if the default lib/ext directory has any non-JDK jar files; if so, error -+ DIR* dir = os::opendir(extDir); -+ if (dir != NULL) { -+ int num_ext_jars = 0; -+ struct dirent *entry; -+ char *dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(extDir), mtInternal); -+ while ((entry = os::readdir(dir, (dirent *) dbuf)) != NULL) { -+ const char* name = entry->d_name; -+ const char* ext = name + strlen(name) - 4; -+ if (ext > name && (os::file_name_strcmp(ext, ".jar") == 0)) { -+ bool is_jdk_jar = false; -+ const char* jarfile = NULL; -+ for (int i=0; (jarfile = jdk_ext_jars[i]) != NULL; i++) { -+ if (os::file_name_strcmp(name, jarfile) == 0) { -+ is_jdk_jar = true; -+ break; -+ } -+ } -+ if (!is_jdk_jar) { -+ jio_fprintf(defaultStream::output_stream(), -+ "%s installed in /lib/ext\n", name); -+ num_ext_jars++; -+ } -+ } -+ } -+ FREE_C_HEAP_ARRAY(char, dbuf, mtInternal); -+ os::closedir(dir); -+ if (num_ext_jars > 0) { -+ nonEmptyDirs += 1; -+ } -+ } -+ -+ // check if the default lib/endorsed directory exists; if so, error -+ dir = os::opendir(endorsedDir); -+ if (dir != NULL) { -+ jio_fprintf(defaultStream::output_stream(), "/lib/endorsed exists\n"); -+ os::closedir(dir); -+ nonEmptyDirs += 1; -+ } -+ -+ if (nonEmptyDirs > 0) { -+ jio_fprintf(defaultStream::output_stream(), -+ "Endorsed standards override mechanism and extension mechanism " -+ "will not be supported in a future release.\n" -+ "Refer to JEP 220 for details (http://openjdk.java.net/jeps/220).\n"); -+ return false; -+ } -+ -+ return true; -+} -+ - jint Arguments::finalize_vm_init_args(SysClassPath* scp_p, bool scp_assembly_required) { - // This must be done after all -D arguments have been processed. - scp_p->expand_endorsed(); -@@ -3372,6 +3562,10 @@ - Arguments::set_sysclasspath(scp_p->combined_path()); - } - -+ if (!check_endorsed_and_ext_dirs()) { -+ return JNI_ERR; -+ } -+ - // This must be done after all arguments have been processed. - // java_compiler() true means set to "NONE" or empty. - if (java_compiler() && !xdebug_mode()) { -@@ -3432,7 +3626,7 @@ - } - } - -- if (!ArgumentsExt::check_vm_args_consistency()) { -+ if (!check_vm_args_consistency()) { - return JNI_ERR; - } - -@@ -3618,6 +3812,8 @@ - bool settings_file_specified = false; - bool needs_hotspotrc_warning = false; - -+ ArgumentsExt::process_options(args); -+ - const char* flags_file; - int index; - for (index = 0; index < args->nOptions; index++) { -@@ -3833,7 +4029,7 @@ - // Set heap size based on available physical memory - set_heap_size(); - -- set_gc_specific_flags(); -+ ArgumentsExt::set_gc_specific_flags(); - - // Initialize Metaspace flags and alignments. - Metaspace::ergo_initialize(); ---- jdk8/hotspot/src/share/vm/runtime/arguments_ext.hpp 2015-01-27 08:42:54.009817366 +0100 -+++ jdk8/hotspot/src/share/vm/runtime/arguments_ext.hpp 2015-01-27 08:43:45.280624246 +0100 -@@ -31,25 +31,21 @@ - class ArgumentsExt: AllStatic { - public: - static inline void select_gc_ergonomically(); -- static inline bool check_gc_consistency_user(); -+ static inline void set_gc_specific_flags(); - static inline bool check_gc_consistency_ergo(); -- static inline bool check_vm_args_consistency(); -+ static void process_options(const JavaVMInitArgs* args) {} - }; - - void ArgumentsExt::select_gc_ergonomically() { - Arguments::select_gc_ergonomically(); - } - --bool ArgumentsExt::check_gc_consistency_user() { -- return Arguments::check_gc_consistency_user(); -+void ArgumentsExt::set_gc_specific_flags() { -+ Arguments::set_gc_specific_flags(); - } - - bool ArgumentsExt::check_gc_consistency_ergo() { - return Arguments::check_gc_consistency_ergo(); - } - --bool ArgumentsExt::check_vm_args_consistency() { -- return Arguments::check_vm_args_consistency(); --} -- - #endif // SHARE_VM_RUNTIME_ARGUMENTS_EXT_HPP ---- jdk8/hotspot/src/share/vm/runtime/arguments.hpp 2015-01-27 08:42:54.009817366 +0100 -+++ jdk8/hotspot/src/share/vm/runtime/arguments.hpp 2015-01-27 08:43:45.280624246 +0100 -@@ -327,6 +327,7 @@ - - // Tiered - static void set_tiered_flags(); -+ static int get_min_number_of_compiler_threads(); - // CMS/ParNew garbage collectors - static void set_parnew_gc_flags(); - static void set_cms_and_parnew_gc_flags(); -@@ -341,7 +342,6 @@ - static void select_gc(); - static void set_ergonomics_flags(); - static void set_shared_spaces_flags(); -- static void set_gc_specific_flags(); - // limits the given memory size by the maximum amount of memory this process is - // currently allowed to allocate or reserve. - static julong limit_by_allocatable_memory(julong size); -@@ -453,6 +453,7 @@ - // Adjusts the arguments after the OS have adjusted the arguments - static jint adjust_after_os(); - -+ static void set_gc_specific_flags(); - static inline bool gc_selected(); // whether a gc has been selected - static void select_gc_ergonomically(); - ---- jdk8/hotspot/src/share/vm/runtime/deoptimization.cpp 2015-01-27 08:42:54.009817366 +0100 -+++ jdk8/hotspot/src/share/vm/runtime/deoptimization.cpp 2015-01-27 08:43:45.281624222 +0100 -@@ -219,6 +219,8 @@ - assert(vf->is_compiled_frame(), "Wrong frame type"); - chunk->push(compiledVFrame::cast(vf)); - -+ bool realloc_failures = false; -+ - #ifdef COMPILER2 - // Reallocate the non-escaping objects and restore their fields. Then - // relock objects if synchronization on them was eliminated. -@@ -249,19 +251,16 @@ - tty->print_cr("SAVED OOP RESULT " INTPTR_FORMAT " in thread " INTPTR_FORMAT, (void *)result, thread); - } - } -- bool reallocated = false; - if (objects != NULL) { - JRT_BLOCK -- reallocated = realloc_objects(thread, &deoptee, objects, THREAD); -+ realloc_failures = realloc_objects(thread, &deoptee, objects, THREAD); - JRT_END -- } -- if (reallocated) { -- reassign_fields(&deoptee, &map, objects); -+ reassign_fields(&deoptee, &map, objects, realloc_failures); - #ifndef PRODUCT - if (TraceDeoptimization) { - ttyLocker ttyl; - tty->print_cr("REALLOC OBJECTS in thread " INTPTR_FORMAT, thread); -- print_objects(objects); -+ print_objects(objects, realloc_failures); - } - #endif - } -@@ -279,7 +278,7 @@ - assert (cvf->scope() != NULL,"expect only compiled java frames"); - GrowableArray* monitors = cvf->monitors(); - if (monitors->is_nonempty()) { -- relock_objects(monitors, thread); -+ relock_objects(monitors, thread, realloc_failures); - #ifndef PRODUCT - if (TraceDeoptimization) { - ttyLocker ttyl; -@@ -290,10 +289,15 @@ - first = false; - tty->print_cr("RELOCK OBJECTS in thread " INTPTR_FORMAT, thread); - } -+ if (mi->owner_is_scalar_replaced()) { -+ Klass* k = java_lang_Class::as_Klass(mi->owner_klass()); -+ tty->print_cr(" failed reallocation for klass %s", k->external_name()); -+ } else { - tty->print_cr(" object <" INTPTR_FORMAT "> locked", (void *)mi->owner()); - } - } - } -+ } - #endif - } - } -@@ -305,9 +309,14 @@ - // out the java state residing in the vframeArray will be missed. - No_Safepoint_Verifier no_safepoint; - -- vframeArray* array = create_vframeArray(thread, deoptee, &map, chunk); -+ vframeArray* array = create_vframeArray(thread, deoptee, &map, chunk, realloc_failures); -+#ifdef COMPILER2 -+ if (realloc_failures) { -+ pop_frames_failed_reallocs(thread, array); -+ } -+#endif - -- assert(thread->vframe_array_head() == NULL, "Pending deopt!");; -+ assert(thread->vframe_array_head() == NULL, "Pending deopt!"); - thread->set_vframe_array_head(array); - - // Now that the vframeArray has been created if we have any deferred local writes -@@ -759,6 +768,8 @@ - int exception_line = thread->exception_line(); - thread->clear_pending_exception(); - -+ bool failures = false; -+ - for (int i = 0; i < objects->length(); i++) { - assert(objects->at(i)->is_object(), "invalid debug information"); - ObjectValue* sv = (ObjectValue*) objects->at(i); -@@ -768,27 +779,34 @@ - - if (k->oop_is_instance()) { - InstanceKlass* ik = InstanceKlass::cast(k()); -- obj = ik->allocate_instance(CHECK_(false)); -+ obj = ik->allocate_instance(THREAD); - } else if (k->oop_is_typeArray()) { - TypeArrayKlass* ak = TypeArrayKlass::cast(k()); - assert(sv->field_size() % type2size[ak->element_type()] == 0, "non-integral array length"); - int len = sv->field_size() / type2size[ak->element_type()]; -- obj = ak->allocate(len, CHECK_(false)); -+ obj = ak->allocate(len, THREAD); - } else if (k->oop_is_objArray()) { - ObjArrayKlass* ak = ObjArrayKlass::cast(k()); -- obj = ak->allocate(sv->field_size(), CHECK_(false)); -+ obj = ak->allocate(sv->field_size(), THREAD); -+ } -+ -+ if (obj == NULL) { -+ failures = true; - } - -- assert(obj != NULL, "allocation failed"); - assert(sv->value().is_null(), "redundant reallocation"); -+ assert(obj != NULL || HAS_PENDING_EXCEPTION, "allocation should succeed or we should get an exception"); -+ CLEAR_PENDING_EXCEPTION; - sv->set_value(obj); - } - -- if (pending_exception.not_null()) { -+ if (failures) { -+ THROW_OOP_(Universe::out_of_memory_error_realloc_objects(), failures); -+ } else if (pending_exception.not_null()) { - thread->set_pending_exception(pending_exception(), exception_file, exception_line); - } - -- return true; -+ return failures; - } - - // This assumes that the fields are stored in ObjectValue in the same order -@@ -926,12 +944,15 @@ - - - // restore fields of all eliminated objects and arrays --void Deoptimization::reassign_fields(frame* fr, RegisterMap* reg_map, GrowableArray* objects) { -+void Deoptimization::reassign_fields(frame* fr, RegisterMap* reg_map, GrowableArray* objects, bool realloc_failures) { - for (int i = 0; i < objects->length(); i++) { - ObjectValue* sv = (ObjectValue*) objects->at(i); - KlassHandle k(java_lang_Class::as_Klass(sv->klass()->as_ConstantOopReadValue()->value()())); - Handle obj = sv->value(); -- assert(obj.not_null(), "reallocation was missed"); -+ assert(obj.not_null() || realloc_failures, "reallocation was missed"); -+ if (obj.is_null()) { -+ continue; -+ } - - if (k->oop_is_instance()) { - InstanceKlass* ik = InstanceKlass::cast(k()); -@@ -948,11 +969,12 @@ - - - // relock objects for which synchronization was eliminated --void Deoptimization::relock_objects(GrowableArray* monitors, JavaThread* thread) { -+void Deoptimization::relock_objects(GrowableArray* monitors, JavaThread* thread, bool realloc_failures) { - for (int i = 0; i < monitors->length(); i++) { - MonitorInfo* mon_info = monitors->at(i); - if (mon_info->eliminated()) { -- assert(mon_info->owner() != NULL, "reallocation was missed"); -+ assert(!mon_info->owner_is_scalar_replaced() || realloc_failures, "reallocation was missed"); -+ if (!mon_info->owner_is_scalar_replaced()) { - Handle obj = Handle(mon_info->owner()); - markOop mark = obj->mark(); - if (UseBiasedLocking && mark->has_bias_pattern()) { -@@ -967,15 +989,16 @@ - } - BasicLock* lock = mon_info->lock(); - ObjectSynchronizer::slow_enter(obj, lock, thread); -- } - assert(mon_info->owner()->is_locked(), "object must be locked now"); - } - } -+ } -+} - - - #ifndef PRODUCT - // print information about reallocated objects --void Deoptimization::print_objects(GrowableArray* objects) { -+void Deoptimization::print_objects(GrowableArray* objects, bool realloc_failures) { - fieldDescriptor fd; - - for (int i = 0; i < objects->length(); i++) { -@@ -985,10 +1008,15 @@ - - tty->print(" object <" INTPTR_FORMAT "> of type ", (void *)sv->value()()); - k->print_value(); -+ assert(obj.not_null() || realloc_failures, "reallocation was missed"); -+ if (obj.is_null()) { -+ tty->print(" allocation failed"); -+ } else { - tty->print(" allocated (%d bytes)", obj->size() * HeapWordSize); -+ } - tty->cr(); - -- if (Verbose) { -+ if (Verbose && !obj.is_null()) { - k->oop_print_on(obj(), tty); - } - } -@@ -996,7 +1024,7 @@ - #endif - #endif // COMPILER2 - --vframeArray* Deoptimization::create_vframeArray(JavaThread* thread, frame fr, RegisterMap *reg_map, GrowableArray* chunk) { -+vframeArray* Deoptimization::create_vframeArray(JavaThread* thread, frame fr, RegisterMap *reg_map, GrowableArray* chunk, bool realloc_failures) { - Events::log(thread, "DEOPT PACKING pc=" INTPTR_FORMAT " sp=" INTPTR_FORMAT, fr.pc(), fr.sp()); - - #ifndef PRODUCT -@@ -1039,7 +1067,7 @@ - // Since the Java thread being deoptimized will eventually adjust it's own stack, - // the vframeArray containing the unpacking information is allocated in the C heap. - // For Compiler1, the caller of the deoptimized frame is saved for use by unpack_frames(). -- vframeArray* array = vframeArray::allocate(thread, frame_size, chunk, reg_map, sender, caller, fr); -+ vframeArray* array = vframeArray::allocate(thread, frame_size, chunk, reg_map, sender, caller, fr, realloc_failures); - - // Compare the vframeArray to the collected vframes - assert(array->structural_compare(thread, chunk), "just checking"); -@@ -1054,6 +1082,33 @@ - return array; - } - -+#ifdef COMPILER2 -+void Deoptimization::pop_frames_failed_reallocs(JavaThread* thread, vframeArray* array) { -+ // Reallocation of some scalar replaced objects failed. Record -+ // that we need to pop all the interpreter frames for the -+ // deoptimized compiled frame. -+ assert(thread->frames_to_pop_failed_realloc() == 0, "missed frames to pop?"); -+ thread->set_frames_to_pop_failed_realloc(array->frames()); -+ // Unlock all monitors here otherwise the interpreter will see a -+ // mix of locked and unlocked monitors (because of failed -+ // reallocations of synchronized objects) and be confused. -+ for (int i = 0; i < array->frames(); i++) { -+ MonitorChunk* monitors = array->element(i)->monitors(); -+ if (monitors != NULL) { -+ for (int j = 0; j < monitors->number_of_monitors(); j++) { -+ BasicObjectLock* src = monitors->at(j); -+ if (src->obj() != NULL) { -+ ObjectSynchronizer::fast_exit(src->obj(), src->lock(), thread); -+ } -+ } -+ array->element(i)->free_monitors(thread); -+#ifdef ASSERT -+ array->element(i)->set_removed_monitors(); -+#endif -+ } -+ } -+} -+#endif - - static void collect_monitors(compiledVFrame* cvf, GrowableArray* objects_to_revoke) { - GrowableArray* monitors = cvf->monitors(); ---- jdk8/hotspot/src/share/vm/runtime/deoptimization.hpp 2015-01-27 08:42:54.009817366 +0100 -+++ jdk8/hotspot/src/share/vm/runtime/deoptimization.hpp 2015-01-27 08:43:45.281624222 +0100 -@@ -120,13 +120,14 @@ - static bool realloc_objects(JavaThread* thread, frame* fr, GrowableArray* objects, TRAPS); - static void reassign_type_array_elements(frame* fr, RegisterMap* reg_map, ObjectValue* sv, typeArrayOop obj, BasicType type); - static void reassign_object_array_elements(frame* fr, RegisterMap* reg_map, ObjectValue* sv, objArrayOop obj); -- static void reassign_fields(frame* fr, RegisterMap* reg_map, GrowableArray* objects); -- static void relock_objects(GrowableArray* monitors, JavaThread* thread); -- NOT_PRODUCT(static void print_objects(GrowableArray* objects);) -+ static void reassign_fields(frame* fr, RegisterMap* reg_map, GrowableArray* objects, bool realloc_failures); -+ static void relock_objects(GrowableArray* monitors, JavaThread* thread, bool realloc_failures); -+ static void pop_frames_failed_reallocs(JavaThread* thread, vframeArray* array); -+ NOT_PRODUCT(static void print_objects(GrowableArray* objects, bool realloc_failures);) - #endif // COMPILER2 - - public: -- static vframeArray* create_vframeArray(JavaThread* thread, frame fr, RegisterMap *reg_map, GrowableArray* chunk); -+ static vframeArray* create_vframeArray(JavaThread* thread, frame fr, RegisterMap *reg_map, GrowableArray* chunk, bool realloc_failures); - - // Interface used for unpacking deoptimized frames - ---- jdk8/hotspot/src/share/vm/runtime/globals.cpp 2015-01-27 08:42:54.010817343 +0100 -+++ jdk8/hotspot/src/share/vm/runtime/globals.cpp 2015-01-27 08:43:45.281624222 +0100 -@@ -243,6 +243,11 @@ - return is_unlocked_ext(); - } - -+void Flag::unlock_diagnostic() { -+ assert(is_diagnostic(), "sanity"); -+ _flags = Flags(_flags & ~KIND_DIAGNOSTIC); -+} -+ - // Get custom message for this locked flag, or return NULL if - // none is available. - void Flag::get_locked_message(char* buf, int buflen) const { ---- jdk8/hotspot/src/share/vm/runtime/globals.hpp 2015-01-27 08:42:54.010817343 +0100 -+++ jdk8/hotspot/src/share/vm/runtime/globals.hpp 2015-01-27 08:44:59.066869294 +0100 -@@ -325,6 +325,8 @@ - bool is_writeable_ext() const; - bool is_external_ext() const; - -+ void unlock_diagnostic(); -+ - void get_locked_message(char*, int) const; - void get_locked_message_ext(char*, int) const; - -@@ -1220,6 +1222,9 @@ - product(bool, CheckJNICalls, false, \ - "Verify all arguments to JNI calls") \ - \ -+ product(bool, CheckEndorsedAndExtDirs, false, \ -+ "Verify the endorsed and extension directories are not used") \ -+ \ - product(bool, UseFastJNIAccessors, false, \ - "Use optimized versions of GetField") \ - \ ---- jdk8/hotspot/src/share/vm/runtime/interfaceSupport.cpp 2015-01-27 08:42:54.010817343 +0100 -+++ jdk8/hotspot/src/share/vm/runtime/interfaceSupport.cpp 2015-01-27 08:43:45.283624176 +0100 -@@ -85,7 +85,7 @@ - // Short-circuit any possible re-entrant gc-a-lot attempt - if (thread->skip_gcalot()) return; - -- if (is_init_completed()) { -+ if (Threads::is_vm_complete()) { - - if (++_fullgc_alot_invocation < FullGCALotStart) { - return; ---- jdk8/hotspot/src/share/vm/runtime/os.cpp 2015-01-27 08:42:54.011817320 +0100 -+++ jdk8/hotspot/src/share/vm/runtime/os.cpp 2015-01-27 08:43:45.283624176 +0100 -@@ -571,17 +571,6 @@ - NOT_PRODUCT(inc_stat_counter(&num_mallocs, 1)); - NOT_PRODUCT(inc_stat_counter(&alloc_bytes, size)); - --#if INCLUDE_NMT -- // NMT can not track malloc allocation size > MAX_MALLOC_SIZE, which is -- // (1GB - 1) on 32-bit system. It is not an issue on 64-bit system, where -- // MAX_MALLOC_SIZE = ((1 << 62) - 1). -- // VM code does not have such large malloc allocation. However, it can come -- // Unsafe call. -- if (MemTracker::tracking_level() >= NMT_summary && size > MAX_MALLOC_SIZE) { -- return NULL; -- } --#endif -- - #ifdef ASSERT - // checking for the WatcherThread and crash_protection first - // since os::malloc can be called when the libjvm.{dll,so} is -@@ -652,12 +641,6 @@ - } - - void* os::realloc(void *memblock, size_t size, MEMFLAGS memflags, const NativeCallStack& stack) { --#if INCLUDE_NMT -- // See comments in os::malloc() above -- if (MemTracker::tracking_level() >= NMT_summary && size > MAX_MALLOC_SIZE) { -- return NULL; -- } --#endif - - #ifndef ASSERT - NOT_PRODUCT(inc_stat_counter(&num_mallocs, 1)); ---- jdk8/hotspot/src/share/vm/runtime/sharedRuntime.cpp 2015-01-27 08:42:54.012817296 +0100 -+++ jdk8/hotspot/src/share/vm/runtime/sharedRuntime.cpp 2015-01-27 08:43:45.284624152 +0100 -@@ -490,6 +490,7 @@ - - address SharedRuntime::raw_exception_handler_for_return_address(JavaThread* thread, address return_address) { - assert(frame::verify_return_pc(return_address), err_msg("must be a return address: " INTPTR_FORMAT, return_address)); -+ assert(thread->frames_to_pop_failed_realloc() == 0 || Interpreter::contains(return_address), "missed frames to pop?"); - - // Reset method handle flag. - thread->set_is_method_handle_return(false); ---- jdk8/hotspot/src/share/vm/runtime/simpleThresholdPolicy.cpp 2015-01-27 08:42:54.012817296 +0100 -+++ jdk8/hotspot/src/share/vm/runtime/simpleThresholdPolicy.cpp 2015-01-27 08:43:45.284624152 +0100 -@@ -196,7 +196,6 @@ - // Don't trigger other compiles in testing mode - return NULL; - } -- nmethod *osr_nm = NULL; - - handle_counter_overflow(method()); - if (method() != inlinee()) { -@@ -210,14 +209,16 @@ - if (bci == InvocationEntryBci) { - method_invocation_event(method, inlinee, comp_level, nm, thread); - } else { -- method_back_branch_event(method, inlinee, bci, comp_level, nm, thread); - // method == inlinee if the event originated in the main method -- int highest_level = inlinee->highest_osr_comp_level(); -- if (highest_level > comp_level) { -- osr_nm = inlinee->lookup_osr_nmethod_for(bci, highest_level, false); -+ method_back_branch_event(method, inlinee, bci, comp_level, nm, thread); -+ // Check if event led to a higher level OSR compilation -+ nmethod* osr_nm = inlinee->lookup_osr_nmethod_for(bci, comp_level, false); -+ if (osr_nm != NULL && osr_nm->comp_level() > comp_level) { -+ // Perform OSR with new nmethod -+ return osr_nm; - } - } -- return osr_nm; -+ return NULL; - } - - // Check if the method can be compiled, change level if necessary -@@ -239,7 +240,7 @@ - if (bci != InvocationEntryBci && mh->is_not_osr_compilable(level)) { - return; - } -- if (!CompileBroker::compilation_is_in_queue(mh, bci)) { -+ if (!CompileBroker::compilation_is_in_queue(mh)) { - if (PrintTieredEvents) { - print_event(COMPILE, mh, mh, bci, level); - } -@@ -378,7 +379,7 @@ - // Handle the invocation event. - void SimpleThresholdPolicy::method_invocation_event(methodHandle mh, methodHandle imh, - CompLevel level, nmethod* nm, JavaThread* thread) { -- if (is_compilation_enabled() && !CompileBroker::compilation_is_in_queue(mh, InvocationEntryBci)) { -+ if (is_compilation_enabled() && !CompileBroker::compilation_is_in_queue(mh)) { - CompLevel next_level = call_event(mh(), level); - if (next_level != level) { - compile(mh, InvocationEntryBci, next_level, thread); -@@ -391,8 +392,8 @@ - void SimpleThresholdPolicy::method_back_branch_event(methodHandle mh, methodHandle imh, - int bci, CompLevel level, nmethod* nm, JavaThread* thread) { - // If the method is already compiling, quickly bail out. -- if (is_compilation_enabled() && !CompileBroker::compilation_is_in_queue(mh, bci)) { -- // Use loop event as an opportinity to also check there's been -+ if (is_compilation_enabled() && !CompileBroker::compilation_is_in_queue(mh)) { -+ // Use loop event as an opportunity to also check there's been - // enough calls. - CompLevel cur_level = comp_level(mh()); - CompLevel next_level = call_event(mh(), cur_level); ---- jdk8/hotspot/src/share/vm/runtime/simpleThresholdPolicy.inline.hpp 2015-01-27 08:42:54.012817296 +0100 -+++ jdk8/hotspot/src/share/vm/runtime/simpleThresholdPolicy.inline.hpp 2015-01-27 08:43:45.284624152 +0100 -@@ -54,13 +54,17 @@ - // Simple methods are as good being compiled with C1 as C2. - // Determine if a given method is such a case. - bool SimpleThresholdPolicy::is_trivial(Method* method) { -- if (method->is_accessor()) return true; -- if (method->code() != NULL) { -- MethodData* mdo = method->method_data(); -- if (mdo != NULL && mdo->num_loops() == 0 && -- (method->code_size() < 5 || (mdo->num_blocks() < 4) && (method->code_size() < 15))) { -- return !mdo->would_profile(); -+ if (method->is_accessor() || -+ method->is_constant_getter()) { -+ return true; -+ } -+ if (method->has_loops() || method->code_size() >= 15) { -+ return false; - } -+ MethodData* mdo = method->method_data(); -+ if (mdo != NULL && !mdo->would_profile() && -+ (method->code_size() < 5 || (mdo->num_blocks() < 4))) { -+ return true; - } - return false; - } ---- jdk8/hotspot/src/share/vm/runtime/thread.cpp 2015-01-27 08:42:54.013817273 +0100 -+++ jdk8/hotspot/src/share/vm/runtime/thread.cpp 2015-01-27 08:43:45.285624129 +0100 -@@ -234,6 +234,8 @@ - // This initial value ==> never claimed. - _oops_do_parity = 0; - -+ _metadata_on_stack_buffer = NULL; -+ - // the handle mark links itself to last_handle_mark - new HandleMark(this); - -@@ -1493,6 +1495,7 @@ - _popframe_condition = popframe_inactive; - _popframe_preserved_args = NULL; - _popframe_preserved_args_size = 0; -+ _frames_to_pop_failed_realloc = 0; - - pd_initialize(); - } ---- jdk8/hotspot/src/share/vm/runtime/thread.hpp 2015-01-27 08:42:54.013817273 +0100 -+++ jdk8/hotspot/src/share/vm/runtime/thread.hpp 2015-01-27 08:43:45.285624129 +0100 -@@ -42,11 +42,10 @@ - #include "runtime/threadLocalStorage.hpp" - #include "runtime/thread_ext.hpp" - #include "runtime/unhandledOops.hpp" --#include "utilities/macros.hpp" -- - #include "trace/traceBackend.hpp" - #include "trace/traceMacros.hpp" - #include "utilities/exceptions.hpp" -+#include "utilities/macros.hpp" - #include "utilities/top.hpp" - #if INCLUDE_ALL_GCS - #include "gc_implementation/g1/dirtyCardQueue.hpp" -@@ -83,6 +82,10 @@ - class ThreadClosure; - class IdealGraphPrinter; - -+class Metadata; -+template class ChunkedList; -+typedef ChunkedList MetadataOnStackBuffer; -+ - DEBUG_ONLY(class ResourceMark;) - - class WorkerThread; -@@ -256,6 +259,9 @@ - jlong _allocated_bytes; // Cumulative number of bytes allocated on - // the Java heap - -+ // Thread-local buffer used by MetadataOnStackMark. -+ MetadataOnStackBuffer* _metadata_on_stack_buffer; -+ - TRACE_DATA _trace_data; // Thread-local data for tracing - - ThreadExt _ext; -@@ -517,6 +523,9 @@ - // creation fails due to lack of memory, too many threads etc. - bool set_as_starting_thread(); - -+ void set_metadata_on_stack_buffer(MetadataOnStackBuffer* buffer) { _metadata_on_stack_buffer = buffer; } -+ MetadataOnStackBuffer* metadata_on_stack_buffer() const { return _metadata_on_stack_buffer; } -+ - protected: - // OS data associated with the thread - OSThread* _osthread; // Platform-specific thread information -@@ -924,6 +933,12 @@ - // This is set to popframe_pending to signal that top Java frame should be popped immediately - int _popframe_condition; - -+ // If reallocation of scalar replaced objects fails, we throw OOM -+ // and during exception propagation, pop the top -+ // _frames_to_pop_failed_realloc frames, the ones that reference -+ // failed reallocations. -+ int _frames_to_pop_failed_realloc; -+ - #ifndef PRODUCT - int _jmp_ring_index; - struct { -@@ -1576,6 +1591,10 @@ - void clr_pop_frame_in_process(void) { _popframe_condition &= ~popframe_processing_bit; } - #endif - -+ int frames_to_pop_failed_realloc() const { return _frames_to_pop_failed_realloc; } -+ void set_frames_to_pop_failed_realloc(int nb) { _frames_to_pop_failed_realloc = nb; } -+ void dec_frames_to_pop_failed_realloc() { _frames_to_pop_failed_realloc--; } -+ - private: - // Saved incoming arguments to popped frame. - // Used only when popped interpreted frame returns to deoptimized frame. ---- jdk8/hotspot/src/share/vm/runtime/vframeArray.cpp 2015-01-27 08:42:54.013817273 +0100 -+++ jdk8/hotspot/src/share/vm/runtime/vframeArray.cpp 2015-01-27 08:43:45.286624106 +0100 -@@ -56,7 +56,7 @@ - } - } - --void vframeArrayElement::fill_in(compiledVFrame* vf) { -+void vframeArrayElement::fill_in(compiledVFrame* vf, bool realloc_failures) { - - // Copy the information from the compiled vframe to the - // interpreter frame we will be creating to replace vf -@@ -64,6 +64,9 @@ - _method = vf->method(); - _bci = vf->raw_bci(); - _reexecute = vf->should_reexecute(); -+#ifdef ASSERT -+ _removed_monitors = false; -+#endif - - int index; - -@@ -81,13 +84,17 @@ - // Migrate the BasicLocks from the stack to the monitor chunk - for (index = 0; index < list->length(); index++) { - MonitorInfo* monitor = list->at(index); -- assert(!monitor->owner_is_scalar_replaced(), "object should be reallocated already"); -- assert(monitor->owner() == NULL || (!monitor->owner()->is_unlocked() && !monitor->owner()->has_bias_pattern()), "object must be null or locked, and unbiased"); -+ assert(!monitor->owner_is_scalar_replaced() || realloc_failures, "object should be reallocated already"); - BasicObjectLock* dest = _monitors->at(index); -+ if (monitor->owner_is_scalar_replaced()) { -+ dest->set_obj(NULL); -+ } else { -+ assert(monitor->owner() == NULL || (!monitor->owner()->is_unlocked() && !monitor->owner()->has_bias_pattern()), "object must be null or locked, and unbiased"); - dest->set_obj(monitor->owner()); - monitor->lock()->move_to(monitor->owner(), dest->lock()); - } - } -+ } - - // Convert the vframe locals and expressions to off stack - // values. Because we will not gc all oops can be converted to -@@ -110,7 +117,7 @@ - StackValue* value = locs->at(index); - switch(value->type()) { - case T_OBJECT: -- assert(!value->obj_is_scalar_replaced(), "object should be reallocated already"); -+ assert(!value->obj_is_scalar_replaced() || realloc_failures, "object should be reallocated already"); - // preserve object type - _locals->add( new StackValue(cast_from_oop((value->get_obj()())), T_OBJECT )); - break; -@@ -135,7 +142,7 @@ - StackValue* value = exprs->at(index); - switch(value->type()) { - case T_OBJECT: -- assert(!value->obj_is_scalar_replaced(), "object should be reallocated already"); -+ assert(!value->obj_is_scalar_replaced() || realloc_failures, "object should be reallocated already"); - // preserve object type - _expressions->add( new StackValue(cast_from_oop((value->get_obj()())), T_OBJECT )); - break; -@@ -286,7 +293,7 @@ - - _frame.patch_pc(thread, pc); - -- assert (!method()->is_synchronized() || locks > 0, "synchronized methods must have monitors"); -+ assert (!method()->is_synchronized() || locks > 0 || _removed_monitors, "synchronized methods must have monitors"); - - BasicObjectLock* top = iframe()->interpreter_frame_monitor_begin(); - for (int index = 0; index < locks; index++) { -@@ -438,7 +445,8 @@ - - - vframeArray* vframeArray::allocate(JavaThread* thread, int frame_size, GrowableArray* chunk, -- RegisterMap *reg_map, frame sender, frame caller, frame self) { -+ RegisterMap *reg_map, frame sender, frame caller, frame self, -+ bool realloc_failures) { - - // Allocate the vframeArray - vframeArray * result = (vframeArray*) AllocateHeap(sizeof(vframeArray) + // fixed part -@@ -450,19 +458,20 @@ - result->_caller = caller; - result->_original = self; - result->set_unroll_block(NULL); // initialize it -- result->fill_in(thread, frame_size, chunk, reg_map); -+ result->fill_in(thread, frame_size, chunk, reg_map, realloc_failures); - return result; - } - - void vframeArray::fill_in(JavaThread* thread, - int frame_size, - GrowableArray* chunk, -- const RegisterMap *reg_map) { -+ const RegisterMap *reg_map, -+ bool realloc_failures) { - // Set owner first, it is used when adding monitor chunks - - _frame_size = frame_size; - for(int i = 0; i < chunk->length(); i++) { -- element(i)->fill_in(chunk->at(i)); -+ element(i)->fill_in(chunk->at(i), realloc_failures); - } - - // Copy registers for callee-saved registers ---- jdk8/hotspot/src/share/vm/runtime/vframeArray.hpp 2015-01-27 08:42:54.013817273 +0100 -+++ jdk8/hotspot/src/share/vm/runtime/vframeArray.hpp 2015-01-27 08:43:45.286624106 +0100 -@@ -58,6 +58,9 @@ - MonitorChunk* _monitors; // active monitors for this vframe - StackValueCollection* _locals; - StackValueCollection* _expressions; -+#ifdef ASSERT -+ bool _removed_monitors; -+#endif - - public: - -@@ -78,7 +81,7 @@ - - StackValueCollection* expressions(void) const { return _expressions; } - -- void fill_in(compiledVFrame* vf); -+ void fill_in(compiledVFrame* vf, bool realloc_failures); - - // Formerly part of deoptimizedVFrame - -@@ -99,6 +102,12 @@ - bool is_bottom_frame, - int exec_mode); - -+#ifdef ASSERT -+ void set_removed_monitors() { -+ _removed_monitors = true; -+ } -+#endif -+ - #ifndef PRODUCT - void print(outputStream* st); - #endif /* PRODUCT */ -@@ -160,13 +169,14 @@ - int frames() const { return _frames; } - - static vframeArray* allocate(JavaThread* thread, int frame_size, GrowableArray* chunk, -- RegisterMap* reg_map, frame sender, frame caller, frame self); -+ RegisterMap* reg_map, frame sender, frame caller, frame self, -+ bool realloc_failures); - - - vframeArrayElement* element(int index) { assert(is_within_bounds(index), "Bad index"); return &_elements[index]; } - - // Allocates a new vframe in the array and fills the array with vframe information in chunk -- void fill_in(JavaThread* thread, int frame_size, GrowableArray* chunk, const RegisterMap *reg_map); -+ void fill_in(JavaThread* thread, int frame_size, GrowableArray* chunk, const RegisterMap *reg_map, bool realloc_failures); - - // Returns the owner of this vframeArray - JavaThread* owner_thread() const { return _owner_thread; } ---- jdk8/hotspot/src/share/vm/runtime/vmStructs.cpp 2015-01-27 08:42:54.014817250 +0100 -+++ jdk8/hotspot/src/share/vm/runtime/vmStructs.cpp 2015-01-27 08:43:45.287624083 +0100 -@@ -680,6 +680,7 @@ - static_field(SystemDictionary, WK_KLASS(WeakReference_klass), Klass*) \ - static_field(SystemDictionary, WK_KLASS(FinalReference_klass), Klass*) \ - static_field(SystemDictionary, WK_KLASS(PhantomReference_klass), Klass*) \ -+ static_field(SystemDictionary, WK_KLASS(Cleaner_klass), Klass*) \ - static_field(SystemDictionary, WK_KLASS(Finalizer_klass), Klass*) \ - static_field(SystemDictionary, WK_KLASS(Thread_klass), Klass*) \ - static_field(SystemDictionary, WK_KLASS(ThreadGroup_klass), Klass*) \ ---- jdk8/hotspot/src/share/vm/services/mallocTracker.cpp 2015-01-27 08:42:54.015817226 +0100 -+++ jdk8/hotspot/src/share/vm/services/mallocTracker.cpp 2015-01-27 08:43:45.287624083 +0100 -@@ -72,7 +72,7 @@ - - MallocMemorySummary::record_free(size(), flags()); - MallocMemorySummary::record_free_malloc_header(sizeof(MallocHeader)); -- if (tracking_level() == NMT_detail) { -+ if (MemTracker::tracking_level() == NMT_detail) { - MallocSiteTable::deallocation_at(size(), _bucket_idx, _pos_idx); - } - } -@@ -128,36 +128,18 @@ - } - - // Uses placement global new operator to initialize malloc header -- switch(level) { -- case NMT_off: -+ -+ if (level == NMT_off) { - return malloc_base; -- case NMT_minimal: { -- MallocHeader* hdr = ::new (malloc_base) MallocHeader(); -- break; -- } -- case NMT_summary: { -- assert(size <= MAX_MALLOC_SIZE, "malloc size overrun for NMT"); -- header = ::new (malloc_base) MallocHeader(size, flags); -- break; -- } -- case NMT_detail: { -- assert(size <= MAX_MALLOC_SIZE, "malloc size overrun for NMT"); -- header = ::new (malloc_base) MallocHeader(size, flags, stack); -- break; -- } -- default: -- ShouldNotReachHere(); - } -+ -+ header = ::new (malloc_base)MallocHeader(size, flags, stack, level); - memblock = (void*)((char*)malloc_base + sizeof(MallocHeader)); - - // The alignment check: 8 bytes alignment for 32 bit systems. - // 16 bytes alignment for 64-bit systems. - assert(((size_t)memblock & (sizeof(size_t) * 2 - 1)) == 0, "Alignment check"); - -- // Sanity check -- assert(get_memory_tracking_level(memblock) == level, -- "Wrong tracking level"); -- - #ifdef ASSERT - if (level > NMT_minimal) { - // Read back ---- jdk8/hotspot/src/share/vm/services/mallocTracker.hpp 2015-01-27 08:42:54.015817226 +0100 -+++ jdk8/hotspot/src/share/vm/services/mallocTracker.hpp 2015-01-27 08:43:45.287624083 +0100 -@@ -239,46 +239,33 @@ - - class MallocHeader VALUE_OBJ_CLASS_SPEC { - #ifdef _LP64 -- size_t _size : 62; -- size_t _level : 2; -+ size_t _size : 64; - size_t _flags : 8; - size_t _pos_idx : 16; - size_t _bucket_idx: 40; --#define MAX_MALLOCSITE_TABLE_SIZE ((size_t)1 << 40) --#define MAX_BUCKET_LENGTH ((size_t)(1 << 16)) --#define MAX_MALLOC_SIZE (((size_t)1 << 62) - 1) -+#define MAX_MALLOCSITE_TABLE_SIZE right_n_bits(40) -+#define MAX_BUCKET_LENGTH right_n_bits(16) - #else -- size_t _size : 30; -- size_t _level : 2; -+ size_t _size : 32; - size_t _flags : 8; - size_t _pos_idx : 8; - size_t _bucket_idx: 16; --#define MAX_MALLOCSITE_TABLE_SIZE ((size_t)(1 << 16)) --#define MAX_BUCKET_LENGTH ((size_t)(1 << 8)) --// Max malloc size = 1GB - 1 on 32 bit system, such has total 4GB memory --#define MAX_MALLOC_SIZE ((size_t)(1 << 30) - 1) -+#define MAX_MALLOCSITE_TABLE_SIZE right_n_bits(16) -+#define MAX_BUCKET_LENGTH right_n_bits(8) - #endif // _LP64 - - public: -- // Summary tracking header -- MallocHeader(size_t size, MEMFLAGS flags) { -+ MallocHeader(size_t size, MEMFLAGS flags, const NativeCallStack& stack, NMT_TrackingLevel level) { - assert(sizeof(MallocHeader) == sizeof(void*) * 2, - "Wrong header size"); - -- _level = NMT_summary; -- _flags = flags; -- set_size(size); -- MallocMemorySummary::record_malloc(size, flags); -- MallocMemorySummary::record_new_malloc_header(sizeof(MallocHeader)); -+ if (level == NMT_minimal) { -+ return; - } -- // Detail tracking header -- MallocHeader(size_t size, MEMFLAGS flags, const NativeCallStack& stack) { -- assert(sizeof(MallocHeader) == sizeof(void*) * 2, -- "Wrong header size"); - -- _level = NMT_detail; - _flags = flags; - set_size(size); -+ if (level == NMT_detail) { - size_t bucket_idx; - size_t pos_idx; - if (record_malloc_site(stack, size, &bucket_idx, &pos_idx)) { -@@ -287,19 +274,10 @@ - _bucket_idx = bucket_idx; - _pos_idx = pos_idx; - } -- MallocMemorySummary::record_malloc(size, flags); -- MallocMemorySummary::record_new_malloc_header(sizeof(MallocHeader)); -- } -- // Minimal tracking header -- MallocHeader() { -- assert(sizeof(MallocHeader) == sizeof(void*) * 2, -- "Wrong header size"); -- -- _level = (unsigned short)NMT_minimal; - } - -- inline NMT_TrackingLevel tracking_level() const { -- return (NMT_TrackingLevel)_level; -+ MallocMemorySummary::record_malloc(size, flags); -+ MallocMemorySummary::record_new_malloc_header(sizeof(MallocHeader)); - } - - inline size_t size() const { return _size; } -@@ -311,7 +289,6 @@ - - private: - inline void set_size(size_t size) { -- assert(size <= MAX_MALLOC_SIZE, "Malloc size too large, should use virtual memory?"); - _size = size; - } - bool record_malloc_site(const NativeCallStack& stack, size_t size, -@@ -347,10 +324,6 @@ - // Record free on specified memory block - static void* record_free(void* memblock); - -- // Get tracking level of specified memory block -- static inline NMT_TrackingLevel get_memory_tracking_level(void* memblock); -- -- - // Offset memory address to header address - static inline void* get_base(void* memblock); - static inline void* get_base(void* memblock, NMT_TrackingLevel level) { -@@ -361,16 +334,12 @@ - // Get memory size - static inline size_t get_size(void* memblock) { - MallocHeader* header = malloc_header(memblock); -- assert(header->tracking_level() >= NMT_summary, -- "Wrong tracking level"); - return header->size(); - } - - // Get memory type - static inline MEMFLAGS get_flags(void* memblock) { - MallocHeader* header = malloc_header(memblock); -- assert(header->tracking_level() >= NMT_summary, -- "Wrong tracking level"); - return header->flags(); - } - -@@ -394,7 +363,6 @@ - static inline MallocHeader* malloc_header(void *memblock) { - assert(memblock != NULL, "NULL pointer"); - MallocHeader* header = (MallocHeader*)((char*)memblock - sizeof(MallocHeader)); -- assert(header->tracking_level() >= NMT_minimal, "Bad header"); - return header; - } - }; ---- jdk8/hotspot/src/share/vm/services/mallocTracker.inline.hpp 2015-01-27 08:42:54.015817226 +0100 -+++ jdk8/hotspot/src/share/vm/services/mallocTracker.inline.hpp 2015-01-27 08:43:45.287624083 +0100 -@@ -28,13 +28,6 @@ - #include "services/mallocTracker.hpp" - #include "services/memTracker.hpp" - --inline NMT_TrackingLevel MallocTracker::get_memory_tracking_level(void* memblock) { -- assert(memblock != NULL, "Sanity check"); -- if (MemTracker::tracking_level() == NMT_off) return NMT_off; -- MallocHeader* header = malloc_header(memblock); -- return header->tracking_level(); --} -- - inline void* MallocTracker::get_base(void* memblock){ - return get_base(memblock, MemTracker::tracking_level()); - } ---- jdk8/hotspot/src/share/vm/services/runtimeService.cpp 2015-01-27 08:42:54.015817226 +0100 -+++ jdk8/hotspot/src/share/vm/services/runtimeService.cpp 2015-01-27 08:43:45.287624083 +0100 -@@ -46,6 +46,7 @@ - PerfCounter* RuntimeService::_thread_interrupt_signaled_count = NULL; - PerfCounter* RuntimeService::_interrupted_before_count = NULL; - PerfCounter* RuntimeService::_interrupted_during_count = NULL; -+double RuntimeService::_last_safepoint_sync_time_sec = 0.0; - - void RuntimeService::init() { - // Make sure the VM version is initialized -@@ -128,6 +129,7 @@ - - // update the time stamp to begin recording safepoint time - _safepoint_timer.update(); -+ _last_safepoint_sync_time_sec = 0.0; - if (UsePerfData) { - _total_safepoints->inc(); - if (_app_timer.is_updated()) { -@@ -140,6 +142,9 @@ - if (UsePerfData) { - _sync_time_ticks->inc(_safepoint_timer.ticks_since_update()); - } -+ if (PrintGCApplicationStoppedTime) { -+ _last_safepoint_sync_time_sec = last_safepoint_time_sec(); -+ } - } - - void RuntimeService::record_safepoint_end() { -@@ -155,8 +160,10 @@ - gclog_or_tty->date_stamp(PrintGCDateStamps); - gclog_or_tty->stamp(PrintGCTimeStamps); - gclog_or_tty->print_cr("Total time for which application threads " -- "were stopped: %3.7f seconds", -- last_safepoint_time_sec()); -+ "were stopped: %3.7f seconds, " -+ "Stopping threads took: %3.7f seconds", -+ last_safepoint_time_sec(), -+ _last_safepoint_sync_time_sec); - } - - // update the time stamp to begin recording app time ---- jdk8/hotspot/src/share/vm/services/runtimeService.hpp 2015-01-27 08:42:54.015817226 +0100 -+++ jdk8/hotspot/src/share/vm/services/runtimeService.hpp 2015-01-27 08:43:45.287624083 +0100 -@@ -40,6 +40,7 @@ - - static TimeStamp _safepoint_timer; - static TimeStamp _app_timer; -+ static double _last_safepoint_sync_time_sec; - - public: - static void init(); ---- jdk8/hotspot/src/share/vm/trace/noTraceBackend.hpp 2015-01-27 08:42:54.017817180 +0100 -+++ jdk8/hotspot/src/share/vm/trace/noTraceBackend.hpp 2015-01-27 08:43:45.288624059 +0100 -@@ -41,4 +41,4 @@ - - typedef NoTraceBackend Tracing; - --#endif -+#endif // SHARE_VM_TRACE_NOTRACEBACKEND_HPP ---- jdk8/hotspot/src/share/vm/trace/traceBackend.hpp 2015-01-27 08:42:54.017817180 +0100 -+++ jdk8/hotspot/src/share/vm/trace/traceBackend.hpp 2015-01-27 08:43:45.288624059 +0100 -@@ -58,9 +56,7 @@ - - typedef TraceBackend Tracing; - --#else /* INCLUDE_TRACE */ -- -+#else // !INCLUDE_TRACE - #include "trace/noTraceBackend.hpp" -- --#endif /* INCLUDE_TRACE */ --#endif /* SHARE_VM_TRACE_TRACEBACKEND_HPP */ -+#endif // INCLUDE_TRACE -+#endif // SHARE_VM_TRACE_TRACEBACKEND_HPP ---- jdk8/hotspot/src/share/vm/trace/traceEventClasses.xsl 2015-01-27 08:42:54.017817180 +0100 -+++ jdk8/hotspot/src/share/vm/trace/traceEventClasses.xsl 2015-01-27 08:43:45.288624059 +0100 -@@ -51,7 +48,7 @@ - - - --#else -+#else // !INCLUDE_TRACE - - class TraceEvent { - public: -@@ -65,9 +62,8 @@ - - - --#endif -- --#endif -+#endif // INCLUDE_TRACE -+#endif // TRACEFILES_TRACEEVENTCLASSES_HPP - - - ---- jdk8/hotspot/src/share/vm/trace/traceEvent.hpp 2015-01-27 08:42:54.017817180 +0100 -+++ jdk8/hotspot/src/share/vm/trace/traceEvent.hpp 2015-01-27 08:43:45.288624059 +0100 -@@ -154,6 +153,5 @@ - } - }; - --#endif /* INCLUDE_TRACE */ -- --#endif /* SHARE_VM_TRACE_TRACEEVENT_HPP */ -+#endif // INCLUDE_TRACE -+#endif // SHARE_VM_TRACE_TRACEEVENT_HPP ---- jdk8/hotspot/src/share/vm/trace/traceEventIds.xsl 2015-01-27 08:42:54.017817180 +0100 -+++ jdk8/hotspot/src/share/vm/trace/traceEventIds.xsl 2015-01-27 08:43:45.288624059 +0100 -@@ -29,13 +29,11 @@ - - - --#ifndef TRACEFILES_JFREVENTIDS_HPP --#define TRACEFILES_JFREVENTIDS_HPP -+#ifndef TRACEFILES_TRACEEVENTIDS_HPP -+#define TRACEFILES_TRACEEVENTIDS_HPP - - #include "utilities/macros.hpp" -- - #if INCLUDE_TRACE -- - #include "trace/traceDataTypes.hpp" - - /** -@@ -67,8 +65,8 @@ - typedef enum TraceEventId TraceEventId; - typedef enum TraceStructId TraceStructId; - --#endif --#endif -+#endif // INCLUDE_TRACE -+#endif // TRACEFILES_TRACEEVENTIDS_HPP - - - ---- jdk8/hotspot/src/share/vm/trace/traceMacros.hpp 2015-01-27 08:42:54.017817180 +0100 -+++ jdk8/hotspot/src/share/vm/trace/traceMacros.hpp 2015-01-27 08:43:45.288624059 +0100 -@@ -22,8 +22,8 @@ - * - */ - --#ifndef SHARE_VM_TRACE_TRACE_MACRO_HPP --#define SHARE_VM_TRACE_TRACE_MACRO_HPP -+#ifndef SHARE_VM_TRACE_TRACEMACROS_HPP -+#define SHARE_VM_TRACE_TRACEMACROS_HPP - - #define EVENT_THREAD_EXIT(thread) - #define EVENT_THREAD_DESTRUCT(thread) -@@ -41,4 +41,4 @@ - #define TRACE_TEMPLATES(template) - #define TRACE_INTRINSICS(do_intrinsic, do_class, do_name, do_signature, do_alias) - --#endif -+#endif // SHARE_VM_TRACE_TRACEMACROS_HPP ---- jdk8/hotspot/src/share/vm/trace/traceStream.hpp 2015-01-27 08:42:54.017817180 +0100 -+++ jdk8/hotspot/src/share/vm/trace/traceStream.hpp 2015-01-27 08:43:45.288624059 +0100 -@@ -117,5 +115,5 @@ - } - }; - --#endif /* INCLUDE_TRACE */ --#endif /* SHARE_VM_TRACE_TRACESTREAM_HPP */ -+#endif // INCLUDE_TRACE -+#endif // SHARE_VM_TRACE_TRACESTREAM_HPP ---- jdk8/hotspot/src/share/vm/trace/traceTypes.xsl 2015-01-27 08:42:54.017817180 +0100 -+++ jdk8/hotspot/src/share/vm/trace/traceTypes.xsl 2015-01-27 08:43:45.288624059 +0100 -@@ -29,8 +29,8 @@ - - - --#ifndef TRACEFILES_JFRTYPES_HPP --#define TRACEFILES_JFRTYPES_HPP -+#ifndef TRACEFILES_TRACETYPES_HPP -+#define TRACEFILES_TRACETYPES_HPP - - #include "oops/symbol.hpp" - #include "trace/traceDataTypes.hpp" -@@ -58,7 +57,7 @@ - }; - - /** -- * Create typedefs for the JRA types: -+ * Create typedefs for the TRACE types: - * typedef s8 TYPE_LONG; - * typedef s4 TYPE_INTEGER; - * typedef const char * TYPE_STRING; -@@ -68,7 +67,7 @@ - typedef TYPE_; - - --#endif // JFRFILES_JFRTYPES_HPP -+#endif // TRACEFILES_TRACETYPES_HPP - - - ---- jdk8/hotspot/src/share/vm/trace/tracing.hpp 2015-01-27 08:42:54.017817180 +0100 -+++ jdk8/hotspot/src/share/vm/trace/tracing.hpp 2015-01-27 08:43:45.289624036 +0100 -@@ -28,4 +28,4 @@ - #include "tracefiles/traceEventClasses.hpp" - #include "tracefiles/traceEventIds.hpp" - --#endif -+#endif // SHARE_VM_TRACE_TRACING_HPP ---- jdk8/hotspot/src/share/vm/utilities/accessFlags.cpp 2015-01-27 08:42:54.017817180 +0100 -+++ jdk8/hotspot/src/share/vm/utilities/accessFlags.cpp 2015-01-27 08:43:45.289624036 +0100 -@@ -62,6 +62,21 @@ - } while(f != old_flags); - } - -+// Returns true iff this thread succeeded setting the bit. -+bool AccessFlags::atomic_set_one_bit(jint bit) { -+ // Atomically update the flags with the bit given -+ jint old_flags, new_flags, f; -+ bool is_setting_bit = false; -+ do { -+ old_flags = _flags; -+ new_flags = old_flags | bit; -+ is_setting_bit = old_flags != new_flags; -+ f = Atomic::cmpxchg(new_flags, &_flags, old_flags); -+ } while(f != old_flags); -+ -+ return is_setting_bit; -+} -+ - #if !defined(PRODUCT) || INCLUDE_JVMTI - - void AccessFlags::print_on(outputStream* st) const { ---- jdk8/hotspot/src/share/vm/utilities/accessFlags.hpp 2015-01-27 08:42:54.017817180 +0100 -+++ jdk8/hotspot/src/share/vm/utilities/accessFlags.hpp 2015-01-27 08:43:45.289624036 +0100 -@@ -170,6 +170,7 @@ - - // Atomic update of flags - void atomic_set_bits(jint bits); -+ bool atomic_set_one_bit(jint bit); - void atomic_clear_bits(jint bits); - - private: -@@ -230,12 +231,13 @@ - atomic_set_bits(JVM_ACC_FIELD_HAS_GENERIC_SIGNATURE); - } - -- void set_on_stack(const bool value) -+ bool set_on_stack(const bool value) - { - if (value) { -- atomic_set_bits(JVM_ACC_ON_STACK); -+ return atomic_set_one_bit(JVM_ACC_ON_STACK); - } else { - atomic_clear_bits(JVM_ACC_ON_STACK); -+ return true; // Ignored - } - } - // Conversion ---- jdk8/hotspot/src/share/vm/utilities/chunkedList.cpp 1970-01-01 01:00:00.000000000 +0100 -+++ jdk8/hotspot/src/share/vm/utilities/chunkedList.cpp 2015-01-27 08:43:45.289624036 +0100 -@@ -0,0 +1,109 @@ -+/* -+ * 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. -+ * -+ */ -+ -+#include "precompiled.hpp" -+#include "utilities/chunkedList.hpp" -+#include "utilities/debug.hpp" -+ -+/////////////// Unit tests /////////////// -+ -+#ifndef PRODUCT -+ -+template -+class TestChunkedList { -+ typedef ChunkedList ChunkedListT; -+ -+ public: -+ static void testEmpty() { -+ ChunkedListT buffer; -+ assert(buffer.size() == 0, "assert"); -+ } -+ -+ static void testFull() { -+ ChunkedListT buffer; -+ for (uintptr_t i = 0; i < ChunkedListT::BufferSize; i++) { -+ buffer.push((T)i); -+ } -+ assert(buffer.size() == ChunkedListT::BufferSize, "assert"); -+ assert(buffer.is_full(), "assert"); -+ } -+ -+ static void testSize() { -+ ChunkedListT buffer; -+ for (uintptr_t i = 0; i < ChunkedListT::BufferSize; i++) { -+ assert(buffer.size() == i, "assert"); -+ buffer.push((T)i); -+ assert(buffer.size() == i + 1, "assert"); -+ } -+ } -+ -+ static void testClear() { -+ ChunkedListT buffer; -+ -+ buffer.clear(); -+ assert(buffer.size() == 0, "assert"); -+ -+ for (uintptr_t i = 0; i < ChunkedListT::BufferSize / 2; i++) { -+ buffer.push((T)i); -+ } -+ buffer.clear(); -+ assert(buffer.size() == 0, "assert"); -+ -+ for (uintptr_t i = 0; i < ChunkedListT::BufferSize; i++) { -+ buffer.push((T)i); -+ } -+ buffer.clear(); -+ assert(buffer.size() == 0, "assert"); -+ } -+ -+ static void testAt() { -+ ChunkedListT buffer; -+ -+ for (uintptr_t i = 0; i < ChunkedListT::BufferSize; i++) { -+ buffer.push((T)i); -+ assert(buffer.at(i) == (T)i, "assert"); -+ } -+ -+ for (uintptr_t i = 0; i < ChunkedListT::BufferSize; i++) { -+ assert(buffer.at(i) == (T)i, "assert"); -+ } -+ } -+ -+ static void test() { -+ testEmpty(); -+ testFull(); -+ testSize(); -+ testClear(); -+ testAt(); -+ } -+}; -+ -+class Metadata; -+ -+void TestChunkedList_test() { -+ TestChunkedList::test(); -+ TestChunkedList::test(); -+} -+ -+#endif ---- jdk8/hotspot/src/share/vm/utilities/chunkedList.hpp 1970-01-01 01:00:00.000000000 +0100 -+++ jdk8/hotspot/src/share/vm/utilities/chunkedList.hpp 2015-01-27 08:43:45.289624036 +0100 -@@ -0,0 +1,81 @@ -+/* -+ * 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. -+ * -+ */ -+ -+#ifndef SHARE_VM_UTILITIES_CHUNKED_LIST_HPP -+#define SHARE_VM_UTILITIES_CHUNKED_LIST_HPP -+ -+#include "memory/allocation.hpp" -+#include "utilities/debug.hpp" -+ -+template class ChunkedList : public CHeapObj { -+ template friend class TestChunkedList; -+ -+ static const size_t BufferSize = 64; -+ -+ T _values[BufferSize]; -+ T* _top; -+ -+ ChunkedList* _next_used; -+ ChunkedList* _next_free; -+ -+ T const * end() const { -+ return &_values[BufferSize]; -+ } -+ -+ public: -+ ChunkedList() : _top(_values), _next_used(NULL), _next_free(NULL) {} -+ -+ bool is_full() const { -+ return _top == end(); -+ } -+ -+ void clear() { -+ _top = _values; -+ // Don't clear the next pointers since that would interfere -+ // with other threads trying to iterate through the lists. -+ } -+ -+ void push(T m) { -+ assert(!is_full(), "Buffer is full"); -+ *_top = m; -+ _top++; -+ } -+ -+ void set_next_used(ChunkedList* buffer) { _next_used = buffer; } -+ void set_next_free(ChunkedList* buffer) { _next_free = buffer; } -+ -+ ChunkedList* next_used() const { return _next_used; } -+ ChunkedList* next_free() const { return _next_free; } -+ -+ size_t size() const { -+ return pointer_delta(_top, _values, sizeof(T)); -+ } -+ -+ T at(size_t i) { -+ assert(i < size(), err_msg("IOOBE i: " SIZE_FORMAT " size(): " SIZE_FORMAT, i, size())); -+ return _values[i]; -+ } -+}; -+ -+#endif // SHARE_VM_UTILITIES_CHUNKED_LIST_HPP ---- jdk8/hotspot/src/share/vm/utilities/debug.cpp 2015-01-27 08:42:54.018817157 +0100 -+++ jdk8/hotspot/src/share/vm/utilities/debug.cpp 2015-01-27 08:43:45.289624036 +0100 -@@ -266,17 +266,19 @@ - "native memory for metadata", - "shared read only space", - "shared read write space", -- "shared miscellaneous data space" -+ "shared miscellaneous data space", -+ "shared miscellaneous code space" - }; - static const char* flag[] = { - "Metaspace", - "SharedReadOnlySize", - "SharedReadWriteSize", -- "SharedMiscDataSize" -+ "SharedMiscDataSize", -+ "SharedMiscCodeSize" - }; - - warning("\nThe %s is not large enough\n" -- "to preload requested classes. Use -XX:%s=\n" -+ "to preload requested classes. Use -XX:%s=\n" - "to increase the initial size of %s.\n", - name[shared_space], flag[shared_space], name[shared_space]); - exit(2); ---- jdk8/hotspot/src/share/vm/utilities/debug.hpp 2015-01-27 08:42:54.018817157 +0100 -+++ jdk8/hotspot/src/share/vm/utilities/debug.hpp 2015-01-27 08:43:45.290624013 +0100 -@@ -246,7 +246,8 @@ - SharedPermGen, - SharedReadOnly, - SharedReadWrite, -- SharedMiscData -+ SharedMiscData, -+ SharedMiscCode - }; - - void report_out_of_shared_space(SharedSpaceType space_type); ---- jdk8/hotspot/src/share/vm/utilities/defaultStream.hpp 2015-01-27 08:42:54.018817157 +0100 -+++ jdk8/hotspot/src/share/vm/utilities/defaultStream.hpp 2015-01-27 08:43:45.290624013 +0100 -@@ -41,6 +41,8 @@ - - void init(); - void init_log(); -+ fileStream* open_file(const char* log_name); -+ void start_log(); - void finish_log(); - void finish_log_on_error(char *buf, int buflen); - public: ---- jdk8/hotspot/src/share/vm/utilities/ostream.cpp 2015-01-27 08:42:54.019817133 +0100 -+++ jdk8/hotspot/src/share/vm/utilities/ostream.cpp 2015-01-27 08:43:45.290624013 +0100 -@@ -370,7 +370,6 @@ - - #define EXTRACHARLEN 32 - #define CURRENTAPPX ".current" --#define FILENAMEBUFLEN 1024 - // convert YYYY-MM-DD HH:MM:SS to YYYY-MM-DD_HH-MM-SS - char* get_datetime_string(char *buf, size_t len) { - os::local_time_string(buf, len); -@@ -404,7 +403,6 @@ - buffer_length = strlen(log_name) + 1; - } - -- // const char* star = strchr(basename, '*'); - const char* pts = strstr(basename, "%p"); - int pid_pos = (pts == NULL) ? -1 : (pts - nametail); - -@@ -419,6 +417,11 @@ - buffer_length += strlen(tms); - } - -+ // File name is too long. -+ if (buffer_length > JVM_MAXPATHLEN) { -+ return NULL; -+ } -+ - // Create big enough buffer. - char *buf = NEW_C_HEAP_ARRAY(char, buffer_length, mtInternal); - -@@ -492,46 +495,88 @@ - void test_loggc_filename() { - int pid; - char tms[32]; -- char i_result[FILENAMEBUFLEN]; -+ char i_result[JVM_MAXPATHLEN]; - const char* o_result; - get_datetime_string(tms, sizeof(tms)); - pid = os::current_process_id(); - - // test.log -- jio_snprintf(i_result, sizeof(char)*FILENAMEBUFLEN, "test.log", tms); -+ jio_snprintf(i_result, JVM_MAXPATHLEN, "test.log", tms); - o_result = make_log_name_internal("test.log", NULL, pid, tms); - assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"test.log\", NULL)"); - FREE_C_HEAP_ARRAY(char, o_result, mtInternal); - - // test-%t-%p.log -- jio_snprintf(i_result, sizeof(char)*FILENAMEBUFLEN, "test-%s-pid%u.log", tms, pid); -+ jio_snprintf(i_result, JVM_MAXPATHLEN, "test-%s-pid%u.log", tms, pid); - o_result = make_log_name_internal("test-%t-%p.log", NULL, pid, tms); - assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"test-%%t-%%p.log\", NULL)"); - FREE_C_HEAP_ARRAY(char, o_result, mtInternal); - - // test-%t%p.log -- jio_snprintf(i_result, sizeof(char)*FILENAMEBUFLEN, "test-%spid%u.log", tms, pid); -+ jio_snprintf(i_result, JVM_MAXPATHLEN, "test-%spid%u.log", tms, pid); - o_result = make_log_name_internal("test-%t%p.log", NULL, pid, tms); - assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"test-%%t%%p.log\", NULL)"); - FREE_C_HEAP_ARRAY(char, o_result, mtInternal); - - // %p%t.log -- jio_snprintf(i_result, sizeof(char)*FILENAMEBUFLEN, "pid%u%s.log", pid, tms); -+ jio_snprintf(i_result, JVM_MAXPATHLEN, "pid%u%s.log", pid, tms); - o_result = make_log_name_internal("%p%t.log", NULL, pid, tms); - assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"%%p%%t.log\", NULL)"); - FREE_C_HEAP_ARRAY(char, o_result, mtInternal); - - // %p-test.log -- jio_snprintf(i_result, sizeof(char)*FILENAMEBUFLEN, "pid%u-test.log", pid); -+ jio_snprintf(i_result, JVM_MAXPATHLEN, "pid%u-test.log", pid); - o_result = make_log_name_internal("%p-test.log", NULL, pid, tms); - assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"%%p-test.log\", NULL)"); - FREE_C_HEAP_ARRAY(char, o_result, mtInternal); - - // %t.log -- jio_snprintf(i_result, sizeof(char)*FILENAMEBUFLEN, "%s.log", tms); -+ jio_snprintf(i_result, JVM_MAXPATHLEN, "%s.log", tms); - o_result = make_log_name_internal("%t.log", NULL, pid, tms); - assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"%%t.log\", NULL)"); - FREE_C_HEAP_ARRAY(char, o_result, mtInternal); -+ -+ { -+ // longest filename -+ char longest_name[JVM_MAXPATHLEN]; -+ memset(longest_name, 'a', sizeof(longest_name)); -+ longest_name[JVM_MAXPATHLEN - 1] = '\0'; -+ o_result = make_log_name_internal((const char*)&longest_name, NULL, pid, tms); -+ assert(strcmp(longest_name, o_result) == 0, err_msg("longest name does not match. expected '%s' but got '%s'", longest_name, o_result)); -+ FREE_C_HEAP_ARRAY(char, o_result, mtInternal); -+ } -+ -+ { -+ // too long file name -+ char too_long_name[JVM_MAXPATHLEN + 100]; -+ int too_long_length = sizeof(too_long_name); -+ memset(too_long_name, 'a', too_long_length); -+ too_long_name[too_long_length - 1] = '\0'; -+ o_result = make_log_name_internal((const char*)&too_long_name, NULL, pid, tms); -+ assert(o_result == NULL, err_msg("Too long file name should return NULL, but got '%s'", o_result)); -+ } -+ -+ { -+ // too long with timestamp -+ char longest_name[JVM_MAXPATHLEN]; -+ memset(longest_name, 'a', JVM_MAXPATHLEN); -+ longest_name[JVM_MAXPATHLEN - 3] = '%'; -+ longest_name[JVM_MAXPATHLEN - 2] = 't'; -+ longest_name[JVM_MAXPATHLEN - 1] = '\0'; -+ o_result = make_log_name_internal((const char*)&longest_name, NULL, pid, tms); -+ assert(o_result == NULL, err_msg("Too long file name after timestamp expansion should return NULL, but got '%s'", o_result)); -+ } -+ -+ { -+ // too long with pid -+ char longest_name[JVM_MAXPATHLEN]; -+ memset(longest_name, 'a', JVM_MAXPATHLEN); -+ longest_name[JVM_MAXPATHLEN - 3] = '%'; -+ longest_name[JVM_MAXPATHLEN - 2] = 'p'; -+ longest_name[JVM_MAXPATHLEN - 1] = '\0'; -+ o_result = make_log_name_internal((const char*)&longest_name, NULL, pid, tms); -+ assert(o_result == NULL, err_msg("Too long file name after pid expansion should return NULL, but got '%s'", o_result)); -+ } - } - #endif // PRODUCT - -@@ -640,9 +685,16 @@ - _bytes_written = 0L; - _file_name = make_log_name(file_name, NULL); - -+ if (_file_name == NULL) { -+ warning("Cannot open file %s: file name is too long.\n", file_name); -+ _need_close = false; -+ UseGCLogFileRotation = false; -+ return; -+ } -+ - // gc log file rotation - if (UseGCLogFileRotation && NumberOfGCLogFiles > 1) { -- char tempbuf[FILENAMEBUFLEN]; -+ char tempbuf[JVM_MAXPATHLEN]; - jio_snprintf(tempbuf, sizeof(tempbuf), "%s.%d" CURRENTAPPX, _file_name, _cur_file_num); - _file = fopen(tempbuf, "w"); - } else { -@@ -674,10 +726,10 @@ - // concurrent GC threads to run parallel with VMThread at safepoint, write and rotate_log - // must be synchronized. - void gcLogFileStream::rotate_log(bool force, outputStream* out) { -- char time_msg[FILENAMEBUFLEN]; -+ char time_msg[O_BUFLEN]; - char time_str[EXTRACHARLEN]; -- char current_file_name[FILENAMEBUFLEN]; -- char renamed_file_name[FILENAMEBUFLEN]; -+ char current_file_name[JVM_MAXPATHLEN]; -+ char renamed_file_name[JVM_MAXPATHLEN]; - - if (!should_rotate(force)) { - return; -@@ -716,12 +768,15 @@ - // have a form of extended_filename..current where i is the current rotation - // file number. After it reaches max file size, the file will be saved and renamed - // with .current removed from its tail. -- size_t filename_len = strlen(_file_name); - if (_file != NULL) { -- jio_snprintf(renamed_file_name, filename_len + EXTRACHARLEN, "%s.%d", -- _file_name, _cur_file_num); -- jio_snprintf(current_file_name, filename_len + EXTRACHARLEN, "%s.%d" CURRENTAPPX, -+ jio_snprintf(renamed_file_name, JVM_MAXPATHLEN, "%s.%d", - _file_name, _cur_file_num); -+ int result = jio_snprintf(current_file_name, JVM_MAXPATHLEN, -+ "%s.%d" CURRENTAPPX, _file_name, _cur_file_num); -+ if (result >= JVM_MAXPATHLEN) { -+ warning("Cannot create new log file name: %s: file name is too long.\n", current_file_name); -+ return; -+ } - - const char* msg = force ? "GC log rotation request has been received." - : "GC log file has reached the maximum size."; -@@ -760,19 +815,23 @@ - - _cur_file_num++; - if (_cur_file_num > NumberOfGCLogFiles - 1) _cur_file_num = 0; -- jio_snprintf(current_file_name, filename_len + EXTRACHARLEN, "%s.%d" CURRENTAPPX, -+ int result = jio_snprintf(current_file_name, JVM_MAXPATHLEN, "%s.%d" CURRENTAPPX, - _file_name, _cur_file_num); -+ if (result >= JVM_MAXPATHLEN) { -+ warning("Cannot create new log file name: %s: file name is too long.\n", current_file_name); -+ return; -+ } -+ - _file = fopen(current_file_name, "w"); - - if (_file != NULL) { - _bytes_written = 0L; - _need_close = true; - // reuse current_file_name for time_msg -- jio_snprintf(current_file_name, filename_len + EXTRACHARLEN, -+ jio_snprintf(current_file_name, JVM_MAXPATHLEN, - "%s.%d", _file_name, _cur_file_num); - jio_snprintf(time_msg, sizeof(time_msg), "%s GC log file created %s\n", -- os::local_time_string((char *)time_str, sizeof(time_str)), -- current_file_name); -+ os::local_time_string((char *)time_str, sizeof(time_str)), current_file_name); - write(time_msg, strlen(time_msg)); - - if (out != NULL) { -@@ -820,32 +879,64 @@ - return _log_file != NULL; - } - --void defaultStream::init_log() { -- // %%% Need a MutexLocker? -- const char* log_name = LogFile != NULL ? LogFile : "hotspot_%p.log"; -+fileStream* defaultStream::open_file(const char* log_name) { - const char* try_name = make_log_name(log_name, NULL); -+ if (try_name == NULL) { -+ warning("Cannot open file %s: file name is too long.\n", log_name); -+ return NULL; -+ } -+ - fileStream* file = new(ResourceObj::C_HEAP, mtInternal) fileStream(try_name); -- if (!file->is_open()) { -- // Try again to open the file. -+ FREE_C_HEAP_ARRAY(char, try_name, mtInternal); -+ if (file->is_open()) { -+ return file; -+ } -+ -+ // Try again to open the file in the temp directory. -+ delete file; - char warnbuf[O_BUFLEN*2]; -- jio_snprintf(warnbuf, sizeof(warnbuf), -- "Warning: Cannot open log file: %s\n", try_name); -+ jio_snprintf(warnbuf, sizeof(warnbuf), "Warning: Cannot open log file: %s\n", log_name); - // Note: This feature is for maintainer use only. No need for L10N. - jio_print(warnbuf); -- FREE_C_HEAP_ARRAY(char, try_name, mtInternal); - try_name = make_log_name(log_name, os::get_temp_directory()); -+ if (try_name == NULL) { -+ warning("Cannot open file %s: file name is too long for directory %s.\n", log_name, os::get_temp_directory()); -+ return NULL; -+ } -+ - jio_snprintf(warnbuf, sizeof(warnbuf), - "Warning: Forcing option -XX:LogFile=%s\n", try_name); - jio_print(warnbuf); -- delete file; -+ - file = new(ResourceObj::C_HEAP, mtInternal) fileStream(try_name); -- } - FREE_C_HEAP_ARRAY(char, try_name, mtInternal); -- - if (file->is_open()) { -+ return file; -+ } -+ -+ delete file; -+ return NULL; -+} -+ -+void defaultStream::init_log() { -+ // %%% Need a MutexLocker? -+ const char* log_name = LogFile != NULL ? LogFile : "hotspot_%p.log"; -+ fileStream* file = open_file(log_name); -+ -+ if (file != NULL) { - _log_file = file; -- xmlStream* xs = new(ResourceObj::C_HEAP, mtInternal) xmlStream(file); -- _outer_xmlStream = xs; -+ _outer_xmlStream = new(ResourceObj::C_HEAP, mtInternal) xmlStream(file); -+ start_log(); -+ } else { -+ // and leave xtty as NULL -+ LogVMOutput = false; -+ DisplayVMOutput = true; -+ LogCompilation = false; -+ } -+} -+ -+void defaultStream::start_log() { -+ xmlStream*xs = _outer_xmlStream; - if (this == tty) xtty = xs; - // Write XML header. - xs->print_cr(""); -@@ -900,13 +991,6 @@ - xs->head("tty"); - // All further non-markup text gets copied to the tty: - xs->_text = this; // requires friend declaration! -- } else { -- delete(file); -- // and leave xtty as NULL -- LogVMOutput = false; -- DisplayVMOutput = true; -- LogCompilation = false; -- } - } - - // finish_log() is called during normal VM shutdown. finish_log_on_error() is ---- jdk8/hotspot/src/share/vm/utilities/vmError.cpp 2015-01-27 08:42:54.019817133 +0100 -+++ jdk8/hotspot/src/share/vm/utilities/vmError.cpp 2015-01-27 08:43:45.290624013 +0100 -@@ -22,6 +22,7 @@ - * - */ - -+#include - #include "precompiled.hpp" - #include "compiler/compileBroker.hpp" - #include "gc_interface/collectedHeap.hpp" -@@ -841,7 +842,8 @@ - static int expand_and_open(const char* pattern, char* buf, size_t buflen, size_t pos) { - int fd = -1; - if (Arguments::copy_expand_pid(pattern, strlen(pattern), &buf[pos], buflen - pos)) { -- fd = open(buf, O_RDWR | O_CREAT | O_TRUNC, 0666); -+ // the O_EXCL flag will cause the open to fail if the file exists -+ fd = open(buf, O_RDWR | O_CREAT | O_EXCL, 0666); - } - return fd; - } diff --git a/b2ce5df33715.tar.bz2 b/b2ce5df33715.tar.bz2 new file mode 100644 index 0000000..18ce00b --- /dev/null +++ b/b2ce5df33715.tar.bz2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:53cb046e73c43fdf8f88cf588637714e27ebea74df7c4f37b0f1d2c5f10c4162 +size 2744446 diff --git a/b6d03a810a61.tar.bz2 b/b6d03a810a61.tar.bz2 deleted file mode 100644 index 1b1b1b6..0000000 --- a/b6d03a810a61.tar.bz2 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6f25ddc0bc0a04cb79217c3551f9f055d0c9cf6cc2356d2b0476bb089de96151 -size 396113 diff --git a/c5d4ffa220f3.tar.bz2 b/c5d4ffa220f3.tar.bz2 new file mode 100644 index 0000000..3fd6619 --- /dev/null +++ b/c5d4ffa220f3.tar.bz2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7203caf92ca34d348c334720876d2195e83cd466545030346b9a7093b7d7aa9b +size 2373926 diff --git a/d168113f9841.tar.bz2 b/d168113f9841.tar.bz2 deleted file mode 100644 index 7fcf1d0..0000000 --- a/d168113f9841.tar.bz2 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:0fda54b5a783abe76559402613d17c75e46465263e2ffd902be1d675e5b9d3de -size 45404071 diff --git a/f9f70a0f60f4.tar.bz2 b/f9f70a0f60f4.tar.bz2 deleted file mode 100644 index 2d40faa..0000000 --- a/f9f70a0f60f4.tar.bz2 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6a1ab9e1b81a10fb26bd4196ff38c4a8bc575bfc32be6c471a3314e250b5da55 -size 2742531 diff --git a/fa4e797f61e6.tar.bz2 b/fa4e797f61e6.tar.bz2 new file mode 100644 index 0000000..368c4e2 --- /dev/null +++ b/fa4e797f61e6.tar.bz2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a6236d3c0c3dcb96106f4b575f8dcf621ad889aa3bcafe929b80acd327ff4e57 +size 7753551 diff --git a/java-1_8_0-openjdk.changes b/java-1_8_0-openjdk.changes index 3a461be..1db66a0 100644 --- a/java-1_8_0-openjdk.changes +++ b/java-1_8_0-openjdk.changes @@ -1,3 +1,14 @@ +------------------------------------------------------------------- +Thu Feb 5 09:55:30 UTC 2015 - fstrba@suse.com + +- Upgrade to upstream tag jdk8u40-b24 +- Upgrade the aarch64 hotspot to new tip + * sync-ed with jdk8u40-b23 +- Removed patch + * aarch64-b12tob22.patch + - Not needed since the aarch64 tarball is on a recent enough + tag + ------------------------------------------------------------------- Tue Jan 27 07:52:58 UTC 2015 - fstrba@suse.com diff --git a/java-1_8_0-openjdk.spec b/java-1_8_0-openjdk.spec index 8d5eda2..cb3cb1c 100644 --- a/java-1_8_0-openjdk.spec +++ b/java-1_8_0-openjdk.spec @@ -30,20 +30,20 @@ %global archname %{name} # Standard JPackage naming and versioning defines. %global updatever 40 -%global buildver b22 +%global buildver b24 %global root_project jdk8u %global root_repository jdk8u40 -%global root_revision b6d03a810a61 -%global corba_revision 4c7421f74674 -%global hotspot_revision 0ee548a1cda0 -%global jaxp_revision 54a13451ce24 -%global jaxws_revision 6e928fd91525 -%global jdk_revision d168113f9841 -%global langtools_revision 79177246b3db -%global nashorn_revision f9f70a0f60f4 +%global root_revision 5b37e6757d7c +%global corba_revision 472aa5bae0e7 +%global hotspot_revision fa4e797f61e6 +%global jaxp_revision 048cebd17f73 +%global jaxws_revision 5fbbfd66643e +%global jdk_revision 9d903721276c +%global langtools_revision c5d4ffa220f3 +%global nashorn_revision b2ce5df33715 %global aarch64_project aarch64-port %global aarch64_repository jdk8 -%global aarch64_hotspot_revision 06c52e8fd6d3 +%global aarch64_hotspot_revision 44142a22d60f %global icedtea_sound_version 1.0.1 # priority must be 6 digits in total %global priority 180%{updatever} @@ -215,8 +215,6 @@ Patch8: compare-pointer-with-literal.patch Patch9: aarch64-misc.patch # From icedtea: Increase default memory limits Patch10: memory-limits.patch -# Changes from b22 backported to aarch64 which is on b12 -Patch11: aarch64-b12tob22.patch # Fix use of unintialized memory in adlc parser Patch12: adlc-parser.patch # Fix: implicit-pointer-decl @@ -509,9 +507,6 @@ rm -rvf jdk/src/share/native/sun/java2d/cmm/lcms/lcms2* %patch8 -p1 %patch9 -p1 %patch10 -p1 -%ifarch %{aarch64} -%patch11 -p1 -%endif %patch12 -p1 %patch13 -p1