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