Skip to content

Commit

Permalink
more efficient querying of deref handles
Browse files Browse the repository at this point in the history
  • Loading branch information
lukasstadler committed Oct 30, 2019
1 parent e48249e commit 725b94c
Show file tree
Hide file tree
Showing 14 changed files with 302 additions and 314 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,6 @@
import java.util.function.Predicate;
import java.util.stream.Collectors;

import org.graalvm.collections.EconomicMap;

import com.oracle.truffle.api.CallTarget;
import com.oracle.truffle.api.CompilerAsserts;
import com.oracle.truffle.api.CompilerDirectives;
Expand Down Expand Up @@ -77,6 +75,7 @@
import com.oracle.truffle.llvm.runtime.interop.LLVMTypedForeignObject;
import com.oracle.truffle.llvm.runtime.interop.access.LLVMInteropType;
import com.oracle.truffle.llvm.runtime.memory.LLVMMemory;
import com.oracle.truffle.llvm.runtime.memory.LLVMMemory.HandleContainer;
import com.oracle.truffle.llvm.runtime.memory.LLVMMemoryOpNode;
import com.oracle.truffle.llvm.runtime.memory.LLVMStack;
import com.oracle.truffle.llvm.runtime.memory.LLVMStack.StackPointer;
Expand Down Expand Up @@ -117,22 +116,8 @@ public final class LLVMContext {
private ConcurrentHashMap<String, Integer> nativeCallStatistics; // effectively final
// after initialization

private static final class Handle {

private int refcnt;
private final LLVMNativePointer pointer;
private final Object managed;

private Handle(LLVMNativePointer pointer, Object managed) {
this.refcnt = 0;
this.pointer = pointer;
this.managed = managed;
}
}

private final Object handlesLock;
private final EconomicMap<Object, Handle> handleFromManaged;
private final EconomicMap<LLVMNativePointer, Handle> handleFromPointer;
private final HandleContainer handleContainer;
private final HandleContainer derefHandleContainer;

private final LLVMSourceContext sourceContext;

Expand Down Expand Up @@ -193,9 +178,9 @@ synchronized LLVMFunctionDescriptor create(String name, FunctionType type, LLVMF
this.sigDfl = LLVMNativePointer.create(0);
this.sigIgn = LLVMNativePointer.create(1);
this.sigErr = LLVMNativePointer.create(-1);
this.handleFromManaged = EconomicMap.create();
this.handleFromPointer = EconomicMap.create();
this.handlesLock = new Object();
LLVMMemory memory = language.getCapability(LLVMMemory.class);
this.handleContainer = memory.createHandleContainer(false);
this.derefHandleContainer = memory.createHandleContainer(true);
this.functionPointerRegistry = new LLVMFunctionPointerRegistry();
this.interopTypeRegistry = new LLVMInteropType.InteropTypeRegistry();
this.sourceContext = new LLVMSourceContext();
Expand Down Expand Up @@ -654,64 +639,12 @@ public LLVMNativePointer getSigErr() {
return sigErr;
}

@TruffleBoundary
public boolean isHandle(LLVMNativePointer address) {
synchronized (handlesLock) {
return handleFromPointer.containsKey(address);
}
}

@TruffleBoundary
public Object getManagedObjectForHandle(LLVMNativePointer address) {
synchronized (handlesLock) {
final Handle handle = handleFromPointer.get(address);

if (handle == null) {
throw new UnsupportedOperationException("Cannot resolve native handle: " + address);
}

return handle.managed;
}
}

@TruffleBoundary
public void releaseHandle(LLVMMemory memory, LLVMNativePointer address) {
synchronized (handlesLock) {
Handle handle = handleFromPointer.get(address);
if (handle == null) {
throw new UnsupportedOperationException("Cannot resolve native handle: " + address);
}

if (--handle.refcnt == 0) {
handleFromPointer.removeKey(address);
handleFromManaged.removeKey(handle.managed);
memory.free(address);
}
}
public HandleContainer getHandleContainer() {
return handleContainer;
}

public LLVMNativePointer getHandleForManagedObject(LLVMMemory memory, Object object) {
return getHandle(memory, object, false).copy();
}

public LLVMNativePointer getDerefHandleForManagedObject(LLVMMemory memory, Object object) {
return getHandle(memory, object, true).copy();
}

@TruffleBoundary
private LLVMNativePointer getHandle(LLVMMemory memory, Object object, boolean autoDeref) {
synchronized (handlesLock) {
Handle handle = handleFromManaged.get(object);
if (handle == null) {
LLVMNativePointer allocatedMemory = LLVMNativePointer.create(memory.allocateHandle(autoDeref));
handle = new Handle(allocatedMemory, object);
handleFromManaged.put(object, handle);
handleFromPointer.put(allocatedMemory, handle);
}

handle.refcnt++;
return handle.pointer;
}
public HandleContainer getDerefHandleContainer() {
return derefHandleContainer;
}

@TruffleBoundary
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,18 @@
*/
package com.oracle.truffle.llvm.runtime.interop;

import com.oracle.truffle.api.dsl.Fallback;
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.NodeChild;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.profiles.BranchProfile;
import com.oracle.truffle.api.profiles.ConditionProfile;
import com.oracle.truffle.api.profiles.ValueProfile;
import com.oracle.truffle.llvm.runtime.except.LLVMPolyglotException;
import com.oracle.truffle.llvm.runtime.nodes.api.LLVMExpressionNode;
import com.oracle.truffle.llvm.runtime.nodes.api.LLVMNode;
import com.oracle.truffle.llvm.runtime.pointer.LLVMManagedPointer;
import com.oracle.truffle.llvm.runtime.pointer.LLVMPointer;

@NodeChild(type = LLVMExpressionNode.class)
public abstract class LLVMAsForeignNode extends LLVMNode {
Expand All @@ -63,27 +67,27 @@ public static LLVMAsForeignNode createOptional() {
return LLVMAsForeignNodeGen.create(true, null);
}

@Specialization(guards = "isForeign(pointer)")
Object doForeign(LLVMManagedPointer pointer) {

Object foreign = pointer.getObject();

if (foreign instanceof LLVMTypedForeignObject) {
return ((LLVMTypedForeignObject) foreign).getForeign();
@Specialization
Object doForeign(Object pointer,
@Cached("createClassProfile()") ValueProfile objectProfile,
@Cached("createBinaryProfile()") ConditionProfile foreignProfile,
@Cached BranchProfile nonForeignProfile) {
if (LLVMManagedPointer.isInstance(pointer)) {
LLVMManagedPointer managed = LLVMManagedPointer.cast(pointer);
if (managed.getOffset() == 0) {
Object object = objectProfile.profile(managed.getObject());
if (foreignProfile.profile(object instanceof LLVMTypedForeignObject)) {
return ((LLVMTypedForeignObject) object).getForeign();
} else if (!(object instanceof LLVMInternalTruffleObject) && !LLVMPointer.isInstance(object)) {
return object;
}
}
}
return foreign;
}

@Fallback
Object doOther(@SuppressWarnings("unused") Object pointer) {
nonForeignProfile.enter();
if (allowNonForeign) {
return null;
} else {
throw new LLVMPolyglotException(this, "Pointer does not point to a polyglot value.");
}
}

protected static boolean isForeign(LLVMManagedPointer pointer) {
return pointer.getOffset() == 0 && (pointer.getObject() instanceof LLVMTypedForeignObject || LLVMExpressionNode.notLLVM(pointer.getObject()));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,14 @@
*/
package com.oracle.truffle.llvm.runtime.interop;

import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.GenerateUncached;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.interop.TruffleObject;
import com.oracle.truffle.api.library.CachedLibrary;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.profiles.ConditionProfile;
import com.oracle.truffle.api.profiles.ValueProfile;
import com.oracle.truffle.llvm.runtime.interop.LLVMDataEscapeNodeFactory.LLVMDoubleDataEscapeNodeGen;
import com.oracle.truffle.llvm.runtime.interop.LLVMDataEscapeNodeFactory.LLVMFloatDataEscapeNodeGen;
import com.oracle.truffle.llvm.runtime.interop.LLVMDataEscapeNodeFactory.LLVMI16DataEscapeNodeGen;
Expand All @@ -46,7 +49,6 @@
import com.oracle.truffle.llvm.runtime.interop.access.LLVMInteropType;
import com.oracle.truffle.llvm.runtime.interop.convert.ForeignToLLVM.ForeignToLLVMType;
import com.oracle.truffle.llvm.runtime.library.internal.LLVMNativeLibrary;
import com.oracle.truffle.llvm.runtime.nodes.api.LLVMExpressionNode;
import com.oracle.truffle.llvm.runtime.nodes.api.LLVMNode;
import com.oracle.truffle.llvm.runtime.nodes.api.LLVMObjectAccess;
import com.oracle.truffle.llvm.runtime.pointer.LLVMManagedPointer;
Expand Down Expand Up @@ -256,48 +258,44 @@ static TruffleObject escapingType(LLVMInteropType escapingValue, @SuppressWarnin
return escapingValue;
}

protected static boolean isForeign(LLVMPointer address) {
if (LLVMManagedPointer.isInstance(address)) {
LLVMManagedPointer managed = LLVMManagedPointer.cast(address);
boolean isForeignObject = managed.getObject() instanceof LLVMTypedForeignObject;

if (managed.getObject() instanceof LLVMObjectAccess && !(isForeignObject)) {
return false;
} else if (managed.getObject() instanceof DynamicObject) {
if (((DynamicObject) managed.getObject()).getShape().getObjectType() instanceof LLVMObjectAccess) {
return false;
}
}
return managed.getOffset() == 0 && (LLVMExpressionNode.notLLVM(managed.getObject()) || isForeignObject);
} else {
return false;
}
}

@Specialization
static Object escapingForeign(LLVMTypedForeignObject escapingValue, @SuppressWarnings("unused") LLVMInteropType.Structured type) {
return escapingValue.getForeign();
}

@Specialization(guards = {"isForeign(address)"})
static Object escapingManaged(LLVMManagedPointer address, @SuppressWarnings("unused") LLVMInteropType.Structured type) {
Object object = address.getObject();
@Specialization
static Object escapingManaged(LLVMPointer address, @SuppressWarnings("unused") LLVMInteropType.Structured type,
@Cached("createClassProfile()") ValueProfile objectProfile,
@Cached("createBinaryProfile()") ConditionProfile isManagedPointer,
@Cached("createBinaryProfile()") ConditionProfile isTypedForeignObject,
@Cached("createBinaryProfile()") ConditionProfile typedProfile) {

if (object instanceof LLVMTypedForeignObject) {
return escapingForeign((LLVMTypedForeignObject) object, type);
if (isManagedPointer.profile(LLVMManagedPointer.isInstance(address))) {
LLVMManagedPointer managed = LLVMManagedPointer.cast(address);
Object object = objectProfile.profile(managed.getObject());
if (managed.getOffset() == 0) {
if (isTypedForeignObject.profile(object instanceof LLVMTypedForeignObject)) {
return escapingForeign((LLVMTypedForeignObject) object, type);
} else {
if (object instanceof LLVMObjectAccess) {
// fallthrough
} else if (object instanceof DynamicObject && ((DynamicObject) object).getShape().getObjectType() instanceof LLVMObjectAccess) {
// fallthrough
} else if (object instanceof LLVMInternalTruffleObject) {
// fallthrough
} else if (LLVMPointer.isInstance(object)) {
// fallthrough
} else {
return object;
}
}
}
}
if (typedProfile.profile(type == null)) {
return address;
} else {
return address.export(type);
}

return object;
}

@Specialization(guards = {"!isForeign(address)", "type != null"})
static TruffleObject escapingPointerOverrideType(LLVMPointer address, LLVMInteropType.Structured type) {
return address.export(type);
}

@Specialization(guards = {"!isForeign(address)", "type == null"})
static TruffleObject escapingPointer(LLVMPointer address, @SuppressWarnings("unused") LLVMInteropType.Structured type) {
return address;
}

@Specialization
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import com.oracle.truffle.llvm.runtime.LLVMIVarBit;
import com.oracle.truffle.llvm.runtime.config.LLVMCapability;
import com.oracle.truffle.llvm.runtime.floating.LLVM80BitFloat;
import com.oracle.truffle.llvm.runtime.pointer.LLVMManagedPointer;
import com.oracle.truffle.llvm.runtime.pointer.LLVMNativePointer;

public abstract class LLVMMemory implements LLVMCapability {
Expand Down Expand Up @@ -234,12 +235,24 @@ public interface BooleanBinaryOperator {

public abstract void fullFence();

public abstract long allocateHandle(boolean autoDeref);

public abstract boolean isHandleMemory(long addr);
public abstract boolean isCommonHandleMemory(long addr);

public abstract boolean isDerefHandleMemory(long addr);

public abstract static class HandleContainer {

public abstract LLVMNativePointer allocate(Object value);

public abstract void free(long address);

public abstract LLVMManagedPointer getValue(long address);

public abstract boolean isHandle(long address);

}

public abstract HandleContainer createHandleContainer(boolean deref);

@ValueType
public static final class CMPXCHGI8 {
private final byte value;
Expand Down
Loading

0 comments on commit 725b94c

Please sign in to comment.