1 /* 2 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. 3 * Copyright 2012, 2014 SAP AG. 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/assembler.hpp" 28 #include "asm/macroAssembler.inline.hpp" 29 #include "code/vtableStubs.hpp" 30 #include "interp_masm_ppc_64.hpp" 31 #include "memory/resourceArea.hpp" 32 #include "oops/instanceKlass.hpp" 33 #include "oops/klassVtable.hpp" 34 #include "runtime/sharedRuntime.hpp" 35 #include "vmreg_ppc.inline.hpp" 36 #ifdef COMPILER2 37 #include "opto/runtime.hpp" 38 #endif 39 40 #define __ masm-> 41 42 #ifdef PRODUCT 43 #define BLOCK_COMMENT(str) // nothing 44 #else 45 #define BLOCK_COMMENT(str) __ block_comment(str) 46 #endif 47 #define BIND(label) bind(label); BLOCK_COMMENT(#label ":") 48 49 #ifndef PRODUCT 50 extern "C" void bad_compiled_vtable_index(JavaThread* thread, oopDesc* receiver, int index); 51 #endif 52 53 // Used by compiler only; may use only caller saved, non-argument 54 // registers. 55 VtableStub* VtableStubs::create_vtable_stub(int vtable_index) { 56 // PPC port: use fixed size. 57 const int code_length = VtableStub::pd_code_size_limit(true); 58 VtableStub* s = new (code_length) VtableStub(true, vtable_index); 59 ResourceMark rm; 60 CodeBuffer cb(s->entry_point(), code_length); 61 MacroAssembler* masm = new MacroAssembler(&cb); 62 address start_pc; 63 64 #ifndef PRODUCT 65 if (CountCompiledCalls) { 66 __ load_const(R11_scratch1, SharedRuntime::nof_megamorphic_calls_addr()); 67 __ lwz(R12_scratch2, 0, R11_scratch1); 68 __ addi(R12_scratch2, R12_scratch2, 1); 69 __ stw(R12_scratch2, 0, R11_scratch1); 70 } 71 #endif 72 73 assert(VtableStub::receiver_location() == R3_ARG1->as_VMReg(), "receiver expected in R3_ARG1"); 74 75 // Get receiver klass. 76 const Register rcvr_klass = R11_scratch1; 77 78 // We might implicit NULL fault here. 79 address npe_addr = __ pc(); // npe = null pointer exception 80 __ load_klass_with_trap_null_check(rcvr_klass, R3); 81 82 // Set method (in case of interpreted method), and destination address. 83 int entry_offset = InstanceKlass::vtable_start_offset() + vtable_index*vtableEntry::size(); 84 85 #ifndef PRODUCT 86 if (DebugVtables) { 87 Label L; 88 // Check offset vs vtable length. 89 const Register vtable_len = R12_scratch2; 90 __ lwz(vtable_len, InstanceKlass::vtable_length_offset()*wordSize, rcvr_klass); 91 __ cmpwi(CCR0, vtable_len, vtable_index*vtableEntry::size()); 92 __ bge(CCR0, L); 93 __ li(R12_scratch2, vtable_index); 94 __ call_VM(noreg, CAST_FROM_FN_PTR(address, bad_compiled_vtable_index), R3_ARG1, R12_scratch2, false); 95 __ bind(L); 96 } 97 #endif 98 99 int v_off = entry_offset*wordSize + vtableEntry::method_offset_in_bytes(); 100 101 __ ld(R19_method, v_off, rcvr_klass); 102 103 #ifndef PRODUCT 104 if (DebugVtables) { 105 Label L; 106 __ cmpdi(CCR0, R19_method, 0); 107 __ bne(CCR0, L); 108 __ stop("Vtable entry is ZERO", 102); 109 __ bind(L); 110 } 111 #endif 112 113 // If the vtable entry is null, the method is abstract. 114 address ame_addr = __ pc(); // ame = abstract method error 115 116 __ load_with_trap_null_check(R12_scratch2, in_bytes(Method::from_compiled_offset()), R19_method); 117 __ mtctr(R12_scratch2); 118 __ bctr(); 119 masm->flush(); 120 121 guarantee(__ pc() <= s->code_end(), "overflowed buffer"); 122 123 s->set_exception_points(npe_addr, ame_addr); 124 125 return s; 126 } 127 128 VtableStub* VtableStubs::create_itable_stub(int vtable_index) { 129 // PPC port: use fixed size. 130 const int code_length = VtableStub::pd_code_size_limit(false); 131 VtableStub* s = new (code_length) VtableStub(false, vtable_index); 132 ResourceMark rm; 133 CodeBuffer cb(s->entry_point(), code_length); 134 MacroAssembler* masm = new MacroAssembler(&cb); 135 address start_pc; 136 137 #ifndef PRODUCT 138 if (CountCompiledCalls) { 139 __ load_const(R11_scratch1, SharedRuntime::nof_megamorphic_calls_addr()); 140 __ lwz(R12_scratch2, 0, R11_scratch1); 141 __ addi(R12_scratch2, R12_scratch2, 1); 142 __ stw(R12_scratch2, 0, R11_scratch1); 143 } 144 #endif 145 146 assert(VtableStub::receiver_location() == R3_ARG1->as_VMReg(), "receiver expected in R3_ARG1"); 147 148 // Entry arguments: 149 // R19_method: Interface 150 // R3_ARG1: Receiver 151 // 152 153 const Register rcvr_klass = R11_scratch1; 154 const Register vtable_len = R12_scratch2; 155 const Register itable_entry_addr = R21_tmp1; 156 const Register itable_interface = R22_tmp2; 157 158 // Get receiver klass. 159 160 // We might implicit NULL fault here. 161 address npe_addr = __ pc(); // npe = null pointer exception 162 __ load_klass_with_trap_null_check(rcvr_klass, R3_ARG1); 163 164 BLOCK_COMMENT("Load start of itable entries into itable_entry."); 165 __ lwz(vtable_len, InstanceKlass::vtable_length_offset() * wordSize, rcvr_klass); 166 __ slwi(vtable_len, vtable_len, exact_log2(vtableEntry::size() * wordSize)); 167 __ add(itable_entry_addr, vtable_len, rcvr_klass); 168 169 // Loop over all itable entries until desired interfaceOop(Rinterface) found. 170 BLOCK_COMMENT("Increment itable_entry_addr in loop."); 171 const int vtable_base_offset = InstanceKlass::vtable_start_offset() * wordSize; 172 __ addi(itable_entry_addr, itable_entry_addr, vtable_base_offset + itableOffsetEntry::interface_offset_in_bytes()); 173 174 const int itable_offset_search_inc = itableOffsetEntry::size() * wordSize; 175 Label search; 176 __ bind(search); 177 __ ld(itable_interface, 0, itable_entry_addr); 178 179 // Handle IncompatibleClassChangeError in itable stubs. 180 // If the entry is NULL then we've reached the end of the table 181 // without finding the expected interface, so throw an exception. 182 BLOCK_COMMENT("Handle IncompatibleClassChangeError in itable stubs."); 183 Label throw_icce; 184 __ cmpdi(CCR1, itable_interface, 0); 185 __ cmpd(CCR0, itable_interface, R19_method); 186 __ addi(itable_entry_addr, itable_entry_addr, itable_offset_search_inc); 187 __ beq(CCR1, throw_icce); 188 __ bne(CCR0, search); 189 190 // Entry found and itable_entry_addr points to it, get offset of vtable for interface. 191 192 const Register vtable_offset = R12_scratch2; 193 const Register itable_method = R11_scratch1; 194 195 const int vtable_offset_offset = (itableOffsetEntry::offset_offset_in_bytes() - 196 itableOffsetEntry::interface_offset_in_bytes()) - 197 itable_offset_search_inc; 198 __ lwz(vtable_offset, vtable_offset_offset, itable_entry_addr); 199 200 // Compute itableMethodEntry and get method and entry point for compiler. 201 const int method_offset = (itableMethodEntry::size() * wordSize * vtable_index) + 202 itableMethodEntry::method_offset_in_bytes(); 203 204 __ add(itable_method, rcvr_klass, vtable_offset); 205 __ ld(R19_method, method_offset, itable_method); 206 207 #ifndef PRODUCT 208 if (DebugVtables) { 209 Label ok; 210 __ cmpd(CCR0, R19_method, 0); 211 __ bne(CCR0, ok); 212 __ stop("method is null", 103); 213 __ bind(ok); 214 } 215 #endif 216 217 // If the vtable entry is null, the method is abstract. 218 address ame_addr = __ pc(); // ame = abstract method error 219 220 // Must do an explicit check if implicit checks are disabled. 221 assert(!MacroAssembler::needs_explicit_null_check(in_bytes(Method::from_compiled_offset())), "sanity"); 222 if (!ImplicitNullChecks || !os::zero_page_read_protected()) { 223 if (TrapBasedNullChecks) { 224 __ trap_null_check(R19_method); 225 } else { 226 __ cmpdi(CCR0, R19_method, 0); 227 __ beq(CCR0, throw_icce); 228 } 229 } 230 __ ld(R12_scratch2, in_bytes(Method::from_compiled_offset()), R19_method); 231 __ mtctr(R12_scratch2); 232 __ bctr(); 233 234 // Handle IncompatibleClassChangeError in itable stubs. 235 // More detailed error message. 236 // We force resolving of the call site by jumping to the "handle 237 // wrong method" stub, and so let the interpreter runtime do all the 238 // dirty work. 239 __ bind(throw_icce); 240 __ load_const(R11_scratch1, SharedRuntime::get_handle_wrong_method_stub()); 241 __ mtctr(R11_scratch1); 242 __ bctr(); 243 244 masm->flush(); 245 246 guarantee(__ pc() <= s->code_end(), "overflowed buffer"); 247 248 s->set_exception_points(npe_addr, ame_addr); 249 return s; 250 } 251 252 int VtableStub::pd_code_size_limit(bool is_vtable_stub) { 253 if (TraceJumps || DebugVtables || CountCompiledCalls || VerifyOops) { 254 return 1000; 255 } else { 256 int decode_klass_size = MacroAssembler::instr_size_for_decode_klass_not_null(); 257 if (is_vtable_stub) { 258 return 20 + decode_klass_size + 8 + 8; // Plain + cOops + Traps + safety 259 } else { 260 return 96 + decode_klass_size + 12 + 8; // Plain + cOops + Traps + safety 261 } 262 } 263 } 264 265 int VtableStub::pd_code_alignment() { 266 const unsigned int icache_line_size = 32; 267 return icache_line_size; 268 }