Skip to content

Commit 94cccb5

Browse files
committed
[GR-31145] Make updating context locals and context thread locals work for inner contexts.
PullRequest: graal/10072
2 parents 0e92cab + 7b40f7d commit 94cccb5

File tree

4 files changed

+152
-35
lines changed

4 files changed

+152
-35
lines changed

truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ContextLocalTest.java

Lines changed: 102 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,21 +61,30 @@
6161
import org.graalvm.polyglot.Context;
6262
import org.graalvm.polyglot.Engine;
6363
import org.graalvm.polyglot.Instrument;
64+
import org.graalvm.polyglot.PolyglotAccess;
6465
import org.graalvm.polyglot.PolyglotException;
6566
import org.junit.Assert;
6667
import org.junit.Test;
6768

69+
import com.oracle.truffle.api.CallTarget;
70+
import com.oracle.truffle.api.CompilerDirectives;
6871
import com.oracle.truffle.api.ContextLocal;
6972
import com.oracle.truffle.api.ContextThreadLocal;
73+
import com.oracle.truffle.api.InstrumentInfo;
7074
import com.oracle.truffle.api.TruffleContext;
7175
import com.oracle.truffle.api.TruffleLanguage;
7276
import com.oracle.truffle.api.TruffleLanguage.Env;
7377
import com.oracle.truffle.api.frame.VirtualFrame;
7478
import com.oracle.truffle.api.instrumentation.EventContext;
7579
import com.oracle.truffle.api.instrumentation.ExecutionEventListener;
7680
import com.oracle.truffle.api.instrumentation.SourceSectionFilter;
81+
import com.oracle.truffle.api.instrumentation.ThreadsActivationListener;
7782
import com.oracle.truffle.api.instrumentation.TruffleInstrument;
83+
import com.oracle.truffle.api.nodes.IndirectCallNode;
7884
import com.oracle.truffle.api.nodes.LanguageInfo;
85+
import com.oracle.truffle.api.nodes.Node;
86+
import com.oracle.truffle.api.nodes.RootNode;
87+
import com.oracle.truffle.api.source.Source;
7988

8089
public class ContextLocalTest extends AbstractPolyglotTest {
8190

@@ -687,8 +696,11 @@ public void testUnstableContextThreadLocalValue() {
687696
}
688697
}
689698

690-
public void testInstrumentCreatedBeforeContextsInitialized() {
691-
699+
@Test
700+
public void testInnerContextLocals() {
701+
try (Context ctx = Context.newBuilder().allowPolyglotAccess(PolyglotAccess.ALL).build()) {
702+
Assert.assertEquals(0, ctx.eval(VALID_SHARED_LANGUAGE, "").asInt());
703+
}
692704
}
693705

694706
@TruffleLanguage.Registration(id = VALID_EXCLUSIVE_LANGUAGE, name = VALID_EXCLUSIVE_LANGUAGE)
@@ -710,6 +722,17 @@ protected boolean isThreadAccessAllowed(Thread thread, boolean singleThreaded) {
710722
return true;
711723
}
712724

725+
@Override
726+
protected CallTarget parse(ParsingRequest request) throws Exception {
727+
RootNode rootNode = new RootNode(this) {
728+
@Override
729+
public Object execute(VirtualFrame frame) {
730+
return 0;
731+
}
732+
};
733+
return rootNode.getCallTarget();
734+
}
735+
713736
static final ContextReference<Env> CONTEXT_REF = ContextReference.create(ValidExclusiveLanguage.class);
714737
static final LanguageReference<ValidExclusiveLanguage> REFERENCE = LanguageReference.create(ValidExclusiveLanguage.class);
715738

@@ -782,11 +805,71 @@ public ContextThreadLocal<String> createContextThreadLocal0(String value) {
782805
return createContextThreadLocal((e, t) -> value);
783806
}
784807

808+
@Override
809+
protected CallTarget parse(ParsingRequest request) throws Exception {
810+
return (new VSLRootNode(this)).getCallTarget();
811+
}
812+
785813
static final ContextReference<Env> CONTEXT_REF = ContextReference.create(ValidSharedLanguage.class);
786814
static final LanguageReference<ValidSharedLanguage> REFERENCE = LanguageReference.create(ValidSharedLanguage.class);
787815

788816
}
789817

818+
public static class VSLRootNode extends RootNode {
819+
820+
@Node.Child private VSLNode node = new VSLNode();
821+
822+
public VSLRootNode(ValidSharedLanguage language) {
823+
super(language);
824+
}
825+
826+
@Override
827+
public Object execute(VirtualFrame virtualFrame) {
828+
return node.execute(virtualFrame);
829+
}
830+
831+
}
832+
833+
public static class VSLNode extends Node {
834+
835+
private final Source source = Source.newBuilder(VALID_EXCLUSIVE_LANGUAGE, "", "").build();
836+
837+
private final IndirectCallNode callNode = IndirectCallNode.create();
838+
839+
@SuppressWarnings("unused")
840+
public Object execute(VirtualFrame virtualFrame) {
841+
Env outerLanguageOuterEnv = ValidSharedLanguage.CONTEXT_REF.get(this);
842+
TruffleContext innerTruffleContext = createInnerContext(outerLanguageOuterEnv);
843+
Object outerTruffleContext = innerTruffleContext.enter(this);
844+
try {
845+
Env outerLanguageInnerEnv = ValidSharedLanguage.CONTEXT_REF.get(this);
846+
createInstrument(outerLanguageInnerEnv);
847+
CallTarget callTarget = parse(outerLanguageInnerEnv);
848+
return callNode.call(callTarget);
849+
} finally {
850+
innerTruffleContext.leave(this, outerTruffleContext);
851+
innerTruffleContext.close();
852+
}
853+
}
854+
855+
@CompilerDirectives.TruffleBoundary
856+
private CallTarget parse(Env env) {
857+
return env.parsePublic(source);
858+
}
859+
860+
@CompilerDirectives.TruffleBoundary
861+
private static TruffleContext createInnerContext(Env env) {
862+
return env.newContextBuilder().build();
863+
}
864+
865+
@CompilerDirectives.TruffleBoundary
866+
private static void createInstrument(Env env) {
867+
InstrumentInfo instrumentInfo = env.getInstruments().get(VALID_INSTRUMENT);
868+
env.lookup(instrumentInfo, ValidInstrument.class);
869+
}
870+
871+
}
872+
790873
@TruffleInstrument.Registration(id = VALID_INSTRUMENT, name = VALID_INSTRUMENT, services = ValidInstrument.class)
791874
public static class ValidInstrument extends TruffleInstrument {
792875

@@ -804,6 +887,23 @@ public static class ValidInstrument extends TruffleInstrument {
804887
protected void onCreate(Env env) {
805888
this.environment = env;
806889
env.registerService(this);
890+
env.getInstrumenter().attachThreadsActivationListener(new ThreadsActivationListener() {
891+
@Override
892+
public void onEnterThread(TruffleContext c) {
893+
if (threadLocalDynamicValue != null && contextLocalDynamicValue != null) {
894+
local0.get(c);
895+
threadLocal0.get(c);
896+
}
897+
}
898+
899+
@Override
900+
public void onLeaveThread(TruffleContext c) {
901+
if (threadLocalDynamicValue != null && contextLocalDynamicValue != null) {
902+
local0.get(c);
903+
threadLocal0.get(c);
904+
}
905+
}
906+
});
807907
}
808908

809909
InstrumentThreadLocalValue newInstrumentThreadLocal(TruffleContext context, Thread t) {

truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotContextImpl.java

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2624,13 +2624,39 @@ void initializeInstrumentContextThreadLocals() {
26242624
}
26252625
}
26262626

2627-
/**
2628-
* Updates the current thread locals from {@link PolyglotThreadInfo#contextThreadLocals}.
2629-
*/
2630-
synchronized Object[] updateThreadLocals() {
2631-
assert Thread.holdsLock(this);
2632-
Object[] newThreadLocals = getThreadLocals(Thread.currentThread());
2633-
return newThreadLocals;
2627+
void invokeLocalsFactories(LocalLocation[] contextLocalLocations, LocalLocation[] contextThreadLocalLocations) {
2628+
PolyglotContextImpl[] localChildContexts;
2629+
synchronized (this) {
2630+
if (localsCleared) {
2631+
return;
2632+
}
2633+
/*
2634+
* contextLocals might not be initialized yet, in which case the context local factory
2635+
* for this instrument will be invoked during contextLocals initialization.
2636+
*/
2637+
if (contextLocals != null) {
2638+
invokeContextLocalsFactory(contextLocals, contextLocalLocations);
2639+
invokeContextThreadLocalFactory(contextThreadLocalLocations);
2640+
}
2641+
localChildContexts = PolyglotContextImpl.this.childContexts.toArray(new PolyglotContextImpl[0]);
2642+
}
2643+
for (PolyglotContextImpl childCtx : localChildContexts) {
2644+
childCtx.invokeLocalsFactories(contextLocalLocations, contextThreadLocalLocations);
2645+
}
2646+
}
2647+
2648+
void resizeThreadLocals(StableLocalLocations locations) {
2649+
PolyglotContextImpl[] localChildContexts;
2650+
synchronized (this) {
2651+
if (localsCleared) {
2652+
return;
2653+
}
2654+
resizeContextThreadLocals(locations);
2655+
localChildContexts = PolyglotContextImpl.this.childContexts.toArray(new PolyglotContextImpl[0]);
2656+
}
2657+
for (PolyglotContextImpl childCtx : localChildContexts) {
2658+
childCtx.resizeThreadLocals(locations);
2659+
}
26342660
}
26352661

26362662
void resizeContextThreadLocals(StableLocalLocations locations) {
@@ -2643,6 +2669,20 @@ void resizeContextThreadLocals(StableLocalLocations locations) {
26432669
}
26442670
}
26452671

2672+
void resizeLocals(StableLocalLocations locations) {
2673+
PolyglotContextImpl[] localChildContexts;
2674+
synchronized (this) {
2675+
if (localsCleared) {
2676+
return;
2677+
}
2678+
resizeContextLocals(locations);
2679+
localChildContexts = PolyglotContextImpl.this.childContexts.toArray(new PolyglotContextImpl[0]);
2680+
}
2681+
for (PolyglotContextImpl childCtx : localChildContexts) {
2682+
childCtx.resizeLocals(locations);
2683+
}
2684+
}
2685+
26462686
void resizeContextLocals(StableLocalLocations locations) {
26472687
assert Thread.holdsLock(this);
26482688
Object[] oldLocals = this.contextLocals;

truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotEngineImpl.java

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1982,12 +1982,7 @@ LocalLocation[] addContextLocals(List<? extends AbstractContextLocal<?>> newLoca
19821982
newLocations = Arrays.copyOfRange(locationsCopy, stableLocations.locations.length, index);
19831983
}
19841984
for (PolyglotContextImpl context : aliveContexts) {
1985-
synchronized (context) {
1986-
if (context.localsCleared) {
1987-
continue;
1988-
}
1989-
context.resizeContextLocals(newStableLocations);
1990-
}
1985+
context.resizeLocals(newStableLocations);
19911986
}
19921987
return newLocations;
19931988
}
@@ -2015,12 +2010,7 @@ LocalLocation[] addContextThreadLocals(List<? extends AbstractContextThreadLocal
20152010
newLocations = Arrays.copyOfRange(locationsCopy, stableLocations.locations.length, index);
20162011
}
20172012
for (PolyglotContextImpl context : aliveContexts) {
2018-
synchronized (context) {
2019-
if (context.localsCleared) {
2020-
continue;
2021-
}
2022-
context.resizeContextThreadLocals(newStableLocations);
2023-
}
2013+
context.resizeThreadLocals(newStableLocations);
20242014
}
20252015
return newLocations;
20262016
}

truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotInstrument.java

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -184,20 +184,7 @@ void ensureCreated() {
184184
}
185185
if (contexts != null) {
186186
for (PolyglotContextImpl context : contexts) {
187-
synchronized (context) {
188-
if (context.localsCleared) {
189-
continue;
190-
}
191-
/*
192-
* contextLocals might not be initialized yet, in which case the context
193-
* local factory for this instrument will be invoked during contextLocals
194-
* initialization.
195-
*/
196-
if (context.contextLocals != null) {
197-
context.invokeContextLocalsFactory(context.contextLocals, contextLocalLocations);
198-
context.invokeContextThreadLocalFactory(contextThreadLocalLocations);
199-
}
200-
}
187+
context.invokeLocalsFactories(contextLocalLocations, contextThreadLocalLocations);
201188
}
202189
}
203190
}

0 commit comments

Comments
 (0)