Mercurial > hg > graal-jvmci-8
annotate src/share/vm/c1/c1_CodeStubs.hpp @ 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 | e4fee0bdaa85 |
children | 09aad8452938 |
rev | line source |
---|---|
0 | 1 /* |
2168
e4fee0bdaa85
7008809: should report the class in ArrayStoreExceptions from compiled code
never
parents:
1972
diff
changeset
|
2 * Copyright (c) 1999, 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:
1295
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1295
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:
1295
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #ifndef SHARE_VM_C1_C1_CODESTUBS_HPP |
26 #define SHARE_VM_C1_C1_CODESTUBS_HPP | |
27 | |
28 #include "c1/c1_FrameMap.hpp" | |
29 #include "c1/c1_IR.hpp" | |
30 #include "c1/c1_Instruction.hpp" | |
31 #include "c1/c1_LIR.hpp" | |
32 #include "c1/c1_Runtime1.hpp" | |
33 #include "utilities/array.hpp" | |
34 | |
0 | 35 class CodeEmitInfo; |
36 class LIR_Assembler; | |
37 class LIR_OpVisitState; | |
38 | |
39 // CodeStubs are little 'out-of-line' pieces of code that | |
40 // usually handle slow cases of operations. All code stubs | |
41 // are collected and code is emitted at the end of the | |
42 // nmethod. | |
43 | |
44 class CodeStub: public CompilationResourceObj { | |
45 protected: | |
46 Label _entry; // label at the stub entry point | |
47 Label _continuation; // label where stub continues, if any | |
48 | |
49 public: | |
50 CodeStub() {} | |
51 | |
52 // code generation | |
53 void assert_no_unbound_labels() { assert(!_entry.is_unbound() && !_continuation.is_unbound(), "unbound label"); } | |
54 virtual void emit_code(LIR_Assembler* e) = 0; | |
55 virtual CodeEmitInfo* info() const { return NULL; } | |
56 virtual bool is_exception_throw_stub() const { return false; } | |
57 virtual bool is_range_check_stub() const { return false; } | |
58 virtual bool is_divbyzero_stub() const { return false; } | |
59 #ifndef PRODUCT | |
60 virtual void print_name(outputStream* out) const = 0; | |
61 #endif | |
62 | |
63 // label access | |
64 Label* entry() { return &_entry; } | |
65 Label* continuation() { return &_continuation; } | |
66 // for LIR | |
67 virtual void visit(LIR_OpVisitState* visit) { | |
68 #ifndef PRODUCT | |
69 if (LIRTracePeephole && Verbose) { | |
70 tty->print("no visitor for "); | |
71 print_name(tty); | |
72 tty->cr(); | |
73 } | |
74 #endif | |
75 } | |
76 }; | |
77 | |
78 | |
79 define_array(CodeStubArray, CodeStub*) | |
80 define_stack(_CodeStubList, CodeStubArray) | |
81 | |
82 class CodeStubList: public _CodeStubList { | |
83 public: | |
84 CodeStubList(): _CodeStubList() {} | |
85 | |
86 void append(CodeStub* stub) { | |
87 if (!contains(stub)) { | |
88 _CodeStubList::append(stub); | |
89 } | |
90 } | |
91 }; | |
92 | |
93 class CounterOverflowStub: public CodeStub { | |
94 private: | |
95 CodeEmitInfo* _info; | |
96 int _bci; | |
1783 | 97 LIR_Opr _method; |
0 | 98 |
99 public: | |
1783 | 100 CounterOverflowStub(CodeEmitInfo* info, int bci, LIR_Opr method) : _info(info), _bci(bci), _method(method) { |
0 | 101 } |
102 | |
103 virtual void emit_code(LIR_Assembler* e); | |
104 | |
105 virtual void visit(LIR_OpVisitState* visitor) { | |
106 visitor->do_slow_case(_info); | |
1783 | 107 visitor->do_input(_method); |
0 | 108 } |
109 | |
110 #ifndef PRODUCT | |
111 virtual void print_name(outputStream* out) const { out->print("CounterOverflowStub"); } | |
112 #endif // PRODUCT | |
113 | |
114 }; | |
115 | |
116 class ConversionStub: public CodeStub { | |
117 private: | |
118 Bytecodes::Code _bytecode; | |
119 LIR_Opr _input; | |
120 LIR_Opr _result; | |
121 | |
122 static float float_zero; | |
123 static double double_zero; | |
124 public: | |
125 ConversionStub(Bytecodes::Code bytecode, LIR_Opr input, LIR_Opr result) | |
126 : _bytecode(bytecode), _input(input), _result(result) { | |
127 } | |
128 | |
129 Bytecodes::Code bytecode() { return _bytecode; } | |
130 LIR_Opr input() { return _input; } | |
131 LIR_Opr result() { return _result; } | |
132 | |
133 virtual void emit_code(LIR_Assembler* e); | |
134 virtual void visit(LIR_OpVisitState* visitor) { | |
135 visitor->do_slow_case(); | |
136 visitor->do_input(_input); | |
137 visitor->do_output(_result); | |
138 } | |
139 #ifndef PRODUCT | |
140 virtual void print_name(outputStream* out) const { out->print("ConversionStub"); } | |
141 #endif // PRODUCT | |
142 }; | |
143 | |
144 | |
145 // Throws ArrayIndexOutOfBoundsException by default but can be | |
146 // configured to throw IndexOutOfBoundsException in constructor | |
147 class RangeCheckStub: public CodeStub { | |
148 private: | |
149 CodeEmitInfo* _info; | |
150 LIR_Opr _index; | |
151 bool _throw_index_out_of_bounds_exception; | |
152 | |
153 public: | |
154 RangeCheckStub(CodeEmitInfo* info, LIR_Opr index, bool throw_index_out_of_bounds_exception = false); | |
155 virtual void emit_code(LIR_Assembler* e); | |
156 virtual CodeEmitInfo* info() const { return _info; } | |
157 virtual bool is_exception_throw_stub() const { return true; } | |
158 virtual bool is_range_check_stub() const { return true; } | |
159 virtual void visit(LIR_OpVisitState* visitor) { | |
160 visitor->do_slow_case(_info); | |
161 visitor->do_input(_index); | |
162 } | |
163 #ifndef PRODUCT | |
164 virtual void print_name(outputStream* out) const { out->print("RangeCheckStub"); } | |
165 #endif // PRODUCT | |
166 }; | |
167 | |
168 | |
169 class DivByZeroStub: public CodeStub { | |
170 private: | |
171 CodeEmitInfo* _info; | |
172 int _offset; | |
173 | |
174 public: | |
175 DivByZeroStub(CodeEmitInfo* info) | |
176 : _info(info), _offset(-1) { | |
177 } | |
178 DivByZeroStub(int offset, CodeEmitInfo* info) | |
179 : _info(info), _offset(offset) { | |
180 } | |
181 virtual void emit_code(LIR_Assembler* e); | |
182 virtual CodeEmitInfo* info() const { return _info; } | |
183 virtual bool is_exception_throw_stub() const { return true; } | |
184 virtual bool is_divbyzero_stub() const { return true; } | |
185 virtual void visit(LIR_OpVisitState* visitor) { | |
186 visitor->do_slow_case(_info); | |
187 } | |
188 #ifndef PRODUCT | |
189 virtual void print_name(outputStream* out) const { out->print("DivByZeroStub"); } | |
190 #endif // PRODUCT | |
191 }; | |
192 | |
193 | |
194 class ImplicitNullCheckStub: public CodeStub { | |
195 private: | |
196 CodeEmitInfo* _info; | |
197 int _offset; | |
198 | |
199 public: | |
200 ImplicitNullCheckStub(int offset, CodeEmitInfo* info) | |
201 : _offset(offset), _info(info) { | |
202 } | |
203 virtual void emit_code(LIR_Assembler* e); | |
204 virtual CodeEmitInfo* info() const { return _info; } | |
205 virtual bool is_exception_throw_stub() const { return true; } | |
206 virtual void visit(LIR_OpVisitState* visitor) { | |
207 visitor->do_slow_case(_info); | |
208 } | |
209 #ifndef PRODUCT | |
210 virtual void print_name(outputStream* out) const { out->print("ImplicitNullCheckStub"); } | |
211 #endif // PRODUCT | |
212 }; | |
213 | |
214 | |
215 class NewInstanceStub: public CodeStub { | |
216 private: | |
217 ciInstanceKlass* _klass; | |
218 LIR_Opr _klass_reg; | |
219 LIR_Opr _result; | |
220 CodeEmitInfo* _info; | |
221 Runtime1::StubID _stub_id; | |
222 | |
223 public: | |
224 NewInstanceStub(LIR_Opr klass_reg, LIR_Opr result, ciInstanceKlass* klass, CodeEmitInfo* info, Runtime1::StubID stub_id); | |
225 virtual void emit_code(LIR_Assembler* e); | |
226 virtual CodeEmitInfo* info() const { return _info; } | |
227 virtual void visit(LIR_OpVisitState* visitor) { | |
228 visitor->do_slow_case(_info); | |
229 visitor->do_input(_klass_reg); | |
230 visitor->do_output(_result); | |
231 } | |
232 #ifndef PRODUCT | |
233 virtual void print_name(outputStream* out) const { out->print("NewInstanceStub"); } | |
234 #endif // PRODUCT | |
235 }; | |
236 | |
237 | |
238 class NewTypeArrayStub: public CodeStub { | |
239 private: | |
240 LIR_Opr _klass_reg; | |
241 LIR_Opr _length; | |
242 LIR_Opr _result; | |
243 CodeEmitInfo* _info; | |
244 | |
245 public: | |
246 NewTypeArrayStub(LIR_Opr klass_reg, LIR_Opr length, LIR_Opr result, CodeEmitInfo* info); | |
247 virtual void emit_code(LIR_Assembler* e); | |
248 virtual CodeEmitInfo* info() const { return _info; } | |
249 virtual void visit(LIR_OpVisitState* visitor) { | |
250 visitor->do_slow_case(_info); | |
251 visitor->do_input(_klass_reg); | |
252 visitor->do_input(_length); | |
253 assert(_result->is_valid(), "must be valid"); visitor->do_output(_result); | |
254 } | |
255 #ifndef PRODUCT | |
256 virtual void print_name(outputStream* out) const { out->print("NewTypeArrayStub"); } | |
257 #endif // PRODUCT | |
258 }; | |
259 | |
260 | |
261 class NewObjectArrayStub: public CodeStub { | |
262 private: | |
263 LIR_Opr _klass_reg; | |
264 LIR_Opr _length; | |
265 LIR_Opr _result; | |
266 CodeEmitInfo* _info; | |
267 | |
268 public: | |
269 NewObjectArrayStub(LIR_Opr klass_reg, LIR_Opr length, LIR_Opr result, CodeEmitInfo* info); | |
270 virtual void emit_code(LIR_Assembler* e); | |
271 virtual CodeEmitInfo* info() const { return _info; } | |
272 virtual void visit(LIR_OpVisitState* visitor) { | |
273 visitor->do_slow_case(_info); | |
274 visitor->do_input(_klass_reg); | |
275 visitor->do_input(_length); | |
276 assert(_result->is_valid(), "must be valid"); visitor->do_output(_result); | |
277 } | |
278 #ifndef PRODUCT | |
279 virtual void print_name(outputStream* out) const { out->print("NewObjectArrayStub"); } | |
280 #endif // PRODUCT | |
281 }; | |
282 | |
283 | |
284 class MonitorAccessStub: public CodeStub { | |
285 protected: | |
286 LIR_Opr _obj_reg; | |
287 LIR_Opr _lock_reg; | |
288 | |
289 public: | |
290 MonitorAccessStub(LIR_Opr obj_reg, LIR_Opr lock_reg) { | |
291 _obj_reg = obj_reg; | |
292 _lock_reg = lock_reg; | |
293 } | |
294 | |
295 #ifndef PRODUCT | |
296 virtual void print_name(outputStream* out) const { out->print("MonitorAccessStub"); } | |
297 #endif // PRODUCT | |
298 }; | |
299 | |
300 | |
301 class MonitorEnterStub: public MonitorAccessStub { | |
302 private: | |
303 CodeEmitInfo* _info; | |
304 | |
305 public: | |
306 MonitorEnterStub(LIR_Opr obj_reg, LIR_Opr lock_reg, CodeEmitInfo* info); | |
307 | |
308 virtual void emit_code(LIR_Assembler* e); | |
309 virtual CodeEmitInfo* info() const { return _info; } | |
310 virtual void visit(LIR_OpVisitState* visitor) { | |
311 visitor->do_input(_obj_reg); | |
312 visitor->do_input(_lock_reg); | |
313 visitor->do_slow_case(_info); | |
314 } | |
315 #ifndef PRODUCT | |
316 virtual void print_name(outputStream* out) const { out->print("MonitorEnterStub"); } | |
317 #endif // PRODUCT | |
318 }; | |
319 | |
320 | |
321 class MonitorExitStub: public MonitorAccessStub { | |
322 private: | |
323 bool _compute_lock; | |
324 int _monitor_ix; | |
325 | |
326 public: | |
327 MonitorExitStub(LIR_Opr lock_reg, bool compute_lock, int monitor_ix) | |
328 : MonitorAccessStub(LIR_OprFact::illegalOpr, lock_reg), | |
329 _compute_lock(compute_lock), _monitor_ix(monitor_ix) { } | |
330 virtual void emit_code(LIR_Assembler* e); | |
331 virtual void visit(LIR_OpVisitState* visitor) { | |
332 assert(_obj_reg->is_illegal(), "unused"); | |
333 if (_compute_lock) { | |
334 visitor->do_temp(_lock_reg); | |
335 } else { | |
336 visitor->do_input(_lock_reg); | |
337 } | |
338 } | |
339 #ifndef PRODUCT | |
340 virtual void print_name(outputStream* out) const { out->print("MonitorExitStub"); } | |
341 #endif // PRODUCT | |
342 }; | |
343 | |
344 | |
345 class PatchingStub: public CodeStub { | |
346 public: | |
347 enum PatchID { | |
348 access_field_id, | |
349 load_klass_id | |
350 }; | |
351 enum constants { | |
352 patch_info_size = 3 | |
353 }; | |
354 private: | |
355 PatchID _id; | |
356 address _pc_start; | |
357 int _bytes_to_copy; | |
358 Label _patched_code_entry; | |
359 Label _patch_site_entry; | |
360 Label _patch_site_continuation; | |
361 Register _obj; | |
362 CodeEmitInfo* _info; | |
363 int _oop_index; // index of the patchable oop in nmethod oop table if needed | |
364 static int _patch_info_offset; | |
365 | |
366 void align_patch_site(MacroAssembler* masm); | |
367 | |
368 public: | |
369 static int patch_info_offset() { return _patch_info_offset; } | |
370 | |
371 PatchingStub(MacroAssembler* masm, PatchID id, int oop_index = -1): | |
372 _id(id) | |
373 , _info(NULL) | |
374 , _oop_index(oop_index) { | |
375 if (os::is_MP()) { | |
376 // force alignment of patch sites on MP hardware so we | |
377 // can guarantee atomic writes to the patch site. | |
378 align_patch_site(masm); | |
379 } | |
380 _pc_start = masm->pc(); | |
381 masm->bind(_patch_site_entry); | |
382 } | |
383 | |
384 void install(MacroAssembler* masm, LIR_PatchCode patch_code, Register obj, CodeEmitInfo* info) { | |
385 _info = info; | |
386 _obj = obj; | |
387 masm->bind(_patch_site_continuation); | |
388 _bytes_to_copy = masm->pc() - pc_start(); | |
389 if (_id == PatchingStub::access_field_id) { | |
390 // embed a fixed offset to handle long patches which need to be offset by a word. | |
391 // the patching code will just add the field offset field to this offset so | |
392 // that we can refernce either the high or low word of a double word field. | |
393 int field_offset = 0; | |
394 switch (patch_code) { | |
395 case lir_patch_low: field_offset = lo_word_offset_in_bytes; break; | |
396 case lir_patch_high: field_offset = hi_word_offset_in_bytes; break; | |
397 case lir_patch_normal: field_offset = 0; break; | |
398 default: ShouldNotReachHere(); | |
399 } | |
400 NativeMovRegMem* n_move = nativeMovRegMem_at(pc_start()); | |
401 n_move->set_offset(field_offset); | |
402 } else if (_id == load_klass_id) { | |
403 assert(_obj != noreg, "must have register object for load_klass"); | |
404 #ifdef ASSERT | |
405 // verify that we're pointing at a NativeMovConstReg | |
406 nativeMovConstReg_at(pc_start()); | |
407 #endif | |
408 } else { | |
409 ShouldNotReachHere(); | |
410 } | |
411 assert(_bytes_to_copy <= (masm->pc() - pc_start()), "not enough bytes"); | |
412 } | |
413 | |
414 address pc_start() const { return _pc_start; } | |
415 PatchID id() const { return _id; } | |
416 | |
417 virtual void emit_code(LIR_Assembler* e); | |
418 virtual CodeEmitInfo* info() const { return _info; } | |
419 virtual void visit(LIR_OpVisitState* visitor) { | |
420 visitor->do_slow_case(_info); | |
421 } | |
422 #ifndef PRODUCT | |
423 virtual void print_name(outputStream* out) const { out->print("PatchingStub"); } | |
424 #endif // PRODUCT | |
425 }; | |
426 | |
427 | |
1295 | 428 //------------------------------------------------------------------------------ |
429 // DeoptimizeStub | |
430 // | |
431 class DeoptimizeStub : public CodeStub { | |
432 private: | |
433 CodeEmitInfo* _info; | |
434 | |
435 public: | |
436 DeoptimizeStub(CodeEmitInfo* info) : _info(new CodeEmitInfo(info)) {} | |
437 | |
438 virtual void emit_code(LIR_Assembler* e); | |
439 virtual CodeEmitInfo* info() const { return _info; } | |
440 virtual bool is_exception_throw_stub() const { return true; } | |
441 virtual void visit(LIR_OpVisitState* visitor) { | |
442 visitor->do_slow_case(_info); | |
443 } | |
444 #ifndef PRODUCT | |
445 virtual void print_name(outputStream* out) const { out->print("DeoptimizeStub"); } | |
446 #endif // PRODUCT | |
447 }; | |
448 | |
449 | |
0 | 450 class SimpleExceptionStub: public CodeStub { |
451 private: | |
452 LIR_Opr _obj; | |
453 Runtime1::StubID _stub; | |
454 CodeEmitInfo* _info; | |
455 | |
456 public: | |
457 SimpleExceptionStub(Runtime1::StubID stub, LIR_Opr obj, CodeEmitInfo* info): | |
458 _obj(obj), _info(info), _stub(stub) { | |
459 } | |
460 | |
1681
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1552
diff
changeset
|
461 void set_obj(LIR_Opr obj) { |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1552
diff
changeset
|
462 _obj = obj; |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1552
diff
changeset
|
463 } |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1552
diff
changeset
|
464 |
0 | 465 virtual void emit_code(LIR_Assembler* e); |
466 virtual CodeEmitInfo* info() const { return _info; } | |
467 virtual bool is_exception_throw_stub() const { return true; } | |
468 virtual void visit(LIR_OpVisitState* visitor) { | |
469 if (_obj->is_valid()) visitor->do_input(_obj); | |
470 visitor->do_slow_case(_info); | |
471 } | |
472 #ifndef PRODUCT | |
473 virtual void print_name(outputStream* out) const { out->print("SimpleExceptionStub"); } | |
474 #endif // PRODUCT | |
475 }; | |
476 | |
477 | |
478 | |
2168
e4fee0bdaa85
7008809: should report the class in ArrayStoreExceptions from compiled code
never
parents:
1972
diff
changeset
|
479 class ArrayStoreExceptionStub: public SimpleExceptionStub { |
0 | 480 private: |
481 CodeEmitInfo* _info; | |
482 | |
483 public: | |
2168
e4fee0bdaa85
7008809: should report the class in ArrayStoreExceptions from compiled code
never
parents:
1972
diff
changeset
|
484 ArrayStoreExceptionStub(LIR_Opr obj, CodeEmitInfo* info): SimpleExceptionStub(Runtime1::throw_array_store_exception_id, obj, info) {} |
0 | 485 #ifndef PRODUCT |
486 virtual void print_name(outputStream* out) const { out->print("ArrayStoreExceptionStub"); } | |
487 #endif // PRODUCT | |
488 }; | |
489 | |
490 | |
491 class ArrayCopyStub: public CodeStub { | |
492 private: | |
493 LIR_OpArrayCopy* _op; | |
494 | |
495 public: | |
496 ArrayCopyStub(LIR_OpArrayCopy* op): _op(op) { } | |
497 | |
498 LIR_Opr src() const { return _op->src(); } | |
499 LIR_Opr src_pos() const { return _op->src_pos(); } | |
500 LIR_Opr dst() const { return _op->dst(); } | |
501 LIR_Opr dst_pos() const { return _op->dst_pos(); } | |
502 LIR_Opr length() const { return _op->length(); } | |
503 LIR_Opr tmp() const { return _op->tmp(); } | |
504 | |
505 virtual void emit_code(LIR_Assembler* e); | |
506 virtual CodeEmitInfo* info() const { return _op->info(); } | |
507 virtual void visit(LIR_OpVisitState* visitor) { | |
508 // don't pass in the code emit info since it's processed in the fast path | |
509 visitor->do_slow_case(); | |
510 } | |
511 #ifndef PRODUCT | |
512 virtual void print_name(outputStream* out) const { out->print("ArrayCopyStub"); } | |
513 #endif // PRODUCT | |
514 }; | |
342 | 515 |
516 ////////////////////////////////////////////////////////////////////////////////////////// | |
517 #ifndef SERIALGC | |
518 | |
519 // Code stubs for Garbage-First barriers. | |
520 class G1PreBarrierStub: public CodeStub { | |
521 private: | |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
522 bool _do_load; |
342 | 523 LIR_Opr _addr; |
524 LIR_Opr _pre_val; | |
525 LIR_PatchCode _patch_code; | |
526 CodeEmitInfo* _info; | |
527 | |
528 public: | |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
529 // Version that _does_ generate a load of the previous value from addr. |
342 | 530 // addr (the address of the field to be read) must be a LIR_Address |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
531 // pre_val (a temporary register) must be a register; |
342 | 532 G1PreBarrierStub(LIR_Opr addr, LIR_Opr pre_val, LIR_PatchCode patch_code, CodeEmitInfo* info) : |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
533 _addr(addr), _pre_val(pre_val), _do_load(true), |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
534 _patch_code(patch_code), _info(info) |
342 | 535 { |
536 assert(_pre_val->is_register(), "should be temporary register"); | |
537 assert(_addr->is_address(), "should be the address of the field"); | |
538 } | |
539 | |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
540 // Version that _does not_ generate load of the previous value; the |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
541 // previous value is assumed to have already been loaded into pre_val. |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
542 G1PreBarrierStub(LIR_Opr pre_val) : |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
543 _addr(LIR_OprFact::illegalOpr), _pre_val(pre_val), _do_load(false), |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
544 _patch_code(lir_patch_none), _info(NULL) |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
545 { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
546 assert(_pre_val->is_register(), "should be a register"); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
547 } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
548 |
342 | 549 LIR_Opr addr() const { return _addr; } |
550 LIR_Opr pre_val() const { return _pre_val; } | |
551 LIR_PatchCode patch_code() const { return _patch_code; } | |
552 CodeEmitInfo* info() const { return _info; } | |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
553 bool do_load() const { return _do_load; } |
342 | 554 |
555 virtual void emit_code(LIR_Assembler* e); | |
556 virtual void visit(LIR_OpVisitState* visitor) { | |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
557 if (_do_load) { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
558 // don't pass in the code emit info since it's processed in the fast |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
559 // path |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
560 if (_info != NULL) |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
561 visitor->do_slow_case(_info); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
562 else |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
563 visitor->do_slow_case(); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
564 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
565 visitor->do_input(_addr); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
566 visitor->do_temp(_pre_val); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
567 } else { |
342 | 568 visitor->do_slow_case(); |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
569 visitor->do_input(_pre_val); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
570 } |
342 | 571 } |
572 #ifndef PRODUCT | |
573 virtual void print_name(outputStream* out) const { out->print("G1PreBarrierStub"); } | |
574 #endif // PRODUCT | |
575 }; | |
576 | |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
577 // This G1 barrier code stub is used in Unsafe.getObject. |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
578 // It generates a sequence of guards around the SATB |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
579 // barrier code that are used to detect when we have |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
580 // the referent field of a Reference object. |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
581 // The first check is assumed to have been generated |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
582 // in the code generated for Unsafe.getObject(). |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
583 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
584 class G1UnsafeGetObjSATBBarrierStub: public CodeStub { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
585 private: |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
586 LIR_Opr _val; |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
587 LIR_Opr _src; |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
588 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
589 LIR_Opr _tmp; |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
590 LIR_Opr _thread; |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
591 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
592 bool _gen_src_check; |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
593 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
594 public: |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
595 // A G1 barrier that is guarded by generated guards that determine whether |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
596 // val (which is the result of Unsafe.getObject() should be recorded in an |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
597 // SATB log buffer. We could be reading the referent field of a Reference object |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
598 // using Unsafe.getObject() and we need to record the referent. |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
599 // |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
600 // * val is the operand returned by the unsafe.getObject routine. |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
601 // * src is the base object |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
602 // * tmp is a temp used to load the klass of src, and then reference type |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
603 // * thread is the thread object. |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
604 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
605 G1UnsafeGetObjSATBBarrierStub(LIR_Opr val, LIR_Opr src, |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
606 LIR_Opr tmp, LIR_Opr thread, |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
607 bool gen_src_check) : |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
608 _val(val), _src(src), |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
609 _tmp(tmp), _thread(thread), |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
610 _gen_src_check(gen_src_check) |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
611 { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
612 assert(_val->is_register(), "should have already been loaded"); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
613 assert(_src->is_register(), "should have already been loaded"); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
614 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
615 assert(_tmp->is_register(), "should be a temporary register"); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
616 } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
617 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
618 LIR_Opr val() const { return _val; } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
619 LIR_Opr src() const { return _src; } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
620 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
621 LIR_Opr tmp() const { return _tmp; } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
622 LIR_Opr thread() const { return _thread; } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
623 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
624 bool gen_src_check() const { return _gen_src_check; } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
625 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
626 virtual void emit_code(LIR_Assembler* e); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
627 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
628 virtual void visit(LIR_OpVisitState* visitor) { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
629 visitor->do_slow_case(); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
630 visitor->do_input(_val); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
631 visitor->do_input(_src); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
632 visitor->do_input(_thread); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
633 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
634 visitor->do_temp(_tmp); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
635 } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
636 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
637 #ifndef PRODUCT |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
638 virtual void print_name(outputStream* out) const { out->print("G1UnsafeGetObjSATBBarrierStub"); } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
639 #endif // PRODUCT |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
640 }; |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2168
diff
changeset
|
641 |
342 | 642 class G1PostBarrierStub: public CodeStub { |
643 private: | |
644 LIR_Opr _addr; | |
645 LIR_Opr _new_val; | |
646 | |
647 static jbyte* _byte_map_base; | |
648 static jbyte* byte_map_base_slow(); | |
649 static jbyte* byte_map_base() { | |
650 if (_byte_map_base == NULL) { | |
651 _byte_map_base = byte_map_base_slow(); | |
652 } | |
653 return _byte_map_base; | |
654 } | |
655 | |
656 public: | |
657 // addr (the address of the object head) and new_val must be registers. | |
658 G1PostBarrierStub(LIR_Opr addr, LIR_Opr new_val): _addr(addr), _new_val(new_val) { } | |
659 | |
660 LIR_Opr addr() const { return _addr; } | |
661 LIR_Opr new_val() const { return _new_val; } | |
662 | |
663 virtual void emit_code(LIR_Assembler* e); | |
664 virtual void visit(LIR_OpVisitState* visitor) { | |
665 // don't pass in the code emit info since it's processed in the fast path | |
666 visitor->do_slow_case(); | |
667 visitor->do_input(_addr); | |
668 visitor->do_input(_new_val); | |
669 } | |
670 #ifndef PRODUCT | |
671 virtual void print_name(outputStream* out) const { out->print("G1PostBarrierStub"); } | |
672 #endif // PRODUCT | |
673 }; | |
674 | |
675 #endif // SERIALGC | |
676 ////////////////////////////////////////////////////////////////////////////////////////// | |
1972 | 677 |
678 #endif // SHARE_VM_C1_C1_CODESTUBS_HPP |