Skip to content

Commit

Permalink
[GR-27683] Several performance improvements for multi-context mode.
Browse files Browse the repository at this point in the history
PullRequest: graal/7842
  • Loading branch information
fangerer committed Dec 15, 2020
2 parents b32be92 + b85c14a commit 0f5abc1
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
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.profiles.ConditionProfile;
import com.oracle.truffle.llvm.runtime.memory.LLVMStack;
import com.oracle.truffle.llvm.runtime.memory.LLVMThreadingStack;
import com.oracle.truffle.llvm.runtime.nodes.api.LLVMNode;
Expand Down Expand Up @@ -71,7 +72,8 @@ protected LLVMStack cached(LLVMThreadingStack stack, Thread currentThread,
* @see #executeWithTarget(LLVMThreadingStack, Thread)
*/
@Specialization(replaces = "cached")
static LLVMStack generic(LLVMThreadingStack stack, Thread currentThread) {
return stack.getStack();
static LLVMStack generic(LLVMThreadingStack stack, Thread currentThread,
@Cached ConditionProfile profile) {
return stack.getStackProfiled(currentThread, profile);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,10 @@ public Object get() {
}
}

public Object getFallback() {
return fallbackContents;
}

public void set(Object value, BranchProfile needsInitialize, BranchProfile needsInvalidation) {
State c = contents;
if (c.writeCount < MAX_CACHED_WRITES) {
Expand All @@ -109,8 +113,19 @@ public void set(Object value, BranchProfile needsInitialize, BranchProfile needs
needsInvalidation.enter();
c.assumption.invalidate();
}
fallbackContents = value;
}
/*
* Note: we always set the 'fallbackContents' because in theory, it could happen that
* someone writes to this global, then the singleContextAssumption is invalidated and from
* then on just reads the 'fallbackContents'. The penalty won't be high because we only
* allow small number of cached writes (i.e. MAX_CACHED_WRITES) in which case we do write
* the value twice.
*/
setFallback(value);
}

public void setFallback(Object value) {
fallbackContents = value;
}

@ExportMessage
Expand Down Expand Up @@ -144,7 +159,7 @@ public void toNative(@Cached LLVMToNativeNode toNative) {
LLVMNativePointer pointer = memory.allocateMemory(toNative, 8);
address = pointer.asNative();
long value;
Object global = get();
Object global = getFallback();
if (global instanceof Number) {
value = ((Number) global).longValue();
} else {
Expand Down Expand Up @@ -259,19 +274,29 @@ static double readManaged(LLVMGlobalContainer self, long offset,
@ExportMessage
static class ReadGenericI64 {

static Assumption singleContextAssumption() {
return LLVMLanguage.getLanguage().singleContextAssumption;
}

@Specialization(guards = "self.isPointer()")
static long readNative(LLVMGlobalContainer self, long offset,
@CachedLibrary("self") LLVMManagedReadLibrary location,
@CachedLanguage LLVMLanguage language) {
return language.getLLVMMemory().getI64(location, self.getAddress() + offset);
}

@Specialization(guards = {"!self.isPointer()", "offset == 0"})
static Object readManaged(LLVMGlobalContainer self, long offset) {
@Specialization(guards = {"!self.isPointer()", "offset == 0"}, assumptions = "singleContextAssumption()")
static Object readI64ManagedSingleContext(LLVMGlobalContainer self, long offset) {
assert offset == 0;
return self.get();
}

@Specialization(guards = {"!self.isPointer()", "offset == 0"}, replaces = "readI64ManagedSingleContext")
static Object readI64Managed(LLVMGlobalContainer self, long offset) {
assert offset == 0;
return self.getFallback();
}

@Specialization(guards = {"!self.isPointer()", "offset != 0"})
static Object readFallback(LLVMGlobalContainer self, long offset,
@CachedLibrary("self") InteropLibrary interop,
Expand All @@ -284,20 +309,31 @@ static Object readFallback(LLVMGlobalContainer self, long offset,
@ExportMessage
static class ReadPointer {

static Assumption singleContextAssumption() {
return LLVMLanguage.getLanguage().singleContextAssumption;
}

@Specialization(guards = "self.isPointer()")
static LLVMPointer readNative(LLVMGlobalContainer self, long offset,
@CachedLibrary("self") LLVMManagedReadLibrary location,
@CachedLanguage LLVMLanguage language) {
return language.getLLVMMemory().getPointer(location, self.getAddress() + offset);
}

@Specialization(guards = {"!self.isPointer()", "offset == 0"})
static LLVMPointer readManaged(LLVMGlobalContainer self, long offset,
@Cached LLVMToPointerNode toPointer) {
@Specialization(guards = {"!self.isPointer()", "offset == 0"}, assumptions = "singleContextAssumption()")
static LLVMPointer readManagedSingleContext(LLVMGlobalContainer self, long offset,
@Shared("toPointer") @Cached LLVMToPointerNode toPointer) {
assert offset == 0;
return toPointer.executeWithTarget(self.get());
}

@Specialization(guards = {"!self.isPointer()", "offset == 0"}, replaces = "readManagedSingleContext")
static LLVMPointer readManaged(LLVMGlobalContainer self, long offset,
@Shared("toPointer") @Cached LLVMToPointerNode toPointer) {
assert offset == 0;
return toPointer.executeWithTarget(self.getFallback());
}

@Specialization(guards = {"!self.isPointer()", "offset != 0"})
static LLVMPointer readFallback(LLVMGlobalContainer self, long offset,
@CachedLibrary("self") InteropLibrary interop,
Expand Down Expand Up @@ -405,21 +441,31 @@ static void writeManaged(LLVMGlobalContainer self, long offset, double value,
@ExportMessage
static class WriteI64 {

static Assumption singleContextAssumption() {
return LLVMLanguage.getLanguage().singleContextAssumption;
}

@Specialization(guards = "self.isPointer()")
static void writeNative(LLVMGlobalContainer self, long offset, long value,
@CachedLibrary("self") LLVMManagedWriteLibrary location,
@CachedLanguage LLVMLanguage language) {
language.getLLVMMemory().putI64(location, self.getAddress() + offset, value);
}

@Specialization(guards = {"!self.isPointer()", "offset == 0"})
static void writeManaged(LLVMGlobalContainer self, long offset, long value,
@Specialization(guards = {"!self.isPointer()", "offset == 0"}, assumptions = "singleContextAssumption()")
static void writeManagedSingleContext(LLVMGlobalContainer self, long offset, long value,
@Shared("p1") @Cached BranchProfile needsInitialize,
@Shared("p2") @Cached BranchProfile needsInvalidation) {
assert offset == 0;
self.set(value, needsInitialize, needsInvalidation);
}

@Specialization(guards = {"!self.isPointer()", "offset == 0"}, replaces = "writeManagedSingleContext")
static void writeManaged(LLVMGlobalContainer self, long offset, long value) {
assert offset == 0;
self.setFallback(value);
}

@Specialization(guards = {"!self.isPointer()", "offset != 0"})
static void writeFallback(LLVMGlobalContainer self, long offset, long value,
@CachedLibrary("self") InteropLibrary interop,
Expand All @@ -432,6 +478,10 @@ static void writeFallback(LLVMGlobalContainer self, long offset, long value,
@ExportMessage
static class WriteGenericI64 {

static Assumption singleContextAssumption() {
return LLVMLanguage.getLanguage().singleContextAssumption;
}

@Specialization(limit = "3", guards = "self.isPointer()")
static void writeNative(LLVMGlobalContainer self, long offset, Object value,
@CachedLibrary("value") LLVMNativeLibrary toNative,
Expand All @@ -440,14 +490,20 @@ static void writeNative(LLVMGlobalContainer self, long offset, Object value,
language.getLLVMMemory().putI64(toNative, self.getAddress() + offset, ptr);
}

@Specialization(guards = {"!self.isPointer()", "offset == 0"})
static void writeManaged(LLVMGlobalContainer self, long offset, Object value,
@Specialization(guards = {"!self.isPointer()", "offset == 0"}, assumptions = "singleContextAssumption()")
static void writeI64ManagedSingleContext(LLVMGlobalContainer self, long offset, Object value,
@Shared("p1") @Cached BranchProfile needsInitialize,
@Shared("p2") @Cached BranchProfile needsInvalidation) {
assert offset == 0;
self.set(value, needsInitialize, needsInvalidation);
}

@Specialization(guards = {"!self.isPointer()", "offset == 0"}, replaces = "writeI64ManagedSingleContext")
static void writeI64Managed(LLVMGlobalContainer self, long offset, Object value) {
assert offset == 0;
self.setFallback(value);
}

@Specialization(guards = {"!self.isPointer()", "offset != 0"})
static void writeFallback(LLVMGlobalContainer self, long offset, Object value,
@CachedLibrary("self") InteropLibrary interop,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.profiles.ConditionProfile;
import com.oracle.truffle.llvm.runtime.LLVMLanguage;

/**
Expand All @@ -43,6 +45,7 @@ public final class LLVMThreadingStack {
private final Map<Thread, LLVMStack> threadMap;
private final long stackSize;
private final Thread mainThread;
@CompilationFinal private LLVMStack mainThreadStack;

public LLVMThreadingStack(Thread mainTread, long stackSize) {
this.mainThread = mainTread;
Expand All @@ -58,6 +61,18 @@ public LLVMStack getStack() {
return s;
}

public LLVMStack getStackProfiled(Thread thread, ConditionProfile profile) {
if (profile.profile(thread == mainThread)) {
assert mainThreadStack != null;
return mainThreadStack;
}
LLVMStack s = getCurrentStack();
if (s == null) {
s = createNewStack();
}
return s;
}

@TruffleBoundary
private LLVMStack getCurrentStack() {
return threadMap.get(Thread.currentThread());
Expand All @@ -66,7 +81,11 @@ private LLVMStack getCurrentStack() {
@TruffleBoundary
private LLVMStack createNewStack() {
LLVMStack s = new LLVMStack(stackSize, LLVMLanguage.getContext());
Object previous = threadMap.putIfAbsent(Thread.currentThread(), s);
Thread currentThread = Thread.currentThread();
if (currentThread == mainThread) {
mainThreadStack = s;
}
Object previous = threadMap.putIfAbsent(currentThread, s);
assert previous == null;
return s;
}
Expand All @@ -84,6 +103,7 @@ public void freeStack(LLVMMemory memory, Thread thread) {

@TruffleBoundary
public void freeMainStack(LLVMMemory memory) {
mainThreadStack = null;
free(memory, mainThread);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import com.oracle.truffle.api.dsl.Specialization;
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.LLVMContext;
import com.oracle.truffle.llvm.runtime.LLVMLanguage;
import com.oracle.truffle.llvm.runtime.except.LLVMMemoryException;
Expand All @@ -54,13 +55,15 @@ protected LLVMManagedPointer doIntrinsic(Object rawHandle,
@Cached LLVMToNativeNode forceAddressNode,
@CachedLanguage LLVMLanguage language,
@Cached ConditionProfile isDerefProfile,
@Cached BranchProfile invalidHandle) {
@Cached BranchProfile invalidHandle,
@Cached("createClassProfile()") ValueProfile derefHandleContainerProfile,
@Cached("createClassProfile()") ValueProfile handleContainerProfile) {
long address = forceAddressNode.executeWithTarget(rawHandle).asNative();
try {
if (!language.getNoDerefHandleAssumption().isValid() && isDerefProfile.profile(LLVMHandleMemoryBase.isDerefHandleMemory(address))) {
return context.getDerefHandleContainer().getValue(this, address).copy();
return derefHandleContainerProfile.profile(context.getDerefHandleContainer()).getValue(this, address).copy();
} else {
return context.getHandleContainer().getValue(this, address).copy();
return handleContainerProfile.profile(context.getHandleContainer()).getValue(this, address).copy();
}
} catch (ArrayIndexOutOfBoundsException | NullPointerException ex) {
invalidHandle.enter();
Expand Down

0 comments on commit 0f5abc1

Please sign in to comment.