Skip to content

Commit

Permalink
Added supernodes for < and > comparsion of an expression or argument …
Browse files Browse the repository at this point in the history
…with a constant

Signed-off-by: Stefan Marr <[email protected]>
  • Loading branch information
smarr committed Oct 5, 2024
1 parent 99004b7 commit 8f85a37
Show file tree
Hide file tree
Showing 6 changed files with 403 additions and 0 deletions.
18 changes: 18 additions & 0 deletions src/trufflesom/src/trufflesom/compiler/ParserAst.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@
import trufflesom.interpreter.nodes.literals.GenericLiteralNode;
import trufflesom.interpreter.nodes.literals.IntegerLiteralNode;
import trufflesom.interpreter.nodes.literals.LiteralNode;
import trufflesom.interpreter.supernodes.compare.GreaterThanIntNodeGen;
import trufflesom.interpreter.supernodes.compare.LessThanIntNodeGen;
import trufflesom.interpreter.supernodes.compare.LocalArgGreaterThanInt;
import trufflesom.interpreter.supernodes.compare.LocalArgLessThanInt;
import trufflesom.interpreter.supernodes.compare.LocalFieldStringEqualsNode;
import trufflesom.interpreter.supernodes.LocalVariableSquareNodeGen;
import trufflesom.interpreter.supernodes.compare.NonLocalFieldStringEqualsNode;
Expand Down Expand Up @@ -329,6 +333,20 @@ protected ExpressionNode binaryMessage(final MethodGenerationContext mgenc,
} else if (msg == SymbolTable.symMinus && operand instanceof IntegerLiteralNode lit) {
long litValue = lit.executeLong(null);
return IncExpWithValueNodeGen.create(-litValue, true, receiver).initialize(coordWithL);
} else if (binSelector.equals(">") && operand instanceof IntegerLiteralNode lit) {
long litValue = lit.executeLong(null);

if (receiver instanceof LocalArgumentReadNode arg) {
return new LocalArgGreaterThanInt(arg.getArg(), litValue).initialize(coordWithL);
}
return GreaterThanIntNodeGen.create(litValue, receiver).initialize(coordWithL);
} else if (binSelector.equals("<") && operand instanceof IntegerLiteralNode lit) {
long litValue = lit.executeLong(null);

if (receiver instanceof LocalArgumentReadNode arg) {
return new LocalArgLessThanInt(arg.getArg(), litValue).initialize(coordWithL);
}
return LessThanIntNodeGen.create(litValue, receiver).initialize(coordWithL);
}

ExpressionNode inlined =
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package trufflesom.interpreter.supernodes.compare;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.dsl.Fallback;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.VirtualFrame;
import trufflesom.interpreter.bc.RespecializeException;
import trufflesom.interpreter.nodes.ExpressionNode;
import trufflesom.interpreter.nodes.GenericMessageSendNode;
import trufflesom.interpreter.nodes.MessageSendNode;
import trufflesom.interpreter.nodes.bc.BytecodeLoopNode;
import trufflesom.interpreter.nodes.literals.IntegerLiteralNode;
import trufflesom.interpreter.nodes.nary.UnaryExpressionNode;
import trufflesom.vm.SymbolTable;
import trufflesom.vm.VmSettings;
import trufflesom.vmobjects.SSymbol;


public abstract class GreaterThanIntNode extends UnaryExpressionNode {
private final long intValue;

public GreaterThanIntNode(final long intValue) {
this.intValue = intValue;
}

@Override
public abstract ExpressionNode getReceiver();

@Specialization
public final boolean doLong(final long rcvr) {
return rcvr > intValue;
}

@Specialization
public final boolean doDouble(final double rcvr) {
return rcvr > intValue;
}

@Fallback
public final Object makeGenericSend(final VirtualFrame frame,
final Object receiver) {
CompilerDirectives.transferToInterpreterAndInvalidate();
return makeGenericSend(SymbolTable.symbolFor(">")).doPreEvaluated(frame,
new Object[] {receiver, intValue});
}

@Override
protected GenericMessageSendNode makeGenericSend(final SSymbol selector) {
CompilerDirectives.transferToInterpreterAndInvalidate();
GenericMessageSendNode send = MessageSendNode.createGeneric(selector,
new ExpressionNode[] {getReceiver(), new IntegerLiteralNode(intValue)}, sourceCoord);

if (VmSettings.UseAstInterp) {
replace(send);
send.notifyDispatchInserted();
return send;
}

assert getParent() instanceof BytecodeLoopNode : "This node was expected to be a direct child of a `BytecodeLoopNode`.";
throw new RespecializeException(send);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package trufflesom.interpreter.supernodes.compare;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.dsl.Fallback;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.VirtualFrame;
import trufflesom.interpreter.bc.RespecializeException;
import trufflesom.interpreter.nodes.ExpressionNode;
import trufflesom.interpreter.nodes.GenericMessageSendNode;
import trufflesom.interpreter.nodes.MessageSendNode;
import trufflesom.interpreter.nodes.bc.BytecodeLoopNode;
import trufflesom.interpreter.nodes.literals.IntegerLiteralNode;
import trufflesom.interpreter.nodes.nary.UnaryExpressionNode;
import trufflesom.vm.SymbolTable;
import trufflesom.vm.VmSettings;
import trufflesom.vmobjects.SSymbol;


public abstract class LessThanIntNode extends UnaryExpressionNode {
private final long intValue;

public LessThanIntNode(final long intValue) {
this.intValue = intValue;
}

@Override
public abstract ExpressionNode getReceiver();

@Specialization
public final boolean doLong(final long rcvr) {
return rcvr < intValue;
}

@Specialization
public final boolean doDouble(final double rcvr) {
return rcvr < intValue;
}

@Fallback
public final Object makeGenericSend(final VirtualFrame frame,
final Object receiver) {
CompilerDirectives.transferToInterpreterAndInvalidate();
return makeGenericSend(SymbolTable.symbolFor("<")).doPreEvaluated(frame,
new Object[] {receiver, intValue});
}

@Override
protected GenericMessageSendNode makeGenericSend(final SSymbol selector) {
CompilerDirectives.transferToInterpreterAndInvalidate();
GenericMessageSendNode send = MessageSendNode.createGeneric(selector,
new ExpressionNode[] {getReceiver(), new IntegerLiteralNode(intValue)}, sourceCoord);

if (VmSettings.UseAstInterp) {
replace(send);
send.notifyDispatchInserted();
return send;
}

assert getParent() instanceof BytecodeLoopNode : "This node was expected to be a direct child of a `BytecodeLoopNode`.";
throw new RespecializeException(send);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package trufflesom.interpreter.supernodes.compare;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.UnexpectedResultException;
import trufflesom.bdt.inlining.ScopeAdaptationVisitor;
import trufflesom.bdt.inlining.ScopeAdaptationVisitor.ScopeElement;
import trufflesom.compiler.Variable.Argument;
import trufflesom.interpreter.bc.RespecializeException;
import trufflesom.interpreter.nodes.ArgumentReadNode.LocalArgumentReadNode;
import trufflesom.interpreter.nodes.ExpressionNode;
import trufflesom.interpreter.nodes.GenericMessageSendNode;
import trufflesom.interpreter.nodes.MessageSendNode;
import trufflesom.interpreter.nodes.bc.BytecodeLoopNode;
import trufflesom.interpreter.nodes.literals.IntegerLiteralNode;
import trufflesom.vm.SymbolTable;
import trufflesom.vm.VmSettings;


public final class LocalArgGreaterThanInt extends ExpressionNode {
private final Argument arg;
private final int argIdx;
private final long intValue;

public LocalArgGreaterThanInt(final Argument arg, final long intValue) {
this.arg = arg;
this.argIdx = arg.index;
this.intValue = intValue;
}

@Override
public Object executeGeneric(final VirtualFrame frame) {
Object arg = frame.getArguments()[argIdx];
if (arg instanceof Long) {
long argVal = (Long) arg;
return argVal > intValue;
}

CompilerDirectives.transferToInterpreterAndInvalidate();
return fallbackGeneric(frame);
}

@Override
public Object doPreEvaluated(final VirtualFrame frame, final Object[] args) {
CompilerDirectives.transferToInterpreterAndInvalidate();
throw new UnsupportedOperationException();
}

@Override
public boolean executeBoolean(final VirtualFrame frame) throws UnexpectedResultException {
Object arg = frame.getArguments()[argIdx];
if (arg instanceof Long) {
long argVal = (Long) arg;
return argVal > intValue;
}

CompilerDirectives.transferToInterpreterAndInvalidate();
return fallbackBool(frame);
}

private boolean fallbackBool(final VirtualFrame frame) throws UnexpectedResultException {
Object result = makeGenericSend().doPreEvaluated(frame,
new Object[] {arg, intValue});
if (result instanceof Boolean) {
return (Boolean) result;
}
throw new UnexpectedResultException(result);
}

private Object fallbackGeneric(final VirtualFrame frame) {
return makeGenericSend().doPreEvaluated(frame,
new Object[] {arg, intValue});
}

protected GenericMessageSendNode makeGenericSend() {
CompilerDirectives.transferToInterpreterAndInvalidate();
GenericMessageSendNode send =
MessageSendNode.createGeneric(SymbolTable.symbolFor(">"), new ExpressionNode[] {
new LocalArgumentReadNode(arg), new IntegerLiteralNode(intValue)}, sourceCoord);

if (VmSettings.UseAstInterp) {
replace(send);
send.notifyDispatchInserted();
return send;
}

assert getParent() instanceof BytecodeLoopNode : "This node was expected to be a direct child of a `BytecodeLoopNode`.";
throw new RespecializeException(send);
}

@Override
public void replaceAfterScopeChange(final ScopeAdaptationVisitor inliner) {
ScopeElement se = inliner.getAdaptedVar(arg);
if (se.var != arg || se.contextLevel < 0) {
if (se.var instanceof Argument arg) {
replace(new LocalArgGreaterThanInt(arg, intValue).initialize(sourceCoord));
} else {
replace(MessageSendNode.createGeneric(SymbolTable.symbolFor(">"),
new ExpressionNode[] {se.var.getReadNode(se.contextLevel, sourceCoord),
new IntegerLiteralNode(intValue)},
sourceCoord));
}
} else {
assert 0 == se.contextLevel;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package trufflesom.interpreter.supernodes.compare;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.UnexpectedResultException;
import trufflesom.bdt.inlining.ScopeAdaptationVisitor;
import trufflesom.bdt.inlining.ScopeAdaptationVisitor.ScopeElement;
import trufflesom.compiler.Variable.Argument;
import trufflesom.interpreter.bc.RespecializeException;
import trufflesom.interpreter.nodes.ArgumentReadNode.LocalArgumentReadNode;
import trufflesom.interpreter.nodes.ExpressionNode;
import trufflesom.interpreter.nodes.GenericMessageSendNode;
import trufflesom.interpreter.nodes.MessageSendNode;
import trufflesom.interpreter.nodes.bc.BytecodeLoopNode;
import trufflesom.interpreter.nodes.literals.IntegerLiteralNode;
import trufflesom.vm.SymbolTable;
import trufflesom.vm.VmSettings;


public final class LocalArgLessThanInt extends ExpressionNode {
private final Argument arg;
private final int argIdx;
private final long intValue;

public LocalArgLessThanInt(final Argument arg, final long intValue) {
this.arg = arg;
this.argIdx = arg.index;
this.intValue = intValue;
}

@Override
public Object executeGeneric(final VirtualFrame frame) {
Object arg = frame.getArguments()[argIdx];
if (arg instanceof Long) {
long argVal = (Long) arg;
return argVal < intValue;
}

CompilerDirectives.transferToInterpreterAndInvalidate();
return fallbackGeneric(frame);
}

@Override
public Object doPreEvaluated(final VirtualFrame frame, final Object[] args) {
CompilerDirectives.transferToInterpreterAndInvalidate();
throw new UnsupportedOperationException();
}

@Override
public boolean executeBoolean(final VirtualFrame frame) throws UnexpectedResultException {
Object arg = frame.getArguments()[argIdx];
if (arg instanceof Long) {
long argVal = (Long) arg;
return argVal < intValue;
}

CompilerDirectives.transferToInterpreterAndInvalidate();
return fallbackBool(frame);
}

private boolean fallbackBool(final VirtualFrame frame) throws UnexpectedResultException {
Object result = makeGenericSend().doPreEvaluated(frame,
new Object[] {arg, intValue});
if (result instanceof Boolean) {
return (Boolean) result;
}
throw new UnexpectedResultException(result);
}

private Object fallbackGeneric(final VirtualFrame frame) {
return makeGenericSend().doPreEvaluated(frame, new Object[] {arg, intValue});
}

protected GenericMessageSendNode makeGenericSend() {
CompilerDirectives.transferToInterpreterAndInvalidate();
GenericMessageSendNode send =
MessageSendNode.createGeneric(SymbolTable.symbolFor("<"), new ExpressionNode[] {
new LocalArgumentReadNode(arg), new IntegerLiteralNode(intValue)}, sourceCoord);

if (VmSettings.UseAstInterp) {
replace(send);
send.notifyDispatchInserted();
return send;
}

assert getParent() instanceof BytecodeLoopNode : "This node was expected to be a direct child of a `BytecodeLoopNode`.";
throw new RespecializeException(send);
}

@Override
public void replaceAfterScopeChange(final ScopeAdaptationVisitor inliner) {
ScopeElement se = inliner.getAdaptedVar(arg);
if (se.var != arg || se.contextLevel < 0) {
if (se.var instanceof Argument a) {
replace(new LocalArgLessThanInt(a, intValue).initialize(sourceCoord));
} else {
replace(MessageSendNode.createGeneric(SymbolTable.symbolFor("<"),
new ExpressionNode[] {se.var.getReadNode(se.contextLevel, sourceCoord),
new IntegerLiteralNode(intValue)},
sourceCoord));
}
} else {
assert 0 == se.contextLevel;
}
}
}
Loading

0 comments on commit 8f85a37

Please sign in to comment.