mirror of
https://github.com/openjdk/jdk.git
synced 2026-06-08 11:35:21 +00:00
Merge
This commit is contained in:
commit
0c74ceb12d
@ -560,6 +560,7 @@ fc7e94cb748507366b839e859f865f724467446a jdk-10+0
|
||||
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 @@ b01c519b715ef6f785d0631adee0a6537cf6c12e jdk-9+162
|
||||
0af429be8bbaeaaf0cb838e9af28c953dda6a9c8 jdk-9+164
|
||||
c92c6416ca03b1464d5ed99cf6201e52b5ba0a70 jdk-9+165
|
||||
560d7aa083a24b6a56443feb8de0f40435d33aa9 jdk-9+166
|
||||
48809c513ed5ebb4d4dbf2f454afcce2780db6db jdk-10+2
|
||||
|
||||
@ -968,10 +968,11 @@ class StubGenerator: public StubCodeGenerator {
|
||||
// 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 @@ class StubGenerator: public StubCodeGenerator {
|
||||
// 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
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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 @@ public class SymbolTable extends sun.jvm.hotspot.utilities.Hashtable {
|
||||
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 @@ public class SymbolTable extends sun.jvm.hotspot.utilities.Hashtable {
|
||||
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 class SymbolTable extends sun.jvm.hotspot.utilities.Hashtable {
|
||||
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());
|
||||
|
||||
@ -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(intptr_t store_value, volatile intptr_t* dest) { *
|
||||
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::inc_ptr(volatile void* dest) {
|
||||
}
|
||||
|
||||
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 @@ inline void* Atomic::xchg_ptr(void* exchange_value, volatile void* des
|
||||
|
||||
#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 void Atomic::store (jlong store_value, volatile jlong* dest) { *
|
||||
|
||||
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::add_ptr(intptr_t add_value, volatile void* dest) {
|
||||
}
|
||||
|
||||
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 intptr_t Atomic::xchg_ptr(intptr_t exchange_value, volatile intptr_t* des
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -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(intptr_t store_value, volatile intptr_t* dest) { *
|
||||
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::inc_ptr(volatile void* dest) {
|
||||
}
|
||||
|
||||
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 @@ inline void* Atomic::xchg_ptr(void* exchange_value, volatile void* des
|
||||
|
||||
#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 void Atomic::store (jlong store_value, volatile jlong* dest) { *
|
||||
|
||||
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::add_ptr(intptr_t add_value, volatile void* dest) {
|
||||
}
|
||||
|
||||
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 intptr_t Atomic::xchg_ptr(intptr_t exchange_value, volatile intptr_t* des
|
||||
}
|
||||
|
||||
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 @@ inline intptr_t Atomic::xchg_ptr(intptr_t exchange_value, volatile intptr_t* des
|
||||
|
||||
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) {
|
||||
|
||||
@ -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 @@ mmx_acs_CopyLeft:
|
||||
|
||||
# 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 @@ _Atomic_cmpxchg_long:
|
||||
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
|
||||
|
||||
@ -404,7 +404,7 @@ int VM_Version::platform_features(int features) {
|
||||
// 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 @@ int VM_Version::platform_features(int features) {
|
||||
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;
|
||||
|
||||
@ -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 @@ inline void Atomic::dec_ptr(volatile void* dest) { (void)add_ptr(-1, dest);
|
||||
// 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 @@ inline jint Atomic::xchg (jint exchange_value, volatile jint*
|
||||
|
||||
#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 @@ inline void Atomic::store(jlong store_value, volatile jlong* dest) {
|
||||
#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 @@ extern "C" {
|
||||
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 @@ extern "C" {
|
||||
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
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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 @@ mmx_acs_CopyLeft:
|
||||
|
||||
/ 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 @@ _Atomic_cmpxchg_long_gcc:
|
||||
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
|
||||
|
||||
@ -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 (jint store_value, volatile jint* dest) { *
|
||||
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 @@ inline jlong Atomic::load(volatile jlong* src) { return *src; }
|
||||
#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::add_ptr(intptr_t add_value, volatile void* dest) {
|
||||
|
||||
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::inc_ptr(volatile void* dest) {
|
||||
|
||||
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 @@ inline void* Atomic::xchg_ptr(void* exchange_value, volatile void* des
|
||||
#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 @@ inline jlong Atomic::cmpxchg (jlong exchange_value, volatile jlong*
|
||||
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
|
||||
}
|
||||
|
||||
@ -102,6 +102,7 @@ ClassLoaderData::ClassLoaderData(Handle h_class_loader, bool is_anonymous, Depen
|
||||
// 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 @@ void ClassLoaderData::modules_do(void f(ModuleEntry*)) {
|
||||
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::modules_do(void f(ModuleEntry*)) {
|
||||
}
|
||||
|
||||
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 @@ void ClassLoaderData::unload() {
|
||||
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 @@ bool ClassLoaderDataGraph::do_unloading(BoolObjectClosure* is_alive_closure,
|
||||
// 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()) {
|
||||
|
||||
@ -347,8 +347,7 @@ class ClassLoaderData : public CHeapObj<mtClass> {
|
||||
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); }
|
||||
|
||||
@ -174,8 +174,6 @@ PackageEntryTable::PackageEntryTable(int table_size)
|
||||
}
|
||||
|
||||
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 @@ PackageEntry* PackageEntryTable::lookup_only(Symbol* name) {
|
||||
// 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<Symbol*> *pkg_list) {
|
||||
assert_lock_strong(Module_lock);
|
||||
for (int i = 0; i < table_size(); i++) {
|
||||
for (PackageEntry* entry = bucket(i);
|
||||
entry != NULL;
|
||||
|
||||
@ -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 @@ extern "C" void bad_compiled_vtable_index(JavaThread* thread, oop receiver, int
|
||||
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
|
||||
|
||||
@ -923,8 +923,6 @@ public:
|
||||
|
||||
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;
|
||||
|
||||
@ -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 @@ void MarkSweep::set_ref_processor(ReferenceProcessor* rp) {
|
||||
mark_and_push_closure.set_ref_processor(_ref_processor);
|
||||
}
|
||||
|
||||
MarkSweep::AdjustPointerClosure MarkSweep::adjust_pointer_closure;
|
||||
AdjustPointerClosure MarkSweep::adjust_pointer_closure;
|
||||
|
||||
template <typename T>
|
||||
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 @@ void marksweep_init() {
|
||||
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<true>(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<true>(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 <class T> 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 <class T> 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<narrowOop>(obj);
|
||||
} else {
|
||||
adjust_object_specialized<oop>(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<true>(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)
|
||||
|
||||
@ -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 @@ class STWGCTimer;
|
||||
// declared at end
|
||||
class PreservedMark;
|
||||
class MarkAndPushClosure;
|
||||
class AdjustPointerClosure;
|
||||
|
||||
class MarkSweep : AllStatic {
|
||||
//
|
||||
@ -66,16 +67,6 @@ class MarkSweep : AllStatic {
|
||||
virtual void do_void();
|
||||
};
|
||||
|
||||
class AdjustPointerClosure: public OopsInGenClosure {
|
||||
public:
|
||||
template <typename T> 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 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class AdjustPointerClosure: public OopsInGenClosure {
|
||||
public:
|
||||
template <typename T> 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;
|
||||
|
||||
@ -42,7 +42,7 @@ inline bool MarkSweep::is_archive_object(oop object) {
|
||||
}
|
||||
|
||||
inline int MarkSweep::adjust_pointers(oop obj) {
|
||||
return obj->ms_adjust_pointers();
|
||||
return obj->oop_iterate_size(&MarkSweep::adjust_pointer_closure);
|
||||
}
|
||||
|
||||
template <class T> inline void MarkSweep::adjust_pointer(T* p) {
|
||||
|
||||
@ -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 FastScanClosure;
|
||||
class FilteringClosure;
|
||||
// MarkSweep
|
||||
class MarkAndPushClosure;
|
||||
class AdjustPointerClosure;
|
||||
// ParNew
|
||||
class ParScanWithBarrierClosure;
|
||||
class ParScanWithoutBarrierClosure;
|
||||
@ -90,7 +91,8 @@ class NoHeaderExtendedOopClosure;
|
||||
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) \
|
||||
|
||||
@ -86,14 +86,15 @@ class UnlockFlagSaver {
|
||||
// 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 @@ void InterpreterRuntime::set_bcp_and_mdp(address bcp, JavaThread *thread) {
|
||||
|
||||
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 @@ IRT_ENTRY(void, InterpreterRuntime::resolve_ldc(JavaThread* thread, Bytecodes::C
|
||||
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_END
|
||||
|
||||
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 @@ IRT_END
|
||||
// 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 @@ void InterpreterRuntime::note_trap_inner(JavaThread* thread, int reason,
|
||||
// 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 @@ IRT_END
|
||||
// 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 @@ IRT_ENTRY(address, InterpreterRuntime::exception_handler_for_exception(JavaThrea
|
||||
// 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 @@ void InterpreterRuntime::resolve_get_put(JavaThread* thread, Bytecodes::Code byt
|
||||
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 @@ IRT_END
|
||||
|
||||
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 @@ void InterpreterRuntime::resolve_invoke(JavaThread* thread, Bytecodes::Code byte
|
||||
|
||||
// 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 @@ void InterpreterRuntime::resolve_invoke(JavaThread* thread, Bytecodes::Code byte
|
||||
"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_invoke(JavaThread* thread, Bytecodes::Code byte
|
||||
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 @@ nmethod* InterpreterRuntime::frequency_counter_overflow(JavaThread* thread, addr
|
||||
// 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 @@ IRT_ENTRY(nmethod*,
|
||||
// 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 @@ IRT_ENTRY(nmethod*,
|
||||
if (UseBiasedLocking) {
|
||||
ResourceMark rm;
|
||||
GrowableArray<Handle>* objects_to_revoke = new GrowableArray<Handle>();
|
||||
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 @@ IRT_ENTRY(void, InterpreterRuntime::profile_method(JavaThread* thread))
|
||||
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 @@ IRT_ENTRY(void, InterpreterRuntime::update_mdp_for_ret(JavaThread* thread, int r
|
||||
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 @@ IRT_ENTRY(void, InterpreterRuntime::update_mdp_for_ret(JavaThread* thread, int r
|
||||
|
||||
// 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 @@ IRT_ENTRY(void, InterpreterRuntime::at_safepoint(JavaThread* thread))
|
||||
// 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 @@ ConstantPoolCacheEntry *cp_entry))
|
||||
}
|
||||
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 @@ IRT_ENTRY(void, InterpreterRuntime::post_field_modification(JavaThread *thread,
|
||||
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 @@ IRT_LEAF(void, InterpreterRuntime::popframe_move_outgoing_args(JavaThread* threa
|
||||
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 @@ IRT_END
|
||||
// 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
|
||||
|
||||
@ -42,29 +42,54 @@ class InterpreterRuntime: AllStatic {
|
||||
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) {
|
||||
// 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]; }
|
||||
// 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(); }
|
||||
|
||||
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)); }
|
||||
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)
|
||||
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)); }
|
||||
|
||||
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 @@ class InterpreterRuntime: AllStatic {
|
||||
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);
|
||||
|
||||
@ -150,8 +150,6 @@ CallInfo::CallInfo(Method* resolved_method, Klass* resolved_klass) {
|
||||
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 @@ CallInfo::CallInfo(Method* resolved_method, Klass* resolved_klass) {
|
||||
#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 @@ int LinkResolver::vtable_index_of_interface_method(Klass* klass,
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
@ -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 @@ class ExtendedOopClosure : public OopClosure {
|
||||
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():
|
||||
//
|
||||
|
||||
@ -526,8 +526,7 @@ void Universe::run_finalizers_on_exit() {
|
||||
// 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 Universe::reinitialize_vtable_of(Klass* ko, TRAPS) {
|
||||
|
||||
|
||||
void initialize_itable_for_klass(Klass* k, TRAPS) {
|
||||
InstanceKlass::cast(k)->itable()->initialize_itable(false, CHECK);
|
||||
InstanceKlass::cast(k)->itable().initialize_itable(false, CHECK);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -99,7 +99,7 @@ ArrayKlass::ArrayKlass(Symbol* name) :
|
||||
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
|
||||
|
||||
@ -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 @@ public:
|
||||
|
||||
// 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);
|
||||
|
||||
@ -373,8 +373,8 @@ bool InstanceKlass::should_be_initialized() const {
|
||||
return !is_initialized();
|
||||
}
|
||||
|
||||
klassItable* InstanceKlass::itable() const {
|
||||
return new klassItable(const_cast<InstanceKlass*>(this));
|
||||
klassItable InstanceKlass::itable() const {
|
||||
return klassItable(const_cast<InstanceKlass*>(this));
|
||||
}
|
||||
|
||||
void InstanceKlass::eager_initialize(Thread *thread) {
|
||||
@ -621,15 +621,14 @@ bool InstanceKlass::link_class_impl(bool throw_verifyerror, TRAPS) {
|
||||
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 @@ void InstanceKlass::initialize_impl(TRAPS) {
|
||||
// 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 @@ void InstanceKlass::restore_unshareable_info(ClassLoaderData* loader_data, Handl
|
||||
// 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 @@ void InstanceKlass::verify_on(outputStream* st) {
|
||||
|
||||
// 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
|
||||
|
||||
@ -1127,7 +1127,7 @@ public:
|
||||
}
|
||||
|
||||
// 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 @@ public:
|
||||
|
||||
// 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);
|
||||
|
||||
@ -89,8 +89,6 @@ class InstanceMirrorKlass: public InstanceKlass {
|
||||
|
||||
// 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);
|
||||
|
||||
@ -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 @@ class InstanceRefKlass: public InstanceKlass {
|
||||
|
||||
// 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 @@ private:
|
||||
template <bool nv, class OopClosureType>
|
||||
inline void oop_oop_iterate_ref_processing(oop obj, OopClosureType* closure);
|
||||
|
||||
// Building blocks for specialized handling.
|
||||
template <bool nv, typename T, class OopClosureType, class Contains>
|
||||
static void do_referent(oop obj, OopClosureType* closure, Contains& contains);
|
||||
|
||||
template <bool nv, typename T, class OopClosureType, class Contains>
|
||||
static void do_next(oop obj, OopClosureType* closure, Contains& contains);
|
||||
|
||||
template <bool nv, typename T, class OopClosureType, class Contains>
|
||||
static void do_discovered(oop obj, OopClosureType* closure, Contains& contains);
|
||||
|
||||
template <typename T, class OopClosureType>
|
||||
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 <bool nv, typename T, class OopClosureType, class Contains>
|
||||
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 <bool nv, typename T, class OopClosureType, class Contains>
|
||||
static void oop_oop_iterate_fields(oop obj, OopClosureType* closure, Contains& contains);
|
||||
|
||||
template <typename T>
|
||||
static void trace_reference_gc(const char *s, oop obj, T* referent_addr, T* next_addr, T* discovered_addr) NOT_DEBUG_RETURN;
|
||||
|
||||
public:
|
||||
|
||||
|
||||
@ -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,39 +36,99 @@
|
||||
#include "utilities/macros.hpp"
|
||||
|
||||
template <bool nv, typename T, class OopClosureType, class Contains>
|
||||
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);
|
||||
if (closure->apply_to_weak_ref_discovered_field()) {
|
||||
Devirtualizer<nv>::do_oop(closure, disc_addr);
|
||||
}
|
||||
|
||||
void InstanceRefKlass::do_referent(oop obj, OopClosureType* closure, Contains& 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<nv>::do_oop(closure, referent_addr);
|
||||
}
|
||||
if (contains(referent_addr)) {
|
||||
Devirtualizer<nv>::do_oop(closure, referent_addr);
|
||||
}
|
||||
}
|
||||
|
||||
template <bool nv, typename T, class OopClosureType, class Contains>
|
||||
void InstanceRefKlass::do_next(oop obj, OopClosureType* closure, Contains& 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<nv>::do_oop(closure, disc_addr);
|
||||
}
|
||||
// treat next as normal oop
|
||||
if (contains(next_addr)) {
|
||||
Devirtualizer<nv>::do_oop(closure, next_addr);
|
||||
}
|
||||
}
|
||||
|
||||
template <bool nv, typename T, class OopClosureType, class Contains>
|
||||
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<nv>::do_oop(closure, discovered_addr);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, class OopClosureType>
|
||||
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 <bool nv, typename T, class OopClosureType, class Contains>
|
||||
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()) {
|
||||
do_discovered<nv, T>(obj, closure, contains);
|
||||
}
|
||||
|
||||
// Try to discover reference and return if it succeeds.
|
||||
if (try_discover<T>(obj, type, closure)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Treat referent as normal oop.
|
||||
do_referent<nv, T>(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<nv, T>(obj, closure, contains);
|
||||
}
|
||||
|
||||
// Treat next as normal oop.
|
||||
do_next<nv, T>(obj, closure, contains);
|
||||
}
|
||||
|
||||
template <bool nv, typename T, class OopClosureType, class Contains>
|
||||
void InstanceRefKlass::oop_oop_iterate_fields(oop obj, OopClosureType* closure, Contains& contains) {
|
||||
do_referent<nv, T>(obj, closure, contains);
|
||||
do_discovered<nv, T>(obj, closure, contains);
|
||||
do_next<nv, T>(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 <bool nv, typename T, class OopClosureType, class Contains>
|
||||
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<nv, T>(obj, reference_type(), closure, contains);
|
||||
break;
|
||||
case ExtendedOopClosure::DO_FIELDS:
|
||||
oop_oop_iterate_fields<nv, T>(obj, closure, contains);
|
||||
break;
|
||||
default:
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
}
|
||||
|
||||
class AlwaysContains {
|
||||
public:
|
||||
template <typename T> bool operator()(T* p) const { return true; }
|
||||
@ -125,6 +185,19 @@ void InstanceRefKlass::oop_oop_iterate_bounded(oop obj, OopClosureType* closure,
|
||||
oop_oop_iterate_ref_processing_bounded<nv>(obj, closure, mr);
|
||||
}
|
||||
|
||||
#ifdef ASSERT
|
||||
template <typename T>
|
||||
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) \
|
||||
|
||||
@ -497,10 +497,12 @@ void Klass::remove_unshareable_info() {
|
||||
|
||||
// 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 @@ void Klass::oop_verify_on(oop obj, outputStream* st) {
|
||||
guarantee(obj->klass()->is_klass(), "klass field is not a klass");
|
||||
}
|
||||
|
||||
klassVtable* Klass::vtable() const {
|
||||
return new klassVtable(const_cast<Klass*>(this), start_of_vtable(), vtable_length() / vtableEntry::size());
|
||||
klassVtable Klass::vtable() const {
|
||||
return klassVtable(const_cast<Klass*>(this), start_of_vtable(), vtable_length() / vtableEntry::size());
|
||||
}
|
||||
|
||||
vtableEntry* Klass::start_of_vtable() const {
|
||||
|
||||
@ -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 @@ protected:
|
||||
#endif
|
||||
|
||||
// vtables
|
||||
klassVtable* vtable() const;
|
||||
klassVtable vtable() const;
|
||||
int vtable_length() const { return _vtable_len; }
|
||||
|
||||
// subclass check
|
||||
@ -563,6 +563,8 @@ protected:
|
||||
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 @@ protected:
|
||||
|
||||
// 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;
|
||||
|
||||
@ -136,22 +136,22 @@ int klassVtable::initialize_from_super(Klass* super) {
|
||||
// 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* klassVtable::find_transitive_override(InstanceKlass* initialsuper
|
||||
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 @@ bool klassVtable::update_inherited_vtable(InstanceKlass* klass, methodHandle tar
|
||||
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 @@ bool klassVtable::is_initialized() {
|
||||
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 @@ void klassItable::initialize_itable_for_interface(int method_table_offset, Klass
|
||||
}
|
||||
}
|
||||
|
||||
// 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 @@ void klassVtable::verify(outputStream* st, bool forced) {
|
||||
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 @@ class VtableStats : AllStatic {
|
||||
|
||||
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 @@ class VtableStats : AllStatic {
|
||||
}
|
||||
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() {
|
||||
|
||||
@ -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 @@ class itableMethodEntry VALUE_OBJ_CLASS_SPEC {
|
||||
// -- 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 @@ class klassItable : public ResourceObj {
|
||||
// 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,
|
||||
|
||||
@ -1191,7 +1191,6 @@ bool Method::is_overridden_in(Klass* k) const {
|
||||
}
|
||||
|
||||
assert(ik->is_subclass_of(method_holder()), "should be subklass");
|
||||
assert(ik->vtable() != NULL, "vtable should exist");
|
||||
if (!has_vtable_index()) {
|
||||
return false;
|
||||
} else {
|
||||
|
||||
@ -112,8 +112,6 @@ class ObjArrayKlass : public ArrayKlass {
|
||||
|
||||
// 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);
|
||||
|
||||
@ -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 @@ class oopDesc {
|
||||
|
||||
// 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);
|
||||
|
||||
@ -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 @@ void oopDesc::incr_age() {
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
@ -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 @@ class TypeArrayKlass : public ArrayKlass {
|
||||
|
||||
// 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);
|
||||
|
||||
@ -3272,7 +3272,7 @@ void VM_RedefineClasses::AdjustCpoolCacheAndVtable::do_klass(Klass* k) {
|
||||
// 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 @@ void VM_RedefineClasses::AdjustCpoolCacheAndVtable::do_klass(Klass* k) {
|
||||
// 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 @@ void VM_RedefineClasses::AdjustCpoolCacheAndVtable::do_klass(Klass* k) {
|
||||
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 @@ void VM_RedefineClasses::redefine_single_class(jclass the_jclass,
|
||||
// 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 @@ void VM_RedefineClasses::CheckClass::do_klass(Klass* k) {
|
||||
// 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 @@ void VM_RedefineClasses::CheckClass::do_klass(Klass* k) {
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
@ -218,7 +218,7 @@ oop MethodHandles::init_method_MemberName(Handle mname, CallInfo& info, bool int
|
||||
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());
|
||||
|
||||
@ -289,10 +289,10 @@ Flag::Error OptoLoopAlignmentConstraintFunc(intx value, bool verbose) {
|
||||
}
|
||||
|
||||
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 ArraycopyDstPrefetchDistanceConstraintFunc(uintx value, bool verbose
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@ -865,16 +865,15 @@ static Flag flagTable[] = {
|
||||
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 @@ Flag* Flag::find_flag(const char* name, size_t length, bool allow_locked, bool r
|
||||
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);
|
||||
|
||||
@ -186,6 +186,7 @@ struct Flag {
|
||||
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 @@ struct Flag {
|
||||
Flags get_origin();
|
||||
void set_origin(Flags origin);
|
||||
|
||||
size_t get_name_length();
|
||||
|
||||
bool is_default();
|
||||
bool is_ergonomic();
|
||||
bool is_command_line();
|
||||
|
||||
@ -199,6 +199,7 @@ typedef Hashtable<InstanceKlass*, mtClass> KlassHashtable;
|
||||
typedef HashtableEntry<InstanceKlass*, mtClass> KlassHashtableEntry;
|
||||
typedef TwoOopHashtable<Symbol*, mtClass> SymbolTwoOopHashtable;
|
||||
typedef CompactHashtable<Symbol*, char> SymbolCompactHashTable;
|
||||
typedef RehashableHashtable<Symbol*, mtSymbol> RehashableSymbolHashtable;
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
// VM_STRUCTS
|
||||
@ -584,6 +585,7 @@ typedef CompactHashtable<Symbol*, char> SymbolCompactHashTable;
|
||||
\
|
||||
static_field(SymbolTable, _the_table, SymbolTable*) \
|
||||
static_field(SymbolTable, _shared_table, SymbolCompactHashTable) \
|
||||
static_field(RehashableSymbolHashtable, _seed, juint) \
|
||||
\
|
||||
/***************/ \
|
||||
/* StringTable */ \
|
||||
@ -1602,6 +1604,8 @@ typedef CompactHashtable<Symbol*, char> SymbolCompactHashTable;
|
||||
\
|
||||
declare_toplevel_type(BasicHashtable<mtInternal>) \
|
||||
declare_type(IntptrHashtable, BasicHashtable<mtInternal>) \
|
||||
declare_toplevel_type(BasicHashtable<mtSymbol>) \
|
||||
declare_type(RehashableSymbolHashtable, BasicHashtable<mtSymbol>) \
|
||||
declare_type(SymbolTable, SymbolHashtable) \
|
||||
declare_type(StringTable, StringHashtable) \
|
||||
declare_type(LoaderConstraintTable, KlassHashtable) \
|
||||
|
||||
@ -64,6 +64,7 @@ enum {
|
||||
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 @@ class AccessFlags VALUE_OBJ_CLASS_SPEC {
|
||||
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 @@ class AccessFlags VALUE_OBJ_CLASS_SPEC {
|
||||
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
|
||||
|
||||
@ -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 blob(CodeBlob* cb) {
|
||||
extern "C" void dump_vtable(address p) {
|
||||
Command c("dump_vtable");
|
||||
Klass* k = (Klass*)p;
|
||||
k->vtable()->print();
|
||||
k->vtable().print();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -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 @@ protected:
|
||||
};
|
||||
|
||||
template <class T, MEMFLAGS F> class RehashableHashtable : public Hashtable<T, F> {
|
||||
friend class VMStructs;
|
||||
protected:
|
||||
|
||||
enum {
|
||||
|
||||
@ -113,6 +113,7 @@ compiler/aot/DeoptimizationTest.java 8175791 windows-all
|
||||
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 @@ gc/g1/logging/TestG1LoggingFailure.java 8169634 generic-all
|
||||
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
|
||||
|
||||
#############################################################################
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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 @@ public class BootAppendTests {
|
||||
logTestCase("1");
|
||||
testBootAppendModuleClass();
|
||||
|
||||
log("TESTCASE: 2");
|
||||
logTestCase("2");
|
||||
testBootAppendDuplicateModuleClass();
|
||||
|
||||
logTestCase("3");
|
||||
@ -123,11 +124,11 @@ public class BootAppendTests {
|
||||
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 @@ public class BootAppendTests {
|
||||
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 @@ public class BootAppendTests {
|
||||
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 @@ public class BootAppendTests {
|
||||
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 @@ public class BootAppendTests {
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -25,6 +25,7 @@
|
||||
* @test
|
||||
* @bug 8014138
|
||||
* @summary Testing new -XX:SharedArchiveFile=<file-name> 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 @@ import jdk.test.lib.process.OutputAnalyzer;
|
||||
// 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");
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user