1 | /* |
2 | * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. |
3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 | * |
5 | * This code is free software; you can redistribute it and/or modify it |
6 | * under the terms of the GNU General Public License version 2 only, as |
7 | * published by the Free Software Foundation. |
8 | * |
9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
12 | * version 2 for more details (a copy is included in the LICENSE file that |
13 | * accompanied this code). |
14 | * |
15 | * You should have received a copy of the GNU General Public License version |
16 | * 2 along with this work; if not, write to the Free Software Foundation, |
17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
18 | * |
19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
20 | * or visit www.oracle.com if you need additional information or have any |
21 | * questions. |
22 | * |
23 | */ |
24 | |
25 | #include "precompiled.hpp" |
26 | #include "asm/macroAssembler.hpp" |
27 | #include "code/vtableStubs.hpp" |
28 | #include "interp_masm_x86.hpp" |
29 | #include "memory/resourceArea.hpp" |
30 | #include "oops/compiledICHolder.hpp" |
31 | #include "oops/instanceKlass.hpp" |
32 | #include "oops/klassVtable.hpp" |
33 | #include "runtime/sharedRuntime.hpp" |
34 | #include "vmreg_x86.inline.hpp" |
35 | #ifdef COMPILER2 |
36 | #include "opto/runtime.hpp" |
37 | #endif |
38 | |
39 | // machine-dependent part of VtableStubs: create VtableStub of correct size and |
40 | // initialize its code |
41 | |
42 | #define __ masm-> |
43 | |
44 | #ifndef PRODUCT |
45 | extern "C" void bad_compiled_vtable_index(JavaThread* thread, oop receiver, int index); |
46 | #endif |
47 | |
48 | VtableStub* VtableStubs::create_vtable_stub(int vtable_index) { |
49 | // Read "A word on VtableStub sizing" in share/code/vtableStubs.hpp for details on stub sizing. |
50 | const int stub_code_length = code_size_limit(true); |
51 | VtableStub* s = new(stub_code_length) VtableStub(true, vtable_index); |
52 | // Can be NULL if there is no free space in the code cache. |
53 | if (s == NULL) { |
54 | return NULL; |
55 | } |
56 | |
57 | // Count unused bytes in instruction sequences of variable size. |
58 | // We add them to the computed buffer size in order to avoid |
59 | // overflow in subsequently generated stubs. |
60 | address start_pc; |
61 | int slop_bytes = 0; |
62 | int slop_delta = 0; |
63 | // No variance was detected in vtable stub sizes. Setting index_dependent_slop == 0 will unveil any deviation from this observation. |
64 | const int index_dependent_slop = 0; |
65 | |
66 | ResourceMark rm; |
67 | CodeBuffer cb(s->entry_point(), stub_code_length); |
68 | MacroAssembler* masm = new MacroAssembler(&cb); |
69 | |
70 | #if (!defined(PRODUCT) && defined(COMPILER2)) |
71 | if (CountCompiledCalls) { |
72 | __ incrementl(ExternalAddress((address) SharedRuntime::nof_megamorphic_calls_addr())); |
73 | } |
74 | #endif |
75 | |
76 | // get receiver (need to skip return address on top of stack) |
77 | assert(VtableStub::receiver_location() == j_rarg0->as_VMReg(), "receiver expected in j_rarg0" ); |
78 | |
79 | // Free registers (non-args) are rax, rbx |
80 | |
81 | // get receiver klass |
82 | address npe_addr = __ pc(); |
83 | __ load_klass(rax, j_rarg0); |
84 | |
85 | #ifndef PRODUCT |
86 | if (DebugVtables) { |
87 | Label L; |
88 | start_pc = __ pc(); |
89 | // check offset vs vtable length |
90 | __ cmpl(Address(rax, Klass::vtable_length_offset()), vtable_index*vtableEntry::size()); |
91 | slop_delta = 12 - (__ pc() - start_pc); // cmpl varies in length, depending on data |
92 | slop_bytes += slop_delta; |
93 | assert(slop_delta >= 0, "negative slop(%d) encountered, adjust code size estimate!" , slop_delta); |
94 | |
95 | __ jcc(Assembler::greater, L); |
96 | __ movl(rbx, vtable_index); |
97 | // VTABLE TODO: find upper bound for call_VM length. |
98 | start_pc = __ pc(); |
99 | __ call_VM(noreg, CAST_FROM_FN_PTR(address, bad_compiled_vtable_index), j_rarg0, rbx); |
100 | slop_delta = 480 - (__ pc() - start_pc); |
101 | slop_bytes += slop_delta; |
102 | assert(slop_delta >= 0, "negative slop(%d) encountered, adjust code size estimate!" , slop_delta); |
103 | __ bind(L); |
104 | } |
105 | #endif // PRODUCT |
106 | |
107 | const Register method = rbx; |
108 | |
109 | // load Method* and target address |
110 | start_pc = __ pc(); |
111 | __ lookup_virtual_method(rax, vtable_index, method); |
112 | slop_delta = 8 - (int)(__ pc() - start_pc); |
113 | slop_bytes += slop_delta; |
114 | assert(slop_delta >= 0, "negative slop(%d) encountered, adjust code size estimate!" , slop_delta); |
115 | |
116 | #ifndef PRODUCT |
117 | if (DebugVtables) { |
118 | Label L; |
119 | __ cmpptr(method, (int32_t)NULL_WORD); |
120 | __ jcc(Assembler::equal, L); |
121 | __ cmpptr(Address(method, Method::from_compiled_offset()), (int32_t)NULL_WORD); |
122 | __ jcc(Assembler::notZero, L); |
123 | __ stop("Vtable entry is NULL" ); |
124 | __ bind(L); |
125 | } |
126 | #endif // PRODUCT |
127 | |
128 | // rax: receiver klass |
129 | // method (rbx): Method* |
130 | // rcx: receiver |
131 | address ame_addr = __ pc(); |
132 | __ jmp( Address(rbx, Method::from_compiled_offset())); |
133 | |
134 | masm->flush(); |
135 | slop_bytes += index_dependent_slop; // add'l slop for size variance due to large itable offsets |
136 | bookkeeping(masm, tty, s, npe_addr, ame_addr, true, vtable_index, slop_bytes, index_dependent_slop); |
137 | |
138 | return s; |
139 | } |
140 | |
141 | |
142 | VtableStub* VtableStubs::create_itable_stub(int itable_index) { |
143 | // Read "A word on VtableStub sizing" in share/code/vtableStubs.hpp for details on stub sizing. |
144 | const int stub_code_length = code_size_limit(false); |
145 | VtableStub* s = new(stub_code_length) VtableStub(false, itable_index); |
146 | // Can be NULL if there is no free space in the code cache. |
147 | if (s == NULL) { |
148 | return NULL; |
149 | } |
150 | // Count unused bytes in instruction sequences of variable size. |
151 | // We add them to the computed buffer size in order to avoid |
152 | // overflow in subsequently generated stubs. |
153 | address start_pc; |
154 | int slop_bytes = 0; |
155 | int slop_delta = 0; |
156 | const int index_dependent_slop = (itable_index == 0) ? 4 : // code size change with transition from 8-bit to 32-bit constant (@index == 16). |
157 | (itable_index < 16) ? 3 : 0; // index == 0 generates even shorter code. |
158 | |
159 | ResourceMark rm; |
160 | CodeBuffer cb(s->entry_point(), stub_code_length); |
161 | MacroAssembler *masm = new MacroAssembler(&cb); |
162 | |
163 | #if (!defined(PRODUCT) && defined(COMPILER2)) |
164 | if (CountCompiledCalls) { |
165 | __ incrementl(ExternalAddress((address) SharedRuntime::nof_megamorphic_calls_addr())); |
166 | } |
167 | #endif // PRODUCT |
168 | |
169 | // Entry arguments: |
170 | // rax: CompiledICHolder |
171 | // j_rarg0: Receiver |
172 | |
173 | // Most registers are in use; we'll use rax, rbx, r10, r11 |
174 | // (various calling sequences use r[cd]x, r[sd]i, r[89]; stay away from them) |
175 | const Register recv_klass_reg = r10; |
176 | const Register holder_klass_reg = rax; // declaring interface klass (DECC) |
177 | const Register resolved_klass_reg = rbx; // resolved interface klass (REFC) |
178 | const Register temp_reg = r11; |
179 | |
180 | const Register icholder_reg = rax; |
181 | __ movptr(resolved_klass_reg, Address(icholder_reg, CompiledICHolder::holder_klass_offset())); |
182 | __ movptr(holder_klass_reg, Address(icholder_reg, CompiledICHolder::holder_metadata_offset())); |
183 | |
184 | Label L_no_such_interface; |
185 | |
186 | // get receiver klass (also an implicit null-check) |
187 | assert(VtableStub::receiver_location() == j_rarg0->as_VMReg(), "receiver expected in j_rarg0" ); |
188 | address npe_addr = __ pc(); |
189 | __ load_klass(recv_klass_reg, j_rarg0); |
190 | |
191 | start_pc = __ pc(); |
192 | |
193 | // Receiver subtype check against REFC. |
194 | // Destroys recv_klass_reg value. |
195 | __ lookup_interface_method(// inputs: rec. class, interface |
196 | recv_klass_reg, resolved_klass_reg, noreg, |
197 | // outputs: scan temp. reg1, scan temp. reg2 |
198 | recv_klass_reg, temp_reg, |
199 | L_no_such_interface, |
200 | /*return_method=*/false); |
201 | |
202 | const ptrdiff_t typecheckSize = __ pc() - start_pc; |
203 | start_pc = __ pc(); |
204 | |
205 | // Get selected method from declaring class and itable index |
206 | const Register method = rbx; |
207 | __ load_klass(recv_klass_reg, j_rarg0); // restore recv_klass_reg |
208 | __ lookup_interface_method(// inputs: rec. class, interface, itable index |
209 | recv_klass_reg, holder_klass_reg, itable_index, |
210 | // outputs: method, scan temp. reg |
211 | method, temp_reg, |
212 | L_no_such_interface); |
213 | |
214 | const ptrdiff_t lookupSize = __ pc() - start_pc; |
215 | |
216 | // We expect we need index_dependent_slop extra bytes. Reason: |
217 | // The emitted code in lookup_interface_method changes when itable_index exceeds 15. |
218 | // For linux, a very narrow estimate would be 112, but Solaris requires some more space (130). |
219 | const ptrdiff_t estimate = 136; |
220 | const ptrdiff_t codesize = typecheckSize + lookupSize + index_dependent_slop; |
221 | slop_delta = (int)(estimate - codesize); |
222 | slop_bytes += slop_delta; |
223 | assert(slop_delta >= 0, "itable #%d: Code size estimate (%d) for lookup_interface_method too small, required: %d" , itable_index, (int)estimate, (int)codesize); |
224 | |
225 | // If we take a trap while this arg is on the stack we will not |
226 | // be able to walk the stack properly. This is not an issue except |
227 | // when there are mistakes in this assembly code that could generate |
228 | // a spurious fault. Ask me how I know... |
229 | |
230 | // method (rbx): Method* |
231 | // j_rarg0: receiver |
232 | |
233 | #ifdef ASSERT |
234 | if (DebugVtables) { |
235 | Label L2; |
236 | __ cmpptr(method, (int32_t)NULL_WORD); |
237 | __ jcc(Assembler::equal, L2); |
238 | __ cmpptr(Address(method, Method::from_compiled_offset()), (int32_t)NULL_WORD); |
239 | __ jcc(Assembler::notZero, L2); |
240 | __ stop("compiler entrypoint is null" ); |
241 | __ bind(L2); |
242 | } |
243 | #endif // ASSERT |
244 | |
245 | address ame_addr = __ pc(); |
246 | __ jmp(Address(method, Method::from_compiled_offset())); |
247 | |
248 | __ bind(L_no_such_interface); |
249 | // Handle IncompatibleClassChangeError in itable stubs. |
250 | // More detailed error message. |
251 | // We force resolving of the call site by jumping to the "handle |
252 | // wrong method" stub, and so let the interpreter runtime do all the |
253 | // dirty work. |
254 | __ jump(RuntimeAddress(SharedRuntime::get_handle_wrong_method_stub())); |
255 | |
256 | masm->flush(); |
257 | slop_bytes += index_dependent_slop; // add'l slop for size variance due to large itable offsets |
258 | bookkeeping(masm, tty, s, npe_addr, ame_addr, false, itable_index, slop_bytes, index_dependent_slop); |
259 | |
260 | return s; |
261 | } |
262 | |
263 | int VtableStub::pd_code_alignment() { |
264 | // x86 cache line size is 64 bytes, but we want to limit alignment loss. |
265 | const unsigned int icache_line_size = wordSize; |
266 | return icache_line_size; |
267 | } |
268 | |