< prev index next >

src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp

Print this page
@@ -553,13 +553,15 @@
  }
  
  // Generate a subtype check: branch to ok_is_subtype if sub_klass is
  // a subtype of super_klass. Blows registers Rsub_klass, tmp1, tmp2.
  void InterpreterMacroAssembler::gen_subtype_check(Register Rsub_klass, Register Rsuper_klass, Register Rtmp1,
-                                                   Register Rtmp2, Register Rtmp3, Label &ok_is_subtype) {
+                                                   Register Rtmp2, Register Rtmp3, Label &ok_is_subtype, bool profile) {
    // Profile the not-null value's klass.
-   profile_typecheck(Rsub_klass, Rtmp1, Rtmp2);
+   if (profile) {
+     profile_typecheck(Rsub_klass, Rtmp1, Rtmp2);
+   }
    check_klass_subtype(Rsub_klass, Rsuper_klass, Rtmp1, Rtmp2, ok_is_subtype);
  }
  
  // Separate these two to allow for delay slot in middle.
  // These are used to do a test and full jump to exception-throwing code.

@@ -919,10 +921,45 @@
      should_not_reach_here();
  
      bind(no_reserved_zone_enabling);
    }
  
+   if (state == atos && InlineTypeReturnedAsFields) {
+     Label skip, not_null;
+     cmpdi(CR0, R17_tos, 0);
+     bne(CR0, not_null);
+ 
+     untested("remove_activation InlineTypeReturnedAsFields null");
+     // Returned value is null, zero all return registers because they may belong to oop fields
+     li(R3_ARG1, 0);
+     li(R4_ARG2, 0);
+     li(R5_ARG3, 0);
+     li(R6_ARG4, 0);
+     li(R7_ARG5, 0);
+     li(R8_ARG6, 0);
+     li(R9_ARG7, 0);
+     li(R10_ARG8, 0);
+     b(skip);
+ 
+     bind(not_null);
+ 
+     // Check if we are returning an non-null inline type and load its fields into registers
+     test_oop_is_not_inline_type(R17_tos, skip, /* can_be_null= */ false);
+ 
+     // Load fields from a buffered value with an inline class specific handler
+     load_klass(R11_scratch1, R17_tos);
+     ld(R11_scratch1, InlineKlass::adr_members_offset(), R11_scratch1);
+     ld(R11_scratch1, InlineKlass::unpack_handler_offset(), R11_scratch1);
+     // Unpack handler can be null if inline type is not scalarizable in returns
+     cmpdi(CR0, R11_scratch1, 0);
+     beq(CR0, skip);
+     mtctr(R11_scratch1);
+     bctrl();
+ 
+     bind(skip);
+   }
+ 
    verify_oop(R17_tos, state);
  
    remove_top_frame_given_fp(fp, R21_sender_SP, R23_tmp3, /*return_pc*/ R0, R11_scratch1);
    mtlr(R0);
    pop_cont_fastpath();

@@ -1284,11 +1321,11 @@
      bind (profile_continue);
    }
  }
  
  // Count a not-taken branch in the bytecodes.
- void InterpreterMacroAssembler::profile_not_taken_branch(Register scratch1, Register scratch2) {
+ void InterpreterMacroAssembler::profile_not_taken_branch(Register scratch1, Register scratch2, bool acmp) {
    if (ProfileInterpreter) {
      Label profile_continue;
  
      // If no method data exists, go to profile_continue.
      test_method_data_pointer(profile_continue);

@@ -1296,11 +1333,11 @@
      // We are taking a branch. Increment the not taken count.
      increment_mdp_data_at(in_bytes(BranchData::not_taken_offset()), scratch1, scratch2);
  
      // The method data pointer needs to be updated to correspond to the
      // next bytecode.
-     update_mdp_by_constant(in_bytes(BranchData::branch_data_size()));
+     update_mdp_by_constant(acmp ? in_bytes(ACmpData::acmp_data_size()) : in_bytes(BranchData::branch_data_size()));
      bind (profile_continue);
    }
  }
  
  // Count a non-virtual call in the bytecodes.

@@ -1458,10 +1495,115 @@
  
      bind (profile_continue);
    }
  }
  
+ template <class ArrayData> void InterpreterMacroAssembler::profile_array_type(Register array,
+                                                                               Register tmp1,
+                                                                               Register tmp2) {
+   if (ProfileInterpreter) {
+     Label profile_continue;
+     assert_different_registers(array, tmp1, tmp2);
+ 
+     // If no method data exists, go to profile_continue.
+     test_method_data_pointer(profile_continue);
+ 
+     profile_obj_type(array, R28_mdx, in_bytes(ArrayData::array_offset()), tmp1, tmp2);
+ 
+     Label not_flat;
+     test_non_flat_array_oop(array, tmp1, not_flat);
+     set_mdp_flag_at(ArrayData::flat_array_byte_constant(), tmp1);
+     bind(not_flat);
+ 
+     Label not_null_free;
+     test_non_null_free_array_oop(array, tmp1, not_null_free);
+     set_mdp_flag_at(ArrayData::null_free_array_byte_constant(), tmp1);
+     bind(not_null_free);
+ 
+     bind(profile_continue);
+   }
+ }
+ 
+ template void InterpreterMacroAssembler::profile_array_type<ArrayLoadData>(Register array,
+                                                                            Register tmp1,
+                                                                            Register tmp2);
+ template void InterpreterMacroAssembler::profile_array_type<ArrayStoreData>(Register array,
+                                                                             Register tmp1,
+                                                                             Register tmp2);
+ 
+ void InterpreterMacroAssembler::profile_multiple_element_types(Register element, Register tmp1, Register tmp2, Register tmp3) {
+   if (ProfileInterpreter) {
+     Label profile_continue;
+ 
+     // If no method data exists, go to profile_continue.
+     test_method_data_pointer(profile_continue);
+ 
+     Label done, update;
+     cmpdi(CR0, element, 0);
+     bne(CR0, update);
+     set_mdp_flag_at(BitData::null_seen_byte_constant(), tmp1);
+     b(done);
+ 
+     bind(update);
+     load_klass(tmp1, element);
+ 
+     // Record the object type.
+     profile_receiver_type(tmp1, R28_mdx, 0, tmp2, tmp3);
+ 
+     bind(done);
+ 
+     // The method data pointer needs to be updated.
+     update_mdp_by_constant(in_bytes(ArrayStoreData::array_store_data_size()));
+ 
+     bind(profile_continue);
+   }
+ }
+ 
+ 
+ void InterpreterMacroAssembler::profile_element_type(Register element, Register tmp1, Register tmp2) {
+   if (ProfileInterpreter) {
+     Label profile_continue;
+ 
+     // If no method data exists, go to profile_continue.
+     test_method_data_pointer(profile_continue);
+ 
+     profile_obj_type(element, R28_mdx, in_bytes(ArrayLoadData::element_offset()), tmp1, tmp2);
+ 
+     // The method data pointer needs to be updated.
+     update_mdp_by_constant(in_bytes(ArrayLoadData::array_load_data_size()));
+ 
+     bind(profile_continue);
+   }
+ }
+ 
+ void InterpreterMacroAssembler::profile_acmp(Register left,
+                                              Register right,
+                                              Register tmp1,
+                                              Register tmp2) {
+   if (ProfileInterpreter) {
+     Label profile_continue;
+     assert_different_registers(left, right, tmp1, tmp2);
+ 
+     // If no method data exists, go to profile_continue.
+     test_method_data_pointer(profile_continue);
+ 
+     profile_obj_type(left, R28_mdx, in_bytes(ACmpData::left_offset()), tmp1, tmp2);
+ 
+     Label left_not_inline_type;
+     test_oop_is_not_inline_type(left, left_not_inline_type);
+     set_mdp_flag_at(ACmpData::left_inline_type_byte_constant(), tmp1);
+     bind(left_not_inline_type);
+ 
+     profile_obj_type(right, R28_mdx, in_bytes(ACmpData::right_offset()), tmp1, tmp2);
+ 
+     test_oop_is_not_inline_type(right, profile_continue);
+     set_mdp_flag_at(ACmpData::right_inline_type_byte_constant(), tmp1);
+ 
+     bind(profile_continue);
+   }
+ }
+ 
  void InterpreterMacroAssembler::profile_null_seen(Register Rscratch1, Register Rscratch2) {
    if (ProfileInterpreter) {
      assert_different_registers(Rscratch1, Rscratch2);
      Label profile_continue;
  

@@ -1595,11 +1737,11 @@
        if (MethodData::profile_return()) {
          // We're right after the type profile for the last
          // argument. tmp1 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(),
+         assert(SingleTypeEntry::static_cell_count() < TypeStackSlotEntries::per_arg_count(),
                 "can't move past ret type");
          sldi(tmp1, tmp1, exact_log2(DataLayout::cell_size));
          add(R28_mdx, tmp1, R28_mdx);
        }
      } else {

@@ -1636,11 +1778,11 @@
        cmpwi(CR1, tmp2, static_cast<int>(vmIntrinsics::_compiledLambdaForm));
        cror(CR0, Assembler::equal, CR1, Assembler::equal);
        bne(CR0, profile_continue);
      }
  
-     profile_obj_type(ret, R28_mdx, -in_bytes(ReturnTypeEntry::size()), tmp1, tmp2);
+     profile_obj_type(ret, R28_mdx, -in_bytes(SingleTypeEntry::size()), tmp1, tmp2);
  
      align(32, 12);
      bind(profile_continue);
    }
  }

@@ -2285,5 +2427,37 @@
      bind(jvmti_post_done);
    }
  
    // Dtrace support not implemented.
  }
+ 
+ void InterpreterMacroAssembler::read_flat_field(Register entry, Register obj) {
+   call_VM(obj, CAST_FROM_FN_PTR(address, InterpreterRuntime::read_flat_field), obj, entry);
+ }
+ 
+ void InterpreterMacroAssembler::write_flat_field(Register entry, Register tmp1, Register tmp2,
+                                                  Register obj, Register field_offset, Register value) {
+   assert_different_registers(entry, field_offset, tmp1, tmp2, obj, value);
+   Label slow_path, done;
+ 
+   lbz(tmp1, in_bytes(ResolvedFieldEntry::flags_offset()), entry);
+   test_field_is_not_null_free_inline_type(tmp1, slow_path);
+ 
+   null_check_throw(value, -1, tmp1);
+ 
+   add(obj, obj, field_offset);
+ 
+   load_klass(tmp1, value);
+   payload_address(value, value, tmp1, tmp2);
+ 
+   Register layout_info = field_offset;
+   lbz(tmp1, in_bytes(ResolvedFieldEntry::field_index_offset()), entry);
+   ld(tmp2, in_bytes(ResolvedFieldEntry::field_holder_offset()), entry);
+   inline_layout_info(tmp2, tmp1, layout_info);
+ 
+   flat_field_copy(IN_HEAP, value, obj, layout_info);
+   b(done);
+ 
+   bind(slow_path);
+   call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::write_flat_field), obj, value, entry);
+   bind(done);
+ }
< prev index next >