Mercurial > hg > truffle
annotate src/share/vm/interpreter/templateInterpreter.cpp @ 6862:8a5ea0a9ccc4
7127708: G1: change task num types from int to uint in concurrent mark
Summary: Change the type of various task num fields, parameters etc to unsigned and rename them to be more consistent with the other collectors. Code changes were also reviewed by Vitaly Davidovich.
Reviewed-by: johnc
Contributed-by: Kaushik Srenevasan <kaushik@twitter.com>
author | johnc |
---|---|
date | Sat, 06 Oct 2012 01:17:44 -0700 |
parents | da91efe96a93 |
children | a3e2f723f2a5 |
rev | line source |
---|---|
0 | 1 /* |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
2 * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. |
0 | 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 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1489
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1489
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1489
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "interpreter/interpreter.hpp" | |
27 #include "interpreter/interpreterGenerator.hpp" | |
28 #include "interpreter/interpreterRuntime.hpp" | |
29 #include "interpreter/templateTable.hpp" | |
0 | 30 |
31 #ifndef CC_INTERP | |
32 | |
33 # define __ _masm-> | |
34 | |
35 void TemplateInterpreter::initialize() { | |
36 if (_code != NULL) return; | |
37 // assertions | |
38 assert((int)Bytecodes::number_of_codes <= (int)DispatchTable::length, | |
39 "dispatch table too small"); | |
40 | |
41 AbstractInterpreter::initialize(); | |
42 | |
43 TemplateTable::initialize(); | |
44 | |
45 // generate interpreter | |
46 { ResourceMark rm; | |
47 TraceTime timer("Interpreter generation", TraceStartupTime); | |
48 int code_size = InterpreterCodeSize; | |
49 NOT_PRODUCT(code_size *= 4;) // debug uses extra interpreter code space | |
50 _code = new StubQueue(new InterpreterCodeletInterface, code_size, NULL, | |
51 "Interpreter"); | |
52 InterpreterGenerator g(_code); | |
53 if (PrintInterpreter) print(); | |
54 } | |
55 | |
56 // initialize dispatch table | |
57 _active_table = _normal_table; | |
58 } | |
59 | |
60 //------------------------------------------------------------------------------------------------------------------------ | |
61 // Implementation of EntryPoint | |
62 | |
63 EntryPoint::EntryPoint() { | |
64 assert(number_of_states == 9, "check the code below"); | |
65 _entry[btos] = NULL; | |
66 _entry[ctos] = NULL; | |
67 _entry[stos] = NULL; | |
68 _entry[atos] = NULL; | |
69 _entry[itos] = NULL; | |
70 _entry[ltos] = NULL; | |
71 _entry[ftos] = NULL; | |
72 _entry[dtos] = NULL; | |
73 _entry[vtos] = NULL; | |
74 } | |
75 | |
76 | |
77 EntryPoint::EntryPoint(address bentry, address centry, address sentry, address aentry, address ientry, address lentry, address fentry, address dentry, address ventry) { | |
78 assert(number_of_states == 9, "check the code below"); | |
79 _entry[btos] = bentry; | |
80 _entry[ctos] = centry; | |
81 _entry[stos] = sentry; | |
82 _entry[atos] = aentry; | |
83 _entry[itos] = ientry; | |
84 _entry[ltos] = lentry; | |
85 _entry[ftos] = fentry; | |
86 _entry[dtos] = dentry; | |
87 _entry[vtos] = ventry; | |
88 } | |
89 | |
90 | |
91 void EntryPoint::set_entry(TosState state, address entry) { | |
92 assert(0 <= state && state < number_of_states, "state out of bounds"); | |
93 _entry[state] = entry; | |
94 } | |
95 | |
96 | |
97 address EntryPoint::entry(TosState state) const { | |
98 assert(0 <= state && state < number_of_states, "state out of bounds"); | |
99 return _entry[state]; | |
100 } | |
101 | |
102 | |
103 void EntryPoint::print() { | |
104 tty->print("["); | |
105 for (int i = 0; i < number_of_states; i++) { | |
106 if (i > 0) tty->print(", "); | |
107 tty->print(INTPTR_FORMAT, _entry[i]); | |
108 } | |
109 tty->print("]"); | |
110 } | |
111 | |
112 | |
113 bool EntryPoint::operator == (const EntryPoint& y) { | |
114 int i = number_of_states; | |
115 while (i-- > 0) { | |
116 if (_entry[i] != y._entry[i]) return false; | |
117 } | |
118 return true; | |
119 } | |
120 | |
121 | |
122 //------------------------------------------------------------------------------------------------------------------------ | |
123 // Implementation of DispatchTable | |
124 | |
125 EntryPoint DispatchTable::entry(int i) const { | |
126 assert(0 <= i && i < length, "index out of bounds"); | |
127 return | |
128 EntryPoint( | |
129 _table[btos][i], | |
130 _table[ctos][i], | |
131 _table[stos][i], | |
132 _table[atos][i], | |
133 _table[itos][i], | |
134 _table[ltos][i], | |
135 _table[ftos][i], | |
136 _table[dtos][i], | |
137 _table[vtos][i] | |
138 ); | |
139 } | |
140 | |
141 | |
142 void DispatchTable::set_entry(int i, EntryPoint& entry) { | |
143 assert(0 <= i && i < length, "index out of bounds"); | |
144 assert(number_of_states == 9, "check the code below"); | |
145 _table[btos][i] = entry.entry(btos); | |
146 _table[ctos][i] = entry.entry(ctos); | |
147 _table[stos][i] = entry.entry(stos); | |
148 _table[atos][i] = entry.entry(atos); | |
149 _table[itos][i] = entry.entry(itos); | |
150 _table[ltos][i] = entry.entry(ltos); | |
151 _table[ftos][i] = entry.entry(ftos); | |
152 _table[dtos][i] = entry.entry(dtos); | |
153 _table[vtos][i] = entry.entry(vtos); | |
154 } | |
155 | |
156 | |
157 bool DispatchTable::operator == (DispatchTable& y) { | |
158 int i = length; | |
159 while (i-- > 0) { | |
160 EntryPoint t = y.entry(i); // for compiler compatibility (BugId 4150096) | |
161 if (!(entry(i) == t)) return false; | |
162 } | |
163 return true; | |
164 } | |
165 | |
166 address TemplateInterpreter::_remove_activation_entry = NULL; | |
167 address TemplateInterpreter::_remove_activation_preserving_args_entry = NULL; | |
168 | |
169 | |
170 address TemplateInterpreter::_throw_ArrayIndexOutOfBoundsException_entry = NULL; | |
171 address TemplateInterpreter::_throw_ArrayStoreException_entry = NULL; | |
172 address TemplateInterpreter::_throw_ArithmeticException_entry = NULL; | |
173 address TemplateInterpreter::_throw_ClassCastException_entry = NULL; | |
174 address TemplateInterpreter::_throw_NullPointerException_entry = NULL; | |
175 address TemplateInterpreter::_throw_StackOverflowError_entry = NULL; | |
176 address TemplateInterpreter::_throw_exception_entry = NULL; | |
177 | |
178 #ifndef PRODUCT | |
179 EntryPoint TemplateInterpreter::_trace_code; | |
180 #endif // !PRODUCT | |
181 EntryPoint TemplateInterpreter::_return_entry[TemplateInterpreter::number_of_return_entries]; | |
182 EntryPoint TemplateInterpreter::_earlyret_entry; | |
183 EntryPoint TemplateInterpreter::_deopt_entry [TemplateInterpreter::number_of_deopt_entries ]; | |
184 EntryPoint TemplateInterpreter::_continuation_entry; | |
185 EntryPoint TemplateInterpreter::_safept_entry; | |
186 | |
187 address TemplateInterpreter::_return_3_addrs_by_index[TemplateInterpreter::number_of_return_addrs]; | |
188 address TemplateInterpreter::_return_5_addrs_by_index[TemplateInterpreter::number_of_return_addrs]; | |
189 | |
190 DispatchTable TemplateInterpreter::_active_table; | |
191 DispatchTable TemplateInterpreter::_normal_table; | |
192 DispatchTable TemplateInterpreter::_safept_table; | |
193 address TemplateInterpreter::_wentry_point[DispatchTable::length]; | |
194 | |
195 TemplateInterpreterGenerator::TemplateInterpreterGenerator(StubQueue* _code): AbstractInterpreterGenerator(_code) { | |
196 _unimplemented_bytecode = NULL; | |
197 _illegal_bytecode_sequence = NULL; | |
198 } | |
199 | |
200 static const BasicType types[Interpreter::number_of_result_handlers] = { | |
201 T_BOOLEAN, | |
202 T_CHAR , | |
203 T_BYTE , | |
204 T_SHORT , | |
205 T_INT , | |
206 T_LONG , | |
207 T_VOID , | |
208 T_FLOAT , | |
209 T_DOUBLE , | |
210 T_OBJECT | |
211 }; | |
212 | |
213 void TemplateInterpreterGenerator::generate_all() { | |
214 AbstractInterpreterGenerator::generate_all(); | |
215 | |
216 { CodeletMark cm(_masm, "error exits"); | |
217 _unimplemented_bytecode = generate_error_exit("unimplemented bytecode"); | |
218 _illegal_bytecode_sequence = generate_error_exit("illegal bytecode sequence - method not verified"); | |
219 } | |
220 | |
221 #ifndef PRODUCT | |
222 if (TraceBytecodes) { | |
223 CodeletMark cm(_masm, "bytecode tracing support"); | |
224 Interpreter::_trace_code = | |
225 EntryPoint( | |
226 generate_trace_code(btos), | |
227 generate_trace_code(ctos), | |
228 generate_trace_code(stos), | |
229 generate_trace_code(atos), | |
230 generate_trace_code(itos), | |
231 generate_trace_code(ltos), | |
232 generate_trace_code(ftos), | |
233 generate_trace_code(dtos), | |
234 generate_trace_code(vtos) | |
235 ); | |
236 } | |
237 #endif // !PRODUCT | |
238 | |
239 { CodeletMark cm(_masm, "return entry points"); | |
240 for (int i = 0; i < Interpreter::number_of_return_entries; i++) { | |
241 Interpreter::_return_entry[i] = | |
242 EntryPoint( | |
243 generate_return_entry_for(itos, i), | |
244 generate_return_entry_for(itos, i), | |
245 generate_return_entry_for(itos, i), | |
246 generate_return_entry_for(atos, i), | |
247 generate_return_entry_for(itos, i), | |
248 generate_return_entry_for(ltos, i), | |
249 generate_return_entry_for(ftos, i), | |
250 generate_return_entry_for(dtos, i), | |
251 generate_return_entry_for(vtos, i) | |
252 ); | |
253 } | |
254 } | |
255 | |
256 { CodeletMark cm(_masm, "earlyret entry points"); | |
257 Interpreter::_earlyret_entry = | |
258 EntryPoint( | |
259 generate_earlyret_entry_for(btos), | |
260 generate_earlyret_entry_for(ctos), | |
261 generate_earlyret_entry_for(stos), | |
262 generate_earlyret_entry_for(atos), | |
263 generate_earlyret_entry_for(itos), | |
264 generate_earlyret_entry_for(ltos), | |
265 generate_earlyret_entry_for(ftos), | |
266 generate_earlyret_entry_for(dtos), | |
267 generate_earlyret_entry_for(vtos) | |
268 ); | |
269 } | |
270 | |
271 { CodeletMark cm(_masm, "deoptimization entry points"); | |
272 for (int i = 0; i < Interpreter::number_of_deopt_entries; i++) { | |
273 Interpreter::_deopt_entry[i] = | |
274 EntryPoint( | |
275 generate_deopt_entry_for(itos, i), | |
276 generate_deopt_entry_for(itos, i), | |
277 generate_deopt_entry_for(itos, i), | |
278 generate_deopt_entry_for(atos, i), | |
279 generate_deopt_entry_for(itos, i), | |
280 generate_deopt_entry_for(ltos, i), | |
281 generate_deopt_entry_for(ftos, i), | |
282 generate_deopt_entry_for(dtos, i), | |
283 generate_deopt_entry_for(vtos, i) | |
284 ); | |
285 } | |
286 } | |
287 | |
288 { CodeletMark cm(_masm, "result handlers for native calls"); | |
289 // The various result converter stublets. | |
290 int is_generated[Interpreter::number_of_result_handlers]; | |
291 memset(is_generated, 0, sizeof(is_generated)); | |
292 | |
293 for (int i = 0; i < Interpreter::number_of_result_handlers; i++) { | |
294 BasicType type = types[i]; | |
295 if (!is_generated[Interpreter::BasicType_as_index(type)]++) { | |
296 Interpreter::_native_abi_to_tosca[Interpreter::BasicType_as_index(type)] = generate_result_handler_for(type); | |
297 } | |
298 } | |
299 } | |
300 | |
301 for (int j = 0; j < number_of_states; j++) { | |
302 const TosState states[] = {btos, ctos, stos, itos, ltos, ftos, dtos, atos, vtos}; | |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
303 int index = Interpreter::TosState_as_index(states[j]); |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
304 Interpreter::_return_3_addrs_by_index[index] = Interpreter::return_entry(states[j], 3); |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
305 Interpreter::_return_5_addrs_by_index[index] = Interpreter::return_entry(states[j], 5); |
0 | 306 } |
307 | |
308 { CodeletMark cm(_masm, "continuation entry points"); | |
309 Interpreter::_continuation_entry = | |
310 EntryPoint( | |
311 generate_continuation_for(btos), | |
312 generate_continuation_for(ctos), | |
313 generate_continuation_for(stos), | |
314 generate_continuation_for(atos), | |
315 generate_continuation_for(itos), | |
316 generate_continuation_for(ltos), | |
317 generate_continuation_for(ftos), | |
318 generate_continuation_for(dtos), | |
319 generate_continuation_for(vtos) | |
320 ); | |
321 } | |
322 | |
323 { CodeletMark cm(_masm, "safepoint entry points"); | |
324 Interpreter::_safept_entry = | |
325 EntryPoint( | |
326 generate_safept_entry_for(btos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), | |
327 generate_safept_entry_for(ctos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), | |
328 generate_safept_entry_for(stos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), | |
329 generate_safept_entry_for(atos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), | |
330 generate_safept_entry_for(itos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), | |
331 generate_safept_entry_for(ltos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), | |
332 generate_safept_entry_for(ftos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), | |
333 generate_safept_entry_for(dtos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), | |
334 generate_safept_entry_for(vtos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)) | |
335 ); | |
336 } | |
337 | |
338 { CodeletMark cm(_masm, "exception handling"); | |
339 // (Note: this is not safepoint safe because thread may return to compiled code) | |
340 generate_throw_exception(); | |
341 } | |
342 | |
343 { CodeletMark cm(_masm, "throw exception entrypoints"); | |
344 Interpreter::_throw_ArrayIndexOutOfBoundsException_entry = generate_ArrayIndexOutOfBounds_handler("java/lang/ArrayIndexOutOfBoundsException"); | |
345 Interpreter::_throw_ArrayStoreException_entry = generate_klass_exception_handler("java/lang/ArrayStoreException" ); | |
346 Interpreter::_throw_ArithmeticException_entry = generate_exception_handler("java/lang/ArithmeticException" , "/ by zero"); | |
347 Interpreter::_throw_ClassCastException_entry = generate_ClassCastException_handler(); | |
348 Interpreter::_throw_NullPointerException_entry = generate_exception_handler("java/lang/NullPointerException" , NULL ); | |
349 Interpreter::_throw_StackOverflowError_entry = generate_StackOverflowError_handler(); | |
350 } | |
351 | |
352 | |
353 | |
354 #define method_entry(kind) \ | |
355 { CodeletMark cm(_masm, "method entry point (kind = " #kind ")"); \ | |
356 Interpreter::_entry_table[Interpreter::kind] = generate_method_entry(Interpreter::kind); \ | |
357 } | |
358 | |
359 // all non-native method kinds | |
360 method_entry(zerolocals) | |
361 method_entry(zerolocals_synchronized) | |
362 method_entry(empty) | |
363 method_entry(accessor) | |
364 method_entry(abstract) | |
365 method_entry(java_lang_math_sin ) | |
366 method_entry(java_lang_math_cos ) | |
367 method_entry(java_lang_math_tan ) | |
368 method_entry(java_lang_math_abs ) | |
369 method_entry(java_lang_math_sqrt ) | |
370 method_entry(java_lang_math_log ) | |
371 method_entry(java_lang_math_log10) | |
6084
6759698e3140
7133857: exp() and pow() should use the x87 ISA on x86
roland
parents:
3781
diff
changeset
|
372 method_entry(java_lang_math_exp ) |
6759698e3140
7133857: exp() and pow() should use the x87 ISA on x86
roland
parents:
3781
diff
changeset
|
373 method_entry(java_lang_math_pow ) |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2142
diff
changeset
|
374 method_entry(java_lang_ref_reference_get) |
0 | 375 |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6084
diff
changeset
|
376 // method handle entry kinds are generated later in MethodHandlesAdapterGenerator::generate: |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6084
diff
changeset
|
377 for (int i = Interpreter::method_handle_invoke_FIRST; i <= Interpreter::method_handle_invoke_LAST; i++) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6084
diff
changeset
|
378 Interpreter::MethodKind kind = (Interpreter::MethodKind) i; |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6084
diff
changeset
|
379 Interpreter::_entry_table[kind] = Interpreter::_entry_table[Interpreter::abstract]; |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6084
diff
changeset
|
380 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6084
diff
changeset
|
381 |
0 | 382 // all native method kinds (must be one contiguous block) |
383 Interpreter::_native_entry_begin = Interpreter::code()->code_end(); | |
384 method_entry(native) | |
385 method_entry(native_synchronized) | |
386 Interpreter::_native_entry_end = Interpreter::code()->code_end(); | |
387 | |
388 #undef method_entry | |
389 | |
390 // Bytecodes | |
391 set_entry_points_for_all_bytes(); | |
392 set_safepoints_for_all_bytes(); | |
393 } | |
394 | |
395 //------------------------------------------------------------------------------------------------------------------------ | |
396 | |
397 address TemplateInterpreterGenerator::generate_error_exit(const char* msg) { | |
398 address entry = __ pc(); | |
399 __ stop(msg); | |
400 return entry; | |
401 } | |
402 | |
403 | |
404 //------------------------------------------------------------------------------------------------------------------------ | |
405 | |
406 void TemplateInterpreterGenerator::set_entry_points_for_all_bytes() { | |
407 for (int i = 0; i < DispatchTable::length; i++) { | |
408 Bytecodes::Code code = (Bytecodes::Code)i; | |
409 if (Bytecodes::is_defined(code)) { | |
410 set_entry_points(code); | |
411 } else { | |
412 set_unimplemented(i); | |
413 } | |
414 } | |
415 } | |
416 | |
417 | |
418 void TemplateInterpreterGenerator::set_safepoints_for_all_bytes() { | |
419 for (int i = 0; i < DispatchTable::length; i++) { | |
420 Bytecodes::Code code = (Bytecodes::Code)i; | |
421 if (Bytecodes::is_defined(code)) Interpreter::_safept_table.set_entry(code, Interpreter::_safept_entry); | |
422 } | |
423 } | |
424 | |
425 | |
426 void TemplateInterpreterGenerator::set_unimplemented(int i) { | |
427 address e = _unimplemented_bytecode; | |
428 EntryPoint entry(e, e, e, e, e, e, e, e, e); | |
429 Interpreter::_normal_table.set_entry(i, entry); | |
430 Interpreter::_wentry_point[i] = _unimplemented_bytecode; | |
431 } | |
432 | |
433 | |
434 void TemplateInterpreterGenerator::set_entry_points(Bytecodes::Code code) { | |
435 CodeletMark cm(_masm, Bytecodes::name(code), code); | |
436 // initialize entry points | |
437 assert(_unimplemented_bytecode != NULL, "should have been generated before"); | |
438 assert(_illegal_bytecode_sequence != NULL, "should have been generated before"); | |
439 address bep = _illegal_bytecode_sequence; | |
440 address cep = _illegal_bytecode_sequence; | |
441 address sep = _illegal_bytecode_sequence; | |
442 address aep = _illegal_bytecode_sequence; | |
443 address iep = _illegal_bytecode_sequence; | |
444 address lep = _illegal_bytecode_sequence; | |
445 address fep = _illegal_bytecode_sequence; | |
446 address dep = _illegal_bytecode_sequence; | |
447 address vep = _unimplemented_bytecode; | |
448 address wep = _unimplemented_bytecode; | |
449 // code for short & wide version of bytecode | |
450 if (Bytecodes::is_defined(code)) { | |
451 Template* t = TemplateTable::template_for(code); | |
452 assert(t->is_valid(), "just checking"); | |
453 set_short_entry_points(t, bep, cep, sep, aep, iep, lep, fep, dep, vep); | |
454 } | |
455 if (Bytecodes::wide_is_defined(code)) { | |
456 Template* t = TemplateTable::template_for_wide(code); | |
457 assert(t->is_valid(), "just checking"); | |
458 set_wide_entry_point(t, wep); | |
459 } | |
460 // set entry points | |
461 EntryPoint entry(bep, cep, sep, aep, iep, lep, fep, dep, vep); | |
462 Interpreter::_normal_table.set_entry(code, entry); | |
463 Interpreter::_wentry_point[code] = wep; | |
464 } | |
465 | |
466 | |
467 void TemplateInterpreterGenerator::set_wide_entry_point(Template* t, address& wep) { | |
468 assert(t->is_valid(), "template must exist"); | |
1489
cff162798819
6888953: some calls to function-like macros are missing semicolons
jcoomes
parents:
1071
diff
changeset
|
469 assert(t->tos_in() == vtos, "only vtos tos_in supported for wide instructions"); |
0 | 470 wep = __ pc(); generate_and_dispatch(t); |
471 } | |
472 | |
473 | |
474 void TemplateInterpreterGenerator::set_short_entry_points(Template* t, address& bep, address& cep, address& sep, address& aep, address& iep, address& lep, address& fep, address& dep, address& vep) { | |
475 assert(t->is_valid(), "template must exist"); | |
476 switch (t->tos_in()) { | |
1071
b18963243361
6902000: use ShouldNotReachHere() for btos/ctos/stos in TemplateInterpreterGenerator::set_short_entry_points
twisti
parents:
1059
diff
changeset
|
477 case btos: |
b18963243361
6902000: use ShouldNotReachHere() for btos/ctos/stos in TemplateInterpreterGenerator::set_short_entry_points
twisti
parents:
1059
diff
changeset
|
478 case ctos: |
b18963243361
6902000: use ShouldNotReachHere() for btos/ctos/stos in TemplateInterpreterGenerator::set_short_entry_points
twisti
parents:
1059
diff
changeset
|
479 case stos: |
b18963243361
6902000: use ShouldNotReachHere() for btos/ctos/stos in TemplateInterpreterGenerator::set_short_entry_points
twisti
parents:
1059
diff
changeset
|
480 ShouldNotReachHere(); // btos/ctos/stos should use itos. |
b18963243361
6902000: use ShouldNotReachHere() for btos/ctos/stos in TemplateInterpreterGenerator::set_short_entry_points
twisti
parents:
1059
diff
changeset
|
481 break; |
0 | 482 case atos: vep = __ pc(); __ pop(atos); aep = __ pc(); generate_and_dispatch(t); break; |
483 case itos: vep = __ pc(); __ pop(itos); iep = __ pc(); generate_and_dispatch(t); break; | |
484 case ltos: vep = __ pc(); __ pop(ltos); lep = __ pc(); generate_and_dispatch(t); break; | |
485 case ftos: vep = __ pc(); __ pop(ftos); fep = __ pc(); generate_and_dispatch(t); break; | |
486 case dtos: vep = __ pc(); __ pop(dtos); dep = __ pc(); generate_and_dispatch(t); break; | |
487 case vtos: set_vtos_entry_points(t, bep, cep, sep, aep, iep, lep, fep, dep, vep); break; | |
488 default : ShouldNotReachHere(); break; | |
489 } | |
490 } | |
491 | |
492 | |
493 //------------------------------------------------------------------------------------------------------------------------ | |
494 | |
495 void TemplateInterpreterGenerator::generate_and_dispatch(Template* t, TosState tos_out) { | |
496 if (PrintBytecodeHistogram) histogram_bytecode(t); | |
497 #ifndef PRODUCT | |
498 // debugging code | |
499 if (CountBytecodes || TraceBytecodes || StopInterpreterAt > 0) count_bytecode(); | |
500 if (PrintBytecodePairHistogram) histogram_bytecode_pair(t); | |
501 if (TraceBytecodes) trace_bytecode(t); | |
502 if (StopInterpreterAt > 0) stop_interpreter_at(); | |
503 __ verify_FPU(1, t->tos_in()); | |
504 #endif // !PRODUCT | |
505 int step; | |
506 if (!t->does_dispatch()) { | |
507 step = t->is_wide() ? Bytecodes::wide_length_for(t->bytecode()) : Bytecodes::length_for(t->bytecode()); | |
508 if (tos_out == ilgl) tos_out = t->tos_out(); | |
509 // compute bytecode size | |
510 assert(step > 0, "just checkin'"); | |
511 // setup stuff for dispatching next bytecode | |
512 if (ProfileInterpreter && VerifyDataPointer | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
513 && MethodData::bytecode_has_profile(t->bytecode())) { |
0 | 514 __ verify_method_data_pointer(); |
515 } | |
516 __ dispatch_prolog(tos_out, step); | |
517 } | |
518 // generate template | |
519 t->generate(_masm); | |
520 // advance | |
521 if (t->does_dispatch()) { | |
522 #ifdef ASSERT | |
523 // make sure execution doesn't go beyond this point if code is broken | |
524 __ should_not_reach_here(); | |
525 #endif // ASSERT | |
526 } else { | |
527 // dispatch to next bytecode | |
528 __ dispatch_epilog(tos_out, step); | |
529 } | |
530 } | |
531 | |
532 //------------------------------------------------------------------------------------------------------------------------ | |
533 // Entry points | |
534 | |
535 address TemplateInterpreter::return_entry(TosState state, int length) { | |
536 guarantee(0 <= length && length < Interpreter::number_of_return_entries, "illegal length"); | |
537 return _return_entry[length].entry(state); | |
538 } | |
539 | |
540 | |
541 address TemplateInterpreter::deopt_entry(TosState state, int length) { | |
542 guarantee(0 <= length && length < Interpreter::number_of_deopt_entries, "illegal length"); | |
543 return _deopt_entry[length].entry(state); | |
544 } | |
545 | |
546 //------------------------------------------------------------------------------------------------------------------------ | |
547 // Suport for invokes | |
548 | |
549 int TemplateInterpreter::TosState_as_index(TosState state) { | |
550 assert( state < number_of_states , "Invalid state in TosState_as_index"); | |
551 assert(0 <= (int)state && (int)state < TemplateInterpreter::number_of_return_addrs, "index out of bounds"); | |
552 return (int)state; | |
553 } | |
554 | |
555 | |
556 //------------------------------------------------------------------------------------------------------------------------ | |
557 // Safepoint suppport | |
558 | |
559 static inline void copy_table(address* from, address* to, int size) { | |
560 // Copy non-overlapping tables. The copy has to occur word wise for MT safety. | |
561 while (size-- > 0) *to++ = *from++; | |
562 } | |
563 | |
564 void TemplateInterpreter::notice_safepoints() { | |
565 if (!_notice_safepoints) { | |
566 // switch to safepoint dispatch table | |
567 _notice_safepoints = true; | |
568 copy_table((address*)&_safept_table, (address*)&_active_table, sizeof(_active_table) / sizeof(address)); | |
569 } | |
570 } | |
571 | |
572 // switch from the dispatch table which notices safepoints back to the | |
573 // normal dispatch table. So that we can notice single stepping points, | |
574 // keep the safepoint dispatch table if we are single stepping in JVMTI. | |
575 // Note that the should_post_single_step test is exactly as fast as the | |
576 // JvmtiExport::_enabled test and covers both cases. | |
577 void TemplateInterpreter::ignore_safepoints() { | |
578 if (_notice_safepoints) { | |
579 if (!JvmtiExport::should_post_single_step()) { | |
580 // switch to normal dispatch table | |
581 _notice_safepoints = false; | |
582 copy_table((address*)&_normal_table, (address*)&_active_table, sizeof(_active_table) / sizeof(address)); | |
583 } | |
584 } | |
585 } | |
586 | |
900
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
726
diff
changeset
|
587 //------------------------------------------------------------------------------------------------------------------------ |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
726
diff
changeset
|
588 // Deoptimization support |
0 | 589 |
900
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
726
diff
changeset
|
590 // If deoptimization happens, this function returns the point of next bytecode to continue execution |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
591 address TemplateInterpreter::deopt_continue_after_entry(Method* method, address bcp, int callee_parameters, bool is_top_frame) { |
900
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
726
diff
changeset
|
592 return AbstractInterpreter::deopt_continue_after_entry(method, bcp, callee_parameters, is_top_frame); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
726
diff
changeset
|
593 } |
0 | 594 |
900
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
726
diff
changeset
|
595 // If deoptimization happens, this function returns the point where the interpreter reexecutes |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
726
diff
changeset
|
596 // the bytecode. |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
726
diff
changeset
|
597 // Note: Bytecodes::_athrow (C1 only) and Bytecodes::_return are the special cases |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
726
diff
changeset
|
598 // that do not return "Interpreter::deopt_entry(vtos, 0)" |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
599 address TemplateInterpreter::deopt_reexecute_entry(Method* method, address bcp) { |
0 | 600 assert(method->contains(bcp), "just checkin'"); |
2142 | 601 Bytecodes::Code code = Bytecodes::java_code_at(method, bcp); |
0 | 602 if (code == Bytecodes::_return) { |
900
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
726
diff
changeset
|
603 // This is used for deopt during registration of finalizers |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
726
diff
changeset
|
604 // during Object.<init>. We simply need to resume execution at |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
726
diff
changeset
|
605 // the standard return vtos bytecode to pop the frame normally. |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
726
diff
changeset
|
606 // reexecuting the real bytecode would cause double registration |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
726
diff
changeset
|
607 // of the finalizable object. |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
726
diff
changeset
|
608 return _normal_table.entry(Bytecodes::_return).entry(vtos); |
0 | 609 } else { |
900
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
726
diff
changeset
|
610 return AbstractInterpreter::deopt_reexecute_entry(method, bcp); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
726
diff
changeset
|
611 } |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
726
diff
changeset
|
612 } |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
726
diff
changeset
|
613 |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
726
diff
changeset
|
614 // If deoptimization happens, the interpreter should reexecute this bytecode. |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
726
diff
changeset
|
615 // This function mainly helps the compilers to set up the reexecute bit. |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
726
diff
changeset
|
616 bool TemplateInterpreter::bytecode_should_reexecute(Bytecodes::Code code) { |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
726
diff
changeset
|
617 if (code == Bytecodes::_return) { |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
726
diff
changeset
|
618 //Yes, we consider Bytecodes::_return as a special case of reexecution |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
726
diff
changeset
|
619 return true; |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
726
diff
changeset
|
620 } else { |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
726
diff
changeset
|
621 return AbstractInterpreter::bytecode_should_reexecute(code); |
0 | 622 } |
623 } | |
624 | |
625 #endif // !CC_INTERP |