28 #include "code/vtableStubs.hpp"
29 #include "interp_masm_x86.hpp"
30 #include "memory/resourceArea.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 == nullptr) {
54 return nullptr;
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 __ incrementq(ExternalAddress(SharedRuntime::nof_megamorphic_calls_addr()), rscratch1);
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, rscratch1);
84
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, NULL_WORD);
120 __ jcc(Assembler::equal, L);
121 __ cmpptr(Address(method, Method::from_compiled_offset()), 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 == nullptr) {
148 return nullptr;
149 }
150
151 // Count unused bytes in instruction sequences of variable size.
152 // We add them to the computed buffer size in order to avoid
153 // overflow in subsequently generated stubs.
154 address start_pc;
155 int slop_bytes = 0;
156 int slop_delta = 0;
157 const int index_dependent_slop = (itable_index == 0) ? 4 : // code size change with transition from 8-bit to 32-bit constant (@index == 16).
158 (itable_index < 16) ? 3 : 0; // index == 0 generates even shorter code.
159
160 ResourceMark rm;
161 CodeBuffer cb(s->entry_point(), stub_code_length);
162 MacroAssembler *masm = new MacroAssembler(&cb);
163
164 #if (!defined(PRODUCT) && defined(COMPILER2))
165 if (CountCompiledCalls) {
166 __ incrementq(ExternalAddress(SharedRuntime::nof_megamorphic_calls_addr()), rscratch1);
193
194 start_pc = __ pc();
195
196 // Receiver subtype check against REFC.
197 // Get selected method from declaring class and itable index
198 __ lookup_interface_method_stub(recv_klass_reg, // input
199 holder_klass_reg, // input
200 resolved_klass_reg, // input
201 method, // output
202 temp_reg,
203 temp_reg2,
204 noreg,
205 itable_index,
206 L_no_such_interface);
207
208 const ptrdiff_t lookupSize = __ pc() - start_pc;
209
210 // We expect we need index_dependent_slop extra bytes. Reason:
211 // The emitted code in lookup_interface_method changes when itable_index exceeds 15.
212 // For linux, a very narrow estimate would be 112, but Solaris requires some more space (130).
213 const ptrdiff_t estimate = 136;
214 const ptrdiff_t codesize = lookupSize + index_dependent_slop;
215 slop_delta = (int)(estimate - codesize);
216 slop_bytes += slop_delta;
217 assert(slop_delta >= 0, "itable #%d: Code size estimate (%d) for lookup_interface_method too small, required: %d", itable_index, (int)estimate, (int)codesize);
218
219 // If we take a trap while this arg is on the stack we will not
220 // be able to walk the stack properly. This is not an issue except
221 // when there are mistakes in this assembly code that could generate
222 // a spurious fault. Ask me how I know...
223
224 // method (rbx): Method*
225 // j_rarg0: receiver
226
227 #ifdef ASSERT
228 if (DebugVtables) {
229 Label L2;
230 __ cmpptr(method, NULL_WORD);
231 __ jcc(Assembler::equal, L2);
232 __ cmpptr(Address(method, Method::from_compiled_offset()), NULL_WORD);
233 __ jcc(Assembler::notZero, L2);
234 __ stop("compiler entrypoint is null");
235 __ bind(L2);
236 }
237 #endif // ASSERT
238
239 address ame_addr = __ pc();
240 __ jmp(Address(method, Method::from_compiled_offset()));
241
242 __ bind(L_no_such_interface);
243 // Handle IncompatibleClassChangeError in itable stubs.
244 // More detailed error message.
245 // We force resolving of the call site by jumping to the "handle
246 // wrong method" stub, and so let the interpreter runtime do all the
247 // dirty work.
248 __ jump(RuntimeAddress(SharedRuntime::get_handle_wrong_method_stub()));
249
250 masm->flush();
251 slop_bytes += index_dependent_slop; // add'l slop for size variance due to large itable offsets
252 bookkeeping(masm, tty, s, npe_addr, ame_addr, false, itable_index, slop_bytes, index_dependent_slop);
253
254 return s;
255 }
256
257 int VtableStub::pd_code_alignment() {
258 // x86 cache line size is 64 bytes, but we want to limit alignment loss.
259 const unsigned int icache_line_size = wordSize;
260 return icache_line_size;
|
28 #include "code/vtableStubs.hpp"
29 #include "interp_masm_x86.hpp"
30 #include "memory/resourceArea.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, bool caller_is_c1) {
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, caller_is_c1);
52 // Can be nullptr if there is no free space in the code cache.
53 if (s == nullptr) {
54 return nullptr;
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 ByteSize entry_offset = caller_is_c1 ? Method::from_compiled_inline_offset() : Method::from_compiled_inline_ro_offset();
66
67 ResourceMark rm;
68 CodeBuffer cb(s->entry_point(), stub_code_length);
69 MacroAssembler* masm = new MacroAssembler(&cb);
70
71 #if (!defined(PRODUCT) && defined(COMPILER2))
72 if (CountCompiledCalls) {
73 __ incrementq(ExternalAddress(SharedRuntime::nof_megamorphic_calls_addr()), rscratch1);
74 }
75 #endif
76
77 // get receiver (need to skip return address on top of stack)
78 assert(VtableStub::receiver_location() == j_rarg0->as_VMReg(), "receiver expected in j_rarg0");
79
80 // Free registers (non-args) are rax, rbx
81
82 // get receiver klass
83 address npe_addr = __ pc();
84 __ load_klass(rax, j_rarg0, rscratch1);
85
102 slop_bytes += slop_delta;
103 assert(slop_delta >= 0, "negative slop(%d) encountered, adjust code size estimate!", slop_delta);
104 __ bind(L);
105 }
106 #endif // PRODUCT
107
108 const Register method = rbx;
109
110 // load Method* and target address
111 start_pc = __ pc();
112 __ lookup_virtual_method(rax, vtable_index, method);
113 slop_delta = 8 - (int)(__ pc() - start_pc);
114 slop_bytes += slop_delta;
115 assert(slop_delta >= 0, "negative slop(%d) encountered, adjust code size estimate!", slop_delta);
116
117 #ifndef PRODUCT
118 if (DebugVtables) {
119 Label L;
120 __ cmpptr(method, NULL_WORD);
121 __ jcc(Assembler::equal, L);
122 __ cmpptr(Address(method, entry_offset), NULL_WORD);
123 __ jcc(Assembler::notZero, L);
124 __ stop("Vtable entry is null");
125 __ bind(L);
126 }
127 #endif // PRODUCT
128
129 // rax: receiver klass
130 // method (rbx): Method*
131 // rcx: receiver
132 address ame_addr = __ pc();
133 __ jmp( Address(rbx, entry_offset));
134
135 masm->flush();
136 slop_bytes += index_dependent_slop; // add'l slop for size variance due to large itable offsets
137 bookkeeping(masm, tty, s, npe_addr, ame_addr, true, vtable_index, slop_bytes, index_dependent_slop);
138
139 return s;
140 }
141
142
143 VtableStub* VtableStubs::create_itable_stub(int itable_index, bool caller_is_c1) {
144 // Read "A word on VtableStub sizing" in share/code/vtableStubs.hpp for details on stub sizing.
145 const int stub_code_length = code_size_limit(false);
146 ByteSize entry_offset = caller_is_c1 ? Method::from_compiled_inline_offset() : Method::from_compiled_inline_ro_offset();
147 VtableStub* s = new(stub_code_length) VtableStub(false, itable_index, caller_is_c1);
148 // Can be nullptr if there is no free space in the code cache.
149 if (s == nullptr) {
150 return nullptr;
151 }
152
153 // Count unused bytes in instruction sequences of variable size.
154 // We add them to the computed buffer size in order to avoid
155 // overflow in subsequently generated stubs.
156 address start_pc;
157 int slop_bytes = 0;
158 int slop_delta = 0;
159 const int index_dependent_slop = (itable_index == 0) ? 4 : // code size change with transition from 8-bit to 32-bit constant (@index == 16).
160 (itable_index < 16) ? 3 : 0; // index == 0 generates even shorter code.
161
162 ResourceMark rm;
163 CodeBuffer cb(s->entry_point(), stub_code_length);
164 MacroAssembler *masm = new MacroAssembler(&cb);
165
166 #if (!defined(PRODUCT) && defined(COMPILER2))
167 if (CountCompiledCalls) {
168 __ incrementq(ExternalAddress(SharedRuntime::nof_megamorphic_calls_addr()), rscratch1);
195
196 start_pc = __ pc();
197
198 // Receiver subtype check against REFC.
199 // Get selected method from declaring class and itable index
200 __ lookup_interface_method_stub(recv_klass_reg, // input
201 holder_klass_reg, // input
202 resolved_klass_reg, // input
203 method, // output
204 temp_reg,
205 temp_reg2,
206 noreg,
207 itable_index,
208 L_no_such_interface);
209
210 const ptrdiff_t lookupSize = __ pc() - start_pc;
211
212 // We expect we need index_dependent_slop extra bytes. Reason:
213 // The emitted code in lookup_interface_method changes when itable_index exceeds 15.
214 // For linux, a very narrow estimate would be 112, but Solaris requires some more space (130).
215 const ptrdiff_t estimate = 144;
216 const ptrdiff_t codesize = lookupSize + index_dependent_slop;
217 slop_delta = (int)(estimate - codesize);
218 slop_bytes += slop_delta;
219 assert(slop_delta >= 0, "itable #%d: Code size estimate (%d) for lookup_interface_method too small, required: %d", itable_index, (int)estimate, (int)codesize);
220
221 // If we take a trap while this arg is on the stack we will not
222 // be able to walk the stack properly. This is not an issue except
223 // when there are mistakes in this assembly code that could generate
224 // a spurious fault. Ask me how I know...
225
226 // method (rbx): Method*
227 // j_rarg0: receiver
228
229 #ifdef ASSERT
230 if (DebugVtables) {
231 Label L2;
232 __ cmpptr(method, NULL_WORD);
233 __ jcc(Assembler::equal, L2);
234 __ cmpptr(Address(method, entry_offset), NULL_WORD);
235 __ jcc(Assembler::notZero, L2);
236 __ stop("compiler entrypoint is null");
237 __ bind(L2);
238 }
239 #endif // ASSERT
240
241 address ame_addr = __ pc();
242 __ jmp(Address(method, entry_offset));
243
244 __ bind(L_no_such_interface);
245 // Handle IncompatibleClassChangeError in itable stubs.
246 // More detailed error message.
247 // We force resolving of the call site by jumping to the "handle
248 // wrong method" stub, and so let the interpreter runtime do all the
249 // dirty work.
250 __ jump(RuntimeAddress(SharedRuntime::get_handle_wrong_method_stub()));
251
252 masm->flush();
253 slop_bytes += index_dependent_slop; // add'l slop for size variance due to large itable offsets
254 bookkeeping(masm, tty, s, npe_addr, ame_addr, false, itable_index, slop_bytes, index_dependent_slop);
255
256 return s;
257 }
258
259 int VtableStub::pd_code_alignment() {
260 // x86 cache line size is 64 bytes, but we want to limit alignment loss.
261 const unsigned int icache_line_size = wordSize;
262 return icache_line_size;
|