In the Java programming language accesses to 64-bit long and double fields are not required to be atomic, unless the fields are declared volatile. For volatile longs we have special handling in C2. AFAICS the final call for a volatile load (and similarly for store) goes down to this method: Node* GraphKit::make_load(Node* ctl, Node* adr, const Type* t, BasicType bt, int adr_idx, bool require_atomic_access) { assert(adr_idx != Compile::AliasIdxTop, "use other make_load factory" ); const TypePtr* adr_type = NULL; // debug-mode-only argument debug_only(adr_type = C->get_adr_type(adr_idx)); Node* mem = memory(adr_idx); Node* ld; if (require_atomic_access && bt == T_LONG) { ld = LoadLNode::make_atomic(C, ctl, mem, adr, adr_type, t); } else { ld = LoadNode::make(_gvn, ctl, mem, adr, adr_type, t, bt); } ld = _gvn.transform(ld); if ((bt == T_OBJECT) && C->do_escape_analysis() || C->eliminate_boxing()) { // Improve graph before escape analysis and boxing elimination. record_for_igvn(ld); } return ld; } which only performs an atomic access for T_LONG! And going further down here is the node for accessing doubles: // Load a double (64 bits) from memory class LoadDNode : public LoadNode { public: LoadDNode( Node *c, Node *mem, Node *adr, const TypePtr* at, const Type *t = Type::DOUBLE ) : LoadNode(c,mem,adr,at,t) {} virtual int Opcode() const; virtual uint ideal_reg() const { return Op_RegD; } virtual int store_Opcode() const { return Op_StoreD; } virtual BasicType memory_type() const { return T_DOUBLE; } }; no mention of need for atomic access at all. It appears that because double accesses on x86 and sparc were always atomic, there was no need to call this out in the C2 structure. However it need not be the case on other architectures, which means they must provide atomic access for all double accesses, not just volatile accesses. We should add support for atomic double access so that it can be distinguished from non-atomic accesses on platforms where the distinction is significant.
|