Mercurial > hg > truffle
annotate src/share/vm/interpreter/templateInterpreter.cpp @ 9126:bc26f978b0ce
HotSpotResolvedObjectType: implement hasFinalizeSubclass() correctly
don't use the (wrong) cached value, but ask the runtime on each request.
Fixes regression on xml.* benchmarks @ specjvm2008. The problem was:
After the constructor of Object was deoptimized due to an assumption violation,
it was recompiled again after some time. However, on recompilation, the value
of hasFinalizeSubclass for the class was not updated and it was compiled again
with a, now wrong, assumption, which then triggers deoptimization again.
This was repeated until it hit the recompilation limit (defined by
PerMethodRecompilationCutoff), and therefore only executed by the interpreter
from now on, causing the performance regression.
author | Bernhard Urban <bernhard.urban@jku.at> |
---|---|
date | Mon, 15 Apr 2013 19:54:58 +0200 |
parents | c6a1ffc707ff |
children | 6b0fd0964b87 |
rev | line source |
---|---|
7066 | 1 /* |
2 * Copyright (c) 1997, 2012, 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 "interpreter/interpreter.hpp" | |
27 #include "interpreter/interpreterGenerator.hpp" | |
28 #include "interpreter/interpreterRuntime.hpp" | |
29 #include "interpreter/templateTable.hpp" | |
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; | |
8328
6b6cbd8b8914
Support deoptimizing before the entry to a synchronized method.
Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
parents:
8151
diff
changeset
|
183 EntryPoint TemplateInterpreter::_deopt_entry[TemplateInterpreter::number_of_deopt_entries ]; |
7066 | 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( | |
8328
6b6cbd8b8914
Support deoptimizing before the entry to a synchronized method.
Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
parents:
8151
diff
changeset
|
275 ((InterpreterGenerator*)this)->generate_deopt_entry_for(itos, i), |
6b6cbd8b8914
Support deoptimizing before the entry to a synchronized method.
Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
parents:
8151
diff
changeset
|
276 ((InterpreterGenerator*)this)->generate_deopt_entry_for(itos, i), |
6b6cbd8b8914
Support deoptimizing before the entry to a synchronized method.
Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
parents:
8151
diff
changeset
|
277 ((InterpreterGenerator*)this)->generate_deopt_entry_for(itos, i), |
6b6cbd8b8914
Support deoptimizing before the entry to a synchronized method.
Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
parents:
8151
diff
changeset
|
278 ((InterpreterGenerator*)this)->generate_deopt_entry_for(atos, i), |
6b6cbd8b8914
Support deoptimizing before the entry to a synchronized method.
Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
parents:
8151
diff
changeset
|
279 ((InterpreterGenerator*)this)->generate_deopt_entry_for(itos, i), |
6b6cbd8b8914
Support deoptimizing before the entry to a synchronized method.
Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
parents:
8151
diff
changeset
|
280 ((InterpreterGenerator*)this)->generate_deopt_entry_for(ltos, i), |
6b6cbd8b8914
Support deoptimizing before the entry to a synchronized method.
Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
parents:
8151
diff
changeset
|
281 ((InterpreterGenerator*)this)->generate_deopt_entry_for(ftos, i), |
6b6cbd8b8914
Support deoptimizing before the entry to a synchronized method.
Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
parents:
8151
diff
changeset
|
282 ((InterpreterGenerator*)this)->generate_deopt_entry_for(dtos, i), |
6b6cbd8b8914
Support deoptimizing before the entry to a synchronized method.
Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
parents:
8151
diff
changeset
|
283 ((InterpreterGenerator*)this)->generate_deopt_entry_for(vtos, i) |
7066 | 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}; | |
303 int index = Interpreter::TosState_as_index(states[j]); | |
304 Interpreter::_return_3_addrs_by_index[index] = Interpreter::return_entry(states[j], 3); | |
305 Interpreter::_return_5_addrs_by_index[index] = Interpreter::return_entry(states[j], 5); | |
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) | |
9046
c6a1ffc707ff
Comments and #ifdef GRAAL for recent changes to C++ code for calling nmethods directly.
Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
parents:
9025
diff
changeset
|
363 #ifdef GRAAL |
9025
ff5a32117e02
Implement fast invocation of installed code (direct tail call to the target machine code address).
Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
parents:
8328
diff
changeset
|
364 method_entry(execute_compiled_method) |
9046
c6a1ffc707ff
Comments and #ifdef GRAAL for recent changes to C++ code for calling nmethods directly.
Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
parents:
9025
diff
changeset
|
365 #endif |
7066 | 366 method_entry(accessor) |
367 method_entry(abstract) | |
368 method_entry(java_lang_math_sin ) | |
369 method_entry(java_lang_math_cos ) | |
370 method_entry(java_lang_math_tan ) | |
371 method_entry(java_lang_math_abs ) | |
372 method_entry(java_lang_math_sqrt ) | |
373 method_entry(java_lang_math_log ) | |
374 method_entry(java_lang_math_log10) | |
375 method_entry(java_lang_math_exp ) | |
376 method_entry(java_lang_math_pow ) | |
377 method_entry(java_lang_ref_reference_get) | |
378 | |
379 initialize_method_handle_entries(); | |
380 | |
381 // all native method kinds (must be one contiguous block) | |
382 Interpreter::_native_entry_begin = Interpreter::code()->code_end(); | |
383 method_entry(native) | |
384 method_entry(native_synchronized) | |
385 Interpreter::_native_entry_end = Interpreter::code()->code_end(); | |
386 | |
387 #undef method_entry | |
388 | |
389 // Bytecodes | |
390 set_entry_points_for_all_bytes(); | |
391 set_safepoints_for_all_bytes(); | |
392 } | |
393 | |
394 //------------------------------------------------------------------------------------------------------------------------ | |
395 | |
396 address TemplateInterpreterGenerator::generate_error_exit(const char* msg) { | |
397 address entry = __ pc(); | |
398 __ stop(msg); | |
399 return entry; | |
400 } | |
401 | |
402 | |
403 //------------------------------------------------------------------------------------------------------------------------ | |
404 | |
405 void TemplateInterpreterGenerator::set_entry_points_for_all_bytes() { | |
406 for (int i = 0; i < DispatchTable::length; i++) { | |
407 Bytecodes::Code code = (Bytecodes::Code)i; | |
408 if (Bytecodes::is_defined(code)) { | |
409 set_entry_points(code); | |
410 } else { | |
411 set_unimplemented(i); | |
412 } | |
413 } | |
414 } | |
415 | |
416 | |
417 void TemplateInterpreterGenerator::set_safepoints_for_all_bytes() { | |
418 for (int i = 0; i < DispatchTable::length; i++) { | |
419 Bytecodes::Code code = (Bytecodes::Code)i; | |
420 if (Bytecodes::is_defined(code)) Interpreter::_safept_table.set_entry(code, Interpreter::_safept_entry); | |
421 } | |
422 } | |
423 | |
424 | |
425 void TemplateInterpreterGenerator::set_unimplemented(int i) { | |
426 address e = _unimplemented_bytecode; | |
427 EntryPoint entry(e, e, e, e, e, e, e, e, e); | |
428 Interpreter::_normal_table.set_entry(i, entry); | |
429 Interpreter::_wentry_point[i] = _unimplemented_bytecode; | |
430 } | |
431 | |
432 | |
433 void TemplateInterpreterGenerator::set_entry_points(Bytecodes::Code code) { | |
434 CodeletMark cm(_masm, Bytecodes::name(code), code); | |
435 // initialize entry points | |
436 assert(_unimplemented_bytecode != NULL, "should have been generated before"); | |
437 assert(_illegal_bytecode_sequence != NULL, "should have been generated before"); | |
438 address bep = _illegal_bytecode_sequence; | |
439 address cep = _illegal_bytecode_sequence; | |
440 address sep = _illegal_bytecode_sequence; | |
441 address aep = _illegal_bytecode_sequence; | |
442 address iep = _illegal_bytecode_sequence; | |
443 address lep = _illegal_bytecode_sequence; | |
444 address fep = _illegal_bytecode_sequence; | |
445 address dep = _illegal_bytecode_sequence; | |
446 address vep = _unimplemented_bytecode; | |
447 address wep = _unimplemented_bytecode; | |
448 // code for short & wide version of bytecode | |
449 if (Bytecodes::is_defined(code)) { | |
450 Template* t = TemplateTable::template_for(code); | |
451 assert(t->is_valid(), "just checking"); | |
452 set_short_entry_points(t, bep, cep, sep, aep, iep, lep, fep, dep, vep); | |
453 } | |
454 if (Bytecodes::wide_is_defined(code)) { | |
455 Template* t = TemplateTable::template_for_wide(code); | |
456 assert(t->is_valid(), "just checking"); | |
457 set_wide_entry_point(t, wep); | |
458 } | |
459 // set entry points | |
460 EntryPoint entry(bep, cep, sep, aep, iep, lep, fep, dep, vep); | |
461 Interpreter::_normal_table.set_entry(code, entry); | |
462 Interpreter::_wentry_point[code] = wep; | |
463 } | |
464 | |
465 | |
466 void TemplateInterpreterGenerator::set_wide_entry_point(Template* t, address& wep) { | |
467 assert(t->is_valid(), "template must exist"); | |
468 assert(t->tos_in() == vtos, "only vtos tos_in supported for wide instructions"); | |
469 wep = __ pc(); generate_and_dispatch(t); | |
470 } | |
471 | |
472 | |
473 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) { | |
474 assert(t->is_valid(), "template must exist"); | |
475 switch (t->tos_in()) { | |
476 case btos: | |
477 case ctos: | |
478 case stos: | |
479 ShouldNotReachHere(); // btos/ctos/stos should use itos. | |
480 break; | |
481 case atos: vep = __ pc(); __ pop(atos); aep = __ pc(); generate_and_dispatch(t); break; | |
482 case itos: vep = __ pc(); __ pop(itos); iep = __ pc(); generate_and_dispatch(t); break; | |
483 case ltos: vep = __ pc(); __ pop(ltos); lep = __ pc(); generate_and_dispatch(t); break; | |
484 case ftos: vep = __ pc(); __ pop(ftos); fep = __ pc(); generate_and_dispatch(t); break; | |
485 case dtos: vep = __ pc(); __ pop(dtos); dep = __ pc(); generate_and_dispatch(t); break; | |
486 case vtos: set_vtos_entry_points(t, bep, cep, sep, aep, iep, lep, fep, dep, vep); break; | |
487 default : ShouldNotReachHere(); break; | |
488 } | |
489 } | |
490 | |
491 | |
492 //------------------------------------------------------------------------------------------------------------------------ | |
493 | |
494 void TemplateInterpreterGenerator::generate_and_dispatch(Template* t, TosState tos_out) { | |
495 if (PrintBytecodeHistogram) histogram_bytecode(t); | |
496 #ifndef PRODUCT | |
497 // debugging code | |
498 if (CountBytecodes || TraceBytecodes || StopInterpreterAt > 0) count_bytecode(); | |
499 if (PrintBytecodePairHistogram) histogram_bytecode_pair(t); | |
500 if (TraceBytecodes) trace_bytecode(t); | |
501 if (StopInterpreterAt > 0) stop_interpreter_at(); | |
502 __ verify_FPU(1, t->tos_in()); | |
503 #endif // !PRODUCT | |
504 int step; | |
505 if (!t->does_dispatch()) { | |
506 step = t->is_wide() ? Bytecodes::wide_length_for(t->bytecode()) : Bytecodes::length_for(t->bytecode()); | |
507 if (tos_out == ilgl) tos_out = t->tos_out(); | |
508 // compute bytecode size | |
509 assert(step > 0, "just checkin'"); | |
510 // setup stuff for dispatching next bytecode | |
511 if (ProfileInterpreter && VerifyDataPointer | |
512 && MethodData::bytecode_has_profile(t->bytecode())) { | |
513 __ verify_method_data_pointer(); | |
514 } | |
515 __ dispatch_prolog(tos_out, step); | |
516 } | |
517 // generate template | |
518 t->generate(_masm); | |
519 // advance | |
520 if (t->does_dispatch()) { | |
521 #ifdef ASSERT | |
522 // make sure execution doesn't go beyond this point if code is broken | |
523 __ should_not_reach_here(); | |
524 #endif // ASSERT | |
525 } else { | |
526 // dispatch to next bytecode | |
527 __ dispatch_epilog(tos_out, step); | |
528 } | |
529 } | |
530 | |
531 //------------------------------------------------------------------------------------------------------------------------ | |
532 // Entry points | |
533 | |
534 address TemplateInterpreter::return_entry(TosState state, int length) { | |
535 guarantee(0 <= length && length < Interpreter::number_of_return_entries, "illegal length"); | |
536 return _return_entry[length].entry(state); | |
537 } | |
538 | |
539 | |
540 address TemplateInterpreter::deopt_entry(TosState state, int length) { | |
541 guarantee(0 <= length && length < Interpreter::number_of_deopt_entries, "illegal length"); | |
542 return _deopt_entry[length].entry(state); | |
543 } | |
544 | |
545 //------------------------------------------------------------------------------------------------------------------------ | |
546 // Suport for invokes | |
547 | |
548 int TemplateInterpreter::TosState_as_index(TosState state) { | |
549 assert( state < number_of_states , "Invalid state in TosState_as_index"); | |
550 assert(0 <= (int)state && (int)state < TemplateInterpreter::number_of_return_addrs, "index out of bounds"); | |
551 return (int)state; | |
552 } | |
553 | |
554 | |
555 //------------------------------------------------------------------------------------------------------------------------ | |
556 // Safepoint suppport | |
557 | |
558 static inline void copy_table(address* from, address* to, int size) { | |
559 // Copy non-overlapping tables. The copy has to occur word wise for MT safety. | |
560 while (size-- > 0) *to++ = *from++; | |
561 } | |
562 | |
563 void TemplateInterpreter::notice_safepoints() { | |
564 if (!_notice_safepoints) { | |
565 // switch to safepoint dispatch table | |
566 _notice_safepoints = true; | |
567 copy_table((address*)&_safept_table, (address*)&_active_table, sizeof(_active_table) / sizeof(address)); | |
568 } | |
569 } | |
570 | |
571 // switch from the dispatch table which notices safepoints back to the | |
572 // normal dispatch table. So that we can notice single stepping points, | |
573 // keep the safepoint dispatch table if we are single stepping in JVMTI. | |
574 // Note that the should_post_single_step test is exactly as fast as the | |
575 // JvmtiExport::_enabled test and covers both cases. | |
576 void TemplateInterpreter::ignore_safepoints() { | |
577 if (_notice_safepoints) { | |
578 if (!JvmtiExport::should_post_single_step()) { | |
579 // switch to normal dispatch table | |
580 _notice_safepoints = false; | |
581 copy_table((address*)&_normal_table, (address*)&_active_table, sizeof(_active_table) / sizeof(address)); | |
582 } | |
583 } | |
584 } | |
585 | |
586 //------------------------------------------------------------------------------------------------------------------------ | |
587 // Deoptimization support | |
588 | |
589 // If deoptimization happens, this function returns the point of next bytecode to continue execution | |
590 address TemplateInterpreter::deopt_continue_after_entry(Method* method, address bcp, int callee_parameters, bool is_top_frame) { | |
591 return AbstractInterpreter::deopt_continue_after_entry(method, bcp, callee_parameters, is_top_frame); | |
592 } | |
593 | |
594 // If deoptimization happens, this function returns the point where the interpreter reexecutes | |
595 // the bytecode. | |
596 // Note: Bytecodes::_athrow (C1 only) and Bytecodes::_return are the special cases | |
597 // that do not return "Interpreter::deopt_entry(vtos, 0)" | |
598 address TemplateInterpreter::deopt_reexecute_entry(Method* method, address bcp) { | |
599 assert(method->contains(bcp), "just checkin'"); | |
600 Bytecodes::Code code = Bytecodes::java_code_at(method, bcp); | |
601 if (code == Bytecodes::_return) { | |
602 // This is used for deopt during registration of finalizers | |
603 // during Object.<init>. We simply need to resume execution at | |
604 // the standard return vtos bytecode to pop the frame normally. | |
605 // reexecuting the real bytecode would cause double registration | |
606 // of the finalizable object. | |
607 return _normal_table.entry(Bytecodes::_return).entry(vtos); | |
608 } else { | |
609 return AbstractInterpreter::deopt_reexecute_entry(method, bcp); | |
610 } | |
611 } | |
612 | |
613 // If deoptimization happens, the interpreter should reexecute this bytecode. | |
614 // This function mainly helps the compilers to set up the reexecute bit. | |
615 bool TemplateInterpreter::bytecode_should_reexecute(Bytecodes::Code code) { | |
616 if (code == Bytecodes::_return) { | |
617 //Yes, we consider Bytecodes::_return as a special case of reexecution | |
618 return true; | |
619 } else { | |
620 return AbstractInterpreter::bytecode_should_reexecute(code); | |
621 } | |
622 } | |
623 | |
624 #endif // !CC_INTERP |