--- old/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp 2019-03-26 15:45:33.922849964 +0000 +++ new/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp 2019-03-26 15:45:32.522791692 +0000 @@ -38,6 +38,7 @@ #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" @@ -440,6 +441,69 @@ __ 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(); @@ -566,6 +630,7 @@ 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));