changeset 48954:67aa88701d46

8190428: Minimal Dynamic Constant support for AArch64 Summary: AArch64 specific code for 8186046 Reviewed-by: aph, psandoz
author dsamersoff
date Sat, 10 Feb 2018 09:48:51 +0000
parents e999964446d7
children c8a33db795b6
files src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp src/hotspot/cpu/aarch64/interp_masm_aarch64.hpp src/hotspot/cpu/aarch64/templateTable_aarch64.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
diffstat 6 files changed, 170 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp	Fri Feb 09 09:56:05 2018 -0800
+++ b/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp	Sat Feb 10 09:48:51 2018 +0000
@@ -277,6 +277,8 @@
   // Add in the index
   add(result, result, tmp);
   load_heap_oop(result, Address(result, arrayOopDesc::base_offset_in_bytes(T_OBJECT)));
+  // 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.
 }
 
 void InterpreterMacroAssembler::load_resolved_klass_at_offset(
@@ -399,6 +401,13 @@
   str(val, Address(esp, Interpreter::expr_offset_in_bytes(n)));
 }
 
+void InterpreterMacroAssembler::load_float(Address src) {
+  ldrs(v0, src);
+}
+
+void InterpreterMacroAssembler::load_double(Address src) {
+  ldrd(v0, src);
+}
 
 void InterpreterMacroAssembler::prepare_to_jump_from_interpreted() {
   // set sender sp
--- a/src/hotspot/cpu/aarch64/interp_masm_aarch64.hpp	Fri Feb 09 09:56:05 2018 -0800
+++ b/src/hotspot/cpu/aarch64/interp_masm_aarch64.hpp	Sat Feb 10 09:48:51 2018 +0000
@@ -158,6 +158,10 @@
   void load_ptr(int n, Register val);
   void store_ptr(int n, Register val);
 
+// Load float value from 'address'. The value is loaded onto the FPU register v0.
+  void load_float(Address src);
+  void load_double(Address src);
+
   // Generate a subtype check: branch to ok_is_subtype if sub_klass is
   // a subtype of super_klass.
   void gen_subtype_check( Register sub_klass, Label &ok_is_subtype );
--- a/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp	Fri Feb 09 09:56:05 2018 -0800
+++ b/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp	Sat Feb 10 09:48:51 2018 +0000
@@ -370,7 +370,7 @@
 void TemplateTable::ldc(bool wide)
 {
   transition(vtos, vtos);
-  Label call_ldc, notFloat, notClass, Done;
+  Label call_ldc, notFloat, notClass, notInt, Done;
 
   if (wide) {
     __ get_unsigned_2_byte_index_at_bcp(r1, 1);
@@ -417,20 +417,19 @@
   __ b(Done);
 
   __ bind(notFloat);
-#ifdef ASSERT
-  {
-    Label L;
-    __ cmp(r3, JVM_CONSTANT_Integer);
-    __ br(Assembler::EQ, L);
-    // String and Object are rewritten to fast_aldc
-    __ stop("unexpected tag type in ldc");
-    __ bind(L);
-  }
-#endif
-  // itos JVM_CONSTANT_Integer only
+
+  __ cmp(r3, JVM_CONSTANT_Integer);
+  __ br(Assembler::NE, notInt);
+
+  // itos
   __ adds(r1, r2, r1, Assembler::LSL, 3);
   __ ldrw(r0, Address(r1, base_offset));
   __ push_i(r0);
+  __ b(Done);
+
+  __ bind(notInt);
+  condy_helper(Done);
+
   __ bind(Done);
 }
 
@@ -441,6 +440,8 @@
 
   Register result = r0;
   Register tmp = r1;
+  Register rarg = r2;
+
   int index_size = wide ? sizeof(u2) : sizeof(u1);
 
   Label resolved;
@@ -455,12 +456,27 @@
   address entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_ldc);
 
   // first time invocation - must resolve first
-  __ mov(tmp, (int)bytecode());
-  __ call_VM(result, entry, tmp);
+  __ mov(rarg, (int)bytecode());
+  __ call_VM(result, entry, rarg);
 
   __ bind(resolved);
 
+  { // Check for the null sentinel.
+    // If we just called the VM, that already did the mapping for us,
+    // but it's harmless to retry.
+    Label notNull;
+
+    // Stash null_sentinel address to get its value later
+    __ movptr(rarg, (uintptr_t)Universe::the_null_sentinel_addr());
+    __ ldr(tmp, Address(rarg));
+    __ cmp(result, tmp);
+    __ br(Assembler::NE, notNull);
+    __ mov(result, 0);  // NULL object reference
+    __ bind(notNull);
+  }
+
   if (VerifyOops) {
+    // Safe to call with 0 result
     __ verify_oop(result);
   }
 }
@@ -468,7 +484,7 @@
 void TemplateTable::ldc2_w()
 {
   transition(vtos, vtos);
-  Label Long, Done;
+  Label notDouble, notLong, Done;
   __ get_unsigned_2_byte_index_at_bcp(r0, 1);
 
   __ get_cpool_and_tags(r1, r2);
@@ -479,22 +495,143 @@
   __ lea(r2, Address(r2, r0, Address::lsl(0)));
   __ load_unsigned_byte(r2, Address(r2, tags_offset));
   __ cmpw(r2, (int)JVM_CONSTANT_Double);
-  __ br(Assembler::NE, Long);
+  __ br(Assembler::NE, notDouble);
+
   // dtos
   __ lea (r2, Address(r1, r0, Address::lsl(3)));
   __ ldrd(v0, Address(r2, base_offset));
   __ push_d();
   __ b(Done);
 
-  __ bind(Long);
+  __ bind(notDouble);
+  __ cmpw(r2, (int)JVM_CONSTANT_Long);
+  __ br(Assembler::NE, notLong);
+
   // ltos
   __ lea(r0, Address(r1, r0, Address::lsl(3)));
   __ ldr(r0, Address(r0, base_offset));
   __ push_l();
+  __ b(Done);
+
+  __ bind(notLong);
+  condy_helper(Done);
 
   __ bind(Done);
 }
 
+void TemplateTable::condy_helper(Label& Done)
+{
+  Register obj = r0;
+  Register rarg = r1;
+  Register flags = r2;
+  Register off = r3;
+
+  address entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_ldc);
+
+  __ mov(rarg, (int) bytecode());
+  __ call_VM(obj, entry, rarg);
+
+  __ get_vm_result_2(flags, rthread);
+
+  // VMr = obj = base address to find primitive value to push
+  // VMr2 = flags = (tos, off) using format of CPCE::_flags
+  __ mov(off, flags);
+  __ andw(off, off, ConstantPoolCacheEntry::field_index_mask);
+
+  const Address field(obj, off);
+
+  // What sort of thing are we loading?
+  // x86 uses a shift and mask or wings it with a shift plus assert
+  // the mask is not needed. aarch64 just uses bitfield extract
+  __ ubfxw(flags, flags, ConstantPoolCacheEntry::tos_state_shift,
+           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;
+        __ cmpw(flags, itos);
+        __ br(Assembler::NE, notInt);
+        // itos
+        __ ldrw(r0, field);
+        __ push(itos);
+        __ b(Done);
+
+        __ bind(notInt);
+        __ cmpw(flags, ftos);
+        __ br(Assembler::NE, notFloat);
+        // ftos
+        __ load_float(field);
+        __ push(ftos);
+        __ b(Done);
+
+        __ bind(notFloat);
+        __ cmpw(flags, stos);
+        __ br(Assembler::NE, notShort);
+        // stos
+        __ load_signed_short(r0, field);
+        __ push(stos);
+        __ b(Done);
+
+        __ bind(notShort);
+        __ cmpw(flags, btos);
+        __ br(Assembler::NE, notByte);
+        // btos
+        __ load_signed_byte(r0, field);
+        __ push(btos);
+        __ b(Done);
+
+        __ bind(notByte);
+        __ cmpw(flags, ctos);
+        __ br(Assembler::NE, notChar);
+        // ctos
+        __ load_unsigned_short(r0, field);
+        __ push(ctos);
+        __ b(Done);
+
+        __ bind(notChar);
+        __ cmpw(flags, ztos);
+        __ br(Assembler::NE, notBool);
+        // ztos
+        __ load_signed_byte(r0, field);
+        __ push(ztos);
+        __ b(Done);
+
+        __ bind(notBool);
+        break;
+      }
+
+    case Bytecodes::_ldc2_w:
+      {
+        Label notLong, notDouble;
+        __ cmpw(flags, ltos);
+        __ br(Assembler::NE, notLong);
+        // ltos
+        __ ldr(r0, field);
+        __ push(ltos);
+        __ b(Done);
+
+        __ bind(notLong);
+        __ cmpw(flags, dtos);
+        __ br(Assembler::NE, notDouble);
+        // dtos
+        __ load_double(field);
+        __ push(dtos);
+        __ b(Done);
+
+       __ bind(notDouble);
+        break;
+      }
+
+    default:
+      ShouldNotReachHere();
+    }
+
+    __ stop("bad ldc/condy");
+}
+
 void TemplateTable::locals_index(Register reg, int offset)
 {
   __ ldrb(reg, at_bcp(offset));
--- a/test/jdk/java/lang/invoke/condy/CondyRepeatFailedResolution.java	Fri Feb 09 09:56:05 2018 -0800
+++ b/test/jdk/java/lang/invoke/condy/CondyRepeatFailedResolution.java	Sat Feb 10 09:48:51 2018 +0000
@@ -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"
+ * @requires os.arch == "x86_64" | os.arch=="aarch64"
  * @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	Fri Feb 09 09:56:05 2018 -0800
+++ b/test/jdk/java/lang/invoke/condy/CondyReturnPrimitiveTest.java	Sat Feb 10 09:48:51 2018 +0000
@@ -25,7 +25,7 @@
  * @test
  * @bug 8186046
  * @summary Test for condy BSMs returning primitive values or null
- * @requires os.arch == "x86_64"
+ * @requires os.arch=="x86_64" | os.arch=="aarch64"
  * @library /lib/testlibrary/bytecode
  * @build jdk.experimental.bytecode.BasicClassBuilder
  * @run testng CondyReturnPrimitiveTest
--- a/test/jdk/java/lang/invoke/condy/CondyWrongType.java	Fri Feb 09 09:56:05 2018 -0800
+++ b/test/jdk/java/lang/invoke/condy/CondyWrongType.java	Sat Feb 10 09:48:51 2018 +0000
@@ -25,7 +25,7 @@
  * @test
  * @bug 8186046
  * @summary Test bootstrap methods returning the wrong type
- * @requires os.arch == "x86_64"
+ * @requires os.arch == "x86_64" | os.arch=="aarch64"
  * @library /lib/testlibrary/bytecode /java/lang/invoke/common
  * @build jdk.experimental.bytecode.BasicClassBuilder test.java.lang.invoke.lib.InstructionHelper
  * @run testng CondyWrongType