Skip to content

Commit c8bda96

Browse files
Only look at frames from the current context during stack walks
Also makes sure that all thread locals are contextualized
1 parent db04937 commit c8bda96

File tree

9 files changed

+92
-60
lines changed

9 files changed

+92
-60
lines changed

espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/EspressoLanguage.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ public final class EspressoLanguage extends TruffleLanguage<EspressoContext> {
104104
@CompilerDirectives.CompilationFinal //
105105
private static StaticShape<StaticObjectFactory> foreignShape;
106106

107-
private final ContextThreadLocal<EspressoThreadLocalState> threadLocalState = createContextThreadLocal(EspressoThreadLocalState::new);
107+
private final ContextThreadLocal<EspressoThreadLocalState> threadLocalState = createContextThreadLocal((context, thread) -> new EspressoThreadLocalState(context));
108108

109109
public EspressoLanguage() {
110110
// Initialize statically defined symbols and substitutions.

espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/ClassRegistry.java

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
import java.util.concurrent.ConcurrentHashMap;
3030
import java.util.concurrent.locks.ReadWriteLock;
3131
import java.util.concurrent.locks.ReentrantReadWriteLock;
32-
import java.util.function.Supplier;
3332

3433
import com.oracle.truffle.espresso.classfile.ClassfileParser;
3534
import com.oracle.truffle.espresso.classfile.ClassfileStream;
@@ -45,6 +44,7 @@
4544
import com.oracle.truffle.espresso.redefinition.DefineKlassListener;
4645
import com.oracle.truffle.espresso.runtime.EspressoContext;
4746
import com.oracle.truffle.espresso.runtime.EspressoException;
47+
import com.oracle.truffle.espresso.runtime.EspressoThreadLocalState;
4848
import com.oracle.truffle.espresso.runtime.StaticObject;
4949
import com.oracle.truffle.espresso.substitutions.JavaType;
5050

@@ -152,22 +152,18 @@ public void initKlassID(int futureKlassID) {
152152
* circularity error.
153153
*/
154154
// TODO: Rework this, a thread local is certainly less than optimal.
155-
static final ThreadLocal<TypeStack> stack = ThreadLocal.withInitial(TypeStack.supplier);
156155

157156
private DefineKlassListener defineKlassListener;
158157

159158
public void registerOnLoadListener(DefineKlassListener listener) {
160159
defineKlassListener = listener;
161160
}
162161

163-
static final class TypeStack {
164-
static final Supplier<TypeStack> supplier = new Supplier<TypeStack>() {
165-
@Override
166-
public TypeStack get() {
167-
return new TypeStack();
168-
}
169-
};
170-
Node head = null;
162+
public static final class TypeStack {
163+
Node head;
164+
165+
public TypeStack() {
166+
}
171167

172168
static final class Node {
173169
Symbol<Type> entry;
@@ -206,9 +202,6 @@ Symbol<Type> pop() {
206202
void push(Symbol<Type> type) {
207203
head = new Node(type, head);
208204
}
209-
210-
private TypeStack() {
211-
}
212205
}
213206

214207
private final EspressoContext context;
@@ -405,7 +398,8 @@ public static boolean loaderIsBootOrPlatform(StaticObject loader, Meta meta) {
405398

406399
@SuppressWarnings("try")
407400
private ObjectKlass createKlass(Meta meta, ParserKlass parserKlass, Symbol<Type> type, Symbol<Type> superKlassType, ClassDefinitionInfo info) {
408-
TypeStack chain = stack.get();
401+
EspressoThreadLocalState threadLocalState = meta.getContext().getLanguage().getThreadLocalState();
402+
TypeStack chain = threadLocalState.getTypeStack();
409403

410404
ObjectKlass superKlass = null;
411405
ObjectKlass[] superInterfaces = null;

espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/jni/JniEnv.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ public StaticObject getPendingException() {
161161
}
162162

163163
public EspressoException getPendingEspressoException() {
164-
return getContext().getLanguage().getThreadLocalState().getpendingException();
164+
return getContext().getLanguage().getThreadLocalState().getPendingException();
165165
}
166166

167167
public void clearPendingException() {

espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/nodes/EspressoInstrumentableNode.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,13 @@ public abstract class EspressoInstrumentableNode extends Node implements BciProv
5050

5151
public abstract Method getMethod();
5252

53+
@Override
5354
public final EspressoContext getContext() {
55+
// WARNING: this returns the **current**, thread-local, context; not a context associated with this node.
5456
return EspressoContext.get(this);
5557
}
5658

59+
@Override
5760
public final boolean isInstrumentable() {
5861
return true;
5962
}

espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/EspressoContext.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1010,6 +1010,9 @@ public void rerunclinit(ObjectKlass oldKlass) {
10101010

10111011
private static final ContextReference<EspressoContext> REFERENCE = ContextReference.create(EspressoLanguage.class);
10121012

1013+
/**
1014+
* Returns the <em>current</em>, thread-local, context.
1015+
*/
10131016
public static EspressoContext get(Node node) {
10141017
return REFERENCE.get(node);
10151018
}

espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/EspressoThreadLocalState.java

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,22 +22,29 @@
2222
*/
2323
package com.oracle.truffle.espresso.runtime;
2424

25+
import com.oracle.truffle.espresso.impl.ClassRegistry;
26+
import com.oracle.truffle.espresso.vm.VM;
27+
2528
public class EspressoThreadLocalState {
2629
private EspressoException pendingJniException;
30+
private final ClassRegistry.TypeStack typeStack;
31+
private final VM.PrivilegedStack privilegedStack;
2732

2833
@SuppressWarnings("unused")
29-
public EspressoThreadLocalState(EspressoContext context, Thread thread) {
34+
public EspressoThreadLocalState(EspressoContext context) {
35+
typeStack = new ClassRegistry.TypeStack();
36+
privilegedStack = new VM.PrivilegedStack(context);
3037
}
3138

3239
public StaticObject getPendingExceptionObject() {
33-
EspressoException espressoException = getpendingException();
40+
EspressoException espressoException = getPendingException();
3441
if (espressoException == null) {
3542
return null;
3643
}
3744
return espressoException.getExceptionObject();
3845
}
3946

40-
public EspressoException getpendingException() {
47+
public EspressoException getPendingException() {
4148
return pendingJniException;
4249
}
4350

@@ -49,4 +56,12 @@ public void setPendingException(EspressoException t) {
4956
public void clearPendingException() {
5057
setPendingException(null);
5158
}
59+
60+
public ClassRegistry.TypeStack getTypeStack() {
61+
return typeStack;
62+
}
63+
64+
public VM.PrivilegedStack getPrivilegedStack() {
65+
return privilegedStack;
66+
}
5267
}

espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/vm/StackWalk.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ private boolean isCallStackWalk(Method m) {
264264
@SuppressWarnings("fallthrough")
265265
@Override
266266
public Integer visitFrame(FrameInstance frameInstance) {
267-
EspressoRootNode root = VM.getEspressoRootFromFrame(frameInstance);
267+
EspressoRootNode root = VM.getEspressoRootFromFrame(frameInstance, meta.getContext());
268268
Method m = root == null ? null : root.getMethod();
269269
if (m != null) {
270270
switch (state) {
@@ -357,7 +357,8 @@ private void fillFrame(FrameInstance frameInstance, Method m, int index) {
357357
StaticObject memberName = meta.java_lang_StackFrameInfo_memberName.getObject(frame);
358358
Target_java_lang_invoke_MethodHandleNatives.plantResolvedMethod(memberName, m, m.getRefKind(), meta);
359359
meta.java_lang_invoke_MemberName_clazz.setObject(memberName, m.getDeclaringKlass().mirror());
360-
meta.java_lang_StackFrameInfo_bci.setInt(frame, VM.getEspressoRootFromFrame(frameInstance).readBCI(frameInstance.getFrame(FrameInstance.FrameAccess.READ_ONLY)));
360+
EspressoRootNode rootNode = VM.getEspressoRootFromFrame(frameInstance, meta.getContext());
361+
meta.java_lang_StackFrameInfo_bci.setInt(frame, rootNode.readBCI(frameInstance.getFrame(FrameInstance.FrameAccess.READ_ONLY)));
361362
}
362363
}
363364
}

espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/vm/VM.java

Lines changed: 53 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,6 @@
5959
import java.util.concurrent.ConcurrentHashMap;
6060
import java.util.concurrent.atomic.AtomicLong;
6161
import java.util.function.IntFunction;
62-
import java.util.function.Supplier;
6362

6463
import org.graalvm.collections.EconomicMap;
6564
import org.graalvm.options.OptionValues;
@@ -2403,7 +2402,7 @@ private boolean isAuthorized(StaticObject context, Klass klass) {
24032402
* frames are skipped according to {@link #isIgnoredBySecurityStackWalk}.
24042403
*/
24052404
@TruffleBoundary
2406-
private static FrameInstance getCallerFrame(int depth, boolean securityStackWalk, Meta meta) {
2405+
private FrameInstance getCallerFrame(int depth, boolean securityStackWalk, Meta meta) {
24072406
if (depth == JVM_CALLER_DEPTH) {
24082407
return getCallerFrame(1, securityStackWalk, meta);
24092408
}
@@ -2443,8 +2442,10 @@ public FrameInstance visitFrame(FrameInstance frameInstance) {
24432442
throw EspressoError.shouldNotReachHere(String.format("Caller frame not found at depth %d", depth));
24442443
}
24452444

2446-
@TruffleBoundary
2447-
public static EspressoRootNode getEspressoRootFromFrame(FrameInstance frameInstance) {
2445+
/**
2446+
* Returns the espresso root node for this frame, event if it comes from a different context.
2447+
*/
2448+
private static EspressoRootNode getRawEspressoRootFromFrame(FrameInstance frameInstance) {
24482449
if (frameInstance.getCallTarget() instanceof RootCallTarget) {
24492450
RootCallTarget callTarget = (RootCallTarget) frameInstance.getCallTarget();
24502451
RootNode rootNode = callTarget.getRootNode();
@@ -2456,14 +2457,34 @@ public static EspressoRootNode getEspressoRootFromFrame(FrameInstance frameInsta
24562457
}
24572458

24582459
@TruffleBoundary
2459-
public static Method getMethodFromFrame(FrameInstance frameInstance) {
2460-
// TODO this should take a context as argument and only return the method if the context
2461-
// matches
2462-
EspressoRootNode root = getEspressoRootFromFrame(frameInstance);
2463-
if (root != null) {
2464-
return root.getMethod();
2460+
public EspressoRootNode getEspressoRootFromFrame(FrameInstance frameInstance) {
2461+
return getEspressoRootFromFrame(frameInstance, getContext());
2462+
}
2463+
2464+
@TruffleBoundary
2465+
public static EspressoRootNode getEspressoRootFromFrame(FrameInstance frameInstance, EspressoContext context) {
2466+
EspressoRootNode root = getRawEspressoRootFromFrame(frameInstance);
2467+
if (root == null) {
2468+
return null;
24652469
}
2466-
return null;
2470+
Method method = root.getMethod();
2471+
if (method.getContext() != context) {
2472+
return null;
2473+
}
2474+
return root;
2475+
}
2476+
2477+
@TruffleBoundary
2478+
public Method getMethodFromFrame(FrameInstance frameInstance) {
2479+
EspressoRootNode root = getRawEspressoRootFromFrame(frameInstance);
2480+
if (root == null) {
2481+
return null;
2482+
}
2483+
Method method = root.getMethod();
2484+
if (method.getContext() != getContext()) {
2485+
return null;
2486+
}
2487+
return method;
24672488
}
24682489

24692490
@VmImpl(isJni = true)
@@ -2566,8 +2587,6 @@ public Object visitFrame(FrameInstance frameInstance) {
25662587

25672588
// region privileged
25682589

2569-
private final ThreadLocal<PrivilegedStack> privilegedStackThreadLocal = ThreadLocal.withInitial(PrivilegedStack.supplier);
2570-
25712590
private @JavaType(AccessControlContext.class) StaticObject createACC(@JavaType(ProtectionDomain[].class) StaticObject context,
25722591
boolean isPriviledged,
25732592
@JavaType(AccessControlContext.class) StaticObject priviledgedContext) {
@@ -2590,40 +2609,37 @@ public Object visitFrame(FrameInstance frameInstance) {
25902609
return createACC(context, false, StaticObject.NULL);
25912610
}
25922611

2593-
@TruffleBoundary
25942612
public PrivilegedStack getPrivilegedStack() {
2595-
return privilegedStackThreadLocal.get();
2613+
return getContext().getLanguage().getThreadLocalState().getPrivilegedStack();
25962614
}
25972615

2598-
static private class PrivilegedStack {
2599-
public static Supplier<PrivilegedStack> supplier = new Supplier<PrivilegedStack>() {
2600-
@Override
2601-
public PrivilegedStack get() {
2602-
return new PrivilegedStack();
2603-
}
2604-
};
2605-
2616+
public static final class PrivilegedStack {
2617+
private final EspressoContext espressoContext;
26062618
private Element top;
26072619

2608-
public void push(FrameInstance frame, StaticObject context, Klass klass) {
2609-
top = new Element(frame, context, klass, top);
2620+
public PrivilegedStack(EspressoContext context) {
2621+
this.espressoContext = context;
2622+
}
2623+
2624+
void push(FrameInstance frame, StaticObject context, Klass klass) {
2625+
top = new Element(frame, context, klass, top, espressoContext);
26102626
}
26112627

2612-
public void pop() {
2613-
assert top != null : "poping empty privileged stack !";
2628+
void pop() {
2629+
assert top != null : "popping empty privileged stack !";
26142630
top = top.next;
26152631
}
26162632

2617-
public boolean compare(FrameInstance frame) {
2618-
return top != null && top.compare(frame);
2633+
boolean compare(FrameInstance frame) {
2634+
return top != null && top.compare(frame, espressoContext);
26192635
}
26202636

2621-
public StaticObject peekContext() {
2637+
StaticObject peekContext() {
26222638
assert top != null;
26232639
return top.context;
26242640
}
26252641

2626-
public StaticObject classLoader() {
2642+
StaticObject classLoader() {
26272643
assert top != null;
26282644
return top.klass.getDefiningClassLoader();
26292645
}
@@ -2634,15 +2650,15 @@ static private class Element {
26342650
Klass klass;
26352651
Element next;
26362652

2637-
public Element(FrameInstance frame, StaticObject context, Klass klass, Element next) {
2638-
this.frameID = getFrameId(frame);
2653+
Element(FrameInstance frame, StaticObject context, Klass klass, Element next, EspressoContext espressoContext) {
2654+
this.frameID = getFrameId(frame, espressoContext);
26392655
this.context = context;
26402656
this.klass = klass;
26412657
this.next = next;
26422658
}
26432659

2644-
public boolean compare(FrameInstance other) {
2645-
EspressoRootNode rootNode = getEspressoRootFromFrame(other);
2660+
boolean compare(FrameInstance other, EspressoContext espressoContext) {
2661+
EspressoRootNode rootNode = getEspressoRootFromFrame(other, espressoContext);
26462662
if (rootNode != null) {
26472663
Frame readOnlyFrame = other.getFrame(FrameInstance.FrameAccess.READ_ONLY);
26482664
long frameIdOrZero = rootNode.readFrameIdOrZero(readOnlyFrame);
@@ -2651,8 +2667,8 @@ public boolean compare(FrameInstance other) {
26512667
return false;
26522668
}
26532669

2654-
private static long getFrameId(FrameInstance frame) {
2655-
EspressoRootNode rootNode = getEspressoRootFromFrame(frame);
2670+
private static long getFrameId(FrameInstance frame, EspressoContext espressoContext) {
2671+
EspressoRootNode rootNode = getEspressoRootFromFrame(frame, espressoContext);
26562672
Frame readOnlyFrame = frame.getFrame(FrameInstance.FrameAccess.READ_ONLY);
26572673
return rootNode.readFrameIdOrZero(readOnlyFrame);
26582674
}

truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1610,14 +1610,14 @@ protected final <T> ContextLocal<T> createContextLocal(ContextLocalFactory<C, T>
16101610

16111611
/**
16121612
* Creates a new context thread local reference for this Truffle language. Context thread locals
1613-
* for languages allow to store additional top-level values for each context and thread. The
1613+
* for languages allow storing additional top-level values for each context and thread. The
16141614
* factory may be invoked on any thread other than the thread of the context thread local value.
16151615
* <p>
16161616
* Context thread local references must be created during the invocation in the
16171617
* {@link TruffleLanguage} constructor. Calling this method at a later point in time will throw
16181618
* an {@link IllegalStateException}. For each registered {@link TruffleLanguage} subclass it is
16191619
* required to always produce the same number of context thread local references. The values
1620-
* produces by the factory must not be <code>null</code> and use a stable exact value type for
1620+
* produced by the factory must not be <code>null</code> and use a stable exact value type for
16211621
* each instance of a registered language class. If the return value of the factory is not
16221622
* stable or <code>null</code> then an {@link IllegalStateException} is thrown. These
16231623
* restrictions allow the Truffle runtime to read the value more efficiently.

0 commit comments

Comments
 (0)