103 |
103 |
104 __ branch(lir_cond_notEqual, T_INT, slow); |
104 __ branch(lir_cond_notEqual, T_INT, slow); |
105 __ branch_destination(slow->continuation()); |
105 __ branch_destination(slow->continuation()); |
106 } |
106 } |
107 |
107 |
108 LIR_Opr ShenandoahBarrierSetC1::load_reference_barrier(LIRGenerator* gen, LIR_Opr obj) { |
108 LIR_Opr ShenandoahBarrierSetC1::load_reference_barrier(LIRGenerator* gen, LIR_Opr obj, LIR_Opr addr) { |
109 if (ShenandoahLoadRefBarrier) { |
109 if (ShenandoahLoadRefBarrier) { |
110 return load_reference_barrier_impl(gen, obj); |
110 return load_reference_barrier_impl(gen, obj, addr); |
111 } else { |
111 } else { |
112 return obj; |
112 return obj; |
113 } |
113 } |
114 } |
114 } |
115 |
115 |
116 LIR_Opr ShenandoahBarrierSetC1::load_reference_barrier_impl(LIRGenerator* gen, LIR_Opr obj) { |
116 LIR_Opr ShenandoahBarrierSetC1::load_reference_barrier_impl(LIRGenerator* gen, LIR_Opr obj, LIR_Opr addr) { |
117 assert(ShenandoahLoadRefBarrier, "Should be enabled"); |
117 assert(ShenandoahLoadRefBarrier, "Should be enabled"); |
118 |
118 |
119 obj = ensure_in_register(gen, obj); |
119 obj = ensure_in_register(gen, obj); |
120 assert(obj->is_register(), "must be a register at this point"); |
120 assert(obj->is_register(), "must be a register at this point"); |
|
121 addr = ensure_in_register(gen, addr); |
|
122 assert(addr->is_register(), "must be a register at this point"); |
121 LIR_Opr result = gen->result_register_for(obj->value_type()); |
123 LIR_Opr result = gen->result_register_for(obj->value_type()); |
122 __ move(obj, result); |
124 __ move(obj, result); |
123 LIR_Opr tmp1 = gen->new_register(T_OBJECT); |
125 LIR_Opr tmp1 = gen->new_register(T_OBJECT); |
124 LIR_Opr tmp2 = gen->new_register(T_OBJECT); |
126 LIR_Opr tmp2 = gen->new_register(T_OBJECT); |
125 |
127 |
144 __ logical_and(flag_val, mask_reg, masked_flag); |
146 __ logical_and(flag_val, mask_reg, masked_flag); |
145 flag_val = masked_flag; |
147 flag_val = masked_flag; |
146 } |
148 } |
147 __ cmp(lir_cond_notEqual, flag_val, LIR_OprFact::intConst(0)); |
149 __ cmp(lir_cond_notEqual, flag_val, LIR_OprFact::intConst(0)); |
148 |
150 |
149 CodeStub* slow = new ShenandoahLoadReferenceBarrierStub(obj, result, tmp1, tmp2); |
151 CodeStub* slow = new ShenandoahLoadReferenceBarrierStub(obj, addr, result, tmp1, tmp2); |
150 __ branch(lir_cond_notEqual, T_INT, slow); |
152 __ branch(lir_cond_notEqual, T_INT, slow); |
151 __ branch_destination(slow->continuation()); |
153 __ branch_destination(slow->continuation()); |
152 |
154 |
153 return result; |
155 return result; |
154 } |
156 } |
155 |
157 |
156 LIR_Opr ShenandoahBarrierSetC1::ensure_in_register(LIRGenerator* gen, LIR_Opr obj) { |
158 LIR_Opr ShenandoahBarrierSetC1::ensure_in_register(LIRGenerator* gen, LIR_Opr obj) { |
157 if (!obj->is_register()) { |
159 if (!obj->is_register()) { |
158 LIR_Opr obj_reg = gen->new_register(T_OBJECT); |
160 LIR_Opr obj_reg; |
159 if (obj->is_constant()) { |
161 if (obj->is_constant()) { |
|
162 obj_reg = gen->new_register(T_OBJECT); |
160 __ move(obj, obj_reg); |
163 __ move(obj, obj_reg); |
161 } else { |
164 } else { |
|
165 #ifdef AARCH64 |
|
166 // AArch64 expects double-size register. |
|
167 obj_reg = gen->new_pointer_register(); |
|
168 #else |
|
169 // x86 expects single-size register. |
|
170 obj_reg = gen->new_register(T_OBJECT); |
|
171 #endif |
162 __ leal(obj, obj_reg); |
172 __ leal(obj, obj_reg); |
163 } |
173 } |
164 obj = obj_reg; |
174 obj = obj_reg; |
165 } |
175 } |
166 return obj; |
176 return obj; |
180 pre_barrier(access.gen(), access.access_emit_info(), access.decorators(), access.resolved_addr(), LIR_OprFact::illegalOpr /* pre_val */); |
190 pre_barrier(access.gen(), access.access_emit_info(), access.decorators(), access.resolved_addr(), LIR_OprFact::illegalOpr /* pre_val */); |
181 } |
191 } |
182 value = storeval_barrier(access.gen(), value, access.access_emit_info(), access.decorators()); |
192 value = storeval_barrier(access.gen(), value, access.access_emit_info(), access.decorators()); |
183 } |
193 } |
184 BarrierSetC1::store_at_resolved(access, value); |
194 BarrierSetC1::store_at_resolved(access, value); |
|
195 } |
|
196 |
|
197 LIR_Opr ShenandoahBarrierSetC1::resolve_address(LIRAccess& access, bool resolve_in_register) { |
|
198 // We must resolve in register when patching. This is to avoid |
|
199 // having a patch area in the load barrier stub, since the call |
|
200 // into the runtime to patch will not have the proper oop map. |
|
201 const bool patch_before_barrier = access.is_oop() && (access.decorators() & C1_NEEDS_PATCHING) != 0; |
|
202 return BarrierSetC1::resolve_address(access, resolve_in_register || patch_before_barrier); |
185 } |
203 } |
186 |
204 |
187 void ShenandoahBarrierSetC1::load_at_resolved(LIRAccess& access, LIR_Opr result) { |
205 void ShenandoahBarrierSetC1::load_at_resolved(LIRAccess& access, LIR_Opr result) { |
188 if (!access.is_oop()) { |
206 if (!access.is_oop()) { |
189 BarrierSetC1::load_at_resolved(access, result); |
207 BarrierSetC1::load_at_resolved(access, result); |
208 } |
226 } |
209 |
227 |
210 if (ShenandoahLoadRefBarrier) { |
228 if (ShenandoahLoadRefBarrier) { |
211 LIR_Opr tmp = gen->new_register(T_OBJECT); |
229 LIR_Opr tmp = gen->new_register(T_OBJECT); |
212 BarrierSetC1::load_at_resolved(access, tmp); |
230 BarrierSetC1::load_at_resolved(access, tmp); |
213 tmp = load_reference_barrier(access.gen(), tmp); |
231 tmp = load_reference_barrier(access.gen(), tmp, access.resolved_addr()); |
214 __ move(tmp, result); |
232 __ move(tmp, result); |
215 } else { |
233 } else { |
216 BarrierSetC1::load_at_resolved(access, result); |
234 BarrierSetC1::load_at_resolved(access, result); |
217 } |
235 } |
218 |
236 |