< prev index next >

src/hotspot/cpu/riscv/macroAssembler_riscv.cpp

Print this page
@@ -24,10 +24,11 @@
   *
   */
  
  #include "asm/assembler.hpp"
  #include "asm/assembler.inline.hpp"
+ #include "ci/ciInlineKlass.hpp"
  #include "code/compiledIC.hpp"
  #include "compiler/disassembler.hpp"
  #include "gc/shared/barrierSet.hpp"
  #include "gc/shared/barrierSetAssembler.hpp"
  #include "gc/shared/cardTable.hpp"

@@ -41,10 +42,11 @@
  #include "oops/accessDecorators.hpp"
  #include "oops/compressedKlass.inline.hpp"
  #include "oops/compressedOops.inline.hpp"
  #include "oops/klass.inline.hpp"
  #include "oops/oop.hpp"
+ #include "oops/resolvedFieldEntry.hpp"
  #include "runtime/interfaceSupport.inline.hpp"
  #include "runtime/javaThread.hpp"
  #include "runtime/jniHandles.inline.hpp"
  #include "runtime/sharedRuntime.hpp"
  #include "runtime/stubRoutines.hpp"

@@ -943,10 +945,14 @@
    pass_arg1(this, arg_1);
    pass_arg2(this, arg_2);
    call_VM_leaf_base(entry_point, 3);
  }
  
+ void MacroAssembler::super_call_VM_leaf(address entry_point) {
+   MacroAssembler::call_VM_leaf_base(entry_point, 1);
+ }
+ 
  void MacroAssembler::super_call_VM_leaf(address entry_point, Register arg_0) {
    pass_arg0(this, arg_0);
    MacroAssembler::call_VM_leaf_base(entry_point, 1);
  }
  

@@ -3593,10 +3599,50 @@
    }
    RelocationHolder rspec = metadata_Relocation::spec(oop_index);
    movptr(dst, Address((address)obj, rspec));
  }
  
+ void MacroAssembler::inline_layout_info(Register holder_klass, Register index, Register layout_info) {
+   assert_different_registers(holder_klass, index, layout_info);
+   InlineLayoutInfo array[2];
+   int size = (char*)&array[1] - (char*)&array[0]; // computing size of array elements
+   if (is_power_of_2(size)) {
+     slli(index, index, log2i_exact(size)); // Scale index by power of 2
+   } else {
+     mv(layout_info, size);
+     mul(index, index, layout_info); // Scale the index to be the entry index * array_element_size
+   }
+   ld(layout_info, Address(holder_klass, InstanceKlass::inline_layout_info_array_offset()));
+   add(layout_info, layout_info, Array<InlineLayoutInfo>::base_offset_in_bytes());
+   add(layout_info, layout_info, index);
+   la(layout_info, Address(layout_info));
+ }
+ 
+ void MacroAssembler::flat_field_copy(DecoratorSet decorators, Register src, Register dst,
+                                      Register inline_layout_info) {
+   BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
+   bs->flat_field_copy(this, decorators, src, dst, inline_layout_info);
+ }
+ 
+ void MacroAssembler::payload_offset(Register inline_klass, Register offset) {
+   ld(offset, Address(inline_klass, InlineKlass::adr_members_offset()));
+   lwu(offset, Address(offset, InlineKlass::payload_offset_offset()));
+ }
+ 
+ void MacroAssembler::payload_address(Register oop, Register data, Register inline_klass) {
+   assert_different_registers(data, t0);
+   // ((address) (void*) o) + vk->payload_offset();
+   Register offset = (data == oop) ? t0 : data;
+   payload_offset(inline_klass, offset);
+   if (data == oop) {
+     add(data, data, offset);
+   } else {
+     add(data, oop, offset);
+     la(data, Address(data));
+   }
+ }
+ 
  // Writes to stack successive pages until offset reached to check for
  // stack overflow + shadow pages.  This clobbers tmp.
  void MacroAssembler::bang_stack_size(Register size, Register tmp) {
    assert_different_registers(tmp, size, t0);
    // Bang stack for total size given plus shadow page size.

@@ -3678,10 +3724,86 @@
      // nothing to do, (later) access of M[reg + offset]
      // will provoke OS null exception if reg is null
    }
  }
  
+ void MacroAssembler::test_field_is_null_free_inline_type(Register flags, Register temp_reg, Label& is_null_free_inline_type) {
+   test_bit(temp_reg, flags, ResolvedFieldEntry::is_null_free_inline_type_shift);
+   bnez(temp_reg, is_null_free_inline_type);
+ }
+ 
+ void MacroAssembler::test_field_is_not_null_free_inline_type(Register flags, Register temp_reg, Label& not_null_free_inline_type) {
+   test_bit(temp_reg, flags, ResolvedFieldEntry::is_null_free_inline_type_shift);
+   beqz(temp_reg, not_null_free_inline_type);
+ }
+ 
+ void MacroAssembler::test_field_is_flat(Register flags, Register temp_reg, Label& is_flat) {
+   test_bit(temp_reg, flags, ResolvedFieldEntry::is_flat_shift);
+   bnez(temp_reg, is_flat);
+ }
+ 
+ void MacroAssembler::test_markword_is_inline_type(Register markword, Label& is_inline_type) {
+   assert_different_registers(markword, t1);
+   mv(t1, markWord::inline_type_pattern_mask);
+   andr(markword, markword, t1);
+   mv(t1, markWord::inline_type_pattern);
+   beq(markword, t1, is_inline_type);
+ }
+ 
+ void MacroAssembler::test_oop_is_not_inline_type(Register object, Register tmp, Label& not_inline_type, bool can_be_null) {
+   assert_different_registers(tmp, t0);
+   if (can_be_null) {
+     beqz(object, not_inline_type);
+   }
+   const int is_inline_type_mask = markWord::inline_type_pattern;
+   ld(tmp, Address(object, oopDesc::mark_offset_in_bytes()));
+   mv(t0, is_inline_type_mask);
+   andr(tmp, tmp, t0);
+   bne(tmp, t0, not_inline_type);
+ }
+ 
+ void MacroAssembler::test_oop_prototype_bit(Register oop, Register temp_reg, int32_t tst_bit, bool jmp_set, Label& jmp_label) {
+   assert_different_registers(temp_reg, t0);
+   Label test_mark_word;
+   // load mark word
+   ld(temp_reg, Address(oop, oopDesc::mark_offset_in_bytes()));
+   // check displaced
+   test_bit(t0, temp_reg, exact_log2(markWord::unlocked_value));
+   bnez(t0, test_mark_word);
+   // slow path use klass prototype
+   load_prototype_header(temp_reg, oop);
+ 
+   bind(test_mark_word);
+   andi(temp_reg, temp_reg, tst_bit);
+   if (jmp_set) {
+     bnez(temp_reg, jmp_label, /* is_far */ true);
+   } else {
+     beqz(temp_reg, jmp_label, /* is_far */ true);
+   }
+ }
+ 
+ void MacroAssembler::test_flat_array_oop(Register oop, Register temp_reg, Label& is_flat_array) {
+   test_oop_prototype_bit(oop, temp_reg, markWord::flat_array_bit_in_place, true, is_flat_array);
+ }
+ 
+ void MacroAssembler::test_null_free_array_oop(Register oop, Register temp_reg, Label& is_null_free_array) {
+   test_oop_prototype_bit(oop, temp_reg, markWord::null_free_array_bit_in_place, true, is_null_free_array);
+ }
+ 
+ void MacroAssembler::test_non_flat_array_oop(Register oop, Register temp_reg, Label&is_non_flat_array) {
+   test_oop_prototype_bit(oop, temp_reg, markWord::flat_array_bit_in_place, false, is_non_flat_array);
+ }
+ 
+ void MacroAssembler::test_non_null_free_array_oop(Register oop, Register temp_reg, Label&is_non_null_free_array) {
+   test_oop_prototype_bit(oop, temp_reg, markWord::null_free_array_bit_in_place, false, is_non_null_free_array);
+ }
+ 
+ void MacroAssembler::test_flat_array_layout(Register lh, Label& is_flat_array) {
+   test_bit(t0, lh, exact_log2(Klass::_lh_array_tag_flat_value_bit_inplace));
+   bnez(t0, is_flat_array);
+ }
+ 
  void MacroAssembler::access_store_at(BasicType type, DecoratorSet decorators,
                                       Address dst, Register val,
                                       Register tmp1, Register tmp2, Register tmp3) {
    BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler();
    decorators = AccessInternal::decorator_fixup(decorators, type);

@@ -3777,10 +3899,15 @@
      lwu(dst, Address(src, oopDesc::klass_offset_in_bytes()));
      decode_klass_not_null(dst, tmp);
    }
  }
  
+ void MacroAssembler::load_prototype_header(Register dst, Register src, Register tmp) {
+   load_klass(dst, src, tmp);
+   ld(dst, Address(dst, Klass::prototype_header_offset()));
+ }
+ 
  void MacroAssembler::store_klass(Register dst, Register src, Register tmp) {
    // FIXME: Should this be a store release? concurrent gcs assumes
    // klass length is valid if klass field is not null.
    assert(!UseCompactObjectHeaders, "not with compact headers");
    encode_klass_not_null(src, tmp);

@@ -5241,10 +5368,12 @@
    pop_reg(saved_regs, sp);
  }
  
  void MacroAssembler::load_byte_map_base(Register reg) {
    CardTableBarrierSet* ctbs = CardTableBarrierSet::barrier_set();
+   // Strictly speaking the card table base isn't an address at all, and it might
+   // even be negative. It is thus materialised as a constant.
    mv(reg, (uint64_t)ctbs->card_table_base_const());
  }
  
  void MacroAssembler::build_frame(int framesize) {
    assert(framesize >= 2, "framesize must include space for FP/RA");

@@ -5261,10 +5390,78 @@
    ld(fp, Address(sp, framesize - 2 * wordSize));
    ld(ra, Address(sp, framesize - wordSize));
    add(sp, sp, framesize);
  }
  
+ void MacroAssembler::remove_frame(int initial_framesize, bool needs_stack_repair) {
+   assert(!needs_stack_repair, "unimplemented");
+   remove_frame(initial_framesize);
+ }
+ 
+ #ifdef COMPILER2
+ // C2 compiled method's prolog code
+ // Moved here from riscv.ad to support Valhalla code belows
+ void MacroAssembler::verified_entry(Compile* C, int sp_inc) {
+   if (C->clinit_barrier_on_entry()) {
+     assert(!C->method()->holder()->is_not_initialized(), "initialization should have been started");
+ 
+     Label L_skip_barrier;
+ 
+     mov_metadata(t1, C->method()->holder()->constant_encoding());
+     clinit_barrier(t1, t0, &L_skip_barrier);
+     far_jump(RuntimeAddress(SharedRuntime::get_handle_wrong_method_stub()));
+     bind(L_skip_barrier);
+   }
+ 
+   int bangsize = C->output()->bang_size_in_bytes();
+   if (C->output()->need_stack_bang(bangsize)) {
+     generate_stack_overflow_check(bangsize);
+   }
+ 
+   // n.b. frame size includes space for return pc and fp
+   const long framesize = C->output()->frame_size_in_bytes();
+   build_frame(framesize);
+ 
+   assert(!C->needs_stack_repair(), "unimplemented");
+ }
+ #endif // COMPILER2
+ 
+ // Move a value between registers/stack slots and update the reg_state
+ bool MacroAssembler::move_helper(VMReg from, VMReg to, BasicType bt, RegState reg_state[]) {
+   Unimplemented();
+   return false;
+ }
+ 
+ // Read all fields from an inline type oop and store the values in registers/stack slots
+ bool MacroAssembler::unpack_inline_helper(const GrowableArray<SigEntry>* sig, int& sig_index,
+                                           VMReg from, int& from_index, VMRegPair* to, int to_count, int& to_index,
+                                           RegState reg_state[]) {
+ 
+   Unimplemented();
+   return false;
+ }
+ 
+ // Pack fields back into an inline type oop
+ bool MacroAssembler::pack_inline_helper(const GrowableArray<SigEntry>* sig, int& sig_index, int vtarg_index,
+                                         VMRegPair* from, int from_count, int& from_index, VMReg to,
+                                         RegState reg_state[], Register val_array) {
+   Unimplemented();
+   return false;
+ }
+ 
+ // Calculate the extra stack space required for packing or unpacking inline
+ // args and adjust the stack pointer
+ int MacroAssembler::extend_stack_for_inline_args(int args_on_stack) {
+   Unimplemented();
+   return false;
+ }
+ 
+ VMReg MacroAssembler::spill_reg_for(VMReg reg) {
+   Unimplemented();
+   return reg;
+ }
+ 
  void MacroAssembler::reserved_stack_check() {
    // testing if reserved zone needs to be enabled
    Label no_reserved_zone_enabling;
  
    ld(t0, Address(xthread, JavaThread::reserved_stack_activation_offset()));

@@ -5526,10 +5723,18 @@
    ld(holder, Address(method, Method::const_offset()));                      // ConstMethod*
    ld(holder, Address(holder, ConstMethod::constants_offset()));             // ConstantPool*
    ld(holder, Address(holder, ConstantPool::pool_holder_offset()));          // InstanceKlass*
  }
  
+ void MacroAssembler::load_metadata(Register dst, Register src) {
+   if (UseCompactObjectHeaders) {
+     load_narrow_klass_compact(dst, src);
+   } else {
+     lwu(dst, Address(src, oopDesc::klass_offset_in_bytes()));
+   }
+ }
+ 
  // string indexof
  // compute index by trailing zeros
  void MacroAssembler::compute_index(Register haystack, Register trailing_zeros,
                                     Register match_mask, Register result,
                                     Register ch2, Register tmp,

@@ -6852,10 +7057,12 @@
    bnez(t, slow, /* is_far */ true);
  
    // Try to lock. Transition lock-bits 0b01 => 0b00
    assert(oopDesc::mark_offset_in_bytes() == 0, "required to avoid a la");
    ori(mark, mark, markWord::unlocked_value);
+   // Mask inline_type bit such that we go to the slow path if object is an inline type
+   andi(mark, mark, ~((int) markWord::inline_type_bit_in_place));
    xori(t, mark, markWord::unlocked_value);
    cmpxchg(/*addr*/ obj, /*expected*/ mark, /*new*/ t, Assembler::int64,
            /*acquire*/ Assembler::aq, /*release*/ Assembler::relaxed, /*result*/ t);
    bne(mark, t, slow, /* is_far */ true);
  
< prev index next >