From 87233cee2a9c0dae76068c1e8e385d5b231360ba Mon Sep 17 00:00:00 2001 From: Tomas Zezula Date: Fri, 16 Aug 2024 09:53:26 +0200 Subject: [PATCH] [GR-57292] TruffleStackTrace.fillIn doesn't work during context pre-init. --- .../ContextPreInitializationTest.java | 43 +++++++++++++++++++ .../oracle/truffle/api/TruffleStackTrace.java | 8 +++- 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ContextPreInitializationTest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ContextPreInitializationTest.java index b3b216b83b85..3f533810a037 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ContextPreInitializationTest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ContextPreInitializationTest.java @@ -47,6 +47,7 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -86,6 +87,10 @@ import java.util.stream.Collectors; import com.oracle.truffle.api.InternalResource; +import com.oracle.truffle.api.TruffleStackTrace; +import com.oracle.truffle.api.exception.AbstractTruffleException; +import com.oracle.truffle.api.interop.InteropLibrary; +import com.oracle.truffle.api.interop.UnsupportedMessageException; import com.oracle.truffle.api.test.ReflectionUtils; import org.graalvm.collections.Pair; import org.graalvm.options.OptionCategory; @@ -2907,6 +2912,44 @@ public void testPatchNotCalledOnNonAllowedLanguage() throws ReflectiveOperationE } } + @Test + public void testGR57292() throws Exception { + String message = "Test exception"; + BaseLanguage.registerAction(ContextPreInitializationTestFirstLanguage.class, ActionKind.ON_INITIALIZE_CONTEXT, (env) -> { + if (env.getContext().getParent() == null) { + try (TruffleContext innerContext = env.newInnerContextBuilder(FIRST).build()) { + try { + innerContext.evalPublic(null, com.oracle.truffle.api.source.Source.newBuilder(FIRST, "", "test").build()); + fail("Should not reach here."); + } catch (Exception e) { + InteropLibrary exceptions = InteropLibrary.getUncached(); + assertTrue(exceptions.isException(e)); + try { + assertEquals(message, exceptions.asString(exceptions.getExceptionMessage(e))); + } catch (UnsupportedMessageException um) { + throw CompilerDirectives.shouldNotReachHere(um); + } + } + } + } else { + TruffleExceptionImpl truffleException = new TruffleExceptionImpl(message); + TruffleStackTrace.fillIn(truffleException); + throw truffleException; + } + }); + setPatchable(FIRST); + doContextPreinitialize(FIRST); + Context.create(FIRST).close(); + } + + @SuppressWarnings("serial") + private static final class TruffleExceptionImpl extends AbstractTruffleException { + + TruffleExceptionImpl(String message) { + super(message); + } + } + private static boolean executedWithXCompOptions() { Properties props = System.getProperties(); return props.containsKey("polyglot.engine.CompileImmediately") || props.containsKey("polyglot.engine.BackgroundCompilation"); diff --git a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleStackTrace.java b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleStackTrace.java index 6822db666d7f..07d0e4cd9cb7 100644 --- a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleStackTrace.java +++ b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleStackTrace.java @@ -47,6 +47,7 @@ import java.util.Objects; import org.graalvm.polyglot.PolyglotException; +import org.graalvm.polyglot.impl.AbstractPolyglotImpl.AbstractHostLanguageService; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.frame.Frame; @@ -270,7 +271,12 @@ public static TruffleStackTrace fillIn(Throwable throwable) { private static boolean isHostException(Throwable throwable) { Object polyglotEngine = LanguageAccessor.ENGINE.getCurrentPolyglotEngine(); - return polyglotEngine != null && LanguageAccessor.ENGINE.getHostService(polyglotEngine).isHostException(throwable); + if (polyglotEngine == null) { + return false; + } + AbstractHostLanguageService hostService = LanguageAccessor.ENGINE.getHostService(polyglotEngine); + // hostService is null during context pre-initialization + return hostService != null && hostService.isHostException(throwable); } private static final class TracebackElement {