comparison src/cpu/ppc/vm/vtableStubs_ppc_64.cpp @ 14408:ec28f9c041ff

8019972: PPC64 (part 9): platform files for interpreter only VM. Summary: With this change the HotSpot core build works on Linux/PPC64. The VM succesfully executes simple test programs. Reviewed-by: kvn
author goetz
date Fri, 02 Aug 2013 16:46:45 +0200
parents
children eb178e97560c
comparison
equal deleted inserted replaced
14407:94c202aa2646 14408:ec28f9c041ff
1 /*
2 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
3 * Copyright 2012, 2013 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 methodOop (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 __ ld_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 //__ ld(rcvr_klass, oopDesc::klass_offset_in_bytes(), R3_ARG1);
165
166 BLOCK_COMMENT("Load start of itable entries into itable_entry.");
167 __ lwz(vtable_len, InstanceKlass::vtable_length_offset() * wordSize, rcvr_klass);
168 __ slwi(vtable_len, vtable_len, exact_log2(vtableEntry::size() * wordSize));
169 __ add(itable_entry_addr, vtable_len, rcvr_klass);
170
171 // Loop over all itable entries until desired interfaceOop(Rinterface) found.
172 BLOCK_COMMENT("Increment itable_entry_addr in loop.");
173 const int vtable_base_offset = InstanceKlass::vtable_start_offset() * wordSize;
174 __ addi(itable_entry_addr, itable_entry_addr, vtable_base_offset + itableOffsetEntry::interface_offset_in_bytes());
175
176 const int itable_offset_search_inc = itableOffsetEntry::size() * wordSize;
177 Label search;
178 __ bind(search);
179 __ ld(itable_interface, 0, itable_entry_addr);
180
181 // Handle IncompatibleClassChangeError in itable stubs.
182 // If the entry is NULL then we've reached the end of the table
183 // without finding the expected interface, so throw an exception.
184 BLOCK_COMMENT("Handle IncompatibleClassChangeError in itable stubs.");
185 Label throw_icce;
186 __ cmpdi(CCR1, itable_interface, 0);
187 __ cmpd(CCR0, itable_interface, R19_method);
188 __ addi(itable_entry_addr, itable_entry_addr, itable_offset_search_inc);
189 __ beq(CCR1, throw_icce);
190 __ bne(CCR0, search);
191
192 // Entry found and itable_entry_addr points to it, get offset of vtable for interface.
193
194 const Register vtable_offset = R12_scratch2;
195 const Register itable_method = R11_scratch1;
196
197 const int vtable_offset_offset = (itableOffsetEntry::offset_offset_in_bytes() -
198 itableOffsetEntry::interface_offset_in_bytes()) -
199 itable_offset_search_inc;
200 __ lwz(vtable_offset, vtable_offset_offset, itable_entry_addr);
201
202 // Compute itableMethodEntry and get methodOop and entry point for compiler.
203 const int method_offset = (itableMethodEntry::size() * wordSize * vtable_index) +
204 itableMethodEntry::method_offset_in_bytes();
205
206 __ add(itable_method, rcvr_klass, vtable_offset);
207 __ ld(R19_method, method_offset, itable_method);
208
209 #ifndef PRODUCT
210 if (DebugVtables) {
211 Label ok;
212 __ cmpd(CCR0, R19_method, 0);
213 __ bne(CCR0, ok);
214 __ stop("methodOop is null", 103);
215 __ bind(ok);
216 }
217 #endif
218
219 // If the vtable entry is null, the method is abstract.
220 address ame_addr = __ pc(); // ame = abstract method error
221
222 // Must do an explicit check if implicit checks are disabled.
223 assert(!MacroAssembler::needs_explicit_null_check(in_bytes(Method::from_compiled_offset())), "sanity");
224 if (!ImplicitNullChecks NOT_LINUX(|| true) /*!os::zero_page_read_protected()*/) {
225 if (TrapBasedNullChecks) {
226 __ trap_null_check(R19_method);
227 } else {
228 __ cmpdi(CCR0, R19_method, 0);
229 __ beq(CCR0, throw_icce);
230 }
231 }
232 __ ld(R12_scratch2, in_bytes(Method::from_compiled_offset()), R19_method);
233 __ mtctr(R12_scratch2);
234 __ bctr();
235
236 // Handle IncompatibleClassChangeError in itable stubs.
237 // More detailed error message.
238 // We force resolving of the call site by jumping to the "handle
239 // wrong method" stub, and so let the interpreter runtime do all the
240 // dirty work.
241 __ bind(throw_icce);
242 __ load_const(R11_scratch1, SharedRuntime::get_handle_wrong_method_stub());
243 __ mtctr(R11_scratch1);
244 __ bctr();
245
246 masm->flush();
247
248 guarantee(__ pc() <= s->code_end(), "overflowed buffer");
249
250 s->set_exception_points(npe_addr, ame_addr);
251 return s;
252 }
253
254 int VtableStub::pd_code_size_limit(bool is_vtable_stub) {
255 if (TraceJumps || DebugVtables || CountCompiledCalls || VerifyOops) {
256 return 1000;
257 } else {
258 if (is_vtable_stub) {
259 return 20 + 16 + 8; // Plain + (cOops & Traps) + safety
260 } else {
261 return 16 + 96;
262 }
263 }
264 }
265
266 int VtableStub::pd_code_alignment() {
267 const unsigned int icache_line_size = 32;
268 return icache_line_size;
269 }