1 /* 2 * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. 3 * Copyright (c) 2014, Red Hat Inc. All rights reserved. 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5 * 6 * This code is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 only, as 8 * published by the Free Software Foundation. 9 * 10 * This code is distributed in the hope that it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 * version 2 for more details (a copy is included in the LICENSE file that 14 * accompanied this code). 15 * 16 * You should have received a copy of the GNU General Public License version 17 * 2 along with this work; if not, write to the Free Software Foundation, 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 * 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 * or visit www.oracle.com if you need additional information or have any 22 * questions. 23 * 24 */ 25 26 #include "precompiled.hpp" 27 #include "asm/macroAssembler.hpp" 28 #include "assembler_aarch64.inline.hpp" 29 #include "code/vtableStubs.hpp" 30 #include "interp_masm_aarch64.hpp" 31 #include "memory/resourceArea.hpp" 32 #include "oops/compiledICHolder.hpp" 33 #include "oops/instanceKlass.hpp" 34 #include "oops/klassVtable.hpp" 35 #include "runtime/sharedRuntime.hpp" 36 #include "vmreg_aarch64.inline.hpp" 37 #ifdef COMPILER2 38 #include "opto/runtime.hpp" 39 #endif 40 41 // machine-dependent part of VtableStubs: create VtableStub of correct size and 42 // initialize its code 43 44 #define __ masm-> 45 46 #ifndef PRODUCT 47 extern "C" void bad_compiled_vtable_index(JavaThread* thread, 48 oop receiver, 49 int index); 50 #endif 51 52 VtableStub* VtableStubs::create_vtable_stub(int vtable_index) { 53 const int aarch64_code_length = VtableStub::pd_code_size_limit(true); 54 VtableStub* s = new(aarch64_code_length) VtableStub(true, vtable_index); 55 // Can be NULL if there is no free space in the code cache. 56 if (s == NULL) { 57 return NULL; 58 } 59 60 ResourceMark rm; 61 CodeBuffer cb(s->entry_point(), aarch64_code_length); 62 MacroAssembler* masm = new MacroAssembler(&cb); 63 64 #ifndef PRODUCT 65 if (CountCompiledCalls) { 66 __ lea(r16, ExternalAddress((address) SharedRuntime::nof_megamorphic_calls_addr())); 67 __ incrementw(Address(r16)); 68 } 69 #endif 70 71 // get receiver (need to skip return address on top of stack) 72 assert(VtableStub::receiver_location() == j_rarg0->as_VMReg(), "receiver expected in j_rarg0"); 73 74 // get receiver klass 75 address npe_addr = __ pc(); 76 __ load_klass(r16, j_rarg0); 77 78 #ifndef PRODUCT 79 if (DebugVtables) { 80 Label L; 81 // check offset vs vtable length 82 __ ldrw(rscratch1, Address(r16, Klass::vtable_length_offset())); 83 __ cmpw(rscratch1, vtable_index * vtableEntry::size()); 84 __ br(Assembler::GT, L); 85 __ enter(); 86 __ mov(r2, vtable_index); 87 __ call_VM(noreg, 88 CAST_FROM_FN_PTR(address, bad_compiled_vtable_index), j_rarg0, r2); 89 __ leave(); 90 __ bind(L); 91 } 92 #endif // PRODUCT 93 94 __ lookup_virtual_method(r16, vtable_index, rmethod); 95 96 if (DebugVtables) { 97 Label L; 98 __ cbz(rmethod, L); 99 __ ldr(rscratch1, Address(rmethod, Method::from_compiled_offset())); 100 __ cbnz(rscratch1, L); 101 __ stop("Vtable entry is NULL"); 102 __ bind(L); 103 } 104 // r0: receiver klass 105 // rmethod: Method* 106 // r2: receiver 107 address ame_addr = __ pc(); 108 __ ldr(rscratch1, Address(rmethod, Method::from_compiled_offset())); 109 __ br(rscratch1); 110 111 __ flush(); 112 113 if (PrintMiscellaneous && (WizardMode || Verbose)) { 114 tty->print_cr("vtable #%d at " PTR_FORMAT "[%d] left over: %d", 115 vtable_index, p2i(s->entry_point()), 116 (int)(s->code_end() - s->entry_point()), 117 (int)(s->code_end() - __ pc())); 118 } 119 guarantee(__ pc() <= s->code_end(), "overflowed buffer"); 120 121 s->set_exception_points(npe_addr, ame_addr); 122 return s; 123 } 124 125 126 VtableStub* VtableStubs::create_itable_stub(int itable_index) { 127 // Note well: pd_code_size_limit is the absolute minimum we can get 128 // away with. If you add code here, bump the code stub size 129 // returned by pd_code_size_limit! 130 const int code_length = VtableStub::pd_code_size_limit(false); 131 VtableStub* s = new(code_length) VtableStub(false, itable_index); 132 ResourceMark rm; 133 CodeBuffer cb(s->entry_point(), code_length); 134 MacroAssembler* masm = new MacroAssembler(&cb); 135 136 #ifndef PRODUCT 137 if (CountCompiledCalls) { 138 __ lea(r10, ExternalAddress((address) SharedRuntime::nof_megamorphic_calls_addr())); 139 __ incrementw(Address(r10)); 140 } 141 #endif 142 143 // Entry arguments: 144 // rscratch2: CompiledICHolder 145 // j_rarg0: Receiver 146 147 148 // Most registers are in use; we'll use r16, rmethod, r10, r11 149 const Register recv_klass_reg = r10; 150 const Register holder_klass_reg = r16; // declaring interface klass (DECC) 151 const Register resolved_klass_reg = rmethod; // resolved interface klass (REFC) 152 const Register temp_reg = r11; 153 const Register icholder_reg = rscratch2; 154 155 Label L_no_such_interface; 156 157 __ ldr(resolved_klass_reg, Address(icholder_reg, CompiledICHolder::holder_klass_offset())); 158 __ ldr(holder_klass_reg, Address(icholder_reg, CompiledICHolder::holder_metadata_offset())); 159 160 // get receiver (need to skip return address on top of stack) 161 assert(VtableStub::receiver_location() == j_rarg0->as_VMReg(), "receiver expected in j_rarg0"); 162 // get receiver klass (also an implicit null-check) 163 address npe_addr = __ pc(); 164 __ load_klass(recv_klass_reg, j_rarg0); 165 166 // Receiver subtype check against REFC. 167 // Destroys recv_klass_reg value. 168 __ lookup_interface_method(// inputs: rec. class, interface 169 recv_klass_reg, resolved_klass_reg, noreg, 170 // outputs: scan temp. reg1, scan temp. reg2 171 recv_klass_reg, temp_reg, 172 L_no_such_interface, 173 /*return_method=*/false); 174 175 // Get selected method from declaring class and itable index 176 __ load_klass(recv_klass_reg, j_rarg0); // restore recv_klass_reg 177 __ lookup_interface_method(// inputs: rec. class, interface, itable index 178 recv_klass_reg, holder_klass_reg, itable_index, 179 // outputs: method, scan temp. reg 180 rmethod, temp_reg, 181 L_no_such_interface); 182 183 // method (rmethod): Method* 184 // j_rarg0: receiver 185 186 #ifdef ASSERT 187 if (DebugVtables) { 188 Label L2; 189 __ cbz(rmethod, L2); 190 __ ldr(rscratch1, Address(rmethod, Method::from_compiled_offset())); 191 __ cbnz(rscratch1, L2); 192 __ stop("compiler entrypoint is null"); 193 __ bind(L2); 194 } 195 #endif // ASSERT 196 197 // rmethod: Method* 198 // j_rarg0: receiver 199 address ame_addr = __ pc(); 200 __ ldr(rscratch1, Address(rmethod, Method::from_compiled_offset())); 201 __ br(rscratch1); 202 203 __ bind(L_no_such_interface); 204 // Handle IncompatibleClassChangeError in itable stubs. 205 // More detailed error message. 206 // We force resolving of the call site by jumping to the "handle 207 // wrong method" stub, and so let the interpreter runtime do all the 208 // dirty work. 209 __ far_jump(RuntimeAddress(SharedRuntime::get_handle_wrong_method_stub())); 210 211 __ flush(); 212 213 if (PrintMiscellaneous && (WizardMode || Verbose)) { 214 tty->print_cr("itable #%d at " PTR_FORMAT "[%d] left over: %d", 215 itable_index, p2i(s->entry_point()), 216 (int)(s->code_end() - s->entry_point()), 217 (int)(s->code_end() - __ pc())); 218 } 219 guarantee(__ pc() <= s->code_end(), "overflowed buffer"); 220 221 s->set_exception_points(npe_addr, ame_addr); 222 return s; 223 } 224 225 226 int VtableStub::pd_code_size_limit(bool is_vtable_stub) { 227 int size = DebugVtables ? 216 : 0; 228 if (CountCompiledCalls) 229 size += 6 * 4; 230 // FIXME: vtable stubs only need 36 bytes 231 if (is_vtable_stub) 232 size += 52; 233 else 234 size += 176; 235 return size; 236 237 // In order to tune these parameters, run the JVM with VM options 238 // +PrintMiscellaneous and +WizardMode to see information about 239 // actual itable stubs. Run it with -Xmx31G -XX:+UseCompressedOops. 240 // 241 // If Universe::narrow_klass_base is nonzero, decoding a compressed 242 // class can take zeveral instructions. 243 // 244 // The JVM98 app. _202_jess has a megamorphic interface call. 245 // The itable code looks like this: 246 247 // ldr xmethod, [xscratch2,#CompiledICHolder::holder_klass_offset] 248 // ldr x0, [xscratch2] 249 // ldr w10, [x1,#oopDesc::klass_offset_in_bytes] 250 // mov xheapbase, #0x3c000000 // #narrow_klass_base 251 // movk xheapbase, #0x3f7, lsl #32 252 // add x10, xheapbase, x10 253 // mov xheapbase, #0xe7ff0000 // #heapbase 254 // movk xheapbase, #0x3f7, lsl #32 255 // ldr w11, [x10,#vtable_length_offset] 256 // add x11, x10, x11, uxtx #3 257 // add x11, x11, #itableMethodEntry::method_offset_in_bytes 258 // ldr x10, [x11] 259 // cmp xmethod, x10 260 // b.eq found_method 261 // search: 262 // cbz x10, no_such_interface 263 // add x11, x11, #0x10 264 // ldr x10, [x11] 265 // cmp xmethod, x10 266 // b.ne search 267 // found_method: 268 // ldr w10, [x1,#oopDesc::klass_offset_in_bytes] 269 // mov xheapbase, #0x3c000000 // #narrow_klass_base 270 // movk xheapbase, #0x3f7, lsl #32 271 // add x10, xheapbase, x10 272 // mov xheapbase, #0xe7ff0000 // #heapbase 273 // movk xheapbase, #0x3f7, lsl #32 274 // ldr w11, [x10,#vtable_length_offset] 275 // add x11, x10, x11, uxtx #3 276 // add x11, x11, #itableMethodEntry::method_offset_in_bytes 277 // add x10, x10, #itentry_off 278 // ldr xmethod, [x11] 279 // cmp x0, xmethod 280 // b.eq found_method2 281 // search2: 282 // cbz xmethod, 0x000003ffa872e6cc 283 // add x11, x11, #0x10 284 // ldr xmethod, [x11] 285 // cmp x0, xmethod 286 // b.ne search2 287 // found_method2: 288 // ldr w11, [x11,#itableOffsetEntry::offset_offset_in_bytes] 289 // ldr xmethod, [x10,w11,uxtw] 290 // ldr xscratch1, [xmethod,#Method::from_compiled_offset] 291 // br xscratch1 292 // no_such_interface: 293 // b throw_ICCE_entry 294 295 } 296 297 int VtableStub::pd_code_alignment() { return 4; }