8154580: Save mirror in interpreter frame to enable cleanups of CLDClosure
Summary: GC walks the mirror using OopClosure rather than using CLDClosure in oops_interpreted_do()
Reviewed-by: dlong, twisti, stefank
--- a/hotspot/src/cpu/aarch64/vm/abstractInterpreter_aarch64.cpp Mon Apr 25 11:36:14 2016 +0200
+++ b/hotspot/src/cpu/aarch64/vm/abstractInterpreter_aarch64.cpp Mon Apr 25 09:51:00 2016 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, Red Hat Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -177,4 +177,6 @@
}
*interpreter_frame->interpreter_frame_cache_addr() =
method->constants()->cache();
+ *interpreter_frame->interpreter_frame_mirror_addr() =
+ method->method_holder()->java_mirror();
}
--- a/hotspot/src/cpu/aarch64/vm/frame_aarch64.hpp Mon Apr 25 11:36:14 2016 +0200
+++ b/hotspot/src/cpu/aarch64/vm/frame_aarch64.hpp Mon Apr 25 09:51:00 2016 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, Red Hat Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -78,7 +78,9 @@
interpreter_frame_last_sp_offset = interpreter_frame_sender_sp_offset - 1,
interpreter_frame_method_offset = interpreter_frame_last_sp_offset - 1,
interpreter_frame_mdp_offset = interpreter_frame_method_offset - 1,
- interpreter_frame_cache_offset = interpreter_frame_mdp_offset - 1,
+ interpreter_frame_padding_offset = interpreter_frame_mdp_offset - 1,
+ interpreter_frame_mirror_offset = interpreter_frame_padding_offset - 1,
+ interpreter_frame_cache_offset = interpreter_frame_mirror_offset - 1,
interpreter_frame_locals_offset = interpreter_frame_cache_offset - 1,
interpreter_frame_bcp_offset = interpreter_frame_locals_offset - 1,
interpreter_frame_initial_sp_offset = interpreter_frame_bcp_offset - 1,
--- a/hotspot/src/cpu/aarch64/vm/frame_aarch64.inline.hpp Mon Apr 25 11:36:14 2016 +0200
+++ b/hotspot/src/cpu/aarch64/vm/frame_aarch64.inline.hpp Mon Apr 25 09:51:00 2016 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, Red Hat Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -188,6 +188,12 @@
return (Method**)addr_at(interpreter_frame_method_offset);
}
+// Mirror
+
+inline oop* frame::interpreter_frame_mirror_addr() const {
+ return (oop*)addr_at(interpreter_frame_mirror_offset);
+}
+
// top of expression stack
inline intptr_t* frame::interpreter_frame_tos_address() const {
intptr_t* last_sp = interpreter_frame_last_sp();
--- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp Mon Apr 25 11:36:14 2016 +0200
+++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp Mon Apr 25 09:51:00 2016 -0400
@@ -3217,6 +3217,14 @@
}
}
+void MacroAssembler::load_mirror(Register dst, Register method) {
+ const int mirror_offset = in_bytes(Klass::java_mirror_offset());
+ ldr(dst, Address(rmethod, Method::const_offset()));
+ ldr(dst, Address(dst, ConstMethod::constants_offset()));
+ ldr(dst, Address(dst, ConstantPool::pool_holder_offset_in_bytes()));
+ ldr(dst, Address(dst, mirror_offset));
+}
+
void MacroAssembler::cmp_klass(Register oop, Register trial_klass, Register tmp) {
if (UseCompressedClassPointers) {
ldrw(tmp, Address(oop, oopDesc::klass_offset_in_bytes()));
--- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp Mon Apr 25 11:36:14 2016 +0200
+++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp Mon Apr 25 09:51:00 2016 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2015, Red Hat Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -770,6 +770,8 @@
void store_klass(Register dst, Register src);
void cmp_klass(Register oop, Register trial_klass, Register tmp);
+ void load_mirror(Register dst, Register method);
+
void load_heap_oop(Register dst, Address src);
void load_heap_oop_not_null(Register dst, Address src);
--- a/hotspot/src/cpu/aarch64/vm/templateInterpreterGenerator_aarch64.cpp Mon Apr 25 11:36:14 2016 +0200
+++ b/hotspot/src/cpu/aarch64/vm/templateInterpreterGenerator_aarch64.cpp Mon Apr 25 09:51:00 2016 -0400
@@ -759,18 +759,13 @@
// get synchronization object
{
- const int mirror_offset = in_bytes(Klass::java_mirror_offset());
Label done;
__ ldrw(r0, access_flags);
__ tst(r0, JVM_ACC_STATIC);
// get receiver (assume this is frequent case)
__ ldr(r0, Address(rlocals, Interpreter::local_offset_in_bytes(0)));
__ br(Assembler::EQ, done);
- __ ldr(r0, Address(rmethod, Method::const_offset()));
- __ ldr(r0, Address(r0, ConstMethod::constants_offset()));
- __ ldr(r0, Address(r0,
- ConstantPool::pool_holder_offset_in_bytes()));
- __ ldr(r0, Address(r0, mirror_offset));
+ __ load_mirror(r0, rmethod);
#ifdef ASSERT
{
@@ -807,16 +802,16 @@
void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call) {
// initialize fixed part of activation frame
if (native_call) {
- __ sub(esp, sp, 12 * wordSize);
+ __ sub(esp, sp, 14 * wordSize);
__ mov(rbcp, zr);
- __ stp(esp, zr, Address(__ pre(sp, -12 * wordSize)));
+ __ stp(esp, zr, Address(__ pre(sp, -14 * wordSize)));
// add 2 zero-initialized slots for native calls
- __ stp(zr, zr, Address(sp, 10 * wordSize));
+ __ stp(zr, zr, Address(sp, 12 * wordSize));
} else {
- __ sub(esp, sp, 10 * wordSize);
+ __ sub(esp, sp, 12 * wordSize);
__ ldr(rscratch1, Address(rmethod, Method::const_offset())); // get ConstMethod
__ add(rbcp, rscratch1, in_bytes(ConstMethod::codes_offset())); // get codebase
- __ stp(esp, rbcp, Address(__ pre(sp, -10 * wordSize)));
+ __ stp(esp, rbcp, Address(__ pre(sp, -12 * wordSize)));
}
if (ProfileInterpreter) {
@@ -825,22 +820,26 @@
__ cbz(rscratch1, method_data_continue);
__ lea(rscratch1, Address(rscratch1, in_bytes(MethodData::data_offset())));
__ bind(method_data_continue);
- __ stp(rscratch1, rmethod, Address(sp, 4 * wordSize)); // save Method* and mdp (method data pointer)
+ __ stp(rscratch1, rmethod, Address(sp, 6 * wordSize)); // save Method* and mdp (method data pointer)
} else {
- __ stp(zr, rmethod, Address(sp, 4 * wordSize)); // save Method* (no mdp)
+ __ stp(zr, rmethod, Address(sp, 6 * wordSize)); // save Method* (no mdp)
}
+ // Get mirror and store it in the frame as GC root for this Method*
+ __ load_mirror(rscratch1, rmethod);
+ __ stp(rscratch1, zr, Address(sp, 4 * wordSize));
+
__ ldr(rcpool, Address(rmethod, Method::const_offset()));
__ ldr(rcpool, Address(rcpool, ConstMethod::constants_offset()));
__ ldr(rcpool, Address(rcpool, ConstantPool::cache_offset_in_bytes()));
__ stp(rlocals, rcpool, Address(sp, 2 * wordSize));
- __ stp(rfp, lr, Address(sp, 8 * wordSize));
- __ lea(rfp, Address(sp, 8 * wordSize));
+ __ stp(rfp, lr, Address(sp, 10 * wordSize));
+ __ lea(rfp, Address(sp, 10 * wordSize));
// set sender sp
// leave last_sp as null
- __ stp(zr, r13, Address(sp, 6 * wordSize));
+ __ stp(zr, r13, Address(sp, 8 * wordSize));
// Move SP out of the way
if (! native_call) {
@@ -1242,15 +1241,11 @@
// pass mirror handle if static call
{
Label L;
- const int mirror_offset = in_bytes(Klass::java_mirror_offset());
__ ldrw(t, Address(rmethod, Method::access_flags_offset()));
__ tst(t, JVM_ACC_STATIC);
__ br(Assembler::EQ, L);
// get mirror
- __ ldr(t, Address(rmethod, Method::const_offset()));
- __ ldr(t, Address(t, ConstMethod::constants_offset()));
- __ ldr(t, Address(t, ConstantPool::pool_holder_offset_in_bytes()));
- __ ldr(t, Address(t, mirror_offset));
+ __ load_mirror(t, rmethod);
// copy mirror into activation frame
__ str(t, Address(rfp, frame::interpreter_frame_oop_temp_offset * wordSize));
// pass handle to mirror
--- a/hotspot/src/cpu/ppc/vm/abstractInterpreter_ppc.cpp Mon Apr 25 11:36:14 2016 +0200
+++ b/hotspot/src/cpu/ppc/vm/abstractInterpreter_ppc.cpp Mon Apr 25 09:51:00 2016 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -152,6 +152,7 @@
intptr_t* top_frame_sp = is_top_frame ? sp : sp + (frame::abi_minframe_size - frame::abi_reg_args_size) / Interpreter::stackElementSize;
interpreter_frame->interpreter_frame_set_method(method);
+ interpreter_frame->interpreter_frame_set_mirror(method->method_holder()->java_mirror());
interpreter_frame->interpreter_frame_set_locals(locals_base);
interpreter_frame->interpreter_frame_set_cpcache(method->constants()->cache());
interpreter_frame->interpreter_frame_set_esp(esp);
--- a/hotspot/src/cpu/ppc/vm/frame_ppc.hpp Mon Apr 25 11:36:14 2016 +0200
+++ b/hotspot/src/cpu/ppc/vm/frame_ppc.hpp Mon Apr 25 09:51:00 2016 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2015 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -261,6 +261,7 @@
uint64_t ijava_reserved2; // Inserted for alignment.
#endif
uint64_t method;
+ uint64_t mirror;
uint64_t locals;
uint64_t monitors;
uint64_t cpoolCache;
--- a/hotspot/src/cpu/ppc/vm/frame_ppc.inline.hpp Mon Apr 25 11:36:14 2016 +0200
+++ b/hotspot/src/cpu/ppc/vm/frame_ppc.inline.hpp Mon Apr 25 09:51:00 2016 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2015 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -148,6 +148,11 @@
inline Method** frame::interpreter_frame_method_addr() const {
return (Method**) &(get_ijava_state()->method);
}
+
+inline oop* frame::interpreter_frame_mirror_addr() const {
+ return (oop*) &(get_ijava_state()->mirror);
+}
+
inline ConstantPoolCache** frame::interpreter_frame_cpoolcache_addr() const {
return (ConstantPoolCache**) &(get_ijava_state()->cpoolCache);
}
--- a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp Mon Apr 25 11:36:14 2016 +0200
+++ b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp Mon Apr 25 09:51:00 2016 -0400
@@ -3118,6 +3118,14 @@
}
}
+void MacroAssembler::load_mirror(Register mirror, Register method) {
+ const int mirror_offset = in_bytes(Klass::java_mirror_offset());
+ ld(mirror, in_bytes(Method::const_offset()), method);
+ ld(mirror, in_bytes(ConstMethod::constants_offset()), mirror);
+ ld(mirror, ConstantPool::pool_holder_offset_in_bytes(), mirror);
+ ld(mirror, mirror_offset, mirror);
+}
+
// Clear Array
// Kills both input registers. tmp == R0 is allowed.
void MacroAssembler::clear_memory_doubleword(Register base_ptr, Register cnt_dwords, Register tmp) {
--- a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.hpp Mon Apr 25 11:36:14 2016 +0200
+++ b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.hpp Mon Apr 25 09:51:00 2016 -0400
@@ -647,6 +647,9 @@
void load_klass(Register dst, Register src);
void store_klass(Register dst_oop, Register klass, Register tmp = R0);
void store_klass_gap(Register dst_oop, Register val = noreg); // Will store 0 if val not specified.
+
+ void load_mirror(Register mirror, Register method);
+
static int instr_size_for_decode_klass_not_null();
void decode_klass_not_null(Register dst, Register src = noreg);
Register encode_klass_not_null(Register dst, Register src = noreg);
--- a/hotspot/src/cpu/ppc/vm/templateInterpreterGenerator_ppc.cpp Mon Apr 25 11:36:14 2016 +0200
+++ b/hotspot/src/cpu/ppc/vm/templateInterpreterGenerator_ppc.cpp Mon Apr 25 09:51:00 2016 -0400
@@ -869,7 +869,6 @@
// Get synchronization object to Rscratch2.
{
- const int mirror_offset = in_bytes(Klass::java_mirror_offset());
Label Lstatic;
Label Ldone;
@@ -881,10 +880,7 @@
__ b(Ldone);
__ bind(Lstatic); // Static case: Lock the java mirror
- __ ld(Robj_to_lock, in_bytes(Method::const_offset()), R19_method);
- __ ld(Robj_to_lock, in_bytes(ConstMethod::constants_offset()), Robj_to_lock);
- __ ld(Robj_to_lock, ConstantPool::pool_holder_offset_in_bytes(), Robj_to_lock);
- __ ld(Robj_to_lock, mirror_offset, Robj_to_lock);
+ __ load_mirror(Robj_to_lock, R19_method);
__ bind(Ldone);
__ verify_oop(Robj_to_lock);
@@ -1049,10 +1045,14 @@
__ addi(R26_monitor, R1_SP, - frame::ijava_state_size);
__ addi(R15_esp, R26_monitor, - Interpreter::stackElementSize);
+ // Get mirror and store it in the frame as GC root for this Method*
+ __ load_mirror(R12_scratch2, R19_method);
+
// Store values.
// R15_esp, R14_bcp, R26_monitor, R28_mdx are saved at java calls
// in InterpreterMacroAssembler::call_from_interpreter.
__ std(R19_method, _ijava_state_neg(method), R1_SP);
+ __ std(R12_scratch2, _ijava_state_neg(mirror), R1_SP);
__ std(R21_sender_SP, _ijava_state_neg(sender_sp), R1_SP);
__ std(R27_constPoolCache, _ijava_state_neg(cpoolCache), R1_SP);
__ std(R18_locals, _ijava_state_neg(locals), R1_SP);
@@ -1317,21 +1317,11 @@
__ testbitdi(CCR0, R0, access_flags, JVM_ACC_STATIC_BIT);
__ bfalse(CCR0, method_is_not_static);
- // constants = method->constants();
- __ ld(R11_scratch1, in_bytes(Method::const_offset()), R19_method);
- __ ld(R11_scratch1, in_bytes(ConstMethod::constants_offset()), R11_scratch1);
- // pool_holder = method->constants()->pool_holder();
- __ ld(R11_scratch1/*pool_holder*/, ConstantPool::pool_holder_offset_in_bytes(),
- R11_scratch1/*constants*/);
-
- const int mirror_offset = in_bytes(Klass::java_mirror_offset());
-
- // mirror = pool_holder->klass_part()->java_mirror();
- __ ld(R0/*mirror*/, mirror_offset, R11_scratch1/*pool_holder*/);
+ __ load_mirror(R12_sratch2, R19_method);
// state->_native_mirror = mirror;
__ ld(R11_scratch1, 0, R1_SP);
- __ std(R0/*mirror*/, _ijava_state_neg(oop_tmp), R11_scratch1);
+ __ std(R12_scratch2/*mirror*/, _ijava_state_neg(oop_tmp), R11_scratch1);
// R4_ARG2 = &state->_oop_temp;
__ addi(R4_ARG2, R11_scratch1, _ijava_state_neg(oop_tmp));
BIND(method_is_not_static);
--- a/hotspot/src/cpu/sparc/vm/abstractInterpreter_sparc.cpp Mon Apr 25 11:36:14 2016 +0200
+++ b/hotspot/src/cpu/sparc/vm/abstractInterpreter_sparc.cpp Mon Apr 25 09:51:00 2016 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, 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
@@ -281,11 +281,12 @@
// Llast_SP will be same as SP as there is no adapter space
*interpreter_frame->register_addr(Llast_SP) = (intptr_t) interpreter_frame->sp() - STACK_BIAS;
*interpreter_frame->register_addr(LcpoolCache) = (intptr_t) method->constants()->cache();
+ // save the mirror in the interpreter frame
+ *interpreter_frame->interpreter_frame_mirror_addr() = method->method_holder()->java_mirror();
#ifdef FAST_DISPATCH
*interpreter_frame->register_addr(IdispatchTables) = (intptr_t) Interpreter::dispatch_table();
#endif
-
#ifdef ASSERT
BasicObjectLock* mp = (BasicObjectLock*)monitors;
--- a/hotspot/src/cpu/sparc/vm/frame_sparc.cpp Mon Apr 25 11:36:14 2016 +0200
+++ b/hotspot/src/cpu/sparc/vm/frame_sparc.cpp Mon Apr 25 09:51:00 2016 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, 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
@@ -783,7 +783,7 @@
if (is_interpreted_frame()) {
DESCRIBE_FP_OFFSET(interpreter_frame_d_scratch_fp);
DESCRIBE_FP_OFFSET(interpreter_frame_l_scratch_fp);
- DESCRIBE_FP_OFFSET(interpreter_frame_padding);
+ DESCRIBE_FP_OFFSET(interpreter_frame_mirror);
DESCRIBE_FP_OFFSET(interpreter_frame_oop_temp);
// esp, according to Lesp (e.g. not depending on bci), if seems valid
--- a/hotspot/src/cpu/sparc/vm/frame_sparc.hpp Mon Apr 25 11:36:14 2016 +0200
+++ b/hotspot/src/cpu/sparc/vm/frame_sparc.hpp Mon Apr 25 09:51:00 2016 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, 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
@@ -209,7 +209,8 @@
// 2 words, also used to save float regs across calls to C
interpreter_frame_d_scratch_fp_offset = -2,
interpreter_frame_l_scratch_fp_offset = -4,
- interpreter_frame_padding_offset = -5, // for native calls only
+ interpreter_frame_mirror_offset = -5, // keep interpreted method alive
+
interpreter_frame_oop_temp_offset = -6, // for native calls only
interpreter_frame_vm_locals_fp_offset = -6, // should be same as above, and should be zero mod 8
--- a/hotspot/src/cpu/sparc/vm/frame_sparc.inline.hpp Mon Apr 25 11:36:14 2016 +0200
+++ b/hotspot/src/cpu/sparc/vm/frame_sparc.inline.hpp Mon Apr 25 09:51:00 2016 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, 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
@@ -163,6 +163,10 @@
*interpreter_frame_monitors_addr() = monitors;
}
+inline oop* frame::interpreter_frame_mirror_addr() const {
+ return (oop*)(fp() + interpreter_frame_mirror_offset);
+}
+
// Constant pool cache
// where LcpoolCache is saved:
--- a/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp Mon Apr 25 11:36:14 2016 +0200
+++ b/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp Mon Apr 25 09:51:00 2016 -0400
@@ -3972,6 +3972,14 @@
card_table_write(bs->byte_map_base, tmp, store_addr);
}
+void MacroAssembler::load_mirror(Register mirror, Register method) {
+ const int mirror_offset = in_bytes(Klass::java_mirror_offset());
+ ld_ptr(method, in_bytes(Method::const_offset()), mirror);
+ ld_ptr(mirror, in_bytes(ConstMethod::constants_offset()), mirror);
+ ld_ptr(mirror, ConstantPool::pool_holder_offset_in_bytes(), mirror);
+ ld_ptr(mirror, mirror_offset, mirror);
+}
+
void MacroAssembler::load_klass(Register src_oop, Register klass) {
// The number of bytes in this code is used by
// MachCallDynamicJavaNode::ret_addr_offset()
--- a/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.hpp Mon Apr 25 11:36:14 2016 +0200
+++ b/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.hpp Mon Apr 25 09:51:00 2016 -0400
@@ -1012,6 +1012,8 @@
inline void ldbool(const Address& a, Register d);
inline void movbool( bool boolconst, Register d);
+ void load_mirror(Register mirror, Register method);
+
// klass oop manipulations if compressed
void load_klass(Register src_oop, Register klass);
void store_klass(Register klass, Register dst_oop);
--- a/hotspot/src/cpu/sparc/vm/templateInterpreterGenerator_sparc.cpp Mon Apr 25 11:36:14 2016 +0200
+++ b/hotspot/src/cpu/sparc/vm/templateInterpreterGenerator_sparc.cpp Mon Apr 25 09:51:00 2016 -0400
@@ -557,17 +557,12 @@
// get synchronization object to O0
{ Label done;
- const int mirror_offset = in_bytes(Klass::java_mirror_offset());
__ btst(JVM_ACC_STATIC, O0);
__ br( Assembler::zero, true, Assembler::pt, done);
__ delayed()->ld_ptr(Llocals, Interpreter::local_offset_in_bytes(0), O0); // get receiver for not-static case
- __ ld_ptr( Lmethod, in_bytes(Method::const_offset()), O0);
- __ ld_ptr( O0, in_bytes(ConstMethod::constants_offset()), O0);
- __ ld_ptr( O0, ConstantPool::pool_holder_offset_in_bytes(), O0);
-
// lock the mirror, not the Klass*
- __ ld_ptr( O0, mirror_offset, O0);
+ __ load_mirror(O0, Lmethod);
#ifdef ASSERT
__ tst(O0);
@@ -881,6 +876,10 @@
__ add(Lbcp, in_bytes(ConstMethod::codes_offset()), Lbcp);
}
__ mov( G5_method, Lmethod); // set Lmethod
+ // Get mirror and store it in the frame as GC root for this Method*
+ Register mirror = LcpoolCache;
+ __ load_mirror(mirror, Lmethod);
+ __ st_ptr(mirror, FP, (frame::interpreter_frame_mirror_offset * wordSize) + STACK_BIAS);
__ get_constant_pool_cache( LcpoolCache ); // set LcpoolCache
__ sub(FP, rounded_vm_local_words * BytesPerWord, Lmonitors ); // set Lmonitors
#ifdef _LP64
@@ -1297,12 +1296,7 @@
// get native function entry point(O0 is a good temp until the very end)
__ delayed()->ld_ptr(Lmethod, in_bytes(Method::native_function_offset()), O0);
// for static methods insert the mirror argument
- const int mirror_offset = in_bytes(Klass::java_mirror_offset());
-
- __ ld_ptr(Lmethod, Method:: const_offset(), O1);
- __ ld_ptr(O1, ConstMethod::constants_offset(), O1);
- __ ld_ptr(O1, ConstantPool::pool_holder_offset_in_bytes(), O1);
- __ ld_ptr(O1, mirror_offset, O1);
+ __ load_mirror(O1, Lmethod);
#ifdef ASSERT
if (!PrintSignatureHandlers) // do not dirty the output with this
{ Label L;
--- a/hotspot/src/cpu/x86/vm/abstractInterpreter_x86.cpp Mon Apr 25 11:36:14 2016 +0200
+++ b/hotspot/src/cpu/x86/vm/abstractInterpreter_x86.cpp Mon Apr 25 09:51:00 2016 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, 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
@@ -113,6 +113,8 @@
}
*interpreter_frame->interpreter_frame_cache_addr() =
method->constants()->cache();
+ *interpreter_frame->interpreter_frame_mirror_addr() =
+ method->method_holder()->java_mirror();
}
#ifndef _LP64
--- a/hotspot/src/cpu/x86/vm/frame_x86.cpp Mon Apr 25 11:36:14 2016 +0200
+++ b/hotspot/src/cpu/x86/vm/frame_x86.cpp Mon Apr 25 09:51:00 2016 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, 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
@@ -640,6 +640,7 @@
DESCRIBE_FP_OFFSET(interpreter_frame_sender_sp);
DESCRIBE_FP_OFFSET(interpreter_frame_last_sp);
DESCRIBE_FP_OFFSET(interpreter_frame_method);
+ DESCRIBE_FP_OFFSET(interpreter_frame_mirror);
DESCRIBE_FP_OFFSET(interpreter_frame_mdp);
DESCRIBE_FP_OFFSET(interpreter_frame_cache);
DESCRIBE_FP_OFFSET(interpreter_frame_locals);
--- a/hotspot/src/cpu/x86/vm/frame_x86.hpp Mon Apr 25 11:36:14 2016 +0200
+++ b/hotspot/src/cpu/x86/vm/frame_x86.hpp Mon Apr 25 09:51:00 2016 -0400
@@ -70,7 +70,8 @@
// outgoing sp before a call to an invoked method
interpreter_frame_last_sp_offset = interpreter_frame_sender_sp_offset - 1,
interpreter_frame_method_offset = interpreter_frame_last_sp_offset - 1,
- interpreter_frame_mdp_offset = interpreter_frame_method_offset - 1,
+ interpreter_frame_mirror_offset = interpreter_frame_method_offset - 1,
+ interpreter_frame_mdp_offset = interpreter_frame_mirror_offset - 1,
interpreter_frame_cache_offset = interpreter_frame_mdp_offset - 1,
interpreter_frame_locals_offset = interpreter_frame_cache_offset - 1,
interpreter_frame_bcp_offset = interpreter_frame_locals_offset - 1,
--- a/hotspot/src/cpu/x86/vm/frame_x86.inline.hpp Mon Apr 25 11:36:14 2016 +0200
+++ b/hotspot/src/cpu/x86/vm/frame_x86.inline.hpp Mon Apr 25 09:51:00 2016 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, 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
@@ -184,6 +184,12 @@
return (Method**)addr_at(interpreter_frame_method_offset);
}
+// Mirror
+
+inline oop* frame::interpreter_frame_mirror_addr() const {
+ return (oop*)addr_at(interpreter_frame_mirror_offset);
+}
+
// top of expression stack
inline intptr_t* frame::interpreter_frame_tos_address() const {
intptr_t* last_sp = interpreter_frame_last_sp();
--- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp Mon Apr 25 11:36:14 2016 +0200
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp Mon Apr 25 09:51:00 2016 -0400
@@ -6705,6 +6705,14 @@
#endif // _LP64
}
+void MacroAssembler::load_mirror(Register mirror, Register method) {
+ // get mirror
+ const int mirror_offset = in_bytes(Klass::java_mirror_offset());
+ movptr(mirror, Address(method, Method::const_offset()));
+ movptr(mirror, Address(mirror, ConstMethod::constants_offset()));
+ movptr(mirror, Address(mirror, ConstantPool::pool_holder_offset_in_bytes()));
+ movptr(mirror, Address(mirror, mirror_offset));
+}
void MacroAssembler::load_klass(Register dst, Register src) {
#ifdef _LP64
--- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp Mon Apr 25 11:36:14 2016 +0200
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp Mon Apr 25 09:51:00 2016 -0400
@@ -323,6 +323,8 @@
void movbool(Address dst, Register src);
void testbool(Register dst);
+ void load_mirror(Register mirror, Register method);
+
// oop manipulations
void load_klass(Register dst, Register src);
void store_klass(Register dst, Register src);
--- a/hotspot/src/cpu/x86/vm/templateInterpreterGenerator_x86.cpp Mon Apr 25 11:36:14 2016 +0200
+++ b/hotspot/src/cpu/x86/vm/templateInterpreterGenerator_x86.cpp Mon Apr 25 09:51:00 2016 -0400
@@ -608,18 +608,13 @@
// get synchronization object
{
- const int mirror_offset = in_bytes(Klass::java_mirror_offset());
Label done;
__ movl(rax, access_flags);
__ testl(rax, JVM_ACC_STATIC);
// get receiver (assume this is frequent case)
__ movptr(rax, Address(rlocals, Interpreter::local_offset_in_bytes(0)));
__ jcc(Assembler::zero, done);
- __ movptr(rax, Address(rbx, Method::const_offset()));
- __ movptr(rax, Address(rax, ConstMethod::constants_offset()));
- __ movptr(rax, Address(rax,
- ConstantPool::pool_holder_offset_in_bytes()));
- __ movptr(rax, Address(rax, mirror_offset));
+ __ load_mirror(rax, rbx);
#ifdef ASSERT
{
@@ -662,6 +657,9 @@
__ movptr(rbcp, Address(rbx, Method::const_offset())); // get ConstMethod*
__ lea(rbcp, Address(rbcp, ConstMethod::codes_offset())); // get codebase
__ push(rbx); // save Method*
+ // Get mirror and store it in the frame as GC root for this Method*
+ __ load_mirror(rdx, rbx);
+ __ push(rdx);
if (ProfileInterpreter) {
Label method_data_continue;
__ movptr(rdx, Address(rbx, in_bytes(Method::method_data_offset())));
@@ -999,15 +997,11 @@
// pass mirror handle if static call
{
Label L;
- const int mirror_offset = in_bytes(Klass::java_mirror_offset());
__ movl(t, Address(method, Method::access_flags_offset()));
__ testl(t, JVM_ACC_STATIC);
__ jcc(Assembler::zero, L);
// get mirror
- __ movptr(t, Address(method, Method::const_offset()));
- __ movptr(t, Address(t, ConstMethod::constants_offset()));
- __ movptr(t, Address(t, ConstantPool::pool_holder_offset_in_bytes()));
- __ movptr(t, Address(t, mirror_offset));
+ __ load_mirror(t, method);
// copy mirror into activation frame
__ movptr(Address(rbp, frame::interpreter_frame_oop_temp_offset * wordSize),
t);
--- a/hotspot/src/cpu/zero/vm/bytecodeInterpreter_zero.cpp Mon Apr 25 11:36:14 2016 +0200
+++ b/hotspot/src/cpu/zero/vm/bytecodeInterpreter_zero.cpp Mon Apr 25 09:51:00 2016 -0400
@@ -49,6 +49,7 @@
DO(_locals);
DO(_constants);
DO(_method);
+ DO(_mirror);
DO(_mdx);
DO(_stack);
DO(_msg);
@@ -77,6 +78,7 @@
bool is_top_frame) {
istate->set_locals(locals);
istate->set_method(method);
+ istate->set_mirror(method->method_holder()->java_mirror());
istate->set_self_link(istate);
istate->set_prev_link(NULL);
// thread will be set by a hacky repurposing of frame::patch_pc()
--- a/hotspot/src/cpu/zero/vm/bytecodeInterpreter_zero.hpp Mon Apr 25 11:36:14 2016 +0200
+++ b/hotspot/src/cpu/zero/vm/bytecodeInterpreter_zero.hpp Mon Apr 25 09:51:00 2016 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright 2007, 2008, 2011 Red Hat, Inc.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -44,6 +44,9 @@
inline void set_method(Method* new_method) {
_method = new_method;
}
+ inline void set_mirror(oop new_mirror) {
+ _mirror = new_mirror;
+ }
inline interpreterState self_link() {
return _self_link;
}
--- a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp Mon Apr 25 11:36:14 2016 +0200
+++ b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp Mon Apr 25 09:51:00 2016 -0400
@@ -755,6 +755,7 @@
istate->set_locals(locals);
istate->set_method(method);
+ istate->set_mirror(method->method_holder()->java_mirror());
istate->set_self_link(istate);
istate->set_prev_link(NULL);
istate->set_thread(thread);
--- a/hotspot/src/cpu/zero/vm/frame_zero.inline.hpp Mon Apr 25 11:36:14 2016 +0200
+++ b/hotspot/src/cpu/zero/vm/frame_zero.inline.hpp Mon Apr 25 09:51:00 2016 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright 2007, 2008, 2009, 2010 Red Hat, Inc.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -115,6 +115,10 @@
return &(get_interpreterState()->_method);
}
+inline oop* frame::interpreter_frame_mirror_addr() const {
+ return &(get_interpreterState()->_mirror);
+}
+
inline intptr_t* frame::interpreter_frame_mdp_addr() const {
return (intptr_t*) &(get_interpreterState()->_mdx);
}
--- a/hotspot/src/share/vm/gc/g1/g1RootClosures.cpp Mon Apr 25 11:36:14 2016 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1RootClosures.cpp Mon Apr 25 09:51:00 2016 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, 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,7 +42,6 @@
CLDClosure* weak_clds() { return &_closures._clds; }
CLDClosure* strong_clds() { return &_closures._clds; }
- CLDClosure* thread_root_clds() { return NULL; }
CLDClosure* second_pass_weak_clds() { return NULL; }
CodeBlobClosure* strong_codeblobs() { return &_closures._codeblobs; }
@@ -89,7 +88,6 @@
// If MarkWeak is G1MarkFromRoot then all CLDs are processed by the weak and strong variants
// return a NULL closure for the following specialized versions in that case.
- CLDClosure* thread_root_clds() { return null_if<G1MarkFromRoot>(&_strong._clds); }
CLDClosure* second_pass_weak_clds() { return null_if<G1MarkFromRoot>(&_weak._clds); }
CodeBlobClosure* strong_codeblobs() { return &_strong._codeblobs; }
--- a/hotspot/src/share/vm/gc/g1/g1RootClosures.hpp Mon Apr 25 11:36:14 2016 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1RootClosures.hpp Mon Apr 25 09:51:00 2016 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, 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
@@ -41,9 +41,6 @@
virtual CLDClosure* weak_clds() = 0;
virtual CLDClosure* strong_clds() = 0;
- // Applied to the CLDs reachable from the thread stacks.
- virtual CLDClosure* thread_root_clds() = 0;
-
// Applied to code blobs reachable as strong roots.
virtual CodeBlobClosure* strong_codeblobs() = 0;
};
--- a/hotspot/src/share/vm/gc/g1/g1RootProcessor.cpp Mon Apr 25 11:36:14 2016 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1RootProcessor.cpp Mon Apr 25 09:51:00 2016 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, 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
@@ -152,7 +152,6 @@
CLDClosure* weak_clds() { return NULL; }
CLDClosure* strong_clds() { return _clds; }
- CLDClosure* thread_root_clds() { return _clds; }
CodeBlobClosure* strong_codeblobs() { return _blobs; }
};
@@ -184,9 +183,6 @@
// system.
CLDClosure* weak_clds() { return _clds; }
CLDClosure* strong_clds() { return _clds; }
- // We don't want to visit CLDs more than once, so we return NULL for the
- // thread root CLDs.
- CLDClosure* thread_root_clds() { return NULL; }
// We don't want to visit code blobs more than once, so we return NULL for the
// strong case and walk the entire code cache as a separate step.
@@ -211,7 +207,6 @@
void G1RootProcessor::process_java_roots(G1RootClosures* closures,
G1GCPhaseTimes* phase_times,
uint worker_i) {
- assert(closures->thread_root_clds() == NULL || closures->weak_clds() == NULL, "There is overlap between those, only one may be set");
// Iterating over the CLDG and the Threads are done early to allow us to
// first process the strong CLDs and nmethods and then, after a barrier,
// let the thread process the weak CLDs and nmethods.
@@ -227,7 +222,6 @@
bool is_par = n_workers() > 1;
Threads::possibly_parallel_oops_do(is_par,
closures->strong_oops(),
- closures->thread_root_clds(),
closures->strong_codeblobs());
}
}
--- a/hotspot/src/share/vm/gc/parallel/pcTasks.cpp Mon Apr 25 11:36:14 2016 +0200
+++ b/hotspot/src/share/vm/gc/parallel/pcTasks.cpp Mon Apr 25 09:51:00 2016 -0400
@@ -58,19 +58,16 @@
ParCompactionManager::gc_thread_compaction_manager(which);
ParCompactionManager::MarkAndPushClosure mark_and_push_closure(cm);
- CLDToOopClosure mark_and_push_from_clds(&mark_and_push_closure, true);
MarkingCodeBlobClosure mark_and_push_in_blobs(&mark_and_push_closure, !CodeBlobToOopClosure::FixRelocations);
if (_java_thread != NULL)
_java_thread->oops_do(
&mark_and_push_closure,
- &mark_and_push_from_clds,
&mark_and_push_in_blobs);
if (_vm_thread != NULL)
_vm_thread->oops_do(
&mark_and_push_closure,
- &mark_and_push_from_clds,
&mark_and_push_in_blobs);
// Do the real work
@@ -99,8 +96,7 @@
{
ResourceMark rm;
MarkingCodeBlobClosure each_active_code_blob(&mark_and_push_closure, !CodeBlobToOopClosure::FixRelocations);
- CLDToOopClosure mark_and_push_from_cld(&mark_and_push_closure);
- Threads::oops_do(&mark_and_push_closure, &mark_and_push_from_cld, &each_active_code_blob);
+ Threads::oops_do(&mark_and_push_closure, &each_active_code_blob);
}
break;
--- a/hotspot/src/share/vm/gc/parallel/psMarkSweep.cpp Mon Apr 25 11:36:14 2016 +0200
+++ b/hotspot/src/share/vm/gc/parallel/psMarkSweep.cpp Mon Apr 25 09:51:00 2016 -0400
@@ -505,9 +505,8 @@
ParallelScavengeHeap::ParStrongRootsScope psrs;
Universe::oops_do(mark_and_push_closure());
JNIHandles::oops_do(mark_and_push_closure()); // Global (strong) JNI handles
- CLDToOopClosure mark_and_push_from_cld(mark_and_push_closure());
MarkingCodeBlobClosure each_active_code_blob(mark_and_push_closure(), !CodeBlobToOopClosure::FixRelocations);
- Threads::oops_do(mark_and_push_closure(), &mark_and_push_from_cld, &each_active_code_blob);
+ Threads::oops_do(mark_and_push_closure(), &each_active_code_blob);
ObjectSynchronizer::oops_do(mark_and_push_closure());
FlatProfiler::oops_do(mark_and_push_closure());
Management::oops_do(mark_and_push_closure());
@@ -597,8 +596,7 @@
// General strong roots.
Universe::oops_do(adjust_pointer_closure());
JNIHandles::oops_do(adjust_pointer_closure()); // Global (strong) JNI handles
- CLDToOopClosure adjust_from_cld(adjust_pointer_closure());
- Threads::oops_do(adjust_pointer_closure(), &adjust_from_cld, NULL);
+ Threads::oops_do(adjust_pointer_closure(), NULL);
ObjectSynchronizer::oops_do(adjust_pointer_closure());
FlatProfiler::oops_do(adjust_pointer_closure());
Management::oops_do(adjust_pointer_closure());
--- a/hotspot/src/share/vm/gc/parallel/psParallelCompact.cpp Mon Apr 25 11:36:14 2016 +0200
+++ b/hotspot/src/share/vm/gc/parallel/psParallelCompact.cpp Mon Apr 25 09:51:00 2016 -0400
@@ -2148,8 +2148,7 @@
// General strong roots.
Universe::oops_do(&oop_closure);
JNIHandles::oops_do(&oop_closure); // Global (strong) JNI handles
- CLDToOopClosure adjust_from_cld(&oop_closure);
- Threads::oops_do(&oop_closure, &adjust_from_cld, NULL);
+ Threads::oops_do(&oop_closure, NULL);
ObjectSynchronizer::oops_do(&oop_closure);
FlatProfiler::oops_do(&oop_closure);
Management::oops_do(&oop_closure);
--- a/hotspot/src/share/vm/gc/parallel/psTasks.cpp Mon Apr 25 11:36:14 2016 +0200
+++ b/hotspot/src/share/vm/gc/parallel/psTasks.cpp Mon Apr 25 09:51:00 2016 -0400
@@ -65,8 +65,7 @@
case threads:
{
ResourceMark rm;
- CLDClosure* cld_closure = NULL; // Not needed. All CLDs are already visited.
- Threads::oops_do(&roots_closure, cld_closure, NULL);
+ Threads::oops_do(&roots_closure, NULL);
}
break;
@@ -122,14 +121,13 @@
PSPromotionManager* pm = PSPromotionManager::gc_thread_promotion_manager(which);
PSScavengeRootsClosure roots_closure(pm);
- CLDClosure* roots_from_clds = NULL; // Not needed. All CLDs are already visited.
MarkingCodeBlobClosure roots_in_blobs(&roots_closure, CodeBlobToOopClosure::FixRelocations);
if (_java_thread != NULL)
- _java_thread->oops_do(&roots_closure, roots_from_clds, &roots_in_blobs);
+ _java_thread->oops_do(&roots_closure, &roots_in_blobs);
if (_vm_thread != NULL)
- _vm_thread->oops_do(&roots_closure, roots_from_clds, &roots_in_blobs);
+ _vm_thread->oops_do(&roots_closure, &roots_in_blobs);
// Do the real work
pm->drain_stacks(false);
--- a/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp Mon Apr 25 11:36:14 2016 +0200
+++ b/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp Mon Apr 25 09:51:00 2016 -0400
@@ -582,14 +582,11 @@
ClassLoaderDataGraph::roots_cld_do(strong_cld_closure, weak_cld_closure);
}
- // Some CLDs contained in the thread frames should be considered strong.
- // Don't process them if they will be processed during the ClassLoaderDataGraph phase.
- CLDClosure* roots_from_clds_p = (strong_cld_closure != weak_cld_closure) ? strong_cld_closure : NULL;
// Only process code roots from thread stacks if we aren't visiting the entire CodeCache anyway
CodeBlobToOopClosure* roots_from_code_p = (so & SO_AllCodeCache) ? NULL : code_roots;
bool is_par = scope->n_threads() > 1;
- Threads::possibly_parallel_oops_do(is_par, strong_roots, roots_from_clds_p, roots_from_code_p);
+ Threads::possibly_parallel_oops_do(is_par, strong_roots, roots_from_code_p);
if (!_process_strong_tasks->is_task_claimed(GCH_PS_Universe_oops_do)) {
Universe::oops_do(strong_roots);
--- a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.hpp Mon Apr 25 11:36:14 2016 +0200
+++ b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.hpp Mon Apr 25 09:51:00 2016 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2016, 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
@@ -110,6 +110,7 @@
intptr_t* _locals; // local variable pointer
ConstantPoolCache* _constants; // constant pool cache
Method* _method; // method being executed
+ oop _mirror; // mirror to klass containing method
DataLayout* _mdx; // compiler profiling data for current bytecode
intptr_t* _stack; // expression stack
messages _msg; // frame manager <-> interpreter message
--- a/hotspot/src/share/vm/runtime/deoptimization.cpp Mon Apr 25 11:36:14 2016 +0200
+++ b/hotspot/src/share/vm/runtime/deoptimization.cpp Mon Apr 25 09:51:00 2016 -0400
@@ -762,7 +762,7 @@
guarantee(false, "wrong number of expression stack elements during deopt");
}
VerifyOopClosure verify;
- iframe->oops_interpreted_do(&verify, NULL, &rm, false);
+ iframe->oops_interpreted_do(&verify, &rm, false);
callee_size_of_parameters = mh->size_of_parameters();
callee_max_locals = mh->max_locals();
is_top_frame = false;
--- a/hotspot/src/share/vm/runtime/frame.cpp Mon Apr 25 11:36:14 2016 +0200
+++ b/hotspot/src/share/vm/runtime/frame.cpp Mon Apr 25 09:51:00 2016 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, 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
@@ -396,6 +396,11 @@
*interpreter_frame_method_addr() = method;
}
+void frame::interpreter_frame_set_mirror(oop mirror) {
+ assert(is_interpreted_frame(), "interpreted frame expected");
+ *interpreter_frame_mirror_addr() = mirror;
+}
+
jint frame::interpreter_frame_bci() const {
assert(is_interpreted_frame(), "interpreted frame expected");
address bcp = interpreter_frame_bcp();
@@ -852,8 +857,7 @@
}
-void frame::oops_interpreted_do(OopClosure* f, CLDClosure* cld_f,
- const RegisterMap* map, bool query_oop_map_cache) {
+void frame::oops_interpreted_do(OopClosure* f, const RegisterMap* map, bool query_oop_map_cache) {
assert(is_interpreted_frame(), "Not an interpreted frame");
assert(map != NULL, "map must be set");
Thread *thread = Thread::current();
@@ -879,20 +883,15 @@
current->oops_do(f);
}
- // process fixed part
- if (cld_f != NULL) {
- // The method pointer in the frame might be the only path to the method's
- // klass, and the klass needs to be kept alive while executing. The GCs
- // don't trace through method pointers, so typically in similar situations
- // the mirror or the class loader of the klass are installed as a GC root.
- // To minimize the overhead of doing that here, we ask the GC to pass down a
- // closure that knows how to keep klasses alive given a ClassLoaderData.
- cld_f->do_cld(m->method_holder()->class_loader_data());
+ if (m->is_native()) {
+ f->do_oop(interpreter_frame_temp_oop_addr());
}
- if (m->is_native() PPC32_ONLY(&& m->is_static())) {
- f->do_oop(interpreter_frame_temp_oop_addr());
- }
+ // The method pointer in the frame might be the only path to the method's
+ // klass, and the klass needs to be kept alive while executing. The GCs
+ // don't trace through method pointers, so the mirror of the method's klass
+ // is installed as a GC root.
+ f->do_oop(interpreter_frame_mirror_addr());
int max_locals = m->is_native() ? m->size_of_parameters() : m->max_locals();
@@ -1093,7 +1092,7 @@
}
-void frame::oops_do_internal(OopClosure* f, CLDClosure* cld_f, CodeBlobClosure* cf, RegisterMap* map, bool use_interpreter_oop_map_cache) {
+void frame::oops_do_internal(OopClosure* f, CodeBlobClosure* cf, RegisterMap* map, bool use_interpreter_oop_map_cache) {
#ifndef PRODUCT
// simulate GC crash here to dump java thread in error report
if (CrashGCForDumpingJavaThread) {
@@ -1102,7 +1101,7 @@
}
#endif
if (is_interpreted_frame()) {
- oops_interpreted_do(f, cld_f, map, use_interpreter_oop_map_cache);
+ oops_interpreted_do(f, map, use_interpreter_oop_map_cache);
} else if (is_entry_frame()) {
oops_entry_do(f, map);
} else if (CodeCache::contains(pc())) {
@@ -1147,7 +1146,7 @@
#if defined(COMPILER2) || INCLUDE_JVMCI
assert(DerivedPointerTable::is_empty(), "must be empty before verify");
#endif
- oops_do_internal(&VerifyOopClosure::verify_oop, NULL, NULL, (RegisterMap*)map, false);
+ oops_do_internal(&VerifyOopClosure::verify_oop, NULL, (RegisterMap*)map, false);
}
--- a/hotspot/src/share/vm/runtime/frame.hpp Mon Apr 25 11:36:14 2016 +0200
+++ b/hotspot/src/share/vm/runtime/frame.hpp Mon Apr 25 09:51:00 2016 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, 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
@@ -320,6 +320,9 @@
void interpreter_frame_set_method(Method* method);
Method** interpreter_frame_method_addr() const;
ConstantPoolCache** interpreter_frame_cache_addr() const;
+ oop* interpreter_frame_mirror_addr() const;
+
+ void interpreter_frame_set_mirror(oop mirror);
public:
// Entry frames
@@ -386,19 +389,19 @@
// Oops-do's
void oops_compiled_arguments_do(Symbol* signature, bool has_receiver, bool has_appendix, const RegisterMap* reg_map, OopClosure* f);
- void oops_interpreted_do(OopClosure* f, CLDClosure* cld_f, const RegisterMap* map, bool query_oop_map_cache = true);
+ void oops_interpreted_do(OopClosure* f, const RegisterMap* map, bool query_oop_map_cache = true);
private:
void oops_interpreted_arguments_do(Symbol* signature, bool has_receiver, OopClosure* f);
// Iteration of oops
- void oops_do_internal(OopClosure* f, CLDClosure* cld_f, CodeBlobClosure* cf, RegisterMap* map, bool use_interpreter_oop_map_cache);
+ void oops_do_internal(OopClosure* f, CodeBlobClosure* cf, RegisterMap* map, bool use_interpreter_oop_map_cache);
void oops_entry_do(OopClosure* f, const RegisterMap* map);
void oops_code_blob_do(OopClosure* f, CodeBlobClosure* cf, const RegisterMap* map);
int adjust_offset(Method* method, int index); // helper for above fn
public:
// Memory management
- void oops_do(OopClosure* f, CLDClosure* cld_f, CodeBlobClosure* cf, RegisterMap* map) { oops_do_internal(f, cld_f, cf, map, true); }
+ void oops_do(OopClosure* f, CodeBlobClosure* cf, RegisterMap* map) { oops_do_internal(f, cf, map, true); }
void nmethods_do(CodeBlobClosure* cf);
// RedefineClasses support for finding live interpreted methods on the stack
--- a/hotspot/src/share/vm/runtime/thread.cpp Mon Apr 25 11:36:14 2016 +0200
+++ b/hotspot/src/share/vm/runtime/thread.cpp Mon Apr 25 09:51:00 2016 -0400
@@ -785,7 +785,7 @@
return false;
}
-void Thread::oops_do(OopClosure* f, CLDClosure* cld_f, CodeBlobClosure* cf) {
+void Thread::oops_do(OopClosure* f, CodeBlobClosure* cf) {
active_handles()->oops_do(f);
// Do oop for ThreadShadow
f->do_oop((oop*)&_pending_exception);
@@ -2758,7 +2758,7 @@
}
};
-void JavaThread::oops_do(OopClosure* f, CLDClosure* cld_f, CodeBlobClosure* cf) {
+void JavaThread::oops_do(OopClosure* f, CodeBlobClosure* cf) {
// Verify that the deferred card marks have been flushed.
assert(deferred_card_mark().is_empty(), "Should be empty during GC");
@@ -2766,7 +2766,7 @@
// since there may be more than one thread using each ThreadProfiler.
// Traverse the GCHandles
- Thread::oops_do(f, cld_f, cf);
+ Thread::oops_do(f, cf);
JVMCI_ONLY(f->do_oop((oop*)&_pending_failed_speculation);)
@@ -2796,7 +2796,7 @@
// Traverse the execution stack
for (StackFrameStream fst(this); !fst.is_done(); fst.next()) {
- fst.current()->oops_do(f, cld_f, cf, fst.register_map());
+ fst.current()->oops_do(f, cf, fst.register_map());
}
}
@@ -2946,7 +2946,7 @@
void JavaThread::verify() {
// Verify oops in the thread.
- oops_do(&VerifyOopClosure::verify_oop, NULL, NULL);
+ oops_do(&VerifyOopClosure::verify_oop, NULL);
// Verify the stack frames.
frames_do(frame_verify);
@@ -3186,7 +3186,7 @@
static void oops_print(frame* f, const RegisterMap *map) {
PrintAndVerifyOopClosure print;
f->print_value();
- f->oops_do(&print, NULL, NULL, (RegisterMap*)map);
+ f->oops_do(&print, NULL, (RegisterMap*)map);
}
// Print our all the locations that contain oops and whether they are
@@ -3303,8 +3303,8 @@
_scanned_nmethod = NULL;
}
-void CodeCacheSweeperThread::oops_do(OopClosure* f, CLDClosure* cld_f, CodeBlobClosure* cf) {
- JavaThread::oops_do(f, cld_f, cf);
+void CodeCacheSweeperThread::oops_do(OopClosure* f, CodeBlobClosure* cf) {
+ JavaThread::oops_do(f, cf);
if (_scanned_nmethod != NULL && cf != NULL) {
// Safepoints can occur when the sweeper is scanning an nmethod so
// process it here to make sure it isn't unloaded in the middle of
@@ -4291,11 +4291,11 @@
// uses the Threads_lock to guarantee this property. It also makes sure that
// all threads gets blocked when exiting or starting).
-void Threads::oops_do(OopClosure* f, CLDClosure* cld_f, CodeBlobClosure* cf) {
+void Threads::oops_do(OopClosure* f, CodeBlobClosure* cf) {
ALL_JAVA_THREADS(p) {
- p->oops_do(f, cld_f, cf);
- }
- VMThread::vm_thread()->oops_do(f, cld_f, cf);
+ p->oops_do(f, cf);
+ }
+ VMThread::vm_thread()->oops_do(f, cf);
}
void Threads::change_thread_claim_parity() {
@@ -4318,16 +4318,16 @@
}
#endif // ASSERT
-void Threads::possibly_parallel_oops_do(bool is_par, OopClosure* f, CLDClosure* cld_f, CodeBlobClosure* cf) {
+void Threads::possibly_parallel_oops_do(bool is_par, OopClosure* f, CodeBlobClosure* cf) {
int cp = Threads::thread_claim_parity();
ALL_JAVA_THREADS(p) {
if (p->claim_oops_do(is_par, cp)) {
- p->oops_do(f, cld_f, cf);
+ p->oops_do(f, cf);
}
}
VMThread* vmt = VMThread::vm_thread();
if (vmt->claim_oops_do(is_par, cp)) {
- vmt->oops_do(f, cld_f, cf);
+ vmt->oops_do(f, cf);
}
}
--- a/hotspot/src/share/vm/runtime/thread.hpp Mon Apr 25 11:36:14 2016 +0200
+++ b/hotspot/src/share/vm/runtime/thread.hpp Mon Apr 25 09:51:00 2016 -0400
@@ -482,10 +482,9 @@
// GC support
// Apply "f->do_oop" to all root oops in "this".
- // Apply "cld_f->do_cld" to CLDs that are otherwise not kept alive.
// Used by JavaThread::oops_do.
// Apply "cf->do_code_blob" (if !NULL) to all code blobs active in frames
- virtual void oops_do(OopClosure* f, CLDClosure* cld_f, CodeBlobClosure* cf);
+ virtual void oops_do(OopClosure* f, CodeBlobClosure* cf);
// Handles the parallel case for the method below.
private:
@@ -1642,7 +1641,7 @@
void frames_do(void f(frame*, const RegisterMap*));
// Memory operations
- void oops_do(OopClosure* f, CLDClosure* cld_f, CodeBlobClosure* cf);
+ void oops_do(OopClosure* f, CodeBlobClosure* cf);
// Sweeper operations
virtual void nmethods_do(CodeBlobClosure* cf);
@@ -1995,7 +1994,7 @@
bool is_Code_cache_sweeper_thread() const { return true; }
// Prevent GC from unloading _scanned_nmethod
- void oops_do(OopClosure* f, CLDClosure* cld_f, CodeBlobClosure* cf);
+ void oops_do(OopClosure* f, CodeBlobClosure* cf);
void nmethods_do(CodeBlobClosure* cf);
};
@@ -2122,9 +2121,9 @@
// Apply "f->do_oop" to all root oops in all threads.
// This version may only be called by sequential code.
- static void oops_do(OopClosure* f, CLDClosure* cld_f, CodeBlobClosure* cf);
+ static void oops_do(OopClosure* f, CodeBlobClosure* cf);
// This version may be called by sequential or parallel code.
- static void possibly_parallel_oops_do(bool is_par, OopClosure* f, CLDClosure* cld_f, CodeBlobClosure* cf);
+ static void possibly_parallel_oops_do(bool is_par, OopClosure* f, CodeBlobClosure* cf);
// This creates a list of GCTasks, one per thread.
static void create_thread_roots_tasks(GCTaskQueue* q);
// This creates a list of GCTasks, one per thread, for marking objects.
--- a/hotspot/src/share/vm/runtime/vmThread.cpp Mon Apr 25 11:36:14 2016 +0200
+++ b/hotspot/src/share/vm/runtime/vmThread.cpp Mon Apr 25 09:51:00 2016 -0400
@@ -655,8 +655,8 @@
}
-void VMThread::oops_do(OopClosure* f, CLDClosure* cld_f, CodeBlobClosure* cf) {
- Thread::oops_do(f, cld_f, cf);
+void VMThread::oops_do(OopClosure* f, CodeBlobClosure* cf) {
+ Thread::oops_do(f, cf);
_vm_queue->oops_do(f);
}
@@ -688,5 +688,5 @@
#endif
void VMThread::verify() {
- oops_do(&VerifyOopClosure::verify_oop, NULL, NULL);
+ oops_do(&VerifyOopClosure::verify_oop, NULL);
}
--- a/hotspot/src/share/vm/runtime/vmThread.hpp Mon Apr 25 11:36:14 2016 +0200
+++ b/hotspot/src/share/vm/runtime/vmThread.hpp Mon Apr 25 09:51:00 2016 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2016, 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
@@ -126,7 +126,7 @@
static VMThread* vm_thread() { return _vm_thread; }
// GC support
- void oops_do(OopClosure* f, CLDClosure* cld_f, CodeBlobClosure* cf);
+ void oops_do(OopClosure* f, CodeBlobClosure* cf);
void verify();
--- a/hotspot/test/TEST.groups Mon Apr 25 11:36:14 2016 +0200
+++ b/hotspot/test/TEST.groups Mon Apr 25 09:51:00 2016 -0400
@@ -353,7 +353,7 @@
runtime/ \
-runtime/ErrorHandling/ErrorHandler.java \
-runtime/RedefineObject/TestRedefineObject.java \
- -runtime/8003720/Test8003720.java \
+ -runtime/MirrorFrame/Test8003720.java \
-runtime/Metaspace/FragmentMetaspace.java \
-runtime/Metaspace/FragmentMetaspaceSimple.java \
-runtime/Thread/TestThreadDumpMonitorContention.java \
--- a/hotspot/test/runtime/8003720/Asmator.java Mon Apr 25 11:36:14 2016 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2012, 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.
- *
- */
-
-import jdk.internal.org.objectweb.asm.*;
-
-class Asmator {
- static byte[] fixup(byte[] buf) throws java.io.IOException {
- ClassReader cr = new ClassReader(buf);
- ClassWriter cw = new ClassWriter(0);
- ClassVisitor cv = new ClassVisitor(Opcodes.ASM4, cw) {
- public MethodVisitor visitMethod(
- final int access,
- final String name,
- final String desc,
- final String signature,
- final String[] exceptions)
- {
- MethodVisitor mv = super.visitMethod(access,
- name,
- desc,
- signature,
- exceptions);
- if (mv == null) return null;
- if (name.equals("callme")) {
- // make receiver go dead!
- mv.visitInsn(Opcodes.ACONST_NULL);
- mv.visitVarInsn(Opcodes.ASTORE, 0);
- }
- return mv;
- }
- };
- cr.accept(cv, 0);
- return cw.toByteArray();
- }
-}
--- a/hotspot/test/runtime/8003720/Test8003720.java Mon Apr 25 11:36:14 2016 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-/*
- * Copyright (c) 2012, 2015, 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.
- *
- */
-
-/*
- * @test
- * @bug 8003720
- * @summary Method in interpreter stack frame can be deallocated
- * @modules java.base/jdk.internal.org.objectweb.asm
- * java.base/jdk.internal.misc
- * @compile -XDignore.symbol.file Victim.java
- * @run main/othervm -Xverify:all -Xint Test8003720
- */
-
-// Attempts to make the JVM unload a class while still executing one of its methods.
-public class Test8003720 {
- final static String VICTIM_CLASS_NAME = "Victim";
- final static boolean QUIET = true;
- final static long DURATION = 30000;
-
- public interface CallMe { void callme(); }
-
- public static void main(String... av) throws Throwable {
- newVictimClassLoader();
- System.gc();
-
- newVictimClass();
- System.gc();
-
- newVictimInstance();
- System.gc();
-
- ((CallMe)newVictimInstance()).callme();
- }
-
- public static Object newVictimInstance() throws Throwable {
- return newVictimClass().newInstance();
- }
-
- public static Class<?> newVictimClass() throws Throwable {
- return Class.forName(VICTIM_CLASS_NAME, true, new VictimClassLoader());
- }
-
- public static ClassLoader newVictimClassLoader() throws Throwable {
- return new VictimClassLoader();
- }
-
- public static void println(String line) {
- if (!QUIET) {
- System.out.println(line);
- }
- }
-}
--- a/hotspot/test/runtime/8003720/Victim.java Mon Apr 25 11:36:14 2016 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 2012, 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.
- *
- */
-
-public class Victim implements Test8003720.CallMe {
- public void callme() {
- // note: Victim.this is dead here
- Test8003720.println("executing in loader=" + Victim.class.getClassLoader());
-
- long now = System.currentTimeMillis();
-
- while ((System.currentTimeMillis() - now) < Test8003720.DURATION) {
- long count = VictimClassLoader.counter++;
- if (count % 1000000 == 0) System.gc();
- if (count % 16180000 == 0) blurb();
- new Object[1].clone();
- }
- }
- static void blurb() {
- Test8003720.println("count=" + VictimClassLoader.counter);
- }
- static {
- blather();
- }
- static void blather() {
- new java.util.ArrayList<Object>(1000000);
- Class<Victim> c = Victim.class;
- Test8003720.println("initializing " + c + "#" + System.identityHashCode(c) + " in " + c.getClassLoader());
- }
-}
--- a/hotspot/test/runtime/8003720/VictimClassLoader.java Mon Apr 25 11:36:14 2016 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,88 +0,0 @@
-/*
- * Copyright (c) 2012, 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.
- *
- */
-
-public class VictimClassLoader extends ClassLoader {
- public static long counter = 0;
-
- private int which = (int) ++counter;
-
- protected VictimClassLoader() {
- super(VictimClassLoader.class.getClassLoader());
- }
-
- protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException {
- Class c;
- if (!name.endsWith("Victim")) {
- c = super.loadClass(name, resolve);
- return c;
- }
-
- c = findLoadedClass(name);
- if (c != null) {
- return c;
- }
-
- byte[] buf = readClassFile(name);
- c = defineClass(name, buf, 0, buf.length);
- resolveClass(c);
-
- if (c.getClassLoader() != this) {
- throw new AssertionError();
- }
-
- Test8003720.println("loaded " + c + "#" + System.identityHashCode(c) + " in " + c.getClassLoader());
- return c;
- }
-
- static byte[] readClassFile(String name) {
- try {
- String rname = name.substring(name.lastIndexOf('.') + 1) + ".class";
- java.net.URL url = VictimClassLoader.class.getResource(rname);
- Test8003720.println("found " + rname + " = " + url);
-
- java.net.URLConnection connection = url.openConnection();
- int contentLength = connection.getContentLength();
- byte[] buf = readFully(connection.getInputStream(), contentLength);
-
- return Asmator.fixup(buf);
- } catch (java.io.IOException ex) {
- throw new Error(ex);
- }
- }
-
- static byte[] readFully(java.io.InputStream in, int len) throws java.io.IOException {
- byte[] b = in.readAllBytes();
- if (len != -1 && b.length != len)
- throw new java.io.IOException("Expected:" + len + ", actual:" + b.length);
- return b;
- }
-
- public void finalize() {
- Test8003720.println("Goodbye from " + this);
- }
-
- public String toString() {
- return "VictimClassLoader#" + which;
- }
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/MirrorFrame/Asmator.java Mon Apr 25 09:51:00 2016 -0400
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2012, 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.
+ *
+ */
+
+import jdk.internal.org.objectweb.asm.*;
+
+class Asmator {
+ static byte[] fixup(byte[] buf) throws java.io.IOException {
+ ClassReader cr = new ClassReader(buf);
+ ClassWriter cw = new ClassWriter(0);
+ ClassVisitor cv = new ClassVisitor(Opcodes.ASM4, cw) {
+ public MethodVisitor visitMethod(
+ final int access,
+ final String name,
+ final String desc,
+ final String signature,
+ final String[] exceptions)
+ {
+ MethodVisitor mv = super.visitMethod(access,
+ name,
+ desc,
+ signature,
+ exceptions);
+ if (mv == null) return null;
+ if (name.equals("callme")) {
+ // make receiver go dead!
+ mv.visitInsn(Opcodes.ACONST_NULL);
+ mv.visitVarInsn(Opcodes.ASTORE, 0);
+ }
+ return mv;
+ }
+ };
+ cr.accept(cv, 0);
+ return cw.toByteArray();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/MirrorFrame/Test8003720.java Mon Apr 25 09:51:00 2016 -0400
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2012, 2015, 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.
+ *
+ */
+
+/*
+ * @test
+ * @bug 8003720
+ * @summary Method in interpreter stack frame can be deallocated
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ * java.base/jdk.internal.misc
+ * @compile -XDignore.symbol.file Victim.java
+ * @run main/othervm -Xverify:all -Xint Test8003720
+ */
+
+// Attempts to make the JVM unload a class while still executing one of its methods.
+public class Test8003720 {
+ final static String VICTIM_CLASS_NAME = "Victim";
+ final static boolean QUIET = true;
+ final static long DURATION = 30000;
+
+ public interface CallMe { void callme(); }
+
+ public static void main(String... av) throws Throwable {
+ newVictimClassLoader();
+ System.gc();
+
+ newVictimClass();
+ System.gc();
+
+ newVictimInstance();
+ System.gc();
+
+ ((CallMe)newVictimInstance()).callme();
+ }
+
+ public static Object newVictimInstance() throws Throwable {
+ return newVictimClass().newInstance();
+ }
+
+ public static Class<?> newVictimClass() throws Throwable {
+ return Class.forName(VICTIM_CLASS_NAME, true, new VictimClassLoader());
+ }
+
+ public static ClassLoader newVictimClassLoader() throws Throwable {
+ return new VictimClassLoader();
+ }
+
+ public static void println(String line) {
+ if (!QUIET) {
+ System.out.println(line);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/MirrorFrame/Victim.java Mon Apr 25 09:51:00 2016 -0400
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2012, 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.
+ *
+ */
+
+public class Victim implements Test8003720.CallMe {
+ public void callme() {
+ // note: Victim.this is dead here
+ Test8003720.println("executing in loader=" + Victim.class.getClassLoader());
+
+ long now = System.currentTimeMillis();
+
+ while ((System.currentTimeMillis() - now) < Test8003720.DURATION) {
+ long count = VictimClassLoader.counter++;
+ if (count % 1000000 == 0) System.gc();
+ if (count % 16180000 == 0) blurb();
+ new Object[1].clone();
+ }
+ }
+ static void blurb() {
+ Test8003720.println("count=" + VictimClassLoader.counter);
+ }
+ static {
+ blather();
+ }
+ static void blather() {
+ new java.util.ArrayList<Object>(1000000);
+ Class<Victim> c = Victim.class;
+ Test8003720.println("initializing " + c + "#" + System.identityHashCode(c) + " in " + c.getClassLoader());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/MirrorFrame/VictimClassLoader.java Mon Apr 25 09:51:00 2016 -0400
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2012, 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.
+ *
+ */
+
+public class VictimClassLoader extends ClassLoader {
+ public static long counter = 0;
+
+ private int which = (int) ++counter;
+
+ protected VictimClassLoader() {
+ super(VictimClassLoader.class.getClassLoader());
+ }
+
+ protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException {
+ Class c;
+ if (!name.endsWith("Victim")) {
+ c = super.loadClass(name, resolve);
+ return c;
+ }
+
+ c = findLoadedClass(name);
+ if (c != null) {
+ return c;
+ }
+
+ byte[] buf = readClassFile(name);
+ c = defineClass(name, buf, 0, buf.length);
+ resolveClass(c);
+
+ if (c.getClassLoader() != this) {
+ throw new AssertionError();
+ }
+
+ Test8003720.println("loaded " + c + "#" + System.identityHashCode(c) + " in " + c.getClassLoader());
+ return c;
+ }
+
+ static byte[] readClassFile(String name) {
+ try {
+ String rname = name.substring(name.lastIndexOf('.') + 1) + ".class";
+ java.net.URL url = VictimClassLoader.class.getResource(rname);
+ Test8003720.println("found " + rname + " = " + url);
+
+ java.net.URLConnection connection = url.openConnection();
+ int contentLength = connection.getContentLength();
+ byte[] buf = readFully(connection.getInputStream(), contentLength);
+
+ return Asmator.fixup(buf);
+ } catch (java.io.IOException ex) {
+ throw new Error(ex);
+ }
+ }
+
+ static byte[] readFully(java.io.InputStream in, int len) throws java.io.IOException {
+ byte[] b = in.readAllBytes();
+ if (len != -1 && b.length != len)
+ throw new java.io.IOException("Expected:" + len + ", actual:" + b.length);
+ return b;
+ }
+
+ public void finalize() {
+ Test8003720.println("Goodbye from " + this);
+ }
+
+ public String toString() {
+ return "VictimClassLoader#" + which;
+ }
+}