@@ -209,7 +209,21 @@ void Parse::do_put_xxx(Node* obj, ciField* field, bool is_field) {
209209 Node* val = type2size[bt] == 1 ? pop () : pop_pair ();
210210
211211 DecoratorSet decorators = IN_HEAP;
212- decorators |= is_vol ? MO_SEQ_CST : MO_UNORDERED;
212+
213+ if (is_vol) {
214+ // Volatile access, full SC.
215+ decorators |= MO_SEQ_CST;
216+ } else if (field->is_stable () && !field->is_final () &&
217+ is_reference_type (field->layout_type ())) {
218+ // For reference @Stable fields, make sure we publish the contents
219+ // safely. We need this to make sure compilers see a proper value when
220+ // constant folding the access. Final @Stable fields are already
221+ // handled in constructors.
222+ decorators |= MO_RELEASE;
223+ } else {
224+ // Everything else is unordered.
225+ decorators |= MO_UNORDERED;
226+ }
213227
214228 bool is_obj = is_reference_type (bt);
215229
@@ -243,7 +257,12 @@ void Parse::do_put_xxx(Node* obj, ciField* field, bool is_field) {
243257 // can insert a memory barrier later on to keep the writes from floating
244258 // out of the constructor.
245259 if (field->is_final () || field->is_stable ()) {
246- set_wrote_final_or_stable (true );
260+ if (field->is_final ()) {
261+ set_wrote_final (true );
262+ }
263+ if (field->is_stable ()) {
264+ set_wrote_stable (true );
265+ }
247266 if (AllocateNode::Ideal_allocation (obj) != nullptr ) {
248267 // Preserve allocation ptr to create precedent edge to it in membar
249268 // generated on exit from constructor.
0 commit comments