# HG changeset patch # User sspitsyn # Date 1493778722 0 # Node ID 02a1fc0641449f259cb11bb9d0cb05995519c840 # Parent 2f733d553ca0678a3938b1777c51a51bbfe7d7a6# Parent 2dfc07162b351c3c88350ffd550ca091d637ffe4 Merge diff -r 2f733d553ca0 -r 02a1fc064144 hotspot/.hgtags --- a/hotspot/.hgtags Tue May 02 19:27:26 2017 -0700 +++ b/hotspot/.hgtags Wed May 03 02:32:02 2017 +0000 @@ -560,6 +560,7 @@ a9fdfd55835ef9dccb7f317b07249bd66653b874 jdk-9+154 f3b3d77a1751897413aae43ac340a130b6fa2ae1 jdk-9+155 43139c588ea48b6504e52b6c3dec530b17b1fdb4 jdk-9+156 +1ea217626ba0995dd03127f8322ba3687926a085 jdk-10+1 b2d0a906afd73dcf27f572217eb1be0f196ec16c jdk-9+157 4e78f30935229f13ce7c43089621cf7169f5abac jdk-9+158 9211c2e89c1cd11ec2d5752b0f97131a7d7525c7 jdk-9+159 @@ -570,3 +571,4 @@ 0af429be8bbaeaaf0cb838e9af28c953dda6a9c8 jdk-9+164 c92c6416ca03b1464d5ed99cf6201e52b5ba0a70 jdk-9+165 560d7aa083a24b6a56443feb8de0f40435d33aa9 jdk-9+166 +48809c513ed5ebb4d4dbf2f454afcce2780db6db jdk-10+2 diff -r 2f733d553ca0 -r 02a1fc064144 hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp --- a/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp Tue May 02 19:27:26 2017 -0700 +++ b/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp Wed May 03 02:32:02 2017 +0000 @@ -968,10 +968,11 @@ // than prefetch distance. __ set(prefetch_count, O4); __ cmp_and_brx_short(count, O4, Assembler::less, Assembler::pt, L_block_copy); - __ sub(count, prefetch_count, count); + __ sub(count, O4, count); (this->*copy_loop_func)(from, to, count, count_dec, L_block_copy_prefetch, true, true); - __ add(count, prefetch_count, count); // restore count + __ set(prefetch_count, O4); + __ add(count, O4, count); } // prefetch_count > 0 @@ -992,11 +993,12 @@ // than prefetch distance. __ set(prefetch_count, O4); __ cmp_and_brx_short(count, O4, Assembler::lessUnsigned, Assembler::pt, L_copy); - __ sub(count, prefetch_count, count); + __ sub(count, O4, count); Label L_copy_prefetch; (this->*copy_loop_func)(from, to, count, count_dec, L_copy_prefetch, true, false); - __ add(count, prefetch_count, count); // restore count + __ set(prefetch_count, O4); + __ add(count, O4, count); } // prefetch_count > 0 diff -r 2f733d553ca0 -r 02a1fc064144 hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/AltHashing.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/AltHashing.java Wed May 03 02:32:02 2017 +0000 @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package sun.jvm.hotspot.memory; + +public class AltHashing { + public static long murmur3_32(long seed, byte[] data) { + long h1 = seed; + int len = data.length; + int count = len; + + int offset = 0; + + // body + while (count >= 4) { + long k1 = (data[offset] & 0x0FF) + | (data[offset + 1] & 0x0FF) << 8 + | (data[offset + 2] & 0x0FF) << 16 + | data[offset + 3] << 24; + + count -= 4; + offset += 4; + + k1 *= 0xcc9e2d51; + k1 = Integer.rotateLeft((int)k1, 15); + k1 *= 0x1b873593; + k1 &= 0xFFFFFFFFL; + + h1 ^= k1; + h1 = Integer.rotateLeft((int)h1, 13); + h1 = h1 * 5 + 0xe6546b64; + h1 &= 0xFFFFFFFFL; + } + + //tail + if (count > 0) { + long k1 = 0; + + switch (count) { + case 3: + k1 ^= (data[offset + 2] & 0xff) << 16; + // fall through + case 2: + k1 ^= (data[offset + 1] & 0xff) << 8; + // fall through + case 1: + k1 ^= (data[offset] & 0xff); + // fall through + default: + k1 *= 0xcc9e2d51; + k1 = Integer.rotateLeft((int)k1, 15); + k1 *= 0x1b873593; + k1 &= 0xFFFFFFFFL; + h1 ^= k1; + h1 &= 0xFFFFFFFFL; + } + } + + // finalization + h1 ^= len; + + // finalization mix force all bits of a hash block to avalanche + h1 ^= h1 >> 16; + h1 *= 0x85ebca6b; + h1 &= 0xFFFFFFFFL; + h1 ^= h1 >> 13; + h1 *= 0xc2b2ae35; + h1 &= 0xFFFFFFFFL; + h1 ^= h1 >> 16; + + return h1 & 0xFFFFFFFFL; + } +} diff -r 2f733d553ca0 -r 02a1fc064144 hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/SymbolTable.java --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/SymbolTable.java Tue May 02 19:27:26 2017 -0700 +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/SymbolTable.java Wed May 03 02:32:02 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,11 +45,14 @@ Type type = db.lookupType("SymbolTable"); theTableField = type.getAddressField("_the_table"); sharedTableField = type.getAddressField("_shared_table"); + type = db.lookupType("RehashableSymbolHashtable"); + seedField = type.getCIntegerField("_seed"); } // Fields private static AddressField theTableField; private static AddressField sharedTableField; + private static CIntegerField seedField; private CompactHashTable sharedTable; @@ -62,6 +65,17 @@ return table; } + public static long getSeed() { + return (long) seedField.getValue(); + } + + public static boolean useAlternateHashcode() { + if (getSeed() != 0) { + return true; + } + return false; + } + public SymbolTable(Address addr) { super(addr); } @@ -86,11 +100,17 @@ public Symbol probe(byte[] name) { long hashValue = hashSymbol(name); + // shared table does not use alternate hashing algorithm, + // it always uses the same original hash code. Symbol s = sharedTable.probe(name, hashValue); if (s != null) { return s; } + if (useAlternateHashcode()) { + hashValue = AltHashing.murmur3_32(getSeed(), name); + } + for (HashtableEntry e = (HashtableEntry) bucket(hashToIndex(hashValue)); e != null; e = (HashtableEntry) e.next()) { if (e.hash() == hashValue) { Symbol sym = Symbol.create(e.literalValue()); diff -r 2f733d553ca0 -r 02a1fc064144 hotspot/src/os_cpu/bsd_x86/vm/atomic_bsd_x86.hpp --- a/hotspot/src/os_cpu/bsd_x86/vm/atomic_bsd_x86.hpp Tue May 02 19:27:26 2017 -0700 +++ b/hotspot/src/os_cpu/bsd_x86/vm/atomic_bsd_x86.hpp Wed May 03 02:32:02 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,23 +42,18 @@ inline void Atomic::store_ptr(void* store_value, volatile void* dest) { *(void* volatile *)dest = store_value; } -// Adding a lock prefix to an instruction on MP machine -#define LOCK_IF_MP(mp) "cmp $0, " #mp "; je 1f; lock; 1: " - inline jint Atomic::add (jint add_value, volatile jint* dest) { jint addend = add_value; - int mp = os::is_MP(); - __asm__ volatile ( LOCK_IF_MP(%3) "xaddl %0,(%2)" + __asm__ volatile ( "lock xaddl %0,(%2)" : "=r" (addend) - : "0" (addend), "r" (dest), "r" (mp) + : "0" (addend), "r" (dest) : "cc", "memory"); return addend + add_value; } inline void Atomic::inc (volatile jint* dest) { - int mp = os::is_MP(); - __asm__ volatile (LOCK_IF_MP(%1) "addl $1,(%0)" : - : "r" (dest), "r" (mp) : "cc", "memory"); + __asm__ volatile ( "lock addl $1,(%0)" : + : "r" (dest) : "cc", "memory"); } inline void Atomic::inc_ptr(volatile void* dest) { @@ -66,9 +61,8 @@ } inline void Atomic::dec (volatile jint* dest) { - int mp = os::is_MP(); - __asm__ volatile (LOCK_IF_MP(%1) "subl $1,(%0)" : - : "r" (dest), "r" (mp) : "cc", "memory"); + __asm__ volatile ( "lock subl $1,(%0)" : + : "r" (dest) : "cc", "memory"); } inline void Atomic::dec_ptr(volatile void* dest) { @@ -89,19 +83,17 @@ #define VM_HAS_SPECIALIZED_CMPXCHG_BYTE inline jbyte Atomic::cmpxchg (jbyte exchange_value, volatile jbyte* dest, jbyte compare_value, cmpxchg_memory_order order) { - int mp = os::is_MP(); - __asm__ volatile (LOCK_IF_MP(%4) "cmpxchgb %1,(%3)" + __asm__ volatile ( "lock cmpxchgb %1,(%3)" : "=a" (exchange_value) - : "q" (exchange_value), "a" (compare_value), "r" (dest), "r" (mp) + : "q" (exchange_value), "a" (compare_value), "r" (dest) : "cc", "memory"); return exchange_value; } inline jint Atomic::cmpxchg (jint exchange_value, volatile jint* dest, jint compare_value, cmpxchg_memory_order order) { - int mp = os::is_MP(); - __asm__ volatile (LOCK_IF_MP(%4) "cmpxchgl %1,(%3)" + __asm__ volatile ( "lock cmpxchgl %1,(%3)" : "=a" (exchange_value) - : "r" (exchange_value), "a" (compare_value), "r" (dest), "r" (mp) + : "r" (exchange_value), "a" (compare_value), "r" (dest) : "cc", "memory"); return exchange_value; } @@ -112,10 +104,9 @@ inline intptr_t Atomic::add_ptr(intptr_t add_value, volatile intptr_t* dest) { intptr_t addend = add_value; - bool mp = os::is_MP(); - __asm__ __volatile__ (LOCK_IF_MP(%3) "xaddq %0,(%2)" + __asm__ __volatile__ ( "lock xaddq %0,(%2)" : "=r" (addend) - : "0" (addend), "r" (dest), "r" (mp) + : "0" (addend), "r" (dest) : "cc", "memory"); return addend + add_value; } @@ -125,18 +116,16 @@ } inline void Atomic::inc_ptr(volatile intptr_t* dest) { - bool mp = os::is_MP(); - __asm__ __volatile__ (LOCK_IF_MP(%1) "addq $1,(%0)" + __asm__ __volatile__ ( "lock addq $1,(%0)" : - : "r" (dest), "r" (mp) + : "r" (dest) : "cc", "memory"); } inline void Atomic::dec_ptr(volatile intptr_t* dest) { - bool mp = os::is_MP(); - __asm__ __volatile__ (LOCK_IF_MP(%1) "subq $1,(%0)" + __asm__ __volatile__ ( "lock subq $1,(%0)" : - : "r" (dest), "r" (mp) + : "r" (dest) : "cc", "memory"); } @@ -149,10 +138,9 @@ } inline jlong Atomic::cmpxchg (jlong exchange_value, volatile jlong* dest, jlong compare_value, cmpxchg_memory_order order) { - bool mp = os::is_MP(); - __asm__ __volatile__ (LOCK_IF_MP(%4) "cmpxchgq %1,(%3)" + __asm__ __volatile__ ( "lock cmpxchgq %1,(%3)" : "=a" (exchange_value) - : "r" (exchange_value), "a" (compare_value), "r" (dest), "r" (mp) + : "r" (exchange_value), "a" (compare_value), "r" (dest) : "cc", "memory"); return exchange_value; } diff -r 2f733d553ca0 -r 02a1fc064144 hotspot/src/os_cpu/linux_x86/vm/atomic_linux_x86.hpp --- a/hotspot/src/os_cpu/linux_x86/vm/atomic_linux_x86.hpp Tue May 02 19:27:26 2017 -0700 +++ b/hotspot/src/os_cpu/linux_x86/vm/atomic_linux_x86.hpp Wed May 03 02:32:02 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,23 +42,18 @@ inline void Atomic::store_ptr(void* store_value, volatile void* dest) { *(void* volatile *)dest = store_value; } -// Adding a lock prefix to an instruction on MP machine -#define LOCK_IF_MP(mp) "cmp $0, " #mp "; je 1f; lock; 1: " - inline jint Atomic::add (jint add_value, volatile jint* dest) { jint addend = add_value; - int mp = os::is_MP(); - __asm__ volatile ( LOCK_IF_MP(%3) "xaddl %0,(%2)" + __asm__ volatile ( "lock xaddl %0,(%2)" : "=r" (addend) - : "0" (addend), "r" (dest), "r" (mp) + : "0" (addend), "r" (dest) : "cc", "memory"); return addend + add_value; } inline void Atomic::inc (volatile jint* dest) { - int mp = os::is_MP(); - __asm__ volatile (LOCK_IF_MP(%1) "addl $1,(%0)" : - : "r" (dest), "r" (mp) : "cc", "memory"); + __asm__ volatile ( "lock addl $1,(%0)" : + : "r" (dest) : "cc", "memory"); } inline void Atomic::inc_ptr(volatile void* dest) { @@ -66,9 +61,8 @@ } inline void Atomic::dec (volatile jint* dest) { - int mp = os::is_MP(); - __asm__ volatile (LOCK_IF_MP(%1) "subl $1,(%0)" : - : "r" (dest), "r" (mp) : "cc", "memory"); + __asm__ volatile ( "lock subl $1,(%0)" : + : "r" (dest) : "cc", "memory"); } inline void Atomic::dec_ptr(volatile void* dest) { @@ -89,19 +83,17 @@ #define VM_HAS_SPECIALIZED_CMPXCHG_BYTE inline jbyte Atomic::cmpxchg (jbyte exchange_value, volatile jbyte* dest, jbyte compare_value, cmpxchg_memory_order order) { - int mp = os::is_MP(); - __asm__ volatile (LOCK_IF_MP(%4) "cmpxchgb %1,(%3)" + __asm__ volatile ("lock cmpxchgb %1,(%3)" : "=a" (exchange_value) - : "q" (exchange_value), "a" (compare_value), "r" (dest), "r" (mp) + : "q" (exchange_value), "a" (compare_value), "r" (dest) : "cc", "memory"); return exchange_value; } inline jint Atomic::cmpxchg (jint exchange_value, volatile jint* dest, jint compare_value, cmpxchg_memory_order order) { - int mp = os::is_MP(); - __asm__ volatile (LOCK_IF_MP(%4) "cmpxchgl %1,(%3)" + __asm__ volatile ("lock cmpxchgl %1,(%3)" : "=a" (exchange_value) - : "r" (exchange_value), "a" (compare_value), "r" (dest), "r" (mp) + : "r" (exchange_value), "a" (compare_value), "r" (dest) : "cc", "memory"); return exchange_value; } @@ -112,10 +104,9 @@ inline intptr_t Atomic::add_ptr(intptr_t add_value, volatile intptr_t* dest) { intptr_t addend = add_value; - bool mp = os::is_MP(); - __asm__ __volatile__ (LOCK_IF_MP(%3) "xaddq %0,(%2)" + __asm__ __volatile__ ("lock xaddq %0,(%2)" : "=r" (addend) - : "0" (addend), "r" (dest), "r" (mp) + : "0" (addend), "r" (dest) : "cc", "memory"); return addend + add_value; } @@ -125,18 +116,16 @@ } inline void Atomic::inc_ptr(volatile intptr_t* dest) { - bool mp = os::is_MP(); - __asm__ __volatile__ (LOCK_IF_MP(%1) "addq $1,(%0)" + __asm__ __volatile__ ("lock addq $1,(%0)" : - : "r" (dest), "r" (mp) + : "r" (dest) : "cc", "memory"); } inline void Atomic::dec_ptr(volatile intptr_t* dest) { - bool mp = os::is_MP(); - __asm__ __volatile__ (LOCK_IF_MP(%1) "subq $1,(%0)" + __asm__ __volatile__ ("lock subq $1,(%0)" : - : "r" (dest), "r" (mp) + : "r" (dest) : "cc", "memory"); } @@ -149,10 +138,9 @@ } inline jlong Atomic::cmpxchg (jlong exchange_value, volatile jlong* dest, jlong compare_value, cmpxchg_memory_order order) { - bool mp = os::is_MP(); - __asm__ __volatile__ (LOCK_IF_MP(%4) "cmpxchgq %1,(%3)" + __asm__ __volatile__ ("lock cmpxchgq %1,(%3)" : "=a" (exchange_value) - : "r" (exchange_value), "a" (compare_value), "r" (dest), "r" (mp) + : "r" (exchange_value), "a" (compare_value), "r" (dest) : "cc", "memory"); return exchange_value; } @@ -192,12 +180,12 @@ extern "C" { // defined in linux_x86.s - jlong _Atomic_cmpxchg_long(jlong, volatile jlong*, jlong, bool); + jlong _Atomic_cmpxchg_long(jlong, volatile jlong*, jlong); void _Atomic_move_long(volatile jlong* src, volatile jlong* dst); } inline jlong Atomic::cmpxchg (jlong exchange_value, volatile jlong* dest, jlong compare_value, cmpxchg_memory_order order) { - return _Atomic_cmpxchg_long(exchange_value, dest, compare_value, os::is_MP()); + return _Atomic_cmpxchg_long(exchange_value, dest, compare_value); } inline intptr_t Atomic::cmpxchg_ptr(intptr_t exchange_value, volatile intptr_t* dest, intptr_t compare_value, cmpxchg_memory_order order) { diff -r 2f733d553ca0 -r 02a1fc064144 hotspot/src/os_cpu/linux_x86/vm/linux_x86_32.s --- a/hotspot/src/os_cpu/linux_x86/vm/linux_x86_32.s Tue May 02 19:27:26 2017 -0700 +++ b/hotspot/src/os_cpu/linux_x86/vm/linux_x86_32.s Wed May 03 02:32:02 2017 +0000 @@ -1,5 +1,5 @@ # -# Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2004, 2017, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -614,8 +614,7 @@ # Support for jlong Atomic::cmpxchg(jlong exchange_value, # volatile jlong* dest, - # jlong compare_value, - # bool is_MP) + # jlong compare_value) # .p2align 4,,15 .type _Atomic_cmpxchg_long,@function @@ -628,10 +627,7 @@ movl 24(%esp), %eax # 24(%esp) : compare_value (low) movl 28(%esp), %edx # 28(%esp) : compare_value (high) movl 20(%esp), %edi # 20(%esp) : dest - cmpl $0, 32(%esp) # 32(%esp) : is_MP - je 1f - lock -1: cmpxchg8b (%edi) + lock cmpxchg8b (%edi) popl %edi popl %ebx ret diff -r 2f733d553ca0 -r 02a1fc064144 hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp --- a/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp Tue May 02 19:27:26 2017 -0700 +++ b/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp Wed May 03 02:32:02 2017 +0000 @@ -404,7 +404,7 @@ // is available to us as well Sysinfo cpu_info(SI_CPUBRAND); bool use_solaris_12_api = cpu_info.valid(); - const char* impl; + const char* impl = "unknown"; int impl_m = 0; if (use_solaris_12_api) { impl = cpu_info.value(); @@ -431,7 +431,7 @@ kstat_close(kc); } } - assert(impl_m != 0, "Unknown CPU implementation %s", impl); + assert(impl_m != 0, "Unrecognized CPU implementation: %s", impl); features |= impl_m; bool is_sun4v = (features & sun4v_m) != 0; diff -r 2f733d553ca0 -r 02a1fc064144 hotspot/src/os_cpu/solaris_x86/vm/atomic_solaris_x86.hpp --- a/hotspot/src/os_cpu/solaris_x86/vm/atomic_solaris_x86.hpp Tue May 02 19:27:26 2017 -0700 +++ b/hotspot/src/os_cpu/solaris_x86/vm/atomic_solaris_x86.hpp Wed May 03 02:32:02 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -52,31 +52,19 @@ // For Sun Studio - implementation is in solaris_x86_[32/64].il. // For gcc - implementation is just below. -// The lock prefix can be omitted for certain instructions on uniprocessors; to -// facilitate this, os::is_MP() is passed as an additional argument. 64-bit -// processors are assumed to be multi-threaded and/or multi-core, so the extra -// argument is unnecessary. -#ifndef _LP64 -#define IS_MP_DECL() , int is_mp -#define IS_MP_ARG() , (int) os::is_MP() -#else -#define IS_MP_DECL() -#define IS_MP_ARG() -#endif // _LP64 - extern "C" { - jint _Atomic_add(jint add_value, volatile jint* dest IS_MP_DECL()); + jint _Atomic_add(jint add_value, volatile jint* dest); jint _Atomic_xchg(jint exchange_value, volatile jint* dest); jbyte _Atomic_cmpxchg_byte(jbyte exchange_value, volatile jbyte* dest, - jbyte compare_value IS_MP_DECL()); + jbyte compare_value); jint _Atomic_cmpxchg(jint exchange_value, volatile jint* dest, - jint compare_value IS_MP_DECL()); + jint compare_value); jlong _Atomic_cmpxchg_long(jlong exchange_value, volatile jlong* dest, - jlong compare_value IS_MP_DECL()); + jlong compare_value); } inline jint Atomic::add (jint add_value, volatile jint* dest) { - return _Atomic_add(add_value, dest IS_MP_ARG()); + return _Atomic_add(add_value, dest); } inline jint Atomic::xchg (jint exchange_value, volatile jint* dest) { @@ -85,15 +73,15 @@ #define VM_HAS_SPECIALIZED_CMPXCHG_BYTE inline jbyte Atomic::cmpxchg (jbyte exchange_value, volatile jbyte* dest, jbyte compare_value, cmpxchg_memory_order order) { - return _Atomic_cmpxchg_byte(exchange_value, dest, compare_value IS_MP_ARG()); + return _Atomic_cmpxchg_byte(exchange_value, dest, compare_value); } inline jint Atomic::cmpxchg (jint exchange_value, volatile jint* dest, jint compare_value, cmpxchg_memory_order order) { - return _Atomic_cmpxchg(exchange_value, dest, compare_value IS_MP_ARG()); + return _Atomic_cmpxchg(exchange_value, dest, compare_value); } inline jlong Atomic::cmpxchg (jlong exchange_value, volatile jlong* dest, jlong compare_value, cmpxchg_memory_order order) { - return _Atomic_cmpxchg_long(exchange_value, dest, compare_value IS_MP_ARG()); + return _Atomic_cmpxchg_long(exchange_value, dest, compare_value); } @@ -174,25 +162,23 @@ #endif // AMD64 #ifdef _GNU_SOURCE -// Add a lock prefix to an instruction on an MP machine -#define LOCK_IF_MP(mp) "cmp $0, " #mp "; je 1f; lock; 1: " extern "C" { - inline jint _Atomic_add(jint add_value, volatile jint* dest, int mp) { + inline jint _Atomic_add(jint add_value, volatile jint* dest) { jint addend = add_value; - __asm__ volatile ( LOCK_IF_MP(%3) "xaddl %0,(%2)" + __asm__ volatile ("lock xaddl %0,(%2)" : "=r" (addend) - : "0" (addend), "r" (dest), "r" (mp) + : "0" (addend), "r" (dest) : "cc", "memory"); return addend + add_value; } #ifdef AMD64 - inline jlong _Atomic_add_long(jlong add_value, volatile jlong* dest, int mp) { + inline jlong _Atomic_add_long(jlong add_value, volatile jlong* dest) { intptr_t addend = add_value; - __asm__ __volatile__ (LOCK_IF_MP(%3) "xaddq %0,(%2)" + __asm__ __volatile__ ("lock xaddq %0,(%2)" : "=r" (addend) - : "0" (addend), "r" (dest), "r" (mp) + : "0" (addend), "r" (dest) : "cc", "memory"); return addend + add_value; } @@ -215,35 +201,35 @@ return exchange_value; } - inline jint _Atomic_cmpxchg(jint exchange_value, volatile jint* dest, jint compare_value, int mp) { - __asm__ volatile (LOCK_IF_MP(%4) "cmpxchgl %1,(%3)" + inline jint _Atomic_cmpxchg(jint exchange_value, volatile jint* dest, jint compare_value) { + __asm__ volatile ("lock cmpxchgl %1,(%3)" : "=a" (exchange_value) - : "r" (exchange_value), "a" (compare_value), "r" (dest), "r" (mp) + : "r" (exchange_value), "a" (compare_value), "r" (dest) : "cc", "memory"); return exchange_value; } - inline jbyte _Atomic_cmpxchg_byte(jbyte exchange_value, volatile jbyte* dest, jbyte compare_value, int mp) { - __asm__ volatile (LOCK_IF_MP(%4) "cmpxchgb %1,(%3)" + inline jbyte _Atomic_cmpxchg_byte(jbyte exchange_value, volatile jbyte* dest, jbyte compare_value) { + __asm__ volatile ("lock cmpxchgb %1,(%3)" : "=a" (exchange_value) - : "q" (exchange_value), "a" (compare_value), "r" (dest), "r" (mp) + : "q" (exchange_value), "a" (compare_value), "r" (dest) : "cc", "memory"); return exchange_value; } // This is the interface to the atomic instruction in solaris_i486.s. - jlong _Atomic_cmpxchg_long_gcc(jlong exchange_value, volatile jlong* dest, jlong compare_value, int mp); + jlong _Atomic_cmpxchg_long_gcc(jlong exchange_value, volatile jlong* dest, jlong compare_value); - inline jlong _Atomic_cmpxchg_long(jlong exchange_value, volatile jlong* dest, jlong compare_value, int mp) { + inline jlong _Atomic_cmpxchg_long(jlong exchange_value, volatile jlong* dest, jlong compare_value) { #ifdef AMD64 - __asm__ __volatile__ (LOCK_IF_MP(%4) "cmpxchgq %1,(%3)" + __asm__ __volatile__ ("lock cmpxchgq %1,(%3)" : "=a" (exchange_value) - : "r" (exchange_value), "a" (compare_value), "r" (dest), "r" (mp) + : "r" (exchange_value), "a" (compare_value), "r" (dest) : "cc", "memory"); return exchange_value; #else - return _Atomic_cmpxchg_long_gcc(exchange_value, dest, compare_value, os::is_MP()); + return _Atomic_cmpxchg_long_gcc(exchange_value, dest, compare_value); #if 0 // The code below does not work presumably because of the bug in gcc @@ -255,23 +241,19 @@ volatile jlong_accessor evl, cvl, rv; evl.long_value = exchange_value; cvl.long_value = compare_value; - int mp = os::is_MP(); - __asm__ volatile ("cmp $0, %%esi\n\t" - "je 1f \n\t" - "lock\n\t" - "1: cmpxchg8b (%%edi)\n\t" + __asm__ volatile ( + "lock cmpxchg8b (%%edi)\n\t" : "=a"(cvl.words[0]), "=d"(cvl.words[1]) : "a"(cvl.words[0]), "d"(cvl.words[1]), "b"(evl.words[0]), "c"(evl.words[1]), - "D"(dest), "S"(mp) + "D"(dest) : "cc", "memory"); return cvl.long_value; #endif // if 0 #endif // AMD64 } } -#undef LOCK_IF_MP #endif // _GNU_SOURCE diff -r 2f733d553ca0 -r 02a1fc064144 hotspot/src/os_cpu/solaris_x86/vm/solaris_x86_32.il --- a/hotspot/src/os_cpu/solaris_x86/vm/solaris_x86_32.il Tue May 02 19:27:26 2017 -0700 +++ b/hotspot/src/os_cpu/solaris_x86/vm/solaris_x86_32.il Wed May 03 02:32:02 2017 +0000 @@ -1,5 +1,5 @@ // -// Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. // // This code is free software; you can redistribute it and/or modify it @@ -55,18 +55,12 @@ .end // Support for jint Atomic::add(jint inc, volatile jint* dest) - // An additional bool (os::is_MP()) is passed as the last argument. .inline _Atomic_add,3 movl 0(%esp), %eax // inc movl 4(%esp), %edx // dest movl %eax, %ecx - cmpl $0, 8(%esp) // MP test - jne 1f - xaddl %eax, (%edx) - jmp 2f -1: lock - xaddl %eax, (%edx) -2: addl %ecx, %eax + lock xaddl %eax, (%edx) + addl %ecx, %eax .end // Support for jint Atomic::xchg(jint exchange_value, volatile jint* dest). @@ -79,41 +73,26 @@ // Support for jbyte Atomic::cmpxchg(jbyte exchange_value, // volatile jbyte *dest, // jbyte compare_value) - // An additional bool (os::is_MP()) is passed as the last argument. .inline _Atomic_cmpxchg_byte,4 movb 8(%esp), %al // compare_value movb 0(%esp), %cl // exchange_value movl 4(%esp), %edx // dest - cmp $0, 12(%esp) // MP test - jne 1f - cmpxchgb %cl, (%edx) - jmp 2f -1: lock - cmpxchgb %cl, (%edx) -2: + lock cmpxchgb %cl, (%edx) .end // Support for jint Atomic::cmpxchg(jint exchange_value, // volatile jint *dest, // jint compare_value) - // An additional bool (os::is_MP()) is passed as the last argument. .inline _Atomic_cmpxchg,4 movl 8(%esp), %eax // compare_value movl 0(%esp), %ecx // exchange_value movl 4(%esp), %edx // dest - cmp $0, 12(%esp) // MP test - jne 1f - cmpxchgl %ecx, (%edx) - jmp 2f -1: lock - cmpxchgl %ecx, (%edx) -2: + lock cmpxchgl %ecx, (%edx) .end // Support for jlong Atomic::cmpxchg(jlong exchange_value, // volatile jlong* dest, // jlong compare_value) - // An additional bool (os::is_MP()) is passed as the last argument. .inline _Atomic_cmpxchg_long,6 pushl %ebx pushl %edi @@ -122,13 +101,8 @@ movl 16(%esp), %edi // dest movl 8(%esp), %ebx // exchange_value (low) movl 12(%esp), %ecx // exchange_high (high) - cmp $0, 28(%esp) // MP test - jne 1f - cmpxchg8b (%edi) - jmp 2f -1: lock - cmpxchg8b (%edi) -2: popl %edi + lock cmpxchg8b (%edi) + popl %edi popl %ebx .end diff -r 2f733d553ca0 -r 02a1fc064144 hotspot/src/os_cpu/solaris_x86/vm/solaris_x86_32.s --- a/hotspot/src/os_cpu/solaris_x86/vm/solaris_x86_32.s Tue May 02 19:27:26 2017 -0700 +++ b/hotspot/src/os_cpu/solaris_x86/vm/solaris_x86_32.s Wed May 03 02:32:02 2017 +0000 @@ -1,5 +1,5 @@ // -// Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 2004, 2017, Oracle and/or its affiliates. All rights reserved. // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. // // This code is free software; you can redistribute it and/or modify it @@ -643,8 +643,7 @@ / Support for jlong Atomic::cmpxchg(jlong exchange_value, / volatile jlong* dest, - / jlong compare_value, - / bool is_MP) + / jlong compare_value) / Used only for Solaris/gcc builds .align 16 _Atomic_cmpxchg_long_gcc: @@ -656,10 +655,7 @@ movl 24(%esp), %eax / 24(%esp) : compare_value (low) movl 28(%esp), %edx / 28(%esp) : compare_value (high) movl 20(%esp), %edi / 20(%esp) : dest - cmpl $0, 32(%esp) / 32(%esp) : is_MP - je 1f - lock -1: cmpxchg8b (%edi) + lock cmpxchg8b (%edi) popl %edi popl %ebx ret diff -r 2f733d553ca0 -r 02a1fc064144 hotspot/src/os_cpu/windows_x86/vm/atomic_windows_x86.hpp --- a/hotspot/src/os_cpu/windows_x86/vm/atomic_windows_x86.hpp Tue May 02 19:27:26 2017 -0700 +++ b/hotspot/src/os_cpu/windows_x86/vm/atomic_windows_x86.hpp Wed May 03 02:32:02 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -57,15 +57,6 @@ inline void Atomic::store_ptr(intptr_t store_value, volatile intptr_t* dest) { *dest = store_value; } inline void Atomic::store_ptr(void* store_value, volatile void* dest) { *(void* volatile *)dest = store_value; } -// Adding a lock prefix to an instruction on MP machine -// VC++ doesn't like the lock prefix to be on a single line -// so we can't insert a label after the lock prefix. -// By emitting a lock prefix, we can define a label after it. -#define LOCK_IF_MP(mp) __asm cmp mp, 0 \ - __asm je L0 \ - __asm _emit 0xF0 \ - __asm L0: - #ifdef AMD64 inline void Atomic::store (jlong store_value, jlong* dest) { *dest = store_value; } inline void Atomic::store (jlong store_value, volatile jlong* dest) { *dest = store_value; } @@ -144,13 +135,11 @@ #else // !AMD64 inline jint Atomic::add (jint add_value, volatile jint* dest) { - int mp = os::is_MP(); __asm { mov edx, dest; mov eax, add_value; mov ecx, eax; - LOCK_IF_MP(mp) - xadd dword ptr [edx], eax; + lock xadd dword ptr [edx], eax; add eax, ecx; } } @@ -165,11 +154,9 @@ inline void Atomic::inc (volatile jint* dest) { // alternative for InterlockedIncrement - int mp = os::is_MP(); __asm { mov edx, dest; - LOCK_IF_MP(mp) - add dword ptr [edx], 1; + lock add dword ptr [edx], 1; } } @@ -183,11 +170,9 @@ inline void Atomic::dec (volatile jint* dest) { // alternative for InterlockedDecrement - int mp = os::is_MP(); __asm { mov edx, dest; - LOCK_IF_MP(mp) - sub dword ptr [edx], 1; + lock sub dword ptr [edx], 1; } } @@ -219,30 +204,25 @@ #define VM_HAS_SPECIALIZED_CMPXCHG_BYTE inline jbyte Atomic::cmpxchg (jbyte exchange_value, volatile jbyte* dest, jbyte compare_value, cmpxchg_memory_order order) { // alternative for InterlockedCompareExchange - int mp = os::is_MP(); __asm { mov edx, dest mov cl, exchange_value mov al, compare_value - LOCK_IF_MP(mp) - cmpxchg byte ptr [edx], cl + lock cmpxchg byte ptr [edx], cl } } inline jint Atomic::cmpxchg (jint exchange_value, volatile jint* dest, jint compare_value, cmpxchg_memory_order order) { // alternative for InterlockedCompareExchange - int mp = os::is_MP(); __asm { mov edx, dest mov ecx, exchange_value mov eax, compare_value - LOCK_IF_MP(mp) - cmpxchg dword ptr [edx], ecx + lock cmpxchg dword ptr [edx], ecx } } inline jlong Atomic::cmpxchg (jlong exchange_value, volatile jlong* dest, jlong compare_value, cmpxchg_memory_order order) { - int mp = os::is_MP(); jint ex_lo = (jint)exchange_value; jint ex_hi = *( ((jint*)&exchange_value) + 1 ); jint cmp_lo = (jint)compare_value; @@ -255,8 +235,7 @@ mov edi, dest mov ebx, ex_lo mov ecx, ex_hi - LOCK_IF_MP(mp) - cmpxchg8b qword ptr [edi] + lock cmpxchg8b qword ptr [edi] pop edi pop ebx } diff -r 2f733d553ca0 -r 02a1fc064144 hotspot/src/share/vm/classfile/classLoaderData.cpp --- a/hotspot/src/share/vm/classfile/classLoaderData.cpp Tue May 02 19:27:26 2017 -0700 +++ b/hotspot/src/share/vm/classfile/classLoaderData.cpp Wed May 03 02:32:02 2017 +0000 @@ -102,6 +102,7 @@ // ModuleEntryTable or PackageEntryTable created for it. The defining package // and module for an anonymous class will be found in its host class. if (!is_anonymous) { + _packages = new PackageEntryTable(PackageEntryTable::_packagetable_entry_size); if (h_class_loader.is_null()) { // Create unnamed module for boot loader _unnamed_module = ModuleEntry::create_boot_unnamed_module(this); @@ -297,8 +298,8 @@ if (_modules != NULL) { for (int i = 0; i < _modules->table_size(); i++) { for (ModuleEntry* entry = _modules->bucket(i); - entry != NULL; - entry = entry->next()) { + entry != NULL; + entry = entry->next()) { f(entry); } } @@ -306,13 +307,12 @@ } void ClassLoaderData::packages_do(void f(PackageEntry*)) { - // Lock-free access requires load_ptr_acquire - PackageEntryTable* packages = load_ptr_acquire(&_packages); - if (packages != NULL) { - for (int i = 0; i < packages->table_size(); i++) { - for (PackageEntry* entry = packages->bucket(i); - entry != NULL; - entry = entry->next()) { + assert_locked_or_safepoint(Module_lock); + if (_packages != NULL) { + for (int i = 0; i < _packages->table_size(); i++) { + for (PackageEntry* entry = _packages->bucket(i); + entry != NULL; + entry = entry->next()) { f(entry); } } @@ -494,22 +494,6 @@ free_deallocate_list(); } -PackageEntryTable* ClassLoaderData::packages() { - // Lazily create the package entry table at first request. - // Lock-free access requires load_ptr_acquire. - PackageEntryTable* packages = load_ptr_acquire(&_packages); - if (packages == NULL) { - MutexLockerEx m1(metaspace_lock(), Mutex::_no_safepoint_check_flag); - // Check if _packages got allocated while we were waiting for this lock. - if ((packages = _packages) == NULL) { - packages = new PackageEntryTable(PackageEntryTable::_packagetable_entry_size); - // Ensure _packages is stable, since it is examined without a lock - OrderAccess::release_store_ptr(&_packages, packages); - } - } - return packages; -} - ModuleEntryTable* ClassLoaderData::modules() { // Lazily create the module entry table at first request. // Lock-free access requires load_ptr_acquire. @@ -1096,7 +1080,7 @@ // occur after each class loader's aliveness is determined. data = _head; while (data != NULL) { - if (data->packages_defined()) { + if (data->packages() != NULL) { data->packages()->purge_all_package_exports(); } if (data->modules_defined()) { diff -r 2f733d553ca0 -r 02a1fc064144 hotspot/src/share/vm/classfile/classLoaderData.hpp --- a/hotspot/src/share/vm/classfile/classLoaderData.hpp Tue May 02 19:27:26 2017 -0700 +++ b/hotspot/src/share/vm/classfile/classLoaderData.hpp Wed May 03 02:32:02 2017 +0000 @@ -347,8 +347,7 @@ bool contains_klass(Klass* k); void record_dependency(const Klass* to, TRAPS); void init_dependencies(TRAPS); - PackageEntryTable* packages(); - bool packages_defined() { return (_packages != NULL); } + PackageEntryTable* packages() { return _packages; } ModuleEntry* unnamed_module() { return _unnamed_module; } ModuleEntryTable* modules(); bool modules_defined() { return (_modules != NULL); } diff -r 2f733d553ca0 -r 02a1fc064144 hotspot/src/share/vm/classfile/packageEntry.cpp --- a/hotspot/src/share/vm/classfile/packageEntry.cpp Tue May 02 19:27:26 2017 -0700 +++ b/hotspot/src/share/vm/classfile/packageEntry.cpp Wed May 03 02:32:02 2017 +0000 @@ -174,8 +174,6 @@ } PackageEntryTable::~PackageEntryTable() { - assert_locked_or_safepoint(Module_lock); - // Walk through all buckets and all entries in each bucket, // freeing each entry. for (int i = 0; i < table_size(); ++i) { @@ -271,6 +269,7 @@ // Called when a define module for java.base is being processed. // Verify the packages loaded thus far are in java.base's package list. void PackageEntryTable::verify_javabase_packages(GrowableArray *pkg_list) { + assert_lock_strong(Module_lock); for (int i = 0; i < table_size(); i++) { for (PackageEntry* entry = bucket(i); entry != NULL; diff -r 2f733d553ca0 -r 02a1fc064144 hotspot/src/share/vm/code/vtableStubs.cpp --- a/hotspot/src/share/vm/code/vtableStubs.cpp Tue May 02 19:27:26 2017 -0700 +++ b/hotspot/src/share/vm/code/vtableStubs.cpp Wed May 03 02:32:02 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -218,11 +218,11 @@ HandleMark hm; Klass* klass = receiver->klass(); InstanceKlass* ik = InstanceKlass::cast(klass); - klassVtable* vt = ik->vtable(); + klassVtable vt = ik->vtable(); ik->print(); fatal("bad compiled vtable dispatch: receiver " INTPTR_FORMAT ", " "index %d (vtable length %d)", - p2i(receiver), index, vt->length()); + p2i(receiver), index, vt.length()); } #endif // PRODUCT diff -r 2f733d553ca0 -r 02a1fc064144 hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp --- a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp Tue May 02 19:27:26 2017 -0700 +++ b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp Wed May 03 02:32:02 2017 +0000 @@ -923,8 +923,6 @@ double end_vtime_sec = os::elapsedVTime(); double elapsed_vtime_sec = end_vtime_sec - start_vtime_sec; - _cm->clear_has_overflown(); - _cm->do_yield_check(); jlong sleep_time_ms; diff -r 2f733d553ca0 -r 02a1fc064144 hotspot/src/share/vm/gc/serial/markSweep.cpp --- a/hotspot/src/share/vm/gc/serial/markSweep.cpp Tue May 02 19:27:26 2017 -0700 +++ b/hotspot/src/share/vm/gc/serial/markSweep.cpp Wed May 03 02:32:02 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -224,12 +224,12 @@ mark_and_push_closure.set_ref_processor(_ref_processor); } -MarkSweep::AdjustPointerClosure MarkSweep::adjust_pointer_closure; +AdjustPointerClosure MarkSweep::adjust_pointer_closure; template -void MarkSweep::AdjustPointerClosure::do_oop_nv(T* p) { adjust_pointer(p); } -void MarkSweep::AdjustPointerClosure::do_oop(oop* p) { do_oop_nv(p); } -void MarkSweep::AdjustPointerClosure::do_oop(narrowOop* p) { do_oop_nv(p); } +void AdjustPointerClosure::do_oop_nv(T* p) { MarkSweep::adjust_pointer(p); } +void AdjustPointerClosure::do_oop(oop* p) { do_oop_nv(p); } +void AdjustPointerClosure::do_oop(narrowOop* p) { do_oop_nv(p); } void MarkSweep::adjust_marks() { assert( _preserved_oop_stack.size() == _preserved_mark_stack.size(), @@ -280,79 +280,5 @@ MarkSweep::_gc_tracer = new (ResourceObj::C_HEAP, mtGC) SerialOldTracer(); } -int InstanceKlass::oop_ms_adjust_pointers(oop obj) { - int size = size_helper(); - oop_oop_iterate_oop_maps(obj, &MarkSweep::adjust_pointer_closure); - return size; -} - -int InstanceMirrorKlass::oop_ms_adjust_pointers(oop obj) { - int size = oop_size(obj); - InstanceKlass::oop_ms_adjust_pointers(obj); - - oop_oop_iterate_statics(obj, &MarkSweep::adjust_pointer_closure); - return size; -} - -int InstanceClassLoaderKlass::oop_ms_adjust_pointers(oop obj) { - return InstanceKlass::oop_ms_adjust_pointers(obj); -} - -#ifdef ASSERT -template static void trace_reference_gc(const char *s, oop obj, - T* referent_addr, - T* next_addr, - T* discovered_addr) { - log_develop_trace(gc, ref)("%s obj " PTR_FORMAT, s, p2i(obj)); - log_develop_trace(gc, ref)(" referent_addr/* " PTR_FORMAT " / " PTR_FORMAT, - p2i(referent_addr), p2i(referent_addr ? (address)oopDesc::load_decode_heap_oop(referent_addr) : NULL)); - log_develop_trace(gc, ref)(" next_addr/* " PTR_FORMAT " / " PTR_FORMAT, - p2i(next_addr), p2i(next_addr ? (address)oopDesc::load_decode_heap_oop(next_addr) : NULL)); - log_develop_trace(gc, ref)(" discovered_addr/* " PTR_FORMAT " / " PTR_FORMAT, - p2i(discovered_addr), p2i(discovered_addr ? (address)oopDesc::load_decode_heap_oop(discovered_addr) : NULL)); -} -#endif - -template void static adjust_object_specialized(oop obj) { - T* referent_addr = (T*)java_lang_ref_Reference::referent_addr(obj); - MarkSweep::adjust_pointer(referent_addr); - T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj); - MarkSweep::adjust_pointer(next_addr); - T* discovered_addr = (T*)java_lang_ref_Reference::discovered_addr(obj); - MarkSweep::adjust_pointer(discovered_addr); - debug_only(trace_reference_gc("InstanceRefKlass::oop_ms_adjust_pointers", obj, - referent_addr, next_addr, discovered_addr);) -} - -int InstanceRefKlass::oop_ms_adjust_pointers(oop obj) { - int size = size_helper(); - InstanceKlass::oop_ms_adjust_pointers(obj); - - if (UseCompressedOops) { - adjust_object_specialized(obj); - } else { - adjust_object_specialized(obj); - } - return size; -} - -int ObjArrayKlass::oop_ms_adjust_pointers(oop obj) { - assert(obj->is_objArray(), "obj must be obj array"); - objArrayOop a = objArrayOop(obj); - // Get size before changing pointers. - // Don't call size() or oop_size() since that is a virtual call. - int size = a->object_size(); - oop_oop_iterate_elements(a, &MarkSweep::adjust_pointer_closure); - return size; -} - -int TypeArrayKlass::oop_ms_adjust_pointers(oop obj) { - assert(obj->is_typeArray(), "must be a type array"); - typeArrayOop t = typeArrayOop(obj); - // Performance tweak: We skip iterating over the klass pointer since we - // know that Universe::TypeArrayKlass never moves. - return t->object_size(); -} - // Generate MS specialized oop_oop_iterate functions. SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_MS(ALL_KLASS_OOP_OOP_ITERATE_DEFN) diff -r 2f733d553ca0 -r 02a1fc064144 hotspot/src/share/vm/gc/serial/markSweep.hpp --- a/hotspot/src/share/vm/gc/serial/markSweep.hpp Tue May 02 19:27:26 2017 -0700 +++ b/hotspot/src/share/vm/gc/serial/markSweep.hpp Wed May 03 02:32:02 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,6 +50,7 @@ // declared at end class PreservedMark; class MarkAndPushClosure; +class AdjustPointerClosure; class MarkSweep : AllStatic { // @@ -66,16 +67,6 @@ virtual void do_void(); }; - class AdjustPointerClosure: public OopsInGenClosure { - public: - template void do_oop_nv(T* p); - virtual void do_oop(oop* p); - virtual void do_oop(narrowOop* p); - - // This closure provides its own oop verification code. - debug_only(virtual bool should_verify_oops() { return false; }) - }; - // Used for java/lang/ref handling class IsAliveClosure: public BoolObjectClosure { public: @@ -201,6 +192,17 @@ } }; +class AdjustPointerClosure: public OopsInGenClosure { + public: + template void do_oop_nv(T* p); + virtual void do_oop(oop* p); + virtual void do_oop(narrowOop* p); + virtual ReferenceIterationMode reference_iteration_mode() { return DO_FIELDS; } + + // This closure provides its own oop verification code. + debug_only(virtual bool should_verify_oops() { return false; }) +}; + class PreservedMark VALUE_OBJ_CLASS_SPEC { private: oop _obj; diff -r 2f733d553ca0 -r 02a1fc064144 hotspot/src/share/vm/gc/serial/markSweep.inline.hpp --- a/hotspot/src/share/vm/gc/serial/markSweep.inline.hpp Tue May 02 19:27:26 2017 -0700 +++ b/hotspot/src/share/vm/gc/serial/markSweep.inline.hpp Wed May 03 02:32:02 2017 +0000 @@ -42,7 +42,7 @@ } inline int MarkSweep::adjust_pointers(oop obj) { - return obj->ms_adjust_pointers(); + return obj->oop_iterate_size(&MarkSweep::adjust_pointer_closure); } template inline void MarkSweep::adjust_pointer(T* p) { diff -r 2f733d553ca0 -r 02a1fc064144 hotspot/src/share/vm/gc/shared/specialized_oop_closures.hpp --- a/hotspot/src/share/vm/gc/shared/specialized_oop_closures.hpp Tue May 02 19:27:26 2017 -0700 +++ b/hotspot/src/share/vm/gc/shared/specialized_oop_closures.hpp Wed May 03 02:32:02 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,6 +44,7 @@ class FilteringClosure; // MarkSweep class MarkAndPushClosure; +class AdjustPointerClosure; // ParNew class ParScanWithBarrierClosure; class ParScanWithoutBarrierClosure; @@ -90,7 +91,8 @@ SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_P(f) #define SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_MS(f) \ - f(MarkAndPushClosure,_nv) + f(MarkAndPushClosure,_nv) \ + f(AdjustPointerClosure,_nv) #if INCLUDE_ALL_GCS #define SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_CMS(f) \ diff -r 2f733d553ca0 -r 02a1fc064144 hotspot/src/share/vm/interpreter/interpreterRuntime.cpp --- a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp Tue May 02 19:27:26 2017 -0700 +++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp Wed May 03 02:32:02 2017 +0000 @@ -86,14 +86,15 @@ // State accessors void InterpreterRuntime::set_bcp_and_mdp(address bcp, JavaThread *thread) { - last_frame(thread).interpreter_frame_set_bcp(bcp); + LastFrameAccessor last_frame(thread); + last_frame.set_bcp(bcp); if (ProfileInterpreter) { // ProfileTraps uses MDOs independently of ProfileInterpreter. // That is why we must check both ProfileInterpreter and mdo != NULL. - MethodData* mdo = last_frame(thread).interpreter_frame_method()->method_data(); + MethodData* mdo = last_frame.method()->method_data(); if (mdo != NULL) { NEEDS_CLEANUP; - last_frame(thread).interpreter_frame_set_mdp(mdo->bci_to_dp(last_frame(thread).interpreter_frame_bci())); + last_frame.set_mdp(mdo->bci_to_dp(last_frame.bci())); } } } @@ -104,8 +105,9 @@ IRT_ENTRY(void, InterpreterRuntime::ldc(JavaThread* thread, bool wide)) // access constant pool - ConstantPool* pool = method(thread)->constants(); - int index = wide ? get_index_u2(thread, Bytecodes::_ldc_w) : get_index_u1(thread, Bytecodes::_ldc); + LastFrameAccessor last_frame(thread); + ConstantPool* pool = last_frame.method()->constants(); + int index = wide ? last_frame.get_index_u2(Bytecodes::_ldc_w) : last_frame.get_index_u1(Bytecodes::_ldc); constantTag tag = pool->tag_at(index); assert (tag.is_unresolved_klass() || tag.is_klass(), "wrong ldc call"); @@ -118,13 +120,14 @@ assert(bytecode == Bytecodes::_fast_aldc || bytecode == Bytecodes::_fast_aldc_w, "wrong bc"); ResourceMark rm(thread); - methodHandle m (thread, method(thread)); - Bytecode_loadconstant ldc(m, bci(thread)); + LastFrameAccessor last_frame(thread); + methodHandle m (thread, last_frame.method()); + Bytecode_loadconstant ldc(m, last_frame.bci()); oop result = ldc.resolve_constant(CHECK); #ifdef ASSERT { // The bytecode wrappers aren't GC-safe so construct a new one - Bytecode_loadconstant ldc2(m, bci(thread)); + Bytecode_loadconstant ldc2(m, last_frame.bci()); oop coop = m->constants()->resolved_references()->obj_at(ldc2.cache_index()); assert(result == coop, "expected result for assembly code"); } @@ -181,10 +184,11 @@ IRT_ENTRY(void, InterpreterRuntime::multianewarray(JavaThread* thread, jint* first_size_address)) // We may want to pass in more arguments - could make this slightly faster - ConstantPool* constants = method(thread)->constants(); - int i = get_index_u2(thread, Bytecodes::_multianewarray); - Klass* klass = constants->klass_at(i, CHECK); - int nof_dims = number_of_dimensions(thread); + LastFrameAccessor last_frame(thread); + ConstantPool* constants = last_frame.method()->constants(); + int i = last_frame.get_index_u2(Bytecodes::_multianewarray); + Klass* klass = constants->klass_at(i, CHECK); + int nof_dims = last_frame.number_of_dimensions(); assert(klass->is_klass(), "not a class"); assert(nof_dims >= 1, "multianewarray rank must be nonzero"); @@ -216,8 +220,9 @@ // Quicken instance-of and check-cast bytecodes IRT_ENTRY(void, InterpreterRuntime::quicken_io_cc(JavaThread* thread)) // Force resolving; quicken the bytecode - int which = get_index_u2(thread, Bytecodes::_checkcast); - ConstantPool* cpool = method(thread)->constants(); + LastFrameAccessor last_frame(thread); + int which = last_frame.get_index_u2(Bytecodes::_checkcast); + ConstantPool* cpool = last_frame.method()->constants(); // We'd expect to assert that we're only here to quicken bytecodes, but in a multithreaded // program we might have seen an unquick'd bytecode in the interpreter but have another // thread quicken the bytecode before we get here. @@ -256,8 +261,9 @@ // If necessary, create an MDO to hold the information, and record it. void InterpreterRuntime::note_trap(JavaThread* thread, int reason, TRAPS) { assert(ProfileTraps, "call me only if profiling"); - methodHandle trap_method(thread, method(thread)); - int trap_bci = trap_method->bci_from(bcp(thread)); + LastFrameAccessor last_frame(thread); + methodHandle trap_method(thread, last_frame.method()); + int trap_bci = trap_method->bci_from(last_frame.bcp()); note_trap_inner(thread, reason, trap_method, trap_bci, THREAD); } @@ -390,12 +396,13 @@ // invoke w/o arguments (i.e., as if one were inside the call). IRT_ENTRY(address, InterpreterRuntime::exception_handler_for_exception(JavaThread* thread, oopDesc* exception)) + LastFrameAccessor last_frame(thread); Handle h_exception(thread, exception); - methodHandle h_method (thread, method(thread)); + methodHandle h_method (thread, last_frame.method()); constantPoolHandle h_constants(thread, h_method->constants()); bool should_repeat; int handler_bci; - int current_bci = bci(thread); + int current_bci = last_frame.bci(); if (thread->frames_to_pop_failed_realloc() > 0) { // Allocation of scalar replaced object used in this frame @@ -493,7 +500,7 @@ // notify JVMTI of an exception throw; JVMTI will detect if this is a first // time throw or a stack unwinding throw and accordingly notify the debugger if (JvmtiExport::can_post_on_exceptions()) { - JvmtiExport::post_exception_throw(thread, h_method(), bcp(thread), h_exception()); + JvmtiExport::post_exception_throw(thread, h_method(), last_frame.bcp(), h_exception()); } #ifdef CC_INTERP @@ -556,20 +563,21 @@ Thread* THREAD = thread; // resolve field fieldDescriptor info; - constantPoolHandle pool(thread, method(thread)->constants()); - methodHandle m(thread, method(thread)); + LastFrameAccessor last_frame(thread); + constantPoolHandle pool(thread, last_frame.method()->constants()); + methodHandle m(thread, last_frame.method()); bool is_put = (bytecode == Bytecodes::_putfield || bytecode == Bytecodes::_nofast_putfield || bytecode == Bytecodes::_putstatic); bool is_static = (bytecode == Bytecodes::_getstatic || bytecode == Bytecodes::_putstatic); { JvmtiHideSingleStepping jhss(thread); - LinkResolver::resolve_field_access(info, pool, get_index_u2_cpcache(thread, bytecode), + LinkResolver::resolve_field_access(info, pool, last_frame.get_index_u2_cpcache(bytecode), m, bytecode, CHECK); } // end JvmtiHideSingleStepping // check if link resolution caused cpCache to be updated - ConstantPoolCacheEntry* cp_cache_entry = cache_entry(thread); + ConstantPoolCacheEntry* cp_cache_entry = last_frame.cache_entry(); if (cp_cache_entry->is_resolved(bytecode)) return; // compute auxiliary field attributes @@ -718,15 +726,15 @@ void InterpreterRuntime::resolve_invoke(JavaThread* thread, Bytecodes::Code bytecode) { Thread* THREAD = thread; + LastFrameAccessor last_frame(thread); // extract receiver from the outgoing argument list if necessary Handle receiver(thread, NULL); if (bytecode == Bytecodes::_invokevirtual || bytecode == Bytecodes::_invokeinterface) { ResourceMark rm(thread); - methodHandle m (thread, method(thread)); - Bytecode_invoke call(m, bci(thread)); + methodHandle m (thread, last_frame.method()); + Bytecode_invoke call(m, last_frame.bci()); Symbol* signature = call.signature(); - receiver = Handle(thread, - thread->last_frame().interpreter_callee_receiver(signature)); + receiver = Handle(thread, last_frame.callee_receiver(signature)); assert(Universe::heap()->is_in_reserved_or_null(receiver()), "sanity check"); assert(receiver.is_null() || @@ -736,12 +744,12 @@ // resolve method CallInfo info; - constantPoolHandle pool(thread, method(thread)->constants()); + constantPoolHandle pool(thread, last_frame.method()->constants()); { JvmtiHideSingleStepping jhss(thread); LinkResolver::resolve_invoke(info, receiver, pool, - get_index_u2_cpcache(thread, bytecode), bytecode, + last_frame.get_index_u2_cpcache(bytecode), bytecode, CHECK); if (JvmtiExport::can_hotswap_or_post_breakpoint()) { int retry_count = 0; @@ -753,14 +761,14 @@ "Could not resolve to latest version of redefined method"); // method is redefined in the middle of resolve so re-try. LinkResolver::resolve_invoke(info, receiver, pool, - get_index_u2_cpcache(thread, bytecode), bytecode, + last_frame.get_index_u2_cpcache(bytecode), bytecode, CHECK); } } } // end JvmtiHideSingleStepping // check if link resolution caused cpCache to be updated - ConstantPoolCacheEntry* cp_cache_entry = cache_entry(thread); + ConstantPoolCacheEntry* cp_cache_entry = last_frame.cache_entry(); if (cp_cache_entry->is_resolved(bytecode)) return; #ifdef ASSERT @@ -815,33 +823,35 @@ void InterpreterRuntime::resolve_invokehandle(JavaThread* thread) { Thread* THREAD = thread; const Bytecodes::Code bytecode = Bytecodes::_invokehandle; + LastFrameAccessor last_frame(thread); // resolve method CallInfo info; - constantPoolHandle pool(thread, method(thread)->constants()); + constantPoolHandle pool(thread, last_frame.method()->constants()); { JvmtiHideSingleStepping jhss(thread); LinkResolver::resolve_invoke(info, Handle(), pool, - get_index_u2_cpcache(thread, bytecode), bytecode, + last_frame.get_index_u2_cpcache(bytecode), bytecode, CHECK); } // end JvmtiHideSingleStepping - ConstantPoolCacheEntry* cp_cache_entry = cache_entry(thread); + ConstantPoolCacheEntry* cp_cache_entry = last_frame.cache_entry(); cp_cache_entry->set_method_handle(pool, info); } // First time execution: Resolve symbols, create a permanent CallSite object. void InterpreterRuntime::resolve_invokedynamic(JavaThread* thread) { Thread* THREAD = thread; + LastFrameAccessor last_frame(thread); const Bytecodes::Code bytecode = Bytecodes::_invokedynamic; //TO DO: consider passing BCI to Java. - // int caller_bci = method(thread)->bci_from(bcp(thread)); + // int caller_bci = last_frame.method()->bci_from(last_frame.bcp()); // resolve method CallInfo info; - constantPoolHandle pool(thread, method(thread)->constants()); - int index = get_index_u4(thread, bytecode); + constantPoolHandle pool(thread, last_frame.method()->constants()); + int index = last_frame.get_index_u4(bytecode); { JvmtiHideSingleStepping jhss(thread); LinkResolver::resolve_invoke(info, Handle(), pool, @@ -895,9 +905,9 @@ // nm could have been unloaded so look it up again. It's unsafe // to examine nm directly since it might have been freed and used // for something else. - frame fr = thread->last_frame(); - Method* method = fr.interpreter_frame_method(); - int bci = method->bci_from(fr.interpreter_frame_bcp()); + LastFrameAccessor last_frame(thread); + Method* method = last_frame.method(); + int bci = method->bci_from(last_frame.bcp()); nm = method->lookup_osr_nmethod_for(bci, CompLevel_none, false); } #ifndef PRODUCT @@ -917,11 +927,11 @@ // flag, in case this method triggers classloading which will call into Java. UnlockFlagSaver fs(thread); - frame fr = thread->last_frame(); - assert(fr.is_interpreted_frame(), "must come from interpreter"); - methodHandle method(thread, fr.interpreter_frame_method()); + LastFrameAccessor last_frame(thread); + assert(last_frame.is_interpreted_frame(), "must come from interpreter"); + methodHandle method(thread, last_frame.method()); const int branch_bci = branch_bcp != NULL ? method->bci_from(branch_bcp) : InvocationEntryBci; - const int bci = branch_bcp != NULL ? method->bci_from(fr.interpreter_frame_bcp()) : InvocationEntryBci; + const int bci = branch_bcp != NULL ? method->bci_from(last_frame.bcp()) : InvocationEntryBci; assert(!HAS_PENDING_EXCEPTION, "Should not have any exceptions pending"); nmethod* osr_nm = CompilationPolicy::policy()->event(method, method, branch_bci, bci, CompLevel_none, NULL, thread); @@ -937,9 +947,9 @@ if (UseBiasedLocking) { ResourceMark rm; GrowableArray* objects_to_revoke = new GrowableArray(); - for( BasicObjectLock *kptr = fr.interpreter_frame_monitor_end(); - kptr < fr.interpreter_frame_monitor_begin(); - kptr = fr.next_monitor_in_interpreter_frame(kptr) ) { + for( BasicObjectLock *kptr = last_frame.monitor_end(); + kptr < last_frame.monitor_begin(); + kptr = last_frame.next_monitor(kptr) ) { if( kptr->obj() != NULL ) { objects_to_revoke->append(Handle(THREAD, kptr->obj())); } @@ -964,9 +974,9 @@ UnlockFlagSaver fs(thread); assert(ProfileInterpreter, "must be profiling interpreter"); - frame fr = thread->last_frame(); - assert(fr.is_interpreted_frame(), "must come from interpreter"); - methodHandle method(thread, fr.interpreter_frame_method()); + LastFrameAccessor last_frame(thread); + assert(last_frame.is_interpreted_frame(), "must come from interpreter"); + methodHandle method(thread, last_frame.method()); Method::build_interpreter_method_data(method, THREAD); if (HAS_PENDING_EXCEPTION) { assert((PENDING_EXCEPTION->is_a(SystemDictionary::OutOfMemoryError_klass())), "we expect only an OOM error here"); @@ -1011,9 +1021,9 @@ assert(ProfileInterpreter, "must be profiling interpreter"); ResourceMark rm(thread); HandleMark hm(thread); - frame fr = thread->last_frame(); - assert(fr.is_interpreted_frame(), "must come from interpreter"); - MethodData* h_mdo = fr.interpreter_frame_method()->method_data(); + LastFrameAccessor last_frame(thread); + assert(last_frame.is_interpreted_frame(), "must come from interpreter"); + MethodData* h_mdo = last_frame.method()->method_data(); // Grab a lock to ensure atomic access to setting the return bci and // the displacement. This can block and GC, invalidating all naked oops. @@ -1021,10 +1031,10 @@ // ProfileData is essentially a wrapper around a derived oop, so we // need to take the lock before making any ProfileData structures. - ProfileData* data = h_mdo->data_at(h_mdo->dp_to_di(fr.interpreter_frame_mdp())); + ProfileData* data = h_mdo->data_at(h_mdo->dp_to_di(last_frame.mdp())); RetData* rdata = data->as_RetData(); address new_mdp = rdata->fixup_ret(return_bci, h_mdo); - fr.interpreter_frame_set_mdp(new_mdp); + last_frame.set_mdp(new_mdp); IRT_END IRT_ENTRY(MethodCounters*, InterpreterRuntime::build_method_counters(JavaThread* thread, Method* m)) @@ -1049,7 +1059,8 @@ // We are called during regular safepoints and when the VM is // single stepping. If any thread is marked for single stepping, // then we may have JVMTI work to do. - JvmtiExport::at_single_stepping_point(thread, method(thread), bcp(thread)); + LastFrameAccessor last_frame(thread); + JvmtiExport::at_single_stepping_point(thread, last_frame.method(), last_frame.bcp()); } IRT_END @@ -1072,7 +1083,8 @@ } InstanceKlass* cp_entry_f1 = InstanceKlass::cast(cp_entry->f1_as_klass()); jfieldID fid = jfieldIDWorkaround::to_jfieldID(cp_entry_f1, cp_entry->f2_as_index(), is_static); - JvmtiExport::post_field_access(thread, method(thread), bcp(thread), cp_entry_f1, h_obj, fid); + LastFrameAccessor last_frame(thread); + JvmtiExport::post_field_access(thread, last_frame.method(), last_frame.bcp(), cp_entry_f1, h_obj, fid); IRT_END IRT_ENTRY(void, InterpreterRuntime::post_field_modification(JavaThread *thread, @@ -1127,17 +1139,20 @@ h_obj = Handle(thread, obj); } - JvmtiExport::post_raw_field_modification(thread, method(thread), bcp(thread), ik, h_obj, + LastFrameAccessor last_frame(thread); + JvmtiExport::post_raw_field_modification(thread, last_frame.method(), last_frame.bcp(), ik, h_obj, fid, sig_type, &fvalue); IRT_END IRT_ENTRY(void, InterpreterRuntime::post_method_entry(JavaThread *thread)) - JvmtiExport::post_method_entry(thread, InterpreterRuntime::method(thread), InterpreterRuntime::last_frame(thread)); + LastFrameAccessor last_frame(thread); + JvmtiExport::post_method_entry(thread, last_frame.method(), last_frame.get_frame()); IRT_END IRT_ENTRY(void, InterpreterRuntime::post_method_exit(JavaThread *thread)) - JvmtiExport::post_method_exit(thread, InterpreterRuntime::method(thread), InterpreterRuntime::last_frame(thread)); + LastFrameAccessor last_frame(thread); + JvmtiExport::post_method_exit(thread, last_frame.method(), last_frame.get_frame()); IRT_END IRT_LEAF(int, InterpreterRuntime::interpreter_contains(address pc)) @@ -1362,10 +1377,10 @@ ResetNoHandleMark rnm; // In a LEAF entry. HandleMark hm; ResourceMark rm; - frame fr = thread->last_frame(); - assert(fr.is_interpreted_frame(), ""); - jint bci = fr.interpreter_frame_bci(); - methodHandle mh(thread, fr.interpreter_frame_method()); + LastFrameAccessor last_frame(thread); + assert(last_frame.is_interpreted_frame(), ""); + jint bci = last_frame.bci(); + methodHandle mh(thread, last_frame.method()); Bytecode_invoke invoke(mh, bci); ArgumentSizeComputer asc(invoke.signature()); int size_of_arguments = (asc.size() + (invoke.has_receiver() ? 1 : 0)); // receiver @@ -1411,10 +1426,10 @@ // The generated code still uses call_VM because that will set up the frame pointer for // bcp and method. IRT_LEAF(intptr_t, InterpreterRuntime::trace_bytecode(JavaThread* thread, intptr_t preserve_this_value, intptr_t tos, intptr_t tos2)) - const frame f = thread->last_frame(); - assert(f.is_interpreted_frame(), "must be an interpreted frame"); - methodHandle mh(thread, f.interpreter_frame_method()); - BytecodeTracer::trace(mh, f.interpreter_frame_bcp(), tos, tos2); + LastFrameAccessor last_frame(thread); + assert(last_frame.is_interpreted_frame(), "must be an interpreted frame"); + methodHandle mh(thread, last_frame.method()); + BytecodeTracer::trace(mh, last_frame.bcp(), tos, tos2); return preserve_this_value; IRT_END #endif // !PRODUCT diff -r 2f733d553ca0 -r 02a1fc064144 hotspot/src/share/vm/interpreter/interpreterRuntime.hpp --- a/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp Tue May 02 19:27:26 2017 -0700 +++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp Wed May 03 02:32:02 2017 +0000 @@ -42,29 +42,54 @@ friend class PrintingClosure; // for method and bcp private: - // Helper functions to access current interpreter state - static frame last_frame(JavaThread *thread) { return thread->last_frame(); } - static Method* method(JavaThread *thread) { return last_frame(thread).interpreter_frame_method(); } - static address bcp(JavaThread *thread) { return last_frame(thread).interpreter_frame_bcp(); } - static int bci(JavaThread *thread) { return last_frame(thread).interpreter_frame_bci(); } - static void set_bcp_and_mdp(address bcp, JavaThread*thread); - static Bytecodes::Code code(JavaThread *thread) { + // Helper class to access current interpreter state + class LastFrameAccessor : public StackObj { + frame _last_frame; + public: + LastFrameAccessor(JavaThread* thread) { + assert(thread == Thread::current(), "sanity"); + _last_frame = thread->last_frame(); + } + bool is_interpreted_frame() const { return _last_frame.is_interpreted_frame(); } + Method* method() const { return _last_frame.interpreter_frame_method(); } + address bcp() const { return _last_frame.interpreter_frame_bcp(); } + int bci() const { return _last_frame.interpreter_frame_bci(); } + address mdp() const { return _last_frame.interpreter_frame_mdp(); } + + void set_bcp(address bcp) { _last_frame.interpreter_frame_set_bcp(bcp); } + void set_mdp(address dp) { _last_frame.interpreter_frame_set_mdp(dp); } + // pass method to avoid calling unsafe bcp_to_method (partial fix 4926272) - return Bytecodes::code_at(method(thread), bcp(thread)); - } - static Bytecode bytecode(JavaThread *thread) { return Bytecode(method(thread), bcp(thread)); } - static int get_index_u1(JavaThread *thread, Bytecodes::Code bc) - { return bytecode(thread).get_index_u1(bc); } - static int get_index_u2(JavaThread *thread, Bytecodes::Code bc) - { return bytecode(thread).get_index_u2(bc); } - static int get_index_u2_cpcache(JavaThread *thread, Bytecodes::Code bc) - { return bytecode(thread).get_index_u2_cpcache(bc); } - static int get_index_u4(JavaThread *thread, Bytecodes::Code bc) - { return bytecode(thread).get_index_u4(bc); } - static int number_of_dimensions(JavaThread *thread) { return bcp(thread)[3]; } + Bytecodes::Code code() const { return Bytecodes::code_at(method(), bcp()); } + + Bytecode bytecode() const { return Bytecode(method(), bcp()); } + int get_index_u1(Bytecodes::Code bc) const { return bytecode().get_index_u1(bc); } + int get_index_u2(Bytecodes::Code bc) const { return bytecode().get_index_u2(bc); } + int get_index_u2_cpcache(Bytecodes::Code bc) const + { return bytecode().get_index_u2_cpcache(bc); } + int get_index_u4(Bytecodes::Code bc) const { return bytecode().get_index_u4(bc); } + int number_of_dimensions() const { return bcp()[3]; } + ConstantPoolCacheEntry* cache_entry_at(int i) const + { return method()->constants()->cache()->entry_at(i); } + ConstantPoolCacheEntry* cache_entry() const { return cache_entry_at(Bytes::get_native_u2(bcp() + 1)); } - static ConstantPoolCacheEntry* cache_entry_at(JavaThread *thread, int i) { return method(thread)->constants()->cache()->entry_at(i); } - static ConstantPoolCacheEntry* cache_entry(JavaThread *thread) { return cache_entry_at(thread, Bytes::get_native_u2(bcp(thread) + 1)); } + oop callee_receiver(Symbol* signature) { + return _last_frame.interpreter_callee_receiver(signature); + } + BasicObjectLock* monitor_begin() const { + return _last_frame.interpreter_frame_monitor_end(); + } + BasicObjectLock* monitor_end() const { + return _last_frame.interpreter_frame_monitor_begin(); + } + BasicObjectLock* next_monitor(BasicObjectLock* current) const { + return _last_frame.next_monitor_in_interpreter_frame(current); + } + + frame& get_frame() { return _last_frame; } + }; + + static void set_bcp_and_mdp(address bcp, JavaThread*thread); static void note_trap_inner(JavaThread* thread, int reason, methodHandle trap_method, int trap_bci, TRAPS); static void note_trap(JavaThread *thread, int reason, TRAPS); @@ -139,7 +164,7 @@ static void _breakpoint(JavaThread* thread, Method* method, address bcp); static Bytecodes::Code get_original_bytecode_at(JavaThread* thread, Method* method, address bcp); static void set_original_bytecode_at(JavaThread* thread, Method* method, address bcp, Bytecodes::Code new_code); - static bool is_breakpoint(JavaThread *thread) { return Bytecodes::code_or_bp_at(bcp(thread)) == Bytecodes::_breakpoint; } + static bool is_breakpoint(JavaThread *thread) { return Bytecodes::code_or_bp_at(LastFrameAccessor(thread).bcp()) == Bytecodes::_breakpoint; } // Safepoints static void at_safepoint(JavaThread* thread); diff -r 2f733d553ca0 -r 02a1fc064144 hotspot/src/share/vm/interpreter/linkResolver.cpp --- a/hotspot/src/share/vm/interpreter/linkResolver.cpp Tue May 02 19:27:26 2017 -0700 +++ b/hotspot/src/share/vm/interpreter/linkResolver.cpp Wed May 03 02:32:02 2017 +0000 @@ -150,8 +150,6 @@ kind = CallInfo::vtable_call; } else if (!resolved_klass->is_interface()) { // A default or miranda method. Compute the vtable index. - ResourceMark rm; - klassVtable* vt = resolved_klass->vtable(); index = LinkResolver::vtable_index_of_interface_method(resolved_klass, resolved_method); assert(index >= 0 , "we should have valid vtable index at this point"); @@ -163,7 +161,7 @@ #ifdef ASSERT // Ensure that this is really the case. Klass* object_klass = SystemDictionary::Object_klass(); - Method * object_resolved_method = object_klass->vtable()->method_at(index); + Method * object_resolved_method = object_klass->vtable().method_at(index); assert(object_resolved_method->name() == resolved_method->name(), "Object and interface method names should match at vtable index %d, %s != %s", index, object_resolved_method->name()->as_C_string(), resolved_method->name()->as_C_string()); @@ -400,9 +398,8 @@ } if (vtable_index == Method::invalid_vtable_index) { // get vtable_index for miranda methods - ResourceMark rm; - klassVtable *vt = ik->vtable(); - vtable_index = vt->index_of_miranda(name, signature); + klassVtable vt = ik->vtable(); + vtable_index = vt.index_of_miranda(name, signature); } return vtable_index; } diff -r 2f733d553ca0 -r 02a1fc064144 hotspot/src/share/vm/memory/iterator.hpp --- a/hotspot/src/share/vm/memory/iterator.hpp Tue May 02 19:27:26 2017 -0700 +++ b/hotspot/src/share/vm/memory/iterator.hpp Wed May 03 02:32:02 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -65,6 +65,16 @@ public: ReferenceProcessor* ref_processor() const { return _ref_processor; } + // Iteration of InstanceRefKlasses differ depending on the closure, + // the below enum describes the different alternatives. + enum ReferenceIterationMode { + DO_DISCOVERY, // Apply closure and discover references + DO_FIELDS // Apply closure to all fields + }; + + // The default iteration mode is to do discovery. + virtual ReferenceIterationMode reference_iteration_mode() { return DO_DISCOVERY; } + // If the do_metadata functions return "true", // we invoke the following when running oop_iterate(): // diff -r 2f733d553ca0 -r 02a1fc064144 hotspot/src/share/vm/memory/universe.cpp --- a/hotspot/src/share/vm/memory/universe.cpp Tue May 02 19:27:26 2017 -0700 +++ b/hotspot/src/share/vm/memory/universe.cpp Wed May 03 02:32:02 2017 +0000 @@ -526,8 +526,7 @@ // In case those ever change we use handles for oops void Universe::reinitialize_vtable_of(Klass* ko, TRAPS) { // init vtable of k and all subclasses - klassVtable* vt = ko->vtable(); - if (vt) vt->initialize_vtable(false, CHECK); + ko->vtable().initialize_vtable(false, CHECK); if (ko->is_instance_klass()) { for (Klass* sk = ko->subklass(); sk != NULL; @@ -539,7 +538,7 @@ void initialize_itable_for_klass(Klass* k, TRAPS) { - InstanceKlass::cast(k)->itable()->initialize_itable(false, CHECK); + InstanceKlass::cast(k)->itable().initialize_itable(false, CHECK); } diff -r 2f733d553ca0 -r 02a1fc064144 hotspot/src/share/vm/oops/arrayKlass.cpp --- a/hotspot/src/share/vm/oops/arrayKlass.cpp Tue May 02 19:27:26 2017 -0700 +++ b/hotspot/src/share/vm/oops/arrayKlass.cpp Wed May 03 02:32:02 2017 +0000 @@ -99,7 +99,7 @@ void ArrayKlass::complete_create_array_klass(ArrayKlass* k, Klass* super_klass, ModuleEntry* module_entry, TRAPS) { ResourceMark rm(THREAD); k->initialize_supers(super_klass, CHECK); - k->vtable()->initialize_vtable(false, CHECK); + k->vtable().initialize_vtable(false, CHECK); // During bootstrapping, before java.base is defined, the module_entry may not be present yet. // These classes will be put on a fixup list and their module fields will be patched once diff -r 2f733d553ca0 -r 02a1fc064144 hotspot/src/share/vm/oops/instanceClassLoaderKlass.hpp --- a/hotspot/src/share/vm/oops/instanceClassLoaderKlass.hpp Tue May 02 19:27:26 2017 -0700 +++ b/hotspot/src/share/vm/oops/instanceClassLoaderKlass.hpp Wed May 03 02:32:02 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -48,8 +48,6 @@ // GC specific object visitors // - // Mark Sweep - int oop_ms_adjust_pointers(oop obj); #if INCLUDE_ALL_GCS // Parallel Scavenge void oop_ps_push_contents( oop obj, PSPromotionManager* pm); diff -r 2f733d553ca0 -r 02a1fc064144 hotspot/src/share/vm/oops/instanceKlass.cpp --- a/hotspot/src/share/vm/oops/instanceKlass.cpp Tue May 02 19:27:26 2017 -0700 +++ b/hotspot/src/share/vm/oops/instanceKlass.cpp Wed May 03 02:32:02 2017 +0000 @@ -373,8 +373,8 @@ return !is_initialized(); } -klassItable* InstanceKlass::itable() const { - return new klassItable(const_cast(this)); +klassItable InstanceKlass::itable() const { + return klassItable(const_cast(this)); } void InstanceKlass::eager_initialize(Thread *thread) { @@ -621,15 +621,14 @@ if (!(is_shared() && loader_data->is_the_null_class_loader_data())) { ResourceMark rm(THREAD); - vtable()->initialize_vtable(true, CHECK_false); - itable()->initialize_itable(true, CHECK_false); + vtable().initialize_vtable(true, CHECK_false); + itable().initialize_itable(true, CHECK_false); } #ifdef ASSERT else { - ResourceMark rm(THREAD); - vtable()->verify(tty, true); + vtable().verify(tty, true); // In case itable verification is ever added. - // itable()->verify(tty, true); + // itable().verify(tty, true); } #endif set_init_state(linked); @@ -807,8 +806,8 @@ // Step 9 if (!HAS_PENDING_EXCEPTION) { set_initialization_state_and_notify(fully_initialized, CHECK); - { ResourceMark rm(THREAD); - debug_only(vtable()->verify(tty, true);) + { + debug_only(vtable().verify(tty, true);) } } else { @@ -2041,8 +2040,8 @@ // vtables in the shared system dictionary, only the main one. // It also redefines the itable too so fix that too. ResourceMark rm(THREAD); - vtable()->initialize_vtable(false, CHECK); - itable()->initialize_itable(false, CHECK); + vtable().initialize_vtable(false, CHECK); + itable().initialize_itable(false, CHECK); } // restore constant pool resolved references @@ -3212,10 +3211,9 @@ // Verify vtables if (is_linked()) { - ResourceMark rm; // $$$ This used to be done only for m/s collections. Doing it // always seemed a valid generalization. (DLD -- 6/00) - vtable()->verify(st); + vtable().verify(st); } // Verify first subklass diff -r 2f733d553ca0 -r 02a1fc064144 hotspot/src/share/vm/oops/instanceKlass.hpp --- a/hotspot/src/share/vm/oops/instanceKlass.hpp Tue May 02 19:27:26 2017 -0700 +++ b/hotspot/src/share/vm/oops/instanceKlass.hpp Wed May 03 02:32:02 2017 +0000 @@ -1127,7 +1127,7 @@ } // Java itable - klassItable* itable() const; // return new klassItable wrapper + klassItable itable() const; // return klassItable wrapper Method* method_at_itable(Klass* holder, int index, TRAPS); #if INCLUDE_JVMTI @@ -1163,8 +1163,6 @@ // GC specific object visitors // - // Mark Sweep - int oop_ms_adjust_pointers(oop obj); #if INCLUDE_ALL_GCS // Parallel Scavenge void oop_ps_push_contents( oop obj, PSPromotionManager* pm); diff -r 2f733d553ca0 -r 02a1fc064144 hotspot/src/share/vm/oops/instanceMirrorKlass.hpp --- a/hotspot/src/share/vm/oops/instanceMirrorKlass.hpp Tue May 02 19:27:26 2017 -0700 +++ b/hotspot/src/share/vm/oops/instanceMirrorKlass.hpp Wed May 03 02:32:02 2017 +0000 @@ -89,8 +89,6 @@ // GC specific object visitors // - // Mark Sweep - int oop_ms_adjust_pointers(oop obj); #if INCLUDE_ALL_GCS // Parallel Scavenge void oop_ps_push_contents( oop obj, PSPromotionManager* pm); diff -r 2f733d553ca0 -r 02a1fc064144 hotspot/src/share/vm/oops/instanceRefKlass.hpp --- a/hotspot/src/share/vm/oops/instanceRefKlass.hpp Tue May 02 19:27:26 2017 -0700 +++ b/hotspot/src/share/vm/oops/instanceRefKlass.hpp Wed May 03 02:32:02 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -58,8 +58,6 @@ // GC specific object visitors // - // Mark Sweep - int oop_ms_adjust_pointers(oop obj); #if INCLUDE_ALL_GCS // Parallel Scavenge void oop_ps_push_contents( oop obj, PSPromotionManager* pm); @@ -107,6 +105,30 @@ template inline void oop_oop_iterate_ref_processing(oop obj, OopClosureType* closure); + // Building blocks for specialized handling. + template + static void do_referent(oop obj, OopClosureType* closure, Contains& contains); + + template + static void do_next(oop obj, OopClosureType* closure, Contains& contains); + + template + static void do_discovered(oop obj, OopClosureType* closure, Contains& contains); + + template + static bool try_discover(oop obj, ReferenceType type, OopClosureType* closure); + + // Do discovery while handling InstanceRefKlasses. Reference discovery + // is only done if the closure provides a ReferenceProcessor. + template + static void oop_oop_iterate_discovery(oop obj, ReferenceType type, OopClosureType* closure, Contains& contains); + + // Apply the closure to all fields. No reference discovery is done. + template + static void oop_oop_iterate_fields(oop obj, OopClosureType* closure, Contains& contains); + + template + static void trace_reference_gc(const char *s, oop obj, T* referent_addr, T* next_addr, T* discovered_addr) NOT_DEBUG_RETURN; public: diff -r 2f733d553ca0 -r 02a1fc064144 hotspot/src/share/vm/oops/instanceRefKlass.inline.hpp --- a/hotspot/src/share/vm/oops/instanceRefKlass.inline.hpp Tue May 02 19:27:26 2017 -0700 +++ b/hotspot/src/share/vm/oops/instanceRefKlass.inline.hpp Wed May 03 02:32:02 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,36 +36,96 @@ #include "utilities/macros.hpp" template -void InstanceRefKlass::oop_oop_iterate_ref_processing_specialized(oop obj, OopClosureType* closure, Contains& contains) { - T* disc_addr = (T*)java_lang_ref_Reference::discovered_addr(obj); +void InstanceRefKlass::do_referent(oop obj, OopClosureType* closure, Contains& contains) { + T* referent_addr = (T*)java_lang_ref_Reference::referent_addr(obj); + if (contains(referent_addr)) { + Devirtualizer::do_oop(closure, referent_addr); + } +} + +template +void InstanceRefKlass::do_next(oop obj, OopClosureType* closure, Contains& contains) { + T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj); + if (contains(next_addr)) { + Devirtualizer::do_oop(closure, next_addr); + } +} + +template +void InstanceRefKlass::do_discovered(oop obj, OopClosureType* closure, Contains& contains) { + T* discovered_addr = (T*)java_lang_ref_Reference::discovered_addr(obj); + if (contains(discovered_addr)) { + Devirtualizer::do_oop(closure, discovered_addr); + } +} + +template +bool InstanceRefKlass::try_discover(oop obj, ReferenceType type, OopClosureType* closure) { + ReferenceProcessor* rp = closure->ref_processor(); + if (rp != NULL) { + T referent_oop = oopDesc::load_heap_oop((T*)java_lang_ref_Reference::referent_addr(obj)); + if (!oopDesc::is_null(referent_oop)) { + oop referent = oopDesc::decode_heap_oop_not_null(referent_oop); + if (!referent->is_gc_marked()) { + // Only try to discover if not yet marked. + return rp->discover_reference(obj, type); + } + } + } + return false; +} + +template +void InstanceRefKlass::oop_oop_iterate_discovery(oop obj, ReferenceType type, OopClosureType* closure, Contains& contains) { + log_develop_trace(gc, ref)("Process reference with discovery " PTR_FORMAT, p2i(obj)); + + // Special case for some closures. if (closure->apply_to_weak_ref_discovered_field()) { - Devirtualizer::do_oop(closure, disc_addr); + do_discovered(obj, closure, contains); } - T* referent_addr = (T*)java_lang_ref_Reference::referent_addr(obj); - T heap_oop = oopDesc::load_heap_oop(referent_addr); - ReferenceProcessor* rp = closure->ref_processor(); - if (!oopDesc::is_null(heap_oop)) { - oop referent = oopDesc::decode_heap_oop_not_null(heap_oop); - if (!referent->is_gc_marked() && (rp != NULL) && - rp->discover_reference(obj, reference_type())) { - return; - } else if (contains(referent_addr)) { - // treat referent as normal oop - Devirtualizer::do_oop(closure, referent_addr); - } + // Try to discover reference and return if it succeeds. + if (try_discover(obj, type, closure)) { + return; + } + + // Treat referent as normal oop. + do_referent(obj, closure, contains); + + // Treat discovered as normal oop, if ref is not "active" (next non-NULL). + T next_oop = oopDesc::load_heap_oop((T*)java_lang_ref_Reference::next_addr(obj)); + if (!oopDesc::is_null(next_oop)) { + do_discovered(obj, closure, contains); } - T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj); - T next_oop = oopDesc::load_heap_oop(next_addr); - // Treat discovered as normal oop, if ref is not "active" (next non-NULL) - if (!oopDesc::is_null(next_oop) && contains(disc_addr)) { - // i.e. ref is not "active" - log_develop_trace(gc, ref)(" Process discovered as normal " PTR_FORMAT, p2i(disc_addr)); - Devirtualizer::do_oop(closure, disc_addr); - } - // treat next as normal oop - if (contains(next_addr)) { - Devirtualizer::do_oop(closure, next_addr); + + // Treat next as normal oop. + do_next(obj, closure, contains); +} + +template +void InstanceRefKlass::oop_oop_iterate_fields(oop obj, OopClosureType* closure, Contains& contains) { + do_referent(obj, closure, contains); + do_discovered(obj, closure, contains); + do_next(obj, closure, contains); + + trace_reference_gc("InstanceRefKlass::oop_oop_iterate_fields()", + obj, + (T*)java_lang_ref_Reference::referent_addr(obj), + (T*)java_lang_ref_Reference::next_addr(obj), + (T*)java_lang_ref_Reference::discovered_addr(obj)); +} + +template +void InstanceRefKlass::oop_oop_iterate_ref_processing_specialized(oop obj, OopClosureType* closure, Contains& contains) { + switch (closure->reference_iteration_mode()) { + case ExtendedOopClosure::DO_DISCOVERY: + oop_oop_iterate_discovery(obj, reference_type(), closure, contains); + break; + case ExtendedOopClosure::DO_FIELDS: + oop_oop_iterate_fields(obj, closure, contains); + break; + default: + ShouldNotReachHere(); } } @@ -125,6 +185,19 @@ oop_oop_iterate_ref_processing_bounded(obj, closure, mr); } +#ifdef ASSERT +template +void InstanceRefKlass::trace_reference_gc(const char *s, oop obj, T* referent_addr, T* next_addr, T* discovered_addr) { + log_develop_trace(gc, ref)("%s obj " PTR_FORMAT, s, p2i(obj)); + log_develop_trace(gc, ref)(" referent_addr/* " PTR_FORMAT " / " PTR_FORMAT, + p2i(referent_addr), p2i(referent_addr ? (address)oopDesc::load_decode_heap_oop(referent_addr) : NULL)); + log_develop_trace(gc, ref)(" next_addr/* " PTR_FORMAT " / " PTR_FORMAT, + p2i(next_addr), p2i(next_addr ? (address)oopDesc::load_decode_heap_oop(next_addr) : NULL)); + log_develop_trace(gc, ref)(" discovered_addr/* " PTR_FORMAT " / " PTR_FORMAT, + p2i(discovered_addr), p2i(discovered_addr ? (address)oopDesc::load_decode_heap_oop(discovered_addr) : NULL)); +} +#endif + // Macro to define InstanceRefKlass::oop_oop_iterate for virtual/nonvirtual for // all closures. Macros calling macros above for each oop size. #define ALL_INSTANCE_REF_KLASS_OOP_OOP_ITERATE_DEFN(OopClosureType, nv_suffix) \ diff -r 2f733d553ca0 -r 02a1fc064144 hotspot/src/share/vm/oops/klass.cpp --- a/hotspot/src/share/vm/oops/klass.cpp Tue May 02 19:27:26 2017 -0700 +++ b/hotspot/src/share/vm/oops/klass.cpp Wed May 03 02:32:02 2017 +0000 @@ -497,10 +497,12 @@ // Null out class_loader_data because we don't share that yet. set_class_loader_data(NULL); + set_is_shared(); } void Klass::restore_unshareable_info(ClassLoaderData* loader_data, Handle protection_domain, TRAPS) { assert(is_klass(), "ensure C++ vtable is restored"); + assert(is_shared(), "must be set"); TRACE_RESTORE_ID(this); // If an exception happened during CDS restore, some of these fields may already be @@ -696,8 +698,8 @@ guarantee(obj->klass()->is_klass(), "klass field is not a klass"); } -klassVtable* Klass::vtable() const { - return new klassVtable(const_cast(this), start_of_vtable(), vtable_length() / vtableEntry::size()); +klassVtable Klass::vtable() const { + return klassVtable(const_cast(this), start_of_vtable(), vtable_length() / vtableEntry::size()); } vtableEntry* Klass::start_of_vtable() const { diff -r 2f733d553ca0 -r 02a1fc064144 hotspot/src/share/vm/oops/klass.hpp --- a/hotspot/src/share/vm/oops/klass.hpp Tue May 02 19:27:26 2017 -0700 +++ b/hotspot/src/share/vm/oops/klass.hpp Wed May 03 02:32:02 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -399,7 +399,7 @@ #endif // vtables - klassVtable* vtable() const; + klassVtable vtable() const; int vtable_length() const { return _vtable_len; } // subclass check @@ -563,6 +563,8 @@ void set_has_vanilla_constructor() { _access_flags.set_has_vanilla_constructor(); } bool has_miranda_methods () const { return access_flags().has_miranda_methods(); } void set_has_miranda_methods() { _access_flags.set_has_miranda_methods(); } + bool is_shared() const { return access_flags().is_shared_class(); } // shadows MetaspaceObj::is_shared)() + void set_is_shared() { _access_flags.set_is_shared_class(); } bool is_cloneable() const; void set_is_cloneable(); @@ -607,8 +609,6 @@ // GC specific object visitors // - // Mark Sweep - virtual int oop_ms_adjust_pointers(oop obj) = 0; #if INCLUDE_ALL_GCS // Parallel Scavenge virtual void oop_ps_push_contents( oop obj, PSPromotionManager* pm) = 0; diff -r 2f733d553ca0 -r 02a1fc064144 hotspot/src/share/vm/oops/klassVtable.cpp --- a/hotspot/src/share/vm/oops/klassVtable.cpp Tue May 02 19:27:26 2017 -0700 +++ b/hotspot/src/share/vm/oops/klassVtable.cpp Wed May 03 02:32:02 2017 +0000 @@ -136,22 +136,22 @@ // methods from super class for shared class, as that was already done // during archiving time. However, if Jvmti has redefined a class, // copy super class's vtable in case the super class has changed. - return super->vtable()->length(); + return super->vtable().length(); } else { // copy methods from superKlass - klassVtable* superVtable = super->vtable(); - assert(superVtable->length() <= _length, "vtable too short"); + klassVtable superVtable = super->vtable(); + assert(superVtable.length() <= _length, "vtable too short"); #ifdef ASSERT - superVtable->verify(tty, true); + superVtable.verify(tty, true); #endif - superVtable->copy_vtable_to(table()); + superVtable.copy_vtable_to(table()); if (log_develop_is_enabled(Trace, vtables)) { ResourceMark rm; log_develop_trace(vtables)("copy vtable from %s to %s size %d", super->internal_name(), klass()->internal_name(), _length); } - return superVtable->length(); + return superVtable.length(); } } @@ -290,9 +290,9 @@ InstanceKlass* superk = initialsuper; while (superk != NULL && superk->super() != NULL) { InstanceKlass* supersuperklass = InstanceKlass::cast(superk->super()); - klassVtable* ssVtable = supersuperklass->vtable(); - if (vtable_index < ssVtable->length()) { - Method* super_method = ssVtable->method_at(vtable_index); + klassVtable ssVtable = supersuperklass->vtable(); + if (vtable_index < ssVtable.length()) { + Method* super_method = ssVtable.method_at(vtable_index); #ifndef PRODUCT Symbol* name= target_method()->name(); Symbol* signature = target_method()->signature(); @@ -445,8 +445,8 @@ if (is_preinitialized_vtable()) { // If this is a shared class, the vtable is already in the final state (fully // initialized). Need to look at the super's vtable. - klassVtable* superVtable = super->vtable(); - super_method = superVtable->method_at(i); + klassVtable superVtable = super->vtable(); + super_method = superVtable.method_at(i); } else { super_method = method_at(i); } @@ -1014,15 +1014,16 @@ void itableMethodEntry::initialize(Method* m) { if (m == NULL) return; +#ifdef ASSERT if (MetaspaceShared::is_in_shared_space((void*)&_method) && !MetaspaceShared::remapped_readwrite()) { // At runtime initialize_itable is rerun as part of link_class_impl() // for a shared class loaded by the non-boot loader. // The dumptime itable method entry should be the same as the runtime entry. assert(_method == m, "sanity"); - } else { - _method = m; } +#endif + _method = m; } klassItable::klassItable(InstanceKlass* klass) { @@ -1249,17 +1250,6 @@ } } -// Update entry for specific Method* -void klassItable::initialize_with_method(Method* m) { - itableMethodEntry* ime = method_entry(0); - for(int i = 0; i < _size_method_table; i++) { - if (ime->method() == m) { - ime->initialize(m); - } - ime++; - } -} - #if INCLUDE_JVMTI // search the itable for uses of either obsolete or EMCP methods void klassItable::adjust_method_entries(InstanceKlass* holder, bool * trace_name_printed) { @@ -1488,9 +1478,9 @@ Klass* super = _klass->super(); if (super != NULL) { InstanceKlass* sk = InstanceKlass::cast(super); - klassVtable* vt = sk->vtable(); - for (int i = 0; i < vt->length(); i++) { - verify_against(st, vt, i); + klassVtable vt = sk->vtable(); + for (int i = 0; i < vt.length(); i++) { + verify_against(st, &vt, i); } } } @@ -1557,8 +1547,7 @@ static void do_class(Klass* k) { Klass* kl = k; - klassVtable* vt = kl->vtable(); - if (vt == NULL) return; + klassVtable vt = kl->vtable(); no_klasses++; if (kl->is_instance_klass()) { no_instance_klasses++; @@ -1566,9 +1555,9 @@ } if (kl->is_array_klass()) { no_array_klasses++; - sum_of_array_vtable_len += vt->length(); + sum_of_array_vtable_len += vt.length(); } - sum_of_vtable_len += vt->length(); + sum_of_vtable_len += vt.length(); } static void compute() { diff -r 2f733d553ca0 -r 02a1fc064144 hotspot/src/share/vm/oops/klassVtable.hpp --- a/hotspot/src/share/vm/oops/klassVtable.hpp Tue May 02 19:27:26 2017 -0700 +++ b/hotspot/src/share/vm/oops/klassVtable.hpp Wed May 03 02:32:02 2017 +0000 @@ -41,7 +41,7 @@ class vtableEntry; -class klassVtable : public ResourceObj { +class klassVtable VALUE_OBJ_CLASS_SPEC { Klass* _klass; // my klass int _tableOffset; // offset of start of vtable data within klass int _length; // length of vtable (number of entries) @@ -288,7 +288,7 @@ // -- vtable for interface 2 --- // ... // -class klassItable : public ResourceObj { +class klassItable VALUE_OBJ_CLASS_SPEC { private: InstanceKlass* _klass; // my klass int _table_offset; // offset of start of itable data within klass (in words) @@ -310,9 +310,6 @@ // Initialization void initialize_itable(bool checkconstraints, TRAPS); - // Updates - void initialize_with_method(Method* m); - #if INCLUDE_JVMTI // RedefineClasses() API support: // if any entry of this itable points to any of old_methods, diff -r 2f733d553ca0 -r 02a1fc064144 hotspot/src/share/vm/oops/method.cpp --- a/hotspot/src/share/vm/oops/method.cpp Tue May 02 19:27:26 2017 -0700 +++ b/hotspot/src/share/vm/oops/method.cpp Wed May 03 02:32:02 2017 +0000 @@ -1191,7 +1191,6 @@ } assert(ik->is_subclass_of(method_holder()), "should be subklass"); - assert(ik->vtable() != NULL, "vtable should exist"); if (!has_vtable_index()) { return false; } else { diff -r 2f733d553ca0 -r 02a1fc064144 hotspot/src/share/vm/oops/objArrayKlass.hpp --- a/hotspot/src/share/vm/oops/objArrayKlass.hpp Tue May 02 19:27:26 2017 -0700 +++ b/hotspot/src/share/vm/oops/objArrayKlass.hpp Wed May 03 02:32:02 2017 +0000 @@ -112,8 +112,6 @@ // GC specific object visitors // - // Mark Sweep - int oop_ms_adjust_pointers(oop obj); #if INCLUDE_ALL_GCS // Parallel Scavenge void oop_ps_push_contents( oop obj, PSPromotionManager* pm); diff -r 2f733d553ca0 -r 02a1fc064144 hotspot/src/share/vm/oops/oop.hpp --- a/hotspot/src/share/vm/oops/oop.hpp Tue May 02 19:27:26 2017 -0700 +++ b/hotspot/src/share/vm/oops/oop.hpp Wed May 03 02:32:02 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -325,10 +325,6 @@ // Garbage Collection support - // Mark Sweep - // Adjust all pointers in this object to point at it's forwarded location and - // return the size of this oop. This is used by the MarkSweep collector. - inline int ms_adjust_pointers(); #if INCLUDE_ALL_GCS // Parallel Compact inline void pc_follow_contents(ParCompactionManager* cm); diff -r 2f733d553ca0 -r 02a1fc064144 hotspot/src/share/vm/oops/oop.inline.hpp --- a/hotspot/src/share/vm/oops/oop.inline.hpp Tue May 02 19:27:26 2017 -0700 +++ b/hotspot/src/share/vm/oops/oop.inline.hpp Wed May 03 02:32:02 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -664,13 +664,6 @@ } } -int oopDesc::ms_adjust_pointers() { - debug_only(int check_size = size()); - int s = klass()->oop_ms_adjust_pointers(this); - assert(s == check_size, "should be the same"); - return s; -} - #if INCLUDE_ALL_GCS void oopDesc::pc_follow_contents(ParCompactionManager* cm) { klass()->oop_pc_follow_contents(this, cm); diff -r 2f733d553ca0 -r 02a1fc064144 hotspot/src/share/vm/oops/typeArrayKlass.hpp --- a/hotspot/src/share/vm/oops/typeArrayKlass.hpp Tue May 02 19:27:26 2017 -0700 +++ b/hotspot/src/share/vm/oops/typeArrayKlass.hpp Wed May 03 02:32:02 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -74,8 +74,6 @@ // GC specific object visitors // - // Mark Sweep - int oop_ms_adjust_pointers(oop obj); #if INCLUDE_ALL_GCS // Parallel Scavenge void oop_ps_push_contents( oop obj, PSPromotionManager* pm); diff -r 2f733d553ca0 -r 02a1fc064144 hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp --- a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp Tue May 02 19:27:26 2017 -0700 +++ b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp Wed May 03 02:32:02 2017 +0000 @@ -3272,7 +3272,7 @@ // If the class being redefined is java.lang.Object, we need to fix all // array class vtables also if (k->is_array_klass() && _the_class == SystemDictionary::Object_klass()) { - k->vtable()->adjust_method_entries(the_class, &trace_name_printed); + k->vtable().adjust_method_entries(the_class, &trace_name_printed); } else if (k->is_instance_klass()) { HandleMark hm(_thread); @@ -3315,7 +3315,7 @@ // ik->vtable() creates a wrapper object; rm cleans it up ResourceMark rm(_thread); - ik->vtable()->adjust_method_entries(the_class, &trace_name_printed); + ik->vtable().adjust_method_entries(the_class, &trace_name_printed); ik->adjust_default_methods(the_class, &trace_name_printed); } @@ -3329,10 +3329,8 @@ if (ik->itable_length() > 0 && (_the_class->is_interface() || _the_class == SystemDictionary::internal_Unsafe_klass() || ik->is_subclass_of(_the_class))) { - // ik->itable() creates a wrapper object; rm cleans it up ResourceMark rm(_thread); - - ik->itable()->adjust_method_entries(the_class, &trace_name_printed); + ik->itable().adjust_method_entries(the_class, &trace_name_printed); } // The constant pools in other classes (other_cp) can refer to @@ -3957,8 +3955,8 @@ // compare_and_normalize_class_versions has already checked: // - classloaders unchanged, signatures unchanged // - all instanceKlasses for redefined classes reused & contents updated - the_class->vtable()->initialize_vtable(false, THREAD); - the_class->itable()->initialize_itable(false, THREAD); + the_class->vtable().initialize_vtable(false, THREAD); + the_class->itable().initialize_itable(false, THREAD); assert(!HAS_PENDING_EXCEPTION || (THREAD->pending_exception()->is_a(SystemDictionary::ThreadDeath_klass())), "redefine exception"); } @@ -4093,12 +4091,12 @@ // a vtable should never contain old or obsolete methods ResourceMark rm(_thread); if (k->vtable_length() > 0 && - !k->vtable()->check_no_old_or_obsolete_entries()) { + !k->vtable().check_no_old_or_obsolete_entries()) { if (log_is_enabled(Trace, redefine, class, obsolete, metadata)) { log_trace(redefine, class, obsolete, metadata) ("klassVtable::check_no_old_or_obsolete_entries failure -- OLD or OBSOLETE method found -- class: %s", k->signature_name()); - k->vtable()->dump_vtable(); + k->vtable().dump_vtable(); } no_old_methods = false; } @@ -4109,12 +4107,12 @@ // an itable should never contain old or obsolete methods if (ik->itable_length() > 0 && - !ik->itable()->check_no_old_or_obsolete_entries()) { + !ik->itable().check_no_old_or_obsolete_entries()) { if (log_is_enabled(Trace, redefine, class, obsolete, metadata)) { log_trace(redefine, class, obsolete, metadata) ("klassItable::check_no_old_or_obsolete_entries failure -- OLD or OBSOLETE method found -- class: %s", ik->signature_name()); - ik->itable()->dump_itable(); + ik->itable().dump_itable(); } no_old_methods = false; } diff -r 2f733d553ca0 -r 02a1fc064144 hotspot/src/share/vm/prims/methodHandles.cpp --- a/hotspot/src/share/vm/prims/methodHandles.cpp Tue May 02 19:27:26 2017 -0700 +++ b/hotspot/src/share/vm/prims/methodHandles.cpp Wed May 03 02:32:02 2017 +0000 @@ -218,7 +218,7 @@ m_klass_non_interface = SystemDictionary::Object_klass(); #ifdef ASSERT { ResourceMark rm; - Method* m2 = m_klass_non_interface->vtable()->method_at(vmindex); + Method* m2 = m_klass_non_interface->vtable().method_at(vmindex); assert(m->name() == m2->name() && m->signature() == m2->signature(), "at %d, %s != %s", vmindex, m->name_and_sig_as_C_string(), m2->name_and_sig_as_C_string()); diff -r 2f733d553ca0 -r 02a1fc064144 hotspot/src/share/vm/runtime/commandLineFlagConstraintsCompiler.cpp --- a/hotspot/src/share/vm/runtime/commandLineFlagConstraintsCompiler.cpp Tue May 02 19:27:26 2017 -0700 +++ b/hotspot/src/share/vm/runtime/commandLineFlagConstraintsCompiler.cpp Wed May 03 02:32:02 2017 +0000 @@ -289,10 +289,10 @@ } Flag::Error ArraycopyDstPrefetchDistanceConstraintFunc(uintx value, bool verbose) { - if (value != 0) { + if (value >= 4032) { CommandLineError::print(verbose, - "ArraycopyDstPrefetchDistance (" UINTX_FORMAT ") must be 0\n", - value); + "ArraycopyDstPrefetchDistance (" UINTX_FORMAT ") must be" + "between 0 and 4031\n", value); return Flag::VIOLATES_CONSTRAINT; } @@ -300,10 +300,10 @@ } Flag::Error ArraycopySrcPrefetchDistanceConstraintFunc(uintx value, bool verbose) { - if (value != 0) { + if (value >= 4032) { CommandLineError::print(verbose, - "ArraycopySrcPrefetchDistance (" UINTX_FORMAT ") must be 0\n", - value); + "ArraycopySrcPrefetchDistance (" UINTX_FORMAT ") must be" + "between 0 and 4031\n", value); return Flag::VIOLATES_CONSTRAINT; } diff -r 2f733d553ca0 -r 02a1fc064144 hotspot/src/share/vm/runtime/globals.cpp --- a/hotspot/src/share/vm/runtime/globals.cpp Tue May 02 19:27:26 2017 -0700 +++ b/hotspot/src/share/vm/runtime/globals.cpp Wed May 03 02:32:02 2017 +0000 @@ -865,16 +865,15 @@ Flag* Flag::flags = flagTable; size_t Flag::numFlags = (sizeof(flagTable) / sizeof(Flag)); -inline bool str_equal(const char* s, const char* q, size_t len) { - // s is null terminated, q is not! - if (strlen(s) != (unsigned int) len) return false; - return strncmp(s, q, len) == 0; +inline bool str_equal(const char* s, size_t s_len, const char* q, size_t q_len) { + if (s_len != q_len) return false; + return memcmp(s, q, q_len) == 0; } // Search the flag table for a named flag Flag* Flag::find_flag(const char* name, size_t length, bool allow_locked, bool return_flag) { for (Flag* current = &flagTable[0]; current->_name != NULL; current++) { - if (str_equal(current->_name, name, length)) { + if (str_equal(current->_name, current->get_name_length(), name, length)) { // Found a matching entry. // Don't report notproduct and develop flags in product builds. if (current->is_constant_in_binary()) { @@ -895,6 +894,14 @@ return NULL; } +// Get or compute the flag name length +size_t Flag::get_name_length() { + if (_name_len == 0) { + _name_len = strlen(_name); + } + return _name_len; +} + // Compute string similarity based on Dice's coefficient static float str_similar(const char* str1, const char* str2, size_t len2) { int len1 = (int) strlen(str1); diff -r 2f733d553ca0 -r 02a1fc064144 hotspot/src/share/vm/runtime/globals.hpp --- a/hotspot/src/share/vm/runtime/globals.hpp Tue May 02 19:27:26 2017 -0700 +++ b/hotspot/src/share/vm/runtime/globals.hpp Wed May 03 02:32:02 2017 +0000 @@ -186,6 +186,7 @@ void* _addr; NOT_PRODUCT(const char* _doc;) Flags _flags; + size_t _name_len; // points to all Flags static array static Flag* flags; @@ -247,6 +248,8 @@ Flags get_origin(); void set_origin(Flags origin); + size_t get_name_length(); + bool is_default(); bool is_ergonomic(); bool is_command_line(); diff -r 2f733d553ca0 -r 02a1fc064144 hotspot/src/share/vm/runtime/vmStructs.cpp --- a/hotspot/src/share/vm/runtime/vmStructs.cpp Tue May 02 19:27:26 2017 -0700 +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp Wed May 03 02:32:02 2017 +0000 @@ -199,6 +199,7 @@ typedef HashtableEntry KlassHashtableEntry; typedef TwoOopHashtable SymbolTwoOopHashtable; typedef CompactHashtable SymbolCompactHashTable; +typedef RehashableHashtable RehashableSymbolHashtable; //-------------------------------------------------------------------------------- // VM_STRUCTS @@ -584,6 +585,7 @@ \ static_field(SymbolTable, _the_table, SymbolTable*) \ static_field(SymbolTable, _shared_table, SymbolCompactHashTable) \ + static_field(RehashableSymbolHashtable, _seed, juint) \ \ /***************/ \ /* StringTable */ \ @@ -1602,6 +1604,8 @@ \ declare_toplevel_type(BasicHashtable) \ declare_type(IntptrHashtable, BasicHashtable) \ + declare_toplevel_type(BasicHashtable) \ + declare_type(RehashableSymbolHashtable, BasicHashtable) \ declare_type(SymbolTable, SymbolHashtable) \ declare_type(StringTable, StringHashtable) \ declare_type(LoaderConstraintTable, KlassHashtable) \ diff -r 2f733d553ca0 -r 02a1fc064144 hotspot/src/share/vm/utilities/accessFlags.hpp --- a/hotspot/src/share/vm/utilities/accessFlags.hpp Tue May 02 19:27:26 2017 -0700 +++ b/hotspot/src/share/vm/utilities/accessFlags.hpp Wed May 03 02:32:02 2017 +0000 @@ -64,6 +64,7 @@ JVM_ACC_HAS_FINALIZER = 0x40000000, // True if klass has a non-empty finalize() method JVM_ACC_IS_CLONEABLE_FAST = (int)0x80000000,// True if klass implements the Cloneable interface and can be optimized in generated code JVM_ACC_HAS_FINAL_METHOD = 0x01000000, // True if klass has final method + JVM_ACC_IS_SHARED_CLASS = 0x02000000, // True if klass is shared // Klass* and Method* flags JVM_ACC_HAS_LOCAL_VARIABLE_TABLE= 0x00200000, @@ -146,6 +147,8 @@ bool has_finalizer () const { return (_flags & JVM_ACC_HAS_FINALIZER ) != 0; } bool has_final_method () const { return (_flags & JVM_ACC_HAS_FINAL_METHOD ) != 0; } bool is_cloneable_fast () const { return (_flags & JVM_ACC_IS_CLONEABLE_FAST ) != 0; } + bool is_shared_class () const { return (_flags & JVM_ACC_IS_SHARED_CLASS ) != 0; } + // Klass* and Method* flags bool has_localvariable_table () const { return (_flags & JVM_ACC_HAS_LOCAL_VARIABLE_TABLE) != 0; } void set_has_localvariable_table() { atomic_set_bits(JVM_ACC_HAS_LOCAL_VARIABLE_TABLE); } @@ -216,6 +219,7 @@ void set_has_final_method() { atomic_set_bits(JVM_ACC_HAS_FINAL_METHOD); } void set_is_cloneable_fast() { atomic_set_bits(JVM_ACC_IS_CLONEABLE_FAST); } void set_has_miranda_methods() { atomic_set_bits(JVM_ACC_HAS_MIRANDA_METHODS); } + void set_is_shared_class() { atomic_set_bits(JVM_ACC_IS_SHARED_CLASS); } public: // field flags diff -r 2f733d553ca0 -r 02a1fc064144 hotspot/src/share/vm/utilities/debug.cpp --- a/hotspot/src/share/vm/utilities/debug.cpp Tue May 02 19:27:26 2017 -0700 +++ b/hotspot/src/share/vm/utilities/debug.cpp Wed May 03 02:32:02 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -490,7 +490,7 @@ extern "C" void dump_vtable(address p) { Command c("dump_vtable"); Klass* k = (Klass*)p; - k->vtable()->print(); + k->vtable().print(); } diff -r 2f733d553ca0 -r 02a1fc064144 hotspot/src/share/vm/utilities/hashtable.hpp --- a/hotspot/src/share/vm/utilities/hashtable.hpp Tue May 02 19:27:26 2017 -0700 +++ b/hotspot/src/share/vm/utilities/hashtable.hpp Wed May 03 02:32:02 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -294,6 +294,7 @@ }; template class RehashableHashtable : public Hashtable { + friend class VMStructs; protected: enum { diff -r 2f733d553ca0 -r 02a1fc064144 hotspot/test/ProblemList.txt --- a/hotspot/test/ProblemList.txt Tue May 02 19:27:26 2017 -0700 +++ b/hotspot/test/ProblemList.txt Wed May 03 02:32:02 2017 +0000 @@ -113,6 +113,7 @@ gc/g1/humongousObjects/objectGraphTest/TestObjectGraphAfterGC.java 8156755 generic-all gc/survivorAlignment/TestPromotionToSurvivor.java 8129886 generic-all gc/g1/logging/TestG1LoggingFailure.java 8169634 generic-all +gc/g1/humongousObjects/TestHeapCounters.java 8178918 generic-all ############################################################################# @@ -121,7 +122,6 @@ runtime/CompressedOops/UseCompressedOops.java 8079353 generic-all # This test is disabled since it will stress NMT and timeout during normal testing runtime/NMT/MallocStressTest.java 8166548 generic-all -runtime/SharedArchiveFile/BootAppendTests.java 8150683 generic-all runtime/SharedArchiveFile/DefaultUseWithClient.java 8154204 generic-all ############################################################################# diff -r 2f733d553ca0 -r 02a1fc064144 hotspot/test/runtime/SharedArchiveFile/ArchiveDoesNotExist.java --- a/hotspot/test/runtime/SharedArchiveFile/ArchiveDoesNotExist.java Tue May 02 19:27:26 2017 -0700 +++ b/hotspot/test/runtime/SharedArchiveFile/ArchiveDoesNotExist.java Wed May 03 02:32:02 2017 +0000 @@ -27,6 +27,7 @@ * attempting to use CDS archive. JVM should exit gracefully * when sharing mode is ON, and continue w/o sharing if sharing * mode is AUTO. + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) * @library /test/lib * @modules java.base/jdk.internal.misc * java.management diff -r 2f733d553ca0 -r 02a1fc064144 hotspot/test/runtime/SharedArchiveFile/BootAppendTests.java --- a/hotspot/test/runtime/SharedArchiveFile/BootAppendTests.java Tue May 02 19:27:26 2017 -0700 +++ b/hotspot/test/runtime/SharedArchiveFile/BootAppendTests.java Wed May 03 02:32:02 2017 +0000 @@ -24,6 +24,7 @@ /** * @test * @summary Testing -Xbootclasspath/a support for CDS + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) * @library /test/lib * @modules java.base/jdk.internal.misc * java.management @@ -73,7 +74,7 @@ logTestCase("1"); testBootAppendModuleClass(); - log("TESTCASE: 2"); + logTestCase("2"); testBootAppendDuplicateModuleClass(); logTestCase("3"); @@ -123,11 +124,11 @@ for (String mode : modes) { CDSOptions opts = (new CDSOptions()) .setXShareMode(mode).setUseVersion(false) - .addPrefix("-Xbootclasspath/a:" + bootAppendJar, "-cp", appJar) + .addPrefix("-Xbootclasspath/a:" + bootAppendJar, "-cp", appJar, "-showversion") .addSuffix(APP_CLASS, BOOT_APPEND_MODULE_CLASS_NAME); - CDSTestUtils.runWithArchive(opts) - .shouldContain("java.lang.ClassNotFoundException: javax.sound.sampled.MyClass"); + OutputAnalyzer out = CDSTestUtils.runWithArchive(opts); + CDSTestUtils.checkExec(out, opts, "java.lang.ClassNotFoundException: javax.sound.sampled.MyClass"); } } @@ -144,11 +145,13 @@ for (String mode : modes) { CDSOptions opts = (new CDSOptions()) .setXShareMode(mode).setUseVersion(false) - .addPrefix("-Xbootclasspath/a:" + bootAppendJar, "-cp", appJar) - .addSuffix(APP_CLASS, BOOT_APPEND_DUPLICATE_MODULE_CLASS_NAME); + .addPrefix("--add-modules", "java.corba", "-showversion", + "-Xbootclasspath/a:" + bootAppendJar, "-cp", appJar) + .addSuffix("-Xlog:class+load=info", + APP_CLASS, BOOT_APPEND_DUPLICATE_MODULE_CLASS_NAME); - CDSTestUtils.runWithArchive(opts) - .shouldContain("[class,load] org.omg.CORBA.Context source: jrt:/java.corba"); + OutputAnalyzer out = CDSTestUtils.runWithArchive(opts); + CDSTestUtils.checkExec(out, opts, "[class,load] org.omg.CORBA.Context source: jrt:/java.corba"); } } @@ -164,17 +167,17 @@ for (String mode : modes) { CDSOptions opts = (new CDSOptions()) .setXShareMode(mode).setUseVersion(false) - .addPrefix("-Xbootclasspath/a:" + bootAppendJar, + .addPrefix("-Xbootclasspath/a:" + bootAppendJar, "-showversion", "--limit-modules=java.base", "-cp", appJar) .addSuffix("-Xlog:class+load=info", APP_CLASS, BOOT_APPEND_MODULE_CLASS_NAME); - OutputAnalyzer out = CDSTestUtils.runWithArchive(opts) - .shouldContain("[class,load] javax.sound.sampled.MyClass"); + OutputAnalyzer out = CDSTestUtils.runWithArchive(opts); + CDSTestUtils.checkExec(out, opts, "[class,load] javax.sound.sampled.MyClass"); // When CDS is enabled, the shared class should be loaded from the archive. if (mode.equals("on")) { - out.shouldContain("[class,load] javax.sound.sampled.MyClass source: shared objects file"); + CDSTestUtils.checkExec(out, opts, "[class,load] javax.sound.sampled.MyClass source: shared objects file"); } } } @@ -193,14 +196,16 @@ for (String mode : modes) { CDSOptions opts = (new CDSOptions()) .setXShareMode(mode).setUseVersion(false) - .addPrefix("-Xbootclasspath/a:" + bootAppendJar, + .addPrefix("-Xbootclasspath/a:" + bootAppendJar, "-showversion", "--limit-modules=java.base", "-cp", appJar) .addSuffix("-Xlog:class+load=info", APP_CLASS, BOOT_APPEND_DUPLICATE_MODULE_CLASS_NAME); - CDSTestUtils.runWithArchive(opts) - .shouldContain("[class,load] org.omg.CORBA.Context") - .shouldMatch(".*\\[class,load\\] org.omg.CORBA.Context source:.*bootAppend.jar"); + OutputAnalyzer out = CDSTestUtils.runWithArchive(opts); + CDSTestUtils.checkExec(out, opts, "[class,load] org.omg.CORBA.Context"); + if (!CDSTestUtils.isUnableToMap(out)) { + out.shouldMatch(".*\\[class,load\\] org.omg.CORBA.Context source:.*bootAppend.jar"); + } } } @@ -215,18 +220,18 @@ for (String mode : modes) { CDSOptions opts = (new CDSOptions()) .setXShareMode(mode).setUseVersion(false) - .addPrefix("-Xbootclasspath/a:" + bootAppendJar, + .addPrefix("-Xbootclasspath/a:" + bootAppendJar, "-showversion", "--limit-modules=java.base", "-cp", appJar) .addSuffix("-Xlog:class+load=info", APP_CLASS, BOOT_APPEND_CLASS_NAME); - OutputAnalyzer out = CDSTestUtils.runWithArchive(opts) - .shouldContain("[class,load] nonjdk.myPackage.MyClass"); + OutputAnalyzer out = CDSTestUtils.runWithArchive(opts); + CDSTestUtils.checkExec(out, opts, "[class,load] nonjdk.myPackage.MyClass"); // If CDS is enabled, the nonjdk.myPackage.MyClass should be loaded // from the shared archive. if (mode.equals("on")) { - out.shouldContain( + CDSTestUtils.checkExec(out, opts, "[class,load] nonjdk.myPackage.MyClass source: shared objects file"); } } diff -r 2f733d553ca0 -r 02a1fc064144 hotspot/test/runtime/SharedArchiveFile/CdsDifferentCompactStrings.java --- a/hotspot/test/runtime/SharedArchiveFile/CdsDifferentCompactStrings.java Tue May 02 19:27:26 2017 -0700 +++ b/hotspot/test/runtime/SharedArchiveFile/CdsDifferentCompactStrings.java Wed May 03 02:32:02 2017 +0000 @@ -25,6 +25,7 @@ * @test CdsDifferentCompactStrings * @summary CDS (class data sharing) requires the same -XX:[+-]CompactStrings * setting between archive creation time and load time. + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) * @library /test/lib * @modules java.base/jdk.internal.misc * java.management diff -r 2f733d553ca0 -r 02a1fc064144 hotspot/test/runtime/SharedArchiveFile/CdsDifferentObjectAlignment.java --- a/hotspot/test/runtime/SharedArchiveFile/CdsDifferentObjectAlignment.java Tue May 02 19:27:26 2017 -0700 +++ b/hotspot/test/runtime/SharedArchiveFile/CdsDifferentObjectAlignment.java Wed May 03 02:32:02 2017 +0000 @@ -28,6 +28,7 @@ * This is a negative test; using object alignment for loading that * is different from object alignment for creating a CDS file * should fail when loading. + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) * @library /test/lib * @bug 8025642 * @modules java.base/jdk.internal.misc diff -r 2f733d553ca0 -r 02a1fc064144 hotspot/test/runtime/SharedArchiveFile/CdsSameObjectAlignment.java --- a/hotspot/test/runtime/SharedArchiveFile/CdsSameObjectAlignment.java Tue May 02 19:27:26 2017 -0700 +++ b/hotspot/test/runtime/SharedArchiveFile/CdsSameObjectAlignment.java Wed May 03 02:32:02 2017 +0000 @@ -25,6 +25,7 @@ * @test CdsSameObjectAlignment * @summary Testing CDS (class data sharing) using varying object alignment. * Using same object alignment for each dump/load pair + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) * @library /test/lib * @modules java.base/jdk.internal.misc * java.management diff -r 2f733d553ca0 -r 02a1fc064144 hotspot/test/runtime/SharedArchiveFile/DefaultUseWithClient.java --- a/hotspot/test/runtime/SharedArchiveFile/DefaultUseWithClient.java Tue May 02 19:27:26 2017 -0700 +++ b/hotspot/test/runtime/SharedArchiveFile/DefaultUseWithClient.java Wed May 03 02:32:02 2017 +0000 @@ -24,6 +24,7 @@ /* * @test DefaultUseWithClient * @summary Test default behavior of sharing with -client + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) * @library /test/lib * @modules java.base/jdk.internal.misc * java.management diff -r 2f733d553ca0 -r 02a1fc064144 hotspot/test/runtime/SharedArchiveFile/LargeSharedSpace.java --- a/hotspot/test/runtime/SharedArchiveFile/LargeSharedSpace.java Tue May 02 19:27:26 2017 -0700 +++ b/hotspot/test/runtime/SharedArchiveFile/LargeSharedSpace.java Wed May 03 02:32:02 2017 +0000 @@ -26,6 +26,7 @@ * @bug 8168790 8169870 * @summary Test CDS dumping using specific space size without crashing. * The space size used in the test might not be suitable on windows. + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) * @requires (os.family != "windows") * @library /test/lib * @modules java.base/jdk.internal.misc diff -r 2f733d553ca0 -r 02a1fc064144 hotspot/test/runtime/SharedArchiveFile/LimitSharedSizes.java --- a/hotspot/test/runtime/SharedArchiveFile/LimitSharedSizes.java Tue May 02 19:27:26 2017 -0700 +++ b/hotspot/test/runtime/SharedArchiveFile/LimitSharedSizes.java Wed May 03 02:32:02 2017 +0000 @@ -23,6 +23,7 @@ /* @test LimitSharedSizes * @summary Test handling of limits on shared space size + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) * @library /test/lib /runtime/CommandLine/OptionsValidation/common * @modules java.base/jdk.internal.misc * java.management diff -r 2f733d553ca0 -r 02a1fc064144 hotspot/test/runtime/SharedArchiveFile/PrintSharedArchiveAndExit.java --- a/hotspot/test/runtime/SharedArchiveFile/PrintSharedArchiveAndExit.java Tue May 02 19:27:26 2017 -0700 +++ b/hotspot/test/runtime/SharedArchiveFile/PrintSharedArchiveAndExit.java Wed May 03 02:32:02 2017 +0000 @@ -25,6 +25,7 @@ * @test * @bug 8066670 * @summary Testing -XX:+PrintSharedArchiveAndExit option + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) * @library /test/lib * @modules java.base/jdk.internal.misc * java.management diff -r 2f733d553ca0 -r 02a1fc064144 hotspot/test/runtime/SharedArchiveFile/SASymbolTableTest.java --- a/hotspot/test/runtime/SharedArchiveFile/SASymbolTableTest.java Tue May 02 19:27:26 2017 -0700 +++ b/hotspot/test/runtime/SharedArchiveFile/SASymbolTableTest.java Wed May 03 02:32:02 2017 +0000 @@ -24,6 +24,7 @@ /* * @test SASymbolTableTest * @summary Walk symbol table using SA, with and without CDS. + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) * @library /test/lib * @modules java.base/jdk.internal.misc * jdk.hotspot.agent/sun.jvm.hotspot.oops diff -r 2f733d553ca0 -r 02a1fc064144 hotspot/test/runtime/SharedArchiveFile/SharedArchiveFile.java --- a/hotspot/test/runtime/SharedArchiveFile/SharedArchiveFile.java Tue May 02 19:27:26 2017 -0700 +++ b/hotspot/test/runtime/SharedArchiveFile/SharedArchiveFile.java Wed May 03 02:32:02 2017 +0000 @@ -25,6 +25,7 @@ * @test * @bug 8014138 * @summary Testing new -XX:SharedArchiveFile= option + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) * @library /test/lib * @modules java.base/jdk.internal.misc * java.management @@ -40,14 +41,14 @@ // methods to form command line to create/use shared archive. public class SharedArchiveFile { public static void main(String[] args) throws Exception { - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, "-XX:+UnlockDiagnosticVMOptions", "-XX:SharedArchiveFile=./SharedArchiveFile.jsa", "-Xshare:dump"); OutputAnalyzer out = CDSTestUtils.executeAndLog(pb, "SharedArchiveFile"); CDSTestUtils.checkDump(out); - pb = ProcessTools.createJavaProcessBuilder( + pb = ProcessTools.createJavaProcessBuilder(true, "-XX:+UnlockDiagnosticVMOptions", "-XX:SharedArchiveFile=./SharedArchiveFile.jsa", "-Xshare:on", "-version"); diff -r 2f733d553ca0 -r 02a1fc064144 hotspot/test/runtime/SharedArchiveFile/SharedBaseAddress.java --- a/hotspot/test/runtime/SharedArchiveFile/SharedBaseAddress.java Tue May 02 19:27:26 2017 -0700 +++ b/hotspot/test/runtime/SharedArchiveFile/SharedBaseAddress.java Wed May 03 02:32:02 2017 +0000 @@ -25,6 +25,7 @@ * @test SharedBaseAddress * @summary Test variety of values for SharedBaseAddress, making sure * VM handles normal values as well as edge values w/o a crash. + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) * @library /test/lib * @modules java.base/jdk.internal.misc * java.management diff -r 2f733d553ca0 -r 02a1fc064144 hotspot/test/runtime/SharedArchiveFile/SharedSymbolTableBucketSize.java --- a/hotspot/test/runtime/SharedArchiveFile/SharedSymbolTableBucketSize.java Tue May 02 19:27:26 2017 -0700 +++ b/hotspot/test/runtime/SharedArchiveFile/SharedSymbolTableBucketSize.java Wed May 03 02:32:02 2017 +0000 @@ -25,6 +25,7 @@ * @test * @bug 8059510 * @summary Test SharedSymbolTableBucketSize option + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) * @library /test/lib * @modules java.base/jdk.internal.misc * java.management diff -r 2f733d553ca0 -r 02a1fc064144 hotspot/test/runtime/SharedArchiveFile/SpaceUtilizationCheck.java --- a/hotspot/test/runtime/SharedArchiveFile/SpaceUtilizationCheck.java Tue May 02 19:27:26 2017 -0700 +++ b/hotspot/test/runtime/SharedArchiveFile/SpaceUtilizationCheck.java Wed May 03 02:32:02 2017 +0000 @@ -24,6 +24,7 @@ /* * @test SpaceUtilizationCheck * @summary Check if the space utilization for shared spaces is adequate + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) * @library /test/lib * @modules java.base/jdk.internal.misc * java.management diff -r 2f733d553ca0 -r 02a1fc064144 hotspot/test/runtime/SharedArchiveFile/TestInterpreterMethodEntries.java --- a/hotspot/test/runtime/SharedArchiveFile/TestInterpreterMethodEntries.java Tue May 02 19:27:26 2017 -0700 +++ b/hotspot/test/runtime/SharedArchiveFile/TestInterpreterMethodEntries.java Wed May 03 02:32:02 2017 +0000 @@ -26,6 +26,7 @@ * @bug 8169711 * @summary Test interpreter method entries for intrinsics with CDS (class data sharing) * and different settings of the intrinsic flag during dump/use of the archive. + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) * @library /test/lib * @modules java.base/jdk.internal.misc * java.management