From b111dc0f2db7d8745599ae2eb522007cf4474326 Mon Sep 17 00:00:00 2001 From: Adam Ruka Date: Wed, 25 Dec 2024 22:02:00 -0800 Subject: [PATCH] Attempt to fix VariablesObject - still doesn't work! --- .../part_15/nodes/root/StmtBlockRootNode.java | 16 +- .../nodes/stmts/EasyScriptStmtNode.java | 17 +- .../part_15/nodes/stmts/ExprStmtNode.java | 2 +- .../nodes/stmts/blocks/BlockStmtNode.java | 89 +++-- .../runtime/nodes/FuncArgsScopeObject.java | 42 +-- .../truffle/part_15/runtime/nodes/Key.java | 62 ---- .../part_15/runtime/nodes/KeysArray.java | 70 ---- .../runtime/nodes/LocalVarsScopeObject.java | 263 +++++++++++++ .../part_15/runtime/nodes/RefObject.java | 4 +- .../runtime/nodes/RefObjectsArray.java | 18 +- .../runtime/nodes/VariablesObject.java | 350 ------------------ 11 files changed, 348 insertions(+), 585 deletions(-) delete mode 100644 part-16/src/main/java/com/endoflineblog/truffle/part_15/runtime/nodes/Key.java delete mode 100644 part-16/src/main/java/com/endoflineblog/truffle/part_15/runtime/nodes/KeysArray.java create mode 100644 part-16/src/main/java/com/endoflineblog/truffle/part_15/runtime/nodes/LocalVarsScopeObject.java delete mode 100644 part-16/src/main/java/com/endoflineblog/truffle/part_15/runtime/nodes/VariablesObject.java diff --git a/part-16/src/main/java/com/endoflineblog/truffle/part_15/nodes/root/StmtBlockRootNode.java b/part-16/src/main/java/com/endoflineblog/truffle/part_15/nodes/root/StmtBlockRootNode.java index ab47c6f0..77f1f2b7 100644 --- a/part-16/src/main/java/com/endoflineblog/truffle/part_15/nodes/root/StmtBlockRootNode.java +++ b/part-16/src/main/java/com/endoflineblog/truffle/part_15/nodes/root/StmtBlockRootNode.java @@ -36,7 +36,7 @@ public final class StmtBlockRootNode extends RootNode { private final String name; @CompilationFinal(dimensions = 1) - private RefObject[] funcArgRefObjects; + private RefObject[] findFuncArgRefsCache; public StmtBlockRootNode(EasyScriptTruffleLanguage truffleLanguage, FrameDescriptor frameDescriptor, BlockStmtNode blockStmt, String name) { @@ -67,11 +67,11 @@ public String getName() { } public RefObject[] getFuncArgReferences(int argNr) { - if (this.funcArgRefObjects == null) { + if (this.findFuncArgRefsCache == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - this.funcArgRefObjects = this.findFuncArgReferences(argNr); + this.findFuncArgRefsCache = this.findFuncArgReferences(argNr); } - return this.funcArgRefObjects; + return this.findFuncArgRefsCache; } private RefObject[] findFuncArgReferences(int argNr) { @@ -79,16 +79,18 @@ private RefObject[] findFuncArgReferences(int argNr) { // The first argument is always special - it represents 'this'. // We'll never encounter 'this' below, because we check for ReadFunctionArgExprNode, // while 'this' has its own Node (ThisExprNode) - funcArgs[0] = new RefObject("this", null); + funcArgs[0] = new RefObject("this", 0, null); NodeUtil.forEachChild(this.blockStmt, new NodeVisitor() { @Override public boolean visit(Node visitedNode) { if (visitedNode instanceof ReadFunctionArgExprNode) { - ReadFunctionArgExprNode readFunctionArgExprNode = (ReadFunctionArgExprNode) visitedNode; + var readFunctionArgExprNode = (ReadFunctionArgExprNode) visitedNode; if (funcArgs[readFunctionArgExprNode.index] == null) { // only fill this the first time we encounter a reference to the given func argument funcArgs[readFunctionArgExprNode.index] = new RefObject( - readFunctionArgExprNode.argName, readFunctionArgExprNode.getSourceSection()); + readFunctionArgExprNode.argName, + readFunctionArgExprNode.index, + readFunctionArgExprNode.getSourceSection()); } return true; } diff --git a/part-16/src/main/java/com/endoflineblog/truffle/part_15/nodes/stmts/EasyScriptStmtNode.java b/part-16/src/main/java/com/endoflineblog/truffle/part_15/nodes/stmts/EasyScriptStmtNode.java index a3bdaad2..df3c0915 100644 --- a/part-16/src/main/java/com/endoflineblog/truffle/part_15/nodes/stmts/EasyScriptStmtNode.java +++ b/part-16/src/main/java/com/endoflineblog/truffle/part_15/nodes/stmts/EasyScriptStmtNode.java @@ -4,7 +4,7 @@ import com.endoflineblog.truffle.part_15.nodes.root.StmtBlockRootNode; import com.endoflineblog.truffle.part_15.nodes.stmts.blocks.BlockStmtNode; import com.endoflineblog.truffle.part_15.runtime.nodes.FuncArgsScopeObject; -import com.endoflineblog.truffle.part_15.runtime.nodes.VariablesObject; +import com.endoflineblog.truffle.part_15.runtime.nodes.LocalVarsScopeObject; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.frame.Frame; import com.oracle.truffle.api.frame.VirtualFrame; @@ -65,7 +65,7 @@ public SourceSection getSourceSection() { * * @return the block node, always non-null. Either SLBlockNode, or SLRootNode. */ - public final Node findBlock() { + public final Node findParentBlock() { Node parent = getParent(); while (parent != null) { if (parent instanceof BlockStmtNode) { @@ -89,16 +89,13 @@ public final Node findBlock() { @ExportMessage Object getScope( Frame frame, boolean nodeEnter, - @Cached(value = "this", adopt = false) EasyScriptStmtNode cachedNode, - @Cached(value = "this.findBlock()", adopt = false, allowUncached = true) Node blockNode) { - return blockNode instanceof BlockStmtNode - ? new VariablesObject(frame, cachedNode, nodeEnter, (BlockStmtNode) blockNode) - : new FuncArgsScopeObject(frame, (StmtBlockRootNode) blockNode); + @Cached(value = "this", adopt = false) EasyScriptStmtNode thisCached, + @Cached(value = "this.findParentBlock()", adopt = false, allowUncached = true) Node thisParentBlock) { + return thisParentBlock instanceof BlockStmtNode + ? new LocalVarsScopeObject(frame, nodeEnter, thisCached, (BlockStmtNode) thisParentBlock) + : new FuncArgsScopeObject(frame, (StmtBlockRootNode) thisParentBlock); } - /** - * We do provide a scope. - */ @ExportMessage boolean hasScope(@SuppressWarnings("unused") Frame frame) { return true; diff --git a/part-16/src/main/java/com/endoflineblog/truffle/part_15/nodes/stmts/ExprStmtNode.java b/part-16/src/main/java/com/endoflineblog/truffle/part_15/nodes/stmts/ExprStmtNode.java index 075ca20d..9876b24d 100644 --- a/part-16/src/main/java/com/endoflineblog/truffle/part_15/nodes/stmts/ExprStmtNode.java +++ b/part-16/src/main/java/com/endoflineblog/truffle/part_15/nodes/stmts/ExprStmtNode.java @@ -17,7 +17,7 @@ public final class ExprStmtNode extends EasyScriptStmtNode { @Child private EasyScriptExprNode expr; - private final boolean discardExpressionValue; + public final boolean discardExpressionValue; /** * Creates a new instance of the expression statement. diff --git a/part-16/src/main/java/com/endoflineblog/truffle/part_15/nodes/stmts/blocks/BlockStmtNode.java b/part-16/src/main/java/com/endoflineblog/truffle/part_15/nodes/stmts/blocks/BlockStmtNode.java index 03f2696b..e21ba8d9 100644 --- a/part-16/src/main/java/com/endoflineblog/truffle/part_15/nodes/stmts/blocks/BlockStmtNode.java +++ b/part-16/src/main/java/com/endoflineblog/truffle/part_15/nodes/stmts/blocks/BlockStmtNode.java @@ -2,8 +2,10 @@ import com.endoflineblog.truffle.part_15.nodes.exprs.variables.LocalVarAssignmentExprNode; import com.endoflineblog.truffle.part_15.nodes.stmts.EasyScriptStmtNode; +import com.endoflineblog.truffle.part_15.nodes.stmts.ExprStmtNode; import com.endoflineblog.truffle.part_15.nodes.stmts.SkippedStmtNode; import com.endoflineblog.truffle.part_15.runtime.Undefined; +import com.endoflineblog.truffle.part_15.runtime.nodes.RefObject; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.frame.VirtualFrame; @@ -15,7 +17,6 @@ import com.oracle.truffle.api.nodes.NodeVisitor; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; /** @@ -33,7 +34,7 @@ public final class BlockStmtNode extends SkippedStmtNode { private final EasyScriptStmtNode[] stmts; @CompilationFinal(dimensions = 1) - private LocalVarAssignmentExprNode[] writeNodesCache; + private RefObject[] findLocalVarRefsCache; public BlockStmtNode(List stmts) { this.stmts = stmts.toArray(new EasyScriptStmtNode[]{}); @@ -61,70 +62,80 @@ public boolean hasTag(Class tag) { return tag == StandardTags.RootTag.class; } - public LocalVarAssignmentExprNode[] getDeclaredLocalVariables() { - LocalVarAssignmentExprNode[] writeNodes = this.writeNodesCache; - if (writeNodes == null) { + public RefObject[] getLocalVarRefs() { + if (this.findLocalVarRefsCache == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - writeNodesCache = writeNodes = this.findDeclaredLocalVariables(); + this.findLocalVarRefsCache = this.findLocalVarRefs(); } - return writeNodes; + return this.findLocalVarRefsCache; } - private LocalVarAssignmentExprNode[] findDeclaredLocalVariables() { + private RefObject[] findLocalVarRefs() { // Search for those write nodes, which declare variables - List writeNodes = new ArrayList<>(4); + List localVarRefs = new ArrayList<>(4); // int[] varsIndex = new int[]{0}; NodeUtil.forEachChild(this, new NodeVisitor() { + private boolean inDeclaration = false; + @Override - public boolean visit(Node visitedNode) { - if (visitedNode instanceof WrapperNode) { - NodeUtil.forEachChild(visitedNode, this); - return true; - } -// if (visitedNode instanceof SLScopedNode) { -// SLScopedNode scopedNode = (SLScopedNode) visitedNode; + public boolean visit(Node visistedNode) { +// if (visistedNode instanceof WrapperNode) { +// NodeUtil.forEachChild(visistedNode, this); +// return true; +// } +// if (visistedNode instanceof SLScopedNode) { +// SLScopedNode scopedNode = (SLScopedNode) visistedNode; // scopedNode.setVisibleVariablesIndexOnEnter(varsIndex[0]); // } - // Do not enter any nested blocks. - if (!(visitedNode instanceof BlockStmtNode)) { - NodeUtil.forEachChild(visitedNode, this); + if (visistedNode instanceof ExprStmtNode) { + var exprStmtNode = (ExprStmtNode) visistedNode; + if (exprStmtNode.discardExpressionValue) { + this.inDeclaration = true; + } + NodeUtil.forEachChild(visistedNode, this); + if (exprStmtNode.discardExpressionValue) { + this.inDeclaration = false; + } + return true; } // Write to a variable is a declaration unless it exists already in a parent scope. - if (visitedNode instanceof LocalVarAssignmentExprNode) { - LocalVarAssignmentExprNode wn = (LocalVarAssignmentExprNode) visitedNode; -// if (wn.isDeclaration()) { - writeNodes.add(wn); -// varsIndex[0]++; -// } + if (this.inDeclaration && visistedNode instanceof LocalVarAssignmentExprNode) { + LocalVarAssignmentExprNode lvaen = (LocalVarAssignmentExprNode) visistedNode; + localVarRefs.add(new RefObject( + lvaen.getSlotName(), + lvaen.getFrameSlot(), + lvaen.getSourceSection())); + return true; + } + // Recur into any Node except a block of statements. + if (!(visistedNode instanceof BlockStmtNode)) { + NodeUtil.forEachChild(visistedNode, this); } -// if (visitedNode instanceof SLScopedNode) { -// SLScopedNode scopedNode = (SLScopedNode) visitedNode; +// if (visistedNode instanceof SLScopedNode) { +// SLScopedNode scopedNode = (SLScopedNode) visistedNode; // scopedNode.setVisibleVariablesIndexOnExit(varsIndex[0]); // } return true; } }); - LocalVarAssignmentExprNode[] variables = writeNodes.toArray(new LocalVarAssignmentExprNode[0]); -// this.parentBlockIndex = variables.length; - - Node parentBlock = this.findBlock(); - LocalVarAssignmentExprNode[] parentVariables = null; + Node parentBlock = this.findParentBlock(); + RefObject[] parentVariables = null; if (parentBlock instanceof BlockStmtNode) { - parentVariables = ((BlockStmtNode) parentBlock).getDeclaredLocalVariables(); + parentVariables = ((BlockStmtNode) parentBlock).getLocalVarRefs(); } + RefObject[] variables = localVarRefs.toArray(new RefObject[0]); +// parentBlockIndex = variables.length; if (parentVariables == null || parentVariables.length == 0) { return variables; } else { -// int parentVariablesIndex = ((BlockStmtNode) parentBlock).getParentBlockIndex(); +// int parentVariablesIndex = ((SLBlockNode) parentBlock).getParentBlockIndex(); // int visibleVarsIndex = getVisibleVariablesIndexOnEnter(); // int allVarsLength = variables.length + visibleVarsIndex + parentVariables.length - parentVariablesIndex; -// LocalVarAssignmentExprNode[] allVariables = Arrays.copyOf(variables, allVarsLength); // System.arraycopy(parentVariables, 0, allVariables, variables.length, visibleVarsIndex); // System.arraycopy(parentVariables, parentVariablesIndex, allVariables, variables.length + visibleVarsIndex, parentVariables.length - parentVariablesIndex); - - int allVarsLength = variables.length + parentVariables.length; - LocalVarAssignmentExprNode[] allVariables = Arrays.copyOf(variables, allVarsLength); - System.arraycopy(parentVariables, 0, allVariables, variables.length, allVarsLength - variables.length); + RefObject[] allVariables = new RefObject[variables.length + parentVariables.length]; + System.arraycopy(variables, 0, allVariables, 0, variables.length); + System.arraycopy(parentVariables, 0, allVariables, variables.length, parentVariables.length); return allVariables; } } diff --git a/part-16/src/main/java/com/endoflineblog/truffle/part_15/runtime/nodes/FuncArgsScopeObject.java b/part-16/src/main/java/com/endoflineblog/truffle/part_15/runtime/nodes/FuncArgsScopeObject.java index 82ea231f..b45b8e02 100644 --- a/part-16/src/main/java/com/endoflineblog/truffle/part_15/runtime/nodes/FuncArgsScopeObject.java +++ b/part-16/src/main/java/com/endoflineblog/truffle/part_15/runtime/nodes/FuncArgsScopeObject.java @@ -23,34 +23,22 @@ public final class FuncArgsScopeObject implements TruffleObject { private final Frame frame; final StmtBlockRootNode rootNode; - /** - * The arguments depend on the current frame and root node. - */ public FuncArgsScopeObject(Frame frame, StmtBlockRootNode rootNode) { this.frame = frame; this.rootNode = rootNode; } - /** - * For performance reasons, fix the library implementation for the particular root node. - */ @ExportMessage boolean accepts( @Cached(value = "this.rootNode", adopt = false) StmtBlockRootNode cachedRoot) { return this.rootNode == cachedRoot; } - /** - * This is a scope object, providing arguments as members. - */ @ExportMessage boolean isScope() { return true; } - /** - * The scope must provide an associated language. - */ @ExportMessage boolean hasLanguage() { return true; @@ -61,41 +49,26 @@ Class> getLanguage() { return EasyScriptTruffleLanguage.class; } - /** - * Provide the function name as the scope's display string. - */ @ExportMessage Object toDisplayString(@SuppressWarnings("unused") boolean allowSideEffects) { return rootNode.getName(); } - /** - * We provide a source section of this scope. - */ @ExportMessage boolean hasSourceLocation() { return true; } - /** - * @return Source section of the function. - */ @ExportMessage SourceSection getSourceLocation() { return rootNode.getSourceSection(); } - /** - * Scope must provide scope members. - */ @ExportMessage boolean hasMembers() { return true; } - /** - * We return an array of argument objects as scope members. - */ @ExportMessage Object getMembers(@SuppressWarnings("unused") boolean includeInternal) { RefObject[] refObjects = rootNode.getFuncArgReferences(this.frame.getArguments().length); @@ -125,7 +98,7 @@ static boolean isMemberReadableUncached(FuncArgsScopeObject receiver, String mem static final class MemberModifiable { @Specialization(limit = "MEMBER_CACHE_LIMIT", guards = {"cachedMember.equals(member)"}) static boolean isMemberModifiableCached( - FuncArgsScopeObject receiver, + @SuppressWarnings("unused") FuncArgsScopeObject receiver, @SuppressWarnings("unused") String member, @Cached("member") @SuppressWarnings("unused") String cachedMember, // We cache the member existence for fast-path access @@ -140,14 +113,6 @@ static boolean isMemberModifiableUncached(FuncArgsScopeObject receiver, String m } } - /** - * We can not insert new arguments. - */ - @ExportMessage - boolean isMemberInsertable(@SuppressWarnings("unused") String member) { - return false; - } - @ExportMessage(name = "readMember") static final class ReadMember { @Specialization(limit = "MEMBER_CACHE_LIMIT", guards = {"cachedMember.equals(member)"}) @@ -207,6 +172,11 @@ private static void writeMember(FuncArgsScopeObject receiver, String member, int } } + @ExportMessage + boolean isMemberInsertable(@SuppressWarnings("unused") String member) { + return false; + } + private boolean hasArgCalled(String member) { return this.findArgumentIndex(member) >= 0; } diff --git a/part-16/src/main/java/com/endoflineblog/truffle/part_15/runtime/nodes/Key.java b/part-16/src/main/java/com/endoflineblog/truffle/part_15/runtime/nodes/Key.java deleted file mode 100644 index 2952f836..00000000 --- a/part-16/src/main/java/com/endoflineblog/truffle/part_15/runtime/nodes/Key.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.endoflineblog.truffle.part_15.runtime.nodes; - -import com.endoflineblog.truffle.part_15.nodes.exprs.variables.LocalVarAssignmentExprNode; -import com.endoflineblog.truffle.part_15.runtime.EasyScriptTruffleStrings; -import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.dsl.Cached; -import com.oracle.truffle.api.interop.InteropLibrary; -import com.oracle.truffle.api.interop.TruffleObject; -import com.oracle.truffle.api.interop.UnsupportedMessageException; -import com.oracle.truffle.api.library.ExportLibrary; -import com.oracle.truffle.api.library.ExportMessage; -import com.oracle.truffle.api.source.SourceSection; -import com.oracle.truffle.api.strings.TruffleString; - -/** - * Representation of a variable based on a {@link LocalVarAssignmentExprNode write node} that - * declares the variable. It provides the variable name as a {@link Key#asString() string} and - * the name node associated with the variable's write node as a {@link Key#getSourceLocation() - * source location}. - */ -@ExportLibrary(InteropLibrary.class) -final class Key implements TruffleObject { - private final LocalVarAssignmentExprNode writeNode; - - Key(LocalVarAssignmentExprNode writeNode) { - this.writeNode = writeNode; - } - - @ExportMessage - boolean isString() { - return true; - } - - @ExportMessage - String asString() { - // frame slot's identifier object is not safe to convert to String on fast-path. - return writeNode.getSlotName(); - } - - @ExportMessage - TruffleString asTruffleString(@Cached TruffleString.FromJavaStringNode fromJavaStringNode) { - // frame slot's identifier object is not safe to convert to String on fast-path. - return EasyScriptTruffleStrings.fromJavaString(writeNode.getSlotName(), - fromJavaStringNode); - } - - @ExportMessage - boolean hasSourceLocation() { - return this.writeNode.getSourceSection() != null; - } - - @ExportMessage - @TruffleBoundary - SourceSection getSourceLocation() throws UnsupportedMessageException { - if (!hasSourceLocation()) { - throw UnsupportedMessageException.create(); - } - return this.writeNode.getSourceSection(); -// SLExpressionNode nameNode = writeNode.getNameNode(); -// return writeNode.getRootNode().getSourceSection().getSource().createSection(nameNode.getSourceCharIndex(), nameNode.getSourceLength()); - } -} diff --git a/part-16/src/main/java/com/endoflineblog/truffle/part_15/runtime/nodes/KeysArray.java b/part-16/src/main/java/com/endoflineblog/truffle/part_15/runtime/nodes/KeysArray.java deleted file mode 100644 index cc9c33b0..00000000 --- a/part-16/src/main/java/com/endoflineblog/truffle/part_15/runtime/nodes/KeysArray.java +++ /dev/null @@ -1,70 +0,0 @@ -package com.endoflineblog.truffle.part_15.runtime.nodes; - -import com.endoflineblog.truffle.part_15.nodes.exprs.variables.LocalVarAssignmentExprNode; -import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; -import com.oracle.truffle.api.interop.InteropLibrary; -import com.oracle.truffle.api.interop.InvalidArrayIndexException; -import com.oracle.truffle.api.interop.TruffleObject; -import com.oracle.truffle.api.library.ExportLibrary; -import com.oracle.truffle.api.library.ExportMessage; - -/** - * Array of visible variables. The variables are based on their declaration write nodes and are - * represented as {@link Key} objects. - */ -@ExportLibrary(InteropLibrary.class) -final class KeysArray implements TruffleObject { - @CompilationFinal(dimensions = 1) - private final LocalVarAssignmentExprNode[] writeNodes; - - private final int variableIndex; - private final int parentBlockIndex; - - /** - * Creates a new array of visible variables. - * - * @param writeNodes all variables declarations in the scope, including parent scopes. - * @param variableIndex index to the variables array, determining variables in the - * inner-most scope (from zero index up to the variableIndex, - * exclusive). - * @param parentBlockIndex index to the variables array, determining variables in the parent - * block's scope (from parentBlockIndex to the end of the - * writeNodes array). - */ - KeysArray(LocalVarAssignmentExprNode[] writeNodes, int variableIndex, int parentBlockIndex) { - this.writeNodes = writeNodes; - this.variableIndex = variableIndex; - this.parentBlockIndex = parentBlockIndex; - } - - @ExportMessage - boolean hasArrayElements() { - return true; - } - - @ExportMessage - long getArraySize() { - // We see all parent's variables (writeNodes.length - parentBlockIndex) plus the - // variables in the inner-most scope visible by the current node (variableIndex). - return writeNodes.length - parentBlockIndex + variableIndex; - } - - @ExportMessage - boolean isArrayElementReadable(long index) { - return index >= 0 && index < (writeNodes.length - parentBlockIndex + variableIndex); - } - - @ExportMessage - Object readArrayElement(long index) throws InvalidArrayIndexException { - if (!isArrayElementReadable(index)) { - throw InvalidArrayIndexException.create(index); - } - if (index < variableIndex) { - // if we're in the inner-most scope, it's simply the variable on the index - return new Key(writeNodes[(int) index]); - } else { - // else it's a variable declared in the parent's scope, we start at parentBlockIndex - return new Key(writeNodes[(int) index - variableIndex + parentBlockIndex]); - } - } -} diff --git a/part-16/src/main/java/com/endoflineblog/truffle/part_15/runtime/nodes/LocalVarsScopeObject.java b/part-16/src/main/java/com/endoflineblog/truffle/part_15/runtime/nodes/LocalVarsScopeObject.java new file mode 100644 index 00000000..df329e20 --- /dev/null +++ b/part-16/src/main/java/com/endoflineblog/truffle/part_15/runtime/nodes/LocalVarsScopeObject.java @@ -0,0 +1,263 @@ +package com.endoflineblog.truffle.part_15.runtime.nodes; + +import com.endoflineblog.truffle.part_15.EasyScriptTruffleLanguage; +import com.endoflineblog.truffle.part_15.nodes.stmts.EasyScriptStmtNode; +import com.endoflineblog.truffle.part_15.nodes.stmts.blocks.BlockStmtNode; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.TruffleLanguage; +import com.oracle.truffle.api.dsl.Cached; +import com.oracle.truffle.api.dsl.Cached.Shared; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.frame.Frame; +import com.oracle.truffle.api.interop.InteropLibrary; +import com.oracle.truffle.api.interop.TruffleObject; +import com.oracle.truffle.api.interop.UnknownIdentifierException; +import com.oracle.truffle.api.interop.UnsupportedMessageException; +import com.oracle.truffle.api.library.ExportLibrary; +import com.oracle.truffle.api.library.ExportMessage; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.api.source.SourceSection; + +import java.util.Objects; + +@ExportLibrary(InteropLibrary.class) +public final class LocalVarsScopeObject implements TruffleObject { + static int MEMBER_CACHE_LIMIT = 4; + + private final Frame frame; + final boolean nodeEnter; + final EasyScriptStmtNode node; + final BlockStmtNode nodeParentBlock; + + public LocalVarsScopeObject(Frame frame, boolean nodeEnter, EasyScriptStmtNode node, BlockStmtNode nodeParentBlock) { + this.frame = frame; + this.nodeEnter = nodeEnter; + this.node = node; + this.nodeParentBlock = nodeParentBlock; + } + + @ExportMessage + boolean accepts( + @Cached(value = "this.node", adopt = false) EasyScriptStmtNode cachedNode, + @Cached(value = "this.nodeEnter") boolean cachedNodeEnter) { + return this.node == cachedNode && this.nodeEnter == cachedNodeEnter; + } + + @ExportMessage + boolean isScope() { + return true; + } + + @ExportMessage + boolean hasLanguage() { + return true; + } + + @ExportMessage + Class> getLanguage() { + return EasyScriptTruffleLanguage.class; + } + + @ExportMessage + Object toDisplayString( + @SuppressWarnings("unused") boolean allowSideEffects/*, + @Cached(value = "this.nodeParentBlock", adopt = false) @Shared("nodeParentBlock") @SuppressWarnings("unused") BlockStmtNode nodeParentBlock, + @Cached(value = "this.nodeParentBlock.findParentBlock()", adopt = false, allowUncached = true) @Shared("nodeGrandParentBlock") Node nodeGrandParentBlock*/ + ) { + // Cache the grandparent block for the fast-path access + // ToDo fix this somehow...? +// if (nodeGrandParentBlock instanceof BlockStmtNode) { +// return "block"; +// } else { +// return ((StmtBlockRootNode) nodeGrandParentBlock).getName(); +// } + return "block"; + } + + @ExportMessage + boolean hasScopeParent( + /*@Cached(value = "this.nodeParentBlock", adopt = false) @Shared("nodeParentBlock") @SuppressWarnings("unused") BlockStmtNode nodeParentBlock,*/ + @Cached(value = "this.nodeParentBlock.findParentBlock()", adopt = false, allowUncached = true) @Shared("nodeGrandParentBlock") Node nodeGrandParentBlock) { + return nodeGrandParentBlock instanceof BlockStmtNode; + } + + @ExportMessage + Object getScopeParent( + @Cached(value = "this.nodeParentBlock", adopt = false) /*@Shared("nodeParentBlock")*/ BlockStmtNode nodeParentBlock, + @Cached(value = "this.nodeParentBlock.findParentBlock()", adopt = false, allowUncached = true) @Shared("nodeGrandParentBlock") Node nodeGrandParentBlock) + throws UnsupportedMessageException { + if (nodeGrandParentBlock instanceof BlockStmtNode) { + return new LocalVarsScopeObject(frame, true, nodeParentBlock, (BlockStmtNode) nodeGrandParentBlock); + } + throw UnsupportedMessageException.create(); + } + + @ExportMessage + boolean hasSourceLocation() { + return this.getSourceLocation() != null; + } + + @ExportMessage +// @TruffleBoundary + SourceSection getSourceLocation() { + return this.nodeParentBlock.getSourceSection(); +// Node nodeGrandParentBlock = this.nodeParentBlock.findParentBlock(); +// if (nodeGrandParentBlock instanceof RootNode) { +// return nodeGrandParentBlock.getSourceSection(); +// } else { +// return this.nodeParentBlock.getSourceSection(); +// } + } + + @ExportMessage + boolean hasMembers() { + return true; + } + + @ExportMessage(name = "isMemberReadable") + static final class MemberReadable { + @Specialization(limit = "MEMBER_CACHE_LIMIT", guards = "cachedMember.equals(member)") + static boolean isMemberReadableCached( + @SuppressWarnings("unused") LocalVarsScopeObject receiver, + @SuppressWarnings("unused") String member, + @Cached("member") @SuppressWarnings("unused") String cachedMember, + // We cache the member existence for fast-path access + @Cached("isMemberReadableUncached(receiver, member)") boolean cachedResult) { + return cachedResult; + } + + @Specialization(replaces = "isMemberReadableCached") + @TruffleBoundary + static boolean isMemberReadableUncached(LocalVarsScopeObject receiver, String member) { + return receiver.hasLocalVarCalled(member); + } + } + + @ExportMessage(name = "isMemberModifiable") + static final class MemberModifiable { + @Specialization(limit = "MEMBER_CACHE_LIMIT", guards = "cachedMember.equals(member)") + static boolean isMemberModifiableCached( + @SuppressWarnings("unused") LocalVarsScopeObject receiver, + @SuppressWarnings("unused") String member, + @Cached("member") @SuppressWarnings("unused") String cachedMember, + // We cache the member existence for fast-path access + @Cached("isMemberModifiableUncached(receiver, member)") boolean cachedResult) { + return cachedResult; + } + + @Specialization(replaces = "isMemberModifiableCached") + @TruffleBoundary + static boolean isMemberModifiableUncached(LocalVarsScopeObject receiver, String member) { + return receiver.hasLocalVarCalled(member); + } + } + + @ExportMessage + boolean isMemberInsertable(@SuppressWarnings("unused") String member) { + return false; + } + + @ExportMessage(name = "readMember") + static final class ReadMember { + @Specialization(limit = "MEMBER_CACHE_LIMIT", guards = "cachedMember.equals(member)") + static Object readMemberCached( + LocalVarsScopeObject receiver, + @SuppressWarnings("unused") String member, + @Cached("member") String cachedMember, + // We cache the member's frame slot for fast-path access + @Cached("receiver.findLocalVarSlot(member)") int slot) + throws UnknownIdentifierException { + return readMember(receiver, cachedMember, slot); + } + + @Specialization(replaces = "readMemberCached") + @TruffleBoundary + static Object readMemberUncached(LocalVarsScopeObject receiver, String member) + throws UnknownIdentifierException { + int slot = receiver.findLocalVarSlot(member); + return readMember(receiver, member, slot); + } + + private static Object readMember(LocalVarsScopeObject receiver, String member, int slot) + throws UnknownIdentifierException { + if (slot == -1) { + throw UnknownIdentifierException.create(member); + } + return receiver.frame.getValue(slot); + } + } + + /** + * Write a variable value. Cache the write node by variable name for fast access. + */ + @ExportMessage(name = "writeMember") + static final class WriteMember { + /* + * If the member is cached, use the cached write node and use it to write the value. + * Call {@link #doGeneric(LocalVarsScopeObject, String, Object)} otherwise. + */ + @Specialization(limit = "MEMBER_CACHE_LIMIT", guards = "cachedMember.equals(member)") + static void writeMemberCached( + LocalVarsScopeObject receiver, + @SuppressWarnings("unused") String member, + Object value, + @Cached("member") String cachedMember, + // We cache the member's write node for fast-path access + @Cached(value = "receiver.findLocalVarRef(member)") RefObject ref) + throws UnknownIdentifierException { + writeMember(receiver, cachedMember, ref, value); + } + + /** + * The uncached version finds the write node and use it to write the value. + */ + @Specialization(replaces = "writeMemberCached") + @TruffleBoundary + static void writeMemberUncached(LocalVarsScopeObject receiver, String member, Object value) + throws UnknownIdentifierException { + RefObject ref = receiver.findLocalVarRef(member); + writeMember(receiver, member, ref, value); + } + + private static void writeMember(LocalVarsScopeObject receiver, String member, RefObject ref, Object value) + throws UnknownIdentifierException { + if (ref == null) { + throw UnknownIdentifierException.create(member); + } + receiver.frame.setObject(ref.refIndexOrSlot, value); + } + } + + /** + * Get the variables. Cache the array of write nodes that declare variables in the scope(s) + * and the indexes which determine visible variables. + */ + @ExportMessage + Object getMembers( + @SuppressWarnings("unused") boolean includeInternal, + @Cached(value = "this.nodeParentBlock.getLocalVarRefs()", dimensions = 1, allowUncached = true) RefObject[] references +// @Cached(value = "this.getVisibleVariablesIndex()", allowUncached = true) int visibleVariablesIndex, +// @Cached(value = "this.block.getParentBlockIndex()", allowUncached = true) int parentBlockIndex + ) { + return new RefObjectsArray(references, Integer.MAX_VALUE, Integer.MIN_VALUE); + } + + private boolean hasLocalVarCalled(String member) { + return this.findLocalVarRef(member) != null; + } + + int findLocalVarSlot(String member) { + RefObject refObject = this.findLocalVarRef(member); + return refObject == null ? -1 : refObject.refIndexOrSlot; + } + + RefObject findLocalVarRef(String member) { + RefObject[] localVarRefs = this.nodeParentBlock.getLocalVarRefs(); + for (RefObject localVarRef : localVarRefs) { + if (Objects.equals(member, localVarRef.refName)) { + return localVarRef; + } + } + return null; + } +} diff --git a/part-16/src/main/java/com/endoflineblog/truffle/part_15/runtime/nodes/RefObject.java b/part-16/src/main/java/com/endoflineblog/truffle/part_15/runtime/nodes/RefObject.java index 017716e2..c00801aa 100644 --- a/part-16/src/main/java/com/endoflineblog/truffle/part_15/runtime/nodes/RefObject.java +++ b/part-16/src/main/java/com/endoflineblog/truffle/part_15/runtime/nodes/RefObject.java @@ -11,10 +11,12 @@ @ExportLibrary(InteropLibrary.class) public final class RefObject implements TruffleObject { public final String refName; + public final int refIndexOrSlot; private final SourceSection refSourceSection; - public RefObject(String refName, SourceSection refSourceSection) { + public RefObject(String refName, int refIndexOrSlot, SourceSection refSourceSection) { this.refName = refName; + this.refIndexOrSlot = refIndexOrSlot; this.refSourceSection = refSourceSection; } diff --git a/part-16/src/main/java/com/endoflineblog/truffle/part_15/runtime/nodes/RefObjectsArray.java b/part-16/src/main/java/com/endoflineblog/truffle/part_15/runtime/nodes/RefObjectsArray.java index 1e1b93d7..76ec6128 100644 --- a/part-16/src/main/java/com/endoflineblog/truffle/part_15/runtime/nodes/RefObjectsArray.java +++ b/part-16/src/main/java/com/endoflineblog/truffle/part_15/runtime/nodes/RefObjectsArray.java @@ -10,13 +10,13 @@ @ExportLibrary(InteropLibrary.class) final class RefObjectsArray implements TruffleObject { @CompilationFinal(dimensions = 1) - private final RefObject[] refObjects; + private final RefObject[] references; private final int variableIndex; private final int parentBlockIndex; - RefObjectsArray(RefObject[] refObjects, int variableIndex, int parentBlockIndex) { - this.refObjects = refObjects; + RefObjectsArray(RefObject[] references, int variableIndex, int parentBlockIndex) { + this.references = references; this.variableIndex = variableIndex; this.parentBlockIndex = parentBlockIndex; } @@ -32,7 +32,7 @@ long getArraySize() { // variables in the inner-most scope visible by the current node (variableIndex). // return writeNodes.length - parentBlockIndex + variableIndex; long length = 0; - for (RefObject refObject : this.refObjects) { + for (RefObject refObject : this.references) { if (refObject != null) { length++; } @@ -43,16 +43,16 @@ long getArraySize() { @ExportMessage boolean isArrayElementReadable(long index) { int offsetIndex = this.offsetIndex(index); - return offsetIndex >= 0 && offsetIndex < this.refObjects.length; + return offsetIndex >= 0 && offsetIndex < this.references.length; } @ExportMessage Object readArrayElement(long index) throws InvalidArrayIndexException { int offsetIndex = this.offsetIndex(index); - if (offsetIndex >= 0 && offsetIndex < this.refObjects.length) { + if (offsetIndex >= 0 && offsetIndex < this.references.length) { // if the offset index is within the refObjects bounds, // we know for sure it points to a non-null refObject - return this.refObjects[offsetIndex]; + return this.references[offsetIndex]; } else { throw InvalidArrayIndexException.create(index); } @@ -60,14 +60,14 @@ Object readArrayElement(long index) throws InvalidArrayIndexException { private int offsetIndex(long index) { int ret = (int) index; - for (int i = 0; i < this.refObjects.length; i++) { + for (int i = 0; i < this.references.length; i++) { if (i > ret) { // once we're iterating past the desired index, // we can safely stop break; } // otherwise, if we encounter a gap, we need to shift the index to the right - if (this.refObjects[i] == null) { + if (this.references[i] == null) { ret++; } } diff --git a/part-16/src/main/java/com/endoflineblog/truffle/part_15/runtime/nodes/VariablesObject.java b/part-16/src/main/java/com/endoflineblog/truffle/part_15/runtime/nodes/VariablesObject.java deleted file mode 100644 index 91e15bc3..00000000 --- a/part-16/src/main/java/com/endoflineblog/truffle/part_15/runtime/nodes/VariablesObject.java +++ /dev/null @@ -1,350 +0,0 @@ -package com.endoflineblog.truffle.part_15.runtime.nodes; - -import com.endoflineblog.truffle.part_15.EasyScriptTruffleLanguage; -import com.endoflineblog.truffle.part_15.nodes.exprs.variables.LocalVarAssignmentExprNode; -import com.endoflineblog.truffle.part_15.nodes.root.StmtBlockRootNode; -import com.endoflineblog.truffle.part_15.nodes.stmts.EasyScriptStmtNode; -import com.endoflineblog.truffle.part_15.nodes.stmts.blocks.BlockStmtNode; -import com.endoflineblog.truffle.part_15.runtime.Undefined; -import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.TruffleLanguage; -import com.oracle.truffle.api.dsl.Cached; -import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.api.frame.Frame; -import com.oracle.truffle.api.interop.InteropLibrary; -import com.oracle.truffle.api.interop.TruffleObject; -import com.oracle.truffle.api.interop.UnknownIdentifierException; -import com.oracle.truffle.api.interop.UnsupportedMessageException; -import com.oracle.truffle.api.library.ExportLibrary; -import com.oracle.truffle.api.library.ExportMessage; -import com.oracle.truffle.api.nodes.Node; -import com.oracle.truffle.api.nodes.RootNode; -import com.oracle.truffle.api.source.SourceSection; - -import java.util.Objects; - -/** - * Scope of all variables accessible in the scope from the entered or exited node. - */ -@ExportLibrary(InteropLibrary.class) -public final class VariablesObject implements TruffleObject { - /** - * The member caching limit. - */ - static int LIMIT = 4; - - private final Frame frame; // the current frame - final EasyScriptStmtNode node; // the current node - final boolean nodeEnter; // whether the node was entered or is about to be exited - final BlockStmtNode block; // the inner-most block of the current node - - public VariablesObject(Frame frame, EasyScriptStmtNode node, boolean nodeEnter, BlockStmtNode blockNode) { - this.frame = frame; - this.node = node; - this.nodeEnter = nodeEnter; - this.block = blockNode; - } - - /** - * For performance reasons, fix the library implementation for the current node and enter - * flag. - */ - @ExportMessage - boolean accepts( - @Cached(value = "this.node", adopt = false) EasyScriptStmtNode cachedNode, - @Cached(value = "this.nodeEnter") boolean cachedNodeEnter) { - return this.node == cachedNode && this.nodeEnter == cachedNodeEnter; - } - - /** - * This is a scope object, providing variables as members. - */ - @ExportMessage - boolean isScope() { - return true; - } - - /** - * The scope must provide an associated language. - */ - @ExportMessage - boolean hasLanguage() { - return true; - } - - @ExportMessage - Class> getLanguage() { - return EasyScriptTruffleLanguage.class; - } - - /** - * Provide either "block", or the function name as the scope's display string. - */ - @ExportMessage - Object toDisplayString( - @SuppressWarnings("unused") boolean allowSideEffects, - @Cached.Shared("block") @Cached(value = "this.block", adopt = false) @SuppressWarnings("unused") BlockStmtNode cachedBlock, - @Cached.Shared("parentBlock") @Cached(value = "this.block.findBlock()", adopt = false, allowUncached = true) Node parentBlock) { - // Cache the parent block for the fast-path access - if (parentBlock instanceof BlockStmtNode) { - return "block"; - } else { - return ((StmtBlockRootNode) parentBlock).getName(); - } - } - - /** - * There is a parent scope if we're in a block. - */ - @ExportMessage - boolean hasScopeParent( - @Cached.Shared("block") @Cached(value = "this.block", adopt = false) @SuppressWarnings("unused") BlockStmtNode cachedBlock, - @Cached.Shared("parentBlock") @Cached(value = "this.block.findBlock()", adopt = false, allowUncached = true) Node parentBlock) { - // Cache the parent block for the fast-path access - return parentBlock instanceof BlockStmtNode; - } - - /** - * The parent scope object is based on the parent block node. - */ - @ExportMessage - Object getScopeParent( - @Cached.Shared("block") @Cached(value = "this.block", adopt = false) BlockStmtNode cachedBlock, - @Cached.Shared("parentBlock") @Cached(value = "this.block.findBlock()", adopt = false, allowUncached = true) Node parentBlock) - throws UnsupportedMessageException { - // Cache the parent block for the fast-path access - if (!(parentBlock instanceof BlockStmtNode)) { - throw UnsupportedMessageException.create(); - } - return new VariablesObject(frame, cachedBlock, true, (BlockStmtNode) parentBlock); - } - - /** - * We provide a source section of this scope. - */ - @ExportMessage - boolean hasSourceLocation() { - return true; - } - - /** - * The source section of this scope is either the block, or the function. - */ - @ExportMessage - @TruffleBoundary - SourceSection getSourceLocation() { - Node parentBlock = block.findBlock(); - if (parentBlock instanceof RootNode) { - // We're in the function block - assert parentBlock instanceof StmtBlockRootNode : String.format("In SLLanguage we expect StmtBlockRootNode, not %s", parentBlock.getClass()); - return parentBlock.getSourceSection(); - } else { - return block.getSourceSection(); - } - } - - /** - * Scope must provide scope members. - */ - @ExportMessage - boolean hasMembers() { - return true; - } - - /** - * Test if a member exists. We cache the result for fast access. - */ - @ExportMessage(name = "isMemberReadable") - static final class ExistsMember { - /** - * If the member is cached, provide the cached result. Call - * {@link #doGeneric(VariablesObject, String)} otherwise. - */ - @Specialization(limit = "LIMIT", guards = {"cachedMember.equals(member)"}) - static boolean doCached(VariablesObject receiver, String member, - @Cached("member") @SuppressWarnings("unused") String cachedMember, - // We cache the member existence for fast-path access - @Cached("doGeneric(receiver, member)") boolean cachedResult) { - assert cachedResult == doGeneric(receiver, member); - return cachedResult; - } - - /** - * Test if a variable with that name exists. It exists if we have a corresponding write - * node. - */ - @Specialization(replaces = "doCached") - @TruffleBoundary - static boolean doGeneric(VariablesObject receiver, String member) { - return receiver.hasWriteNode(member); - } - } - - /** - * Test if a member is modifiable. We cache the result for fast access. - */ - @ExportMessage(name = "isMemberModifiable") - static final class ModifiableMember { - @Specialization(limit = "LIMIT", guards = {"cachedMember.equals(member)"}) - static boolean doCached( - VariablesObject receiver, - @SuppressWarnings("unused") String member, - @Cached("member") @SuppressWarnings("unused") String cachedMember, - // We cache the member existence for fast-path access - @Cached("receiver.hasWriteNode(member)") boolean cachedResult) { - return cachedResult && receiver.frame != null; - } - - /** - * Test if a variable with that name exists and we have a frame. - */ - @Specialization(replaces = "doCached") - @TruffleBoundary - static boolean doGeneric(VariablesObject receiver, String member) { - return receiver.hasWriteNode(member) && receiver.frame != null; - } - } - - /** - * We do not support insertion of new variables. - */ - @ExportMessage - boolean isMemberInsertable(@SuppressWarnings("unused") String member) { - return false; - } - - /** - * Read a variable value. Cache the frame slot by variable name for fast access. - */ - @ExportMessage(name = "readMember") - static final class ReadMember { - /** - * If the member is cached, use the cached frame slot and read the value from it. Call - * {@link #doGeneric(VariablesObject, String)} otherwise. - */ - @Specialization(limit = "LIMIT", guards = {"cachedMember.equals(member)"}) - static Object doCached(VariablesObject receiver, - @SuppressWarnings("unused") String member, - @Cached("member") String cachedMember, - // We cache the member's frame slot for fast-path access - @Cached("receiver.findSlot(member)") int slot) throws UnknownIdentifierException { - return doRead(receiver, cachedMember, slot); - } - - /** - * The uncached version finds the member's slot and read the value from it. - */ - @Specialization(replaces = "doCached") - @TruffleBoundary - static Object doGeneric(VariablesObject receiver, String member) throws UnknownIdentifierException { - int slot = receiver.findSlot(member); - return doRead(receiver, member, slot); - } - - private static Object doRead(VariablesObject receiver, String member, int slot) throws UnknownIdentifierException { - if (slot == -1) { - throw UnknownIdentifierException.create(member); - } - if (receiver.frame != null) { - return receiver.frame.getValue(slot); - } else { - return Undefined.INSTANCE; - } - } - } - - @ExportMessage - void writeMember( - @SuppressWarnings("unused") String member, - @SuppressWarnings("unused") Object value) throws - UnsupportedMessageException { - throw UnsupportedMessageException.create(); - } - -// /** -// * Write a variable value. Cache the write node by variable name for fast access. -// */ -// @ExportMessage(name = "writeMember") -// static final class WriteMember { -// /* -// * If the member is cached, use the cached write node and use it to write the value. -// * Call {@link #doGeneric(VariablesObject, String, Object)} otherwise. -// */ -// @Specialization(limit = "LIMIT", guards = {"cachedMember.equals(member)"}) -// static void doCached(VariablesObject receiver, String member, Object value, -// @Cached("member") String cachedMember, -// // We cache the member's write node for fast-path access -// @Cached(value = "receiver.findWriteNode(member)", adopt = false) LocalVarAssignmentExprNode writeNode) -// throws UnknownIdentifierException, UnsupportedMessageException { -// doWrite(receiver, cachedMember, writeNode, value); -// } -// -// /** -// * The uncached version finds the write node and use it to write the value. -// */ -// @Specialization(replaces = "doCached") -// @TruffleBoundary -// static void doGeneric(VariablesObject receiver, String member, Object value) -// throws UnknownIdentifierException, UnsupportedMessageException { -// LocalVarAssignmentExprNode writeNode = receiver.findWriteNode(member); -// doWrite(receiver, member, writeNode, value); -// } -// -// private static void doWrite(VariablesObject receiver, String member, LocalVarAssignmentExprNode writeNode, Object value) -// throws UnknownIdentifierException, UnsupportedMessageException { -// if (writeNode == null) { -// throw UnknownIdentifierException.create(member); -// } -// if (receiver.frame == null) { -// throw UnsupportedMessageException.create(); -// } -// writeNode.executeGeneric((VirtualFrame) receiver.frame, value); -// } -// } - - /** - * Get the variables. Cache the array of write nodes that declare variables in the scope(s) - * and the indexes which determine visible variables. - */ - @ExportMessage - Object getMembers( - @SuppressWarnings("unused") boolean includeInternal, - @Cached(value = "this.block.getDeclaredLocalVariables()", adopt = false, dimensions = 1, allowUncached = true) LocalVarAssignmentExprNode[] writeNodes -// @Cached(value = "this.getVisibleVariablesIndex()", allowUncached = true) int visibleVariablesIndex, -// @Cached(value = "this.block.getParentBlockIndex()", allowUncached = true) int parentBlockIndex - ) { - return new KeysArray(writeNodes, Integer.MAX_VALUE, Integer.MIN_VALUE); - } - - boolean hasWriteNode(String member) { - return findWriteNode(member) != null; - } - - int findSlot(String member) { - LocalVarAssignmentExprNode writeNode = findWriteNode(member); - if (writeNode != null) { - return writeNode.getFrameSlot(); - } else { - return -1; - } - } - - /** - * Find write node, which declares variable of the given name. Search through the variables - * declared in the block and its parents and return the first one that matches. - * - * @param member the variable name - */ - LocalVarAssignmentExprNode findWriteNode(String member) { - LocalVarAssignmentExprNode[] writeNodes = block.getDeclaredLocalVariables(); -// int parentBlockIndex = block.getParentBlockIndex(); -// int index = getVisibleVariablesIndex(); - for (int i = 0; i < writeNodes.length; i++) { - LocalVarAssignmentExprNode writeNode = writeNodes[i]; - if (Objects.equals(member, writeNode.getSlotName())) { - return writeNode; - } - } - return null; - } -}