< prev index next >

src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp

Print this page
rev 54670 : Port of valuetypes to aarch64

@@ -36,10 +36,11 @@
 #include "memory/resourceArea.hpp"
 #include "oops/arrayOop.hpp"
 #include "oops/methodData.hpp"
 #include "oops/method.hpp"
 #include "oops/oop.inline.hpp"
+#include "oops/valueKlass.hpp"
 #include "prims/jvmtiExport.hpp"
 #include "prims/jvmtiThreadState.hpp"
 #include "runtime/arguments.hpp"
 #include "runtime/deoptimization.hpp"
 #include "runtime/frame.inline.hpp"

@@ -438,10 +439,73 @@
 
   // Restore stack bottom in case i2c adjusted stack
   __ ldr(esp, Address(rfp, frame::interpreter_frame_last_sp_offset * wordSize));
   // and NULL it as marker that esp is now tos until next java call
   __ str(zr, Address(rfp, frame::interpreter_frame_last_sp_offset * wordSize));
+
+ if (state == atos && ValueTypeReturnedAsFields) {
+    // A value type might be returned. If fields are in registers we
+    // need to allocate a value type instance and initialize it with
+    // the value of the fields.
+    Label skip, slow_case;
+
+    // We only need a new buffered value if a new one is not returned
+
+    __ tbz(r0, 0, skip);
+
+    // Try to allocate a new buffered value (from the heap)
+    if (UseTLAB) {
+
+      // klass is in r0
+      __ andr(rscratch1, r0, -2);
+      
+      // get obj size
+      __ ldrw(rscratch1, Address(rscratch1 /*klass*/, Klass::layout_helper_offset()));
+      __ ldr(rscratch2, Address(rthread, in_bytes(JavaThread::tlab_top_offset())));
+
+     // check whether we have space in TLAB, 
+     // rscratch1 contains pointer to just allocated obj
+      __ lea(rscratch1, Address(rscratch1, rscratch2)); 
+      __ ldr(rscratch2, Address(rthread, in_bytes(JavaThread::tlab_end_offset())));
+
+      __ cmp(rscratch1, rscratch2);
+      __ br(Assembler::GT, slow_case);
+
+      // OK we have room in TLAB, 
+      // Set new TLAB top
+      __ str(rscratch1, Address(rthread, in_bytes(JavaThread::tlab_top_offset()))); 
+
+      // Set new class always locked
+      __ mov(rscratch2, (uint64_t) markOopDesc::always_locked_prototype());
+      __ str(rscratch2, Address(rscratch1, oopDesc::mark_offset_in_bytes()));
+
+      __ store_klass_gap(rscratch1, zr);  // zero klass gap for compressed oops
+      __ andr(rscratch2, r0, -2);
+      __ store_klass(rscratch1, rscratch2);  // klass
+
+      // We have our new buffered value, initialize its fields with a
+      // value class specific handler
+      __ ldr(rscratch2, Address(rscratch1, InstanceKlass::adr_valueklass_fixed_block_offset()));
+      __ ldr(rscratch2, Address(rscratch2, ValueKlass::pack_handler_offset()));
+
+
+      // Mov new class to r0 and call pack_handler
+      __ mov(r0, rscratch1);
+      __ blrt(rscratch2, 1, 0, 0);
+      __ b(skip);
+    }
+
+    __ bind(slow_case);
+
+    // We failed to allocate a new value, fall back to a runtime
+    // call. Some oop field may be live in some registers but we can't
+    // tell. That runtime call will take care of preserving them
+    // across a GC if there's one.
+    __ super_call_VM_leaf(StubRoutines::store_value_type_fields_to_buf());
+    __ bind(skip);
+  }
+
   __ restore_bcp();
   __ restore_locals();
   __ restore_constant_pool_cache();
   __ get_method(rmethod);
 

@@ -564,10 +628,11 @@
   case T_INT    : __ uxtw(r0, r0);        break;  // FIXME: We almost certainly don't need this
   case T_LONG   : /* nothing to do */        break;
   case T_VOID   : /* nothing to do */        break;
   case T_FLOAT  : /* nothing to do */        break;
   case T_DOUBLE : /* nothing to do */        break;
+  case T_VALUETYPE: // fall through (value types are handled with oops)
   case T_OBJECT :
     // retrieve result from frame
     __ ldr(r0, Address(rfp, frame::interpreter_frame_oop_temp_offset*wordSize));
     // and verify it
     __ verify_oop(r0);
< prev index next >