Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Specialize frame slots in the bytecode interpreter #83

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions src/trufflesom/compiler/Variable.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import com.oracle.truffle.api.frame.FrameDescriptor;
import com.oracle.truffle.api.frame.FrameSlot;
import com.oracle.truffle.api.frame.FrameSlotKind;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.source.SourceSection;

import bd.inlining.NodeState;
Expand Down Expand Up @@ -163,6 +164,50 @@ public void init(final FrameSlot slot, final FrameDescriptor descriptor) {
this.descriptor = descriptor;
}

public boolean isBoolKind(final VirtualFrame frame) {
FrameSlotKind kind = descriptor.getFrameSlotKind(slot);
if (kind == FrameSlotKind.Boolean) {
return true;
}
if (kind == FrameSlotKind.Illegal) {
descriptor.setFrameSlotKind(slot, FrameSlotKind.Boolean);
return true;
}
return false;
}

public boolean isLongKind(final VirtualFrame frame) {
FrameSlotKind kind = descriptor.getFrameSlotKind(slot);
if (kind == FrameSlotKind.Long) {
return true;
}
if (kind == FrameSlotKind.Illegal) {
descriptor.setFrameSlotKind(slot, FrameSlotKind.Long);
return true;
}
return false;
}

public boolean isDoubleKind(final VirtualFrame frame) {
FrameSlotKind kind = descriptor.getFrameSlotKind(slot);
if (kind == FrameSlotKind.Double) {
return true;
}
if (kind == FrameSlotKind.Illegal) {
descriptor.setFrameSlotKind(slot, FrameSlotKind.Double);
return true;
}
return false;
}

public boolean isUninitialized(final VirtualFrame frame) {
return descriptor.getFrameSlotKind(slot) == FrameSlotKind.Illegal;
}

public void makeObject() {
descriptor.setFrameSlotKind(slot, FrameSlotKind.Object);
}

@Override
public ExpressionNode getReadNode(final int contextLevel, final SourceSection source) {
transferToInterpreterAndInvalidate("Variable.getReadNode");
Expand Down
8 changes: 1 addition & 7 deletions src/trufflesom/compiler/bc/BytecodeMethodGenContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -373,13 +373,7 @@ private BytecodeLoopNode constructBytecodeBody(final SourceSection sourceSection
byte[] bytecodes = getBytecodeArray();

Object[] literalsArr = literals.toArray();
FrameSlot[] localsAndOuters = new FrameSlot[localAndOuterVars.size()];

int i = 0;
for (Local l : localAndOuterVars.values()) {
localsAndOuters[i] = l.getSlot();
i += 1;
}
Local[] localsAndOuters = localAndOuterVars.values().toArray(new Local[0]);

FrameSlot frameOnStackMarker =
throwsNonLocalReturn ? getFrameOnStackMarker(sourceSection).getSlot() : null;
Expand Down
104 changes: 22 additions & 82 deletions src/trufflesom/interpreter/nodes/LocalVariableNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@

import com.oracle.truffle.api.dsl.NodeChild;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.FrameDescriptor;
import com.oracle.truffle.api.frame.FrameSlot;
import com.oracle.truffle.api.frame.FrameSlotKind;
import com.oracle.truffle.api.frame.FrameSlotTypeException;
import com.oracle.truffle.api.frame.VirtualFrame;

Expand All @@ -17,21 +14,17 @@


public abstract class LocalVariableNode extends ExpressionNode implements Invocation<SSymbol> {
protected final FrameSlot slot;
protected final FrameDescriptor descriptor;
protected final Local local;
protected final Local local;

// TODO: We currently assume that there is a 1:1 mapping between lexical contexts
// and frame descriptors, which is apparently not strictly true anymore in Truffle 1.0.0.
// Generally, we also need to revise everything in this area and address issue SOMns#240.
private LocalVariableNode(final Local local) {
this.local = local;
this.slot = local.getSlot();
this.descriptor = local.getFrameDescriptor();
}

public final Object getSlotIdentifier() {
return slot.getIdentifier();
return local.getSlot().getIdentifier();
}

@Override
Expand All @@ -49,51 +42,34 @@ public LocalVariableReadNode(final LocalVariableReadNode node) {
this(node.local);
}

@Specialization(guards = "isUninitialized(frame)")
@Specialization(guards = "local.isUninitialized(frame)")
public final SObject doNil(final VirtualFrame frame) {
return Nil.nilObject;
}

protected boolean isBoolean(final VirtualFrame frame) {
return frame.isBoolean(slot);
}

protected boolean isLong(final VirtualFrame frame) {
return frame.isLong(slot);
}

protected boolean isDouble(final VirtualFrame frame) {
return frame.isDouble(slot);
}

protected boolean isObject(final VirtualFrame frame) {
return frame.isObject(slot);
}

@Specialization(guards = {"isBoolean(frame)"}, rewriteOn = {FrameSlotTypeException.class})
@Specialization(guards = {"frame.isBoolean(local.getSlot())"},
rewriteOn = {FrameSlotTypeException.class})
public final boolean doBoolean(final VirtualFrame frame) throws FrameSlotTypeException {
return frame.getBoolean(slot);
return frame.getBoolean(local.getSlot());
}

@Specialization(guards = {"isLong(frame)"}, rewriteOn = {FrameSlotTypeException.class})
@Specialization(guards = {"frame.isLong(local.getSlot())"},
rewriteOn = {FrameSlotTypeException.class})
public final long doLong(final VirtualFrame frame) throws FrameSlotTypeException {
return frame.getLong(slot);
return frame.getLong(local.getSlot());
}

@Specialization(guards = {"isDouble(frame)"}, rewriteOn = {FrameSlotTypeException.class})
@Specialization(guards = {"frame.isDouble(local.getSlot())"},
rewriteOn = {FrameSlotTypeException.class})
public final double doDouble(final VirtualFrame frame) throws FrameSlotTypeException {
return frame.getDouble(slot);
return frame.getDouble(local.getSlot());
}

@Specialization(guards = {"isObject(frame)"},
@Specialization(guards = {"frame.isObject(local.getSlot())"},
replaces = {"doBoolean", "doLong", "doDouble"},
rewriteOn = {FrameSlotTypeException.class})
public final Object doObject(final VirtualFrame frame) throws FrameSlotTypeException {
return frame.getObject(slot);
}

protected final boolean isUninitialized(final VirtualFrame frame) {
return descriptor.getFrameSlotKind(slot) == FrameSlotKind.Illegal;
return frame.getObject(local.getSlot());
}

@Override
Expand All @@ -115,67 +91,31 @@ public LocalVariableWriteNode(final LocalVariableWriteNode node) {

public abstract ExpressionNode getExp();

@Specialization(guards = "isBoolKind(expValue)")
@Specialization(guards = "local.isBoolKind(frame)")
public final boolean writeBoolean(final VirtualFrame frame, final boolean expValue) {
frame.setBoolean(slot, expValue);
frame.setBoolean(local.getSlot(), expValue);
return expValue;
}

@Specialization(guards = "isLongKind(expValue)")
@Specialization(guards = "local.isLongKind(frame)")
public final long writeLong(final VirtualFrame frame, final long expValue) {
frame.setLong(slot, expValue);
frame.setLong(local.getSlot(), expValue);
return expValue;
}

@Specialization(guards = "isDoubleKind(expValue)")
@Specialization(guards = "local.isDoubleKind(frame)")
public final double writeDouble(final VirtualFrame frame, final double expValue) {
frame.setDouble(slot, expValue);
frame.setDouble(local.getSlot(), expValue);
return expValue;
}

@Specialization(replaces = {"writeBoolean", "writeLong", "writeDouble"})
public final Object writeGeneric(final VirtualFrame frame, final Object expValue) {
descriptor.setFrameSlotKind(slot, FrameSlotKind.Object);
frame.setObject(slot, expValue);
local.makeObject();
frame.setObject(local.getSlot(), expValue);
return expValue;
}

// uses expValue to make sure guard is not converted to assertion
protected final boolean isBoolKind(final boolean expValue) {
if (descriptor.getFrameSlotKind(slot) == FrameSlotKind.Boolean) {
return true;
}
if (descriptor.getFrameSlotKind(slot) == FrameSlotKind.Illegal) {
descriptor.setFrameSlotKind(slot, FrameSlotKind.Boolean);
return true;
}
return false;
}

// uses expValue to make sure guard is not converted to assertion
protected final boolean isLongKind(final long expValue) {
if (descriptor.getFrameSlotKind(slot) == FrameSlotKind.Long) {
return true;
}
if (descriptor.getFrameSlotKind(slot) == FrameSlotKind.Illegal) {
descriptor.setFrameSlotKind(slot, FrameSlotKind.Long);
return true;
}
return false;
}

// uses expValue to make sure guard is not converted to assertion
protected final boolean isDoubleKind(final double expValue) {
if (descriptor.getFrameSlotKind(slot) == FrameSlotKind.Double) {
return true;
}
if (descriptor.getFrameSlotKind(slot) == FrameSlotKind.Illegal) {
descriptor.setFrameSlotKind(slot, FrameSlotKind.Double);
return true;
}
return false;
}

@Override
public void replaceAfterScopeChange(final ScopeAdaptationVisitor inliner) {
inliner.updateWrite(local, this, getExp(), 0);
Expand Down
Loading