6161import org .graalvm .polyglot .Context ;
6262import org .graalvm .polyglot .Engine ;
6363import org .graalvm .polyglot .Instrument ;
64+ import org .graalvm .polyglot .PolyglotAccess ;
6465import org .graalvm .polyglot .PolyglotException ;
6566import org .junit .Assert ;
6667import org .junit .Test ;
6768
69+ import com .oracle .truffle .api .CallTarget ;
70+ import com .oracle .truffle .api .CompilerDirectives ;
6871import com .oracle .truffle .api .ContextLocal ;
6972import com .oracle .truffle .api .ContextThreadLocal ;
73+ import com .oracle .truffle .api .InstrumentInfo ;
7074import com .oracle .truffle .api .TruffleContext ;
7175import com .oracle .truffle .api .TruffleLanguage ;
7276import com .oracle .truffle .api .TruffleLanguage .Env ;
7377import com .oracle .truffle .api .frame .VirtualFrame ;
7478import com .oracle .truffle .api .instrumentation .EventContext ;
7579import com .oracle .truffle .api .instrumentation .ExecutionEventListener ;
7680import com .oracle .truffle .api .instrumentation .SourceSectionFilter ;
81+ import com .oracle .truffle .api .instrumentation .ThreadsActivationListener ;
7782import com .oracle .truffle .api .instrumentation .TruffleInstrument ;
83+ import com .oracle .truffle .api .nodes .IndirectCallNode ;
7884import 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
8089public 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 ) {
0 commit comments