< prev index next >

src/cpu/x86/vm/templateInterpreterGenerator_x86.cpp

Print this page

        

@@ -32,10 +32,11 @@
 #include "interpreter/templateTable.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"

@@ -202,14 +203,65 @@
   __ movptr(rsp, Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize));
   // and NULL it as marker that esp is now tos until next java call
   __ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), (int32_t)NULL_WORD);
 
   if (state == qtos && ValueTypeReturnedAsFields) {
+#ifndef _LP64
+    __ super_call_VM_leaf(StubRoutines::store_value_type_fields_to_buf());
+#else
     // A value type is being 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
+    __ testptr(rax, 1);
+    __ jcc(Assembler::zero, skip);
+
+    // Try to allocate a new buffered value (from the heap)
+    if (UseTLAB) {
+      __ mov(rbx, rax);
+      __ andptr(rbx, -2);
+
+      __ cmpptr(Address(rbx, ValueKlass::pack_handler_offset()), 0);
+      __ jcc(Assembler::equal, slow_case);
+
+      __ movl(r14, Address(rbx, Klass::layout_helper_offset()));
+
+      __ movptr(r13, Address(r15_thread, in_bytes(JavaThread::tlab_top_offset())));
+      __ lea(r14, Address(r13, r14, Address::times_1));
+      __ cmpptr(r14, Address(r15_thread, in_bytes(JavaThread::tlab_end_offset())));
+      __ jcc(Assembler::above, slow_case);
+      __ movptr(Address(r15_thread, in_bytes(JavaThread::tlab_top_offset())), r14);
+
+      if (UseBiasedLocking) {
+        __ movptr(rax, Address(rbx, Klass::prototype_header_offset()));
+        __ movptr(Address(r13, oopDesc::mark_offset_in_bytes ()), rax);
+      } else {
+        __ movptr(Address(r13, oopDesc::mark_offset_in_bytes ()),
+                  (intptr_t)markOopDesc::prototype());
+      }
+      __ xorl(rax, rax); // use zero reg to clear memory (shorter code)
+      __ store_klass_gap(r13, rax);  // zero klass gap for compressed oops
+      __ mov(rax, rbx);
+      __ store_klass(r13, rbx);  // klass
+
+      // We have our new buffered value, initialize its fields with a
+      // value class specific handler
+      __ movptr(rbx, Address(rax, ValueKlass::pack_handler_offset()));
+      __ mov(rax, r13);
+      __ call(rbx);
+      __ jmp(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);
+#endif
   }
 
   __ restore_bcp();
   __ restore_locals();
   
< prev index next >