Skip to content

Commit

Permalink
[JVM] Do a modern object-oriented atomic ops (i.e. eliminate Unsafe)
Browse files Browse the repository at this point in the history
As commented, VarHandle can handle the atomic ops that we would've been
forced to depend on Unsafe to accomplish (racily!) prior to Java 9.
  • Loading branch information
Kaiepi committed Jul 27, 2022
1 parent f3bcaa1 commit 572d61d
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 78 deletions.
45 changes: 0 additions & 45 deletions src/vm/jvm/runtime/org/raku/nqp/runtime/Intrinsics.java

This file was deleted.

3 changes: 2 additions & 1 deletion src/vm/jvm/runtime/org/raku/nqp/runtime/Ops.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.lang.invoke.VarHandle;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
Expand Down Expand Up @@ -6039,7 +6040,7 @@ public static SixModelObject atomicbindattr(SixModelObject obj, SixModelObject c
return value;
}
public static SixModelObject barrierfull(ThreadContext tc) {
Intrinsics.itsUnsafe(tc, (unsafe) -> { unsafe.fullFence(); });
VarHandle.fullFence();
return createNull(tc);
}

Expand Down
11 changes: 7 additions & 4 deletions src/vm/jvm/runtime/org/raku/nqp/sixmodel/SixModelObject.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,25 +33,28 @@ public SixModelObject get_attribute_boxed(ThreadContext tc, SixModelObject class
public void get_attribute_native(ThreadContext tc, SixModelObject class_handle, String name, long hint) {
throw ExceptionHandling.dieInternal(tc, this.st.REPR.name + " representation does not support natively typed attributes");
}
public void bind_attribute_boxed(ThreadContext tc,SixModelObject class_handle,
public void bind_attribute_boxed(ThreadContext tc, SixModelObject class_handle,
String name, long hint, SixModelObject value) {
throw ExceptionHandling.dieInternal(tc, this.st.REPR.name + " representation does not support attributes");
}
public void bind_attribute_native(ThreadContext tc,SixModelObject class_handle, String name, long hint) {
public void bind_attribute_native(ThreadContext tc, SixModelObject class_handle, String name, long hint) {
throw ExceptionHandling.dieInternal(tc, this.st.REPR.name + " representation does not support natively typed attributes");
}
public long is_attribute_initialized(ThreadContext tc, SixModelObject class_handle,
String name, long hint) {
throw ExceptionHandling.dieInternal(tc, this.st.REPR.name + " representation does not support attributes");
}
public SixModelObject cas_attribute_boxed(ThreadContext tc,SixModelObject class_handle,
public SixModelObject cas_attribute_boxed(ThreadContext tc, SixModelObject class_handle,
String name, SixModelObject expected, SixModelObject value) {
throw ExceptionHandling.dieInternal(tc, this.st.REPR.name + " representation does not support cas of attributes");
}
public void atomic_bind_attribute_boxed(ThreadContext tc,SixModelObject class_handle,
public void atomic_bind_attribute_boxed(ThreadContext tc, SixModelObject class_handle,
String name, SixModelObject value) {
throw ExceptionHandling.dieInternal(tc, this.st.REPR.name + " representation does not support atomic binding to attributes");
}
public SixModelObject atomic_load_attribute_boxed(ThreadContext tc, SixModelObject class_handle, String name) {
throw ExceptionHandling.dieInternal(tc, this.st.REPR.name + " representation does not support atomic loading of attributes");
}

/**
* Boxing related functions.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package org.raku.nqp.sixmodel.reprs;

import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;
import org.raku.nqp.runtime.ExceptionHandling;
import org.raku.nqp.runtime.Intrinsics;
import org.raku.nqp.runtime.Ops;
import org.raku.nqp.runtime.ThreadContext;
import org.raku.nqp.sixmodel.STable;
Expand Down Expand Up @@ -115,41 +117,53 @@ public long is_attribute_initialized(ThreadContext tc, SixModelObject class_hand
return super.is_attribute_initialized(tc, class_handle, name, hint);
}

private long scalarValueOffset;

@Override
public SixModelObject cas_attribute_boxed(ThreadContext tc, SixModelObject class_handle,
String name, SixModelObject expected, SixModelObject value) {
return Intrinsics.butUnsafe(tc, (unsafe) -> {
try {
long offset = unsafe.objectFieldOffset(this.getClass().getDeclaredField(
"field_" + resolveAttribute(class_handle, name)));
return unsafe.compareAndSwapObject(this, offset, expected, value)
? expected
: (SixModelObject)unsafe.getObjectVolatile(this, offset);
}
catch (Exception e) {
throw ExceptionHandling.dieInternal(tc, e);
}
finally {
return Ops.createNull(tc);
}
});
SixModelObject result = null;
try {
String attribute = "field_" + resolveAttribute(class_handle, name);
VarHandle variable = MethodHandles.lookup().in(this.getClass())
.findVarHandle(this.getClass(), attribute, SixModelObject.class);
result = (SixModelObject)variable.compareAndExchange(this, expected, value);
}
catch (Exception e) {
throw ExceptionHandling.dieInternal(tc, e);
}
finally {
return result == null ? Ops.createNull(tc) : result;
}
}

@Override
public void atomic_bind_attribute_boxed(ThreadContext tc, SixModelObject class_handle,
String name, SixModelObject value) {
Intrinsics.itsUnsafe(tc, (unsafe) -> {
try {
long offset = unsafe.objectFieldOffset(this.getClass().getDeclaredField(
"field_" + resolveAttribute(class_handle, name)));
unsafe.putObjectVolatile(this, offset, value);
}
catch (Exception e) {
throw ExceptionHandling.dieInternal(tc, e);
}
});
try {
String attribute = "field_" + resolveAttribute(class_handle, name);
VarHandle variable = MethodHandles.lookup().in(this.getClass())
.findVarHandle(this.getClass(), attribute, SixModelObject.class);
variable.setRelease(this, value);
}
catch (Exception e) {
throw ExceptionHandling.dieInternal(tc, e);
}
}

@Override
public SixModelObject atomic_load_attribute_boxed(ThreadContext tc, SixModelObject class_handle, String name) {
SixModelObject result = null;
try {
String attribute = "field_" + resolveAttribute(class_handle, name);
VarHandle variable = MethodHandles.lookup().in(this.getClass())
.findVarHandle(this.getClass(), attribute, SixModelObject.class);
result = (SixModelObject)variable.getAcquire(this);
}
catch (Exception e) {
throw ExceptionHandling.dieInternal(tc, e);
}
finally {
return result == null ? Ops.createNull(tc) : result;
}
}

public SixModelObject posDelegate() {
Expand Down

0 comments on commit 572d61d

Please sign in to comment.