8171392: Move Klass pointers outside of ConstantPool entries so ConstantPool can be read-only
Summary: Added _resolved_klasses; moved _resolved_references to ConstantPoolCache, etc.
Reviewed-by: coleenp, lfoltan, simonis, aph
--- a/hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.cpp Wed May 03 02:32:02 2017 +0000
+++ b/hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.cpp Fri Mar 03 23:08:35 2017 -0800
@@ -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.
* Copyright (c) 2014, Red Hat Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -270,7 +270,8 @@
get_constant_pool(result);
// load pointer for resolved_references[] objArray
- ldr(result, Address(result, ConstantPool::resolved_references_offset_in_bytes()));
+ ldr(result, Address(result, ConstantPool::cache_offset_in_bytes()));
+ ldr(result, Address(result, ConstantPoolCache::resolved_references_offset_in_bytes()));
// JNIHandles::resolve(obj);
ldr(result, Address(result, 0));
// Add in the index
@@ -278,6 +279,15 @@
load_heap_oop(result, Address(result, arrayOopDesc::base_offset_in_bytes(T_OBJECT)));
}
+void InterpreterMacroAssembler::load_resolved_klass_at_offset(
+ Register cpool, Register index, Register klass, Register temp) {
+ add(temp, cpool, index, LSL, LogBytesPerWord);
+ ldrh(temp, Address(temp, sizeof(ConstantPool))); // temp = resolved_klass_index
+ ldr(klass, Address(cpool, ConstantPool::resolved_klasses_offset_in_bytes())); // klass = cpool->_resolved_klasses
+ add(klass, klass, temp, LSL, LogBytesPerWord);
+ ldr(klass, Address(klass, Array<Klass*>::base_offset_in_bytes()));
+}
+
// Generate a subtype check: branch to ok_is_subtype if sub_klass is a
// subtype of super_klass.
//
--- a/hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.hpp Wed May 03 02:32:02 2017 +0000
+++ b/hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.hpp Fri Mar 03 23:08:35 2017 -0800
@@ -123,6 +123,9 @@
// load cpool->resolved_references(index);
void load_resolved_reference_at_index(Register result, Register index);
+ // load cpool->resolved_klass_at(index);
+ void load_resolved_klass_at_offset(Register cpool, Register index, Register klass, Register temp);
+
void pop_ptr(Register r = r0);
void pop_i(Register r = r0);
void pop_l(Register r = r0);
--- a/hotspot/src/cpu/aarch64/vm/templateTable_aarch64.cpp Wed May 03 02:32:02 2017 +0000
+++ b/hotspot/src/cpu/aarch64/vm/templateTable_aarch64.cpp Fri Mar 03 23:08:35 2017 -0800
@@ -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.
* Copyright (c) 2014, Red Hat Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -3372,8 +3372,7 @@
__ br(Assembler::NE, slow_case);
// get InstanceKlass
- __ lea(r4, Address(r4, r3, Address::lsl(3)));
- __ ldr(r4, Address(r4, sizeof(ConstantPool)));
+ __ load_resolved_klass_at_offset(r4, r3, r4, rscratch1);
// make sure klass is initialized & doesn't have finalizer
// make sure klass is fully initialized
@@ -3526,8 +3525,7 @@
// Get superklass in r0 and subklass in r3
__ bind(quicked);
__ mov(r3, r0); // Save object in r3; r0 needed for subtype check
- __ lea(r0, Address(r2, r19, Address::lsl(3)));
- __ ldr(r0, Address(r0, sizeof(ConstantPool)));
+ __ load_resolved_klass_at_offset(r2, r19, r0, rscratch1); // r0 = klass
__ bind(resolved);
__ load_klass(r19, r3);
@@ -3583,8 +3581,7 @@
// Get superklass in r0 and subklass in r3
__ bind(quicked);
__ load_klass(r3, r0);
- __ lea(r0, Address(r2, r19, Address::lsl(3)));
- __ ldr(r0, Address(r0, sizeof(ConstantPool)));
+ __ load_resolved_klass_at_offset(r2, r19, r0, rscratch1);
__ bind(resolved);
--- a/hotspot/src/cpu/arm/vm/interp_masm_arm.cpp Wed May 03 02:32:02 2017 +0000
+++ b/hotspot/src/cpu/arm/vm/interp_masm_arm.cpp Fri Mar 03 23:08:35 2017 -0800
@@ -298,7 +298,8 @@
Register cache = result;
// load pointer for resolved_references[] objArray
- ldr(cache, Address(result, ConstantPool::resolved_references_offset_in_bytes()));
+ ldr(cache, Address(result, ConstantPool::cache_offset_in_bytes()));
+ ldr(cache, Address(result, ConstantPoolCache::resolved_references_offset_in_bytes()));
// JNIHandles::resolve(result)
ldr(cache, Address(cache, 0));
// Add in the index
@@ -308,6 +309,15 @@
load_heap_oop(result, Address(cache, arrayOopDesc::base_offset_in_bytes(T_OBJECT)));
}
+void InterpreterMacroAssembler::load_resolved_klass_at_offset(
+ Register Rcpool, Register Rindex, Register Rklass) {
+ add(Rtemp, Rcpool, AsmOperand(Rindex, lsl, LogBytesPerWord));
+ ldrh(Rtemp, Address(Rtemp, sizeof(ConstantPool))); // Rtemp = resolved_klass_index
+ ldr(Rklass, Address(Rcpool, ConstantPool::resolved_klasses_offset_in_bytes())); // Rklass = cpool->_resolved_klasses
+ add(Rklass, Rklass, AsmOperand(Rtemp, lsl, LogBytesPerWord));
+ ldr(Rklass, Address(Rklass, Array<Klass*>::base_offset_in_bytes()));
+}
+
// Generate a subtype check: branch to not_subtype if sub_klass is
// not a subtype of super_klass.
// Profiling code for the subtype check failure (profile_typecheck_failed)
--- a/hotspot/src/cpu/arm/vm/interp_masm_arm.hpp Wed May 03 02:32:02 2017 +0000
+++ b/hotspot/src/cpu/arm/vm/interp_masm_arm.hpp Fri Mar 03 23:08:35 2017 -0800
@@ -141,6 +141,9 @@
// Load object from cpool->resolved_references(*bcp+1)
void load_resolved_reference_at_index(Register result, Register tmp);
+ // load cpool->resolved_klass_at(index); Rtemp is corrupted upon return
+ void load_resolved_klass_at_offset(Register Rcpool, Register Rindex, Register Rklass);
+
void store_check_part1(Register card_table_base); // Sets card_table_base register.
void store_check_part2(Register obj, Register card_table_base, Register tmp);
--- a/hotspot/src/cpu/arm/vm/templateTable_arm.cpp Wed May 03 02:32:02 2017 +0000
+++ b/hotspot/src/cpu/arm/vm/templateTable_arm.cpp Fri Mar 03 23:08:35 2017 -0800
@@ -4372,10 +4372,9 @@
#endif // AARCH64
// get InstanceKlass
- __ add(Rklass, Rcpool, AsmOperand(Rindex, lsl, LogBytesPerWord));
- __ ldr(Rklass, Address(Rklass, sizeof(ConstantPool)));
__ cmp(Rtemp, JVM_CONSTANT_Class);
__ b(slow_case, ne);
+ __ load_resolved_klass_at_offset(Rcpool, Rindex, Rklass);
// make sure klass is initialized & doesn't have finalizer
// make sure klass is fully initialized
@@ -4647,8 +4646,7 @@
// Get superklass in Rsuper and subklass in Rsub
__ bind(quicked);
- __ add(Rtemp, Rcpool, AsmOperand(Rindex, lsl, LogBytesPerWord));
- __ ldr(Rsuper, Address(Rtemp, sizeof(ConstantPool)));
+ __ load_resolved_klass_at_offset(Rcpool, Rindex, Rsuper);
__ bind(resolved);
__ load_klass(Rsub, Robj);
@@ -4721,8 +4719,7 @@
// Get superklass in Rsuper and subklass in Rsub
__ bind(quicked);
- __ add(Rtemp, Rcpool, AsmOperand(Rindex, lsl, LogBytesPerWord));
- __ ldr(Rsuper, Address(Rtemp, sizeof(ConstantPool)));
+ __ load_resolved_klass_at_offset(Rcpool, Rindex, Rsuper);
__ bind(resolved);
__ load_klass(Rsub, Robj);
--- a/hotspot/src/cpu/ppc/vm/interp_masm_ppc.hpp Wed May 03 02:32:02 2017 +0000
+++ b/hotspot/src/cpu/ppc/vm/interp_masm_ppc.hpp Fri Mar 03 23:08:35 2017 -0800
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012, 2016 SAP SE. All rights reserved.
+ * Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017 SAP SE. 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
@@ -79,6 +79,9 @@
// Load object from cpool->resolved_references(index).
void load_resolved_reference_at_index(Register result, Register index, Label *is_null = NULL);
+ // load cpool->resolved_klass_at(index)
+ void load_resolved_klass_at_offset(Register Rcpool, Register Roffset, Register Rklass);
+
void load_receiver(Register Rparam_count, Register Rrecv_dst);
// helpers for expression stack
--- a/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp Wed May 03 02:32:02 2017 +0000
+++ b/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp Fri Mar 03 23:08:35 2017 -0800
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012, 2016 SAP SE. All rights reserved.
+ * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017 SAP SE. 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
@@ -454,7 +454,8 @@
Register tmp = index; // reuse
sldi(tmp, index, LogBytesPerHeapOop);
// Load pointer for resolved_references[] objArray.
- ld(result, ConstantPool::resolved_references_offset_in_bytes(), result);
+ ld(result, ConstantPool::cache_offset_in_bytes(), result);
+ ld(result, ConstantPoolCache::resolved_references_offset_in_bytes(), result);
// JNIHandles::resolve(result)
ld(result, 0, result);
#ifdef ASSERT
@@ -471,6 +472,25 @@
load_heap_oop(result, arrayOopDesc::base_offset_in_bytes(T_OBJECT), result, is_null);
}
+// load cpool->resolved_klass_at(index)
+void InterpreterMacroAssembler::load_resolved_klass_at_offset(Register Rcpool, Register Roffset, Register Rklass) {
+ // int value = *(Rcpool->int_at_addr(which));
+ // int resolved_klass_index = extract_low_short_from_int(value);
+ add(Roffset, Rcpool, Roffset);
+#if defined(VM_LITTLE_ENDIAN)
+ lhz(Roffset, sizeof(ConstantPool), Roffset); // Roffset = resolved_klass_index
+#else
+ lhz(Roffset, sizeof(ConstantPool) + 2, Roffset); // Roffset = resolved_klass_index
+#endif
+
+ ld(Rklass, ConstantPool::resolved_klasses_offset_in_bytes(), Rcpool); // Rklass = Rcpool->_resolved_klasses
+
+ sldi(Roffset, Roffset, LogBytesPerWord);
+ addi(Roffset, Roffset, Array<Klass*>::base_offset_in_bytes());
+ isync(); // Order load of instance Klass wrt. tags.
+ ldx(Rklass, Rklass, Roffset);
+}
+
// Generate a subtype check: branch to ok_is_subtype if sub_klass is
// a subtype of super_klass. Blows registers Rsub_klass, tmp1, tmp2.
void InterpreterMacroAssembler::gen_subtype_check(Register Rsub_klass, Register Rsuper_klass, Register Rtmp1,
--- a/hotspot/src/cpu/ppc/vm/templateTable_ppc_64.cpp Wed May 03 02:32:02 2017 +0000
+++ b/hotspot/src/cpu/ppc/vm/templateTable_ppc_64.cpp Fri Mar 03 23:08:35 2017 -0800
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2013, 2016 SAP SE. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017 SAP SE. 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
@@ -3660,11 +3660,9 @@
__ cmpdi(CCR0, Rtags, JVM_CONSTANT_Class);
__ bne(CCR0, Lslow_case);
- // Get instanceKlass (load from Rcpool + sizeof(ConstantPool) + Rindex*BytesPerWord).
+ // Get instanceKlass
__ sldi(Roffset, Rindex, LogBytesPerWord);
- __ addi(Rscratch, Rcpool, sizeof(ConstantPool));
- __ isync(); // Order load of instance Klass wrt. tags.
- __ ldx(RinstanceKlass, Roffset, Rscratch);
+ __ load_resolved_klass_at_offset(Rcpool, Roffset, RinstanceKlass);
// Make sure klass is fully initialized and get instance_size.
__ lbz(Rscratch, in_bytes(InstanceKlass::init_state_offset()), RinstanceKlass);
@@ -3875,9 +3873,7 @@
// Extract target class from constant pool.
__ bind(Lquicked);
__ sldi(Roffset, Roffset, LogBytesPerWord);
- __ addi(Rcpool, Rcpool, sizeof(ConstantPool));
- __ isync(); // Order load of specified Klass wrt. tags.
- __ ldx(RspecifiedKlass, Rcpool, Roffset);
+ __ load_resolved_klass_at_offset(Rcpool, Roffset, RspecifiedKlass);
// Do the checkcast.
__ bind(Lresolved);
@@ -3939,9 +3935,7 @@
// Extract target class from constant pool.
__ bind(Lquicked);
__ sldi(Roffset, Roffset, LogBytesPerWord);
- __ addi(Rcpool, Rcpool, sizeof(ConstantPool));
- __ isync(); // Order load of specified Klass wrt. tags.
- __ ldx(RspecifiedKlass, Rcpool, Roffset);
+ __ load_resolved_klass_at_offset(Rcpool, Roffset, RspecifiedKlass);
// Do the checkcast.
__ bind(Lresolved);
--- a/hotspot/src/cpu/s390/vm/interp_masm_s390.cpp Wed May 03 02:32:02 2017 +0000
+++ b/hotspot/src/cpu/s390/vm/interp_masm_s390.cpp Fri Mar 03 23:08:35 2017 -0800
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2016 SAP SE. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017 SAP SE. 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
@@ -371,7 +371,8 @@
Register tmp = index; // reuse
z_sllg(index, index, LogBytesPerHeapOop); // Offset into resolved references array.
// Load pointer for resolved_references[] objArray.
- z_lg(result, ConstantPool::resolved_references_offset_in_bytes(), result);
+ z_lg(result, ConstantPool::cache_offset_in_bytes(), result);
+ z_lg(result, ConstantPoolCache::resolved_references_offset_in_bytes(), result);
// JNIHandles::resolve(result)
z_lg(result, 0, result); // Load resolved references array itself.
#ifdef ASSERT
@@ -386,6 +387,16 @@
load_heap_oop(result, arrayOopDesc::base_offset_in_bytes(T_OBJECT), result);
}
+// load cpool->resolved_klass_at(index)
+void InterpreterMacroAssembler::load_resolved_klass_at_offset(Register cpool, Register offset, Register iklass) {
+ // int value = *(Rcpool->int_at_addr(which));
+ // int resolved_klass_index = extract_low_short_from_int(value);
+ z_llgh(offset, Address(cpool, offset, sizeof(ConstantPool) + 2)); // offset = resolved_klass_index (s390 is big-endian)
+ z_sllg(offset, offset, LogBytesPerWord); // Convert 'index' to 'offset'
+ z_lg(iklass, Address(cpool, ConstantPool::resolved_klasses_offset_in_bytes())); // iklass = cpool->_resolved_klasses
+ z_lg(iklass, Address(iklass, offset, Array<Klass*>::base_offset_in_bytes()));
+}
+
void InterpreterMacroAssembler::get_cache_entry_pointer_at_bcp(Register cache,
Register tmp,
int bcp_offset,
--- a/hotspot/src/cpu/s390/vm/interp_masm_s390.hpp Wed May 03 02:32:02 2017 +0000
+++ b/hotspot/src/cpu/s390/vm/interp_masm_s390.hpp Fri Mar 03 23:08:35 2017 -0800
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2016 SAP SE. All rights reserved.
+ * Copyright (c) 2016, 2017 SAP SE. 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
@@ -115,6 +115,8 @@
void get_cache_entry_pointer_at_bcp(Register cache, Register tmp, int bcp_offset, size_t index_size = sizeof(u2));
void get_cache_index_at_bcp(Register index, int bcp_offset, size_t index_size = sizeof(u2));
void load_resolved_reference_at_index(Register result, Register index);
+ // load cpool->resolved_klass_at(index)
+ void load_resolved_klass_at_offset(Register cpool, Register offset, Register iklass);
// Pop topmost element from stack. It just disappears. Useful if
// consumed previously by access via stackTop().
--- a/hotspot/src/cpu/s390/vm/templateTable_s390.cpp Wed May 03 02:32:02 2017 +0000
+++ b/hotspot/src/cpu/s390/vm/templateTable_s390.cpp Fri Mar 03 23:08:35 2017 -0800
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2016 SAP SE. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017 SAP SE. 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
@@ -3708,7 +3708,7 @@
__ z_sllg(offset, offset, LogBytesPerWord); // Convert to to offset.
// Get InstanceKlass.
Register iklass = cpool;
- __ z_lg(iklass, Address(cpool, offset, sizeof(ConstantPool)));
+ __ load_resolved_klass_at_offset(cpool, offset, iklass);
// Make sure klass is initialized & doesn't have finalizer.
// Make sure klass is fully initialized.
@@ -3895,7 +3895,7 @@
__ z_lgr(Z_ARG4, Z_tos); // Save receiver.
__ z_sllg(index, index, LogBytesPerWord); // index2bytes for addressing
- __ mem2reg_opt(klass, Address(cpool, index, sizeof(ConstantPool)));
+ __ load_resolved_klass_at_offset(cpool, index, klass);
__ bind(resolved);
@@ -3969,8 +3969,7 @@
__ load_klass(subklass, Z_tos);
__ z_sllg(index, index, LogBytesPerWord); // index2bytes for addressing
- __ mem2reg_opt(klass,
- Address(cpool, index, sizeof(ConstantPool)));
+ __ load_resolved_klass_at_offset(cpool, index, klass);
__ bind(resolved);
--- a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp Wed May 03 02:32:02 2017 +0000
+++ b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp Fri Mar 03 23:08:35 2017 -0800
@@ -755,7 +755,8 @@
sll(index, LogBytesPerHeapOop, tmp);
get_constant_pool(result);
// load pointer for resolved_references[] objArray
- ld_ptr(result, ConstantPool::resolved_references_offset_in_bytes(), result);
+ ld_ptr(result, ConstantPool::cache_offset_in_bytes(), result);
+ ld_ptr(result, ConstantPoolCache::resolved_references_offset_in_bytes(), result);
// JNIHandles::resolve(result)
ld_ptr(result, 0, result);
// Add in the index
@@ -764,6 +765,24 @@
}
+// load cpool->resolved_klass_at(index)
+void InterpreterMacroAssembler::load_resolved_klass_at_offset(Register Rcpool,
+ Register Roffset, Register Rklass) {
+ // int value = *this_cp->int_at_addr(which);
+ // int resolved_klass_index = extract_low_short_from_int(value);
+ //
+ // Because SPARC is big-endian, the low_short is at (cpool->int_at_addr(which) + 2 bytes)
+ add(Roffset, Rcpool, Roffset);
+ lduh(Roffset, sizeof(ConstantPool) + 2, Roffset); // Roffset = resolved_klass_index
+
+ Register Rresolved_klasses = Rklass;
+ ld_ptr(Rcpool, ConstantPool::resolved_klasses_offset_in_bytes(), Rresolved_klasses);
+ sll(Roffset, LogBytesPerWord, Roffset);
+ add(Roffset, Array<Klass*>::base_offset_in_bytes(), Roffset);
+ ld_ptr(Rresolved_klasses, Roffset, Rklass);
+}
+
+
// Generate a subtype check: branch to ok_is_subtype if sub_klass is
// a subtype of super_klass. Blows registers Rsuper_klass, Rsub_klass, tmp1, tmp2.
void InterpreterMacroAssembler::gen_subtype_check(Register Rsub_klass,
--- a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp Wed May 03 02:32:02 2017 +0000
+++ b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp Fri Mar 03 23:08:35 2017 -0800
@@ -196,6 +196,9 @@
// load cpool->resolved_references(index);
void load_resolved_reference_at_index(Register result, Register index);
+ // load cpool->resolved_klass_at(index)
+ void load_resolved_klass_at_offset(Register Rcpool, Register Roffset, Register Rklass);
+
// common code
void field_offset_at(int n, Register tmp, Register dest, Register base);
--- a/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp Wed May 03 02:32:02 2017 +0000
+++ b/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp Fri Mar 03 23:08:35 2017 -0800
@@ -3241,9 +3241,7 @@
__ br(Assembler::notEqual, false, Assembler::pn, slow_case);
__ delayed()->sll(Roffset, LogBytesPerWord, Roffset);
// get InstanceKlass
- //__ sll(Roffset, LogBytesPerWord, Roffset); // executed in delay slot
- __ add(Roffset, sizeof(ConstantPool), Roffset);
- __ ld_ptr(Rscratch, Roffset, RinstanceKlass);
+ __ load_resolved_klass_at_offset(Rscratch, Roffset, RinstanceKlass);
// make sure klass is fully initialized:
__ ldub(RinstanceKlass, in_bytes(InstanceKlass::init_state_offset()), G3_scratch);
@@ -3465,8 +3463,9 @@
// Extract target class from constant pool
__ bind(quicked);
- __ add(Roffset, sizeof(ConstantPool), Roffset);
- __ ld_ptr(Lscratch, Roffset, RspecifiedKlass);
+ __ load_resolved_klass_at_offset(Lscratch, Roffset, RspecifiedKlass);
+
+
__ bind(resolved);
__ load_klass(Otos_i, RobjKlass); // get value klass
@@ -3522,9 +3521,9 @@
// Extract target class from constant pool
__ bind(quicked);
- __ add(Roffset, sizeof(ConstantPool), Roffset);
__ get_constant_pool(Lscratch);
- __ ld_ptr(Lscratch, Roffset, RspecifiedKlass);
+ __ load_resolved_klass_at_offset(Lscratch, Roffset, RspecifiedKlass);
+
__ bind(resolved);
__ load_klass(Otos_i, RobjKlass); // get value klass
--- a/hotspot/src/cpu/x86/vm/interp_masm_x86.cpp Wed May 03 02:32:02 2017 +0000
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86.cpp Fri Mar 03 23:08:35 2017 -0800
@@ -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
@@ -509,7 +509,8 @@
get_constant_pool(result);
// load pointer for resolved_references[] objArray
- movptr(result, Address(result, ConstantPool::resolved_references_offset_in_bytes()));
+ movptr(result, Address(result, ConstantPool::cache_offset_in_bytes()));
+ movptr(result, Address(result, ConstantPoolCache::resolved_references_offset_in_bytes()));
// JNIHandles::resolve(obj);
movptr(result, Address(result, 0));
// Add in the index
@@ -517,6 +518,14 @@
load_heap_oop(result, Address(result, arrayOopDesc::base_offset_in_bytes(T_OBJECT)));
}
+// load cpool->resolved_klass_at(index)
+void InterpreterMacroAssembler::load_resolved_klass_at_index(Register cpool,
+ Register index, Register klass) {
+ movw(index, Address(cpool, index, Address::times_ptr, sizeof(ConstantPool)));
+ Register resolved_klasses = cpool;
+ movptr(resolved_klasses, Address(cpool, ConstantPool::resolved_klasses_offset_in_bytes()));
+ movptr(klass, Address(resolved_klasses, index, Address::times_ptr, Array<Klass*>::base_offset_in_bytes()));
+}
// Generate a subtype check: branch to ok_is_subtype if sub_klass is a
// subtype of super_klass.
--- a/hotspot/src/cpu/x86/vm/interp_masm_x86.hpp Wed May 03 02:32:02 2017 +0000
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86.hpp Fri Mar 03 23:08:35 2017 -0800
@@ -123,6 +123,11 @@
// load cpool->resolved_references(index);
void load_resolved_reference_at_index(Register result, Register index);
+ // load cpool->resolved_klass_at(index)
+ void load_resolved_klass_at_index(Register cpool, // the constant pool (corrupted on return)
+ Register index, // the constant pool index (corrupted on return)
+ Register klass); // contains the Klass on return
+
NOT_LP64(void f2ieee();) // truncate ftos to 32bits
NOT_LP64(void d2ieee();) // truncate dtos to 64bits
--- a/hotspot/src/cpu/x86/vm/templateTable_x86.cpp Wed May 03 02:32:02 2017 +0000
+++ b/hotspot/src/cpu/x86/vm/templateTable_x86.cpp Fri Mar 03 23:08:35 2017 -0800
@@ -3846,7 +3846,7 @@
__ jcc(Assembler::notEqual, slow_case_no_pop);
// get InstanceKlass
- __ movptr(rcx, Address(rcx, rdx, Address::times_ptr, sizeof(ConstantPool)));
+ __ load_resolved_klass_at_index(rcx, rdx, rcx);
__ push(rcx); // save the contexts of klass for initializing the header
// make sure klass is initialized & doesn't have finalizer
@@ -4061,8 +4061,7 @@
// Get superklass in rax and subklass in rbx
__ bind(quicked);
__ mov(rdx, rax); // Save object in rdx; rax needed for subtype check
- __ movptr(rax, Address(rcx, rbx,
- Address::times_ptr, sizeof(ConstantPool)));
+ __ load_resolved_klass_at_index(rcx, rbx, rax);
__ bind(resolved);
__ load_klass(rbx, rdx);
@@ -4128,8 +4127,7 @@
// Get superklass in rax and subklass in rdx
__ bind(quicked);
__ load_klass(rdx, rax);
- __ movptr(rax, Address(rcx, rbx,
- Address::times_ptr, sizeof(ConstantPool)));
+ __ load_resolved_klass_at_index(rcx, rbx, rax);
__ bind(resolved);
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ConstantPool.java Wed May 03 02:32:02 2017 +0000
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ConstantPool.java Fri Mar 03 23:08:35 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 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
@@ -84,8 +84,6 @@
cache = type.getAddressField("_cache");
poolHolder = new MetadataField(type.getAddressField("_pool_holder"), 0);
length = new CIntField(type.getCIntegerField("_length"), 0);
- resolvedReferences = type.getAddressField("_resolved_references");
- referenceMap = type.getAddressField("_reference_map");
headerSize = type.getSize();
elementSize = 0;
// fetch constants:
@@ -105,8 +103,6 @@
private static AddressField cache;
private static MetadataField poolHolder;
private static CIntField length; // number of elements in oop
- private static AddressField resolvedReferences;
- private static AddressField referenceMap;
private static long headerSize;
private static long elementSize;
@@ -124,17 +120,11 @@
public InstanceKlass getPoolHolder() { return (InstanceKlass)poolHolder.getValue(this); }
public int getLength() { return (int)length.getValue(getAddress()); }
public Oop getResolvedReferences() {
- Address handle = resolvedReferences.getValue(getAddress());
- if (handle != null) {
- // Load through the handle
- OopHandle refs = handle.getOopHandleAt(0);
- return VM.getVM().getObjectHeap().newOop(refs);
- }
- return null;
+ return getCache().getResolvedReferences();
}
public U2Array referenceMap() {
- return new U2Array(referenceMap.getValue(getAddress()));
+ return getCache().referenceMap();
}
public int objectToCPIndex(int index) {
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ConstantPoolCache.java Wed May 03 02:32:02 2017 +0000
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ConstantPoolCache.java Fri Mar 03 23:08:35 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 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
@@ -51,6 +51,8 @@
elementSize = elType.getSize();
length = new CIntField(type.getCIntegerField("_length"), 0);
intSize = VM.getVM().getObjectHeap().getIntSize();
+ resolvedReferences = type.getAddressField("_resolved_references");
+ referenceMap = type.getAddressField("_reference_map");
}
public ConstantPoolCache(Address addr) {
@@ -65,7 +67,8 @@
private static long elementSize;
private static CIntField length;
private static long intSize;
-
+ private static AddressField resolvedReferences;
+ private static AddressField referenceMap;
public ConstantPool getConstants() { return (ConstantPool) constants.getValue(this); }
@@ -100,4 +103,18 @@
entry.iterateFields(visitor);
}
}
+
+ public Oop getResolvedReferences() {
+ Address handle = resolvedReferences.getValue(getAddress());
+ if (handle != null) {
+ // Load through the handle
+ OopHandle refs = handle.getOopHandleAt(0);
+ return VM.getVM().getObjectHeap().newOop(refs);
+ }
+ return null;
+ }
+
+ public U2Array referenceMap() {
+ return new U2Array(referenceMap.getValue(getAddress()));
+ }
};
--- a/hotspot/src/share/vm/classfile/bytecodeAssembler.cpp Wed May 03 02:32:02 2017 +0000
+++ b/hotspot/src/share/vm/classfile/bytecodeAssembler.cpp Fri Mar 03 23:08:35 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -64,8 +64,8 @@
cp->symbol_at_put(idx, entry._u.utf8);
break;
case BytecodeCPEntry::KLASS:
- cp->unresolved_klass_at_put(
- idx, cp->symbol_at(entry._u.klass));
+ cp->klass_index_at_put(
+ idx, entry._u.klass);
break;
case BytecodeCPEntry::STRING:
cp->unresolved_string_at_put(
@@ -85,6 +85,9 @@
ShouldNotReachHere();
}
}
+
+ cp->initialize_unresolved_klasses(_orig->pool_holder()->class_loader_data(),
+ CHECK_NULL);
return cp;
}
--- a/hotspot/src/share/vm/classfile/classFileParser.cpp Wed May 03 02:32:02 2017 +0000
+++ b/hotspot/src/share/vm/classfile/classFileParser.cpp Fri Mar 03 23:08:35 2017 -0800
@@ -391,6 +391,7 @@
}
int index = 1; // declared outside of loops for portability
+ int num_klasses = 0;
// first verification pass - validate cross references
// and fixup class and string constants
@@ -459,7 +460,7 @@
check_property(valid_symbol_at(class_index),
"Invalid constant pool index %u in class file %s",
class_index, CHECK);
- cp->unresolved_klass_at_put(index, cp->symbol_at(class_index));
+ cp->unresolved_klass_at_put(index, class_index, num_klasses++);
break;
}
case JVM_CONSTANT_StringIndex: {
@@ -550,8 +551,19 @@
} // switch(tag)
} // end of for
+ _first_patched_klass_resolved_index = num_klasses;
+ cp->allocate_resolved_klasses(_loader_data, num_klasses + _max_num_patched_klasses, CHECK);
+
if (_cp_patches != NULL) {
// need to treat this_class specially...
+
+ // Add dummy utf8 entries in the space reserved for names of patched classes. We'll use "*"
+ // for now. These will be replaced with actual names of the patched classes in patch_class().
+ Symbol* s = vmSymbols::star_name();
+ for (int n=_orig_cp_size; n<cp->length(); n++) {
+ cp->symbol_at_put(n, s);
+ }
+
int this_class_index;
{
stream->guarantee_more(8, CHECK); // flags, this_class, super_class, infs_len
@@ -701,6 +713,14 @@
} // end of for
}
+void ClassFileParser::patch_class(ConstantPool* cp, int class_index, Klass* k, Symbol* name) {
+ int name_index = _orig_cp_size + _num_patched_klasses;
+ int resolved_klass_index = _first_patched_klass_resolved_index + _num_patched_klasses;
+
+ cp->klass_at_put(class_index, name_index, resolved_klass_index, k, name);
+ _num_patched_klasses ++;
+}
+
void ClassFileParser::patch_constant_pool(ConstantPool* cp,
int index,
Handle patch,
@@ -718,13 +738,14 @@
guarantee_property(!java_lang_Class::is_primitive(patch()),
"Illegal class patch at %d in class file %s",
index, CHECK);
- cp->klass_at_put(index, java_lang_Class::as_Klass(patch()));
+ Klass* k = java_lang_Class::as_Klass(patch());
+ patch_class(cp, index, k, k->name());
} else {
guarantee_property(java_lang_String::is_instance(patch()),
"Illegal class patch at %d in class file %s",
index, CHECK);
Symbol* const name = java_lang_String::as_symbol(patch(), CHECK);
- cp->unresolved_klass_at_put(index, name);
+ patch_class(cp, index, NULL, name);
}
break;
}
@@ -5340,8 +5361,14 @@
ik->set_name(_class_name);
if (is_anonymous()) {
- // I am well known to myself
- ik->constants()->klass_at_put(_this_class_index, ik); // eagerly resolve
+ // _this_class_index is a CONSTANT_Class entry that refers to this
+ // anonymous class itself. If this class needs to refer to its own methods or
+ // fields, it would use a CONSTANT_MethodRef, etc, which would reference
+ // _this_class_index. However, because this class is anonymous (it's
+ // not stored in SystemDictionary), _this_class_index cannot be resolved
+ // with ConstantPool::klass_at_impl, which does a SystemDictionary lookup.
+ // Therefore, we must eagerly resolve _this_class_index now.
+ ik->constants()->klass_at_put(_this_class_index, ik);
}
ik->set_minor_version(_minor_version);
@@ -5577,6 +5604,10 @@
_loader_data(loader_data),
_host_klass(host_klass),
_cp_patches(cp_patches),
+ _num_patched_klasses(0),
+ _max_num_patched_klasses(0),
+ _orig_cp_size(0),
+ _first_patched_klass_resolved_index(0),
_super_klass(),
_cp(NULL),
_fields(NULL),
@@ -5647,6 +5678,25 @@
_need_verify = Verifier::should_verify_for(_loader_data->class_loader(),
stream->need_verify());
}
+ if (_cp_patches != NULL) {
+ int len = _cp_patches->length();
+ for (int i=0; i<len; i++) {
+ if (has_cp_patch_at(i)) {
+ Handle patch = cp_patch_at(i);
+ if (java_lang_String::is_instance(patch()) || java_lang_Class::is_instance(patch())) {
+ // We need to append the names of the patched classes to the end of the constant pool,
+ // because a patched class may have a Utf8 name that's not already included in the
+ // original constant pool. These class names are used when patch_constant_pool()
+ // calls patch_class().
+ //
+ // Note that a String in cp_patch_at(i) may be used to patch a Utf8, a String, or a Class.
+ // At this point, we don't know the tag for index i yet, because we haven't parsed the
+ // constant pool. So we can only assume the worst -- every String is used to patch a Class.
+ _max_num_patched_klasses++;
+ }
+ }
+ }
+ }
// synch back verification state to stream
stream->set_verify(_need_verify);
@@ -5776,19 +5826,25 @@
}
stream->guarantee_more(3, CHECK); // length, first cp tag
- const u2 cp_size = stream->get_u2_fast();
+ u2 cp_size = stream->get_u2_fast();
guarantee_property(
cp_size >= 1, "Illegal constant pool size %u in class file %s",
cp_size, CHECK);
+ _orig_cp_size = cp_size;
+ if (int(cp_size) + _max_num_patched_klasses > 0xffff) {
+ THROW_MSG(vmSymbols::java_lang_InternalError(), "not enough space for patched classes");
+ }
+ cp_size += _max_num_patched_klasses;
+
_cp = ConstantPool::allocate(_loader_data,
cp_size,
CHECK);
ConstantPool* const cp = _cp;
- parse_constant_pool(stream, cp, cp_size, CHECK);
+ parse_constant_pool(stream, cp, _orig_cp_size, CHECK);
assert(cp_size == (const u2)cp->length(), "invariant");
--- a/hotspot/src/share/vm/classfile/classFileParser.hpp Wed May 03 02:32:02 2017 +0000
+++ b/hotspot/src/share/vm/classfile/classFileParser.hpp Fri Mar 03 23:08:35 2017 -0800
@@ -81,6 +81,10 @@
mutable ClassLoaderData* _loader_data;
const InstanceKlass* _host_klass;
GrowableArray<Handle>* _cp_patches; // overrides for CP entries
+ int _num_patched_klasses;
+ int _max_num_patched_klasses;
+ int _orig_cp_size;
+ int _first_patched_klass_resolved_index;
// Metadata created before the instance klass is created. Must be deallocated
// if not transferred to the InstanceKlass upon successful class loading
@@ -434,6 +438,7 @@
return patch;
}
+ void patch_class(ConstantPool* cp, int class_index, Klass* k, Symbol* name);
void patch_constant_pool(ConstantPool* cp,
int index,
Handle patch,
--- a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp Wed May 03 02:32:02 2017 +0000
+++ b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp Fri Mar 03 23:08:35 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 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
@@ -2168,7 +2168,7 @@
ConstantPool* constants = istate->method()->constants();
if (!constants->tag_at(index).is_unresolved_klass()) {
// Make sure klass is initialized and doesn't have a finalizer
- Klass* entry = constants->slot_at(index).get_klass();
+ Klass* entry = constants->resolved_klass_at(index);
InstanceKlass* ik = InstanceKlass::cast(entry);
if (ik->is_initialized() && ik->can_be_fastpath_allocated() ) {
size_t obj_size = ik->size_helper();
@@ -2268,7 +2268,7 @@
if (METHOD->constants()->tag_at(index).is_unresolved_klass()) {
CALL_VM(InterpreterRuntime::quicken_io_cc(THREAD), handle_exception);
}
- Klass* klassOf = (Klass*) METHOD->constants()->slot_at(index).get_klass();
+ Klass* klassOf = (Klass*) METHOD->constants()->resolved_klass_at(index);
Klass* objKlass = STACK_OBJECT(-1)->klass(); // ebx
//
// Check for compatibilty. This check must not GC!!
@@ -2303,7 +2303,7 @@
if (METHOD->constants()->tag_at(index).is_unresolved_klass()) {
CALL_VM(InterpreterRuntime::quicken_io_cc(THREAD), handle_exception);
}
- Klass* klassOf = (Klass*) METHOD->constants()->slot_at(index).get_klass();
+ Klass* klassOf = (Klass*) METHOD->constants()->resolved_klass_at(index);
Klass* objKlass = STACK_OBJECT(-1)->klass();
//
// Check for compatibilty. This check must not GC!!
--- a/hotspot/src/share/vm/interpreter/rewriter.cpp Wed May 03 02:32:02 2017 +0000
+++ b/hotspot/src/share/vm/interpreter/rewriter.cpp Fri Mar 03 23:08:35 2017 -0800
@@ -94,11 +94,14 @@
_invokedynamic_references_map, CHECK);
// initialize object cache in constant pool
+ _pool->set_cache(cache);
+ cache->set_constant_pool(_pool());
+
+ // _resolved_references is stored in pool->cache(), so need to be done after
+ // the above lines.
_pool->initialize_resolved_references(loader_data, _resolved_references_map,
_resolved_reference_limit,
CHECK);
- _pool->set_cache(cache);
- cache->set_constant_pool(_pool());
}
--- a/hotspot/src/share/vm/memory/metaspaceShared.hpp Wed May 03 02:32:02 2017 +0000
+++ b/hotspot/src/share/vm/memory/metaspaceShared.hpp Fri Mar 03 23:08:35 2017 -0800
@@ -35,8 +35,8 @@
#define DEFAULT_SHARED_READ_WRITE_SIZE (NOT_LP64(6*M) LP64_ONLY(10*M))
#define MIN_SHARED_READ_WRITE_SIZE (NOT_LP64(6*M) LP64_ONLY(10*M))
-#define DEFAULT_SHARED_READ_ONLY_SIZE (NOT_LP64(6*M) LP64_ONLY(10*M))
-#define MIN_SHARED_READ_ONLY_SIZE (NOT_LP64(6*M) LP64_ONLY(10*M))
+#define DEFAULT_SHARED_READ_ONLY_SIZE (NOT_LP64(8*M) LP64_ONLY(13*M))
+#define MIN_SHARED_READ_ONLY_SIZE (NOT_LP64(8*M) LP64_ONLY(13*M))
// the MIN_SHARED_MISC_DATA_SIZE and MIN_SHARED_MISC_CODE_SIZE estimates are based on
// the sizes required for dumping the archive using the default classlist. The sizes
@@ -61,8 +61,8 @@
#define LargeSharedArchiveSize (300*M)
#define HugeSharedArchiveSize (800*M)
-#define ReadOnlyRegionPercentage 0.4
-#define ReadWriteRegionPercentage 0.55
+#define ReadOnlyRegionPercentage 0.52
+#define ReadWriteRegionPercentage 0.43
#define MiscDataRegionPercentage 0.03
#define MiscCodeRegionPercentage 0.02
#define LargeThresholdClassCount 5000
--- a/hotspot/src/share/vm/oops/constantPool.cpp Wed May 03 02:32:02 2017 +0000
+++ b/hotspot/src/share/vm/oops/constantPool.cpp Fri Mar 03 23:08:35 2017 -0800
@@ -47,18 +47,9 @@
#include "utilities/copy.hpp"
ConstantPool* ConstantPool::allocate(ClassLoaderData* loader_data, int length, TRAPS) {
- // Tags are RW but comment below applies to tags also.
Array<u1>* tags = MetadataFactory::new_writeable_array<u1>(loader_data, length, 0, CHECK_NULL);
-
int size = ConstantPool::size(length);
-
- // CDS considerations:
- // Allocate read-write but may be able to move to read-only at dumping time
- // if all the klasses are resolved. The only other field that is writable is
- // the resolved_references array, which is recreated at startup time.
- // But that could be moved to InstanceKlass (although a pain to access from
- // assembly code). Maybe it could be moved to the cpCache which is RW.
- return new (loader_data, size, false, MetaspaceObj::ConstantPoolType, THREAD) ConstantPool(tags);
+ return new (loader_data, size, true, MetaspaceObj::ConstantPoolType, THREAD) ConstantPool(tags);
}
#ifdef ASSERT
@@ -80,22 +71,26 @@
ConstantPool::ConstantPool(Array<u1>* tags) :
_tags(tags),
- _length(tags->length()),
- _flags(0) {
+ _length(tags->length()) {
assert(_tags != NULL, "invariant");
assert(tags->length() == _length, "invariant");
assert(tag_array_is_zero_initialized(tags), "invariant");
- assert(0 == _flags, "invariant");
+ assert(0 == flags(), "invariant");
assert(0 == version(), "invariant");
assert(NULL == _pool_holder, "invariant");
}
void ConstantPool::deallocate_contents(ClassLoaderData* loader_data) {
- MetadataFactory::free_metadata(loader_data, cache());
- set_cache(NULL);
- MetadataFactory::free_array<u2>(loader_data, reference_map());
- set_reference_map(NULL);
+ if (cache() != NULL) {
+ MetadataFactory::free_array<u2>(loader_data, reference_map());
+ set_reference_map(NULL);
+ MetadataFactory::free_metadata(loader_data, cache());
+ set_cache(NULL);
+ }
+
+ MetadataFactory::free_array<Klass*>(loader_data, resolved_klasses());
+ set_resolved_klasses(NULL);
MetadataFactory::free_array<jushort>(loader_data, operands());
set_operands(NULL);
@@ -113,7 +108,7 @@
}
objArrayOop ConstantPool::resolved_references() const {
- return (objArrayOop)JNIHandles::resolve(_resolved_references);
+ return (objArrayOop)JNIHandles::resolve(_cache->resolved_references());
}
// Create resolved_references array and mapping array for original cp indexes
@@ -150,9 +145,82 @@
}
}
+void ConstantPool::allocate_resolved_klasses(ClassLoaderData* loader_data, int num_klasses, TRAPS) {
+ // A ConstantPool can't possibly have 0xffff valid class entries,
+ // because entry #0 must be CONSTANT_Invalid, and each class entry must refer to a UTF8
+ // entry for the class's name. So at most we will have 0xfffe class entries.
+ // This allows us to use 0xffff (ConstantPool::_temp_resolved_klass_index) to indicate
+ // UnresolvedKlass entries that are temporarily created during class redefinition.
+ assert(num_klasses < CPKlassSlot::_temp_resolved_klass_index, "sanity");
+ assert(resolved_klasses() == NULL, "sanity");
+ Array<Klass*>* rk = MetadataFactory::new_writeable_array<Klass*>(loader_data, num_klasses, CHECK);
+ set_resolved_klasses(rk);
+}
+
+void ConstantPool::initialize_unresolved_klasses(ClassLoaderData* loader_data, TRAPS) {
+ int len = length();
+ int num_klasses = 0;
+ for (int i = 1; i <len; i++) {
+ switch (tag_at(i).value()) {
+ case JVM_CONSTANT_ClassIndex:
+ {
+ const int class_index = klass_index_at(i);
+ unresolved_klass_at_put(i, class_index, num_klasses++);
+ }
+ break;
+#ifndef PRODUCT
+ case JVM_CONSTANT_Class:
+ case JVM_CONSTANT_UnresolvedClass:
+ case JVM_CONSTANT_UnresolvedClassInError:
+ // All of these should have been reverted back to ClassIndex before calling
+ // this function.
+ ShouldNotReachHere();
+#endif
+ }
+ }
+ allocate_resolved_klasses(loader_data, num_klasses, THREAD);
+}
+
+// Anonymous class support:
+void ConstantPool::klass_at_put(int class_index, int name_index, int resolved_klass_index, Klass* k, Symbol* name) {
+ assert(is_within_bounds(class_index), "index out of bounds");
+ assert(is_within_bounds(name_index), "index out of bounds");
+ assert((resolved_klass_index & 0xffff0000) == 0, "must be");
+ *int_at_addr(class_index) =
+ build_int_from_shorts((jushort)resolved_klass_index, (jushort)name_index);
+
+ symbol_at_put(name_index, name);
+ name->increment_refcount();
+ Klass** adr = resolved_klasses()->adr_at(resolved_klass_index);
+ OrderAccess::release_store_ptr((Klass* volatile *)adr, k);
+
+ // The interpreter assumes when the tag is stored, the klass is resolved
+ // and the Klass* non-NULL, so we need hardware store ordering here.
+ if (k != NULL) {
+ release_tag_at_put(class_index, JVM_CONSTANT_Class);
+ } else {
+ release_tag_at_put(class_index, JVM_CONSTANT_UnresolvedClass);
+ }
+}
+
+// Anonymous class support:
+void ConstantPool::klass_at_put(int class_index, Klass* k) {
+ assert(k != NULL, "must be valid klass");
+ CPKlassSlot kslot = klass_slot_at(class_index);
+ int resolved_klass_index = kslot.resolved_klass_index();
+ Klass** adr = resolved_klasses()->adr_at(resolved_klass_index);
+ OrderAccess::release_store_ptr((Klass* volatile *)adr, k);
+
+ // The interpreter assumes when the tag is stored, the klass is resolved
+ // and the Klass* non-NULL, so we need hardware store ordering here.
+ release_tag_at_put(class_index, JVM_CONSTANT_Class);
+}
+
// CDS support. Create a new resolved_references array.
void ConstantPool::restore_unshareable_info(TRAPS) {
assert(is_constantPool(), "ensure C++ vtable is restored");
+ assert(on_stack(), "should always be set for shared constant pools");
+ assert(is_shared(), "should always be set for shared constant pools");
// Only create the new resolved references array if it hasn't been attempted before
if (resolved_references() != NULL) return;
@@ -180,6 +248,12 @@
set_resolved_reference_length(
resolved_references() != NULL ? resolved_references()->length() : 0);
set_resolved_references(NULL);
+
+ // Shared ConstantPools are in the RO region, so the _flags cannot be modified.
+ // The _on_stack flag is used to prevent ConstantPools from deallocation during
+ // class redefinition. Since shared ConstantPools cannot be deallocated anyway,
+ // we always set _on_stack to true to avoid having to change _flags during runtime.
+ _flags |= (_on_stack | _is_shared);
}
int ConstantPool::cp_to_object_index(int cp_index) {
@@ -229,11 +303,14 @@
// A resolved constantPool entry will contain a Klass*, otherwise a Symbol*.
// It is not safe to rely on the tag bit's here, since we don't have a lock, and
// the entry and tag is not updated atomicly.
- CPSlot entry = this_cp->slot_at(which);
- if (entry.is_resolved()) {
- assert(entry.get_klass()->is_klass(), "must be");
- // Already resolved - return entry.
- return entry.get_klass();
+ CPKlassSlot kslot = this_cp->klass_slot_at(which);
+ int resolved_klass_index = kslot.resolved_klass_index();
+ int name_index = kslot.name_index();
+ assert(this_cp->tag_at(name_index).is_symbol(), "sanity");
+
+ Klass* klass = this_cp->resolved_klasses()->at(resolved_klass_index);
+ if (klass != NULL) {
+ return klass;
}
// This tag doesn't change back to unresolved class unless at a safepoint.
@@ -251,7 +328,7 @@
}
Handle mirror_handle;
- Symbol* name = entry.get_symbol();
+ Symbol* name = this_cp->symbol_at(name_index);
Handle loader (THREAD, this_cp->pool_holder()->class_loader());
Handle protection_domain (THREAD, this_cp->pool_holder()->protection_domain());
Klass* k = SystemDictionary::resolve_or_fail(name, loader, protection_domain, true, THREAD);
@@ -270,10 +347,9 @@
// If CHECK_NULL above doesn't return the exception, that means that
// some other thread has beaten us and has resolved the class.
// To preserve old behavior, we return the resolved class.
- entry = this_cp->resolved_klass_at(which);
- assert(entry.is_resolved(), "must be resolved if exception was cleared");
- assert(entry.get_klass()->is_klass(), "must be resolved to a klass");
- return entry.get_klass();
+ klass = this_cp->resolved_klasses()->at(resolved_klass_index);
+ assert(klass != NULL, "must be resolved if exception was cleared");
+ return klass;
} else {
return NULL; // return the pending exception
}
@@ -287,10 +363,13 @@
if (log_is_enabled(Debug, class, resolve)){
trace_class_resolution(this_cp, k);
}
- this_cp->klass_at_put(which, k);
- entry = this_cp->resolved_klass_at(which);
- assert(entry.is_resolved() && entry.get_klass()->is_klass(), "must be resolved at this point");
- return entry.get_klass();
+ Klass** adr = this_cp->resolved_klasses()->adr_at(resolved_klass_index);
+ OrderAccess::release_store_ptr((Klass* volatile *)adr, k);
+ // The interpreter assumes when the tag is stored, the klass is resolved
+ // and the Klass* stored in _resolved_klasses is non-NULL, so we need
+ // hardware store ordering here.
+ this_cp->release_tag_at_put(which, JVM_CONSTANT_Class);
+ return k;
}
@@ -299,14 +378,17 @@
// instanceof operations. Returns NULL if the class has not been loaded or
// if the verification of constant pool failed
Klass* ConstantPool::klass_at_if_loaded(const constantPoolHandle& this_cp, int which) {
- CPSlot entry = this_cp->slot_at(which);
- if (entry.is_resolved()) {
- assert(entry.get_klass()->is_klass(), "must be");
- return entry.get_klass();
+ CPKlassSlot kslot = this_cp->klass_slot_at(which);
+ int resolved_klass_index = kslot.resolved_klass_index();
+ int name_index = kslot.name_index();
+ assert(this_cp->tag_at(name_index).is_symbol(), "sanity");
+
+ Klass* k = this_cp->resolved_klasses()->at(resolved_klass_index);
+ if (k != NULL) {
+ return k;
} else {
- assert(entry.is_unresolved(), "must be either symbol or klass");
Thread *thread = Thread::current();
- Symbol* name = entry.get_symbol();
+ Symbol* name = this_cp->symbol_at(name_index);
oop loader = this_cp->pool_holder()->class_loader();
oop protection_domain = this_cp->pool_holder()->protection_domain();
Handle h_prot (thread, protection_domain);
@@ -484,22 +566,8 @@
return klass_at(klass_ref_index_at(which), THREAD);
}
-
Symbol* ConstantPool::klass_name_at(int which) const {
- assert(tag_at(which).is_unresolved_klass() || tag_at(which).is_klass(),
- "Corrupted constant pool");
- // A resolved constantPool entry will contain a Klass*, otherwise a Symbol*.
- // It is not safe to rely on the tag bit's here, since we don't have a lock, and the entry and
- // tag is not updated atomicly.
- CPSlot entry = slot_at(which);
- if (entry.is_resolved()) {
- // Already resolved - return entry's name.
- assert(entry.get_klass()->is_klass(), "must be");
- return entry.get_klass()->name();
- } else {
- assert(entry.is_unresolved(), "must be either symbol or klass");
- return entry.get_symbol();
- }
+ return symbol_at(klass_slot_at(which).name_index());
}
Symbol* ConstantPool::klass_ref_at_noresolve(int which) {
@@ -850,7 +918,7 @@
// Iterate over symbols and decrement ones which are Symbol*s
// This is done during GC.
-// Only decrement the UTF8 symbols. Unresolved classes and strings point to
+// Only decrement the UTF8 symbols. Strings point to
// these symbols but didn't increment the reference count.
void ConstantPool::unreference_symbols() {
for (int index = 1; index < length(); index++) { // Index 0 is unused
@@ -1231,12 +1299,6 @@
int tag = from_cp->tag_at(from_i).value();
switch (tag) {
- case JVM_CONSTANT_Class:
- {
- Klass* k = from_cp->klass_at(from_i, CHECK);
- to_cp->klass_at_put(to_i, k);
- } break;
-
case JVM_CONSTANT_ClassIndex:
{
jint ki = from_cp->klass_index_at(from_i);
@@ -1305,18 +1367,14 @@
to_cp->string_index_at_put(to_i, si);
} break;
+ case JVM_CONSTANT_Class:
case JVM_CONSTANT_UnresolvedClass:
case JVM_CONSTANT_UnresolvedClassInError:
{
- // Can be resolved after checking tag, so check the slot first.
- CPSlot entry = from_cp->slot_at(from_i);
- if (entry.is_resolved()) {
- assert(entry.get_klass()->is_klass(), "must be");
- // Already resolved
- to_cp->klass_at_put(to_i, entry.get_klass());
- } else {
- to_cp->unresolved_klass_at_put(to_i, entry.get_symbol());
- }
+ // Revert to JVM_CONSTANT_ClassIndex
+ int name_index = from_cp->klass_slot_at(from_i).name_index();
+ assert(from_cp->tag_at(name_index).is_symbol(), "sanity");
+ to_cp->klass_index_at_put(to_i, name_index);
} break;
case JVM_CONSTANT_String:
@@ -1368,7 +1426,6 @@
}
} // end copy_entry_to()
-
// Search constant pool search_cp for an entry that matches this
// constant pool's entry at pattern_i. Returns the index of a
// matching entry or zero (0) if there is no matching entry.
@@ -1824,12 +1881,15 @@
if (value) {
// Only record if it's not already set.
if (!on_stack()) {
+ assert(!is_shared(), "should always be set for shared constant pools");
_flags |= _on_stack;
MetadataOnStackMark::record(this);
}
} else {
// Clearing is done single-threadedly.
- _flags &= ~_on_stack;
+ if (!is_shared()) {
+ _flags &= ~_on_stack;
+ }
}
}
@@ -1905,6 +1965,7 @@
st->print_cr(" - cache: " INTPTR_FORMAT, p2i(cache()));
st->print_cr(" - resolved_references: " INTPTR_FORMAT, p2i(resolved_references()));
st->print_cr(" - reference_map: " INTPTR_FORMAT, p2i(reference_map()));
+ st->print_cr(" - resolved_klasses: " INTPTR_FORMAT, p2i(resolved_klasses()));
for (int index = 1; index < length(); index++) { // Index 0 is unused
((ConstantPool*)this)->print_entry_on(index, st);
@@ -1966,14 +2027,25 @@
case JVM_CONSTANT_Utf8 :
symbol_at(index)->print_value_on(st);
break;
+ case JVM_CONSTANT_ClassIndex: {
+ int name_index = *int_at_addr(index);
+ st->print("klass_index=%d ", name_index);
+ symbol_at(name_index)->print_value_on(st);
+ }
+ break;
case JVM_CONSTANT_UnresolvedClass : // fall-through
case JVM_CONSTANT_UnresolvedClassInError: {
- CPSlot entry = slot_at(index);
- if (entry.is_resolved()) {
- entry.get_klass()->print_value_on(st);
- } else {
- entry.get_symbol()->print_value_on(st);
- }
+ CPKlassSlot kslot = klass_slot_at(index);
+ int resolved_klass_index = kslot.resolved_klass_index();
+ int name_index = kslot.name_index();
+ assert(tag_at(name_index).is_symbol(), "sanity");
+
+ Klass* klass = resolved_klasses()->at(resolved_klass_index);
+ if (klass != NULL) {
+ klass->print_value_on(st);
+ } else {
+ symbol_at(name_index)->print_value_on(st);
+ }
}
break;
case JVM_CONSTANT_MethodHandle :
@@ -2044,18 +2116,13 @@
guarantee(is_constantPool(), "object must be constant pool");
for (int i = 0; i< length(); i++) {
constantTag tag = tag_at(i);
- CPSlot entry = slot_at(i);
- if (tag.is_klass()) {
- if (entry.is_resolved()) {
- guarantee(entry.get_klass()->is_klass(), "should be klass");
- }
- } else if (tag.is_unresolved_klass()) {
- if (entry.is_resolved()) {
- guarantee(entry.get_klass()->is_klass(), "should be klass");
- }
+ if (tag.is_klass() || tag.is_unresolved_klass()) {
+ guarantee(klass_name_at(i)->refcount() != 0, "should have nonzero reference count");
} else if (tag.is_symbol()) {
+ CPSlot entry = slot_at(i);
guarantee(entry.get_symbol()->refcount() != 0, "should have nonzero reference count");
} else if (tag.is_string()) {
+ CPSlot entry = slot_at(i);
guarantee(entry.get_symbol()->refcount() != 0, "should have nonzero reference count");
}
}
--- a/hotspot/src/share/vm/oops/constantPool.hpp Wed May 03 02:32:02 2017 +0000
+++ b/hotspot/src/share/vm/oops/constantPool.hpp Fri Mar 03 23:08:35 2017 -0800
@@ -46,27 +46,47 @@
class SymbolHashMap;
class CPSlot VALUE_OBJ_CLASS_SPEC {
+ friend class ConstantPool;
intptr_t _ptr;
+ enum TagBits {_pseudo_bit = 1};
public:
- enum TagBits { _resolved_value = 0, _symbol_bit = 1, _pseudo_bit = 2, _symbol_mask = 3 };
CPSlot(intptr_t ptr): _ptr(ptr) {}
- CPSlot(Klass* ptr): _ptr((intptr_t)ptr) {}
- CPSlot(Symbol* ptr): _ptr((intptr_t)ptr | _symbol_bit) {}
- CPSlot(Symbol* ptr, int tag_bits): _ptr((intptr_t)ptr | tag_bits) {}
+ CPSlot(Symbol* ptr, int tag_bits = 0): _ptr((intptr_t)ptr | tag_bits) {}
intptr_t value() { return _ptr; }
- bool is_resolved() { return (_ptr & _symbol_bit ) == _resolved_value; }
- bool is_unresolved() { return (_ptr & _symbol_bit ) != _resolved_value; }
- bool is_pseudo_string() { return (_ptr & _symbol_mask) == _symbol_bit + _pseudo_bit; }
+ bool is_pseudo_string() { return (_ptr & _pseudo_bit) != 0; }
Symbol* get_symbol() {
- assert(is_unresolved(), "bad call");
- return (Symbol*)(_ptr & ~_symbol_mask);
+ return (Symbol*)(_ptr & ~_pseudo_bit);
}
- Klass* get_klass() {
- assert(is_resolved(), "bad call");
- return (Klass*)_ptr;
+};
+
+// This represents a JVM_CONSTANT_Class, JVM_CONSTANT_UnresolvedClass, or
+// JVM_CONSTANT_UnresolvedClassInError slot in the constant pool.
+class CPKlassSlot VALUE_OBJ_CLASS_SPEC {
+ // cp->symbol_at(_name_index) gives the name of the class.
+ int _name_index;
+
+ // cp->_resolved_klasses->at(_resolved_klass_index) gives the Klass* for the class.
+ int _resolved_klass_index;
+public:
+ enum {
+ // This is used during constant pool merging where the resolved klass index is
+ // not yet known, and will be computed at a later stage (during a call to
+ // initialize_unresolved_klasses()).
+ _temp_resolved_klass_index = 0xffff
+ };
+ CPKlassSlot(int n, int rk) {
+ _name_index = n;
+ _resolved_klass_index = rk;
+ }
+ int name_index() const {
+ return _name_index;
+ }
+ int resolved_klass_index() const {
+ assert(_resolved_klass_index != _temp_resolved_klass_index, "constant pool merging was incomplete");
+ return _resolved_klass_index;
}
};
@@ -83,14 +103,14 @@
InstanceKlass* _pool_holder; // the corresponding class
Array<u2>* _operands; // for variable-sized (InvokeDynamic) nodes, usually empty
- // Array of resolved objects from the constant pool and map from resolved
- // object index to original constant pool index
- jobject _resolved_references;
- Array<u2>* _reference_map;
+ // Consider using an array of compressed klass pointers to
+ // save space on 64-bit platforms.
+ Array<Klass*>* _resolved_klasses;
enum {
_has_preresolution = 1, // Flags
- _on_stack = 2
+ _on_stack = 2,
+ _is_shared = 4
};
int _flags; // old fashioned bit twiddling
@@ -119,6 +139,7 @@
CPSlot slot_at(int which) const {
assert(is_within_bounds(which), "index out of bounds");
+ assert(!tag_at(which).is_unresolved_klass() && !tag_at(which).is_unresolved_klass_in_error(), "Corrupted constant pool");
// Uses volatile because the klass slot changes without a lock.
volatile intptr_t adr = (intptr_t)OrderAccess::load_ptr_acquire(obj_at_addr_raw(which));
assert(adr != 0 || which == 0, "cp entry for klass should not be zero");
@@ -166,7 +187,10 @@
Array<u2>* operands() const { return _operands; }
bool has_preresolution() const { return (_flags & _has_preresolution) != 0; }
- void set_has_preresolution() { _flags |= _has_preresolution; }
+ void set_has_preresolution() {
+ assert(!is_shared(), "should never be called on shared ConstantPools");
+ _flags |= _has_preresolution;
+ }
// Redefine classes support. If a method refering to this constant pool
// is on the executing stack, or as a handle in vm code, this constant pool
@@ -175,6 +199,9 @@
bool on_stack() const { return (_flags &_on_stack) != 0; }
void set_on_stack(const bool value);
+ // Faster than MetaspaceObj::is_shared() - used by set_on_stack()
+ bool is_shared() const { return (_flags & _is_shared) != 0; }
+
// Klass holding pool
InstanceKlass* pool_holder() const { return _pool_holder; }
void set_pool_holder(InstanceKlass* k) { _pool_holder = k; }
@@ -193,9 +220,14 @@
// resolved strings, methodHandles and callsite objects from the constant pool
objArrayOop resolved_references() const;
// mapping resolved object array indexes to cp indexes and back.
- int object_to_cp_index(int index) { return _reference_map->at(index); }
+ int object_to_cp_index(int index) { return reference_map()->at(index); }
int cp_to_object_index(int index);
+ void set_resolved_klasses(Array<Klass*>* rk) { _resolved_klasses = rk; }
+ Array<Klass*>* resolved_klasses() const { return _resolved_klasses; }
+ void allocate_resolved_klasses(ClassLoaderData* loader_data, int num_klasses, TRAPS);
+ void initialize_unresolved_klasses(ClassLoaderData* loader_data, TRAPS);
+
// Invokedynamic indexes.
// They must look completely different from normal indexes.
// The main reason is that byte swapping is sometimes done on normal indexes.
@@ -223,30 +255,27 @@
static int tags_offset_in_bytes() { return offset_of(ConstantPool, _tags); }
static int cache_offset_in_bytes() { return offset_of(ConstantPool, _cache); }
static int pool_holder_offset_in_bytes() { return offset_of(ConstantPool, _pool_holder); }
- static int resolved_references_offset_in_bytes() { return offset_of(ConstantPool, _resolved_references); }
+ static int resolved_klasses_offset_in_bytes() { return offset_of(ConstantPool, _resolved_klasses); }
// Storing constants
- void klass_at_put(int which, Klass* k) {
- assert(k != NULL, "resolved class shouldn't be null");
- assert(is_within_bounds(which), "index out of bounds");
- OrderAccess::release_store_ptr((Klass* volatile *)obj_at_addr_raw(which), k);
- // The interpreter assumes when the tag is stored, the klass is resolved
- // and the Klass* is a klass rather than a Symbol*, so we need
- // hardware store ordering here.
- release_tag_at_put(which, JVM_CONSTANT_Class);
- }
-
// For temporary use while constructing constant pool
void klass_index_at_put(int which, int name_index) {
tag_at_put(which, JVM_CONSTANT_ClassIndex);
*int_at_addr(which) = name_index;
}
- // Temporary until actual use
- void unresolved_klass_at_put(int which, Symbol* s) {
+ // Anonymous class support:
+ void klass_at_put(int class_index, int name_index, int resolved_klass_index, Klass* k, Symbol* name);
+ void klass_at_put(int class_index, Klass* k);
+
+ void unresolved_klass_at_put(int which, int name_index, int resolved_klass_index) {
release_tag_at_put(which, JVM_CONSTANT_UnresolvedClass);
- slot_at_put(which, s);
+
+ assert((name_index & 0xffff0000) == 0, "must be");
+ assert((resolved_klass_index & 0xffff0000) == 0, "must be");
+ *int_at_addr(which) =
+ build_int_from_shorts((jushort)resolved_klass_index, (jushort)name_index);
}
void method_handle_index_at_put(int which, int ref_kind, int ref_index) {
@@ -266,7 +295,7 @@
void unresolved_string_at_put(int which, Symbol* s) {
release_tag_at_put(which, JVM_CONSTANT_String);
- slot_at_put(which, CPSlot(s, CPSlot::_symbol_bit));
+ slot_at_put(which, CPSlot(s));
}
void int_at_put(int which, jint i) {
@@ -348,17 +377,38 @@
return klass_at_impl(h_this, which, false, THREAD);
}
+ CPKlassSlot klass_slot_at(int which) const {
+ assert(tag_at(which).is_unresolved_klass() || tag_at(which).is_klass(),
+ "Corrupted constant pool");
+ int value = *int_at_addr(which);
+ int name_index = extract_high_short_from_int(value);
+ int resolved_klass_index = extract_low_short_from_int(value);
+ return CPKlassSlot(name_index, resolved_klass_index);
+ }
+
Symbol* klass_name_at(int which) const; // Returns the name, w/o resolving.
+ int klass_name_index_at(int which) const {
+ return klass_slot_at(which).name_index();
+ }
Klass* resolved_klass_at(int which) const { // Used by Compiler
guarantee(tag_at(which).is_klass(), "Corrupted constant pool");
// Must do an acquire here in case another thread resolved the klass
// behind our back, lest we later load stale values thru the oop.
- return CPSlot((Klass*)OrderAccess::load_ptr_acquire(obj_at_addr_raw(which))).get_klass();
+ CPKlassSlot kslot = klass_slot_at(which);
+ assert(tag_at(kslot.name_index()).is_symbol(), "sanity");
+
+ Klass** adr = resolved_klasses()->adr_at(kslot.resolved_klass_index());
+ return (Klass*)OrderAccess::load_ptr_acquire(adr);
}
// RedefineClasses() API support:
Symbol* klass_at_noresolve(int which) { return klass_name_at(which); }
+ void temp_unresolved_klass_at_put(int which, int name_index) {
+ // Used only during constant pool merging for class redefinition. The resolved klass index
+ // will be initialized later by a call to initialize_unresolved_klasses().
+ unresolved_klass_at_put(which, name_index, CPKlassSlot::_temp_resolved_klass_index);
+ }
jint int_at(int which) {
assert(tag_at(which).is_int(), "Corrupted constant pool");
@@ -428,7 +478,7 @@
void pseudo_string_at_put(int which, int obj_index, oop x) {
assert(tag_at(which).is_string(), "Corrupted constant pool");
Symbol* sym = unresolved_string_at(which);
- slot_at_put(which, CPSlot(sym, (CPSlot::_symbol_bit | CPSlot::_pseudo_bit)));
+ slot_at_put(which, CPSlot(sym, CPSlot::_pseudo_bit));
string_at_put(which, obj_index, x); // this works just fine
}
@@ -761,9 +811,9 @@
private:
- void set_resolved_references(jobject s) { _resolved_references = s; }
- Array<u2>* reference_map() const { return _reference_map; }
- void set_reference_map(Array<u2>* o) { _reference_map = o; }
+ void set_resolved_references(jobject s) { _cache->set_resolved_references(s); }
+ Array<u2>* reference_map() const { return (_cache == NULL) ? NULL : _cache->reference_map(); }
+ void set_reference_map(Array<u2>* o) { _cache->set_reference_map(o); }
// patch JSR 292 resolved references after the class is linked.
void patch_resolved_references(GrowableArray<Handle>* cp_patches);
--- a/hotspot/src/share/vm/oops/cpCache.hpp Wed May 03 02:32:02 2017 +0000
+++ b/hotspot/src/share/vm/oops/cpCache.hpp Fri Mar 03 23:08:35 2017 -0800
@@ -404,6 +404,13 @@
int _length;
ConstantPool* _constant_pool; // the corresponding constant pool
+ // The following fields need to be modified at runtime, so they cannot be
+ // stored in the ConstantPool, which is read-only.
+ // Array of resolved objects from the constant pool and map from resolved
+ // object index to original constant pool index
+ jobject _resolved_references;
+ Array<u2>* _reference_map;
+
// Sizing
debug_only(friend class ClassVerifier;)
@@ -433,6 +440,15 @@
bool is_constantPoolCache() const { return true; }
int length() const { return _length; }
+
+ jobject resolved_references() { return _resolved_references; }
+ void set_resolved_references(jobject s) { _resolved_references = s; }
+ Array<u2>* reference_map() const { return _reference_map; }
+ void set_reference_map(Array<u2>* o) { _reference_map = o; }
+
+ // Assembly code support
+ static int resolved_references_offset_in_bytes() { return offset_of(ConstantPoolCache, _resolved_references); }
+
private:
void set_length(int length) { _length = length; }
--- a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp Wed May 03 02:32:02 2017 +0000
+++ b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp Fri Mar 03 23:08:35 2017 -0800
@@ -292,12 +292,22 @@
// entries in the input constant pool. We revert the appended copy
// back to UnresolvedClass so that either verifier will be happy
// with the constant pool entry.
+ //
+ // this is an indirect CP entry so it needs special handling
case JVM_CONSTANT_Class:
+ case JVM_CONSTANT_UnresolvedClass:
{
- // revert the copy to JVM_CONSTANT_UnresolvedClass
- (*merge_cp_p)->unresolved_klass_at_put(*merge_cp_length_p,
- scratch_cp->klass_name_at(scratch_i));
-
+ int name_i = scratch_cp->klass_name_index_at(scratch_i);
+ int new_name_i = find_or_append_indirect_entry(scratch_cp, name_i, merge_cp_p,
+ merge_cp_length_p, THREAD);
+
+ if (new_name_i != name_i) {
+ log_trace(redefine, class, constantpool)
+ ("Class entry@%d name_index change: %d to %d",
+ *merge_cp_length_p, name_i, new_name_i);
+ }
+
+ (*merge_cp_p)->temp_unresolved_klass_at_put(*merge_cp_length_p, new_name_i);
if (scratch_i != *merge_cp_length_p) {
// The new entry in *merge_cp_p is at a different index than
// the new entry in scratch_cp so we need to map the index values.
@@ -330,10 +340,6 @@
// This was an indirect CP entry, but it has been changed into
// Symbol*s so this entry can be directly appended.
case JVM_CONSTANT_String: // fall through
-
- // These were indirect CP entries, but they have been changed into
- // Symbol*s so these entries can be directly appended.
- case JVM_CONSTANT_UnresolvedClass: // fall through
{
ConstantPool::copy_entry_to(scratch_cp, scratch_i, *merge_cp_p, *merge_cp_length_p,
THREAD);
@@ -504,7 +510,7 @@
(*merge_cp_length_p)++;
} break;
- // At this stage, Class or UnresolvedClass could be here, but not
+ // At this stage, Class or UnresolvedClass could be in scratch_cp, but not
// ClassIndex
case JVM_CONSTANT_ClassIndex: // fall through
@@ -1270,8 +1276,8 @@
// revert the copy to JVM_CONSTANT_UnresolvedClass
// May be resolving while calling this so do the same for
// JVM_CONSTANT_UnresolvedClass (klass_name_at() deals with transition)
- (*merge_cp_p)->unresolved_klass_at_put(old_i,
- old_cp->klass_name_at(old_i));
+ (*merge_cp_p)->temp_unresolved_klass_at_put(old_i,
+ old_cp->klass_name_index_at(old_i));
break;
case JVM_CONSTANT_Double:
@@ -3102,6 +3108,7 @@
// attach new constant pool to klass
scratch_class->set_constants(scratch_cp());
+ scratch_cp->initialize_unresolved_klasses(loader_data, CHECK);
int i; // for portability
--- a/hotspot/src/share/vm/runtime/vmStructs.cpp Wed May 03 02:32:02 2017 +0000
+++ b/hotspot/src/share/vm/runtime/vmStructs.cpp Fri Mar 03 23:08:35 2017 -0800
@@ -238,8 +238,8 @@
nonstatic_field(ConstantPool, _pool_holder, InstanceKlass*) \
nonstatic_field(ConstantPool, _operands, Array<u2>*) \
nonstatic_field(ConstantPool, _length, int) \
- nonstatic_field(ConstantPool, _resolved_references, jobject) \
- nonstatic_field(ConstantPool, _reference_map, Array<u2>*) \
+ nonstatic_field(ConstantPoolCache, _resolved_references, jobject) \
+ nonstatic_field(ConstantPoolCache, _reference_map, Array<u2>*) \
nonstatic_field(ConstantPoolCache, _length, int) \
nonstatic_field(ConstantPoolCache, _constant_pool, ConstantPool*) \
volatile_nonstatic_field(InstanceKlass, _array_klasses, Klass*) \
--- a/hotspot/test/runtime/SharedArchiveFile/LimitSharedSizes.java Wed May 03 02:32:02 2017 +0000
+++ b/hotspot/test/runtime/SharedArchiveFile/LimitSharedSizes.java Fri Mar 03 23:08:35 2017 -0800
@@ -128,7 +128,7 @@
// test with sizes which just meet the minimum required sizes
// the following tests also attempt to use the shared archive
- new SharedSizeTestData(Region.RO, Platform.is64bit() ? "10M":"9M", Result.VALID_ARCHIVE),
+ new SharedSizeTestData(Region.RO, Platform.is64bit() ? "14M":"9M", Result.VALID_ARCHIVE),
new SharedSizeTestData(Region.RW, Platform.is64bit() ? "12M":"7M", Result.VALID_ARCHIVE),
new SharedSizeTestData(Region.MD, Platform.is64bit() ? "4M":"2M", Result.VALID_ARCHIVE),
new SharedSizeTestData(Region.MC, "120k", Result.VALID_ARCHIVE),