< prev index next >

src/hotspot/cpu/riscv/riscv.ad

Print this page
@@ -1226,10 +1226,13 @@
    //   sd(t0, Address(xthread, JavaThread::last_Java_pc_offset())) ->  sd
    //   movptr(t1, addr, offset, t0)                                ->  lui + lui + slli + add
    //   jalr(t1, offset)                                            ->  jalr
    if (CodeCache::contains(_entry_point)) {
      return 2 * NativeInstruction::instruction_size;
+   } else if (_entry_point == nullptr) {
+     // See CallLeafNoFPIndirect
+     return 1 * NativeInstruction::instruction_size;
    } else {
      return 8 * NativeInstruction::instruction_size;
    }
  }
  

@@ -1273,10 +1276,15 @@
  int CallLeafDirectVectorNode::compute_padding(int current_offset) const
  {
    return align_up(current_offset, alignment_required()) - current_offset;
  }
  
+ int CallLeafNoFPIndirectNode::compute_padding(int current_offset) const
+ {
+   return align_up(current_offset, alignment_required()) - current_offset;
+ }
+ 
  int CallLeafNoFPDirectNode::compute_padding(int current_offset) const
  {
    return align_up(current_offset, alignment_required()) - current_offset;
  }
  

@@ -1379,57 +1387,25 @@
  
  void MachPrologNode::emit(C2_MacroAssembler *masm, PhaseRegAlloc *ra_) const {
    assert_cond(ra_ != nullptr);
    Compile* C = ra_->C;
  
-   // n.b. frame size includes space for return pc and fp
-   const int framesize = C->output()->frame_size_in_bytes();
- 
-   assert_cond(C != nullptr);
- 
-   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);
-   }
- 
-   __ build_frame(framesize);
+   __ verified_entry(C, 0);
  
    if (VerifyStackAtCalls) {
+     // n.b. frame size includes space for return pc and fp
+     const long framesize = C->output()->frame_size_in_bytes();
      __ mv(t2, MAJIK_DWORD);
      __ sd(t2, Address(sp, framesize - 3 * wordSize));
    }
  
    if (C->stub_function() == nullptr) {
-     BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
-     // Dummy labels for just measuring the code size
-     Label dummy_slow_path;
-     Label dummy_continuation;
-     Label dummy_guard;
-     Label* slow_path = &dummy_slow_path;
-     Label* continuation = &dummy_continuation;
-     Label* guard = &dummy_guard;
-     if (!Compile::current()->output()->in_scratch_emit_size()) {
-       // Use real labels from actual stub when not emitting code for purpose of measuring its size
-       C2EntryBarrierStub* stub = new (Compile::current()->comp_arena()) C2EntryBarrierStub();
-       Compile::current()->output()->add_stub(stub);
-       slow_path = &stub->entry();
-       continuation = &stub->continuation();
-       guard = &stub->guard();
-     }
-     // In the C2 code, we move the non-hot part of nmethod entry barriers out-of-line to a stub.
-     bs->nmethod_entry_barrier(masm, slow_path, continuation, guard);
+     __ entry_barrier();
+   }
+ 
+   if (!Compile::current()->output()->in_scratch_emit_size()) {
+     __ bind(*_verified_entry);
    }
  
    C->output()->set_frame_complete(__ offset());
  
    if (C->has_mach_constant_base_node()) {

@@ -1438,17 +1414,10 @@
      ConstantTable& constant_table = C->output()->constant_table();
      constant_table.set_table_base_offset(constant_table.calculate_table_base_offset());
    }
  }
  
- uint MachPrologNode::size(PhaseRegAlloc* ra_) const
- {
-   assert_cond(ra_ != nullptr);
-   return MachNode::size(ra_); // too many variables; just compute it
-                               // the hard way
- }
- 
  int MachPrologNode::reloc() const
  {
    return 0;
  }
  

@@ -1504,16 +1473,10 @@
      __ relocate(relocInfo::poll_return_type);
      __ safepoint_poll(*code_stub, true /* at_return */, true /* in_nmethod */);
    }
  }
  
- uint MachEpilogNode::size(PhaseRegAlloc *ra_) const {
-   assert_cond(ra_ != nullptr);
-   // Variable size. Determine dynamically.
-   return MachNode::size(ra_);
- }
- 
  int MachEpilogNode::reloc() const {
    // Return number of relocatable values contained in this instruction.
    return 1; // 1 for polling page.
  }
  const Pipeline * MachEpilogNode::pipeline() const {

@@ -1788,10 +1751,24 @@
    }
  }
  
  //=============================================================================
  
+ #ifndef PRODUCT
+ void MachVEPNode::format(PhaseRegAlloc* ra_, outputStream* st) const
+ {
+   Unimplemented();
+ }
+ #endif
+ 
+ void MachVEPNode::emit(C2_MacroAssembler *masm, PhaseRegAlloc* ra_) const
+ {
+   Unimplemented();
+ }
+ 
+ //=============================================================================
+ 
  #ifndef PRODUCT
  void MachUEPNode::format(PhaseRegAlloc* ra_, outputStream* st) const
  {
    assert_cond(st != nullptr);
    st->print_cr("# MachUEPNode");

@@ -1810,16 +1787,10 @@
  
    // ic_check() aligns to CodeEntryAlignment >= InteriorEntryAlignment(min 16) > NativeInstruction::instruction_size(4).
    assert(((__ offset()) % CodeEntryAlignment) == 0, "Misaligned verified entry point");
  }
  
- uint MachUEPNode::size(PhaseRegAlloc* ra_) const
- {
-   assert_cond(ra_ != nullptr);
-   return MachNode::size(ra_);
- }
- 
  // REQUIRED EMIT CODE
  
  //=============================================================================
  
  // Emit deopt handler code.

@@ -2680,10 +2651,20 @@
    op_cost(0);
    format %{ %}
    interface(CONST_INTER);
  %}
  
+ operand immI_4()
+ %{
+   predicate(n->get_int() == 4);
+   match(ConI);
+ 
+   op_cost(0);
+   format %{ %}
+   interface(CONST_INTER);
+ %}
+ 
  operand immI_16()
  %{
    predicate(n->get_int() == 16);
    match(ConI);
    op_cost(0);

@@ -8343,10 +8324,38 @@
  %}
  
  // ============================================================================
  // Cast Instructions (Java-level type cast)
  
+ instruct castI2N(iRegNNoSp dst, iRegI src) %{
+   match(Set dst (CastI2N src));
+ 
+   ins_cost(ALU_COST);
+   format %{ "zext $dst, $src, 32\t# int -> narrow ptr" %}
+ 
+   ins_encode %{
+     __ zext(as_Register($dst$$reg), as_Register($src$$reg), 32);
+   %}
+ 
+   ins_pipe(ialu_reg);
+ %}
+ 
+ instruct castN2X(iRegLNoSp dst, iRegN src) %{
+   match(Set dst (CastP2X src));
+ 
+   ins_cost(ALU_COST);
+   format %{ "mv $dst, $src\t# ptr -> long" %}
+ 
+   ins_encode %{
+     if ($dst$$reg != $src$$reg) {
+       __ mv(as_Register($dst$$reg), as_Register($src$$reg));
+     }
+   %}
+ 
+   ins_pipe(ialu_reg);
+ %}
+ 
  instruct castX2P(iRegPNoSp dst, iRegL src) %{
    match(Set dst (CastX2P src));
  
    ins_cost(ALU_COST);
    format %{ "mv  $dst, $src\t# long -> ptr, #@castX2P" %}

@@ -10880,12 +10889,35 @@
    ins_alignment(4);
  %}
  
  // Call Runtime Instruction
  
+ // entry point is null, target holds the address to call
+ instruct CallLeafNoFPIndirect(iRegP target)
+ %{
+   predicate(n->as_Call()->entry_point() == nullptr);
+ 
+   match(CallLeafNoFP target);
+ 
+   ins_cost(BRANCH_COST);
+ 
+   format %{ "CALL, runtime leaf nofp indirect $target" %}
+ 
+   ins_encode %{
+     Assembler::IncompressibleScope scope(masm); // Fixed length: see ret_addr_offset
+     __ jalr($target$$Register);
+     __ post_call_nop();
+   %}
+ 
+   ins_pipe(pipe_class_call);
+   ins_alignment(4);
+ %}
+ 
  instruct CallLeafNoFPDirect(method meth)
  %{
+   predicate(n->as_Call()->entry_point() != nullptr);
+ 
    match(CallLeafNoFP);
  
    effect(USE meth);
  
    ins_cost(BRANCH_COST);

@@ -11211,21 +11243,24 @@
                             $tmp3$$Register, $tmp4$$Register, true /* isL */);
    %}
    ins_pipe(pipe_class_memory);
  %}
  
+ // ============================================================================
  // clearing of an array
- instruct clearArray_reg_reg(iRegL_R29 cnt, iRegP_R28 base, iRegP_R30 tmp1,
-                             iRegP_R31 tmp2, rFlagsReg cr, Universe dummy)
+ 
+ instruct clearArray_reg_reg_immL0(iRegL_R29 cnt, iRegP_R28 base, immL0 zero,
+                                   iRegP_R30 tmp1, iRegP_R31 tmp2, rFlagsReg cr,
+                                   Universe dummy)
  %{
    // temp registers must match the one used in StubGenerator::generate_zero_blocks()
    predicate(UseBlockZeroing || !UseRVV);
-   match(Set dummy (ClearArray cnt base));
+   match(Set dummy (ClearArray (Binary cnt base) zero));
    effect(USE_KILL cnt, USE_KILL base, TEMP tmp1, TEMP tmp2, KILL cr);
  
    ins_cost(4 * DEFAULT_COST);
-   format %{ "ClearArray $cnt, $base\t#@clearArray_reg_reg" %}
+   format %{ "ClearArray $cnt, $base\t#@clearArray_reg_reg_immL0" %}
  
    ins_encode %{
      address tpc = __ zero_words($base$$Register, $cnt$$Register);
      if (tpc == nullptr) {
        ciEnv::current()->record_failure("CodeCache is full");

@@ -11234,15 +11269,36 @@
    %}
  
    ins_pipe(pipe_class_memory);
  %}
  
- instruct clearArray_imm_reg(immL cnt, iRegP_R28 base, Universe dummy, rFlagsReg cr)
+ instruct clearArray_reg_reg(iRegL_R29 cnt, iRegP_R28 base, iRegL val,
+                             iRegP_R30 tmp1, iRegP_R31 tmp2, rFlagsReg cr,
+                             Universe dummy)
+ %{
+   // temp registers must match the one used in StubGenerator::generate_zero_blocks()
+   predicate(((ClearArrayNode*)n)->word_copy_only());
+   match(Set dummy (ClearArray (Binary cnt base) val));
+   effect(USE_KILL cnt, USE_KILL base, TEMP tmp1, TEMP tmp2, KILL cr);
+ 
+   ins_cost(4 * DEFAULT_COST);
+   format %{ "ClearArray $cnt, $base, $val\t#@clearArray_reg_reg" %}
+ 
+   ins_encode %{
+     __ fill_words($base$$Register, $cnt$$Register, $val$$Register);
+   %}
+ 
+   ins_pipe(pipe_class_memory);
+ %}
+ 
+ instruct clearArray_imm_reg(immL cnt, iRegP_R28 base, immL0 zero, Universe dummy, rFlagsReg cr)
  %{
-   predicate(!UseRVV && (uint64_t)n->in(2)->get_long()
-             < (uint64_t)(BlockZeroingLowLimit >> LogBytesPerWord));
-   match(Set dummy (ClearArray cnt base));
+   predicate(!UseRVV
+             && (uint64_t)n->in(2)->in(1)->get_long()
+                < (uint64_t)(BlockZeroingLowLimit >> LogBytesPerWord)
+             && !((ClearArrayNode*)n)->word_copy_only());
+   match(Set dummy (ClearArray (Binary cnt base) zero));
    effect(USE_KILL base, KILL cr);
  
    ins_cost(4 * DEFAULT_COST);
    format %{ "ClearArray $cnt, $base\t#@clearArray_imm_reg" %}
  
< prev index next >