1.1 --- a/src/cpu/x86/vm/interp_masm_x86_64.cpp Fri Oct 11 19:51:31 2013 -0700 1.2 +++ b/src/cpu/x86/vm/interp_masm_x86_64.cpp Sat Oct 12 12:12:59 2013 +0200 1.3 @@ -1120,7 +1120,7 @@ 1.4 return; 1.5 } 1.6 1.7 - if (MethodData::profile_arguments()) { 1.8 + if (MethodData::profile_arguments() || MethodData::profile_return()) { 1.9 Label profile_continue; 1.10 1.11 test_method_data_pointer(mdp, profile_continue); 1.12 @@ -1130,35 +1130,92 @@ 1.13 cmpb(Address(mdp, in_bytes(DataLayout::tag_offset()) - off_to_start), is_virtual ? DataLayout::virtual_call_type_data_tag : DataLayout::call_type_data_tag); 1.14 jcc(Assembler::notEqual, profile_continue); 1.15 1.16 - Label done; 1.17 - int off_to_args = in_bytes(TypeStackSlotEntries::args_data_offset()); 1.18 - addptr(mdp, off_to_args); 1.19 + if (MethodData::profile_arguments()) { 1.20 + Label done; 1.21 + int off_to_args = in_bytes(TypeEntriesAtCall::args_data_offset()); 1.22 + addptr(mdp, off_to_args); 1.23 1.24 - for (int i = 0; i < TypeProfileArgsLimit; i++) { 1.25 - if (i > 0) { 1.26 - movq(tmp, Address(mdp, in_bytes(TypeStackSlotEntries::cell_count_offset())-off_to_args)); 1.27 - subl(tmp, i*TypeStackSlotEntries::per_arg_count()); 1.28 - cmpl(tmp, TypeStackSlotEntries::per_arg_count()); 1.29 - jcc(Assembler::less, done); 1.30 + for (int i = 0; i < TypeProfileArgsLimit; i++) { 1.31 + if (i > 0 || MethodData::profile_return()) { 1.32 + // If return value type is profiled we may have no argument to profile 1.33 + movq(tmp, Address(mdp, in_bytes(TypeEntriesAtCall::cell_count_offset())-off_to_args)); 1.34 + subl(tmp, i*TypeStackSlotEntries::per_arg_count()); 1.35 + cmpl(tmp, TypeStackSlotEntries::per_arg_count()); 1.36 + jcc(Assembler::less, done); 1.37 + } 1.38 + movptr(tmp, Address(callee, Method::const_offset())); 1.39 + load_unsigned_short(tmp, Address(tmp, ConstMethod::size_of_parameters_offset())); 1.40 + subq(tmp, Address(mdp, in_bytes(TypeEntriesAtCall::stack_slot_offset(i))-off_to_args)); 1.41 + subl(tmp, 1); 1.42 + Address arg_addr = argument_address(tmp); 1.43 + movptr(tmp, arg_addr); 1.44 + 1.45 + Address mdo_arg_addr(mdp, in_bytes(TypeEntriesAtCall::argument_type_offset(i))-off_to_args); 1.46 + profile_obj_type(tmp, mdo_arg_addr); 1.47 + 1.48 + int to_add = in_bytes(TypeStackSlotEntries::per_arg_size()); 1.49 + addptr(mdp, to_add); 1.50 + off_to_args += to_add; 1.51 } 1.52 - movptr(tmp, Address(callee, Method::const_offset())); 1.53 - load_unsigned_short(tmp, Address(tmp, ConstMethod::size_of_parameters_offset())); 1.54 - subq(tmp, Address(mdp, in_bytes(TypeStackSlotEntries::stack_slot_offset(i))-off_to_args)); 1.55 - subl(tmp, 1); 1.56 - Address arg_addr = argument_address(tmp); 1.57 - movptr(tmp, arg_addr); 1.58 1.59 - Address mdo_arg_addr(mdp, in_bytes(TypeStackSlotEntries::type_offset(i))-off_to_args); 1.60 - profile_obj_type(tmp, mdo_arg_addr); 1.61 + if (MethodData::profile_return()) { 1.62 + movq(tmp, Address(mdp, in_bytes(TypeEntriesAtCall::cell_count_offset())-off_to_args)); 1.63 + subl(tmp, TypeProfileArgsLimit*TypeStackSlotEntries::per_arg_count()); 1.64 + } 1.65 1.66 - int to_add = in_bytes(TypeStackSlotEntries::per_arg_size()); 1.67 - addptr(mdp, to_add); 1.68 - off_to_args += to_add; 1.69 + bind(done); 1.70 + 1.71 + if (MethodData::profile_return()) { 1.72 + // We're right after the type profile for the last 1.73 + // argument. tmp is the number of cell left in the 1.74 + // CallTypeData/VirtualCallTypeData to reach its end. Non null 1.75 + // if there's a return to profile. 1.76 + assert(ReturnTypeEntry::static_cell_count() < TypeStackSlotEntries::per_arg_count(), "can't move past ret type"); 1.77 + shll(tmp, exact_log2(DataLayout::cell_size)); 1.78 + addptr(mdp, tmp); 1.79 + } 1.80 + movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize), mdp); 1.81 + } else { 1.82 + assert(MethodData::profile_return(), "either profile call args or call ret"); 1.83 + update_mdp_by_constant(mdp, in_bytes(ReturnTypeEntry::size())); 1.84 } 1.85 1.86 - bind(done); 1.87 + // mdp points right after the end of the 1.88 + // CallTypeData/VirtualCallTypeData, right after the cells for the 1.89 + // return value type if there's one 1.90 1.91 - movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize), mdp); 1.92 + bind(profile_continue); 1.93 + } 1.94 +} 1.95 + 1.96 +void InterpreterMacroAssembler::profile_return_type(Register mdp, Register ret, Register tmp) { 1.97 + assert_different_registers(mdp, ret, tmp, r13); 1.98 + if (ProfileInterpreter && MethodData::profile_return()) { 1.99 + Label profile_continue, done; 1.100 + 1.101 + test_method_data_pointer(mdp, profile_continue); 1.102 + 1.103 + if (MethodData::profile_return_jsr292_only()) { 1.104 + // If we don't profile all invoke bytecodes we must make sure 1.105 + // it's a bytecode we indeed profile. We can't go back to the 1.106 + // begining of the ProfileData we intend to update to check its 1.107 + // type because we're right after it and we don't known its 1.108 + // length 1.109 + Label do_profile; 1.110 + cmpb(Address(r13, 0), Bytecodes::_invokedynamic); 1.111 + jcc(Assembler::equal, do_profile); 1.112 + cmpb(Address(r13, 0), Bytecodes::_invokehandle); 1.113 + jcc(Assembler::equal, do_profile); 1.114 + get_method(tmp); 1.115 + cmpb(Address(tmp, Method::intrinsic_id_offset_in_bytes()), vmIntrinsics::_compiledLambdaForm); 1.116 + jcc(Assembler::notEqual, profile_continue); 1.117 + 1.118 + bind(do_profile); 1.119 + } 1.120 + 1.121 + Address mdo_ret_addr(mdp, -in_bytes(ReturnTypeEntry::size())); 1.122 + mov(tmp, ret); 1.123 + profile_obj_type(tmp, mdo_ret_addr); 1.124 1.125 bind(profile_continue); 1.126 }