src/cpu/x86/vm/interp_masm_x86.cpp

Thu, 24 May 2018 17:06:56 +0800

author
aoqi
date
Thu, 24 May 2018 17:06:56 +0800
changeset 8604
04d83ba48607
parent 8368
32b682649973
parent 6876
710a3c8b516e
permissions
-rw-r--r--

Merge

aoqi@0 1 /*
kevinw@8368 2 * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
aoqi@0 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
aoqi@0 4 *
aoqi@0 5 * This code is free software; you can redistribute it and/or modify it
aoqi@0 6 * under the terms of the GNU General Public License version 2 only, as
aoqi@0 7 * published by the Free Software Foundation.
aoqi@0 8 *
aoqi@0 9 * This code is distributed in the hope that it will be useful, but WITHOUT
aoqi@0 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
aoqi@0 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
aoqi@0 12 * version 2 for more details (a copy is included in the LICENSE file that
aoqi@0 13 * accompanied this code).
aoqi@0 14 *
aoqi@0 15 * You should have received a copy of the GNU General Public License version
aoqi@0 16 * 2 along with this work; if not, write to the Free Software Foundation,
aoqi@0 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
aoqi@0 18 *
aoqi@0 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
aoqi@0 20 * or visit www.oracle.com if you need additional information or have any
aoqi@0 21 * questions.
aoqi@0 22 *
aoqi@0 23 */
aoqi@0 24
aoqi@0 25 #include "precompiled.hpp"
aoqi@0 26 #include "interp_masm_x86.hpp"
aoqi@0 27 #include "interpreter/interpreter.hpp"
aoqi@0 28 #include "oops/methodData.hpp"
aoqi@0 29
kevinw@8368 30
kevinw@8368 31 // 8u does not have InterpreterMacroAssembler::load_earlyret_value here
kevinw@8368 32
kevinw@8368 33 void InterpreterMacroAssembler::narrow(Register result) {
kevinw@8368 34
kevinw@8368 35 // Get method->_constMethod->_result_type
kevinw@8368 36 movptr(rcx, Address(rbp, frame::interpreter_frame_method_offset * wordSize));
kevinw@8368 37 movptr(rcx, Address(rcx, Method::const_offset()));
kevinw@8368 38 load_unsigned_byte(rcx, Address(rcx, ConstMethod::result_type_offset()));
kevinw@8368 39
kevinw@8368 40 Label done, notBool, notByte, notChar;
kevinw@8368 41
kevinw@8368 42 // common case first
kevinw@8368 43 cmpl(rcx, T_INT);
kevinw@8368 44 jcc(Assembler::equal, done);
kevinw@8368 45
kevinw@8368 46 // mask integer result to narrower return type.
kevinw@8368 47 cmpl(rcx, T_BOOLEAN);
kevinw@8368 48 jcc(Assembler::notEqual, notBool);
kevinw@8368 49 andl(result, 0x1);
kevinw@8368 50 jmp(done);
kevinw@8368 51
kevinw@8368 52 bind(notBool);
kevinw@8368 53 cmpl(rcx, T_BYTE);
kevinw@8368 54 jcc(Assembler::notEqual, notByte);
kevinw@8368 55 LP64_ONLY(movsbl(result, result);)
kevinw@8368 56 NOT_LP64(shll(result, 24);) // truncate upper 24 bits
kevinw@8368 57 NOT_LP64(sarl(result, 24);) // and sign-extend byte
kevinw@8368 58 jmp(done);
kevinw@8368 59
kevinw@8368 60 bind(notByte);
kevinw@8368 61 cmpl(rcx, T_CHAR);
kevinw@8368 62 jcc(Assembler::notEqual, notChar);
kevinw@8368 63 LP64_ONLY(movzwl(result, result);)
kevinw@8368 64 NOT_LP64(andl(result, 0xFFFF);) // truncate upper 16 bits
kevinw@8368 65 jmp(done);
kevinw@8368 66
kevinw@8368 67 bind(notChar);
kevinw@8368 68 // cmpl(rcx, T_SHORT); // all that's left
kevinw@8368 69 // jcc(Assembler::notEqual, done);
kevinw@8368 70 LP64_ONLY(movswl(result, result);)
kevinw@8368 71 NOT_LP64(shll(result, 16);) // truncate upper 16 bits
kevinw@8368 72 NOT_LP64(sarl(result, 16);) // and sign-extend short
kevinw@8368 73
kevinw@8368 74 // Nothing to do for T_INT
kevinw@8368 75 bind(done);
kevinw@8368 76 }
kevinw@8368 77
aoqi@0 78 #ifndef CC_INTERP
aoqi@0 79 void InterpreterMacroAssembler::profile_obj_type(Register obj, const Address& mdo_addr) {
aoqi@0 80 Label update, next, none;
aoqi@0 81
aoqi@0 82 verify_oop(obj);
aoqi@0 83
aoqi@0 84 testptr(obj, obj);
aoqi@0 85 jccb(Assembler::notZero, update);
aoqi@0 86 orptr(mdo_addr, TypeEntries::null_seen);
aoqi@0 87 jmpb(next);
aoqi@0 88
aoqi@0 89 bind(update);
aoqi@0 90 load_klass(obj, obj);
aoqi@0 91
aoqi@0 92 xorptr(obj, mdo_addr);
aoqi@0 93 testptr(obj, TypeEntries::type_klass_mask);
aoqi@0 94 jccb(Assembler::zero, next); // klass seen before, nothing to
aoqi@0 95 // do. The unknown bit may have been
aoqi@0 96 // set already but no need to check.
aoqi@0 97
aoqi@0 98 testptr(obj, TypeEntries::type_unknown);
aoqi@0 99 jccb(Assembler::notZero, next); // already unknown. Nothing to do anymore.
aoqi@0 100
aoqi@0 101 cmpptr(mdo_addr, 0);
aoqi@0 102 jccb(Assembler::equal, none);
aoqi@0 103 cmpptr(mdo_addr, TypeEntries::null_seen);
aoqi@0 104 jccb(Assembler::equal, none);
aoqi@0 105 // There is a chance that the checks above (re-reading profiling
aoqi@0 106 // data from memory) fail if another thread has just set the
aoqi@0 107 // profiling to this obj's klass
aoqi@0 108 xorptr(obj, mdo_addr);
aoqi@0 109 testptr(obj, TypeEntries::type_klass_mask);
aoqi@0 110 jccb(Assembler::zero, next);
aoqi@0 111
aoqi@0 112 // different than before. Cannot keep accurate profile.
aoqi@0 113 orptr(mdo_addr, TypeEntries::type_unknown);
aoqi@0 114 jmpb(next);
aoqi@0 115
aoqi@0 116 bind(none);
aoqi@0 117 // first time here. Set profile type.
aoqi@0 118 movptr(mdo_addr, obj);
aoqi@0 119
aoqi@0 120 bind(next);
aoqi@0 121 }
aoqi@0 122
aoqi@0 123 void InterpreterMacroAssembler::profile_arguments_type(Register mdp, Register callee, Register tmp, bool is_virtual) {
aoqi@0 124 if (!ProfileInterpreter) {
aoqi@0 125 return;
aoqi@0 126 }
aoqi@0 127
aoqi@0 128 if (MethodData::profile_arguments() || MethodData::profile_return()) {
aoqi@0 129 Label profile_continue;
aoqi@0 130
aoqi@0 131 test_method_data_pointer(mdp, profile_continue);
aoqi@0 132
aoqi@0 133 int off_to_start = is_virtual ? in_bytes(VirtualCallData::virtual_call_data_size()) : in_bytes(CounterData::counter_data_size());
aoqi@0 134
aoqi@0 135 cmpb(Address(mdp, in_bytes(DataLayout::tag_offset()) - off_to_start), is_virtual ? DataLayout::virtual_call_type_data_tag : DataLayout::call_type_data_tag);
aoqi@0 136 jcc(Assembler::notEqual, profile_continue);
aoqi@0 137
aoqi@0 138 if (MethodData::profile_arguments()) {
aoqi@0 139 Label done;
aoqi@0 140 int off_to_args = in_bytes(TypeEntriesAtCall::args_data_offset());
aoqi@0 141 addptr(mdp, off_to_args);
aoqi@0 142
aoqi@0 143 for (int i = 0; i < TypeProfileArgsLimit; i++) {
aoqi@0 144 if (i > 0 || MethodData::profile_return()) {
aoqi@0 145 // If return value type is profiled we may have no argument to profile
aoqi@0 146 movptr(tmp, Address(mdp, in_bytes(TypeEntriesAtCall::cell_count_offset())-off_to_args));
aoqi@0 147 subl(tmp, i*TypeStackSlotEntries::per_arg_count());
aoqi@0 148 cmpl(tmp, TypeStackSlotEntries::per_arg_count());
aoqi@0 149 jcc(Assembler::less, done);
aoqi@0 150 }
aoqi@0 151 movptr(tmp, Address(callee, Method::const_offset()));
aoqi@0 152 load_unsigned_short(tmp, Address(tmp, ConstMethod::size_of_parameters_offset()));
aoqi@0 153 // stack offset o (zero based) from the start of the argument
aoqi@0 154 // list, for n arguments translates into offset n - o - 1 from
aoqi@0 155 // the end of the argument list
aoqi@0 156 subptr(tmp, Address(mdp, in_bytes(TypeEntriesAtCall::stack_slot_offset(i))-off_to_args));
aoqi@0 157 subl(tmp, 1);
aoqi@0 158 Address arg_addr = argument_address(tmp);
aoqi@0 159 movptr(tmp, arg_addr);
aoqi@0 160
aoqi@0 161 Address mdo_arg_addr(mdp, in_bytes(TypeEntriesAtCall::argument_type_offset(i))-off_to_args);
aoqi@0 162 profile_obj_type(tmp, mdo_arg_addr);
aoqi@0 163
aoqi@0 164 int to_add = in_bytes(TypeStackSlotEntries::per_arg_size());
aoqi@0 165 addptr(mdp, to_add);
aoqi@0 166 off_to_args += to_add;
aoqi@0 167 }
aoqi@0 168
aoqi@0 169 if (MethodData::profile_return()) {
aoqi@0 170 movptr(tmp, Address(mdp, in_bytes(TypeEntriesAtCall::cell_count_offset())-off_to_args));
aoqi@0 171 subl(tmp, TypeProfileArgsLimit*TypeStackSlotEntries::per_arg_count());
aoqi@0 172 }
aoqi@0 173
aoqi@0 174 bind(done);
aoqi@0 175
aoqi@0 176 if (MethodData::profile_return()) {
aoqi@0 177 // We're right after the type profile for the last
aoqi@0 178 // argument. tmp is the number of cells left in the
aoqi@0 179 // CallTypeData/VirtualCallTypeData to reach its end. Non null
aoqi@0 180 // if there's a return to profile.
aoqi@0 181 assert(ReturnTypeEntry::static_cell_count() < TypeStackSlotEntries::per_arg_count(), "can't move past ret type");
aoqi@0 182 shll(tmp, exact_log2(DataLayout::cell_size));
aoqi@0 183 addptr(mdp, tmp);
aoqi@0 184 }
aoqi@0 185 movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize), mdp);
aoqi@0 186 } else {
aoqi@0 187 assert(MethodData::profile_return(), "either profile call args or call ret");
aoqi@0 188 update_mdp_by_constant(mdp, in_bytes(TypeEntriesAtCall::return_only_size()));
aoqi@0 189 }
aoqi@0 190
aoqi@0 191 // mdp points right after the end of the
aoqi@0 192 // CallTypeData/VirtualCallTypeData, right after the cells for the
aoqi@0 193 // return value type if there's one
aoqi@0 194
aoqi@0 195 bind(profile_continue);
aoqi@0 196 }
aoqi@0 197 }
aoqi@0 198
aoqi@0 199 void InterpreterMacroAssembler::profile_return_type(Register mdp, Register ret, Register tmp) {
aoqi@0 200 assert_different_registers(mdp, ret, tmp, _bcp_register);
aoqi@0 201 if (ProfileInterpreter && MethodData::profile_return()) {
aoqi@0 202 Label profile_continue, done;
aoqi@0 203
aoqi@0 204 test_method_data_pointer(mdp, profile_continue);
aoqi@0 205
aoqi@0 206 if (MethodData::profile_return_jsr292_only()) {
aoqi@0 207 // If we don't profile all invoke bytecodes we must make sure
aoqi@0 208 // it's a bytecode we indeed profile. We can't go back to the
aoqi@0 209 // begining of the ProfileData we intend to update to check its
aoqi@0 210 // type because we're right after it and we don't known its
aoqi@0 211 // length
aoqi@0 212 Label do_profile;
aoqi@0 213 cmpb(Address(_bcp_register, 0), Bytecodes::_invokedynamic);
aoqi@0 214 jcc(Assembler::equal, do_profile);
aoqi@0 215 cmpb(Address(_bcp_register, 0), Bytecodes::_invokehandle);
aoqi@0 216 jcc(Assembler::equal, do_profile);
aoqi@0 217 get_method(tmp);
aoqi@0 218 cmpb(Address(tmp, Method::intrinsic_id_offset_in_bytes()), vmIntrinsics::_compiledLambdaForm);
aoqi@0 219 jcc(Assembler::notEqual, profile_continue);
aoqi@0 220
aoqi@0 221 bind(do_profile);
aoqi@0 222 }
aoqi@0 223
aoqi@0 224 Address mdo_ret_addr(mdp, -in_bytes(ReturnTypeEntry::size()));
aoqi@0 225 mov(tmp, ret);
aoqi@0 226 profile_obj_type(tmp, mdo_ret_addr);
aoqi@0 227
aoqi@0 228 bind(profile_continue);
aoqi@0 229 }
aoqi@0 230 }
aoqi@0 231
aoqi@0 232 void InterpreterMacroAssembler::profile_parameters_type(Register mdp, Register tmp1, Register tmp2) {
aoqi@0 233 if (ProfileInterpreter && MethodData::profile_parameters()) {
aoqi@0 234 Label profile_continue, done;
aoqi@0 235
aoqi@0 236 test_method_data_pointer(mdp, profile_continue);
aoqi@0 237
aoqi@0 238 // Load the offset of the area within the MDO used for
aoqi@0 239 // parameters. If it's negative we're not profiling any parameters
aoqi@0 240 movl(tmp1, Address(mdp, in_bytes(MethodData::parameters_type_data_di_offset()) - in_bytes(MethodData::data_offset())));
aoqi@0 241 testl(tmp1, tmp1);
aoqi@0 242 jcc(Assembler::negative, profile_continue);
aoqi@0 243
aoqi@0 244 // Compute a pointer to the area for parameters from the offset
aoqi@0 245 // and move the pointer to the slot for the last
aoqi@0 246 // parameters. Collect profiling from last parameter down.
aoqi@0 247 // mdo start + parameters offset + array length - 1
aoqi@0 248 addptr(mdp, tmp1);
aoqi@0 249 movptr(tmp1, Address(mdp, ArrayData::array_len_offset()));
aoqi@0 250 decrement(tmp1, TypeStackSlotEntries::per_arg_count());
aoqi@0 251
aoqi@0 252 Label loop;
aoqi@0 253 bind(loop);
aoqi@0 254
aoqi@0 255 int off_base = in_bytes(ParametersTypeData::stack_slot_offset(0));
aoqi@0 256 int type_base = in_bytes(ParametersTypeData::type_offset(0));
aoqi@0 257 Address::ScaleFactor per_arg_scale = Address::times(DataLayout::cell_size);
aoqi@0 258 Address arg_off(mdp, tmp1, per_arg_scale, off_base);
aoqi@0 259 Address arg_type(mdp, tmp1, per_arg_scale, type_base);
aoqi@0 260
aoqi@0 261 // load offset on the stack from the slot for this parameter
aoqi@0 262 movptr(tmp2, arg_off);
aoqi@0 263 negptr(tmp2);
aoqi@0 264 // read the parameter from the local area
aoqi@0 265 movptr(tmp2, Address(_locals_register, tmp2, Interpreter::stackElementScale()));
aoqi@0 266
aoqi@0 267 // profile the parameter
aoqi@0 268 profile_obj_type(tmp2, arg_type);
aoqi@0 269
aoqi@0 270 // go to next parameter
aoqi@0 271 decrement(tmp1, TypeStackSlotEntries::per_arg_count());
aoqi@0 272 jcc(Assembler::positive, loop);
aoqi@0 273
aoqi@0 274 bind(profile_continue);
aoqi@0 275 }
aoqi@0 276 }
aoqi@0 277 #endif

mercurial