Provide names of local variables via FramePointerAnalysis (#10906)

This commit is contained in:
Jaroslav Tulach 2024-09-05 10:02:35 +02:00 committed by GitHub
parent 77183e50e9
commit d37b8f3786
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
34 changed files with 538 additions and 236 deletions

View File

@ -11,8 +11,8 @@ for future goals.
## Visualization
The IR can be visualized using `-Denso.compiler.dumpIr` system property. This
will output a `.dot` file in [GraphViz](www.graphviz.org) format in the
The IR can be visualized using `--vm.D=enso.compiler.dumpIr` system property.
This will output a `.dot` file in [GraphViz](www.graphviz.org) format in the
`ir-dumps` directory for each IR in the program. The _dot_ file format is a
minimal textual format, that can be converted to a graphical representation
using the `dot` command from the GraphViz package. For example, on Ubuntu,

View File

@ -0,0 +1,22 @@
package org.enso.compiler.context;
import java.util.Objects;
import java.util.function.Supplier;
final class ContextUtils {
private ContextUtils() {}
static <V> V assertSame(String msg, V actual, Supplier<V> expectedSupplier) {
assert checkEquality(actual, expectedSupplier)
: msg + "\nexpected: " + expectedSupplier.get() + "\nactual: " + actual;
return actual;
}
private static <V> boolean checkEquality(V actual, Supplier<V> expectedSupplier) {
if (!Objects.equals(expectedSupplier.get(), actual)) {
return false;
} else {
return true;
}
}
}

View File

@ -1,12 +0,0 @@
package org.enso.compiler.context;
/**
* A representation of a pointer into a stack frame at a given number of levels above the current.
*/
public record FramePointer(int parentLevel, int frameSlotIdx) {
public FramePointer {
assert parentLevel >= 0;
assert frameSlotIdx >= 0;
}
}

View File

@ -0,0 +1,6 @@
package org.enso.compiler.pass.analyse;
import org.enso.compiler.core.ir.ProcessingPass;
public sealed interface FrameAnalysisMeta extends ProcessingPass.Metadata
permits FramePointer, FrameVariableNames {}

View File

@ -0,0 +1,38 @@
package org.enso.compiler.pass.analyse;
import org.enso.compiler.core.CompilerStub;
import org.enso.compiler.core.ir.ProcessingPass;
import org.enso.persist.Persistable;
import scala.Option;
/**
* A representation of a pointer into a stack frame at a given number of levels above the current.
*/
@Persistable(clazz = FramePointer.class, id = 1283)
public record FramePointer(int parentLevel, int frameSlotIdx) implements FrameAnalysisMeta {
public FramePointer {
assert parentLevel >= 0;
assert frameSlotIdx >= 0;
}
@Override
public String metadataName() {
return getClass().getSimpleName();
}
@Override
public ProcessingPass.Metadata prepareForSerialization(CompilerStub compiler) {
return this;
}
@Override
public Option<ProcessingPass.Metadata> restoreFromSerialization(CompilerStub compiler) {
return Option.apply(this);
}
@Override
public Option<ProcessingPass.Metadata> duplicate() {
return Option.apply(this);
}
}

View File

@ -0,0 +1,45 @@
package org.enso.compiler.pass.analyse;
import java.util.List;
import org.enso.compiler.core.CompilerStub;
import org.enso.compiler.core.ir.ProcessingPass;
import org.enso.persist.Persistable;
import scala.Option;
import scala.jdk.javaapi.CollectionConverters;
@Persistable(id = 1286)
public final class FrameVariableNames implements FrameAnalysisMeta {
private final List<String> names;
public FrameVariableNames(List<String> variableNames) {
this.names = variableNames;
}
public static FrameVariableNames create(scala.collection.immutable.List<String> names) {
return new FrameVariableNames(CollectionConverters.asJava(names));
}
public List<String> variableNames() {
return names;
}
@Override
public String metadataName() {
return getClass().getSimpleName();
}
@Override
public ProcessingPass.Metadata prepareForSerialization(CompilerStub compiler) {
return this;
}
@Override
public Option<ProcessingPass.Metadata> restoreFromSerialization(CompilerStub compiler) {
return Option.apply(this);
}
@Override
public Option<ProcessingPass.Metadata> duplicate() {
return Option.apply(new FrameVariableNames(names));
}
}

View File

@ -1,7 +1,6 @@
package org.enso.compiler.pass.analyse;
import java.io.IOException;
import org.enso.compiler.context.FramePointer;
import org.enso.compiler.pass.analyse.alias.AliasMetadata;
import org.enso.compiler.pass.analyse.alias.graph.Graph;
import org.enso.compiler.pass.analyse.alias.graph.GraphOccurrence;
@ -67,8 +66,6 @@ import scala.Tuple2$;
@Persistable(clazz = Graph.Link.class, id = 1266, allowInlining = false)
@Persistable(clazz = TypeInference.class, id = 1280)
@Persistable(clazz = FramePointerAnalysis$.class, id = 1281)
@Persistable(clazz = FramePointerAnalysis.FramePointerMeta.class, id = 1282)
@Persistable(clazz = FramePointer.class, id = 1283)
public final class PassPersistance {
private PassPersistance() {}
@ -155,19 +152,16 @@ public final class PassPersistance {
@SuppressWarnings("unchecked")
protected Graph readObject(Input in) throws IOException {
var g = new Graph();
var rootScope = (Graph.Scope) in.readObject();
assignParents(rootScope);
g.rootScope_$eq(rootScope);
var links =
(scala.collection.immutable.Set) in.readInline(scala.collection.immutable.Set.class);
g.initLinks(links);
var nextIdCounter = in.readInt();
g.nextIdCounter_$eq(nextIdCounter);
var g = new Graph(rootScope, nextIdCounter, links);
g.freeze();
return g;
}

View File

@ -1,5 +1,8 @@
package org.enso.compiler.context
import org.enso.compiler.pass.analyse.FrameAnalysisMeta
import org.enso.compiler.pass.analyse.FramePointer
import org.enso.compiler.pass.analyse.FrameVariableNames
import org.enso.compiler.pass.analyse.DataflowAnalysis
import org.enso.compiler.pass.analyse.alias.graph.{
GraphOccurrence,
@ -7,6 +10,7 @@ import org.enso.compiler.pass.analyse.alias.graph.{
}
import scala.jdk.CollectionConverters._
import java.util.function.BiFunction
/** A representation of an Enso local scope.
*
@ -34,12 +38,47 @@ class LocalScope(
final val aliasingGraph: () => AliasGraph,
final private val scopeProvider: () => AliasGraph.Scope,
final private val dataflowInfoProvider: () => DataflowAnalysis.Metadata,
final val flattenToParent: Boolean = false,
private val parentFrameSlotIdxs: Map[AliasGraph.Id, Int] = Map()
final private val symbolsProvider: () => FrameAnalysisMeta = null,
final val flattenToParent: Boolean = false,
private val parentFrameSlotIdxs: () => Map[AliasGraph.Id, Int] = () => Map()
) {
lazy val scope: AliasGraph.Scope = scopeProvider()
lazy val dataflowInfo: DataflowAnalysis.Metadata = dataflowInfoProvider()
/** Computes allSymbols needed by this scope. Either the value is obtained
* from symbolsProvider or (as a fallback) a computation from aliasingGraph
* is performed - the latter situation is logged, when log is not null.
*
* @param where human "friendly" identification of the caller
* @param log function to log or null if no logging is needed
*/
def allSymbols(
where: String,
log: BiFunction[String, Array[Object], Void]
): java.util.List[String] = {
def symbols(): java.util.List[String] = {
val r = scope.allDefinitions.map(_.symbol)
r.asJava
}
val meta = if (symbolsProvider == null) null else symbolsProvider()
if (meta.isInstanceOf[FrameVariableNames]) {
val cached = meta.asInstanceOf[FrameVariableNames].variableNames()
if (log != null) {
ContextUtils.assertSame(where, cached, () => symbols())
}
cached
} else {
val result = symbols()
if (log != null) {
log(
"Scope computed from AliasAnalysis at {0} = {1}",
Array(where, result)
)
}
result
}
}
private lazy val localFrameSlotIdxs: Map[AliasGraph.Id, Int] =
gatherLocalFrameSlotIdxs()
@ -47,7 +86,7 @@ class LocalScope(
* Useful for quick searching for [[FramePointer]] of parent scopes.
*/
private lazy val allFrameSlotIdxs: Map[AliasGraph.Id, Int] =
parentFrameSlotIdxs ++ localFrameSlotIdxs
parentFrameSlotIdxs() ++ localFrameSlotIdxs
/** Creates a new child with a new aliasing scope.
*
@ -64,15 +103,23 @@ class LocalScope(
*/
def createChild(
childScope: () => AliasGraph.Scope,
flattenToParent: Boolean = false
flattenToParent: Boolean = false,
symbolsProvider: () => FrameVariableNames = null
): LocalScope = {
val sp = if (flattenToParent) {
assert(symbolsProvider == null)
this.symbolsProvider
} else {
symbolsProvider
}
new LocalScope(
Some(this),
aliasingGraph,
childScope,
() => dataflowInfo,
sp,
flattenToParent,
allFrameSlotIdxs
() => allFrameSlotIdxs
)
}
@ -125,11 +172,27 @@ class LocalScope(
}
object LocalScope {
/** Constructs a local scope for an [[EnsoRootNode]].
*
* @return a defaulted local scope
/** Empty and immutable singleton scope.
*/
def root: LocalScope = {
val empty: LocalScope = {
val graph = new AliasGraph
graph.freeze()
val info = DataflowAnalysis.DependencyInfo()
val emptyVariableNames = FrameVariableNames.create(List())
new LocalScope(
None,
() => graph,
() => graph.rootScope,
() => info,
() => emptyVariableNames
)
}
/** Constructs a new local scope for an [[EnsoRootNode]] that can then be modified.
*
* @return a new empty scope ready for additional modifications.
*/
def createEmpty: LocalScope = {
val graph = new AliasGraph
val info = DataflowAnalysis.DependencyInfo()
new LocalScope(

View File

@ -1,12 +1,7 @@
package org.enso.compiler.pass.analyse
import org.enso.compiler.context.{
CompilerContext,
FramePointer,
InlineContext,
LocalScope,
ModuleContext
}
import org.enso.compiler.pass.analyse.FramePointer
import org.enso.compiler.context.{InlineContext, LocalScope, ModuleContext}
import org.enso.compiler.core.ir.Name.GenericAnnotation
import org.enso.compiler.core.{CompilerError, IR}
import org.enso.compiler.core.ir.expression.{Application, Case}
@ -17,13 +12,11 @@ import org.enso.compiler.core.ir.{
Function,
Module,
Name,
Pattern,
ProcessingPass
Pattern
}
import org.enso.compiler.core.ir.module.scope.Definition
import org.enso.compiler.core.ir.module.scope.definition.Method
import org.enso.compiler.pass.IRPass
import org.enso.compiler.pass.IRPass.IRMetadata
import org.enso.compiler.pass.analyse.alias.AliasMetadata
import org.enso.compiler.pass.analyse.alias.graph.{Graph, GraphOccurrence}
@ -33,7 +26,7 @@ import org.enso.compiler.pass.analyse.alias.graph.{Graph, GraphOccurrence}
*/
case object FramePointerAnalysis extends IRPass {
override type Metadata = FramePointerMeta
override type Metadata = FrameAnalysisMeta
override type Config = IRPass.Configuration.Default
@ -54,14 +47,18 @@ case object FramePointerAnalysis extends IRPass {
ir match {
case m: Method.Explicit =>
getAliasAnalysisGraph(m) match {
case Some(graph) =>
case Some(
graph
) =>
processExpression(m.body, graph)
updateSymbolNames(m, graph.rootScope)
case _ => ()
}
case m: Method.Conversion =>
getAliasAnalysisGraph(m) match {
case Some(graph) =>
processExpression(m.body, graph)
updateSymbolNames(m, graph.rootScope)
case _ => ()
}
case t: Definition.Type =>
@ -78,7 +75,9 @@ case object FramePointerAnalysis extends IRPass {
member.annotations.foreach { annotation =>
processAnnotation(annotation, memberGraph)
}
updateSymbolNames(member, memberGraph.rootScope)
}
updateSymbolNames(t, graph.rootScope)
case _ => ()
}
case annot: GenericAnnotation =>
@ -94,6 +93,11 @@ case object FramePointerAnalysis extends IRPass {
}
}
private def updateSymbolNames(e: IR, s: Graph.Scope): Unit = {
val symbols = s.allDefinitions.map(_.symbol)
updateMeta(e, FrameVariableNames.create(symbols))
}
private def processAnnotation(
annot: GenericAnnotation,
graph: Graph
@ -103,6 +107,7 @@ case object FramePointerAnalysis extends IRPass {
rootScope.graph
case None => graph
}
updateSymbolNames(annot, annotGraph.rootScope)
processExpression(annot.expression, annotGraph)
}
@ -123,7 +128,8 @@ case object FramePointerAnalysis extends IRPass {
case Some(defaultValue) =>
getAliasAnalysisGraph(defaultValue) match {
case Some(defaultValueGraph) =>
processExpression(defaultValue, defaultValueGraph)
processExpression(defaultValue, defaultValueGraph, false)
maybAttachFrameVariableNames(defaultValue)
case None =>
processExpression(defaultValue, graph)
}
@ -134,7 +140,8 @@ case object FramePointerAnalysis extends IRPass {
private def processExpression(
exprIr: Expression,
graph: Graph
graph: Graph,
updateSymbols: Boolean = true
): Unit = {
exprIr match {
case name: Name => maybeAttachFramePointer(name, graph)
@ -147,7 +154,6 @@ case object FramePointerAnalysis extends IRPass {
processArgumentDefs(args, graph)
processExpression(body, graph)
case binding @ Expression.Binding(name, expr, _, _) =>
maybeAttachFramePointer(binding, graph)
maybeAttachFramePointer(name, graph)
processExpression(expr, graph)
maybeAttachFramePointer(binding, graph)
@ -159,6 +165,9 @@ case object FramePointerAnalysis extends IRPass {
}
case _ => ()
}
if (updateSymbols) {
maybAttachFrameVariableNames(exprIr)
}
}
private def processCaseBranch(
@ -170,6 +179,7 @@ case object FramePointerAnalysis extends IRPass {
"An alias analysis graph is expected on " + branch
)
case Some(graph) =>
maybAttachFrameVariableNames(branch)
processExpression(branch.expression, graph)
processCasePattern(branch.pattern, graph)
}
@ -197,6 +207,7 @@ case object FramePointerAnalysis extends IRPass {
case _: Pattern.Documentation => ()
case _ => ()
}
updateSymbolNames(pattern, graph.rootScope)
}
private def processApplication(
@ -230,10 +241,19 @@ case object FramePointerAnalysis extends IRPass {
arguments.foreach { case arg @ CallArgument.Specified(name, value, _, _) =>
maybeAttachFramePointer(arg, graph)
name.foreach(maybeAttachFramePointer(_, graph))
processExpression(value, graph)
processExpression(value, graph, false)
maybAttachFrameVariableNames(value)
maybAttachFrameVariableNames(arg)
}
}
private def maybAttachFrameVariableNames(ir: IR): Unit = {
getAliasRootScope(ir).foreach(root =>
updateSymbolNames(ir, root.graph.rootScope)
)
getAliasChildScope(ir).foreach(child => updateSymbolNames(ir, child.scope))
}
/** Attaches [[FramePointerMeta]] metadata to the given `ir` if there is an
* appropriate [[AliasMetadata.Occurrence]] already attached to it.
* @param ir IR to attach the frame pointer metadata to.
@ -263,7 +283,10 @@ case object FramePointerAnalysis extends IRPass {
val parentLevel = getScopeDistance(defScope, scope)
val frameSlotIdx =
getFrameSlotIdxInScope(graph, defScope, defOcc)
updateMeta(ir, new FramePointer(parentLevel, frameSlotIdx))
updateMeta(
ir,
new FramePointer(parentLevel, frameSlotIdx)
)
case None =>
// It is possible that there is no Def for this Use. It can, for example, be
// Use for some global symbol. In `IrToTruffle`, an UnresolvedSymbol will be
@ -275,7 +298,10 @@ case object FramePointerAnalysis extends IRPass {
// The definition cannot write to parent's frame slots.
val parentLevel = 0
val frameSlotIdx = getFrameSlotIdxInScope(graph, scope, defn)
updateMeta(ir, new FramePointer(parentLevel, frameSlotIdx))
updateMeta(
ir,
new FramePointer(parentLevel, frameSlotIdx)
)
case _ => ()
}
case _ => ()
@ -286,9 +312,19 @@ case object FramePointerAnalysis extends IRPass {
private def updateMeta(
ir: IR,
framePointer: FramePointer
newMeta: FrameAnalysisMeta
): Unit = {
ir.passData().update(this, new FramePointerMeta(framePointer))
ir.passData().get(this) match {
case None =>
ir.passData()
.update(this, newMeta)
case Some(meta) =>
val ex = new IllegalStateException(
"Unexpected FrameAnalysisMeta associated with IR " + ir + "\nOld: " + meta + " new " + newMeta
)
ex.setStackTrace(ex.getStackTrace().slice(0, 10))
throw ex
}
}
/** Returns the index of the given `defOcc` definition in the given `scope`
@ -357,6 +393,15 @@ case object FramePointerAnalysis extends IRPass {
}
}
private def getAliasChildScope(
ir: IR
): Option[AliasMetadata.ChildScope] = {
ir.passData()
.get(AliasAnalysis)
.filter(_.isInstanceOf[AliasMetadata.ChildScope])
.map(_.asInstanceOf[AliasMetadata.ChildScope])
}
private def getAliasAnalysisGraph(
ir: IR
): Option[Graph] = {
@ -380,36 +425,4 @@ case object FramePointerAnalysis extends IRPass {
exprIr
}
}
// === Pass Configuration ===================================================
class FramePointerMeta(
val framePointer: FramePointer
) extends IRMetadata {
override val metadataName: String = "FramePointer"
def parentLevel(): Int = framePointer.parentLevel
def frameSlotIdx(): Int = framePointer.frameSlotIdx
/** @inheritdoc
*/
override def duplicate(): Option[Metadata] = {
Some(new FramePointerMeta(framePointer))
}
/** @inheritdoc
*/
override def prepareForSerialization(
compiler: CompilerContext
): ProcessingPass.Metadata = this
/** @inheritdoc
*/
override def restoreFromSerialization(
compiler: CompilerContext
): Option[ProcessingPass.Metadata] = Some(this)
override def toString: String = s"FramePointerMeta($framePointer)"
}
}

View File

@ -9,44 +9,53 @@ import scala.collection.mutable
import scala.reflect.ClassTag
/** A graph containing aliasing information for a given root scope in Enso. */
sealed class Graph extends Serializable {
var rootScope: Graph.Scope = new Graph.Scope()
private var links: Set[Graph.Link] = Set()
sealed class Graph(
val rootScope: Graph.Scope = new Graph.Scope(),
private var _nextIdCounter: Int = 0,
private var links: Set[Graph.Link] = Set()
) extends Serializable {
private var sourceLinks: Map[Graph.Id, Set[Graph.Link]] = new HashMap()
private var targetLinks: Map[Graph.Id, Set[Graph.Link]] = new HashMap()
var nextIdCounter = 0
private var frozen: Boolean = false
{
links.foreach(addSourceTargetLink)
}
private var globalSymbols: Map[Graph.Symbol, GraphOccurrence.Global] =
Map()
/** @return the next counter value
*/
def nextIdCounter: Int = _nextIdCounter
/** @return a deep structural copy of `this` */
def deepCopy(
scope_mapping: mutable.Map[Scope, Scope] = mutable.Map()
): Graph = {
val copy = new Graph
copy.rootScope = this.rootScope.deepCopy(scope_mapping)
val copy = new Graph(
this.rootScope.deepCopy(scope_mapping),
this.nextIdCounter
)
copy.links = this.links
copy.sourceLinks = this.sourceLinks
copy.targetLinks = this.targetLinks
copy.globalSymbols = this.globalSymbols
copy.nextIdCounter = this.nextIdCounter
copy
}
def initLinks(links: Set[Graph.Link]): Unit = {
sourceLinks = new HashMap()
targetLinks = new HashMap()
links.foreach(addSourceTargetLink)
this.links = links
}
def getLinks(): Set[Graph.Link] = links
def freeze(): Unit = {
frozen = true
}
/** Registers a requested global symbol in the aliasing scope.
*
* @param sym the symbol occurrence
*/
def addGlobalSymbol(sym: GraphOccurrence.Global): Unit = {
assert(!frozen)
if (!globalSymbols.contains(sym.symbol)) {
globalSymbols = globalSymbols + (sym.symbol -> sym)
}
@ -57,12 +66,13 @@ sealed class Graph extends Serializable {
* @return a copy of the graph structure
*/
def copy: Graph = {
val graph = new Graph
graph.links = links
graph.sourceLinks = sourceLinks
graph.targetLinks = targetLinks
graph.rootScope = rootScope.deepCopy(mutable.Map())
graph.nextIdCounter = nextIdCounter
val graph = new Graph(
rootScope.deepCopy(mutable.Map()),
nextIdCounter
)
graph.links = links
graph.sourceLinks = sourceLinks
graph.targetLinks = targetLinks
graph
}
@ -84,8 +94,8 @@ sealed class Graph extends Serializable {
* @return a unique identifier for this graph
*/
def nextId(): Graph.Id = {
val nextId = nextIdCounter
nextIdCounter += 1
val nextId = _nextIdCounter
_nextIdCounter += 1
nextId
}
@ -99,13 +109,14 @@ sealed class Graph extends Serializable {
occurrence: GraphOccurrence.Use
): Option[Graph.Link] = {
scopeFor(occurrence.id).flatMap(_.resolveUsage(occurrence).map { link =>
links += link
addSourceTargetLink(link)
links += link
link
})
}
private def addSourceTargetLink(link: Graph.Link): Unit = {
assert(!frozen)
sourceLinks = sourceLinks.updatedWith(link.source)(v =>
v.map(s => s + link).orElse(Some(Set(link)))
)

View File

@ -488,7 +488,7 @@ class ChangesetBuilderTest
def freshInlineContext: InlineContext =
buildInlineContext(
localScope = Some(LocalScope.root),
localScope = Some(LocalScope.createEmpty),
freshNameSupply = Some(new FreshNameSupply),
isInTailPosition = Some(false)
)

View File

@ -30,7 +30,7 @@ import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import org.enso.common.DebugServerInfo;
import org.enso.compiler.context.FramePointer;
import org.enso.compiler.pass.analyse.FramePointer;
import org.enso.interpreter.node.EnsoRootNode;
import org.enso.interpreter.node.expression.builtin.debug.DebugBreakpointNode;
import org.enso.interpreter.node.expression.builtin.text.util.ToJavaStringNode;

View File

@ -442,6 +442,48 @@ public class ExecCompilerTest {
}
}
@Test
public void testFnAsADefaultValue() throws Exception {
var code =
"""
type N
type T
V (r:(T -> N | T)=(_->N))
v self = self.r self
run type = case type of
0 -> T.V
1 -> T.V (_->N)
""";
var module = ctx.eval(LanguageInfo.ID, code);
var run = module.invokeMember("eval_expression", "run");
var real = run.execute(1L);
var realN = real.invokeMember("v");
var defaulted = run.execute(0L);
var defaultedN = defaulted.invokeMember("v");
assertEquals("Should be the same", realN, defaultedN);
}
@Test
public void testTemporaryFileSpecProblem() throws Exception {
var code =
"""
from Standard.Base.Errors.Common import all
run t = F.app f->
f.read t
type F
read self r = r
app fn = fn F
""";
var module = ctx.eval(LanguageInfo.ID, code);
var run = module.invokeMember("eval_expression", "run");
var real = run.execute(1L);
assertEquals("Should be the same", 1, real.asInt());
}
@Test
public void testPropertlyIdentifyNameOfJavaClassInError() throws Exception {
var module =

View File

@ -161,7 +161,7 @@ class DataflowAnalysisTest extends CompilerTest {
*/
def mkInlineContext: InlineContext = {
buildInlineContext(
localScope = Some(LocalScope.root),
localScope = Some(LocalScope.createEmpty),
isInTailPosition = Some(false),
freshNameSupply = Some(new FreshNameSupply)
)

View File

@ -71,7 +71,7 @@ class DemandAnalysisTest extends CompilerTest {
*/
def mkInlineContext: InlineContext = {
buildInlineContext(
localScope = Some(LocalScope.root),
localScope = Some(LocalScope.createEmpty),
freshNameSupply = Some(new FreshNameSupply)
)
}

View File

@ -1,7 +1,9 @@
package org.enso.compiler.test.pass.analyse
import org.enso.compiler.Passes
import org.enso.compiler.context.{FramePointer, FreshNameSupply, ModuleContext}
import org.enso.compiler.pass.analyse.FramePointer
import org.enso.compiler.pass.analyse.FrameAnalysisMeta
import org.enso.compiler.context.{FreshNameSupply, ModuleContext}
import org.enso.compiler.core.IR
import org.enso.compiler.core.ir.{
CallArgument,
@ -87,10 +89,10 @@ class FramePointerAnalysisTest extends CompilerTest {
withClue("Expression.Binding must have FramePointer associated") {
allOcc.head._1
.unsafeGetMetadata(FramePointerAnalysis, "should exist")
.framePointer shouldEqual new FramePointer(0, 1)
.asInstanceOf[FramePointer] shouldEqual new FramePointer(0, 1)
allOcc.last._1
.unsafeGetMetadata(FramePointerAnalysis, "should exist")
.framePointer shouldEqual new FramePointer(0, 2)
.asInstanceOf[FramePointer] shouldEqual new FramePointer(0, 2)
}
}
@ -129,7 +131,7 @@ class FramePointerAnalysisTest extends CompilerTest {
"There should be no associated FramePointer with usage of `+`, because it is not defined " +
"in any scope"
) {
plusUseIr.passData().get(FramePointerAnalysis) shouldNot be(defined)
findFP(plusUseIr) shouldNot be(defined)
}
val framePointers = collectAllFramePointers(ir)
framePointers.size shouldBe 4
@ -429,7 +431,7 @@ class FramePointerAnalysisTest extends CompilerTest {
lit => lit.name == "My_Type"
).last
withClue("No frame pointer attached to a symbol with global occurence") {
myTypeLit.passData.get(FramePointerAnalysis) shouldNot be(defined)
findFP(myTypeLit) shouldNot be(defined)
}
withClue("There is a Use occurence") {
myTypeLit.passData.get(AliasAnalysis) shouldBe defined
@ -455,7 +457,7 @@ class FramePointerAnalysisTest extends CompilerTest {
lit => lit.name == "My_Type"
).apply(1)
withClue("No frame pointer attached to a symbol with global occurence") {
myTypeLit.passData.get(FramePointerAnalysis) shouldNot be(defined)
findFP(myTypeLit) shouldNot be(defined)
}
withClue("There is a Use occurence") {
myTypeLit.passData.get(AliasAnalysis) shouldBe defined
@ -466,6 +468,10 @@ class FramePointerAnalysisTest extends CompilerTest {
}
}
private def findFP(ir: IR) = ir.passData
.get(FramePointerAnalysis)
.filter(meta => meta.isInstanceOf[FramePointer])
/** Find the first IR element of the given `T` type by the given `filterCondition`.
* @param filterCondition Filter condition will be applied to all the elements of the desired type.
* The first element that matches the condition will be returned
@ -513,7 +519,7 @@ class FramePointerAnalysisTest extends CompilerTest {
}
ir
.unsafeGetMetadata(FramePointerAnalysis, "should exist")
.framePointer shouldEqual framePointer
.asInstanceOf[FramePointer] shouldEqual framePointer
}
private def findAssociatedIr(
@ -548,10 +554,11 @@ class FramePointerAnalysisTest extends CompilerTest {
private def collectAllFramePointers(
ir: IR
): List[(IR, FramePointerAnalysis.Metadata)] = {
): List[(IR, FrameAnalysisMeta)] = {
ir.preorder().flatMap { childIr =>
childIr.getMetadata(FramePointerAnalysis) match {
case Some(framePointerMeta: FramePointerAnalysis.Metadata) =>
case Some(framePointerMeta: FrameAnalysisMeta)
if (framePointerMeta.isInstanceOf[FramePointer]) =>
Some((childIr, framePointerMeta))
case _ => None
}

View File

@ -31,14 +31,14 @@ class TailCallTest extends CompilerTest {
def mkTailContext: InlineContext =
buildInlineContext(
localScope = Some(LocalScope.root),
localScope = Some(LocalScope.createEmpty),
isInTailPosition = Some(true),
freshNameSupply = Some(new FreshNameSupply)
)
def mkNoTailContext: InlineContext =
buildInlineContext(
localScope = Some(LocalScope.root),
localScope = Some(LocalScope.createEmpty),
isInTailPosition = Some(false),
freshNameSupply = Some(new FreshNameSupply)
)

View File

@ -51,7 +51,7 @@ class UnusedBindingsTest extends CompilerTest with Inside {
*/
def mkInlineContext: InlineContext = {
buildInlineContext(
localScope = Some(LocalScope.root),
localScope = Some(LocalScope.createEmpty),
isInTailPosition = Some(false),
freshNameSupply = Some(new FreshNameSupply)
)

View File

@ -77,7 +77,7 @@ class LambdaConsolidateTest extends CompilerTest {
*/
def mkContext: InlineContext = {
buildInlineContext(
localScope = Some(LocalScope.root),
localScope = Some(LocalScope.createEmpty),
freshNameSupply = Some(new FreshNameSupply),
passConfiguration = Some(passConfiguration)
)

View File

@ -80,7 +80,7 @@ class SuspendedArgumentsTest extends CompilerTest {
def mkInlineContext: InlineContext = {
buildInlineContext(
freshNameSupply = Some(new FreshNameSupply),
localScope = Some(LocalScope.root)
localScope = Some(LocalScope.createEmpty)
)
}

View File

@ -84,7 +84,7 @@ object Function {
Persistance.Reference.of(body, true),
location,
true,
ir.passData
ir.passData.duplicate()
)
diagnostics = ir.diagnostics
}

View File

@ -267,7 +267,7 @@ public final class EnsoLanguage extends TruffleLanguage<EnsoContext> {
if (optionTupple.nonEmpty()) {
var newInlineContext = optionTupple.get()._1();
var ir = optionTupple.get()._2();
var sco = newInlineContext.localScope().getOrElse(LocalScope::root);
var sco = newInlineContext.localScope().getOrElse(LocalScope::empty);
var mod = newInlineContext.getModule();
var m = org.enso.interpreter.runtime.Module.fromCompilerModule(mod);
var toTruffle =

View File

@ -287,7 +287,11 @@ public final class Cache<T, M> {
return Optional.empty();
}
} catch (ClassNotFoundException | IOException ex) {
logger.log(Level.WARNING, "`" + logName + "` in " + dataPath + " failed to load: ", ex);
logger.log(
Level.WARNING,
"`{0}` in {1} failed to load: {2}",
new Object[] {logName, dataPath, ex.getMessage()});
logger.log(Level.FINE, "`{0}` in {1} failed to load:", ex);
invalidateCache(cacheRoot, logger);
return Optional.empty();
}

View File

@ -1,5 +1,6 @@
package org.enso.interpreter.node;
import com.oracle.truffle.api.TruffleLogger;
import com.oracle.truffle.api.frame.FrameDescriptor;
import com.oracle.truffle.api.frame.FrameSlotKind;
import com.oracle.truffle.api.nodes.NodeInfo;
@ -7,16 +8,20 @@ import com.oracle.truffle.api.nodes.RootNode;
import com.oracle.truffle.api.source.Source;
import com.oracle.truffle.api.source.SourceSection;
import java.util.Objects;
import java.util.function.BiFunction;
import java.util.logging.Level;
import org.enso.common.LanguageInfo;
import org.enso.compiler.context.LocalScope;
import org.enso.interpreter.EnsoLanguage;
import org.enso.interpreter.runtime.EnsoContext;
import org.enso.interpreter.runtime.error.DataflowError;
import org.enso.interpreter.runtime.scope.ModuleScope;
import org.enso.interpreter.util.ScalaConversions;
/** A common base class for all kinds of root node in Enso. */
@NodeInfo(shortName = "Root", description = "A root node for Enso computations")
public abstract class EnsoRootNode extends RootNode {
private static final TruffleLogger LOGGER = TruffleLogger.getLogger(LanguageInfo.ID);
private final String name;
private final int sourceStartIndex;
private final int sourceLength;
@ -39,7 +44,7 @@ public abstract class EnsoRootNode extends RootNode {
ModuleScope moduleScope,
String name,
SourceSection sourceSection) {
super(language, buildFrameDescriptor(localScope));
super(language, buildFrameDescriptor(name, localScope, LOGGER));
Objects.requireNonNull(language);
Objects.requireNonNull(localScope);
Objects.requireNonNull(moduleScope);
@ -62,11 +67,21 @@ public abstract class EnsoRootNode extends RootNode {
*
* @return {@link FrameDescriptor} built from the variable definitions in the local localScope.
*/
private static FrameDescriptor buildFrameDescriptor(LocalScope localScope) {
private static FrameDescriptor buildFrameDescriptor(
String name, LocalScope localScope, TruffleLogger log) {
var descriptorBuilder = FrameDescriptor.newBuilder();
descriptorBuilder.addSlot(FrameSlotKind.Object, LocalScope.monadicStateSlotName(), null);
for (var definition : ScalaConversions.asJava(localScope.scope().allDefinitions())) {
descriptorBuilder.addSlot(FrameSlotKind.Illegal, definition.symbol(), null);
BiFunction<String, Object[], Void> logFnOrNull =
log.isLoggable(Level.FINE)
? (msg, args) -> {
log.log(Level.FINE, msg, args);
return null;
}
: null;
var allDefs = localScope.allSymbols(name, logFnOrNull);
for (var definition : allDefs) {
descriptorBuilder.addSlot(FrameSlotKind.Illegal, definition, null);
}
descriptorBuilder.defaultValue(DataflowError.UNINITIALIZED);
var frameDescriptor = descriptorBuilder.build();

View File

@ -65,7 +65,8 @@ public abstract class EvalNode extends BaseNode {
@CompilerDirectives.TruffleBoundary
RootCallTarget parseExpression(LocalScope scope, ModuleScope moduleScope, String expression) {
EnsoContext context = EnsoContext.get(this);
LocalScope localScope = scope.createChild();
LocalScope localScope =
scope == LocalScope.empty() ? LocalScope.createEmpty() : scope.createChild();
var compiler = context.getCompiler();
InlineContext inlineContext =
InlineContext.fromJava(
@ -83,7 +84,7 @@ public abstract class EvalNode extends BaseNode {
var newInlineContext = tuppleOption.get()._1();
var ir = tuppleOption.get()._2();
var sco = newInlineContext.localScope().getOrElse(LocalScope::root);
var sco = newInlineContext.localScope().getOrElse(LocalScope::empty);
var mod = newInlineContext.getModule();
var m = org.enso.interpreter.runtime.Module.fromCompilerModule(mod);
var toTruffle = new IrToTruffle(context, src, m.getScopeBuilder(), compiler.getConfig());

View File

@ -8,7 +8,7 @@ import com.oracle.truffle.api.frame.MaterializedFrame;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.ExplodeLoop;
import com.oracle.truffle.api.nodes.NodeInfo;
import org.enso.compiler.context.FramePointer;
import org.enso.compiler.pass.analyse.FramePointer;
import org.enso.interpreter.node.ExpressionNode;
import org.enso.interpreter.runtime.callable.function.Function;

View File

@ -660,7 +660,7 @@ public final class Module implements EnsoObject {
.getBuiltinFunction(
builtins.debug(), Builtins.MethodNames.Debug.EVAL, context.getLanguage())
.orElseThrow();
CallerInfo callerInfo = new CallerInfo(null, LocalScope.root(), scope);
CallerInfo callerInfo = new CallerInfo(null, LocalScope.empty(), scope);
return callOptimiserNode.executeDispatch(
null,
eval.getFunction(),

View File

@ -200,7 +200,7 @@ public final class UnresolvedConstructor implements EnsoObject {
body.adoptChildren();
var root =
ClosureRootNode.build(
lang, LocalScope.root(), scope, body, section, prototype.getName(), true, true);
lang, LocalScope.empty(), scope, body, section, prototype.getName(), true, true);
root.adoptChildren();
assert Objects.equals(expr.getSourceSection(), section)
: "Expr: " + expr.getSourceSection() + " orig: " + section;

View File

@ -112,7 +112,7 @@ public final class AtomConstructor implements EnsoObject {
return initializeFields(
language,
null,
LocalScope.root(),
LocalScope.empty(),
scopeBuilder,
new ExpressionNode[0],
reads,

View File

@ -24,7 +24,7 @@ final class GetFieldNode extends EnsoRootNode {
* @param index the index this node should use for field lookup.
*/
GetFieldNode(EnsoLanguage language, int index, Type type, String name, ModuleScope moduleScope) {
super(language, LocalScope.root(), moduleScope, name, null);
super(language, LocalScope.empty(), moduleScope, name, null);
this.index = index;
this.type = type;
this.name = name;

View File

@ -24,7 +24,7 @@ final class QualifiedAccessorNode extends EnsoRootNode {
EnsoLanguage language, AtomConstructor atomConstructor, ModuleScope moduleScope) {
super(
language,
LocalScope.root(),
LocalScope.empty(),
moduleScope,
atomConstructor.getQualifiedName().toString(),
null);

View File

@ -16,7 +16,7 @@ import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.stream.Collectors;
import org.enso.compiler.context.FramePointer;
import org.enso.compiler.pass.analyse.FramePointer;
import org.enso.interpreter.EnsoLanguage;
import org.enso.interpreter.node.EnsoRootNode;
import org.enso.interpreter.runtime.callable.function.Function;

View File

@ -179,7 +179,9 @@ public final class TopLevelScope implements EnsoObject {
} catch (InterruptedException e) {
throw new RuntimeException(e);
} catch (ExecutionException e) {
throw new RuntimeException(e);
var re = new RuntimeException(e);
re.setStackTrace(e.getStackTrace());
throw re;
}
}

View File

@ -1,10 +1,12 @@
package org.enso.interpreter.runtime
import java.util.logging.Level
import com.oracle.truffle.api.source.{Source, SourceSection}
import com.oracle.truffle.api.interop.InteropLibrary
import org.enso.compiler.pass.analyse.FramePointer
import org.enso.compiler.pass.analyse.FrameVariableNames
import org.enso.compiler.context.{
CompilerContext,
FramePointer,
LocalScope,
NameResolutionAlgorithm
}
@ -264,30 +266,28 @@ class IrToTruffle(
atomCons: AtomConstructor,
atomDefn: Definition.Data
): Unit = {
def scopeInfo() = {
atomDefn
.unsafeGetMetadata(
AliasAnalysis,
"No root scope on an atom definition."
)
.unsafeAs[AliasMetadata.RootScope]
}
val scopeInfo = rootScopeInfo("atom definition", atomDefn)
def dataflowInfo() = atomDefn.unsafeGetMetadata(
DataflowAnalysis,
"No dataflow information associated with an atom."
)
def frameInfo() = atomDefn.unsafeGetMetadata(
FramePointerAnalysis,
"Method definition missing frame information."
)
val localScope = new LocalScope(
None,
() => scopeInfo().graph,
() => scopeInfo().graph.rootScope,
dataflowInfo
dataflowInfo,
frameInfo
)
val argFactory =
new DefinitionArgumentProcessor(
scope = localScope,
initialName = "Type " + tpDef.name
initialName = "Type " + tpDef.name.name
)
val argDefs =
new Array[ArgumentDefinition](atomDefn.arguments.size)
@ -303,6 +303,7 @@ class IrToTruffle(
FramePointerAnalysis,
"No frame pointer on an argument definition."
)
.asInstanceOf[FramePointer]
val slotIdx = fp.frameSlotIdx()
argDefs(idx) = arg
val readArg =
@ -332,7 +333,8 @@ class IrToTruffle(
() => scopeInfo().graph,
() => scopeInfo().graph.rootScope,
dataflowInfo,
atomDefn.name.name
atomDefn.name.name,
frameInfo
)
val expressionNode =
expressionProcessor.run(annotation.expression, true)
@ -369,19 +371,17 @@ class IrToTruffle(
}
methodDefs.foreach(methodDef => {
def scopeInfo() = {
methodDef
.unsafeGetMetadata(
AliasAnalysis,
s"Missing scope information for method " +
s"`${methodDef.typeName.map(_.name + ".").getOrElse("")}${methodDef.methodName.name}`."
)
.unsafeAs[AliasMetadata.RootScope]
}
lazy val where =
s"`method ${methodDef.typeName.map(_.name + ".").getOrElse("")}${methodDef.methodName.name}`."
val scopeInfo = rootScopeInfo(where, methodDef)
def dataflowInfo() = methodDef.unsafeGetMetadata(
DataflowAnalysis,
"Method definition missing dataflow information."
)
def frameInfo() = methodDef.unsafeGetMetadata(
FramePointerAnalysis,
"Method definition missing frame information."
)
@tailrec
def getContext(tp: Expression): Option[String] = tp match {
@ -415,7 +415,8 @@ class IrToTruffle(
() => scopeInfo().graph,
() => scopeInfo().graph.rootScope,
dataflowInfo,
fullMethodDefName
fullMethodDefName,
frameInfo
)
scopeBuilder.registerMethod(
@ -546,17 +547,12 @@ class IrToTruffle(
)
val scopeName =
scopeElements.mkString(Constants.SCOPE_SEPARATOR)
def scopeInfo() = {
annotation
.unsafeGetMetadata(
AliasAnalysis,
s"Missing scope information for annotation " +
s"${annotation.name} of method " +
scopeElements.init
.mkString(Constants.SCOPE_SEPARATOR)
)
.unsafeAs[AliasMetadata.RootScope]
}
lazy val where =
s"annotation ${annotation.name} of method ${scopeElements.init
.mkString(Constants.SCOPE_SEPARATOR)}"
val scopeInfo = rootScopeInfo(where, annotation)
def dataflowInfo() = annotation.unsafeGetMetadata(
DataflowAnalysis,
"Missing dataflow information for annotation " +
@ -564,12 +560,17 @@ class IrToTruffle(
scopeElements.init
.mkString(Constants.SCOPE_SEPARATOR)
)
def frameInfo() = annotation.unsafeGetMetadata(
FramePointerAnalysis,
"Method definition missing frame information."
)
val expressionProcessor = new ExpressionProcessor(
scopeName,
() => scopeInfo().graph,
() => scopeInfo().graph.rootScope,
dataflowInfo,
methodDef.methodName.name
methodDef.methodName.name,
frameInfo
)
val expressionNode =
expressionProcessor.run(annotation.expression, true)
@ -599,9 +600,9 @@ class IrToTruffle(
.annotations(annotations: _*)
.argumentDefinitions(arguments: _*)
if (methodDef.isPrivate) {
funcSchemaBldr.projectPrivate();
funcSchemaBldr.projectPrivate()
}
val funcSchema = funcSchemaBldr.build();
val funcSchema = funcSchemaBldr.build()
new RuntimeFunction(
callTarget,
null,
@ -700,7 +701,7 @@ class IrToTruffle(
.newBuilder()
.argumentDefinitions(bodyBuilder.args(): _*)
if (methodDef.isPrivate) {
funcSchemaBldr.projectPrivate();
funcSchemaBldr.projectPrivate()
}
val funcSchema = funcSchemaBldr.build()
new RuntimeFunction(
@ -767,19 +768,18 @@ class IrToTruffle(
// Register the conversion definitions in scope
conversionDefs.foreach(methodDef => {
def scopeInfo() = {
methodDef
.unsafeGetMetadata(
AliasAnalysis,
s"Missing scope information for conversion " +
s"`${methodDef.typeName.map(_.name + ".").getOrElse("")}${methodDef.methodName.name}`."
)
.unsafeAs[AliasMetadata.RootScope]
}
lazy val where =
s"conversion `${methodDef.typeName.map(_.name + ".").getOrElse("")}${methodDef.methodName.name}`."
val scopeInfo = rootScopeInfo(where, methodDef)
def dataflowInfo() = methodDef.unsafeGetMetadata(
DataflowAnalysis,
"Method definition missing dataflow information."
)
def frameInfo() = methodDef.unsafeGetMetadata(
FramePointerAnalysis,
"Method definition missing frame information."
)
val toOpt =
methodDef.methodReference.typePointer match {
@ -795,7 +795,8 @@ class IrToTruffle(
() => scopeInfo().graph,
() => scopeInfo().graph.rootScope,
dataflowInfo,
methodDef.methodName.name
methodDef.methodName.name,
frameInfo
)
val function = methodDef.body match {
@ -1230,10 +1231,11 @@ class IrToTruffle(
graph: () => AliasGraph,
scope: () => AliasScope,
dataflowInfo: () => DataflowAnalysis.Metadata,
initialName: String
initialName: String,
frameInfo: () => FramePointerAnalysis.Metadata = null
) = {
this(
new LocalScope(None, graph, scope, dataflowInfo),
new LocalScope(None, graph, scope, dataflowInfo, frameInfo),
scopeName,
initialName
)
@ -1249,9 +1251,12 @@ class IrToTruffle(
def createChild(
name: String,
scope: () => AliasScope,
initialName: String
initialName: String,
symbolsProvider: () => FrameVariableNames = null
): ExpressionProcessor = {
new ExpressionProcessor(this.scope.createChild(scope), name, initialName)
val childScope =
this.scope.createChild(scope, symbolsProvider = symbolsProvider)
new ExpressionProcessor(childScope, name, initialName)
}
// === Runner =============================================================
@ -1304,7 +1309,7 @@ class IrToTruffle(
ir.getMetadata(TypeSignatures)
types.foreach { tpe =>
val checkNode =
extractAscribedType(tpe.comment.orNull, tpe.signature);
extractAscribedType(tpe.comment.orNull, tpe.signature)
if (checkNode != null) {
runtimeExpression =
ReadArgumentCheckNode.wrap(runtimeExpression, checkNode)
@ -1334,19 +1339,19 @@ class IrToTruffle(
*/
private def processBlock(block: Expression.Block): RuntimeExpression = {
if (block.suspended) {
def scopeInfo() = {
block
.unsafeGetMetadata(
AliasAnalysis,
"Missing scope information on block."
)
.unsafeAs[AliasMetadata.ChildScope]
}
val scopeInfo = childScopeInfo("block", block)
def frameInfo() = block
.unsafeGetMetadata(
FramePointerAnalysis,
"Method definition missing frame information."
)
.asInstanceOf[FrameVariableNames]
val childFactory = this.createChild(
"suspended-block",
() => scopeInfo().scope,
"suspended " + currentVarName
"suspended " + currentVarName,
frameInfo
)
val childScope = childFactory.scope
@ -1448,20 +1453,19 @@ class IrToTruffle(
def processCaseBranch(
branch: Case.Branch
): Either[BadPatternMatch, BranchNode] = {
def scopeInfo() = {
branch
.unsafeGetMetadata(
AliasAnalysis,
"No scope information on a case branch."
)
.unsafeAs[AliasMetadata.ChildScope]
}
val scopeInfo = childScopeInfo("case branch", branch)
def frameInfo() = branch
.unsafeGetMetadata(
FramePointerAnalysis,
"Method definition missing frame information."
)
.asInstanceOf[FrameVariableNames]
val childProcessor =
this.createChild(
"case_branch",
() => scopeInfo().scope,
"case " + currentVarName
"case " + currentVarName,
frameInfo
)
branch.pattern match {
@ -1607,7 +1611,7 @@ class IrToTruffle(
BadPatternMatch.NonConstantPolyglotSymbol(symbol)
)
} else {
val value = iop.readMember(polyClass, symbol);
val value = iop.readMember(polyClass, symbol)
val ensoValue =
HostValueToEnsoNode.getUncached().execute(value)
Right(ensoValue)
@ -1834,6 +1838,7 @@ class IrToTruffle(
FramePointerAnalysis,
"Binding with missing frame pointer."
)
.asInstanceOf[FramePointer]
currentVarName = binding.name.name
val slotIdx = fp.frameSlotIdx()
@ -1853,17 +1858,19 @@ class IrToTruffle(
function: Function,
binding: Boolean
): RuntimeExpression = {
def scopeInfo() = {
function
.unsafeGetMetadata(AliasAnalysis, "No scope info on a function.")
.unsafeAs[AliasMetadata.ChildScope]
}
val scopeInfo = childScopeInfo("function", function)
if (function.body.isInstanceOf[Function]) {
throw new CompilerError(
"Lambda found directly as function body. It looks like Lambda " +
"Consolidation hasn't run."
)
}
def frameInfo() = function
.unsafeGetMetadata(
FramePointerAnalysis,
"Method definition missing frame information."
)
.asInstanceOf[FrameVariableNames]
val scopeName = if (function.canBeTCO) {
this.scopeName + "." + currentVarName
@ -1875,7 +1882,8 @@ class IrToTruffle(
this.createChild(
scopeName,
() => scopeInfo().scope,
"case " + currentVarName
"case " + currentVarName,
frameInfo
)
val fn = child.processFunctionBody(
@ -1898,8 +1906,8 @@ class IrToTruffle(
case literalName: Name.Literal =>
val resolver = new RuntimeNameResolution()
val fpMeta = literalName.passData.get(FramePointerAnalysis) match {
case Some(meta: FramePointerAnalysis.FramePointerMeta) => meta
case _ => null
case Some(meta: FramePointer) => meta
case _ => null
}
resolver.resolveName(literalName, fpMeta)
case Name.MethodReference(
@ -1959,17 +1967,17 @@ class IrToTruffle(
extends NameResolutionAlgorithm[
RuntimeExpression,
FramePointer,
FramePointerAnalysis.FramePointerMeta
FramePointer
] {
override protected def findLocalLink(
fpMeta: FramePointerAnalysis.FramePointerMeta
fpMeta: FramePointer
): Option[FramePointer] = {
if (scope.flattenToParent && fpMeta.parentLevel() > 0) {
Some(
new FramePointer(fpMeta.parentLevel() - 1, fpMeta.frameSlotIdx())
)
} else {
Some(fpMeta.framePointer)
Some(fpMeta)
}
}
@ -2059,11 +2067,11 @@ class IrToTruffle(
private def fileLocationFromSection(loc: IdentifiedLocation) = {
val section =
source.createSection(loc.location().start(), loc.location().length());
source.createSection(loc.location().start(), loc.location().length())
val locStr = "" + section.getStartLine() + ":" + section
.getStartColumn() + "-" + section.getEndLine() + ":" + section
.getEndColumn()
source.getName() + "[" + locStr + "]";
source.getName() + "[" + locStr + "]"
}
/** Generates a runtime implementation for compile error nodes.
@ -2213,6 +2221,7 @@ class IrToTruffle(
FramePointerAnalysis,
"No frame pointer on an argument definition."
)
.asInstanceOf[FramePointer]
val slotIdx = fp.frameSlotIdx()
val readArg =
ReadArgumentNode.build(
@ -2432,14 +2441,7 @@ class IrToTruffle(
): callable.argument.CallArgument =
arg match {
case CallArgument.Specified(name, value, _, _) =>
def scopeInfo() = {
arg
.unsafeGetMetadata(
AliasAnalysis,
"No scope attached to a call argument."
)
.unsafeAs[AliasMetadata.ChildScope]
}
val scopeInfo = childScopeInfo("call argument", arg)
def valueHasSomeTypeCheck() =
value.getMetadata(TypeSignatures).isDefined
@ -2452,7 +2454,17 @@ class IrToTruffle(
}
val childScope = if (shouldCreateClosureRootNode) {
scope.createChild(() => scopeInfo().scope)
def frameInfo() = arg
.unsafeGetMetadata(
FramePointerAnalysis,
"Method definition missing frame information."
)
.asInstanceOf[FrameVariableNames]
scope.createChild(
() => scopeInfo().scope,
symbolsProvider = frameInfo
)
} else {
// Note [Scope Flattening]
scope.createChild(() => scopeInfo().scope, flattenToParent = true)
@ -2618,4 +2630,43 @@ class IrToTruffle(
private def scopeAssociatedType =
scopeBuilder.asModuleScope().getAssociatedType
private def rootScopeInfo(
where: => String,
ir: IR
): () => AliasMetadata.RootScope = {
def readScopeInfo() = {
val raw =
ir.unsafeGetMetadata(AliasAnalysis, s"No root scope for ${where}.")
val scope = raw.unsafeAs[AliasMetadata.RootScope]
val log = context.getLogger()
if (log.isLoggable(Level.FINEST)) {
val allDefs = scope.graph.rootScope.allDefinitions
log.log(Level.FINEST, s"Scope for ${where} loaded with {0}", allDefs)
}
scope
}
readScopeInfo
}
private def childScopeInfo(
where: => String,
ir: IR
): () => AliasMetadata.ChildScope = {
def readScopeInfo() = {
val raw =
ir.unsafeGetMetadata(AliasAnalysis, s"No root scope for ${where}.")
val scope = raw.unsafeAs[AliasMetadata.ChildScope]
val log = context.getLogger()
if (log.isLoggable(Level.FINEST)) {
val allDefs = scope.graph.rootScope.allDefinitions
log.log(Level.FINEST, s"Scope for ${where} loaded with {0}", allDefs)
}
scope
}
readScopeInfo
}
}