Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactoring and Analysis Fixes from WIP Automatic Parallelism #1748

Merged
merged 5 commits into from
May 21, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 7 additions & 0 deletions RELEASES.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
[GraalVM 21.1.0](https://github.com/graalvm/graalvm-ce-builds/releases/tag/vm-21.1.0)
([#1738](https://github.com/enso-org/enso/pull/1738)). This brings a raft of
bug-fixes and improvements to how quickly Enso can reach its peak performance.
- Added support for bidirectional dataflow tracking to the `DataflowAnalysis`
pass ([#1748](https://github.com/enso-org/enso/pull/1748)). This will allow
the interpreter to perform more detailed analyses in the future to enable
optimisations and new features.

## Tooling

Expand All @@ -17,6 +21,9 @@
- Implemented log masking ([#1732](https://github.com/enso-org/enso/pull/1732)).
This feature masks personally identifiable information in the logs, such as
code literals, computed values, and user environment variables.
- Added support for evaluating one-shot expressions on the result values of
arbitrary expressions ([#1749](https://github.com/enso-org/enso/pull/1749)).
This is very useful for enabling more advanced introspection in the IDE.

## Libraries

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
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 java.util.Arrays;
import java.util.logging.Level;

/** Class representing runtime options supported by the Enso engine. */
public class RuntimeOptions {
public static final String PACKAGES_PATH = optionName("packagesPath");
Expand Down Expand Up @@ -56,9 +55,9 @@ public class RuntimeOptions {
STRICT_ERRORS_DESCRIPTOR,
LOG_LEVEL_DESCRIPTOR,
DISABLE_INLINE_CACHES_DESCRIPTOR,
INTERPRETER_SEQUENTIAL_COMMAND_EXECUTION_DESCRIPTOR,
ENABLE_PROJECT_SUGGESTIONS_DESCRIPTOR,
ENABLE_GLOBAL_SUGGESTIONS_DESCRIPTOR));
ENABLE_GLOBAL_SUGGESTIONS_DESCRIPTOR,
INTERPRETER_SEQUENTIAL_COMMAND_EXECUTION_DESCRIPTOR));

/**
* Canonicalizes the option name by prefixing it with the language name.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,13 @@ public static EvalNode buildWithResultScopeCapture() {
public abstract Stateful execute(CallerInfo callerInfo, Object state, Text expression);

RootCallTarget parseExpression(LocalScope scope, ModuleScope moduleScope, String expression) {
Context context = lookupContextReference(Language.class).get();
LocalScope localScope = scope.createChild();
InlineContext inlineContext = InlineContext.fromJava(localScope, moduleScope, getTailStatus());
InlineContext inlineContext =
InlineContext.fromJava(
localScope, moduleScope, getTailStatus(), context.getCompilerConfig());
ExpressionNode expr =
lookupContextReference(Language.class)
.get()
.getCompiler()
.runInline(expression, inlineContext)
.getOrElse(null);
context.getCompiler().runInline(expression, inlineContext).getOrElse(null);
if (expr == null) {
throw new RuntimeException("Invalid code passed to `eval`: " + expression);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import java.util.function.Function;
import java.util.stream.Collectors;
import org.enso.compiler.Compiler;
import org.enso.compiler.data.CompilerConfig;
import org.enso.home.HomeManager;
import org.enso.interpreter.Language;
import org.enso.interpreter.OptionsHelper;
Expand Down Expand Up @@ -53,6 +54,7 @@ public class Context {
private final Builtins builtins;
private final String home;
private final List<ShadowedPackage> shadowedPackages;
private final CompilerConfig compilerConfig;

/**
* Creates a new Enso context.
Expand All @@ -70,12 +72,13 @@ public Context(Language language, String home, Env environment) {
this.threadManager = new ThreadManager();
this.resourceManager = new ResourceManager(this);
this.isCachingDisabled = environment.getOptions().get(RuntimeOptions.DISABLE_INLINE_CACHES_KEY);
this.compilerConfig = new CompilerConfig(false, true);
this.home = home;
this.shadowedPackages = new ArrayList<>();

builtins = new Builtins(this);

this.compiler = new Compiler(this, builtins);
this.compiler = new Compiler(this, builtins, compilerConfig);
}

/** Perform expensive initialization logic for the context. */
Expand Down Expand Up @@ -384,4 +387,9 @@ public boolean isCachingDisabled() {
public List<ShadowedPackage> getShadowedPackages() {
return shadowedPackages;
}

/** @return the compiler configuration for this language */
public CompilerConfig getCompilerConfig() {
return compilerConfig;
}
}
25 changes: 18 additions & 7 deletions engine/runtime/src/main/scala/org/enso/compiler/Compiler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import org.enso.compiler.codegen.{AstToIr, IrToTruffle, RuntimeStubsGenerator}
import org.enso.compiler.context.{FreshNameSupply, InlineContext, ModuleContext}
import org.enso.compiler.core.IR
import org.enso.compiler.core.IR.Expression
import org.enso.compiler.data.CompilerConfig
import org.enso.compiler.exception.{CompilationAbortedException, CompilerError}
import org.enso.compiler.pass.PassManager
import org.enso.compiler.pass.analyse._
Expand All @@ -31,9 +32,13 @@ import scala.jdk.OptionConverters._
*
* @param context the language context
*/
class Compiler(val context: Context, private val builtins: Builtins) {
class Compiler(
val context: Context,
val builtins: Builtins,
config: CompilerConfig
) {
private val freshNameSupply: FreshNameSupply = new FreshNameSupply
private val passes: Passes = new Passes
private val passes: Passes = new Passes(config)
private val passManager: PassManager = passes.passManager
private val importResolver: ImportResolver = new ImportResolver(this)
private val stubsGenerator: RuntimeStubsGenerator =
Expand Down Expand Up @@ -80,7 +85,8 @@ class Compiler(val context: Context, private val builtins: Builtins) {

val moduleContext = ModuleContext(
module = module,
freshNameSupply = Some(freshNameSupply)
freshNameSupply = Some(freshNameSupply),
compilerConfig = config
)
val compilerOutput = runCompilerPhases(module.getIr, moduleContext)
module.unsafeSetIr(compilerOutput)
Expand Down Expand Up @@ -121,7 +127,8 @@ class Compiler(val context: Context, private val builtins: Builtins) {
module.getScope.reset()
val moduleContext = ModuleContext(
module = module,
freshNameSupply = Some(freshNameSupply)
freshNameSupply = Some(freshNameSupply),
compilerConfig = config
)
val parsedAST = parse(module.getSource)
val expr = generateIR(parsedAST)
Expand Down Expand Up @@ -331,7 +338,10 @@ class Compiler(val context: Context, private val builtins: Builtins) {
if (context.isStrictErrors) {
val diagnostics = modules.map { module =>
val errors = GatherDiagnostics
.runModule(module.getIr, new ModuleContext(module))
.runModule(
module.getIr,
ModuleContext(module, compilerConfig = config)
)
.unsafeGetMetadata(
GatherDiagnostics,
"No diagnostics metadata right after the gathering pass."
Expand Down Expand Up @@ -467,7 +477,7 @@ class Compiler(val context: Context, private val builtins: Builtins) {
source: Source,
scope: ModuleScope
): Unit = {
new IrToTruffle(context, source, scope).run(ir)
new IrToTruffle(context, source, scope, config).run(ir)
}

/** Generates code for the truffle interpreter in an inline context.
Expand All @@ -486,7 +496,8 @@ class Compiler(val context: Context, private val builtins: Builtins) {
new IrToTruffle(
context,
source,
inlineContext.module.getScope
inlineContext.module.getScope,
config
).runInline(
ir,
inlineContext.localScope.getOrElse(LocalScope.root),
Expand Down
22 changes: 19 additions & 3 deletions engine/runtime/src/main/scala/org/enso/compiler/Passes.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.enso.compiler

import org.enso.compiler.data.CompilerConfig
import org.enso.compiler.pass.PassConfiguration._
import org.enso.compiler.pass.analyse._
import org.enso.compiler.pass.desugar._
Expand All @@ -17,7 +18,10 @@ import org.enso.compiler.pass.{
PassManager
}

class Passes(passes: Option[List[PassGroup]] = None) {
class Passes(
config: CompilerConfig,
passes: Option[List[PassGroup]] = None
) {

val moduleDiscoveryPasses = new PassGroup(
List(
Expand Down Expand Up @@ -60,7 +64,16 @@ class Passes(passes: Option[List[PassGroup]] = None) {
Patterns,
AliasAnalysis,
UndefinedVariables,
DataflowAnalysis,
DataflowAnalysis
) ++
(if (config.autoParallelismEnabled) {
List(
AutomaticParallelism,
AliasAnalysis,
DataflowAnalysis
)
} else List()) ++
List(
CachePreferenceAnalysis,
UnusedBindings
)
Expand All @@ -79,7 +92,10 @@ class Passes(passes: Option[List[PassGroup]] = None) {
/** Configuration for the passes. */
private val passConfig: PassConfiguration = PassConfiguration(
ApplicationSaturation -->> ApplicationSaturation.Configuration(),
AliasAnalysis -->> AliasAnalysis.Configuration()
AliasAnalysis -->> AliasAnalysis.Configuration(),
AutomaticParallelism -->> AutomaticParallelism.Configuration(
config.autoParallelismEnabled
)
)

/** The pass manager for running compiler passes. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import com.oracle.truffle.api.source.{Source, SourceSection}
import org.enso.compiler.core.IR
import org.enso.compiler.core.IR.Module.Scope.Import
import org.enso.compiler.core.IR.{Error, IdentifiedLocation, Pattern}
import org.enso.compiler.data.BindingsMap
import org.enso.compiler.data.{BindingsMap, CompilerConfig}
import org.enso.compiler.exception.{BadPatternMatch, CompilerError}
import org.enso.compiler.pass.analyse.AliasAnalysis.Graph.{Scope => AliasScope}
import org.enso.compiler.pass.analyse.AliasAnalysis.{Graph => AliasGraph}
Expand Down Expand Up @@ -85,11 +85,13 @@ import scala.collection.mutable.ArrayBuffer
* @param source the source code that corresponds to the text for which code
* is being generated
* @param moduleScope the scope of the module for which code is being generated
* @param compilerConfig the configuration for the compiler
*/
class IrToTruffle(
val context: Context,
val source: Source,
val moduleScope: ModuleScope
val moduleScope: ModuleScope,
val compilerConfig: CompilerConfig
) {

val language: Language = context.getLanguage
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ final class ChangesetBuilder[A: TextEditor: IndexedSource](
if (queue.isEmpty) visited.flatMap(_.externalId).toSet
else {
val elem = queue.dequeue()
val transitive = metadata.get(elem).getOrElse(Set())
val transitive = metadata.dependents.get(elem).getOrElse(Set())
val dynamic = transitive
.flatMap {
case DataflowAnalysis.DependencyInfo.Type.Static(int, _) =>
Expand All @@ -80,7 +80,7 @@ final class ChangesetBuilder[A: TextEditor: IndexedSource](
case _ =>
None
}
.flatMap(metadata.get)
.flatMap(metadata.dependents.get)
.flatten
val combined = transitive.union(dynamic)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package org.enso.compiler.context

import org.enso.compiler.data.CompilerConfig
import org.enso.compiler.pass.PassConfiguration
import org.enso.interpreter.node.BaseNode.TailStatus
import org.enso.interpreter.runtime.scope.{LocalScope, ModuleScope}
import org.enso.interpreter.runtime.Module
import org.enso.interpreter.runtime.scope.{LocalScope, ModuleScope}

/** A type containing the information about the execution context for an inline
* expression.
Expand All @@ -14,14 +15,15 @@ import org.enso.interpreter.runtime.Module
* position ([[None]] indicates no information)
* @param freshNameSupply the compiler's supply of fresh names
* @param passConfiguration the pass configuration
* @param compilerConfig the compiler configuration
*/
case class InlineContext(
module: Module,
localScope: Option[LocalScope] = None,
isInTailPosition: Option[Boolean] = None,
freshNameSupply: Option[FreshNameSupply] = None,
passConfiguration: Option[PassConfiguration] = None,
noWarnings: Boolean = false
compilerConfig: CompilerConfig
)
object InlineContext {

Expand All @@ -37,12 +39,31 @@ object InlineContext {
def fromJava(
localScope: LocalScope,
moduleScope: ModuleScope,
isInTailPosition: TailStatus
isInTailPosition: TailStatus,
compilerConfig: CompilerConfig
): InlineContext = {
InlineContext(
localScope = Option(localScope),
module = moduleScope.getModule,
isInTailPosition = Option(isInTailPosition != TailStatus.NOT_TAIL)
isInTailPosition = Option(isInTailPosition != TailStatus.NOT_TAIL),
compilerConfig = compilerConfig
)
}

/** Transform a module context into an inline context, retaining the useful
* information.
*
* @param moduleContext the module context
* @return an inline context wrapping the same data as `moduleContext`
*/
def fromModuleContext(moduleContext: ModuleContext): InlineContext = {
InlineContext(
localScope = None,
module = moduleContext.module,
isInTailPosition = None,
freshNameSupply = moduleContext.freshNameSupply,
passConfiguration = moduleContext.passConfiguration,
compilerConfig = moduleContext.compilerConfig
)
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.enso.compiler.context

import org.enso.compiler.data.CompilerConfig
import org.enso.compiler.pass.PassConfiguration
import org.enso.interpreter.runtime.Module

Expand All @@ -8,10 +9,11 @@ import org.enso.interpreter.runtime.Module
* @param module the current module scope
* @param freshNameSupply the compiler's supply of fresh names
* @param passConfiguration the pass configuration
* @param compilerConfig the compiler configuration
*/
case class ModuleContext(
module: Module,
freshNameSupply: Option[FreshNameSupply] = None,
passConfiguration: Option[PassConfiguration] = None,
noWarnings: Boolean = false
compilerConfig: CompilerConfig
)
15 changes: 15 additions & 0 deletions engine/runtime/src/main/scala/org/enso/compiler/core/IR.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5331,6 +5331,21 @@ object IR {
s"The pattern field $shadowedName is shadowed by $shadower."
}
}

/** A warning raised when a call is annotated with `@Auto_Parallel`, but the
* annotation cannot be obeyed.
*
* @param ir the annotated application
* @param reason the reason why the annotation cannot be obeyed
*/
case class FailedParallelism(
ir: IR,
reason: String
) extends Warning {
override val location: Option[IdentifiedLocation] = ir.location
override def message: String =
s"The expression ${ir.showCode()} could not be parallelised: $reason."
}
}

// === Errors ===============================================================
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package org.enso.compiler.data

/** Configuration for the compiler.
*
* @param autoParallelismEnabled whether or not automatic parallelism detection
* is enabled.
* @param warningsEnabled whether or not warnings are enabled
*/
case class CompilerConfig(
autoParallelismEnabled: Boolean = false,
warningsEnabled: Boolean = true
)