Mercurial > hg > graal-compiler
annotate src/share/vm/interpreter/templateInterpreter.cpp @ 3249:e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
Summary: A referent object that is only weakly reachable at the start of concurrent marking but is re-attached to the strongly reachable object graph during marking may not be marked as live. This can cause the reference object to be processed prematurely and leave dangling pointers to the referent object. Implement a read barrier for the java.lang.ref.Reference::referent field by intrinsifying the Reference.get() method, and intercepting accesses though JNI, reflection, and Unsafe, so that when a non-null referent object is read it is also logged in an SATB buffer.
Reviewed-by: kvn, iveresov, never, tonyp, dholmes
author | johnc |
---|---|
date | Thu, 07 Apr 2011 09:53:20 -0700 |
parents | 8012aa3ccede |
children | 38fa55e5e792 |
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; | |
710 | 174 address TemplateInterpreter::_throw_WrongMethodType_entry = NULL; |
0 | 175 address TemplateInterpreter::_throw_NullPointerException_entry = NULL; |
176 address TemplateInterpreter::_throw_StackOverflowError_entry = NULL; | |
177 address TemplateInterpreter::_throw_exception_entry = NULL; | |
178 | |
179 #ifndef PRODUCT | |
180 EntryPoint TemplateInterpreter::_trace_code; | |
181 #endif // !PRODUCT | |
182 EntryPoint TemplateInterpreter::_return_entry[TemplateInterpreter::number_of_return_entries]; | |
183 EntryPoint TemplateInterpreter::_earlyret_entry; | |
184 EntryPoint TemplateInterpreter::_deopt_entry [TemplateInterpreter::number_of_deopt_entries ]; | |
185 EntryPoint TemplateInterpreter::_continuation_entry; | |
186 EntryPoint TemplateInterpreter::_safept_entry; | |
187 | |
188 address TemplateInterpreter::_return_3_addrs_by_index[TemplateInterpreter::number_of_return_addrs]; | |
189 address TemplateInterpreter::_return_5_addrs_by_index[TemplateInterpreter::number_of_return_addrs]; | |
190 | |
191 DispatchTable TemplateInterpreter::_active_table; | |
192 DispatchTable TemplateInterpreter::_normal_table; | |
193 DispatchTable TemplateInterpreter::_safept_table; | |
194 address TemplateInterpreter::_wentry_point[DispatchTable::length]; | |
195 | |
196 TemplateInterpreterGenerator::TemplateInterpreterGenerator(StubQueue* _code): AbstractInterpreterGenerator(_code) { | |
197 _unimplemented_bytecode = NULL; | |
198 _illegal_bytecode_sequence = NULL; | |
199 } | |
200 | |
201 static const BasicType types[Interpreter::number_of_result_handlers] = { | |
202 T_BOOLEAN, | |
203 T_CHAR , | |
204 T_BYTE , | |
205 T_SHORT , | |
206 T_INT , | |
207 T_LONG , | |
208 T_VOID , | |
209 T_FLOAT , | |
210 T_DOUBLE , | |
211 T_OBJECT | |
212 }; | |
213 | |
214 void TemplateInterpreterGenerator::generate_all() { | |
215 AbstractInterpreterGenerator::generate_all(); | |
216 | |
217 { CodeletMark cm(_masm, "error exits"); | |
218 _unimplemented_bytecode = generate_error_exit("unimplemented bytecode"); | |
219 _illegal_bytecode_sequence = generate_error_exit("illegal bytecode sequence - method not verified"); | |
220 } | |
221 | |
222 #ifndef PRODUCT | |
223 if (TraceBytecodes) { | |
224 CodeletMark cm(_masm, "bytecode tracing support"); | |
225 Interpreter::_trace_code = | |
226 EntryPoint( | |
227 generate_trace_code(btos), | |
228 generate_trace_code(ctos), | |
229 generate_trace_code(stos), | |
230 generate_trace_code(atos), | |
231 generate_trace_code(itos), | |
232 generate_trace_code(ltos), | |
233 generate_trace_code(ftos), | |
234 generate_trace_code(dtos), | |
235 generate_trace_code(vtos) | |
236 ); | |
237 } | |
238 #endif // !PRODUCT | |
239 | |
240 { CodeletMark cm(_masm, "return entry points"); | |
241 for (int i = 0; i < Interpreter::number_of_return_entries; i++) { | |
242 Interpreter::_return_entry[i] = | |
243 EntryPoint( | |
244 generate_return_entry_for(itos, i), | |
245 generate_return_entry_for(itos, i), | |
246 generate_return_entry_for(itos, i), | |
247 generate_return_entry_for(atos, i), | |
248 generate_return_entry_for(itos, i), | |
249 generate_return_entry_for(ltos, i), | |
250 generate_return_entry_for(ftos, i), | |
251 generate_return_entry_for(dtos, i), | |
252 generate_return_entry_for(vtos, i) | |
253 ); | |
254 } | |
255 } | |
256 | |
257 { CodeletMark cm(_masm, "earlyret entry points"); | |
258 Interpreter::_earlyret_entry = | |
259 EntryPoint( | |
260 generate_earlyret_entry_for(btos), | |
261 generate_earlyret_entry_for(ctos), | |
262 generate_earlyret_entry_for(stos), | |
263 generate_earlyret_entry_for(atos), | |
264 generate_earlyret_entry_for(itos), | |
265 generate_earlyret_entry_for(ltos), | |
266 generate_earlyret_entry_for(ftos), | |
267 generate_earlyret_entry_for(dtos), | |
268 generate_earlyret_entry_for(vtos) | |
269 ); | |
270 } | |
271 | |
272 { CodeletMark cm(_masm, "deoptimization entry points"); | |
273 for (int i = 0; i < Interpreter::number_of_deopt_entries; i++) { | |
274 Interpreter::_deopt_entry[i] = | |
275 EntryPoint( | |
276 generate_deopt_entry_for(itos, i), | |
277 generate_deopt_entry_for(itos, i), | |
278 generate_deopt_entry_for(itos, i), | |
279 generate_deopt_entry_for(atos, i), | |
280 generate_deopt_entry_for(itos, i), | |
281 generate_deopt_entry_for(ltos, i), | |
282 generate_deopt_entry_for(ftos, i), | |
283 generate_deopt_entry_for(dtos, i), | |
284 generate_deopt_entry_for(vtos, i) | |
285 ); | |
286 } | |
287 } | |
288 | |
289 { CodeletMark cm(_masm, "result handlers for native calls"); | |
290 // The various result converter stublets. | |
291 int is_generated[Interpreter::number_of_result_handlers]; | |
292 memset(is_generated, 0, sizeof(is_generated)); | |
293 | |
294 for (int i = 0; i < Interpreter::number_of_result_handlers; i++) { | |
295 BasicType type = types[i]; | |
296 if (!is_generated[Interpreter::BasicType_as_index(type)]++) { | |
297 Interpreter::_native_abi_to_tosca[Interpreter::BasicType_as_index(type)] = generate_result_handler_for(type); | |
298 } | |
299 } | |
300 } | |
301 | |
302 for (int j = 0; j < number_of_states; j++) { | |
303 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
|
304 int index = Interpreter::TosState_as_index(states[j]); |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
305 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
|
306 Interpreter::_return_5_addrs_by_index[index] = Interpreter::return_entry(states[j], 5); |
0 | 307 } |
308 | |
309 { CodeletMark cm(_masm, "continuation entry points"); | |
310 Interpreter::_continuation_entry = | |
311 EntryPoint( | |
312 generate_continuation_for(btos), | |
313 generate_continuation_for(ctos), | |
314 generate_continuation_for(stos), | |
315 generate_continuation_for(atos), | |
316 generate_continuation_for(itos), | |
317 generate_continuation_for(ltos), | |
318 generate_continuation_for(ftos), | |
319 generate_continuation_for(dtos), | |
320 generate_continuation_for(vtos) | |
321 ); | |
322 } | |
323 | |
324 { CodeletMark cm(_masm, "safepoint entry points"); | |
325 Interpreter::_safept_entry = | |
326 EntryPoint( | |
327 generate_safept_entry_for(btos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), | |
328 generate_safept_entry_for(ctos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), | |
329 generate_safept_entry_for(stos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), | |
330 generate_safept_entry_for(atos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), | |
331 generate_safept_entry_for(itos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), | |
332 generate_safept_entry_for(ltos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), | |
333 generate_safept_entry_for(ftos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), | |
334 generate_safept_entry_for(dtos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), | |
335 generate_safept_entry_for(vtos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)) | |
336 ); | |
337 } | |
338 | |
339 { CodeletMark cm(_masm, "exception handling"); | |
340 // (Note: this is not safepoint safe because thread may return to compiled code) | |
341 generate_throw_exception(); | |
342 } | |
343 | |
344 { CodeletMark cm(_masm, "throw exception entrypoints"); | |
345 Interpreter::_throw_ArrayIndexOutOfBoundsException_entry = generate_ArrayIndexOutOfBounds_handler("java/lang/ArrayIndexOutOfBoundsException"); | |
346 Interpreter::_throw_ArrayStoreException_entry = generate_klass_exception_handler("java/lang/ArrayStoreException" ); | |
347 Interpreter::_throw_ArithmeticException_entry = generate_exception_handler("java/lang/ArithmeticException" , "/ by zero"); | |
348 Interpreter::_throw_ClassCastException_entry = generate_ClassCastException_handler(); | |
710 | 349 Interpreter::_throw_WrongMethodType_entry = generate_WrongMethodType_handler(); |
0 | 350 Interpreter::_throw_NullPointerException_entry = generate_exception_handler("java/lang/NullPointerException" , NULL ); |
351 Interpreter::_throw_StackOverflowError_entry = generate_StackOverflowError_handler(); | |
352 } | |
353 | |
354 | |
355 | |
356 #define method_entry(kind) \ | |
357 { CodeletMark cm(_masm, "method entry point (kind = " #kind ")"); \ | |
358 Interpreter::_entry_table[Interpreter::kind] = generate_method_entry(Interpreter::kind); \ | |
359 } | |
360 | |
361 // all non-native method kinds | |
362 method_entry(zerolocals) | |
363 method_entry(zerolocals_synchronized) | |
364 method_entry(empty) | |
365 method_entry(accessor) | |
366 method_entry(abstract) | |
710 | 367 method_entry(method_handle) |
0 | 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) | |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2142
diff
changeset
|
375 method_entry(java_lang_ref_reference_get) |
0 | 376 |
377 // all native method kinds (must be one contiguous block) | |
378 Interpreter::_native_entry_begin = Interpreter::code()->code_end(); | |
379 method_entry(native) | |
380 method_entry(native_synchronized) | |
381 Interpreter::_native_entry_end = Interpreter::code()->code_end(); | |
382 | |
383 #undef method_entry | |
384 | |
385 // Bytecodes | |
386 set_entry_points_for_all_bytes(); | |
387 set_safepoints_for_all_bytes(); | |
388 } | |
389 | |
390 //------------------------------------------------------------------------------------------------------------------------ | |
391 | |
392 address TemplateInterpreterGenerator::generate_error_exit(const char* msg) { | |
393 address entry = __ pc(); | |
394 __ stop(msg); | |
395 return entry; | |
396 } | |
397 | |
398 | |
399 //------------------------------------------------------------------------------------------------------------------------ | |
400 | |
401 void TemplateInterpreterGenerator::set_entry_points_for_all_bytes() { | |
402 for (int i = 0; i < DispatchTable::length; i++) { | |
403 Bytecodes::Code code = (Bytecodes::Code)i; | |
404 if (Bytecodes::is_defined(code)) { | |
405 set_entry_points(code); | |
406 } else { | |
407 set_unimplemented(i); | |
408 } | |
409 } | |
410 } | |
411 | |
412 | |
413 void TemplateInterpreterGenerator::set_safepoints_for_all_bytes() { | |
414 for (int i = 0; i < DispatchTable::length; i++) { | |
415 Bytecodes::Code code = (Bytecodes::Code)i; | |
416 if (Bytecodes::is_defined(code)) Interpreter::_safept_table.set_entry(code, Interpreter::_safept_entry); | |
417 } | |
418 } | |
419 | |
420 | |
421 void TemplateInterpreterGenerator::set_unimplemented(int i) { | |
422 address e = _unimplemented_bytecode; | |
423 EntryPoint entry(e, e, e, e, e, e, e, e, e); | |
424 Interpreter::_normal_table.set_entry(i, entry); | |
425 Interpreter::_wentry_point[i] = _unimplemented_bytecode; | |
426 } | |
427 | |
428 | |
429 void TemplateInterpreterGenerator::set_entry_points(Bytecodes::Code code) { | |
430 CodeletMark cm(_masm, Bytecodes::name(code), code); | |
431 // initialize entry points | |
432 assert(_unimplemented_bytecode != NULL, "should have been generated before"); | |
433 assert(_illegal_bytecode_sequence != NULL, "should have been generated before"); | |
434 address bep = _illegal_bytecode_sequence; | |
435 address cep = _illegal_bytecode_sequence; | |
436 address sep = _illegal_bytecode_sequence; | |
437 address aep = _illegal_bytecode_sequence; | |
438 address iep = _illegal_bytecode_sequence; | |
439 address lep = _illegal_bytecode_sequence; | |
440 address fep = _illegal_bytecode_sequence; | |
441 address dep = _illegal_bytecode_sequence; | |
442 address vep = _unimplemented_bytecode; | |
443 address wep = _unimplemented_bytecode; | |
444 // code for short & wide version of bytecode | |
445 if (Bytecodes::is_defined(code)) { | |
446 Template* t = TemplateTable::template_for(code); | |
447 assert(t->is_valid(), "just checking"); | |
448 set_short_entry_points(t, bep, cep, sep, aep, iep, lep, fep, dep, vep); | |
449 } | |
450 if (Bytecodes::wide_is_defined(code)) { | |
451 Template* t = TemplateTable::template_for_wide(code); | |
452 assert(t->is_valid(), "just checking"); | |
453 set_wide_entry_point(t, wep); | |
454 } | |
455 // set entry points | |
456 EntryPoint entry(bep, cep, sep, aep, iep, lep, fep, dep, vep); | |
457 Interpreter::_normal_table.set_entry(code, entry); | |
458 Interpreter::_wentry_point[code] = wep; | |
459 } | |
460 | |
461 | |
462 void TemplateInterpreterGenerator::set_wide_entry_point(Template* t, address& wep) { | |
463 assert(t->is_valid(), "template must exist"); | |
1489
cff162798819
6888953: some calls to function-like macros are missing semicolons
jcoomes
parents:
1071
diff
changeset
|
464 assert(t->tos_in() == vtos, "only vtos tos_in supported for wide instructions"); |
0 | 465 wep = __ pc(); generate_and_dispatch(t); |
466 } | |
467 | |
468 | |
469 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) { | |
470 assert(t->is_valid(), "template must exist"); | |
471 switch (t->tos_in()) { | |
1071
b18963243361
6902000: use ShouldNotReachHere() for btos/ctos/stos in TemplateInterpreterGenerator::set_short_entry_points
twisti
parents:
1059
diff
changeset
|
472 case btos: |
b18963243361
6902000: use ShouldNotReachHere() for btos/ctos/stos in TemplateInterpreterGenerator::set_short_entry_points
twisti
parents:
1059
diff
changeset
|
473 case ctos: |
b18963243361
6902000: use ShouldNotReachHere() for btos/ctos/stos in TemplateInterpreterGenerator::set_short_entry_points
twisti
parents:
1059
diff
changeset
|
474 case stos: |
b18963243361
6902000: use ShouldNotReachHere() for btos/ctos/stos in TemplateInterpreterGenerator::set_short_entry_points
twisti
parents:
1059
diff
changeset
|
475 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
|
476 break; |
0 | 477 case atos: vep = __ pc(); __ pop(atos); aep = __ pc(); generate_and_dispatch(t); break; |
478 case itos: vep = __ pc(); __ pop(itos); iep = __ pc(); generate_and_dispatch(t); break; | |
479 case ltos: vep = __ pc(); __ pop(ltos); lep = __ pc(); generate_and_dispatch(t); break; | |
480 case ftos: vep = __ pc(); __ pop(ftos); fep = __ pc(); generate_and_dispatch(t); break; | |
481 case dtos: vep = __ pc(); __ pop(dtos); dep = __ pc(); generate_and_dispatch(t); break; | |
482 case vtos: set_vtos_entry_points(t, bep, cep, sep, aep, iep, lep, fep, dep, vep); break; | |
483 default : ShouldNotReachHere(); break; | |
484 } | |
485 } | |
486 | |
487 | |
488 //------------------------------------------------------------------------------------------------------------------------ | |
489 | |
490 void TemplateInterpreterGenerator::generate_and_dispatch(Template* t, TosState tos_out) { | |
491 if (PrintBytecodeHistogram) histogram_bytecode(t); | |
492 #ifndef PRODUCT | |
493 // debugging code | |
494 if (CountBytecodes || TraceBytecodes || StopInterpreterAt > 0) count_bytecode(); | |
495 if (PrintBytecodePairHistogram) histogram_bytecode_pair(t); | |
496 if (TraceBytecodes) trace_bytecode(t); | |
497 if (StopInterpreterAt > 0) stop_interpreter_at(); | |
498 __ verify_FPU(1, t->tos_in()); | |
499 #endif // !PRODUCT | |
500 int step; | |
501 if (!t->does_dispatch()) { | |
502 step = t->is_wide() ? Bytecodes::wide_length_for(t->bytecode()) : Bytecodes::length_for(t->bytecode()); | |
503 if (tos_out == ilgl) tos_out = t->tos_out(); | |
504 // compute bytecode size | |
505 assert(step > 0, "just checkin'"); | |
506 // setup stuff for dispatching next bytecode | |
507 if (ProfileInterpreter && VerifyDataPointer | |
508 && methodDataOopDesc::bytecode_has_profile(t->bytecode())) { | |
509 __ verify_method_data_pointer(); | |
510 } | |
511 __ dispatch_prolog(tos_out, step); | |
512 } | |
513 // generate template | |
514 t->generate(_masm); | |
515 // advance | |
516 if (t->does_dispatch()) { | |
517 #ifdef ASSERT | |
518 // make sure execution doesn't go beyond this point if code is broken | |
519 __ should_not_reach_here(); | |
520 #endif // ASSERT | |
521 } else { | |
522 // dispatch to next bytecode | |
523 __ dispatch_epilog(tos_out, step); | |
524 } | |
525 } | |
526 | |
527 //------------------------------------------------------------------------------------------------------------------------ | |
528 // Entry points | |
529 | |
530 address TemplateInterpreter::return_entry(TosState state, int length) { | |
531 guarantee(0 <= length && length < Interpreter::number_of_return_entries, "illegal length"); | |
532 return _return_entry[length].entry(state); | |
533 } | |
534 | |
535 | |
536 address TemplateInterpreter::deopt_entry(TosState state, int length) { | |
537 guarantee(0 <= length && length < Interpreter::number_of_deopt_entries, "illegal length"); | |
538 return _deopt_entry[length].entry(state); | |
539 } | |
540 | |
541 //------------------------------------------------------------------------------------------------------------------------ | |
542 // Suport for invokes | |
543 | |
544 int TemplateInterpreter::TosState_as_index(TosState state) { | |
545 assert( state < number_of_states , "Invalid state in TosState_as_index"); | |
546 assert(0 <= (int)state && (int)state < TemplateInterpreter::number_of_return_addrs, "index out of bounds"); | |
547 return (int)state; | |
548 } | |
549 | |
550 | |
551 //------------------------------------------------------------------------------------------------------------------------ | |
552 // Safepoint suppport | |
553 | |
554 static inline void copy_table(address* from, address* to, int size) { | |
555 // Copy non-overlapping tables. The copy has to occur word wise for MT safety. | |
556 while (size-- > 0) *to++ = *from++; | |
557 } | |
558 | |
559 void TemplateInterpreter::notice_safepoints() { | |
560 if (!_notice_safepoints) { | |
561 // switch to safepoint dispatch table | |
562 _notice_safepoints = true; | |
563 copy_table((address*)&_safept_table, (address*)&_active_table, sizeof(_active_table) / sizeof(address)); | |
564 } | |
565 } | |
566 | |
567 // switch from the dispatch table which notices safepoints back to the | |
568 // normal dispatch table. So that we can notice single stepping points, | |
569 // keep the safepoint dispatch table if we are single stepping in JVMTI. | |
570 // Note that the should_post_single_step test is exactly as fast as the | |
571 // JvmtiExport::_enabled test and covers both cases. | |
572 void TemplateInterpreter::ignore_safepoints() { | |
573 if (_notice_safepoints) { | |
574 if (!JvmtiExport::should_post_single_step()) { | |
575 // switch to normal dispatch table | |
576 _notice_safepoints = false; | |
577 copy_table((address*)&_normal_table, (address*)&_active_table, sizeof(_active_table) / sizeof(address)); | |
578 } | |
579 } | |
580 } | |
581 | |
900
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
726
diff
changeset
|
582 //------------------------------------------------------------------------------------------------------------------------ |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
726
diff
changeset
|
583 // Deoptimization support |
0 | 584 |
900
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
726
diff
changeset
|
585 // 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
|
586 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
|
587 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
|
588 } |
0 | 589 |
900
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
726
diff
changeset
|
590 // If deoptimization happens, this function returns the point where the interpreter reexecutes |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
726
diff
changeset
|
591 // the bytecode. |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
726
diff
changeset
|
592 // 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
|
593 // 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
|
594 address TemplateInterpreter::deopt_reexecute_entry(methodOop method, address bcp) { |
0 | 595 assert(method->contains(bcp), "just checkin'"); |
2142 | 596 Bytecodes::Code code = Bytecodes::java_code_at(method, bcp); |
0 | 597 if (code == Bytecodes::_return) { |
900
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
726
diff
changeset
|
598 // 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
|
599 // 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
|
600 // 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
|
601 // 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
|
602 // of the finalizable object. |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
726
diff
changeset
|
603 return _normal_table.entry(Bytecodes::_return).entry(vtos); |
0 | 604 } else { |
900
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
726
diff
changeset
|
605 return AbstractInterpreter::deopt_reexecute_entry(method, bcp); |
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 } |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
726
diff
changeset
|
608 |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
726
diff
changeset
|
609 // 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
|
610 // 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
|
611 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
|
612 if (code == Bytecodes::_return) { |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
726
diff
changeset
|
613 //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
|
614 return true; |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
726
diff
changeset
|
615 } else { |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
726
diff
changeset
|
616 return AbstractInterpreter::bytecode_should_reexecute(code); |
0 | 617 } |
618 } | |
619 | |
620 #endif // !CC_INTERP |