diff --git a/build.sbt b/build.sbt index fd55d75409..599c71b930 100644 --- a/build.sbt +++ b/build.sbt @@ -479,6 +479,7 @@ val sqliteVersion = "3.41.2.1" val tikaVersion = "2.4.1" val typesafeConfigVersion = "1.4.2" val junitVersion = "4.13.2" +val junitIfVersion = "0.11" val netbeansApiVersion = "RELEASE140" // ============================================================================ @@ -733,7 +734,7 @@ lazy val `logging-service` = project "io.circe" %% "circe-core" % circeVersion, "io.circe" %% "circe-parser" % circeVersion, "junit" % "junit" % junitVersion % Test, - "com.novocode" % "junit-interface" % "0.11" % Test exclude ("junit", "junit-dep"), + "com.novocode" % "junit-interface" % junitIfVersion % Test exclude ("junit", "junit-dep"), "org.scalatest" %% "scalatest" % scalatestVersion % Test, "org.graalvm.nativeimage" % "svm" % graalVersion % "provided" ) @@ -989,6 +990,28 @@ lazy val `interpreter-dsl` = (project in file("lib/scala/interpreter-dsl")) ) ) +lazy val `interpreter-dsl-test` = + (project in file("engine/interpreter-dsl-test")) + .configs(Test) + .settings( + version := "0.1", + frgaalJavaCompilerSetting, + Test / fork := true, + Test / javaOptions ++= Seq( + "-Dgraalvm.locatorDisabled=true", + s"--upgrade-module-path=${file("engine/runtime/build-cache/truffle-api.jar").absolutePath}" + ), + commands += WithDebugCommand.withDebug, + libraryDependencies ++= Seq( + "org.graalvm.truffle" % "truffle-api" % graalVersion % "provided", + "org.graalvm.truffle" % "truffle-dsl-processor" % graalVersion % "provided", + "junit" % "junit" % junitVersion % Test, + "com.novocode" % "junit-interface" % junitIfVersion % Test exclude ("junit", "junit-dep") + ) + ) + .dependsOn(`interpreter-dsl`) + .dependsOn(`runtime`) + // ============================================================================ // === Sub-Projects =========================================================== // ============================================================================ @@ -1310,7 +1333,7 @@ lazy val runtime = (project in file("engine/runtime")) "org.graalvm.truffle" % "truffle-api" % graalVersion % Benchmark, "org.typelevel" %% "cats-core" % catsVersion, "junit" % "junit" % junitVersion % Test, - "com.novocode" % "junit-interface" % "0.11" % Test exclude ("junit", "junit-dep") + "com.novocode" % "junit-interface" % junitIfVersion % Test exclude ("junit", "junit-dep") ), Compile / compile / compileInputs := (Compile / compile / compileInputs) .dependsOn(CopyTruffleJAR.preCompileTask) diff --git a/engine/interpreter-dsl-test/src/test/java/org/enso/interpreter/dsl/test/InliningBuiltinsInNode.java b/engine/interpreter-dsl-test/src/test/java/org/enso/interpreter/dsl/test/InliningBuiltinsInNode.java new file mode 100644 index 0000000000..b37ca62a7d --- /dev/null +++ b/engine/interpreter-dsl-test/src/test/java/org/enso/interpreter/dsl/test/InliningBuiltinsInNode.java @@ -0,0 +1,13 @@ +package org.enso.interpreter.dsl.test; + +import com.oracle.truffle.api.nodes.Node; +import org.enso.interpreter.dsl.BuiltinMethod; + +@BuiltinMethod(type = "InliningBuiltins", name = "in") +final class InliningBuiltinsInNode extends Node { + + long execute(long a, long b) { + return a + b; + } + +} diff --git a/engine/interpreter-dsl-test/src/test/java/org/enso/interpreter/dsl/test/InliningBuiltinsOutNode.java b/engine/interpreter-dsl-test/src/test/java/org/enso/interpreter/dsl/test/InliningBuiltinsOutNode.java new file mode 100644 index 0000000000..d24ac1ebb9 --- /dev/null +++ b/engine/interpreter-dsl-test/src/test/java/org/enso/interpreter/dsl/test/InliningBuiltinsOutNode.java @@ -0,0 +1,16 @@ +package org.enso.interpreter.dsl.test; + +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.nodes.Node; +import org.enso.interpreter.dsl.BuiltinMethod; +import org.junit.Assert; + +@BuiltinMethod(type = "InliningBuiltins", name = "out") +final class InliningBuiltinsOutNode extends Node { + + long execute(VirtualFrame frame, long a, long b) { + Assert.assertNotNull("VirtualFrame is always provided " + frame); + return a + b; + } + +} diff --git a/engine/interpreter-dsl-test/src/test/java/org/enso/interpreter/dsl/test/InliningBuiltinsTest.java b/engine/interpreter-dsl-test/src/test/java/org/enso/interpreter/dsl/test/InliningBuiltinsTest.java new file mode 100644 index 0000000000..37f3d7f500 --- /dev/null +++ b/engine/interpreter-dsl-test/src/test/java/org/enso/interpreter/dsl/test/InliningBuiltinsTest.java @@ -0,0 +1,43 @@ +package org.enso.interpreter.dsl.test; + +import org.enso.interpreter.node.InlineableRootNode; +import org.enso.interpreter.runtime.callable.function.Function; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; +import org.junit.Test; + +public class InliningBuiltinsTest { + + /** @see InliningBuiltinsInNode#execute(long, long) */ + @Test + public void executeWithoutVirtualFrame() { + var fn = InliningBuiltinsInMethodGen.makeFunction(null); + if (fn.getCallTarget().getRootNode() instanceof InlineableRootNode root) { + var call = root.createDirectCallNode(); + var clazz = call.getClass().getSuperclass(); + assertEquals("InlinedCallNode", clazz.getSimpleName()); + assertEquals("BuiltinRootNode", clazz.getEnclosingClass().getSimpleName()); + + var res = call.call(Function.ArgumentsHelper.buildArguments(null, null, new Object[] { null, 5L, 7L })); + assertEquals(12L, res); + } else { + fail("It is inlineable: " + fn.getCallTarget().getRootNode()); + } + } + + /** @see InliningBuiltinsOutNode#execute(com.oracle.truffle.api.frame.VirtualFrame, long, long) */ + @Test + public void executeWithVirtualFrame() { + var fn = InliningBuiltinsOutMethodGen.makeFunction(null); + if (fn.getCallTarget().getRootNode() instanceof InlineableRootNode root) { + var call = root.createDirectCallNode(); + var clazz = call.getClass().getSuperclass(); + assertEquals("com.oracle.truffle.api.nodes.DirectCallNode", clazz.getName()); + + var res = call.call(Function.ArgumentsHelper.buildArguments(null, null, new Object[] { null, 3L, 9L })); + assertEquals(12L, res); + } else { + fail("It is inlineable: " + fn.getCallTarget().getRootNode()); + } + } +} diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/BuiltinRootNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/BuiltinRootNode.java index c36cd40d4d..8d67dd59bb 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/BuiltinRootNode.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/BuiltinRootNode.java @@ -90,7 +90,7 @@ public abstract class BuiltinRootNode extends RootNode implements InlineableRoot @Override public final CallTarget getClonedCallTarget() { - return null; + return getRootNode().getCallTarget(); } } } diff --git a/lib/scala/interpreter-dsl/src/main/java/org/enso/interpreter/dsl/BuiltinMethod.java b/lib/scala/interpreter-dsl/src/main/java/org/enso/interpreter/dsl/BuiltinMethod.java index cf071ca70c..c5163ae96f 100644 --- a/lib/scala/interpreter-dsl/src/main/java/org/enso/interpreter/dsl/BuiltinMethod.java +++ b/lib/scala/interpreter-dsl/src/main/java/org/enso/interpreter/dsl/BuiltinMethod.java @@ -5,11 +5,17 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -/** An annotation denoting a node that should be wrapped for standard library export. */ +/** + * An annotation denoting a node that should be wrapped for standard library export. A subclass of + * {@code BuiltinRootNode} is generated with implementation of {@code + * InlineableRootNode#createDirectCallNode()} that either delegates to regular {@link + * DirectCallNode} (when the {@code execute} method requires {@code VirtualFrame} as one of its + * arguments) or provides a special implementation, if no {@code VirtualFrame} is needed. + */ @Target(ElementType.TYPE) @Retention(RetentionPolicy.SOURCE) public @interface BuiltinMethod { - /** @return the language-level type of {@code this} argument. */ + /** @return the language-level type of {@code self} argument. */ String type(); /** @return the language-level name of this method. */