Mercurial > hg > graal-compiler
annotate src/share/vm/interpreter/templateInterpreter.cpp @ 3992:d1bdeef3e3e2
7098282: G1: assert(interval >= 0) failed: Sanity check, referencePolicy.cpp: 76
Summary: There is a race between one thread successfully forwarding and copying the klass mirror for the SoftReference class (including the static master clock) and another thread attempting to use the master clock while attempting to discover a soft reference object. Maintain a shadow copy of the soft reference master clock and use the shadow during reference discovery and reference processing.
Reviewed-by: tonyp, brutisso, ysr
author | johnc |
---|---|
date | Wed, 12 Oct 2011 10:25:51 -0700 |
parents | d83ac25d0304 |
children | 6759698e3140 |
rev | line source |
---|---|
0 | 1 /* |
2142 | 2 * Copyright (c) 1997, 2011, 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) | |
710 | 365 method_entry(method_handle) |
0 | 366 method_entry(java_lang_math_sin ) |
367 method_entry(java_lang_math_cos ) | |
368 method_entry(java_lang_math_tan ) | |
369 method_entry(java_lang_math_abs ) | |
370 method_entry(java_lang_math_sqrt ) | |
371 method_entry(java_lang_math_log ) | |
372 method_entry(java_lang_math_log10) | |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2142
diff
changeset
|
373 method_entry(java_lang_ref_reference_get) |
0 | 374 |
375 // all native method kinds (must be one contiguous block) | |
376 Interpreter::_native_entry_begin = Interpreter::code()->code_end(); | |
377 method_entry(native) | |
378 method_entry(native_synchronized) | |
379 Interpreter::_native_entry_end = Interpreter::code()->code_end(); | |
380 | |
381 #undef method_entry | |
382 | |
383 // Bytecodes | |
384 set_entry_points_for_all_bytes(); | |
385 set_safepoints_for_all_bytes(); | |
386 } | |
387 | |
388 //------------------------------------------------------------------------------------------------------------------------ | |
389 | |
390 address TemplateInterpreterGenerator::generate_error_exit(const char* msg) { | |
391 address entry = __ pc(); | |
392 __ stop(msg); | |
393 return entry; | |
394 } | |
395 | |
396 | |
397 //------------------------------------------------------------------------------------------------------------------------ | |
398 | |
399 void TemplateInterpreterGenerator::set_entry_points_for_all_bytes() { | |
400 for (int i = 0; i < DispatchTable::length; i++) { | |
401 Bytecodes::Code code = (Bytecodes::Code)i; | |
402 if (Bytecodes::is_defined(code)) { | |
403 set_entry_points(code); | |
404 } else { | |
405 set_unimplemented(i); | |
406 } | |
407 } | |
408 } | |
409 | |
410 | |
411 void TemplateInterpreterGenerator::set_safepoints_for_all_bytes() { | |
412 for (int i = 0; i < DispatchTable::length; i++) { | |
413 Bytecodes::Code code = (Bytecodes::Code)i; | |
414 if (Bytecodes::is_defined(code)) Interpreter::_safept_table.set_entry(code, Interpreter::_safept_entry); | |
415 } | |
416 } | |
417 | |
418 | |
419 void TemplateInterpreterGenerator::set_unimplemented(int i) { | |
420 address e = _unimplemented_bytecode; | |
421 EntryPoint entry(e, e, e, e, e, e, e, e, e); | |
422 Interpreter::_normal_table.set_entry(i, entry); | |
423 Interpreter::_wentry_point[i] = _unimplemented_bytecode; | |
424 } | |
425 | |
426 | |
427 void TemplateInterpreterGenerator::set_entry_points(Bytecodes::Code code) { | |
428 CodeletMark cm(_masm, Bytecodes::name(code), code); | |
429 // initialize entry points | |
430 assert(_unimplemented_bytecode != NULL, "should have been generated before"); | |
431 assert(_illegal_bytecode_sequence != NULL, "should have been generated before"); | |
432 address bep = _illegal_bytecode_sequence; | |
433 address cep = _illegal_bytecode_sequence; | |
434 address sep = _illegal_bytecode_sequence; | |
435 address aep = _illegal_bytecode_sequence; | |
436 address iep = _illegal_bytecode_sequence; | |
437 address lep = _illegal_bytecode_sequence; | |
438 address fep = _illegal_bytecode_sequence; | |
439 address dep = _illegal_bytecode_sequence; | |
440 address vep = _unimplemented_bytecode; | |
441 address wep = _unimplemented_bytecode; | |
442 // code for short & wide version of bytecode | |
443 if (Bytecodes::is_defined(code)) { | |
444 Template* t = TemplateTable::template_for(code); | |
445 assert(t->is_valid(), "just checking"); | |
446 set_short_entry_points(t, bep, cep, sep, aep, iep, lep, fep, dep, vep); | |
447 } | |
448 if (Bytecodes::wide_is_defined(code)) { | |
449 Template* t = TemplateTable::template_for_wide(code); | |
450 assert(t->is_valid(), "just checking"); | |
451 set_wide_entry_point(t, wep); | |
452 } | |
453 // set entry points | |
454 EntryPoint entry(bep, cep, sep, aep, iep, lep, fep, dep, vep); | |
455 Interpreter::_normal_table.set_entry(code, entry); | |
456 Interpreter::_wentry_point[code] = wep; | |
457 } | |
458 | |
459 | |
460 void TemplateInterpreterGenerator::set_wide_entry_point(Template* t, address& wep) { | |
461 assert(t->is_valid(), "template must exist"); | |
1489
cff162798819
6888953: some calls to function-like macros are missing semicolons
jcoomes
parents:
1071
diff
changeset
|
462 assert(t->tos_in() == vtos, "only vtos tos_in supported for wide instructions"); |
0 | 463 wep = __ pc(); generate_and_dispatch(t); |
464 } | |
465 | |
466 | |
467 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) { | |
468 assert(t->is_valid(), "template must exist"); | |
469 switch (t->tos_in()) { | |
1071
b18963243361
6902000: use ShouldNotReachHere() for btos/ctos/stos in TemplateInterpreterGenerator::set_short_entry_points
twisti
parents:
1059
diff
changeset
|
470 case btos: |
b18963243361
6902000: use ShouldNotReachHere() for btos/ctos/stos in TemplateInterpreterGenerator::set_short_entry_points
twisti
parents:
1059
diff
changeset
|
471 case ctos: |
b18963243361
6902000: use ShouldNotReachHere() for btos/ctos/stos in TemplateInterpreterGenerator::set_short_entry_points
twisti
parents:
1059
diff
changeset
|
472 case stos: |
b18963243361
6902000: use ShouldNotReachHere() for btos/ctos/stos in TemplateInterpreterGenerator::set_short_entry_points
twisti
parents:
1059
diff
changeset
|
473 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
|
474 break; |
0 | 475 case atos: vep = __ pc(); __ pop(atos); aep = __ pc(); generate_and_dispatch(t); break; |
476 case itos: vep = __ pc(); __ pop(itos); iep = __ pc(); generate_and_dispatch(t); break; | |
477 case ltos: vep = __ pc(); __ pop(ltos); lep = __ pc(); generate_and_dispatch(t); break; | |
478 case ftos: vep = __ pc(); __ pop(ftos); fep = __ pc(); generate_and_dispatch(t); break; | |
479 case dtos: vep = __ pc(); __ pop(dtos); dep = __ pc(); generate_and_dispatch(t); break; | |
480 case vtos: set_vtos_entry_points(t, bep, cep, sep, aep, iep, lep, fep, dep, vep); break; | |
481 default : ShouldNotReachHere(); break; | |
482 } | |
483 } | |
484 | |
485 | |
486 //------------------------------------------------------------------------------------------------------------------------ | |
487 | |
488 void TemplateInterpreterGenerator::generate_and_dispatch(Template* t, TosState tos_out) { | |
489 if (PrintBytecodeHistogram) histogram_bytecode(t); | |
490 #ifndef PRODUCT | |
491 // debugging code | |
492 if (CountBytecodes || TraceBytecodes || StopInterpreterAt > 0) count_bytecode(); | |
493 if (PrintBytecodePairHistogram) histogram_bytecode_pair(t); | |
494 if (TraceBytecodes) trace_bytecode(t); | |
495 if (StopInterpreterAt > 0) stop_interpreter_at(); | |
496 __ verify_FPU(1, t->tos_in()); | |
497 #endif // !PRODUCT | |
498 int step; | |
499 if (!t->does_dispatch()) { | |
500 step = t->is_wide() ? Bytecodes::wide_length_for(t->bytecode()) : Bytecodes::length_for(t->bytecode()); | |
501 if (tos_out == ilgl) tos_out = t->tos_out(); | |
502 // compute bytecode size | |
503 assert(step > 0, "just checkin'"); | |
504 // setup stuff for dispatching next bytecode | |
505 if (ProfileInterpreter && VerifyDataPointer | |
506 && methodDataOopDesc::bytecode_has_profile(t->bytecode())) { | |
507 __ verify_method_data_pointer(); | |
508 } | |
509 __ dispatch_prolog(tos_out, step); | |
510 } | |
511 // generate template | |
512 t->generate(_masm); | |
513 // advance | |
514 if (t->does_dispatch()) { | |
515 #ifdef ASSERT | |
516 // make sure execution doesn't go beyond this point if code is broken | |
517 __ should_not_reach_here(); | |
518 #endif // ASSERT | |
519 } else { | |
520 // dispatch to next bytecode | |
521 __ dispatch_epilog(tos_out, step); | |
522 } | |
523 } | |
524 | |
525 //------------------------------------------------------------------------------------------------------------------------ | |
526 // Entry points | |
527 | |
528 address TemplateInterpreter::return_entry(TosState state, int length) { | |
529 guarantee(0 <= length && length < Interpreter::number_of_return_entries, "illegal length"); | |
530 return _return_entry[length].entry(state); | |
531 } | |
532 | |
533 | |
534 address TemplateInterpreter::deopt_entry(TosState state, int length) { | |
535 guarantee(0 <= length && length < Interpreter::number_of_deopt_entries, "illegal length"); | |
536 return _deopt_entry[length].entry(state); | |
537 } | |
538 | |
539 //------------------------------------------------------------------------------------------------------------------------ | |
540 // Suport for invokes | |
541 | |
542 int TemplateInterpreter::TosState_as_index(TosState state) { | |
543 assert( state < number_of_states , "Invalid state in TosState_as_index"); | |
544 assert(0 <= (int)state && (int)state < TemplateInterpreter::number_of_return_addrs, "index out of bounds"); | |
545 return (int)state; | |
546 } | |
547 | |
548 | |
549 //------------------------------------------------------------------------------------------------------------------------ | |
550 // Safepoint suppport | |
551 | |
552 static inline void copy_table(address* from, address* to, int size) { | |
553 // Copy non-overlapping tables. The copy has to occur word wise for MT safety. | |
554 while (size-- > 0) *to++ = *from++; | |
555 } | |
556 | |
557 void TemplateInterpreter::notice_safepoints() { | |
558 if (!_notice_safepoints) { | |
559 // switch to safepoint dispatch table | |
560 _notice_safepoints = true; | |
561 copy_table((address*)&_safept_table, (address*)&_active_table, sizeof(_active_table) / sizeof(address)); | |
562 } | |
563 } | |
564 | |
565 // switch from the dispatch table which notices safepoints back to the | |
566 // normal dispatch table. So that we can notice single stepping points, | |
567 // keep the safepoint dispatch table if we are single stepping in JVMTI. | |
568 // Note that the should_post_single_step test is exactly as fast as the | |
569 // JvmtiExport::_enabled test and covers both cases. | |
570 void TemplateInterpreter::ignore_safepoints() { | |
571 if (_notice_safepoints) { | |
572 if (!JvmtiExport::should_post_single_step()) { | |
573 // switch to normal dispatch table | |
574 _notice_safepoints = false; | |
575 copy_table((address*)&_normal_table, (address*)&_active_table, sizeof(_active_table) / sizeof(address)); | |
576 } | |
577 } | |
578 } | |
579 | |
900
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
726
diff
changeset
|
580 //------------------------------------------------------------------------------------------------------------------------ |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
726
diff
changeset
|
581 // Deoptimization support |
0 | 582 |
900
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
726
diff
changeset
|
583 // If deoptimization happens, this function returns the point of next bytecode to continue execution |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
726
diff
changeset
|
584 address TemplateInterpreter::deopt_continue_after_entry(methodOop method, address bcp, int callee_parameters, bool is_top_frame) { |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
726
diff
changeset
|
585 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
|
586 } |
0 | 587 |
900
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
726
diff
changeset
|
588 // 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
|
589 // the bytecode. |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
726
diff
changeset
|
590 // 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
|
591 // that do not return "Interpreter::deopt_entry(vtos, 0)" |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
726
diff
changeset
|
592 address TemplateInterpreter::deopt_reexecute_entry(methodOop method, address bcp) { |
0 | 593 assert(method->contains(bcp), "just checkin'"); |
2142 | 594 Bytecodes::Code code = Bytecodes::java_code_at(method, bcp); |
0 | 595 if (code == Bytecodes::_return) { |
900
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
726
diff
changeset
|
596 // 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
|
597 // 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
|
598 // 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
|
599 // 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
|
600 // of the finalizable object. |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
726
diff
changeset
|
601 return _normal_table.entry(Bytecodes::_return).entry(vtos); |
0 | 602 } else { |
900
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
726
diff
changeset
|
603 return AbstractInterpreter::deopt_reexecute_entry(method, bcp); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
726
diff
changeset
|
604 } |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
726
diff
changeset
|
605 } |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
726
diff
changeset
|
606 |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
726
diff
changeset
|
607 // 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
|
608 // 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
|
609 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
|
610 if (code == Bytecodes::_return) { |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
726
diff
changeset
|
611 //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
|
612 return true; |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
726
diff
changeset
|
613 } else { |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
726
diff
changeset
|
614 return AbstractInterpreter::bytecode_should_reexecute(code); |
0 | 615 } |
616 } | |
617 | |
618 #endif // !CC_INTERP |