mirror of
https://github.com/enso-org/enso.git
synced 2024-11-22 22:10:15 +03:00
Add Polyglot Support in Runtime Tests (#4016)
`runtime-with-instruments` project sets `-Dgraalvm.locatorDisabled=true` that disables the discovery of available polyglot languages (installed with `gu`). On the other hand, enabling locator makes polyglot languages available, but also makes the program classes and the test classes loaded with different classloaders. This way we're unable to use `EnsoContext` in tests to observe internal context state (there is an exception when you try to cast to `EnsoContext`). The solution is to move tests with enabled polyglot support, but disabled `EnsoContext` introspection to a separate project.
This commit is contained in:
parent
1e5e2327ab
commit
9df6448d85
49
build.sbt
49
build.sbt
@ -285,6 +285,7 @@ lazy val enso = (project in file("."))
|
||||
`runtime-instrument-repl-debugger`,
|
||||
`runtime-instrument-runtime-server`,
|
||||
`runtime-with-instruments`,
|
||||
`runtime-with-polyglot`,
|
||||
`runtime-version-manager`,
|
||||
`runtime-version-manager-test`,
|
||||
editions,
|
||||
@ -1143,6 +1144,7 @@ lazy val `polyglot-api` = project
|
||||
},
|
||||
libraryDependencies ++= Seq(
|
||||
"org.graalvm.sdk" % "polyglot-tck" % graalVersion % "provided",
|
||||
"org.graalvm.truffle" % "truffle-api" % graalVersion % "provided",
|
||||
"com.google.flatbuffers" % "flatbuffers-java" % flatbuffersVersion,
|
||||
"org.scalatest" %% "scalatest" % scalatestVersion % Test,
|
||||
"org.scalacheck" %% "scalacheck" % scalacheckVersion % Test
|
||||
@ -1569,6 +1571,53 @@ lazy val `runtime-with-instruments` =
|
||||
.dependsOn(`runtime-instrument-repl-debugger`)
|
||||
.dependsOn(`runtime-instrument-runtime-server`)
|
||||
|
||||
/* runtime-with-polyglot
|
||||
* ~~~~~~~~~~~~~~~~~~~~~
|
||||
* A project that allows loading polyglot languages by not disabling
|
||||
* the GraalVM locator explicitly with `-Dgraalvm.locatorDisabled=true` like the
|
||||
* `runtime-with-instruments` project does. It means that the test classes and
|
||||
* runtime classes are loaded using different classloaders, and the test code
|
||||
* cannot access the `EnsoContext`.
|
||||
*/
|
||||
|
||||
lazy val `runtime-with-polyglot` =
|
||||
(project in file("engine/runtime-with-polyglot"))
|
||||
.configs(Benchmark)
|
||||
.settings(
|
||||
frgaalJavaCompilerSetting,
|
||||
inConfig(Compile)(truffleRunOptionsSettings),
|
||||
inConfig(Benchmark)(Defaults.testSettings),
|
||||
commands += WithDebugCommand.withDebug,
|
||||
Benchmark / javacOptions --= Seq(
|
||||
"-source",
|
||||
frgaalSourceLevel,
|
||||
"--enable-preview"
|
||||
),
|
||||
Test / javaOptions ++= {
|
||||
// Note [Classpath Separation]
|
||||
val runtimeClasspath =
|
||||
(LocalProject("runtime") / Compile / fullClasspath).value
|
||||
val runtimeInstrumentsClasspath =
|
||||
(LocalProject("runtime-with-instruments") / Compile / fullClasspath).value
|
||||
val appendClasspath =
|
||||
(runtimeClasspath ++ runtimeInstrumentsClasspath)
|
||||
.map(_.data)
|
||||
.mkString(File.pathSeparator)
|
||||
Seq(
|
||||
s"-Dtruffle.class.path.append=$appendClasspath"
|
||||
)
|
||||
},
|
||||
Test / fork := true,
|
||||
Test / envVars ++= distributionEnvironmentOverrides ++ Map(
|
||||
"ENSO_TEST_DISABLE_IR_CACHE" -> "false"
|
||||
),
|
||||
libraryDependencies ++= Seq(
|
||||
"org.scalatest" %% "scalatest" % scalatestVersion % Test
|
||||
)
|
||||
)
|
||||
.dependsOn(runtime % "compile->compile;test->test;runtime->runtime")
|
||||
.dependsOn(`runtime-with-instruments`)
|
||||
|
||||
/* Note [Unmanaged Classpath]
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* As the definition of the core primitives in `core_definition` is achieved
|
||||
|
@ -1,10 +1,9 @@
|
||||
package org.enso.polyglot;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.logging.Level;
|
||||
import org.graalvm.options.OptionDescriptor;
|
||||
import org.graalvm.options.OptionDescriptors;
|
||||
import org.graalvm.options.OptionKey;
|
||||
|
||||
import org.graalvm.options.*;
|
||||
import com.oracle.truffle.api.Option;
|
||||
|
||||
/** Class representing runtime options supported by the Enso engine. */
|
||||
public class RuntimeOptions {
|
||||
@ -91,6 +90,16 @@ public class RuntimeOptions {
|
||||
OptionDescriptor.newBuilder(USE_GLOBAL_IR_CACHE_LOCATION_KEY, USE_GLOBAL_IR_CACHE_LOCATION)
|
||||
.build();
|
||||
|
||||
public static final String ENABLE_EXECUTION_TIMER = optionName("enableExecutionTimer");
|
||||
|
||||
@Option(
|
||||
help = "Enables timer that counts down the execution time of expressions.",
|
||||
category = OptionCategory.INTERNAL)
|
||||
public static final OptionKey<Boolean> ENABLE_EXECUTION_TIMER_KEY = new OptionKey<>(true);
|
||||
|
||||
private static final OptionDescriptor ENABLE_EXECUTION_TIMER_DESCRIPTOR =
|
||||
OptionDescriptor.newBuilder(ENABLE_EXECUTION_TIMER_KEY, ENABLE_EXECUTION_TIMER).build();
|
||||
|
||||
public static final OptionDescriptors OPTION_DESCRIPTORS =
|
||||
OptionDescriptors.create(
|
||||
Arrays.asList(
|
||||
@ -107,7 +116,8 @@ public class RuntimeOptions {
|
||||
INTERPRETER_SEQUENTIAL_COMMAND_EXECUTION_DESCRIPTOR,
|
||||
DISABLE_IR_CACHES_DESCRIPTOR,
|
||||
WAIT_FOR_PENDING_SERIALIZATION_JOBS_DESCRIPTOR,
|
||||
USE_GLOBAL_IR_CACHE_LOCATION_DESCRIPTOR));
|
||||
USE_GLOBAL_IR_CACHE_LOCATION_DESCRIPTOR,
|
||||
ENABLE_EXECUTION_TIMER_DESCRIPTOR));
|
||||
|
||||
/**
|
||||
* Canonicalizes the option name by prefixing it with the language name.
|
||||
|
@ -37,7 +37,7 @@ import org.enso.interpreter.runtime.tag.AvoidIdInstrumentationTag;
|
||||
id = IdExecutionService.INSTRUMENT_ID,
|
||||
services = IdExecutionService.class)
|
||||
public class IdExecutionInstrument extends TruffleInstrument implements IdExecutionService {
|
||||
private Timer timer;
|
||||
|
||||
private Env env;
|
||||
|
||||
/**
|
||||
@ -48,20 +48,9 @@ public class IdExecutionInstrument extends TruffleInstrument implements IdExecut
|
||||
@Override
|
||||
protected void onCreate(Env env) {
|
||||
env.registerService(this);
|
||||
this.timer = new Timer.Nanosecond();
|
||||
this.env = env;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override the default nanosecond timer with the specified {@code timer}.
|
||||
*
|
||||
* @param timer the timer to override with
|
||||
*/
|
||||
@Override
|
||||
public void overrideTimer(Timer timer) {
|
||||
this.timer = timer;
|
||||
}
|
||||
|
||||
/** The listener class used by this instrument. */
|
||||
private static class IdExecutionEventListener implements ExecutionEventListener {
|
||||
private final CallTarget entryCallTarget;
|
||||
@ -305,6 +294,7 @@ public class IdExecutionInstrument extends TruffleInstrument implements IdExecut
|
||||
* @param cache the precomputed expression values.
|
||||
* @param methodCallsCache the storage tracking the executed method calls.
|
||||
* @param syncState the synchronization state of runtime updates.
|
||||
* @param timer the execution timer.
|
||||
* @param nextExecutionItem the next item scheduled for execution.
|
||||
* @param functionCallCallback the consumer of function call events.
|
||||
* @param onComputedCallback the consumer of the computed value events.
|
||||
@ -319,6 +309,7 @@ public class IdExecutionInstrument extends TruffleInstrument implements IdExecut
|
||||
RuntimeCache cache,
|
||||
MethodCallsCache methodCallsCache,
|
||||
UpdatesSynchronizationState syncState,
|
||||
Timer timer,
|
||||
UUID nextExecutionItem,
|
||||
Consumer<IdExecutionInstrument.ExpressionCall> functionCallCallback,
|
||||
Consumer<IdExecutionInstrument.ExpressionValue> onComputedCallback,
|
||||
|
@ -2,9 +2,7 @@ package org.enso.interpreter.test.instrument
|
||||
|
||||
import org.enso.distribution.FileSystem
|
||||
import org.enso.distribution.locking.ThreadSafeFileLockManager
|
||||
import org.enso.interpreter.instrument.execution.Timer
|
||||
import org.enso.interpreter.runtime.`type`.ConstantsGen
|
||||
import org.enso.interpreter.runtime.EnsoContext
|
||||
import org.enso.interpreter.test.Metadata
|
||||
import org.enso.pkg.{Package, PackageManager}
|
||||
import org.enso.polyglot._
|
||||
@ -24,12 +22,6 @@ class BuiltinTypesTest
|
||||
with Matchers
|
||||
with BeforeAndAfterEach {
|
||||
|
||||
// === Test Timer ===========================================================
|
||||
|
||||
class TestTimer extends Timer {
|
||||
override def getTime(): Long = 0
|
||||
}
|
||||
|
||||
// === Test Utilities =======================================================
|
||||
|
||||
var context: TestContext = _
|
||||
@ -56,6 +48,7 @@ class BuiltinTypesTest
|
||||
.option(RuntimeOptions.INTERPRETER_SEQUENTIAL_COMMAND_EXECUTION, "true")
|
||||
.option(RuntimeOptions.ENABLE_PROJECT_SUGGESTIONS, "false")
|
||||
.option(RuntimeOptions.ENABLE_GLOBAL_SUGGESTIONS, "false")
|
||||
.option(RuntimeOptions.ENABLE_EXECUTION_TIMER, "false")
|
||||
.option(
|
||||
RuntimeOptions.DISABLE_IR_CACHES,
|
||||
InstrumentTestContext.DISABLE_IR_CACHE
|
||||
@ -77,14 +70,6 @@ class BuiltinTypesTest
|
||||
)
|
||||
executionContext.context.initialize(LanguageInfo.ID)
|
||||
|
||||
val languageContext = executionContext.context
|
||||
.getBindings(LanguageInfo.ID)
|
||||
.invokeMember(MethodNames.TopScope.LEAK_CONTEXT)
|
||||
.asHostObject[EnsoContext]
|
||||
languageContext.getLanguage.getIdExecutionService.ifPresent(
|
||||
_.overrideTimer(new TestTimer)
|
||||
);
|
||||
|
||||
def writeMain(contents: String): File =
|
||||
Files.write(pkg.mainFile.toPath, contents.getBytes).toFile
|
||||
|
||||
|
@ -2,7 +2,6 @@ package org.enso.interpreter.test.instrument
|
||||
|
||||
import org.enso.distribution.FileSystem
|
||||
import org.enso.distribution.locking.ThreadSafeFileLockManager
|
||||
import org.enso.interpreter.instrument.execution.Timer
|
||||
import org.enso.interpreter.test.Metadata
|
||||
import org.enso.pkg.{Package, PackageManager}
|
||||
import org.enso.polyglot._
|
||||
@ -23,12 +22,6 @@ class RuntimeAsyncCommandsTest
|
||||
with Matchers
|
||||
with BeforeAndAfterEach {
|
||||
|
||||
// === Test Timer ===========================================================
|
||||
|
||||
class TestTimer extends Timer {
|
||||
override def getTime(): Long = 0
|
||||
}
|
||||
|
||||
// === Test Utilities =======================================================
|
||||
|
||||
var context: TestContext = _
|
||||
@ -56,6 +49,7 @@ class RuntimeAsyncCommandsTest
|
||||
)
|
||||
.option(RuntimeOptions.ENABLE_PROJECT_SUGGESTIONS, "false")
|
||||
.option(RuntimeOptions.ENABLE_GLOBAL_SUGGESTIONS, "false")
|
||||
.option(RuntimeOptions.ENABLE_EXECUTION_TIMER, "false")
|
||||
.option(
|
||||
RuntimeOptions.DISABLE_IR_CACHES,
|
||||
InstrumentTestContext.DISABLE_IR_CACHE
|
||||
@ -76,14 +70,6 @@ class RuntimeAsyncCommandsTest
|
||||
)
|
||||
executionContext.context.initialize(LanguageInfo.ID)
|
||||
|
||||
val languageContext = executionContext.context
|
||||
.getBindings(LanguageInfo.ID)
|
||||
.invokeMember(MethodNames.TopScope.LEAK_CONTEXT)
|
||||
.asHostObject[org.enso.interpreter.runtime.EnsoContext]
|
||||
languageContext.getLanguage.getIdExecutionService.ifPresent(
|
||||
_.overrideTimer(new TestTimer)
|
||||
)
|
||||
|
||||
def writeMain(contents: String): File =
|
||||
Files.write(pkg.mainFile.toPath, contents.getBytes).toFile
|
||||
|
||||
|
@ -2,7 +2,6 @@ package org.enso.interpreter.test.instrument
|
||||
|
||||
import org.enso.distribution.FileSystem
|
||||
import org.enso.distribution.locking.ThreadSafeFileLockManager
|
||||
import org.enso.interpreter.instrument.execution.Timer
|
||||
import org.enso.interpreter.runtime.`type`.ConstantsGen
|
||||
import org.enso.interpreter.test.Metadata
|
||||
import org.enso.pkg.{Package, PackageManager}
|
||||
@ -26,12 +25,6 @@ class RuntimeErrorsTest
|
||||
with Matchers
|
||||
with BeforeAndAfterEach {
|
||||
|
||||
// === Test Timer ===========================================================
|
||||
|
||||
class TestTimer extends Timer {
|
||||
override def getTime(): Long = 0
|
||||
}
|
||||
|
||||
// === Test Utilities =======================================================
|
||||
|
||||
var context: TestContext = _
|
||||
@ -61,6 +54,7 @@ class RuntimeErrorsTest
|
||||
.option(RuntimeOptions.INTERPRETER_SEQUENTIAL_COMMAND_EXECUTION, "true")
|
||||
.option(RuntimeOptions.ENABLE_PROJECT_SUGGESTIONS, "false")
|
||||
.option(RuntimeOptions.ENABLE_GLOBAL_SUGGESTIONS, "false")
|
||||
.option(RuntimeOptions.ENABLE_EXECUTION_TIMER, "false")
|
||||
.option(
|
||||
RuntimeOptions.DISABLE_IR_CACHES,
|
||||
InstrumentTestContext.DISABLE_IR_CACHE
|
||||
@ -81,14 +75,6 @@ class RuntimeErrorsTest
|
||||
)
|
||||
executionContext.context.initialize(LanguageInfo.ID)
|
||||
|
||||
val languageContext = executionContext.context
|
||||
.getBindings(LanguageInfo.ID)
|
||||
.invokeMember(MethodNames.TopScope.LEAK_CONTEXT)
|
||||
.asHostObject[org.enso.interpreter.runtime.EnsoContext]
|
||||
languageContext.getLanguage.getIdExecutionService.ifPresent(
|
||||
_.overrideTimer(new TestTimer)
|
||||
)
|
||||
|
||||
def writeMain(contents: String): File =
|
||||
Files.write(pkg.mainFile.toPath, contents.getBytes).toFile
|
||||
|
||||
|
@ -2,7 +2,6 @@ package org.enso.interpreter.test.instrument
|
||||
|
||||
import org.enso.distribution.FileSystem
|
||||
import org.enso.distribution.locking.ThreadSafeFileLockManager
|
||||
import org.enso.interpreter.instrument.execution.Timer
|
||||
import org.enso.interpreter.runtime.`type`.{Constants, ConstantsGen}
|
||||
import org.enso.interpreter.test.Metadata
|
||||
import org.enso.pkg.{Package, PackageManager}
|
||||
@ -24,12 +23,6 @@ class RuntimeInstrumentTest
|
||||
with Matchers
|
||||
with BeforeAndAfterEach {
|
||||
|
||||
// === Test Timer ===========================================================
|
||||
|
||||
class TestTimer extends Timer {
|
||||
override def getTime(): Long = 0
|
||||
}
|
||||
|
||||
// === Test Utilities =======================================================
|
||||
|
||||
var context: TestContext = _
|
||||
@ -54,6 +47,7 @@ class RuntimeInstrumentTest
|
||||
.option(RuntimeOptions.INTERPRETER_SEQUENTIAL_COMMAND_EXECUTION, "true")
|
||||
.option(RuntimeOptions.ENABLE_PROJECT_SUGGESTIONS, "false")
|
||||
.option(RuntimeOptions.ENABLE_GLOBAL_SUGGESTIONS, "false")
|
||||
.option(RuntimeOptions.ENABLE_EXECUTION_TIMER, "false")
|
||||
.option(
|
||||
RuntimeOptions.DISABLE_IR_CACHES,
|
||||
InstrumentTestContext.DISABLE_IR_CACHE
|
||||
@ -74,14 +68,6 @@ class RuntimeInstrumentTest
|
||||
)
|
||||
executionContext.context.initialize(LanguageInfo.ID)
|
||||
|
||||
val languageContext = executionContext.context
|
||||
.getBindings(LanguageInfo.ID)
|
||||
.invokeMember(MethodNames.TopScope.LEAK_CONTEXT)
|
||||
.asHostObject[org.enso.interpreter.runtime.EnsoContext]
|
||||
languageContext.getLanguage.getIdExecutionService.ifPresent(
|
||||
_.overrideTimer(new TestTimer)
|
||||
);
|
||||
|
||||
def writeMain(contents: String): File =
|
||||
Files.write(pkg.mainFile.toPath, contents.getBytes).toFile
|
||||
|
||||
|
@ -2,7 +2,6 @@ package org.enso.interpreter.test.instrument
|
||||
|
||||
import org.enso.distribution.FileSystem
|
||||
import org.enso.distribution.locking.ThreadSafeFileLockManager
|
||||
import org.enso.interpreter.instrument.execution.Timer
|
||||
import org.enso.interpreter.runtime.`type`.{ConstantsGen, Types}
|
||||
import org.enso.interpreter.runtime.EnsoContext
|
||||
import org.enso.interpreter.test.Metadata
|
||||
@ -27,12 +26,6 @@ class RuntimeServerTest
|
||||
with Matchers
|
||||
with BeforeAndAfterEach {
|
||||
|
||||
// === Test Timer ===========================================================
|
||||
|
||||
class TestTimer extends Timer {
|
||||
override def getTime(): Long = 0
|
||||
}
|
||||
|
||||
// === Test Utilities =======================================================
|
||||
|
||||
var context: TestContext = _
|
||||
@ -59,6 +52,7 @@ class RuntimeServerTest
|
||||
.option(RuntimeOptions.INTERPRETER_SEQUENTIAL_COMMAND_EXECUTION, "true")
|
||||
.option(RuntimeOptions.ENABLE_PROJECT_SUGGESTIONS, "false")
|
||||
.option(RuntimeOptions.ENABLE_GLOBAL_SUGGESTIONS, "false")
|
||||
.option(RuntimeOptions.ENABLE_EXECUTION_TIMER, "false")
|
||||
.option(
|
||||
RuntimeOptions.DISABLE_IR_CACHES,
|
||||
InstrumentTestContext.DISABLE_IR_CACHE
|
||||
@ -84,11 +78,6 @@ class RuntimeServerTest
|
||||
.getBindings(LanguageInfo.ID)
|
||||
.invokeMember(MethodNames.TopScope.LEAK_CONTEXT)
|
||||
.asHostObject[EnsoContext]
|
||||
val info =
|
||||
languageContext.getEnvironment.getPublicLanguages.get(LanguageInfo.ID)
|
||||
languageContext.getLanguage.getIdExecutionService.ifPresent(
|
||||
_.overrideTimer(new TestTimer)
|
||||
)
|
||||
|
||||
def writeMain(contents: String): File =
|
||||
Files.write(pkg.mainFile.toPath, contents.getBytes).toFile
|
||||
|
@ -1,10 +1,8 @@
|
||||
package org.enso.interpreter.test.instrument
|
||||
|
||||
import org.enso.distribution.FileSystem
|
||||
import org.apache.commons.io.FileUtils
|
||||
import org.enso.distribution.locking.ThreadSafeFileLockManager
|
||||
import org.enso.interpreter.instrument.execution.Timer
|
||||
import org.enso.interpreter.runtime.`type`.ConstantsGen
|
||||
import org.enso.interpreter.runtime.EnsoContext
|
||||
import org.enso.interpreter.test.Metadata
|
||||
import org.enso.pkg.{Package, PackageManager, QualifiedName}
|
||||
import org.enso.polyglot._
|
||||
@ -27,12 +25,6 @@ class RuntimeVisualizationsTest
|
||||
with Matchers
|
||||
with BeforeAndAfterEach {
|
||||
|
||||
// === Test Timer ===========================================================
|
||||
|
||||
class TestTimer extends Timer {
|
||||
override def getTime(): Long = 0
|
||||
}
|
||||
|
||||
// === Test Utilities =======================================================
|
||||
|
||||
var context: TestContext = _
|
||||
@ -40,7 +32,7 @@ class RuntimeVisualizationsTest
|
||||
class TestContext(packageName: String) extends InstrumentTestContext {
|
||||
|
||||
val tmpDir: Path = Files.createTempDirectory("enso-test-packages")
|
||||
sys.addShutdownHook(FileSystem.removeDirectoryIfExists(tmpDir))
|
||||
sys.addShutdownHook(FileUtils.deleteQuietly(tmpDir.toFile))
|
||||
val lockManager = new ThreadSafeFileLockManager(tmpDir.resolve("locks"))
|
||||
val runtimeServerEmulator =
|
||||
new RuntimeServerEmulator(messageQueue, lockManager)
|
||||
@ -59,6 +51,7 @@ class RuntimeVisualizationsTest
|
||||
.option(RuntimeOptions.INTERPRETER_SEQUENTIAL_COMMAND_EXECUTION, "true")
|
||||
.option(RuntimeOptions.ENABLE_PROJECT_SUGGESTIONS, "false")
|
||||
.option(RuntimeOptions.ENABLE_GLOBAL_SUGGESTIONS, "false")
|
||||
.option(RuntimeOptions.ENABLE_EXECUTION_TIMER, "false")
|
||||
.option(RuntimeServerInfo.ENABLE_OPTION, "true")
|
||||
.option(RuntimeOptions.INTERACTIVE_MODE, "true")
|
||||
.option(
|
||||
@ -76,14 +69,6 @@ class RuntimeVisualizationsTest
|
||||
)
|
||||
executionContext.context.initialize(LanguageInfo.ID)
|
||||
|
||||
val languageContext = executionContext.context
|
||||
.getBindings(LanguageInfo.ID)
|
||||
.invokeMember(MethodNames.TopScope.LEAK_CONTEXT)
|
||||
.asHostObject[EnsoContext]
|
||||
languageContext.getLanguage.getIdExecutionService.ifPresent(
|
||||
_.overrideTimer(new TestTimer)
|
||||
)
|
||||
|
||||
def writeMain(contents: String): File =
|
||||
Files.write(pkg.mainFile.toPath, contents.getBytes).toFile
|
||||
|
||||
@ -2160,10 +2145,6 @@ class RuntimeVisualizationsTest
|
||||
}
|
||||
|
||||
it should "run internal IDE visualisation preprocessor catching error" in {
|
||||
pending
|
||||
// TODO [JD]: Disabled due to issue with context not allowing JS functions.
|
||||
// https://www.pivotaltracker.com/story/show/184064564
|
||||
|
||||
val contextId = UUID.randomUUID()
|
||||
val requestId = UUID.randomUUID()
|
||||
val visualisationId = UUID.randomUUID()
|
||||
@ -2208,8 +2189,8 @@ class RuntimeVisualizationsTest
|
||||
context.send(
|
||||
Api.Request(requestId, Api.PushContextRequest(contextId, item1))
|
||||
)
|
||||
val pushContextResponses = context.receiveNIgnorePendingExpressionUpdates(3)
|
||||
pushContextResponses should contain allOf (
|
||||
val pushContextResponses = context.receiveNIgnoreStdLib(3)
|
||||
pushContextResponses should contain theSameElementsAs Seq(
|
||||
Api.Response(requestId, Api.PushContextResponse(contextId)),
|
||||
TestMessages.error(
|
||||
contextId,
|
||||
@ -2261,7 +2242,7 @@ class RuntimeVisualizationsTest
|
||||
data
|
||||
}
|
||||
val stringified = new String(data)
|
||||
stringified shouldEqual """{ "kind": "Dataflow", "message": "The List is empty. (at <enso> Main.main(Enso_Test.Test.Main:6:5-32)"}"""
|
||||
stringified shouldEqual """{"kind":"Dataflow","message":"The List is empty. (at <enso> Main.main(Enso_Test.Test.Main:6:5-32)"}"""
|
||||
}
|
||||
|
||||
it should "attach method pointer visualisation without arguments" in {
|
@ -30,6 +30,7 @@ import org.enso.interpreter.epb.EpbLanguage;
|
||||
import org.enso.interpreter.instrument.IdExecutionService;
|
||||
import org.enso.interpreter.instrument.NotificationHandler.Forwarder;
|
||||
import org.enso.interpreter.instrument.NotificationHandler.TextMode$;
|
||||
import org.enso.interpreter.instrument.execution.Timer;
|
||||
import org.enso.interpreter.node.EnsoRootNode;
|
||||
import org.enso.interpreter.node.ExpressionNode;
|
||||
import org.enso.interpreter.node.ProgramRootNode;
|
||||
@ -130,6 +131,10 @@ public final class EnsoLanguage extends TruffleLanguage<EnsoContext> {
|
||||
lockManager = new ThreadSafeFileLockManager(distributionManager.paths().locks());
|
||||
}
|
||||
|
||||
boolean isExecutionTimerEnabled =
|
||||
env.getOptions().get(RuntimeOptions.ENABLE_EXECUTION_TIMER_KEY);
|
||||
Timer timer = isExecutionTimerEnabled ? new Timer.Nanosecond() : new Timer.Disabled();
|
||||
|
||||
EnsoContext context =
|
||||
new EnsoContext(
|
||||
this, getLanguageHome(), env, notificationHandler, lockManager, distributionManager);
|
||||
@ -140,7 +145,7 @@ public final class EnsoLanguage extends TruffleLanguage<EnsoContext> {
|
||||
env.lookup(idValueListenerInstrument, IdExecutionService.class));
|
||||
env.registerService(
|
||||
new ExecutionService(
|
||||
context, idExecutionInstrument, notificationHandler, connectedLockManager));
|
||||
context, idExecutionInstrument, notificationHandler, connectedLockManager, timer));
|
||||
|
||||
return context;
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ public interface IdExecutionService {
|
||||
* @param cache the precomputed expression values.
|
||||
* @param methodCallsCache the storage tracking the executed method calls.
|
||||
* @param syncState the synchronization state of runtime updates.
|
||||
* @param timer the execution timer.
|
||||
* @param nextExecutionItem the next item scheduled for execution.
|
||||
* @param functionCallCallback the consumer of function call events.
|
||||
* @param onComputedCallback the consumer of the computed value events.
|
||||
@ -41,19 +42,13 @@ public interface IdExecutionService {
|
||||
RuntimeCache cache,
|
||||
MethodCallsCache methodCallsCache,
|
||||
UpdatesSynchronizationState syncState,
|
||||
Timer timer,
|
||||
UUID nextExecutionItem,
|
||||
Consumer<ExpressionCall> functionCallCallback,
|
||||
Consumer<ExpressionValue> onComputedCallback,
|
||||
Consumer<ExpressionValue> onCachedCallback,
|
||||
Consumer<Exception> onExceptionalCallback);
|
||||
|
||||
/**
|
||||
* Override the default nanosecond timer with the specified {@code timer}.
|
||||
*
|
||||
* @param timer the timer to override with
|
||||
*/
|
||||
void overrideTimer(Timer timer);
|
||||
|
||||
/** A class for notifications about functions being called in the course of execution. */
|
||||
public static class ExpressionCall {
|
||||
private final UUID expressionId;
|
||||
|
@ -18,6 +18,7 @@ import org.enso.interpreter.instrument.MethodCallsCache;
|
||||
import org.enso.interpreter.instrument.NotificationHandler;
|
||||
import org.enso.interpreter.instrument.RuntimeCache;
|
||||
import org.enso.interpreter.instrument.UpdatesSynchronizationState;
|
||||
import org.enso.interpreter.instrument.execution.Timer;
|
||||
import org.enso.interpreter.node.callable.FunctionCallInstrumentationNode;
|
||||
import org.enso.interpreter.node.expression.builtin.text.util.TypeToDisplayTextNodeGen;
|
||||
import org.enso.interpreter.runtime.EnsoContext;
|
||||
@ -58,25 +59,30 @@ public class ExecutionService {
|
||||
private final TruffleLogger logger = TruffleLogger.getLogger(LanguageInfo.ID);
|
||||
private final ConnectedLockManager connectedLockManager;
|
||||
|
||||
private final Timer timer;
|
||||
|
||||
/**
|
||||
* Creates a new instance of this service.
|
||||
*
|
||||
* @param context the language context to use.
|
||||
* @param idExecutionInstrument optional instance of the {@link IdExecutionService} to use in the
|
||||
* course of executions
|
||||
* @param notificationForwarder a forwarder of notifications, used to communicate with the user
|
||||
* course of executions.
|
||||
* @param notificationForwarder a forwarder of notifications, used to communicate with the user.
|
||||
* @param connectedLockManager a connected lock manager (if it is in use) that should be connected
|
||||
* to the language server, or null
|
||||
* to the language server, or null.
|
||||
* @param timer an execution timer.
|
||||
*/
|
||||
public ExecutionService(
|
||||
EnsoContext context,
|
||||
Optional<IdExecutionService> idExecutionInstrument,
|
||||
NotificationHandler.Forwarder notificationForwarder,
|
||||
ConnectedLockManager connectedLockManager) {
|
||||
ConnectedLockManager connectedLockManager,
|
||||
Timer timer) {
|
||||
this.idExecutionInstrument = idExecutionInstrument;
|
||||
this.context = context;
|
||||
this.notificationForwarder = notificationForwarder;
|
||||
this.connectedLockManager = connectedLockManager;
|
||||
this.timer = timer;
|
||||
}
|
||||
|
||||
/** @return the language context. */
|
||||
@ -159,6 +165,7 @@ public class ExecutionService {
|
||||
cache,
|
||||
methodCallsCache,
|
||||
syncState,
|
||||
this.timer,
|
||||
nextExecutionItem,
|
||||
funCallCallback,
|
||||
onComputedCallback,
|
||||
@ -289,6 +296,7 @@ public class ExecutionService {
|
||||
cache,
|
||||
methodCallsCache,
|
||||
syncState,
|
||||
this.timer,
|
||||
nextExecutionItem,
|
||||
funCallCallback,
|
||||
onComputedCallback,
|
||||
|
@ -7,7 +7,12 @@ trait Timer {
|
||||
object Timer {
|
||||
|
||||
/** A nanosecond precision timer. */
|
||||
class Nanosecond extends Timer {
|
||||
final class Nanosecond extends Timer {
|
||||
override def getTime(): Long = System.nanoTime()
|
||||
}
|
||||
|
||||
/** A timer returns the same zero time. */
|
||||
final class Disabled extends Timer {
|
||||
override def getTime(): Long = 0
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user