8196786: [PPC64+s390] ConstantDynamic support
authormdoerr
Tue, 13 Feb 2018 17:38:03 +0100
changeset 48965 be873d8c0114
parent 48964 86143b5899dc
child 48966 e6eb66d2e765
8196786: [PPC64+s390] ConstantDynamic support Reviewed-by: psandoz, dsamersoff
src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp
src/hotspot/cpu/ppc/templateTable_ppc_64.cpp
src/hotspot/cpu/s390/interp_masm_s390.cpp
src/hotspot/cpu/s390/templateTable_s390.cpp
test/jdk/java/lang/invoke/condy/CondyRepeatFailedResolution.java
test/jdk/java/lang/invoke/condy/CondyReturnPrimitiveTest.java
test/jdk/java/lang/invoke/condy/CondyWrongType.java
--- 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