use of com.oracle.truffle.api.test.polyglot.ProxyLanguage in project graal by oracle.
the class CodeInvalidationTest method testInvalidation.
@Test
public void testInvalidation() throws IOException, InterruptedException {
/*
* The test runs the same compiled code in two threads. Invalidation in one thread using
* CompilerDirectives#transferToInterpreterAndInvalidate causes deopt in that thread and
* makes the code non-enterable. However, the other thread does not necessarily deopt and
* can still continue executing the invalidated code, so a subsequent node replace must also
* deopt the other thread in order for the replace to have effect. This test checks whether
* this works properly.
*/
CountDownLatch latch = new CountDownLatch(1);
NodeToInvalidate nodeToInvalidate = new NodeToInvalidate(ThreadLocal.withInitial(() -> true), latch);
WhileLoopNode testedCode = new WhileLoopNode(1000000000, nodeToInvalidate);
LoopNode loopNode = testedCode.loop;
setupEnv(Context.create(), new ProxyLanguage() {
/**
* Makes sure we use the same call target for the single source that we use. Otherwise
* storing the frame slots in member fields of WhileLoopNode wouldn't work as the
* WhileLoopNode is pre-created before the parsing, and so it can be used only in one
* call target (root node).
*/
private CallTarget target;
@Override
protected synchronized CallTarget parse(ParsingRequest request) {
com.oracle.truffle.api.source.Source source = request.getSource();
if (target == null) {
target = new RootNode(languageInstance) {
@Node.Child
private volatile BaseNode child = testedCode;
@Override
public Object execute(VirtualFrame frame) {
return child.execute(frame);
}
@Override
public SourceSection getSourceSection() {
return source.createSection(1);
}
}.getCallTarget();
}
return target;
}
@Override
protected boolean isThreadAccessAllowed(Thread thread, boolean singleThreaded) {
return true;
}
});
Source source = Source.newBuilder(ProxyLanguage.ID, "", "DummySource").build();
Future<?> future1;
Future<?> future2;
ExecutorService executor = Executors.newFixedThreadPool(2);
try {
future1 = executor.submit(new RunCode(context, source, null));
nodeToInvalidate.latch.await();
/*
* The latch is counted down only in compiled code, so the code should be compiled now.
*/
OptimizedCallTarget loopCallTarget = ((OptimizedOSRLoopNode) loopNode).getCompiledOSRLoop();
Assert.assertNotNull(loopCallTarget);
Assert.assertTrue(loopCallTarget.isValid());
future2 = executor.submit(new RunCode(context, source, nodeToInvalidate));
future1.get();
future2.get();
Assert.fail();
} catch (ExecutionException e) {
Assert.assertTrue(e.getCause() instanceof PolyglotException);
Assert.assertEquals("java.lang.RuntimeException: " + NODE_REPLACE_SUCCESSFUL, e.getCause().getMessage());
} finally {
executor.shutdownNow();
executor.awaitTermination(100, TimeUnit.SECONDS);
}
}
use of com.oracle.truffle.api.test.polyglot.ProxyLanguage in project graal by oracle.
the class DebugValueTest method testNull.
@Test
public void testNull() {
ProxyLanguage.setDelegate(new ProxyLanguage() {
@Override
protected CallTarget parse(TruffleLanguage.ParsingRequest request) throws Exception {
return new TestRootNode(languageInstance).getCallTarget();
}
final class TestRootNode extends RootNode {
@Node.Child
TestBody body = new TestBody();
private final int a;
private final int b;
private final int c;
TestRootNode(TruffleLanguage<?> language) {
super(language);
a = getFrameDescriptor().findOrAddAuxiliarySlot("a");
b = getFrameDescriptor().findOrAddAuxiliarySlot("b");
c = getFrameDescriptor().findOrAddAuxiliarySlot("c");
}
@Override
public Object execute(VirtualFrame frame) {
frame.setAuxiliarySlot(a, new ValueLanguageTest.NullObject());
frame.setAuxiliarySlot(b, 11);
frame.setAuxiliarySlot(c, new Object());
return body.execute(frame);
}
}
});
try (DebuggerSession session = tester.startSession(SourceElement.ROOT)) {
session.suspendNextExecution();
Source source = Source.create(ProxyLanguage.ID, "");
tester.startEval(source);
expectSuspended((SuspendedEvent event) -> {
Iterator<DebugValue> declaredValues = event.getTopStackFrame().getScope().getDeclaredValues().iterator();
DebugValue var0 = declaredValues.next();
DebugValue var1 = declaredValues.next();
// var2 is not an interop value
assertFalse(declaredValues.hasNext());
assertTrue(var0.isReadable());
assertTrue(var1.isReadable());
assertNull(var0.getProperties());
assertFalse(var0.isArray());
assertFalse(var0.isBoolean());
assertFalse(var0.isDate());
assertFalse(var0.isDuration());
assertFalse(var0.isInstant());
assertFalse(var0.isInternal());
assertFalse(var0.isMetaObject());
assertTrue(var0.isNull());
assertFalse(var0.isNumber());
assertTrue(var0.isReadable());
assertFalse(var0.isString());
assertFalse(var0.isTime());
assertFalse(var0.isTimeZone());
assertEquals("11", var1.toDisplayString());
});
}
expectDone();
}
use of com.oracle.truffle.api.test.polyglot.ProxyLanguage in project graal by oracle.
the class TruffleExceptionTest method testExceptionFromPolyglotExceptionConstructorImpl.
private void testExceptionFromPolyglotExceptionConstructorImpl(ExceptionType type, boolean internal, TruffleExceptionImpl.MessageKind... failOn) {
setupEnv(Context.create(), new ProxyLanguage() {
@Override
protected CallTarget parse(TruffleLanguage.ParsingRequest request) throws Exception {
ThrowNode throwNode = new ThrowNode((n) -> new TruffleExceptionImpl("test", n, type, new InjectException(failOn)));
return new TestRootNode(languageInstance, "test", "unnamed", throwNode).getCallTarget();
}
});
assertFails(() -> context.eval(ProxyLanguage.ID, "Test"), PolyglotException.class, (pe) -> {
Assert.assertEquals(internal, pe.isInternalError());
});
}
use of com.oracle.truffle.api.test.polyglot.ProxyLanguage in project graal by oracle.
the class TruffleExceptionTest method testTruffleExceptionCustomGuestObject.
@Test
public void testTruffleExceptionCustomGuestObject() {
setupEnv(createContext(verifyingHandler), new ProxyLanguage() {
@Override
protected CallTarget parse(TruffleLanguage.ParsingRequest request) throws Exception {
return createAST(AbstractTruffleException.class, languageInstance, (n) -> new TruffleExceptionImpl("Test exception", n), true);
}
});
verifyingHandler.expect(BlockNode.Kind.TRY, BlockNode.Kind.CATCH, BlockNode.Kind.FINALLY);
context.eval(ProxyLanguage.ID, "Test");
}
use of com.oracle.truffle.api.test.polyglot.ProxyLanguage in project graal by oracle.
the class TruffleSafepointTest method setupSafepointLoop.
@SuppressWarnings("unchecked")
private TestSetup setupSafepointLoop(int threads, NodeCallable callable, Consumer<Throwable> exHandler) {
Context c = createTestContext();
TestSetup setup = null;
try {
c.enter();
c.initialize(ProxyLanguage.ID);
ProxyLanguage proxyLanguage = ProxyLanguage.get(null);
Env env = LanguageContext.get(null).getEnv();
TruffleInstrument.Env instrument = c.getEngine().getInstruments().get(ProxyInstrument.ID).lookup(ProxyInstrument.Initialize.class).getEnv();
c.leave();
CountDownLatch latch = new CountDownLatch(threads);
Object targetEnter = env.getContext().enter(null);
AtomicBoolean stopped = new AtomicBoolean();
TestSetup finalSetup = setup = new TestSetup(c, env, instrument, stopped);
setup.root = new TestRootNode(proxyLanguage, stopped, setup, latch, callable);
setup.target = setup.root.getCallTarget();
env.getContext().leave(null, targetEnter);
setup.futures = new ArrayList<>();
for (int i = 0; i < threads; i++) {
setup.futures.add(service.submit(() -> {
Object prev = env.getContext().enter(finalSetup.target.getRootNode());
try {
do {
try {
return (Boolean) finalSetup.target.call(latch);
} catch (Throwable t) {
if (exHandler != null) {
exHandler.accept(t);
} else {
throw t;
}
}
} while (!stopped.get());
return true;
} finally {
env.getContext().leave(finalSetup.target.getRootNode(), prev);
}
}));
}
try {
if (!latch.await(TIMEOUT_SECONDS, TimeUnit.SECONDS)) {
for (Future<Boolean> future : setup.futures) {
if (future.isDone()) {
try {
future.get();
} catch (ExecutionException e) {
throw new AssertionError(e.getCause());
}
}
}
throw new AssertionError();
}
} catch (InterruptedException e) {
throw new AssertionError(e);
}
return setup;
} catch (Throwable t) {
if (setup != null && setup.futures != null) {
setup.close();
} else {
c.close();
}
throw t;
}
}
Aggregations