< prev index next >

src/hotspot/cpu/aarch64/c1_MacroAssembler_aarch64.cpp

Print this page

        

@@ -26,10 +26,12 @@
 #include "precompiled.hpp"
 #include "c1/c1_MacroAssembler.hpp"
 #include "c1/c1_Runtime1.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "gc/shared/collectedHeap.hpp"
+#include "gc/shared/barrierSet.hpp"
+#include "gc/shared/barrierSetAssembler.hpp"
 #include "interpreter/interpreter.hpp"
 #include "oops/arrayOop.hpp"
 #include "oops/markOop.hpp"
 #include "runtime/basicLock.hpp"
 #include "runtime/biasedLocking.hpp"

@@ -81,10 +83,16 @@
 
   // Load object header
   ldr(hdr, Address(obj, hdr_offset));
   // and mark it as unlocked
   orr(hdr, hdr, markOopDesc::unlocked_value);
+
+  if (EnableValhalla && !UseBiasedLocking) {
+    // Mask always_locked bit such that we go to the slow path if object is a value type
+    andr(hdr, hdr, ~markOopDesc::biased_lock_bit_in_place);
+  }
+
   // save unlocked object header into the displaced header location on the stack
   str(hdr, Address(disp_hdr, 0));
   // test if object header is still the same (i.e. unlocked), and if so, store the
   // displaced header address in the object header - if it is not the same, get the
   // object header instead

@@ -328,37 +336,140 @@
 
   cmp_klass(receiver, iCache, rscratch1);
 }
 
 
-void C1_MacroAssembler::build_frame(int framesize, int bang_size_in_bytes) {
+void C1_MacroAssembler::build_frame(int framesize, int bang_size_in_bytes,  bool needs_stack_repair, Label* verified_value_entry_label) {
+   
+
   // If we have to make this method not-entrant we'll overwrite its
   // first instruction with a jump.  For this action to be legal we
   // must ensure that this first instruction is a B, BL, NOP, BKPT,
   // SVC, HVC, or SMC.  Make it a NOP.
   nop();
   assert(bang_size_in_bytes >= framesize, "stack bang size incorrect");
   // Make sure there is enough stack space for this method's activation.
   // Note that we do this before doing an enter().
   generate_stack_overflow_check(bang_size_in_bytes);
+
+  guarantee(needs_stack_repair == false, "Stack repair should not be true");
+  if (verified_value_entry_label != NULL) {
+    bind(*verified_value_entry_label);
+  }
+
   MacroAssembler::build_frame(framesize + 2 * wordSize);
   if (NotifySimulator) {
     notify(Assembler::method_entry);
   }
 }
 
-void C1_MacroAssembler::remove_frame(int framesize) {
+void C1_MacroAssembler::remove_frame(int framesize, bool needs_stack_repair) {
+
+  guarantee(needs_stack_repair == false, "Stack repair should not be true");
+
   MacroAssembler::remove_frame(framesize + 2 * wordSize);
   if (NotifySimulator) {
     notify(Assembler::method_reentry);
   }
 }
 
+void C1_MacroAssembler::verified_value_entry() {
+  if (C1Breakpoint || VerifyFPU || !UseStackBanging) {
+    // Verified Entry first instruction should be 5 bytes long for correct
+    // patching by patch_verified_entry().
+    //
+    // C1Breakpoint and VerifyFPU have one byte first instruction.
+    // Also first instruction will be one byte "push(rbp)" if stack banging
+    // code is not generated (see build_frame() above).
+    // For all these cases generate long instruction first.
+    nop();
+  }
+  
+  // build frame
+  // verify_FPU(0, "method_entry");
+}
+
+int C1_MacroAssembler::scalarized_entry(const CompiledEntrySignature *ces, int frame_size_in_bytes, int bang_size_in_bytes, Label& verified_value_entry_label, bool is_value_ro_entry) {
+  // This function required to support for ValueTypePassFieldsAsArgs
+  if (C1Breakpoint || VerifyFPU || !UseStackBanging) {
+    // Verified Entry first instruction should be 5 bytes long for correct
+    // patching by patch_verified_entry().
+    //
+    // C1Breakpoint and VerifyFPU have one byte first instruction.
+    // Also first instruction will be one byte "push(rbp)" if stack banging
+    // code is not generated (see build_frame() above).
+    // For all these cases generate long instruction first.
+    nop();
+  }
+
+  // verify_FPU(0, "method_entry");
+
+  assert(ValueTypePassFieldsAsArgs, "sanity");
+
+  GrowableArray<SigEntry>* sig   = &ces->sig();
+  GrowableArray<SigEntry>* sig_cc = is_value_ro_entry ? &ces->sig_cc_ro() : &ces->sig_cc();
+  VMRegPair* regs      = ces->regs();
+  VMRegPair* regs_cc   = is_value_ro_entry ? ces->regs_cc_ro() : ces->regs_cc();
+  int args_on_stack    = ces->args_on_stack();
+  int args_on_stack_cc = is_value_ro_entry ? ces->args_on_stack_cc_ro() : ces->args_on_stack_cc();
+
+  assert(sig->length() <= sig_cc->length(), "Zero-sized value class not allowed!");
+  BasicType* sig_bt = NEW_RESOURCE_ARRAY(BasicType, sig_cc->length());
+  int args_passed = sig->length();
+  int args_passed_cc = SigEntry::fill_sig_bt(sig_cc, sig_bt);
+
+  int extra_stack_offset = wordSize; // tos is return address.
+
+  // Create a temp frame so we can call into runtime. It must be properly set up to accomodate GC.
+  int sp_inc = (args_on_stack - args_on_stack_cc) * VMRegImpl::stack_slot_size;
+  if (sp_inc > 0) {
+    sp_inc = align_up(sp_inc, StackAlignmentInBytes);
+    sub(sp, sp, sp_inc);
+  } else {
+    sp_inc = 0;
+  }
+
+  sub(sp, sp, frame_size_in_bytes);
+  if (sp_inc > 0) {
+    int real_frame_size = frame_size_in_bytes +
+           + wordSize  // pushed rbp
+           + wordSize  // returned address pushed by the stack extension code
+           + sp_inc;   // stack extension
+    mov(rscratch1, real_frame_size);
+    str(rscratch1, Address(sp, frame_size_in_bytes - wordSize));
+  }
+
+  // FIXME -- call runtime only if we cannot in-line allocate all the incoming value args.
+  mov(r1, (intptr_t) ces->method());
+  if (is_value_ro_entry) {
+    far_call(RuntimeAddress(Runtime1::entry_for(Runtime1::buffer_value_args_no_receiver_id)));
+  } else {
+    far_call(RuntimeAddress(Runtime1::entry_for(Runtime1::buffer_value_args_id)));
+  }
+  int rt_call_offset = offset();
+
+  // Remove the temp frame
+  add(sp, sp, frame_size_in_bytes);
 
-void C1_MacroAssembler::verified_entry() {
+  int n = shuffle_value_args(true, is_value_ro_entry, extra_stack_offset, sig_bt, sig_cc,
+                             args_passed_cc, args_on_stack_cc, regs_cc, // from
+                             args_passed, args_on_stack, regs);         // to
+  assert(sp_inc == n, "must be");
+
+  if (sp_inc != 0) {
+    // Do the stack banging here, and skip over the stack repair code in the
+    // verified_value_entry (which has a different real_frame_size).
+    assert(sp_inc > 0, "stack should not shrink");
+    generate_stack_overflow_check(bang_size_in_bytes);
+    decrement(sp, frame_size_in_bytes);
+  }
+
+  b(verified_value_entry_label);
+  return rt_call_offset;
 }
 
+
 void C1_MacroAssembler::load_parameter(int offset_in_words, Register reg) {
   // rbp, + 0: link
   //     + 1: return address
   //     + 2: argument with offset 0
   //     + 3: argument with offset 1
< prev index next >