Unasafe.putOdered -> Unsafe.releasePut

Paul Sandoz paul.sandoz at oracle.com
Mon Mar 2 11:54:57 UTC 2015


On Mar 2, 2015, at 12:07 PM, David Holmes <david.holmes at oracle.com> wrote:

> Hi Paul,
> 
> This is more a question for core-libs and the users of this Unsafe API.

I wanted to check here first because of work done in [1] and because this is where there is most experience with the Unsafe implementation. I don't want to change the semantics of existing Unsafe methods.

Note that the VarHandle work will expose using release/acquire names, where the former implementation defers to Unsafe.putOrdered*, and the later to relaxed plus explicit load fence.


> Sometimes the implementation of unsafe doesn't exactly match the API, so we need to check what the intended API semantics are.
> 

I believe things align naming-wise at least from eyeballing C2 code i.e. Unsafe.putOrdered* is a form of release-store like that of OrderAccess::release_store and Unsafe.storeFence is a form of release-fence like that of OrderAccess::release. 

src/share/vm/opto/library_call.cpp:

bool LibraryCallKit::inline_unsafe_ordered_store(BasicType type) {
  ...
  insert_mem_bar(Op_MemBarRelease);
  insert_mem_bar(Op_MemBarCPUOrder);
  // Ensure that the store is atomic for longs:
  const bool require_atomic_access = true;
  Node* store;
  if (type == T_OBJECT) // reference stores need a store barrier.
    store = store_oop_to_unknown(control(), base, adr, adr_type, val, type, MemNode::release);
  else {
    store = store_to_memory(control(), adr, val, type, adr_type, MemNode::release, require_atomic_access);
  }
  insert_mem_bar(Op_MemBarCPUOrder);
  return true;
}

bool LibraryCallKit::inline_unsafe_fence(vmIntrinsics::ID id) {
  // Regardless of form, don't allow previous ld/st to move down,
  // then issue acquire, release, or volatile mem_bar.
  insert_mem_bar(Op_MemBarCPUOrder);
  switch(id) {
    case vmIntrinsics::_loadFence:
      insert_mem_bar(Op_LoadFence);
      return true;
    case vmIntrinsics::_storeFence:
      insert_mem_bar(Op_StoreFence);
      return true;
    case vmIntrinsics::_fullFence:
      insert_mem_bar(Op_MemBarVolatile);
      return true;
    default:
      fatal_unexpected_iid(id);
      return false;
  }
}


src/cpu/x86/vm/x86_32.ad:

instruct membar_release() %{
  match(MemBarRelease);
  match(StoreFence);
  ins_cost(400);

  size(0);
  format %{ "MEMBAR-release ! (empty encoding)" %}
  ins_encode( );
  ins_pipe(empty);
%}

...

instruct membar_acquire() %{
  match(MemBarAcquire);
  match(LoadFence);
  ins_cost(400);

  size(0);
  format %{ "MEMBAR-acquire ! (empty encoding)" %}
  ins_encode();
  ins_pipe(empty);
%}

...

instruct membar_volatile(eFlagsReg cr) %{
  match(MemBarVolatile);
  effect(KILL cr);
  ins_cost(400);

  format %{ 
    $$template
    if (os::is_MP()) {
      $$emit$$"LOCK ADDL [ESP + #0], 0\t! membar_volatile"
    } else {
      $$emit$$"MEMBAR-volatile ! (empty encoding)"
    }
  %}
  ins_encode %{
    __ membar(Assembler::StoreLoad);
  %}
  ins_pipe(pipe_slow);
%}


Paul.


More information about the hotspot-dev mailing list