Wed, 15 Apr 2020 11:49:55 +0800
Merge
1 /*
2 * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
3 * Copyright 2012, 2017 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 */
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/compiledICHolder.hpp"
33 #include "oops/instanceKlass.hpp"
34 #include "oops/klassVtable.hpp"
35 #include "runtime/sharedRuntime.hpp"
36 #include "vmreg_ppc.inline.hpp"
37 #ifdef COMPILER2
38 #include "opto/runtime.hpp"
39 #endif
41 #define __ masm->
43 #ifdef PRODUCT
44 #define BLOCK_COMMENT(str) // nothing
45 #else
46 #define BLOCK_COMMENT(str) __ block_comment(str)
47 #endif
48 #define BIND(label) bind(label); BLOCK_COMMENT(#label ":")
50 #ifndef PRODUCT
51 extern "C" void bad_compiled_vtable_index(JavaThread* thread, oopDesc* receiver, int index);
52 #endif
54 // Used by compiler only; may use only caller saved, non-argument
55 // registers.
56 VtableStub* VtableStubs::create_vtable_stub(int vtable_index) {
57 // PPC port: use fixed size.
58 const int code_length = VtableStub::pd_code_size_limit(true);
59 VtableStub* s = new (code_length) VtableStub(true, vtable_index);
61 // Can be NULL if there is no free space in the code cache.
62 if (s == NULL) {
63 return NULL;
64 }
66 ResourceMark rm;
67 CodeBuffer cb(s->entry_point(), code_length);
68 MacroAssembler* masm = new MacroAssembler(&cb);
70 #ifndef PRODUCT
71 if (CountCompiledCalls) {
72 int offs = __ load_const_optimized(R11_scratch1, SharedRuntime::nof_megamorphic_calls_addr(), R12_scratch2, true);
73 __ lwz(R12_scratch2, offs, R11_scratch1);
74 __ addi(R12_scratch2, R12_scratch2, 1);
75 __ stw(R12_scratch2, offs, R11_scratch1);
76 }
77 #endif
79 assert(VtableStub::receiver_location() == R3_ARG1->as_VMReg(), "receiver expected in R3_ARG1");
81 // Get receiver klass.
82 const Register rcvr_klass = R11_scratch1;
84 // We might implicit NULL fault here.
85 address npe_addr = __ pc(); // npe = null pointer exception
86 __ load_klass_with_trap_null_check(rcvr_klass, R3);
88 // Set method (in case of interpreted method), and destination address.
89 int entry_offset = InstanceKlass::vtable_start_offset() + vtable_index*vtableEntry::size();
91 #ifndef PRODUCT
92 if (DebugVtables) {
93 Label L;
94 // Check offset vs vtable length.
95 const Register vtable_len = R12_scratch2;
96 __ lwz(vtable_len, InstanceKlass::vtable_length_offset()*wordSize, rcvr_klass);
97 __ cmpwi(CCR0, vtable_len, vtable_index*vtableEntry::size());
98 __ bge(CCR0, L);
99 __ li(R12_scratch2, vtable_index);
100 __ call_VM(noreg, CAST_FROM_FN_PTR(address, bad_compiled_vtable_index), R3_ARG1, R12_scratch2, false);
101 __ bind(L);
102 }
103 #endif
105 int v_off = entry_offset*wordSize + vtableEntry::method_offset_in_bytes();
107 __ ld(R19_method, v_off, rcvr_klass);
109 #ifndef PRODUCT
110 if (DebugVtables) {
111 Label L;
112 __ cmpdi(CCR0, R19_method, 0);
113 __ bne(CCR0, L);
114 __ stop("Vtable entry is ZERO", 102);
115 __ bind(L);
116 }
117 #endif
119 // If the vtable entry is null, the method is abstract.
120 address ame_addr = __ pc(); // ame = abstract method error
122 __ load_with_trap_null_check(R12_scratch2, in_bytes(Method::from_compiled_offset()), R19_method);
123 __ mtctr(R12_scratch2);
124 __ bctr();
126 masm->flush();
128 guarantee(__ pc() <= s->code_end(), "overflowed buffer");
130 s->set_exception_points(npe_addr, ame_addr);
132 return s;
133 }
135 VtableStub* VtableStubs::create_itable_stub(int itable_index) {
136 // PPC port: use fixed size.
137 const int code_length = VtableStub::pd_code_size_limit(false);
138 VtableStub* s = new (code_length) VtableStub(false, itable_index);
140 // Can be NULL if there is no free space in the code cache.
141 if (s == NULL) {
142 return NULL;
143 }
145 ResourceMark rm;
146 CodeBuffer cb(s->entry_point(), code_length);
147 MacroAssembler* masm = new MacroAssembler(&cb);
148 address start_pc;
150 #ifndef PRODUCT
151 if (CountCompiledCalls) {
152 int offs = __ load_const_optimized(R11_scratch1, SharedRuntime::nof_megamorphic_calls_addr(), R12_scratch2, true);
153 __ lwz(R12_scratch2, offs, R11_scratch1);
154 __ addi(R12_scratch2, R12_scratch2, 1);
155 __ stw(R12_scratch2, offs, R11_scratch1);
156 }
157 #endif
159 assert(VtableStub::receiver_location() == R3_ARG1->as_VMReg(), "receiver expected in R3_ARG1");
161 // Entry arguments:
162 // R19_method: Interface
163 // R3_ARG1: Receiver
165 Label L_no_such_interface;
166 const Register rcvr_klass = R11_scratch1,
167 interface = R12_scratch2,
168 tmp1 = R21_tmp1,
169 tmp2 = R22_tmp2;
171 address npe_addr = __ pc(); // npe = null pointer exception
172 __ load_klass_with_trap_null_check(rcvr_klass, R3_ARG1);
174 // Receiver subtype check against REFC.
175 __ ld(interface, CompiledICHolder::holder_klass_offset(), R19_method);
176 __ lookup_interface_method(rcvr_klass, interface, noreg,
177 R0, tmp1, tmp2,
178 L_no_such_interface, /*return_method=*/ false);
180 // Get Method* and entrypoint for compiler
181 __ ld(interface, CompiledICHolder::holder_metadata_offset(), R19_method);
182 __ lookup_interface_method(rcvr_klass, interface, itable_index,
183 R19_method, tmp1, tmp2,
184 L_no_such_interface, /*return_method=*/ true);
186 #ifndef PRODUCT
187 if (DebugVtables) {
188 Label ok;
189 __ cmpd(CCR0, R19_method, 0);
190 __ bne(CCR0, ok);
191 __ stop("method is null", 103);
192 __ bind(ok);
193 }
194 #endif
196 // If the vtable entry is null, the method is abstract.
197 address ame_addr = __ pc(); // ame = abstract method error
199 // Must do an explicit check if implicit checks are disabled.
200 assert(!MacroAssembler::needs_explicit_null_check(in_bytes(Method::from_compiled_offset())), "sanity");
201 if (!ImplicitNullChecks || !os::zero_page_read_protected()) {
202 if (TrapBasedNullChecks) {
203 __ trap_null_check(R19_method);
204 } else {
205 __ cmpdi(CCR0, R19_method, 0);
206 __ beq(CCR0, L_no_such_interface);
207 }
208 }
209 __ ld(R12_scratch2, in_bytes(Method::from_compiled_offset()), R19_method);
210 __ mtctr(R12_scratch2);
211 __ bctr();
213 // Handle IncompatibleClassChangeError in itable stubs.
214 // More detailed error message.
215 // We force resolving of the call site by jumping to the "handle
216 // wrong method" stub, and so let the interpreter runtime do all the
217 // dirty work.
218 __ bind(L_no_such_interface);
219 __ load_const_optimized(R11_scratch1, SharedRuntime::get_handle_wrong_method_stub(), R12_scratch2);
220 __ mtctr(R11_scratch1);
221 __ bctr();
223 masm->flush();
225 guarantee(__ pc() <= s->code_end(), "overflowed buffer");
227 s->set_exception_points(npe_addr, ame_addr);
228 return s;
229 }
231 int VtableStub::pd_code_size_limit(bool is_vtable_stub) {
232 if (TraceJumps || DebugVtables || CountCompiledCalls || VerifyOops) {
233 return 1000;
234 }
235 int size = is_vtable_stub ? 20 + 8 : 164 + 20; // Plain + safety
236 if (UseCompressedClassPointers) {
237 size += MacroAssembler::instr_size_for_decode_klass_not_null();
238 }
239 if (!ImplicitNullChecks || !os::zero_page_read_protected()) {
240 size += is_vtable_stub ? 8 : 12;
241 }
242 return size;
243 }
245 int VtableStub::pd_code_alignment() {
246 const unsigned int icache_line_size = 32;
247 return icache_line_size;
248 }