author | phh |
Sat, 30 Nov 2019 14:33:05 -0800 | |
changeset 59330 | 5b96c12f909d |
parent 58273 | 08a5148e7c4e |
permissions | -rw-r--r-- |
49484
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
1 |
/* |
53747
13acc8e38a29
8218089: Rename DirtyCardQueue et al to follow usual G1 naming conventions
kbarrett
parents:
51368
diff
changeset
|
2 |
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. |
49484
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
3 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
4 |
* |
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
5 |
* This code is free software; you can redistribute it and/or modify it |
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
6 |
* under the terms of the GNU General Public License version 2 only, as |
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
7 |
* published by the Free Software Foundation. |
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
8 |
* |
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
9 |
* This code is distributed in the hope that it will be useful, but WITHOUT |
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
10 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
11 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
12 |
* version 2 for more details (a copy is included in the LICENSE file that |
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
13 |
* accompanied this code). |
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
14 |
* |
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
15 |
* You should have received a copy of the GNU General Public License version |
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
16 |
* 2 along with this work; if not, write to the Free Software Foundation, |
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
17 |
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
18 |
* |
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
19 |
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
20 |
* or visit www.oracle.com if you need additional information or have any |
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
21 |
* questions. |
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
22 |
* |
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
23 |
*/ |
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
24 |
|
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
25 |
#include "precompiled.hpp" |
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
26 |
#include "asm/macroAssembler.inline.hpp" |
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
27 |
#include "gc/g1/g1BarrierSet.hpp" |
49906 | 28 |
#include "gc/g1/g1BarrierSetAssembler.hpp" |
50375
bfbe7d8369bb
8202547: Move G1 runtime calls used by generated code to G1BarrierSetRuntime
eosterlund
parents:
49906
diff
changeset
|
29 |
#include "gc/g1/g1BarrierSetRuntime.hpp" |
49484
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
30 |
#include "gc/g1/g1CardTable.hpp" |
53747
13acc8e38a29
8218089: Rename DirtyCardQueue et al to follow usual G1 naming conventions
kbarrett
parents:
51368
diff
changeset
|
31 |
#include "gc/g1/g1DirtyCardQueue.hpp" |
51368
adcb0bb3d1e9
8209118: Abstract SATBMarkQueueSet's ThreadLocalData access
rkennke
parents:
50803
diff
changeset
|
32 |
#include "gc/g1/g1SATBMarkQueueSet.hpp" |
49752
93d84f667d12
8201318: Introduce GCThreadLocalData to abstract GC-specific data belonging to a thread
pliden
parents:
49748
diff
changeset
|
33 |
#include "gc/g1/g1ThreadLocalData.hpp" |
49484
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
34 |
#include "gc/g1/heapRegion.hpp" |
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
35 |
#include "interpreter/interp_masm.hpp" |
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
36 |
#include "runtime/sharedRuntime.hpp" |
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
37 |
#include "utilities/macros.hpp" |
49906 | 38 |
#ifdef COMPILER1 |
39 |
#include "c1/c1_LIRAssembler.hpp" |
|
40 |
#include "c1/c1_MacroAssembler.hpp" |
|
41 |
#include "gc/g1/c1/g1BarrierSetC1.hpp" |
|
42 |
#endif |
|
49484
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
43 |
|
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
44 |
#define __ masm-> |
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
45 |
|
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
46 |
void G1BarrierSetAssembler::gen_write_ref_array_pre_barrier(MacroAssembler* masm, DecoratorSet decorators, |
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
47 |
Register addr, Register count) { |
50728 | 48 |
bool dest_uninitialized = (decorators & IS_DEST_UNINITIALIZED) != 0; |
49484
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
49 |
// With G1, don't generate the call if we statically know that the target in uninitialized |
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
50 |
if (!dest_uninitialized) { |
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
51 |
Register tmp = O5; |
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
52 |
assert_different_registers(addr, count, tmp); |
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
53 |
Label filtered; |
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
54 |
// Is marking active? |
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
55 |
if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) { |
49752
93d84f667d12
8201318: Introduce GCThreadLocalData to abstract GC-specific data belonging to a thread
pliden
parents:
49748
diff
changeset
|
56 |
__ ld(G2, in_bytes(G1ThreadLocalData::satb_mark_queue_active_offset()), tmp); |
49484
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
57 |
} else { |
49752
93d84f667d12
8201318: Introduce GCThreadLocalData to abstract GC-specific data belonging to a thread
pliden
parents:
49748
diff
changeset
|
58 |
guarantee(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption"); |
93d84f667d12
8201318: Introduce GCThreadLocalData to abstract GC-specific data belonging to a thread
pliden
parents:
49748
diff
changeset
|
59 |
__ ldsb(G2, in_bytes(G1ThreadLocalData::satb_mark_queue_active_offset()), tmp); |
49484
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
60 |
} |
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
61 |
// Is marking active? |
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
62 |
__ cmp_and_br_short(tmp, G0, Assembler::equal, Assembler::pt, filtered); |
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
63 |
|
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
64 |
__ save_frame(0); |
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
65 |
// Save the necessary global regs... will be used after. |
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
66 |
if (addr->is_global()) { |
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
67 |
__ mov(addr, L0); |
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
68 |
} |
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
69 |
if (count->is_global()) { |
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
70 |
__ mov(count, L1); |
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
71 |
} |
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
72 |
__ mov(addr->after_save(), O0); |
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
73 |
// Get the count into O1 |
50375
bfbe7d8369bb
8202547: Move G1 runtime calls used by generated code to G1BarrierSetRuntime
eosterlund
parents:
49906
diff
changeset
|
74 |
address slowpath = UseCompressedOops ? CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_array_pre_narrow_oop_entry) |
bfbe7d8369bb
8202547: Move G1 runtime calls used by generated code to G1BarrierSetRuntime
eosterlund
parents:
49906
diff
changeset
|
75 |
: CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_array_pre_oop_entry); |
49484
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
76 |
__ call(slowpath); |
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
77 |
__ delayed()->mov(count->after_save(), O1); |
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
78 |
if (addr->is_global()) { |
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
79 |
__ mov(L0, addr); |
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
80 |
} |
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
81 |
if (count->is_global()) { |
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
82 |
__ mov(L1, count); |
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
83 |
} |
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
84 |
__ restore(); |
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
85 |
|
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
86 |
__ bind(filtered); |
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
87 |
DEBUG_ONLY(__ set(0xDEADC0DE, tmp);) // we have killed tmp |
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
88 |
} |
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
89 |
} |
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
90 |
|
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
91 |
void G1BarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators, |
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
92 |
Register addr, Register count, Register tmp) { |
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
93 |
// Get some new fresh output registers. |
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
94 |
__ save_frame(0); |
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
95 |
__ mov(addr->after_save(), O0); |
50375
bfbe7d8369bb
8202547: Move G1 runtime calls used by generated code to G1BarrierSetRuntime
eosterlund
parents:
49906
diff
changeset
|
96 |
__ call(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_array_post_entry)); |
49484
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
97 |
__ delayed()->mov(count->after_save(), O1); |
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
98 |
__ restore(); |
ee8fa73b90f9
8198949: Modularize arraycopy stub routine GC barriers
eosterlund
parents:
diff
changeset
|
99 |
} |
49748 | 100 |
|
101 |
#undef __ |
|
102 |
||
103 |
static address satb_log_enqueue_with_frame = NULL; |
|
104 |
static u_char* satb_log_enqueue_with_frame_end = NULL; |
|
105 |
||
106 |
static address satb_log_enqueue_frameless = NULL; |
|
107 |
static u_char* satb_log_enqueue_frameless_end = NULL; |
|
108 |
||
109 |
static int EnqueueCodeSize = 128 DEBUG_ONLY( + 256); // Instructions? |
|
110 |
||
111 |
static void generate_satb_log_enqueue(bool with_frame) { |
|
112 |
BufferBlob* bb = BufferBlob::create("enqueue_with_frame", EnqueueCodeSize); |
|
113 |
CodeBuffer buf(bb); |
|
114 |
MacroAssembler masm(&buf); |
|
115 |
||
116 |
#define __ masm. |
|
117 |
||
118 |
address start = __ pc(); |
|
119 |
Register pre_val; |
|
120 |
||
121 |
Label refill, restart; |
|
122 |
if (with_frame) { |
|
123 |
__ save_frame(0); |
|
124 |
pre_val = I0; // Was O0 before the save. |
|
125 |
} else { |
|
126 |
pre_val = O0; |
|
127 |
} |
|
128 |
||
49752
93d84f667d12
8201318: Introduce GCThreadLocalData to abstract GC-specific data belonging to a thread
pliden
parents:
49748
diff
changeset
|
129 |
int satb_q_index_byte_offset = in_bytes(G1ThreadLocalData::satb_mark_queue_index_offset()); |
93d84f667d12
8201318: Introduce GCThreadLocalData to abstract GC-specific data belonging to a thread
pliden
parents:
49748
diff
changeset
|
130 |
int satb_q_buf_byte_offset = in_bytes(G1ThreadLocalData::satb_mark_queue_buffer_offset()); |
49748 | 131 |
|
132 |
assert(in_bytes(SATBMarkQueue::byte_width_of_index()) == sizeof(intptr_t) && |
|
133 |
in_bytes(SATBMarkQueue::byte_width_of_buf()) == sizeof(intptr_t), |
|
134 |
"check sizes in assembly below"); |
|
135 |
||
136 |
__ bind(restart); |
|
137 |
||
138 |
// Load the index into the SATB buffer. SATBMarkQueue::_index is a size_t |
|
139 |
// so ld_ptr is appropriate. |
|
140 |
__ ld_ptr(G2_thread, satb_q_index_byte_offset, L0); |
|
141 |
||
142 |
// index == 0? |
|
143 |
__ cmp_and_brx_short(L0, G0, Assembler::equal, Assembler::pn, refill); |
|
144 |
||
145 |
__ ld_ptr(G2_thread, satb_q_buf_byte_offset, L1); |
|
146 |
__ sub(L0, oopSize, L0); |
|
147 |
||
148 |
__ st_ptr(pre_val, L1, L0); // [_buf + index] := I0 |
|
149 |
if (!with_frame) { |
|
150 |
// Use return-from-leaf |
|
151 |
__ retl(); |
|
152 |
__ delayed()->st_ptr(L0, G2_thread, satb_q_index_byte_offset); |
|
153 |
} else { |
|
154 |
// Not delayed. |
|
155 |
__ st_ptr(L0, G2_thread, satb_q_index_byte_offset); |
|
156 |
} |
|
157 |
if (with_frame) { |
|
158 |
__ ret(); |
|
159 |
__ delayed()->restore(); |
|
160 |
} |
|
161 |
__ bind(refill); |
|
162 |
||
163 |
address handle_zero = |
|
164 |
CAST_FROM_FN_PTR(address, |
|
51368
adcb0bb3d1e9
8209118: Abstract SATBMarkQueueSet's ThreadLocalData access
rkennke
parents:
50803
diff
changeset
|
165 |
&G1SATBMarkQueueSet::handle_zero_index_for_thread); |
49748 | 166 |
// This should be rare enough that we can afford to save all the |
167 |
// scratch registers that the calling context might be using. |
|
168 |
__ mov(G1_scratch, L0); |
|
169 |
__ mov(G3_scratch, L1); |
|
170 |
__ mov(G4, L2); |
|
171 |
// We need the value of O0 above (for the write into the buffer), so we |
|
172 |
// save and restore it. |
|
173 |
__ mov(O0, L3); |
|
174 |
// Since the call will overwrite O7, we save and restore that, as well. |
|
175 |
__ mov(O7, L4); |
|
176 |
__ call_VM_leaf(L5, handle_zero, G2_thread); |
|
177 |
__ mov(L0, G1_scratch); |
|
178 |
__ mov(L1, G3_scratch); |
|
179 |
__ mov(L2, G4); |
|
180 |
__ mov(L3, O0); |
|
181 |
__ br(Assembler::always, /*annul*/false, Assembler::pt, restart); |
|
182 |
__ delayed()->mov(L4, O7); |
|
183 |
||
184 |
if (with_frame) { |
|
185 |
satb_log_enqueue_with_frame = start; |
|
186 |
satb_log_enqueue_with_frame_end = __ pc(); |
|
187 |
} else { |
|
188 |
satb_log_enqueue_frameless = start; |
|
189 |
satb_log_enqueue_frameless_end = __ pc(); |
|
190 |
} |
|
191 |
||
192 |
#undef __ |
|
193 |
} |
|
194 |
||
195 |
#define __ masm-> |
|
196 |
||
197 |
void G1BarrierSetAssembler::g1_write_barrier_pre(MacroAssembler* masm, |
|
198 |
Register obj, |
|
199 |
Register index, |
|
200 |
int offset, |
|
201 |
Register pre_val, |
|
202 |
Register tmp, |
|
203 |
bool preserve_o_regs) { |
|
204 |
Label filtered; |
|
205 |
||
206 |
if (obj == noreg) { |
|
207 |
// We are not loading the previous value so make |
|
208 |
// sure that we don't trash the value in pre_val |
|
209 |
// with the code below. |
|
210 |
assert_different_registers(pre_val, tmp); |
|
211 |
} else { |
|
212 |
// We will be loading the previous value |
|
213 |
// in this code so... |
|
214 |
assert(offset == 0 || index == noreg, "choose one"); |
|
215 |
assert(pre_val == noreg, "check this code"); |
|
216 |
} |
|
217 |
||
218 |
// Is marking active? |
|
219 |
if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) { |
|
49752
93d84f667d12
8201318: Introduce GCThreadLocalData to abstract GC-specific data belonging to a thread
pliden
parents:
49748
diff
changeset
|
220 |
__ ld(G2, in_bytes(G1ThreadLocalData::satb_mark_queue_active_offset()), tmp); |
49748 | 221 |
} else { |
49752
93d84f667d12
8201318: Introduce GCThreadLocalData to abstract GC-specific data belonging to a thread
pliden
parents:
49748
diff
changeset
|
222 |
guarantee(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption"); |
93d84f667d12
8201318: Introduce GCThreadLocalData to abstract GC-specific data belonging to a thread
pliden
parents:
49748
diff
changeset
|
223 |
__ ldsb(G2, in_bytes(G1ThreadLocalData::satb_mark_queue_active_offset()), tmp); |
49748 | 224 |
} |
225 |
||
226 |
// Is marking active? |
|
227 |
__ cmp_and_br_short(tmp, G0, Assembler::equal, Assembler::pt, filtered); |
|
228 |
||
229 |
// Do we need to load the previous value? |
|
230 |
if (obj != noreg) { |
|
231 |
// Load the previous value... |
|
232 |
if (index == noreg) { |
|
233 |
if (Assembler::is_simm13(offset)) { |
|
234 |
__ load_heap_oop(obj, offset, tmp); |
|
235 |
} else { |
|
236 |
__ set(offset, tmp); |
|
237 |
__ load_heap_oop(obj, tmp, tmp); |
|
238 |
} |
|
239 |
} else { |
|
240 |
__ load_heap_oop(obj, index, tmp); |
|
241 |
} |
|
242 |
// Previous value has been loaded into tmp |
|
243 |
pre_val = tmp; |
|
244 |
} |
|
245 |
||
246 |
assert(pre_val != noreg, "must have a real register"); |
|
247 |
||
248 |
// Is the previous value null? |
|
249 |
__ cmp_and_brx_short(pre_val, G0, Assembler::equal, Assembler::pt, filtered); |
|
250 |
||
251 |
// OK, it's not filtered, so we'll need to call enqueue. In the normal |
|
252 |
// case, pre_val will be a scratch G-reg, but there are some cases in |
|
253 |
// which it's an O-reg. In the first case, do a normal call. In the |
|
254 |
// latter, do a save here and call the frameless version. |
|
255 |
||
256 |
guarantee(pre_val->is_global() || pre_val->is_out(), |
|
257 |
"Or we need to think harder."); |
|
258 |
||
259 |
if (pre_val->is_global() && !preserve_o_regs) { |
|
260 |
__ call(satb_log_enqueue_with_frame); |
|
261 |
__ delayed()->mov(pre_val, O0); |
|
262 |
} else { |
|
263 |
__ save_frame(0); |
|
264 |
__ call(satb_log_enqueue_frameless); |
|
265 |
__ delayed()->mov(pre_val->after_save(), O0); |
|
266 |
__ restore(); |
|
267 |
} |
|
268 |
||
269 |
__ bind(filtered); |
|
270 |
} |
|
271 |
||
272 |
#undef __ |
|
273 |
||
274 |
static address dirty_card_log_enqueue = 0; |
|
275 |
static u_char* dirty_card_log_enqueue_end = 0; |
|
276 |
||
277 |
// This gets to assume that o0 contains the object address. |
|
54110 | 278 |
static void generate_dirty_card_log_enqueue(CardTable::CardValue* byte_map_base) { |
49748 | 279 |
BufferBlob* bb = BufferBlob::create("dirty_card_enqueue", EnqueueCodeSize*2); |
280 |
CodeBuffer buf(bb); |
|
281 |
MacroAssembler masm(&buf); |
|
282 |
#define __ masm. |
|
283 |
address start = __ pc(); |
|
284 |
||
285 |
Label not_already_dirty, restart, refill, young_card; |
|
286 |
||
287 |
__ srlx(O0, CardTable::card_shift, O0); |
|
288 |
AddressLiteral addrlit(byte_map_base); |
|
289 |
__ set(addrlit, O1); // O1 := <card table base> |
|
290 |
__ ldub(O0, O1, O2); // O2 := [O0 + O1] |
|
291 |
||
292 |
__ cmp_and_br_short(O2, G1CardTable::g1_young_card_val(), Assembler::equal, Assembler::pt, young_card); |
|
293 |
||
294 |
__ membar(Assembler::Membar_mask_bits(Assembler::StoreLoad)); |
|
295 |
__ ldub(O0, O1, O2); // O2 := [O0 + O1] |
|
296 |
||
297 |
assert(G1CardTable::dirty_card_val() == 0, "otherwise check this code"); |
|
298 |
__ cmp_and_br_short(O2, G0, Assembler::notEqual, Assembler::pt, not_already_dirty); |
|
299 |
||
300 |
__ bind(young_card); |
|
301 |
// We didn't take the branch, so we're already dirty: return. |
|
302 |
// Use return-from-leaf |
|
303 |
__ retl(); |
|
304 |
__ delayed()->nop(); |
|
305 |
||
306 |
// Not dirty. |
|
307 |
__ bind(not_already_dirty); |
|
308 |
||
309 |
// Get O0 + O1 into a reg by itself |
|
310 |
__ add(O0, O1, O3); |
|
311 |
||
312 |
// First, dirty it. |
|
313 |
__ stb(G0, O3, G0); // [cardPtr] := 0 (i.e., dirty). |
|
314 |
||
49752
93d84f667d12
8201318: Introduce GCThreadLocalData to abstract GC-specific data belonging to a thread
pliden
parents:
49748
diff
changeset
|
315 |
int dirty_card_q_index_byte_offset = in_bytes(G1ThreadLocalData::dirty_card_queue_index_offset()); |
93d84f667d12
8201318: Introduce GCThreadLocalData to abstract GC-specific data belonging to a thread
pliden
parents:
49748
diff
changeset
|
316 |
int dirty_card_q_buf_byte_offset = in_bytes(G1ThreadLocalData::dirty_card_queue_buffer_offset()); |
49748 | 317 |
__ bind(restart); |
318 |
||
53747
13acc8e38a29
8218089: Rename DirtyCardQueue et al to follow usual G1 naming conventions
kbarrett
parents:
51368
diff
changeset
|
319 |
// Load the index into the update buffer. G1DirtyCardQueue::_index is |
49748 | 320 |
// a size_t so ld_ptr is appropriate here. |
321 |
__ ld_ptr(G2_thread, dirty_card_q_index_byte_offset, L0); |
|
322 |
||
323 |
// index == 0? |
|
324 |
__ cmp_and_brx_short(L0, G0, Assembler::equal, Assembler::pn, refill); |
|
325 |
||
326 |
__ ld_ptr(G2_thread, dirty_card_q_buf_byte_offset, L1); |
|
327 |
__ sub(L0, oopSize, L0); |
|
328 |
||
329 |
__ st_ptr(O3, L1, L0); // [_buf + index] := I0 |
|
330 |
// Use return-from-leaf |
|
331 |
__ retl(); |
|
332 |
__ delayed()->st_ptr(L0, G2_thread, dirty_card_q_index_byte_offset); |
|
333 |
||
334 |
__ bind(refill); |
|
335 |
address handle_zero = |
|
336 |
CAST_FROM_FN_PTR(address, |
|
53747
13acc8e38a29
8218089: Rename DirtyCardQueue et al to follow usual G1 naming conventions
kbarrett
parents:
51368
diff
changeset
|
337 |
&G1DirtyCardQueueSet::handle_zero_index_for_thread); |
49748 | 338 |
// This should be rare enough that we can afford to save all the |
339 |
// scratch registers that the calling context might be using. |
|
340 |
__ mov(G1_scratch, L3); |
|
341 |
__ mov(G3_scratch, L5); |
|
342 |
// We need the value of O3 above (for the write into the buffer), so we |
|
343 |
// save and restore it. |
|
344 |
__ mov(O3, L6); |
|
345 |
// Since the call will overwrite O7, we save and restore that, as well. |
|
346 |
__ mov(O7, L4); |
|
347 |
||
348 |
__ call_VM_leaf(L7_thread_cache, handle_zero, G2_thread); |
|
349 |
__ mov(L3, G1_scratch); |
|
350 |
__ mov(L5, G3_scratch); |
|
351 |
__ mov(L6, O3); |
|
352 |
__ br(Assembler::always, /*annul*/false, Assembler::pt, restart); |
|
353 |
__ delayed()->mov(L4, O7); |
|
354 |
||
355 |
dirty_card_log_enqueue = start; |
|
356 |
dirty_card_log_enqueue_end = __ pc(); |
|
357 |
// XXX Should have a guarantee here about not going off the end! |
|
358 |
// Does it already do so? Do an experiment... |
|
359 |
||
360 |
#undef __ |
|
361 |
||
362 |
} |
|
363 |
||
364 |
#define __ masm-> |
|
365 |
||
366 |
void G1BarrierSetAssembler::g1_write_barrier_post(MacroAssembler* masm, Register store_addr, Register new_val, Register tmp) { |
|
367 |
Label filtered; |
|
368 |
MacroAssembler* post_filter_masm = masm; |
|
369 |
||
370 |
if (new_val == G0) return; |
|
371 |
||
49754 | 372 |
G1BarrierSet* bs = barrier_set_cast<G1BarrierSet>(BarrierSet::barrier_set()); |
49748 | 373 |
|
50440
cfdd37095f66
8204084: Remove the G1RSBarrierRegionFilter develop flag
tschatzl
parents:
50375
diff
changeset
|
374 |
__ xor3(store_addr, new_val, tmp); |
cfdd37095f66
8204084: Remove the G1RSBarrierRegionFilter develop flag
tschatzl
parents:
50375
diff
changeset
|
375 |
__ srlx(tmp, HeapRegion::LogOfHRGrainBytes, tmp); |
49748 | 376 |
|
50440
cfdd37095f66
8204084: Remove the G1RSBarrierRegionFilter develop flag
tschatzl
parents:
50375
diff
changeset
|
377 |
__ cmp_and_brx_short(tmp, G0, Assembler::equal, Assembler::pt, filtered); |
49748 | 378 |
|
379 |
// If the "store_addr" register is an "in" or "local" register, move it to |
|
380 |
// a scratch reg so we can pass it as an argument. |
|
381 |
bool use_scr = !(store_addr->is_global() || store_addr->is_out()); |
|
382 |
// Pick a scratch register different from "tmp". |
|
383 |
Register scr = (tmp == G1_scratch ? G3_scratch : G1_scratch); |
|
384 |
// Make sure we use up the delay slot! |
|
385 |
if (use_scr) { |
|
386 |
post_filter_masm->mov(store_addr, scr); |
|
387 |
} else { |
|
388 |
post_filter_masm->nop(); |
|
389 |
} |
|
390 |
__ save_frame(0); |
|
391 |
__ call(dirty_card_log_enqueue); |
|
392 |
if (use_scr) { |
|
393 |
__ delayed()->mov(scr, O0); |
|
394 |
} else { |
|
395 |
__ delayed()->mov(store_addr->after_save(), O0); |
|
396 |
} |
|
397 |
__ restore(); |
|
398 |
||
399 |
__ bind(filtered); |
|
400 |
} |
|
401 |
||
402 |
void G1BarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, |
|
403 |
Register val, Address dst, Register tmp) { |
|
404 |
bool in_heap = (decorators & IN_HEAP) != 0; |
|
50803
45c1fde86050
8205559: Remove IN_CONCURRENT_ROOT Access decorator
kbarrett
parents:
50728
diff
changeset
|
405 |
bool as_normal = (decorators & AS_NORMAL) != 0; |
45c1fde86050
8205559: Remove IN_CONCURRENT_ROOT Access decorator
kbarrett
parents:
50728
diff
changeset
|
406 |
assert((decorators & IS_DEST_UNINITIALIZED) == 0, "unsupported"); |
49748 | 407 |
|
50803
45c1fde86050
8205559: Remove IN_CONCURRENT_ROOT Access decorator
kbarrett
parents:
50728
diff
changeset
|
408 |
bool needs_pre_barrier = as_normal; |
49748 | 409 |
// No need for post barrier if storing NULL |
410 |
bool needs_post_barrier = val != G0 && in_heap; |
|
411 |
||
50728 | 412 |
bool is_array = (decorators & IS_ARRAY) != 0; |
49748 | 413 |
bool on_anonymous = (decorators & ON_UNKNOWN_OOP_REF) != 0; |
50728 | 414 |
bool precise = is_array || on_anonymous; |
49748 | 415 |
|
416 |
Register index = dst.has_index() ? dst.index() : noreg; |
|
417 |
int disp = dst.has_disp() ? dst.disp() : 0; |
|
418 |
||
419 |
if (needs_pre_barrier) { |
|
420 |
// Load and record the previous value. |
|
421 |
g1_write_barrier_pre(masm, dst.base(), index, disp, |
|
422 |
noreg /* pre_val */, |
|
423 |
tmp, true /*preserve_o_regs*/); |
|
424 |
} |
|
425 |
||
426 |
Register new_val = val; |
|
427 |
if (needs_post_barrier) { |
|
428 |
// G1 barrier needs uncompressed oop for region cross check. |
|
429 |
if (UseCompressedOops && val != G0) { |
|
430 |
new_val = tmp; |
|
431 |
__ mov(val, new_val); |
|
432 |
} |
|
433 |
} |
|
434 |
||
435 |
BarrierSetAssembler::store_at(masm, decorators, type, val, dst, tmp); |
|
436 |
||
437 |
if (needs_post_barrier) { |
|
438 |
Register base = dst.base(); |
|
439 |
if (precise) { |
|
440 |
if (!dst.has_index()) { |
|
441 |
__ add(base, disp, base); |
|
442 |
} else { |
|
443 |
assert(!dst.has_disp(), "not supported yet"); |
|
444 |
__ add(base, index, base); |
|
445 |
} |
|
446 |
} |
|
447 |
g1_write_barrier_post(masm, base, new_val, tmp); |
|
448 |
} |
|
449 |
} |
|
450 |
||
451 |
void G1BarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, |
|
452 |
Address src, Register dst, Register tmp) { |
|
58273
08a5148e7c4e
8230505: Replace JVM type comparisons to T_OBJECT and T_ARRAY with call to is_reference_type
lfoltan
parents:
54110
diff
changeset
|
453 |
bool on_oop = is_reference_type(type); |
49748 | 454 |
bool on_weak = (decorators & ON_WEAK_OOP_REF) != 0; |
455 |
bool on_phantom = (decorators & ON_PHANTOM_OOP_REF) != 0; |
|
456 |
bool on_reference = on_weak || on_phantom; |
|
457 |
// Load the value of the referent field. |
|
458 |
ModRefBarrierSetAssembler::load_at(masm, decorators, type, src, dst, tmp); |
|
459 |
if (on_oop && on_reference) { |
|
460 |
// Generate the G1 pre-barrier code to log the value of |
|
461 |
// the referent field in an SATB buffer. Note with |
|
462 |
// these parameters the pre-barrier does not generate |
|
463 |
// the load of the previous value |
|
464 |
||
465 |
Register pre_val = dst; |
|
466 |
bool saved = false; |
|
467 |
if (pre_val->is_in()) { |
|
468 |
// The g1_write_barrier_pre method assumes that the pre_val |
|
469 |
// is not in an input register. |
|
470 |
__ save_frame_and_mov(0, pre_val, O0); |
|
471 |
pre_val = O0; |
|
472 |
saved = true; |
|
473 |
} |
|
474 |
||
475 |
g1_write_barrier_pre(masm, noreg /* obj */, noreg /* index */, 0 /* offset */, |
|
476 |
pre_val /* pre_val */, |
|
477 |
tmp /* tmp */, |
|
478 |
true /* preserve_o_regs */); |
|
479 |
||
480 |
if (saved) { |
|
481 |
__ restore(); |
|
482 |
} |
|
483 |
} |
|
484 |
} |
|
485 |
||
486 |
void G1BarrierSetAssembler::barrier_stubs_init() { |
|
487 |
if (dirty_card_log_enqueue == 0) { |
|
488 |
G1BarrierSet* bs = barrier_set_cast<G1BarrierSet>(BarrierSet::barrier_set()); |
|
489 |
CardTable *ct = bs->card_table(); |
|
490 |
generate_dirty_card_log_enqueue(ct->byte_map_base()); |
|
491 |
assert(dirty_card_log_enqueue != 0, "postcondition."); |
|
492 |
} |
|
493 |
if (satb_log_enqueue_with_frame == 0) { |
|
494 |
generate_satb_log_enqueue(true); |
|
495 |
assert(satb_log_enqueue_with_frame != 0, "postcondition."); |
|
496 |
} |
|
497 |
if (satb_log_enqueue_frameless == 0) { |
|
498 |
generate_satb_log_enqueue(false); |
|
499 |
assert(satb_log_enqueue_frameless != 0, "postcondition."); |
|
500 |
} |
|
501 |
} |
|
49906 | 502 |
|
503 |
#ifdef COMPILER1 |
|
504 |
||
505 |
#undef __ |
|
506 |
#define __ ce->masm()-> |
|
507 |
||
508 |
void G1BarrierSetAssembler::gen_pre_barrier_stub(LIR_Assembler* ce, G1PreBarrierStub* stub) { |
|
509 |
G1BarrierSetC1* bs = (G1BarrierSetC1*)BarrierSet::barrier_set()->barrier_set_c1(); |
|
510 |
// At this point we know that marking is in progress. |
|
511 |
// If do_load() is true then we have to emit the |
|
512 |
// load of the previous value; otherwise it has already |
|
513 |
// been loaded into _pre_val. |
|
514 |
||
515 |
__ bind(*stub->entry()); |
|
516 |
||
517 |
assert(stub->pre_val()->is_register(), "Precondition."); |
|
518 |
Register pre_val_reg = stub->pre_val()->as_register(); |
|
519 |
||
520 |
if (stub->do_load()) { |
|
521 |
ce->mem2reg(stub->addr(), stub->pre_val(), T_OBJECT, stub->patch_code(), stub->info(), false /*wide*/, false /*unaligned*/); |
|
522 |
} |
|
523 |
||
524 |
if (__ is_in_wdisp16_range(*stub->continuation())) { |
|
525 |
__ br_null(pre_val_reg, /*annul*/false, Assembler::pt, *stub->continuation()); |
|
526 |
} else { |
|
527 |
__ cmp(pre_val_reg, G0); |
|
528 |
__ brx(Assembler::equal, false, Assembler::pn, *stub->continuation()); |
|
529 |
} |
|
530 |
__ delayed()->nop(); |
|
531 |
||
532 |
__ call(bs->pre_barrier_c1_runtime_code_blob()->code_begin()); |
|
533 |
__ delayed()->mov(pre_val_reg, G4); |
|
534 |
__ br(Assembler::always, false, Assembler::pt, *stub->continuation()); |
|
535 |
__ delayed()->nop(); |
|
536 |
} |
|
537 |
||
538 |
void G1BarrierSetAssembler::gen_post_barrier_stub(LIR_Assembler* ce, G1PostBarrierStub* stub) { |
|
539 |
G1BarrierSetC1* bs = (G1BarrierSetC1*)BarrierSet::barrier_set()->barrier_set_c1(); |
|
540 |
__ bind(*stub->entry()); |
|
541 |
||
542 |
assert(stub->addr()->is_register(), "Precondition."); |
|
543 |
assert(stub->new_val()->is_register(), "Precondition."); |
|
544 |
Register addr_reg = stub->addr()->as_pointer_register(); |
|
545 |
Register new_val_reg = stub->new_val()->as_register(); |
|
546 |
||
547 |
if (__ is_in_wdisp16_range(*stub->continuation())) { |
|
548 |
__ br_null(new_val_reg, /*annul*/false, Assembler::pt, *stub->continuation()); |
|
549 |
} else { |
|
550 |
__ cmp(new_val_reg, G0); |
|
551 |
__ brx(Assembler::equal, false, Assembler::pn, *stub->continuation()); |
|
552 |
} |
|
553 |
__ delayed()->nop(); |
|
554 |
||
555 |
__ call(bs->post_barrier_c1_runtime_code_blob()->code_begin()); |
|
556 |
__ delayed()->mov(addr_reg, G4); |
|
557 |
__ br(Assembler::always, false, Assembler::pt, *stub->continuation()); |
|
558 |
__ delayed()->nop(); |
|
559 |
} |
|
560 |
||
561 |
#undef __ |
|
562 |
#define __ sasm-> |
|
563 |
||
564 |
void G1BarrierSetAssembler::generate_c1_pre_barrier_runtime_stub(StubAssembler* sasm) { |
|
565 |
__ prologue("g1_pre_barrier", false); |
|
566 |
||
567 |
// G4: previous value of memory |
|
568 |
||
569 |
Register pre_val = G4; |
|
570 |
Register tmp = G1_scratch; |
|
571 |
Register tmp2 = G3_scratch; |
|
572 |
||
573 |
Label refill, restart; |
|
574 |
int satb_q_active_byte_offset = in_bytes(G1ThreadLocalData::satb_mark_queue_active_offset()); |
|
575 |
int satb_q_index_byte_offset = in_bytes(G1ThreadLocalData::satb_mark_queue_index_offset()); |
|
576 |
int satb_q_buf_byte_offset = in_bytes(G1ThreadLocalData::satb_mark_queue_buffer_offset()); |
|
577 |
||
578 |
// Is marking still active? |
|
579 |
if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) { |
|
580 |
__ ld(G2_thread, satb_q_active_byte_offset, tmp); |
|
581 |
} else { |
|
582 |
assert(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption"); |
|
583 |
__ ldsb(G2_thread, satb_q_active_byte_offset, tmp); |
|
584 |
} |
|
585 |
__ cmp_and_br_short(tmp, G0, Assembler::notEqual, Assembler::pt, restart); |
|
586 |
__ retl(); |
|
587 |
__ delayed()->nop(); |
|
588 |
||
589 |
__ bind(restart); |
|
590 |
// Load the index into the SATB buffer. SATBMarkQueue::_index is a |
|
591 |
// size_t so ld_ptr is appropriate |
|
592 |
__ ld_ptr(G2_thread, satb_q_index_byte_offset, tmp); |
|
593 |
||
594 |
// index == 0? |
|
595 |
__ cmp_and_brx_short(tmp, G0, Assembler::equal, Assembler::pn, refill); |
|
596 |
||
597 |
__ ld_ptr(G2_thread, satb_q_buf_byte_offset, tmp2); |
|
598 |
__ sub(tmp, oopSize, tmp); |
|
599 |
||
600 |
__ st_ptr(pre_val, tmp2, tmp); // [_buf + index] := <address_of_card> |
|
601 |
// Use return-from-leaf |
|
602 |
__ retl(); |
|
603 |
__ delayed()->st_ptr(tmp, G2_thread, satb_q_index_byte_offset); |
|
604 |
||
605 |
__ bind(refill); |
|
606 |
||
607 |
__ save_live_registers_no_oop_map(true); |
|
608 |
||
609 |
__ call_VM_leaf(L7_thread_cache, |
|
610 |
CAST_FROM_FN_PTR(address, |
|
51368
adcb0bb3d1e9
8209118: Abstract SATBMarkQueueSet's ThreadLocalData access
rkennke
parents:
50803
diff
changeset
|
611 |
G1SATBMarkQueueSet::handle_zero_index_for_thread), |
adcb0bb3d1e9
8209118: Abstract SATBMarkQueueSet's ThreadLocalData access
rkennke
parents:
50803
diff
changeset
|
612 |
G2_thread); |
49906 | 613 |
|
614 |
__ restore_live_registers(true); |
|
615 |
||
616 |
__ br(Assembler::always, /*annul*/false, Assembler::pt, restart); |
|
617 |
__ epilogue(); |
|
618 |
} |
|
619 |
||
620 |
void G1BarrierSetAssembler::generate_c1_post_barrier_runtime_stub(StubAssembler* sasm) { |
|
621 |
__ prologue("g1_post_barrier", false); |
|
622 |
||
623 |
G1BarrierSet* bs = barrier_set_cast<G1BarrierSet>(BarrierSet::barrier_set()); |
|
624 |
||
625 |
Register addr = G4; |
|
626 |
Register cardtable = G5; |
|
627 |
Register tmp = G1_scratch; |
|
628 |
Register tmp2 = G3_scratch; |
|
54110 | 629 |
CardTable::CardValue* byte_map_base = bs->card_table()->byte_map_base(); |
49906 | 630 |
|
631 |
Label not_already_dirty, restart, refill, young_card; |
|
632 |
||
633 |
#ifdef _LP64 |
|
634 |
__ srlx(addr, CardTable::card_shift, addr); |
|
635 |
#else |
|
636 |
__ srl(addr, CardTable::card_shift, addr); |
|
637 |
#endif |
|
638 |
||
639 |
AddressLiteral rs((address)byte_map_base); |
|
640 |
__ set(rs, cardtable); // cardtable := <card table base> |
|
641 |
__ ldub(addr, cardtable, tmp); // tmp := [addr + cardtable] |
|
642 |
||
643 |
__ cmp_and_br_short(tmp, G1CardTable::g1_young_card_val(), Assembler::equal, Assembler::pt, young_card); |
|
644 |
||
645 |
__ membar(Assembler::Membar_mask_bits(Assembler::StoreLoad)); |
|
646 |
__ ldub(addr, cardtable, tmp); // tmp := [addr + cardtable] |
|
647 |
||
648 |
assert(G1CardTable::dirty_card_val() == 0, "otherwise check this code"); |
|
649 |
__ cmp_and_br_short(tmp, G0, Assembler::notEqual, Assembler::pt, not_already_dirty); |
|
650 |
||
651 |
__ bind(young_card); |
|
652 |
// We didn't take the branch, so we're already dirty: return. |
|
653 |
// Use return-from-leaf |
|
654 |
__ retl(); |
|
655 |
__ delayed()->nop(); |
|
656 |
||
657 |
// Not dirty. |
|
658 |
__ bind(not_already_dirty); |
|
659 |
||
660 |
// Get cardtable + tmp into a reg by itself |
|
661 |
__ add(addr, cardtable, tmp2); |
|
662 |
||
663 |
// First, dirty it. |
|
664 |
__ stb(G0, tmp2, 0); // [cardPtr] := 0 (i.e., dirty). |
|
665 |
||
666 |
Register tmp3 = cardtable; |
|
667 |
Register tmp4 = tmp; |
|
668 |
||
669 |
// these registers are now dead |
|
670 |
addr = cardtable = tmp = noreg; |
|
671 |
||
672 |
int dirty_card_q_index_byte_offset = in_bytes(G1ThreadLocalData::dirty_card_queue_index_offset()); |
|
673 |
int dirty_card_q_buf_byte_offset = in_bytes(G1ThreadLocalData::dirty_card_queue_buffer_offset()); |
|
674 |
||
675 |
__ bind(restart); |
|
676 |
||
53747
13acc8e38a29
8218089: Rename DirtyCardQueue et al to follow usual G1 naming conventions
kbarrett
parents:
51368
diff
changeset
|
677 |
// Get the index into the update buffer. G1DirtyCardQueue::_index is |
49906 | 678 |
// a size_t so ld_ptr is appropriate here. |
679 |
__ ld_ptr(G2_thread, dirty_card_q_index_byte_offset, tmp3); |
|
680 |
||
681 |
// index == 0? |
|
682 |
__ cmp_and_brx_short(tmp3, G0, Assembler::equal, Assembler::pn, refill); |
|
683 |
||
684 |
__ ld_ptr(G2_thread, dirty_card_q_buf_byte_offset, tmp4); |
|
685 |
__ sub(tmp3, oopSize, tmp3); |
|
686 |
||
687 |
__ st_ptr(tmp2, tmp4, tmp3); // [_buf + index] := <address_of_card> |
|
688 |
// Use return-from-leaf |
|
689 |
__ retl(); |
|
690 |
__ delayed()->st_ptr(tmp3, G2_thread, dirty_card_q_index_byte_offset); |
|
691 |
||
692 |
__ bind(refill); |
|
693 |
||
694 |
__ save_live_registers_no_oop_map(true); |
|
695 |
||
696 |
__ call_VM_leaf(L7_thread_cache, |
|
697 |
CAST_FROM_FN_PTR(address, |
|
53747
13acc8e38a29
8218089: Rename DirtyCardQueue et al to follow usual G1 naming conventions
kbarrett
parents:
51368
diff
changeset
|
698 |
G1DirtyCardQueueSet::handle_zero_index_for_thread), |
51368
adcb0bb3d1e9
8209118: Abstract SATBMarkQueueSet's ThreadLocalData access
rkennke
parents:
50803
diff
changeset
|
699 |
G2_thread); |
49906 | 700 |
|
701 |
__ restore_live_registers(true); |
|
702 |
||
703 |
__ br(Assembler::always, /*annul*/false, Assembler::pt, restart); |
|
704 |
__ epilogue(); |
|
705 |
} |
|
706 |
||
707 |
#undef __ |
|
708 |
||
709 |
#endif // COMPILER1 |