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