提交 8eda69f2 编写于 作者: G goetz

8029101: PPC64 (part 211): ordering of Independent Reads of Independent Writes

Reviewed-by: dholmes, kvn
Contributed-by: martin.doerr@sap.com
上级 fbd11f67
...@@ -37,4 +37,7 @@ const int StackAlignmentInBytes = 16; ...@@ -37,4 +37,7 @@ const int StackAlignmentInBytes = 16;
// signatures accordingly. // signatures accordingly.
const bool CCallingConventionRequiresIntsAsLongs = true; const bool CCallingConventionRequiresIntsAsLongs = true;
// The PPC CPUs are NOT multiple-copy-atomic.
#define CPU_NOT_MULTIPLE_COPY_ATOMIC
#endif // CPU_PPC_VM_GLOBALDEFINITIONS_PPC_HPP #endif // CPU_PPC_VM_GLOBALDEFINITIONS_PPC_HPP
...@@ -2034,6 +2034,9 @@ run: ...@@ -2034,6 +2034,9 @@ run:
TosState tos_type = cache->flag_state(); TosState tos_type = cache->flag_state();
int field_offset = cache->f2_as_index(); int field_offset = cache->f2_as_index();
if (cache->is_volatile()) { if (cache->is_volatile()) {
if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
OrderAccess::fence();
}
if (tos_type == atos) { if (tos_type == atos) {
VERIFY_OOP(obj->obj_field_acquire(field_offset)); VERIFY_OOP(obj->obj_field_acquire(field_offset));
SET_STACK_OBJECT(obj->obj_field_acquire(field_offset), -1); SET_STACK_OBJECT(obj->obj_field_acquire(field_offset), -1);
......
...@@ -2627,8 +2627,13 @@ bool LibraryCallKit::inline_unsafe_access(bool is_native_ptr, bool is_store, Bas ...@@ -2627,8 +2627,13 @@ bool LibraryCallKit::inline_unsafe_access(bool is_native_ptr, bool is_store, Bas
// rough approximation of type. // rough approximation of type.
need_mem_bar = true; need_mem_bar = true;
// For Stores, place a memory ordering barrier now. // For Stores, place a memory ordering barrier now.
if (is_store) if (is_store) {
insert_mem_bar(Op_MemBarRelease); insert_mem_bar(Op_MemBarRelease);
} else {
if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
insert_mem_bar(Op_MemBarVolatile);
}
}
} }
// Memory barrier to prevent normal and 'unsafe' accesses from // Memory barrier to prevent normal and 'unsafe' accesses from
...@@ -2717,10 +2722,13 @@ bool LibraryCallKit::inline_unsafe_access(bool is_native_ptr, bool is_store, Bas ...@@ -2717,10 +2722,13 @@ bool LibraryCallKit::inline_unsafe_access(bool is_native_ptr, bool is_store, Bas
} }
if (is_volatile) { if (is_volatile) {
if (!is_store) if (!is_store) {
insert_mem_bar(Op_MemBarAcquire); insert_mem_bar(Op_MemBarAcquire);
else } else {
insert_mem_bar(Op_MemBarVolatile); if (!support_IRIW_for_not_multiple_copy_atomic_cpu) {
insert_mem_bar(Op_MemBarVolatile);
}
}
} }
if (need_mem_bar) insert_mem_bar(Op_MemBarCPUOrder); if (need_mem_bar) insert_mem_bar(Op_MemBarCPUOrder);
......
...@@ -330,7 +330,8 @@ class Parse : public GraphKit { ...@@ -330,7 +330,8 @@ class Parse : public GraphKit {
GraphKit _exits; // Record all normal returns and throws here. GraphKit _exits; // Record all normal returns and throws here.
bool _wrote_final; // Did we write a final field? bool _wrote_final; // Did we write a final field?
bool _count_invocations; // update and test invocation counter bool _wrote_volatile; // Did we write a volatile field?
bool _count_invocations; // update and test invocation counter
bool _method_data_update; // update method data oop bool _method_data_update; // update method data oop
Node* _alloc_with_final; // An allocation node with final field Node* _alloc_with_final; // An allocation node with final field
...@@ -373,6 +374,8 @@ class Parse : public GraphKit { ...@@ -373,6 +374,8 @@ class Parse : public GraphKit {
GraphKit& exits() { return _exits; } GraphKit& exits() { return _exits; }
bool wrote_final() const { return _wrote_final; } bool wrote_final() const { return _wrote_final; }
void set_wrote_final(bool z) { _wrote_final = z; } void set_wrote_final(bool z) { _wrote_final = z; }
bool wrote_volatile() const { return _wrote_volatile; }
void set_wrote_volatile(bool z) { _wrote_volatile = z; }
bool count_invocations() const { return _count_invocations; } bool count_invocations() const { return _count_invocations; }
bool method_data_update() const { return _method_data_update; } bool method_data_update() const { return _method_data_update; }
Node* alloc_with_final() const { return _alloc_with_final; } Node* alloc_with_final() const { return _alloc_with_final; }
......
...@@ -390,6 +390,7 @@ Parse::Parse(JVMState* caller, ciMethod* parse_method, float expected_uses, Pars ...@@ -390,6 +390,7 @@ Parse::Parse(JVMState* caller, ciMethod* parse_method, float expected_uses, Pars
_expected_uses = expected_uses; _expected_uses = expected_uses;
_depth = 1 + (caller->has_method() ? caller->depth() : 0); _depth = 1 + (caller->has_method() ? caller->depth() : 0);
_wrote_final = false; _wrote_final = false;
_wrote_volatile = false;
_alloc_with_final = NULL; _alloc_with_final = NULL;
_entry_bci = InvocationEntryBci; _entry_bci = InvocationEntryBci;
_tf = NULL; _tf = NULL;
...@@ -907,7 +908,13 @@ void Parse::do_exits() { ...@@ -907,7 +908,13 @@ void Parse::do_exits() {
Node* iophi = _exits.i_o(); Node* iophi = _exits.i_o();
_exits.set_i_o(gvn().transform(iophi)); _exits.set_i_o(gvn().transform(iophi));
if (wrote_final()) { // 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) // This method (which must be a constructor by the rules of Java)
// wrote a final. The effects of all initializations must be // wrote a final. The effects of all initializations must be
// committed to memory before any code after the constructor // committed to memory before any code after the constructor
......
...@@ -227,6 +227,9 @@ void Parse::do_get_xxx(Node* obj, ciField* field, bool is_field) { ...@@ -227,6 +227,9 @@ void Parse::do_get_xxx(Node* obj, ciField* field, bool is_field) {
} else { } else {
type = Type::get_const_basic_type(bt); type = Type::get_const_basic_type(bt);
} }
if (support_IRIW_for_not_multiple_copy_atomic_cpu && field->is_volatile()) {
insert_mem_bar(Op_MemBarVolatile); // StoreLoad barrier
}
// Build the load. // Build the load.
// //
MemNode::MemOrd mo = is_vol ? MemNode::acquire : MemNode::unordered; MemNode::MemOrd mo = is_vol ? MemNode::acquire : MemNode::unordered;
...@@ -317,7 +320,16 @@ void Parse::do_put_xxx(Node* obj, ciField* field, bool is_field) { ...@@ -317,7 +320,16 @@ void Parse::do_put_xxx(Node* obj, ciField* field, bool is_field) {
// If reference is volatile, prevent following volatiles ops from // If reference is volatile, prevent following volatiles ops from
// floating up before the volatile write. // floating up before the volatile write.
if (is_vol) { if (is_vol) {
insert_mem_bar(Op_MemBarVolatile); // Use fat membar // If not multiple copy atomic, we do the MemBarVolatile before the load.
if (!support_IRIW_for_not_multiple_copy_atomic_cpu) {
insert_mem_bar(Op_MemBarVolatile); // Use fat membar
}
// Remember we wrote a volatile field.
// For not multiple copy atomic cpu (ppc64) a barrier should be issued
// in constructors which have such stores. See do_exits() in parse1.cpp.
if (is_field) {
set_wrote_volatile(true);
}
} }
// If the field is final, the rules of Java say we are in <init> or <clinit>. // If the field is final, the rules of Java say we are in <init> or <clinit>.
......
...@@ -162,6 +162,9 @@ jint Unsafe_invocation_key_to_method_slot(jint key) { ...@@ -162,6 +162,9 @@ jint Unsafe_invocation_key_to_method_slot(jint key) {
#define GET_FIELD_VOLATILE(obj, offset, type_name, v) \ #define GET_FIELD_VOLATILE(obj, offset, type_name, v) \
oop p = JNIHandles::resolve(obj); \ oop p = JNIHandles::resolve(obj); \
if (support_IRIW_for_not_multiple_copy_atomic_cpu) { \
OrderAccess::fence(); \
} \
volatile type_name v = OrderAccess::load_acquire((volatile type_name*)index_oop_from_field_offset_long(p, offset)); 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) \ #define SET_FIELD_VOLATILE(obj, offset, type_name, x) \
......
...@@ -398,6 +398,17 @@ const uint64_t KlassEncodingMetaspaceMax = (uint64_t(max_juint) + 1) << LogKlass ...@@ -398,6 +398,17 @@ const uint64_t KlassEncodingMetaspaceMax = (uint64_t(max_juint) + 1) << LogKlass
#define PLATFORM_NATIVE_STACK_WALKING_SUPPORTED 1 #define PLATFORM_NATIVE_STACK_WALKING_SUPPORTED 1
#endif #endif
// To assure the IRIW property on processors that are not multiple copy
// atomic, sync instructions must be issued between volatile reads to
// assure their ordering, instead of after volatile stores.
// (See "A Tutorial Introduction to the ARM and POWER Relaxed Memory Models"
// by Luc Maranget, Susmit Sarkar and Peter Sewell, INRIA/Cambridge)
#ifdef CPU_NOT_MULTIPLE_COPY_ATOMIC
const bool support_IRIW_for_not_multiple_copy_atomic_cpu = true;
#else
const bool support_IRIW_for_not_multiple_copy_atomic_cpu = false;
#endif
// The byte alignment to be used by Arena::Amalloc. See bugid 4169348. // The byte alignment to be used by Arena::Amalloc. See bugid 4169348.
// Note: this value must be a power of 2 // Note: this value must be a power of 2
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册