use of com.oracle.truffle.api.test.polyglot.ProxyLanguage in project graal by oracle.
the class TruffleSafepointTest method testNoSafepointAfterThreadDispose.
@Test
public void testNoSafepointAfterThreadDispose() {
final ThreadLocal<Boolean> tl = new ThreadLocal<>();
ProxyLanguage.setDelegate(new ProxyLanguage() {
@Override
@TruffleBoundary
protected void initializeThread(LanguageContext context, Thread thread) {
tl.set(Boolean.TRUE);
}
@Override
@TruffleBoundary
protected void disposeThread(LanguageContext context, Thread thread) {
tl.set(Boolean.FALSE);
}
@Override
protected boolean isThreadAccessAllowed(Thread thread, boolean singleThreaded) {
return true;
}
});
forEachConfig((threads, events) -> {
CountDownLatch awaitThreadStart = new CountDownLatch(1);
AtomicBoolean threadsStopped = new AtomicBoolean();
try (TestSetup setup = setupSafepointLoop(threads, new NodeCallable() {
@TruffleBoundary
public boolean call(@SuppressWarnings("hiding") TestSetup setup, TestRootNode node) {
try {
List<Throwable> errors = Collections.synchronizedList(new ArrayList<>());
List<Thread> polyglotThreads = new ArrayList<>();
try {
for (int i = 0; i < threads; i++) {
Thread t = node.setup.env.createThread(() -> {
do {
TruffleContext context = node.setup.env.getContext();
TruffleSafepoint safepoint = TruffleSafepoint.getCurrent();
boolean prevSideEffects = safepoint.setAllowSideEffects(false);
try {
context.leaveAndEnter(null, () -> {
// cached thread local
return null;
});
} finally {
safepoint.setAllowSideEffects(prevSideEffects);
}
} while (!threadsStopped.get());
});
t.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
public void uncaughtException(@SuppressWarnings("hiding") Thread t, Throwable e) {
threadsStopped.set(true);
e.printStackTrace();
errors.add(e);
}
});
t.start();
polyglotThreads.add(t);
}
} finally {
awaitThreadStart.countDown();
}
for (Thread thread : polyglotThreads) {
thread.join();
}
for (Throwable t : errors) {
throw new AssertionError("thread threw error ", t);
}
return true;
} catch (InterruptedException e1) {
throw new AssertionError(e1);
}
}
})) {
try {
awaitThreadStart.await();
// important to let leaving and submitting race against each other
threadsStopped.set(true);
List<Future<?>> futures = new ArrayList<>();
for (int i = 0; i < events; i++) {
futures.add(setup.env.submitThreadLocal(null, new ThreadLocalAction(true, false) {
@Override
protected void perform(Access access) {
assertEquals(Boolean.TRUE, tl.get());
}
}));
}
for (Future<?> future : futures) {
try {
future.get();
} catch (ExecutionException e) {
throw new AssertionError(e);
}
}
} catch (InterruptedException e) {
throw new AssertionError(e);
}
setup.stopAndAwait();
}
});
ProxyLanguage.setDelegate(new ProxyLanguage());
}
use of com.oracle.truffle.api.test.polyglot.ProxyLanguage in project graal by oracle.
the class TruffleContextTest method testNoInitializeMultiContextForInnerContext.
@Test
public void testNoInitializeMultiContextForInnerContext() {
AtomicBoolean multiContextInitialized = new AtomicBoolean(false);
setupEnv(Context.create(), new ProxyLanguage() {
@Override
protected CallTarget parse(ParsingRequest request) throws Exception {
return RootNode.createConstantNode(42).getCallTarget();
}
@Override
protected void initializeMultipleContexts() {
multiContextInitialized.set(true);
}
@Override
protected boolean areOptionsCompatible(OptionValues firstOptions, OptionValues newOptions) {
return true;
}
});
TruffleContext internalContext = languageEnv.newContextBuilder().initializeCreatorContext(false).build();
internalContext.evalInternal(null, com.oracle.truffle.api.source.Source.newBuilder(ProxyLanguage.ID, "", "").build());
assertFalse(multiContextInitialized.get());
internalContext.close();
}
use of com.oracle.truffle.api.test.polyglot.ProxyLanguage in project graal by oracle.
the class TruffleContextTest method testExiting.
@Test
public void testExiting() throws ExecutionException, InterruptedException {
setupEnv(Context.newBuilder(), new ProxyLanguage() {
@Override
protected boolean isThreadAccessAllowed(Thread thread, boolean singleThreaded) {
return true;
}
});
ExecutorService executorService = Executors.newFixedThreadPool(1);
try {
AtomicReference<TruffleContext> entered = new AtomicReference<>();
CountDownLatch waitUntilExited = new CountDownLatch(1);
instrumentEnv.getInstrumenter().attachExecutionEventListener(SourceSectionFilter.newBuilder().tagIs(StandardTags.StatementTag.class).build(), new ExecutionEventListener() {
@TruffleBoundary
@Override
public void onEnter(EventContext ctx, VirtualFrame frame) {
entered.set(instrumentEnv.getEnteredContext());
}
@Override
public void onReturnValue(EventContext ctx, VirtualFrame frame, Object result) {
}
@Override
public void onReturnExceptional(EventContext ctx, VirtualFrame frame, Throwable exception) {
}
});
Future<?> future = executorService.submit(() -> {
context.enter();
try {
context.eval(InstrumentationTestLanguage.ID, "ROOT(STATEMENT,EXIT(1))");
fail();
} catch (PolyglotException pe) {
if (!pe.isExit()) {
throw pe;
}
assertEquals(1, pe.getExitStatus());
assertTrue(entered.get().isExiting());
} finally {
context.leave();
}
waitUntilExited.countDown();
});
boolean othrerThreadExited = false;
while (!othrerThreadExited) {
try {
waitUntilExited.await();
othrerThreadExited = true;
} catch (InterruptedException ie) {
}
}
/*
* Multi-threading is necessary, otherwise the context is closed while entered and we
* cannot check isExiting().
*/
context.leave();
TruffleContext tc = entered.get();
tc.close();
future.get();
assertFalse(tc.isExiting());
assertTrue(tc.isClosed());
} finally {
executorService.shutdownNow();
executorService.awaitTermination(100, TimeUnit.SECONDS);
}
}
use of com.oracle.truffle.api.test.polyglot.ProxyLanguage in project graal by oracle.
the class ThreadsActivationListenerTest method testMultiContext.
@Test
public void testMultiContext() {
Engine engine = Engine.create();
setupEnv(Context.newBuilder().engine(engine).build(), new ProxyLanguage() {
@Override
protected CallTarget parse(ParsingRequest request) throws Exception {
return RootNode.createConstantNode(42).getCallTarget();
}
});
Context c0 = this.context;
TruffleContext tc0 = this.languageEnv.getContext();
setupEnv(Context.newBuilder().engine(engine).build(), new ProxyLanguage() {
@Override
protected CallTarget parse(ParsingRequest request) throws Exception {
return RootNode.createConstantNode(42).getCallTarget();
}
});
Context c1 = this.context;
TruffleContext tc1 = languageEnv.getContext();
List<TruffleContext> entered = new ArrayList<>();
List<TruffleContext> left = new ArrayList<>();
EventBinding<?> binding = instrumentEnv.getInstrumenter().attachThreadsActivationListener(new ThreadsActivationListener() {
@TruffleBoundary
public void onEnterThread(TruffleContext c) {
entered.add(c);
}
@TruffleBoundary
public void onLeaveThread(TruffleContext c) {
left.add(c);
}
});
assertList(entered);
assertList(left);
c0.enter();
assertList(entered, tc0);
assertList(left);
c1.enter();
assertList(entered, tc0, tc1);
assertList(left);
c1.leave();
assertList(entered, tc0, tc1);
assertList(left, tc1);
c0.leave();
assertList(entered, tc0, tc1);
assertList(left, tc1, tc0);
binding.dispose();
c0.enter();
c1.enter();
c1.leave();
c0.leave();
assertList(entered, tc0, tc1);
assertList(left, tc1, tc0);
c0.close();
c1.close();
engine.close();
}
use of com.oracle.truffle.api.test.polyglot.ProxyLanguage in project graal by oracle.
the class ThreadsActivationListenerTest method testMultiThreading.
@Test
public void testMultiThreading() throws InterruptedException {
setupEnv(Context.create(), new ProxyLanguage() {
@Override
protected CallTarget parse(ParsingRequest request) throws Exception {
return RootNode.createConstantNode(42).getCallTarget();
}
@Override
protected boolean isThreadAccessAllowed(Thread thread, boolean singleThreaded) {
return true;
}
});
List<TruffleContext> entered = new ArrayList<>();
List<TruffleContext> left = new ArrayList<>();
instrumentEnv.getInstrumenter().attachThreadsActivationListener(new ThreadsActivationListener() {
@TruffleBoundary
public void onEnterThread(TruffleContext c) {
synchronized (entered) {
entered.add(c);
}
}
@TruffleBoundary
public void onLeaveThread(TruffleContext c) {
synchronized (left) {
left.add(c);
}
}
});
assertList(entered);
assertList(left);
TruffleContext to = languageEnv.getContext();
context.enter();
assertList(entered, to);
assertList(left);
Thread t = new Thread(new Runnable() {
public void run() {
assertList(entered, to);
assertList(left);
context.enter();
assertList(entered, to, to);
assertList(left);
context.leave();
assertList(entered, to, to);
assertList(left, to);
}
});
t.start();
t.join();
context.leave();
assertList(entered, to, to);
assertList(left, to, to);
}
Aggregations