# HG changeset patch # User goetz # Date 1385567140 -3600 # Node ID c59f800cbc309a1477a7005f6202dc555915d597 # Parent 50fdb38839ebcb515320d95ed6738766b3254a18 8029101: PPC64 (part 211): ordering of Independent Reads of Independent Writes Contributed-by: mdoerr diff --git a/src/share/vm/interpreter/bytecodeInterpreter.cpp b/src/share/vm/interpreter/bytecodeInterpreter.cpp --- a/src/share/vm/interpreter/bytecodeInterpreter.cpp +++ b/src/share/vm/interpreter/bytecodeInterpreter.cpp @@ -2034,6 +2034,9 @@ TosState tos_type = cache->flag_state(); int field_offset = cache->f2_as_index(); if (cache->is_volatile()) { + // Support ordering of "Independent Reads of Independent Writes" (see Parse::do_get_xxx). + // Solution: implement volatile read as sync-load-acquire. + PPC64_ONLY(OrderAccess::fence();) if (tos_type == atos) { VERIFY_OOP(obj->obj_field_acquire(field_offset)); SET_STACK_OBJECT(obj->obj_field_acquire(field_offset), -1); diff --git a/src/share/vm/opto/library_call.cpp b/src/share/vm/opto/library_call.cpp --- a/src/share/vm/opto/library_call.cpp +++ b/src/share/vm/opto/library_call.cpp @@ -2627,8 +2627,13 @@ // rough approximation of type. need_mem_bar = true; // For Stores, place a memory ordering barrier now. - if (is_store) + if (is_store) { insert_mem_bar(Op_MemBarRelease); + } else { + // Support ordering of "Independent Reads of Independent Writes" (see Parse::do_get_xxx). + // Solution: implement volatile read as sync-load-acquire + PPC64_ONLY(insert_mem_bar(Op_MemBarVolatile)); + } } // Memory barrier to prevent normal and 'unsafe' accesses from @@ -2717,10 +2722,12 @@ } if (is_volatile) { - if (!is_store) + if (!is_store) { insert_mem_bar(Op_MemBarAcquire); - else - insert_mem_bar(Op_MemBarVolatile); + } else { + // Changed volatiles/Unsafe: lwsync-store, sync-load-acquire. + NOT_PPC64(insert_mem_bar(Op_MemBarVolatile)); + } } if (need_mem_bar) insert_mem_bar(Op_MemBarCPUOrder); diff --git a/src/share/vm/opto/parse.hpp b/src/share/vm/opto/parse.hpp --- a/src/share/vm/opto/parse.hpp +++ b/src/share/vm/opto/parse.hpp @@ -330,6 +330,8 @@ GraphKit _exits; // Record all normal returns and throws here. bool _wrote_final; // Did we write a final field? + // Add MemBarRelease for constructors which write volatile field (PPC64). + bool _wrote_volatile; bool _count_invocations; // update and test invocation counter bool _method_data_update; // update method data oop Node* _alloc_with_final; // An allocation node with final field @@ -373,6 +375,9 @@ GraphKit& exits() { return _exits; } bool wrote_final() const { return _wrote_final; } void set_wrote_final(bool z) { _wrote_final = z; } + // Add MemBarRelease for constructors which write volatile field (PPC64). + bool wrote_volatile() const { return _wrote_volatile; } + void set_wrote_volatile(bool z) { _wrote_volatile = z; } bool count_invocations() const { return _count_invocations; } bool method_data_update() const { return _method_data_update; } Node* alloc_with_final() const { return _alloc_with_final; } diff --git a/src/share/vm/opto/parse1.cpp b/src/share/vm/opto/parse1.cpp --- a/src/share/vm/opto/parse1.cpp +++ b/src/share/vm/opto/parse1.cpp @@ -390,6 +390,7 @@ _expected_uses = expected_uses; _depth = 1 + (caller->has_method() ? caller->depth() : 0); _wrote_final = false; + _wrote_volatile = false; _alloc_with_final = NULL; _entry_bci = InvocationEntryBci; _tf = NULL; @@ -907,7 +908,10 @@ Node* iophi = _exits.i_o(); _exits.set_i_o(gvn().transform(iophi)); - if (wrote_final()) { + // Add MemBarRelease for constructors which write volatile field (PPC64). + // Intention is to avoid that other threads can observe initial values even though the + // constructor has set the volatile field. + 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 diff --git a/src/share/vm/opto/parse3.cpp b/src/share/vm/opto/parse3.cpp --- a/src/share/vm/opto/parse3.cpp +++ b/src/share/vm/opto/parse3.cpp @@ -227,6 +227,27 @@ } else { type = Type::get_const_basic_type(bt); } +#ifdef PPC64 + // Support VolatileIRIWTest (Independent Reads of Independent Writes). + // Example: volatile x=0, y=0 + // __________ __________ __________ __________ + // | Thread 0 | | Thread 1 | | Thread 2 | | Thread 3 | + // + // write(x=1) read(x) write(y=1) read(y) + // read(y) read(x) + // + // Disallowed: x=1, y=0 y=1, x=0 + // however, this case is observable on PPC64 (allowed by architecture) + // + // Solution: This example requires multiple-copy-atomicity. This is only + // assured by the sync instruction and if it is executed in the thread doing + // the load. Thus implement volatile read as sync-load-acquire and omit the + // sync/MemBarVolatile after the volatile store (see do_put_xxx()). + // MemBarVolatile happens to be implemented by sync. + if (field->is_volatile()) { + insert_mem_bar(Op_MemBarVolatile); // StoreLoad barrier + } +#endif // Build the load. // MemNode::MemOrd mo = is_vol ? MemNode::acquire : MemNode::unordered; @@ -317,7 +338,13 @@ // If reference is volatile, prevent following volatiles ops from // floating up before the volatile write. if (is_vol) { - insert_mem_bar(Op_MemBarVolatile); // Use fat membar + // Not on PPC64: See comment in do_get_xxx(). + NOT_PPC64(insert_mem_bar(Op_MemBarVolatile)); // Use fat membar + // But add MemBarRelease for constructors which write volatile field (PPC64) + // later on. + if (is_field) { + set_wrote_volatile(true); + } } // If the field is final, the rules of Java say we are in or . diff --git a/src/share/vm/prims/unsafe.cpp b/src/share/vm/prims/unsafe.cpp --- a/src/share/vm/prims/unsafe.cpp +++ b/src/share/vm/prims/unsafe.cpp @@ -160,8 +160,11 @@ oop p = JNIHandles::resolve(obj); \ *(type_name*)index_oop_from_field_offset_long(p, offset) = x +// Support ordering of "Independent Reads of Independent Writes" (see Parse::do_get_xxx). +// Solution: implement volatile read as fence-load-acquire. #define GET_FIELD_VOLATILE(obj, offset, type_name, v) \ oop p = JNIHandles::resolve(obj); \ + PPC64_ONLY(OrderAccess::fence();) \ volatile type_name v = OrderAccess::load_acquire((volatile type_name*)index_oop_from_field_offset_long(p, offset)); #define SET_FIELD_VOLATILE(obj, offset, type_name, x) \