--- a/hotspot/src/share/vm/opto/parse1.cpp Mon Mar 03 15:54:45 2014 +0400
+++ b/hotspot/src/share/vm/opto/parse1.cpp Mon Mar 03 15:31:27 2014 +0400
@@ -391,6 +391,8 @@
_depth = 1 + (caller->has_method() ? caller->depth() : 0);
_wrote_final = false;
_wrote_volatile = false;
+ _wrote_stable = false;
+ _wrote_fields = false;
_alloc_with_final = NULL;
_entry_bci = InvocationEntryBci;
_tf = NULL;
@@ -908,26 +910,35 @@
Node* iophi = _exits.i_o();
_exits.set_i_o(gvn().transform(iophi));
- // On PPC64, also add MemBarRelease for constructors which write
- // volatile fields. As support_IRIW_for_not_multiple_copy_atomic_cpu
- // is set on PPC64, no sync instruction is issued after volatile
- // stores. We want to quarantee the same behaviour as on platforms
- // with total store order, although this is not required by the Java
- // memory model. So as with finals, we add a barrier here.
- if (wrote_final() PPC64_ONLY(|| (wrote_volatile() && method()->is_initializer()))) {
- // This method (which must be a constructor by the rules of Java)
- // wrote a final. The effects of all initializations must be
- // committed to memory before any code after the constructor
- // publishes the reference to the newly constructor object.
- // Rather than wait for the publication, we simply block the
- // writes here. Rather than put a barrier on only those writes
- // which are required to complete, we force all writes to complete.
- //
- // "All bets are off" unless the first publication occurs after a
- // normal return from the constructor. We do not attempt to detect
- // such unusual early publications. But no barrier is needed on
- // exceptional returns, since they cannot publish normally.
- //
+ // Figure out if we need to emit the trailing barrier. The barrier is only
+ // needed in the constructors, and only in three cases:
+ //
+ // 1. The constructor wrote a final. The effects of all initializations
+ // must be committed to memory before any code after the constructor
+ // publishes the reference to the newly constructed object. Rather
+ // than wait for the publication, we simply block the writes here.
+ // Rather than put a barrier on only those writes which are required
+ // to complete, we force all writes to complete.
+ //
+ // 2. On PPC64, also add MemBarRelease for constructors which write
+ // volatile fields. As support_IRIW_for_not_multiple_copy_atomic_cpu
+ // is set on PPC64, no sync instruction is issued after volatile
+ // stores. We want to guarantee the same behavior as on platforms
+ // with total store order, although this is not required by the Java
+ // memory model. So as with finals, we add a barrier here.
+ //
+ // 3. Experimental VM option is used to force the barrier if any field
+ // was written out in the constructor.
+ //
+ // "All bets are off" unless the first publication occurs after a
+ // normal return from the constructor. We do not attempt to detect
+ // such unusual early publications. But no barrier is needed on
+ // exceptional returns, since they cannot publish normally.
+ //
+ if (method()->is_initializer() &&
+ (wrote_final() ||
+ PPC64_ONLY(wrote_volatile() ||)
+ (AlwaysSafeConstructors && wrote_fields()))) {
_exits.insert_mem_bar(Op_MemBarRelease, alloc_with_final());
#ifndef PRODUCT
if (PrintOpto && (Verbose || WizardMode)) {
@@ -937,6 +948,19 @@
#endif
}
+ // Any method can write a @Stable field; insert memory barriers after
+ // those also. If there is a predecessor allocation node, bind the
+ // barrier there.
+ if (wrote_stable()) {
+ _exits.insert_mem_bar(Op_MemBarRelease, alloc_with_final());
+#ifndef PRODUCT
+ if (PrintOpto && (Verbose || WizardMode)) {
+ method()->print_name();
+ tty->print_cr(" writes @Stable and needs a memory barrier");
+ }
+#endif
+ }
+
for (MergeMemStream mms(_exits.merged_memory()); mms.next_non_empty(); ) {
// transform each slice of the original memphi:
mms.set_memory(_gvn.transform(mms.memory()));