< prev index next >

src/hotspot/cpu/riscv/interp_masm_riscv.cpp

Print this page
@@ -30,13 +30,15 @@
  #include "interp_masm_riscv.hpp"
  #include "interpreter/interpreter.hpp"
  #include "interpreter/interpreterRuntime.hpp"
  #include "logging/log.hpp"
  #include "oops/arrayOop.hpp"
+ #include "oops/constMethodFlags.hpp"
  #include "oops/markWord.hpp"
  #include "oops/method.hpp"
  #include "oops/methodData.hpp"
+ #include "oops/inlineKlass.hpp"
  #include "oops/resolvedFieldEntry.hpp"
  #include "oops/resolvedIndyEntry.hpp"
  #include "oops/resolvedMethodEntry.hpp"
  #include "prims/jvmtiExport.hpp"
  #include "prims/jvmtiThreadState.hpp"

@@ -237,16 +239,19 @@
  //      Rsub_klass: subklass
  //
  // Kills:
  //      x12
  void InterpreterMacroAssembler::gen_subtype_check(Register Rsub_klass,
-                                                   Label& ok_is_subtype) {
+                                                   Label& ok_is_subtype,
+                                                   bool profile) {
    assert(Rsub_klass != x10, "x10 holds superklass");
    assert(Rsub_klass != x12, "x12 holds 2ndary super array length");
  
    // Profile the not-null value's klass.
-   profile_typecheck(x12, Rsub_klass); // blows x12
+   if (profile) {
+     profile_typecheck(x12, Rsub_klass); // blows x12
+   }
  
    // Do the check.
    check_klass_subtype(Rsub_klass, x10, x12, ok_is_subtype); // blows x12
  }
  

@@ -985,11 +990,11 @@
      update_mdp_by_offset(mdp, in_bytes(JumpData::displacement_offset()));
      bind(profile_continue);
    }
  }
  
- void InterpreterMacroAssembler::profile_not_taken_branch(Register mdp) {
+ void InterpreterMacroAssembler::profile_not_taken_branch(Register mdp, bool acmp) {
    if (ProfileInterpreter) {
      Label profile_continue;
  
      // If no method data exists, go to profile_continue.
      test_method_data_pointer(mdp, profile_continue);

@@ -997,11 +1002,11 @@
      // We are not taking a branch.  Increment the not taken count.
      increment_mdp_data_at(mdp, in_bytes(BranchData::not_taken_offset()));
  
      // The method data pointer needs to be updated to correspond to
      // the next bytecode
-     update_mdp_by_constant(mdp, in_bytes(BranchData::branch_data_size()));
+     update_mdp_by_constant(mdp, acmp ? in_bytes(ACmpData::acmp_data_size()) : in_bytes(BranchData::branch_data_size()));
      bind(profile_continue);
    }
  }
  
  void InterpreterMacroAssembler::profile_call(Register mdp) {

@@ -1184,10 +1189,124 @@
  
      bind(profile_continue);
    }
  }
  
+ template <class ArrayData> void InterpreterMacroAssembler::profile_array_type(Register mdp,
+                                                                               Register array,
+                                                                               Register tmp) {
+   if (ProfileInterpreter) {
+     Label profile_continue;
+ 
+     // If no method data exists, go to profile_continue.
+     test_method_data_pointer(mdp, profile_continue);
+ 
+     mv(tmp, array);
+     profile_obj_type(tmp, Address(mdp, in_bytes(ArrayData::array_offset())), t1);
+ 
+     Label not_flat;
+     test_non_flat_array_oop(array, tmp, not_flat);
+ 
+     set_mdp_flag_at(mdp, ArrayData::flat_array_byte_constant());
+ 
+     bind(not_flat);
+ 
+     Label not_null_free;
+     test_non_null_free_array_oop(array, tmp, not_null_free);
+ 
+     set_mdp_flag_at(mdp, ArrayData::null_free_array_byte_constant());
+ 
+     bind(not_null_free);
+ 
+     bind(profile_continue);
+   }
+ }
+ 
+ template void InterpreterMacroAssembler::profile_array_type<ArrayLoadData>(Register mdp,
+                                                                            Register array,
+                                                                            Register tmp);
+ template void InterpreterMacroAssembler::profile_array_type<ArrayStoreData>(Register mdp,
+                                                                             Register array,
+                                                                             Register tmp);
+ 
+ void InterpreterMacroAssembler::profile_multiple_element_types(Register mdp, Register element, Register tmp, const Register tmp2) {
+   if (ProfileInterpreter) {
+     Label profile_continue;
+ 
+     // If no method data exists, go to profile_continue.
+     test_method_data_pointer(mdp, profile_continue);
+ 
+     Label done, update;
+     bnez(element, update);
+     set_mdp_flag_at(mdp, BitData::null_seen_byte_constant());
+     j(done);
+ 
+     bind(update);
+     load_klass(tmp, element);
+ 
+     // Record the object type.
+     profile_receiver_type(tmp, mdp, 0);
+ 
+     bind(done);
+ 
+     // The method data pointer needs to be updated.
+     update_mdp_by_constant(mdp, in_bytes(ArrayStoreData::array_store_data_size()));
+ 
+     bind(profile_continue);
+   }
+ }
+ 
+ void InterpreterMacroAssembler::profile_element_type(Register mdp,
+                                                      Register element,
+                                                      Register tmp) {
+   if (ProfileInterpreter) {
+     Label profile_continue;
+ 
+     // If no method data exists, go to profile_continue.
+     test_method_data_pointer(mdp, profile_continue);
+ 
+     mv(tmp, element);
+     profile_obj_type(tmp, Address(mdp, in_bytes(ArrayLoadData::element_offset())), t1);
+ 
+     // The method data pointer needs to be updated.
+     update_mdp_by_constant(mdp, in_bytes(ArrayLoadData::array_load_data_size()));
+ 
+     bind(profile_continue);
+   }
+ }
+ 
+ void InterpreterMacroAssembler::profile_acmp(Register mdp,
+                                              Register left,
+                                              Register right,
+                                              Register tmp) {
+   if (ProfileInterpreter) {
+     Label profile_continue;
+ 
+     // If no method data exists, go to profile_continue.
+     test_method_data_pointer(mdp, profile_continue);
+ 
+     mv(tmp, left);
+     profile_obj_type(tmp, Address(mdp, in_bytes(ACmpData::left_offset())), t1);
+ 
+     Label left_not_inline_type;
+     test_oop_is_not_inline_type(left, tmp, left_not_inline_type);
+     set_mdp_flag_at(mdp, ACmpData::left_inline_type_byte_constant());
+     bind(left_not_inline_type);
+ 
+     mv(tmp, right);
+     profile_obj_type(tmp, Address(mdp, in_bytes(ACmpData::right_offset())), t1);
+ 
+     Label right_not_inline_type;
+     test_oop_is_not_inline_type(right, tmp, right_not_inline_type);
+     set_mdp_flag_at(mdp, ACmpData::right_inline_type_byte_constant());
+     bind(right_not_inline_type);
+ 
+     bind(profile_continue);
+   }
+ }
+ 
+ 
  void InterpreterMacroAssembler::notify_method_entry() {
    // Whenever JVMTI is interp_only_mode, method entry/exit events are sent to
    // track stack depth.  If it is possible to enter interp_only_mode we add
    // the code to check if the event should be sent.
    if (JvmtiExport::can_post_interpreter_events()) {

@@ -1598,11 +1717,11 @@
        if (MethodData::profile_return()) {
          // We're right after the type profile for the last
          // argument. tmp is the number of cells left in the
          // CallTypeData/VirtualCallTypeData to reach its end. Non null
          // if there's a return to profile.
-         assert(ReturnTypeEntry::static_cell_count() < TypeStackSlotEntries::per_arg_count(), "can't move past ret type");
+         assert(SingleTypeEntry::static_cell_count() < TypeStackSlotEntries::per_arg_count(), "can't move past ret type");
          shadd(mdp, tmp, mdp, tmp, exact_log2(DataLayout::cell_size));
        }
        sd(mdp, Address(fp, frame::interpreter_frame_mdp_offset * wordSize));
      } else {
        assert(MethodData::profile_return(), "either profile call args or call ret");

@@ -1643,11 +1762,11 @@
        mv(t1, static_cast<int>(vmIntrinsics::_compiledLambdaForm));
        bne(t0, t1, profile_continue);
        bind(do_profile);
      }
  
-     Address mdo_ret_addr(mdp, -in_bytes(ReturnTypeEntry::size()));
+     Address mdo_ret_addr(mdp, -in_bytes(SingleTypeEntry::size()));
      mv(tmp, ret);
      profile_obj_type(tmp, mdo_ret_addr, t1);
  
      bind(profile_continue);
    }

@@ -1745,10 +1864,44 @@
    ld(mcs, Address(method, Method::method_counters_offset()));
    beqz(mcs, skip); // No MethodCounters allocated, OutOfMemory
    bind(has_counters);
  }
  
+ void InterpreterMacroAssembler::read_flat_field(Register entry, Register obj) {
+   call_VM(obj, CAST_FROM_FN_PTR(address, InterpreterRuntime::read_flat_field), obj, entry);
+   membar(MacroAssembler::StoreStore);
+ }
+ 
+ void InterpreterMacroAssembler::write_flat_field(Register entry, Register field_offset,
+                                                  Register tmp1, Register tmp2,
+                                                  Register obj) {
+   assert_different_registers(entry, field_offset, tmp1, tmp2, obj);
+   Label slow_path, done;
+ 
+   load_unsigned_byte(tmp1, Address(entry, in_bytes(ResolvedFieldEntry::flags_offset())));
+   test_field_is_not_null_free_inline_type(tmp1, tmp2, slow_path);
+ 
+   null_check(x10); // FIXME JDK-8341120
+ 
+   add(obj, obj, field_offset);
+ 
+   load_klass(tmp1, x10);
+   payload_address(x10, x10, tmp1);
+ 
+   Register layout_info = field_offset;
+   load_unsigned_short(tmp1, Address(entry, in_bytes(ResolvedFieldEntry::field_index_offset())));
+   ld(tmp2, Address(entry, in_bytes(ResolvedFieldEntry::field_holder_offset())));
+   inline_layout_info(tmp2, tmp1, layout_info);
+ 
+   flat_field_copy(IN_HEAP, x10, obj, layout_info);
+   j(done);
+ 
+   bind(slow_path);
+   call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::write_flat_field), obj, x10, entry);
+   bind(done);
+ }
+ 
  void InterpreterMacroAssembler::load_method_entry(Register cache, Register index, int bcp_offset) {
    // Get index out of bytecode pointer
    get_cache_index_at_bcp(index, cache, bcp_offset, sizeof(u2));
    mv(cache, sizeof(ResolvedMethodEntry));
    mul(index, index, cache); // Scale the index to be the entry index * sizeof(ResolvedMethodEntry)
< prev index next >