< 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 >