--- a/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp Tue Feb 13 16:57:01 2018 +0100
+++ b/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp Tue Feb 13 17:38:03 2018 +0100
@@ -492,6 +492,8 @@
// Add in the index.
add(result, tmp, result);
load_heap_oop(result, arrayOopDesc::base_offset_in_bytes(T_OBJECT), result, is_null);
+ // The resulting oop is null if the reference is not yet resolved.
+ // It is Universe::the_null_sentinel() if the reference resolved to NULL via condy.
}
// load cpool->resolved_klass_at(index)
--- a/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp Tue Feb 13 16:57:01 2018 +0100
+++ b/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp Tue Feb 13 17:38:03 2018 +0100
@@ -314,7 +314,7 @@
Rcpool = R3_ARG1;
transition(vtos, vtos);
- Label notInt, notClass, exit;
+ Label notInt, notFloat, notClass, exit;
__ get_cpool_and_tags(Rcpool, Rscratch2); // Set Rscratch2 = &tags.
if (wide) { // Read index.
@@ -356,13 +356,16 @@
__ align(32, 12);
__ bind(notInt);
-#ifdef ASSERT
- // String and Object are rewritten to fast_aldc
__ cmpdi(CCR0, Rscratch2, JVM_CONSTANT_Float);
- __ asm_assert_eq("unexpected type", 0x8765);
-#endif
+ __ bne(CCR0, notFloat);
__ lfsx(F15_ftos, Rcpool, Rscratch1);
__ push(ftos);
+ __ b(exit);
+
+ __ align(32, 12);
+ // assume the tag is for condy; if not, the VM runtime will tell us
+ __ bind(notFloat);
+ condy_helper(exit);
__ align(32, 12);
__ bind(exit);
@@ -380,6 +383,19 @@
// non-null object (CallSite, etc.)
__ get_cache_index_at_bcp(Rscratch, 1, index_size); // Load index.
__ load_resolved_reference_at_index(R17_tos, Rscratch, &is_null);
+
+ // Convert null sentinel to NULL.
+ int simm16_rest = __ load_const_optimized(Rscratch, Universe::the_null_sentinel_addr(), R0, true);
+ __ ld(Rscratch, simm16_rest, Rscratch);
+ __ cmpld(CCR0, R17_tos, Rscratch);
+ if (VM_Version::has_isel()) {
+ __ isel_0(R17_tos, CCR0, Assembler::equal);
+ } else {
+ Label not_sentinel;
+ __ bne(CCR0, not_sentinel);
+ __ li(R17_tos, 0);
+ __ bind(not_sentinel);
+ }
__ verify_oop(R17_tos);
__ dispatch_epilog(atos, Bytecodes::length_for(bytecode()));
@@ -395,7 +411,7 @@
void TemplateTable::ldc2_w() {
transition(vtos, vtos);
- Label Llong, Lexit;
+ Label not_double, not_long, exit;
Register Rindex = R11_scratch1,
Rcpool = R12_scratch2,
@@ -410,23 +426,129 @@
__ addi(Rtag, Rtag, tags_offset);
__ lbzx(Rtag, Rtag, Rindex);
-
__ sldi(Rindex, Rindex, LogBytesPerWord);
+
__ cmpdi(CCR0, Rtag, JVM_CONSTANT_Double);
- __ bne(CCR0, Llong);
- // A double can be placed at word-aligned locations in the constant pool.
- // Check out Conversions.java for an example.
- // Also ConstantPool::header_size() is 20, which makes it very difficult
- // to double-align double on the constant pool. SG, 11/7/97
+ __ bne(CCR0, not_double);
__ lfdx(F15_ftos, Rcpool, Rindex);
__ push(dtos);
- __ b(Lexit);
-
- __ bind(Llong);
+ __ b(exit);
+
+ __ bind(not_double);
+ __ cmpdi(CCR0, Rtag, JVM_CONSTANT_Long);
+ __ bne(CCR0, not_long);
__ ldx(R17_tos, Rcpool, Rindex);
__ push(ltos);
-
- __ bind(Lexit);
+ __ b(exit);
+
+ __ bind(not_long);
+ condy_helper(exit);
+
+ __ align(32, 12);
+ __ bind(exit);
+}
+
+void TemplateTable::condy_helper(Label& Done) {
+ const Register obj = R31;
+ const Register off = R11_scratch1;
+ const Register flags = R12_scratch2;
+ const Register rarg = R4_ARG2;
+ __ li(rarg, (int)bytecode());
+ call_VM(obj, CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_ldc), rarg);
+ __ get_vm_result_2(flags);
+
+ // VMr = obj = base address to find primitive value to push
+ // VMr2 = flags = (tos, off) using format of CPCE::_flags
+ __ andi(off, flags, ConstantPoolCacheEntry::field_index_mask);
+
+ // What sort of thing are we loading?
+ __ rldicl(flags, flags, 64-ConstantPoolCacheEntry::tos_state_shift, 64-ConstantPoolCacheEntry::tos_state_bits);
+
+ switch (bytecode()) {
+ case Bytecodes::_ldc:
+ case Bytecodes::_ldc_w:
+ {
+ // tos in (itos, ftos, stos, btos, ctos, ztos)
+ Label notInt, notFloat, notShort, notByte, notChar, notBool;
+ __ cmplwi(CCR0, flags, itos);
+ __ bne(CCR0, notInt);
+ // itos
+ __ lwax(R17_tos, obj, off);
+ __ push(itos);
+ __ b(Done);
+
+ __ bind(notInt);
+ __ cmplwi(CCR0, flags, ftos);
+ __ bne(CCR0, notFloat);
+ // ftos
+ __ lfsx(F15_ftos, obj, off);
+ __ push(ftos);
+ __ b(Done);
+
+ __ bind(notFloat);
+ __ cmplwi(CCR0, flags, stos);
+ __ bne(CCR0, notShort);
+ // stos
+ __ lhax(R17_tos, obj, off);
+ __ push(stos);
+ __ b(Done);
+
+ __ bind(notShort);
+ __ cmplwi(CCR0, flags, btos);
+ __ bne(CCR0, notByte);
+ // btos
+ __ lbzx(R17_tos, obj, off);
+ __ extsb(R17_tos, R17_tos);
+ __ push(btos);
+ __ b(Done);
+
+ __ bind(notByte);
+ __ cmplwi(CCR0, flags, ctos);
+ __ bne(CCR0, notChar);
+ // ctos
+ __ lhzx(R17_tos, obj, off);
+ __ push(ctos);
+ __ b(Done);
+
+ __ bind(notChar);
+ __ cmplwi(CCR0, flags, ztos);
+ __ bne(CCR0, notBool);
+ // ztos
+ __ lbzx(R17_tos, obj, off);
+ __ push(ztos);
+ __ b(Done);
+
+ __ bind(notBool);
+ break;
+ }
+
+ case Bytecodes::_ldc2_w:
+ {
+ Label notLong, notDouble;
+ __ cmplwi(CCR0, flags, ltos);
+ __ bne(CCR0, notLong);
+ // ltos
+ __ ldx(R17_tos, obj, off);
+ __ push(ltos);
+ __ b(Done);
+
+ __ bind(notLong);
+ __ cmplwi(CCR0, flags, dtos);
+ __ bne(CCR0, notDouble);
+ // dtos
+ __ lfdx(F15_ftos, obj, off);
+ __ push(dtos);
+ __ b(Done);
+
+ __ bind(notDouble);
+ break;
+ }
+
+ default:
+ ShouldNotReachHere();
+ }
+
+ __ stop("bad ldc/condy");
}
// Get the locals index located in the bytecode stream at bcp + offset.
--- a/src/hotspot/cpu/s390/interp_masm_s390.cpp Tue Feb 13 16:57:01 2018 +0100
+++ b/src/hotspot/cpu/s390/interp_masm_s390.cpp Tue Feb 13 17:38:03 2018 +0100
@@ -389,6 +389,8 @@
#endif
z_agr(result, index); // Address of indexed array element.
load_heap_oop(result, arrayOopDesc::base_offset_in_bytes(T_OBJECT), result);
+ // The resulting oop is null if the reference is not yet resolved.
+ // It is Universe::the_null_sentinel() if the reference resolved to NULL via condy.
}
// load cpool->resolved_klass_at(index)
--- a/src/hotspot/cpu/s390/templateTable_s390.cpp Tue Feb 13 16:57:01 2018 +0100
+++ b/src/hotspot/cpu/s390/templateTable_s390.cpp Tue Feb 13 17:38:03 2018 +0100
@@ -450,7 +450,7 @@
void TemplateTable::ldc(bool wide) {
transition(vtos, vtos);
- Label call_ldc, notFloat, notClass, Done;
+ Label call_ldc, notFloat, notClass, notInt, Done;
const Register RcpIndex = Z_tmp_1;
const Register Rtags = Z_ARG2;
@@ -500,22 +500,17 @@
__ z_bru(Done);
__ bind(notFloat);
-#ifdef ASSERT
- {
- Label L;
-
- __ z_cli(0, Raddr_type, JVM_CONSTANT_Integer);
- __ z_bre(L);
- // String and Object are rewritten to fast_aldc.
- __ stop("unexpected tag type in ldc");
-
- __ bind(L);
- }
-#endif
+ __ z_cli(0, Raddr_type, JVM_CONSTANT_Integer);
+ __ z_brne(notInt);
// itos
__ mem2reg_opt(Z_tos, Address(Z_tmp_2, RcpOffset, base_offset), false);
__ push_i(Z_tos);
+ __ z_bru(Done);
+
+ // assume the tag is for condy; if not, the VM runtime will tell us
+ __ bind(notInt);
+ condy_helper(Done);
__ bind(Done);
}
@@ -528,15 +523,23 @@
const Register index = Z_tmp_2;
int index_size = wide ? sizeof(u2) : sizeof(u1);
- Label L_resolved;
+ Label L_do_resolve, L_resolved;
// We are resolved if the resolved reference cache entry contains a
// non-null object (CallSite, etc.).
__ get_cache_index_at_bcp(index, 1, index_size); // Load index.
__ load_resolved_reference_at_index(Z_tos, index);
__ z_ltgr(Z_tos, Z_tos);
+ __ z_bre(L_do_resolve);
+
+ // Convert null sentinel to NULL.
+ __ load_const_optimized(Z_R1_scratch, (intptr_t)Universe::the_null_sentinel_addr());
+ __ z_cg(Z_tos, Address(Z_R1_scratch));
__ z_brne(L_resolved);
-
+ __ clear_reg(Z_tos);
+ __ z_bru(L_resolved);
+
+ __ bind(L_do_resolve);
// First time invocation - must resolve first.
address entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_ldc);
__ load_const_optimized(Z_ARG1, (int)bytecode());
@@ -548,7 +551,7 @@
void TemplateTable::ldc2_w() {
transition(vtos, vtos);
- Label Long, Done;
+ Label notDouble, notLong, Done;
// Z_tmp_1 = index of cp entry
__ get_2_byte_integer_at_bcp(Z_tmp_1, 1, InterpreterMacroAssembler::Unsigned);
@@ -566,21 +569,132 @@
// Check type.
__ z_cli(0, Z_tos, JVM_CONSTANT_Double);
- __ z_brne(Long);
-
+ __ z_brne(notDouble);
// dtos
__ mem2freg_opt(Z_ftos, Address(Z_tmp_2, Z_tmp_1, base_offset));
__ push_d();
__ z_bru(Done);
- __ bind(Long);
+ __ bind(notDouble);
+ __ z_cli(0, Z_tos, JVM_CONSTANT_Long);
+ __ z_brne(notLong);
// ltos
__ mem2reg_opt(Z_tos, Address(Z_tmp_2, Z_tmp_1, base_offset));
__ push_l();
+ __ z_bru(Done);
+
+ __ bind(notLong);
+ condy_helper(Done);
__ bind(Done);
}
+void TemplateTable::condy_helper(Label& Done) {
+ const Register obj = Z_tmp_1;
+ const Register off = Z_tmp_2;
+ const Register flags = Z_ARG1;
+ const Register rarg = Z_ARG2;
+ __ load_const_optimized(rarg, (int)bytecode());
+ call_VM(obj, CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_ldc), rarg);
+ __ get_vm_result_2(flags);
+
+ // VMr = obj = base address to find primitive value to push
+ // VMr2 = flags = (tos, off) using format of CPCE::_flags
+ assert(ConstantPoolCacheEntry::field_index_mask == 0xffff, "or use other instructions");
+ __ z_llghr(off, flags);
+ const Address field(obj, off);
+
+ // What sort of thing are we loading?
+ __ z_srl(flags, ConstantPoolCacheEntry::tos_state_shift);
+ // Make sure we don't need to mask flags for tos_state after the above shift.
+ ConstantPoolCacheEntry::verify_tos_state_shift();
+
+ switch (bytecode()) {
+ case Bytecodes::_ldc:
+ case Bytecodes::_ldc_w:
+ {
+ // tos in (itos, ftos, stos, btos, ctos, ztos)
+ Label notInt, notFloat, notShort, notByte, notChar, notBool;
+ __ z_cghi(flags, itos);
+ __ z_brne(notInt);
+ // itos
+ __ z_l(Z_tos, field);
+ __ push(itos);
+ __ z_bru(Done);
+
+ __ bind(notInt);
+ __ z_cghi(flags, ftos);
+ __ z_brne(notFloat);
+ // ftos
+ __ z_le(Z_ftos, field);
+ __ push(ftos);
+ __ z_bru(Done);
+
+ __ bind(notFloat);
+ __ z_cghi(flags, stos);
+ __ z_brne(notShort);
+ // stos
+ __ z_lh(Z_tos, field);
+ __ push(stos);
+ __ z_bru(Done);
+
+ __ bind(notShort);
+ __ z_cghi(flags, btos);
+ __ z_brne(notByte);
+ // btos
+ __ z_lb(Z_tos, field);
+ __ push(btos);
+ __ z_bru(Done);
+
+ __ bind(notByte);
+ __ z_cghi(flags, ctos);
+ __ z_brne(notChar);
+ // ctos
+ __ z_llh(Z_tos, field);
+ __ push(ctos);
+ __ z_bru(Done);
+
+ __ bind(notChar);
+ __ z_cghi(flags, ztos);
+ __ z_brne(notBool);
+ // ztos
+ __ z_lb(Z_tos, field);
+ __ push(ztos);
+ __ z_bru(Done);
+
+ __ bind(notBool);
+ break;
+ }
+
+ case Bytecodes::_ldc2_w:
+ {
+ Label notLong, notDouble;
+ __ z_cghi(flags, ltos);
+ __ z_brne(notLong);
+ // ltos
+ __ z_lg(Z_tos, field);
+ __ push(ltos);
+ __ z_bru(Done);
+
+ __ bind(notLong);
+ __ z_cghi(flags, dtos);
+ __ z_brne(notDouble);
+ // dtos
+ __ z_ld(Z_ftos, field);
+ __ push(dtos);
+ __ z_bru(Done);
+
+ __ bind(notDouble);
+ break;
+ }
+
+ default:
+ ShouldNotReachHere();
+ }
+
+ __ stop("bad ldc/condy");
+}
+
void TemplateTable::locals_index(Register reg, int offset) {
__ z_llgc(reg, at_bcp(offset));
__ z_lcgr(reg);
--- a/test/jdk/java/lang/invoke/condy/CondyRepeatFailedResolution.java Tue Feb 13 16:57:01 2018 +0100
+++ b/test/jdk/java/lang/invoke/condy/CondyRepeatFailedResolution.java Tue Feb 13 17:38:03 2018 +0100
@@ -25,7 +25,7 @@
* @test
* @bug 8186211
* @summary Test basic invocation of multiple ldc's of the same dynamic constant that fail resolution
- * @requires os.arch == "x86_64" | os.arch=="aarch64"
+ * @requires os.arch != "sparcv9"
* @library /lib/testlibrary/bytecode /java/lang/invoke/common
* @build jdk.experimental.bytecode.BasicClassBuilder
* @run testng CondyRepeatFailedResolution
--- a/test/jdk/java/lang/invoke/condy/CondyReturnPrimitiveTest.java Tue Feb 13 16:57:01 2018 +0100
+++ b/test/jdk/java/lang/invoke/condy/CondyReturnPrimitiveTest.java Tue Feb 13 17:38:03 2018 +0100
@@ -25,7 +25,7 @@
* @test
* @bug 8186046
* @summary Test for condy BSMs returning primitive values or null
- * @requires os.arch=="x86_64" | os.arch=="aarch64"
+ * @requires os.arch != "sparcv9"
* @library /lib/testlibrary/bytecode
* @build jdk.experimental.bytecode.BasicClassBuilder
* @run testng CondyReturnPrimitiveTest
--- a/test/jdk/java/lang/invoke/condy/CondyWrongType.java Tue Feb 13 16:57:01 2018 +0100
+++ b/test/jdk/java/lang/invoke/condy/CondyWrongType.java Tue Feb 13 17:38:03 2018 +0100
@@ -25,7 +25,7 @@
* @test
* @bug 8186046
* @summary Test bootstrap methods returning the wrong type
- * @requires os.arch == "x86_64" | os.arch=="aarch64"
+ * @requires os.arch != "sparcv9"
* @library /lib/testlibrary/bytecode /java/lang/invoke/common
* @build jdk.experimental.bytecode.BasicClassBuilder test.java.lang.invoke.lib.InstructionHelper
* @run testng CondyWrongType