From 5f42b0e762756a3e7c14b17c27e445477a23cb47 Mon Sep 17 00:00:00 2001 From: Stefan Marr Date: Thu, 26 Aug 2021 23:56:09 +0100 Subject: [PATCH 1/2] Add frame slot specialization in bytecode interpreter - simplify guards in ast interpreter, move them to Local Signed-off-by: Stefan Marr --- src/trufflesom/compiler/Variable.java | 45 +++++++ .../compiler/bc/BytecodeMethodGenContext.java | 8 +- .../interpreter/nodes/LocalVariableNode.java | 104 ++++------------ .../nodes/NonLocalVariableNode.java | 111 ++++------------- .../nodes/bc/BytecodeLoopNode.java | 113 +++++++++++------- .../interpreter/nodes/bc/LocalNode.java | 82 +++++++++++++ 6 files changed, 241 insertions(+), 222 deletions(-) create mode 100644 src/trufflesom/interpreter/nodes/bc/LocalNode.java diff --git a/src/trufflesom/compiler/Variable.java b/src/trufflesom/compiler/Variable.java index 9ace9be74..9a8eaaa66 100644 --- a/src/trufflesom/compiler/Variable.java +++ b/src/trufflesom/compiler/Variable.java @@ -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; @@ -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"); diff --git a/src/trufflesom/compiler/bc/BytecodeMethodGenContext.java b/src/trufflesom/compiler/bc/BytecodeMethodGenContext.java index b2f9e72b0..0cac73c5e 100644 --- a/src/trufflesom/compiler/bc/BytecodeMethodGenContext.java +++ b/src/trufflesom/compiler/bc/BytecodeMethodGenContext.java @@ -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; diff --git a/src/trufflesom/interpreter/nodes/LocalVariableNode.java b/src/trufflesom/interpreter/nodes/LocalVariableNode.java index 52663d48e..547daf153 100644 --- a/src/trufflesom/interpreter/nodes/LocalVariableNode.java +++ b/src/trufflesom/interpreter/nodes/LocalVariableNode.java @@ -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; @@ -17,21 +14,17 @@ public abstract class LocalVariableNode extends ExpressionNode implements Invocation { - 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 @@ -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 @@ -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); diff --git a/src/trufflesom/interpreter/nodes/NonLocalVariableNode.java b/src/trufflesom/interpreter/nodes/NonLocalVariableNode.java index 0e0a5f94d..fd877f17b 100644 --- a/src/trufflesom/interpreter/nodes/NonLocalVariableNode.java +++ b/src/trufflesom/interpreter/nodes/NonLocalVariableNode.java @@ -1,12 +1,7 @@ package trufflesom.interpreter.nodes; -import static trufflesom.interpreter.TruffleCompiler.transferToInterpreter; - 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; @@ -21,15 +16,11 @@ public abstract class NonLocalVariableNode extends ContextualNode implements Invocation { - protected final FrameSlot slot; - protected final Local local; - protected final FrameDescriptor descriptor; + protected final Local local; private NonLocalVariableNode(final int contextLevel, final Local local) { super(contextLevel); this.local = local; - this.descriptor = local.getFrameDescriptor(); - this.slot = local.getSlot(); } @Override @@ -43,51 +34,34 @@ public NonLocalVariableReadNode(final int contextLevel, final Local local) { super(contextLevel, 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 determineContext(frame).isBoolean(slot); - } - - protected boolean isLong(final VirtualFrame frame) { - return determineContext(frame).isLong(slot); - } - - protected boolean isDouble(final VirtualFrame frame) { - return determineContext(frame).isDouble(slot); - } - - protected boolean isObject(final VirtualFrame frame) { - return determineContext(frame).isObject(slot); - } - - @Specialization(guards = {"isBoolean(frame)"}, rewriteOn = {FrameSlotTypeException.class}) + @Specialization(guards = {"determineContext(frame).isBoolean(local.getSlot())"}, + rewriteOn = {FrameSlotTypeException.class}) public final boolean doBoolean(final VirtualFrame frame) throws FrameSlotTypeException { - return determineContext(frame).getBoolean(slot); + return determineContext(frame).getBoolean(local.getSlot()); } - @Specialization(guards = {"isLong(frame)"}, rewriteOn = {FrameSlotTypeException.class}) + @Specialization(guards = {"determineContext(frame).isLong(local.getSlot())"}, + rewriteOn = {FrameSlotTypeException.class}) public final long doLong(final VirtualFrame frame) throws FrameSlotTypeException { - return determineContext(frame).getLong(slot); + return determineContext(frame).getLong(local.getSlot()); } - @Specialization(guards = {"isDouble(frame)"}, rewriteOn = {FrameSlotTypeException.class}) + @Specialization(guards = {"determineContext(frame).isDouble(local.getSlot())"}, + rewriteOn = {FrameSlotTypeException.class}) public final double doDouble(final VirtualFrame frame) throws FrameSlotTypeException { - return determineContext(frame).getDouble(slot); + return determineContext(frame).getDouble(local.getSlot()); } - @Specialization(guards = {"isObject(frame)"}, + @Specialization(guards = {"determineContext(frame).isObject(local.getSlot())"}, replaces = {"doBoolean", "doLong", "doDouble"}, rewriteOn = {FrameSlotTypeException.class}) public final Object doObject(final VirtualFrame frame) throws FrameSlotTypeException { - return determineContext(frame).getObject(slot); - } - - protected final boolean isUninitialized(final VirtualFrame frame) { - return descriptor.getFrameSlotKind(slot) == FrameSlotKind.Illegal; + return determineContext(frame).getObject(local.getSlot()); } @Override @@ -105,74 +79,31 @@ public NonLocalVariableWriteNode(final int contextLevel, final Local local) { public abstract ExpressionNode getExp(); - @Specialization(guards = "isBoolKind(frame)") + @Specialization(guards = "local.isBoolKind(frame)") public final boolean writeBoolean(final VirtualFrame frame, final boolean expValue) { - determineContext(frame).setBoolean(slot, expValue); + determineContext(frame).setBoolean(local.getSlot(), expValue); return expValue; } - @Specialization(guards = "isLongKind(frame)") + @Specialization(guards = "local.isLongKind(frame)") public final long writeLong(final VirtualFrame frame, final long expValue) { - determineContext(frame).setLong(slot, expValue); + determineContext(frame).setLong(local.getSlot(), expValue); return expValue; } - @Specialization(guards = "isDoubleKind(frame)") + @Specialization(guards = "local.isDoubleKind(frame)") public final double writeDouble(final VirtualFrame frame, final double expValue) { - determineContext(frame).setDouble(slot, expValue); + determineContext(frame).setDouble(local.getSlot(), expValue); return expValue; } @Specialization(replaces = {"writeBoolean", "writeLong", "writeDouble"}) public final Object writeGeneric(final VirtualFrame frame, final Object expValue) { - ensureObjectKind(); - determineContext(frame).setObject(slot, expValue); + local.makeObject(); + determineContext(frame).setObject(local.getSlot(), expValue); return expValue; } - protected final boolean isBoolKind(final VirtualFrame frame) { - if (descriptor.getFrameSlotKind(slot) == FrameSlotKind.Boolean) { - return true; - } - if (descriptor.getFrameSlotKind(slot) == FrameSlotKind.Illegal) { - transferToInterpreter("LocalVar.writeBoolToUninit"); - descriptor.setFrameSlotKind(slot, FrameSlotKind.Boolean); - return true; - } - return false; - } - - protected final boolean isLongKind(final VirtualFrame frame) { - if (descriptor.getFrameSlotKind(slot) == FrameSlotKind.Long) { - return true; - } - if (descriptor.getFrameSlotKind(slot) == FrameSlotKind.Illegal) { - transferToInterpreter("LocalVar.writeIntToUninit"); - descriptor.setFrameSlotKind(slot, FrameSlotKind.Long); - return true; - } - return false; - } - - protected final boolean isDoubleKind(final VirtualFrame frame) { - if (descriptor.getFrameSlotKind(slot) == FrameSlotKind.Double) { - return true; - } - if (descriptor.getFrameSlotKind(slot) == FrameSlotKind.Illegal) { - transferToInterpreter("LocalVar.writeDoubleToUninit"); - descriptor.setFrameSlotKind(slot, FrameSlotKind.Double); - return true; - } - return false; - } - - protected final void ensureObjectKind() { - if (descriptor.getFrameSlotKind(slot) != FrameSlotKind.Object) { - transferToInterpreter("LocalVar.writeObjectToUninit"); - descriptor.setFrameSlotKind(slot, FrameSlotKind.Object); - } - } - @Override public void replaceAfterScopeChange(final ScopeAdaptationVisitor inliner) { inliner.updateWrite(local, this, getExp(), contextLevel); diff --git a/src/trufflesom/interpreter/nodes/bc/BytecodeLoopNode.java b/src/trufflesom/interpreter/nodes/bc/BytecodeLoopNode.java index 97c031ba0..b5807967a 100644 --- a/src/trufflesom/interpreter/nodes/bc/BytecodeLoopNode.java +++ b/src/trufflesom/interpreter/nodes/bc/BytecodeLoopNode.java @@ -121,6 +121,10 @@ import trufflesom.interpreter.nodes.MessageSendNode; import trufflesom.interpreter.nodes.MessageSendNode.AbstractMessageSendNode; import trufflesom.interpreter.nodes.MessageSendNode.GenericMessageSendNode; +import trufflesom.interpreter.nodes.bc.LocalNode.LocalPop; +import trufflesom.interpreter.nodes.bc.LocalNode.LocalPush; +import trufflesom.interpreter.nodes.bc.LocalNodeFactory.LocalPopNodeGen; +import trufflesom.interpreter.nodes.bc.LocalNodeFactory.LocalPushNodeGen; import trufflesom.interpreter.nodes.literals.IntegerLiteralNode; import trufflesom.interpreter.nodes.literals.LiteralNode; import trufflesom.interpreter.nodes.nary.BinaryExpressionNode; @@ -147,9 +151,9 @@ public class BytecodeLoopNode extends ExpressionNode implements ScopeReference { private static final ValueProfile frameType = ValueProfile.createClassProfile(); private static final LiteralNode dummyNode = new IntegerLiteralNode(0); - @CompilationFinal(dimensions = 1) private final byte[] bytecodes; - @CompilationFinal(dimensions = 1) private final FrameSlot[] localsAndOuters; - @CompilationFinal(dimensions = 1) private final Object[] literalsAndConstants; + @CompilationFinal(dimensions = 1) private final byte[] bytecodes; + @CompilationFinal(dimensions = 1) private final Local[] localsAndOuters; + @CompilationFinal(dimensions = 1) private final Object[] literalsAndConstants; @CompilationFinal(dimensions = 1) private final BackJump[] inlinedLoops; @@ -162,7 +166,7 @@ public class BytecodeLoopNode extends ExpressionNode implements ScopeReference { private final FrameSlot frameOnStackMarker; public BytecodeLoopNode(final byte[] bytecodes, final int numLocals, - final FrameSlot[] localsAndOuters, final Object[] literals, final int maxStackDepth, + final Local[] localsAndOuters, final Object[] literals, final int maxStackDepth, final FrameSlot frameOnStackMarker, final BackJump[] inlinedLoops, final Universe universe) { this.bytecodes = bytecodes; @@ -180,13 +184,13 @@ public BytecodeLoopNode(final byte[] bytecodes, final int numLocals, @Override public Node deepCopy() { - return new BytecodeLoopNode( - bytecodes.clone(), numLocals, localsAndOuters, literalsAndConstants, - maxStackDepth, frameOnStackMarker, inlinedLoops, universe).initialize(sourceSection); + return new BytecodeLoopNode(bytecodes.clone(), numLocals, localsAndOuters, + literalsAndConstants, maxStackDepth, frameOnStackMarker, inlinedLoops, + universe).initialize(sourceSection); } public String getNameOfLocal(final int idx) { - Local l = (Local) localsAndOuters[idx].getIdentifier(); + Local l = localsAndOuters[idx]; return l.name.getString(); } @@ -264,6 +268,9 @@ public Object executeGeneric(final VirtualFrame frame) { } case PUSH_LOCAL: { + if (quickened[bytecodeIndex] == null) { + quickened[bytecodeIndex] = LocalPushNodeGen.create(); + } byte localIdx = bytecodes[bytecodeIndex + 1]; byte contextIdx = bytecodes[bytecodeIndex + 2]; @@ -271,27 +278,41 @@ public Object executeGeneric(final VirtualFrame frame) { if (contextIdx > 0) { currentOrContext = determineContext(currentOrContext, contextIdx); } - FrameSlot slot = localsAndOuters[localIdx]; - Object value = currentOrContext.getValue(slot); stackPointer += 1; - stack[stackPointer] = value; + stack[stackPointer] = ((LocalPush) quickened[bytecodeIndex]).execute( + currentOrContext, localsAndOuters[localIdx]); break; } case PUSH_LOCAL_0: { + if (quickened[bytecodeIndex] == null) { + quickened[bytecodeIndex] = LocalPushNodeGen.create(); + } + stackPointer += 1; - stack[stackPointer] = frame.getValue(localsAndOuters[0]); + stack[stackPointer] = + ((LocalPush) quickened[bytecodeIndex]).execute(frame, localsAndOuters[0]); break; } case PUSH_LOCAL_1: { + if (quickened[bytecodeIndex] == null) { + quickened[bytecodeIndex] = LocalPushNodeGen.create(); + } + stackPointer += 1; - stack[stackPointer] = frame.getValue(localsAndOuters[1]); + stack[stackPointer] = + ((LocalPush) quickened[bytecodeIndex]).execute(frame, localsAndOuters[1]); break; } case PUSH_LOCAL_2: { + if (quickened[bytecodeIndex] == null) { + quickened[bytecodeIndex] = LocalPushNodeGen.create(); + } + stackPointer += 1; - stack[stackPointer] = frame.getValue(localsAndOuters[2]); + stack[stackPointer] = + ((LocalPush) quickened[bytecodeIndex]).execute(frame, localsAndOuters[2]); break; } @@ -455,6 +476,10 @@ public Object executeGeneric(final VirtualFrame frame) { } case POP_LOCAL: { + if (quickened[bytecodeIndex] == null) { + quickened[bytecodeIndex] = LocalPopNodeGen.create(); + } + byte localIdx = bytecodes[bytecodeIndex + 1]; byte contextIdx = bytecodes[bytecodeIndex + 2]; @@ -463,27 +488,39 @@ public Object executeGeneric(final VirtualFrame frame) { currentOrContext = determineContext(currentOrContext, contextIdx); } - FrameSlot slot = localsAndOuters[localIdx]; - - Object value = stack[stackPointer]; + ((LocalPop) quickened[bytecodeIndex]).execute(currentOrContext, + localsAndOuters[localIdx], stack[stackPointer]); stackPointer -= 1; - - currentOrContext.setObject(slot, value); break; } case POP_LOCAL_0: { - frame.setObject(localsAndOuters[0], stack[stackPointer]); + if (quickened[bytecodeIndex] == null) { + quickened[bytecodeIndex] = LocalPopNodeGen.create(); + } + + ((LocalPop) quickened[bytecodeIndex]).execute(frame, localsAndOuters[0], + stack[stackPointer]); stackPointer -= 1; break; } case POP_LOCAL_1: { - frame.setObject(localsAndOuters[1], stack[stackPointer]); + if (quickened[bytecodeIndex] == null) { + quickened[bytecodeIndex] = LocalPopNodeGen.create(); + } + + ((LocalPop) quickened[bytecodeIndex]).execute(frame, localsAndOuters[1], + stack[stackPointer]); stackPointer -= 1; break; } case POP_LOCAL_2: { - frame.setObject(localsAndOuters[2], stack[stackPointer]); + if (quickened[bytecodeIndex] == null) { + quickened[bytecodeIndex] = LocalPopNodeGen.create(); + } + + ((LocalPop) quickened[bytecodeIndex]).execute(frame, localsAndOuters[2], + stack[stackPointer]); stackPointer -= 1; break; } @@ -1281,9 +1318,7 @@ private void inlineInto(final BytecodeMethodGenContext mgenc, final int targetCo case PUSH_LOCAL: { byte localIdx = bytecodes[i + 1]; - FrameSlot frameSlot = localsAndOuters[localIdx]; - Local local = (Local) frameSlot.getIdentifier(); - local.emitPush(mgenc); + localsAndOuters[localIdx].emitPush(mgenc); break; } @@ -1291,9 +1326,7 @@ private void inlineInto(final BytecodeMethodGenContext mgenc, final int targetCo case PUSH_LOCAL_1: case PUSH_LOCAL_2: { byte localIdx = (byte) (bytecode - PUSH_LOCAL_0); - FrameSlot frameSlot = localsAndOuters[localIdx]; - Local local = (Local) frameSlot.getIdentifier(); - local.emitPush(mgenc); + localsAndOuters[localIdx].emitPush(mgenc); break; } @@ -1372,9 +1405,7 @@ private void inlineInto(final BytecodeMethodGenContext mgenc, final int targetCo case POP_LOCAL: { byte localIdx = bytecodes[i + 1]; - FrameSlot frameSlot = localsAndOuters[localIdx]; - Local local = (Local) frameSlot.getIdentifier(); - local.emitPop(mgenc); + localsAndOuters[localIdx].emitPop(mgenc); break; } @@ -1382,9 +1413,7 @@ private void inlineInto(final BytecodeMethodGenContext mgenc, final int targetCo case POP_LOCAL_1: case POP_LOCAL_2: { byte localIdx = (byte) (bytecode - POP_LOCAL_0); - FrameSlot frameSlot = localsAndOuters[localIdx]; - Local local = (Local) frameSlot.getIdentifier(); - local.emitPop(mgenc); + localsAndOuters[localIdx].emitPop(mgenc); break; } @@ -1508,7 +1537,7 @@ private void inlineInto(final BytecodeMethodGenContext mgenc, final int targetCo private void adapt(final ScopeAdaptationVisitor inliner, final boolean requiresChangesToContextLevels) { - FrameSlot[] oldLocalsAndOuters = Arrays.copyOf(localsAndOuters, localsAndOuters.length); + Local[] oldLocalsAndOuters = Arrays.copyOf(localsAndOuters, localsAndOuters.length); int i = 0; while (i < bytecodes.length) { @@ -1531,15 +1560,14 @@ private void adapt(final ScopeAdaptationVisitor inliner, } else { localIdx = (byte) (bytecode - PUSH_LOCAL_0); } - FrameSlot frameSlot = oldLocalsAndOuters[localIdx]; - Local local = (Local) frameSlot.getIdentifier(); - ScopeElement se = inliner.getAdaptedVar(local); + ScopeElement se = + inliner.getAdaptedVar(oldLocalsAndOuters[localIdx]); if (bytecode == PUSH_LOCAL) { bytecodes[i + 2] = (byte) se.contextLevel; assert bytecodes[i + 2] >= 0; } - localsAndOuters[localIdx] = ((Local) se.var).getSlot(); + localsAndOuters[localIdx] = (Local) se.var; break; } @@ -1602,15 +1630,14 @@ private void adapt(final ScopeAdaptationVisitor inliner, } else { localIdx = (byte) (bytecode - POP_LOCAL_0); } - FrameSlot frameSlot = oldLocalsAndOuters[localIdx]; - Local local = (Local) frameSlot.getIdentifier(); - ScopeElement se = inliner.getAdaptedVar(local); + ScopeElement se = + inliner.getAdaptedVar(oldLocalsAndOuters[localIdx]); if (bytecode == POP_LOCAL) { bytecodes[i + 2] = (byte) se.contextLevel; assert bytecodes[i + 2] >= 0; } - localsAndOuters[localIdx] = ((Local) se.var).getSlot(); + localsAndOuters[localIdx] = (Local) se.var; break; } diff --git a/src/trufflesom/interpreter/nodes/bc/LocalNode.java b/src/trufflesom/interpreter/nodes/bc/LocalNode.java new file mode 100644 index 000000000..c8108b8e9 --- /dev/null +++ b/src/trufflesom/interpreter/nodes/bc/LocalNode.java @@ -0,0 +1,82 @@ +package trufflesom.interpreter.nodes.bc; + +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.frame.FrameSlotTypeException; +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.nodes.Node; + +import trufflesom.compiler.Variable.Local; +import trufflesom.vm.constants.Nil; +import trufflesom.vmobjects.SObject; + + +public abstract class LocalNode { + public abstract static class LocalPush extends Node { + public abstract Object execute(VirtualFrame frame, Local local); + + @Specialization(guards = "local.isUninitialized(frame)") + public final SObject doNil(final VirtualFrame frame, final Local local) { + return Nil.nilObject; + } + + @Specialization(guards = {"frame.isBoolean(local.getSlot())"}, + rewriteOn = {FrameSlotTypeException.class}) + public final boolean doBoolean(final VirtualFrame frame, final Local local) + throws FrameSlotTypeException { + return frame.getBoolean(local.getSlot()); + } + + @Specialization(guards = {"frame.isLong(local.getSlot())"}, + rewriteOn = {FrameSlotTypeException.class}) + public final long doLong(final VirtualFrame frame, final Local local) + throws FrameSlotTypeException { + return frame.getLong(local.getSlot()); + } + + @Specialization(guards = {"frame.isDouble(local.getSlot())"}, + rewriteOn = {FrameSlotTypeException.class}) + public final double doDouble(final VirtualFrame frame, final Local local) + throws FrameSlotTypeException { + return frame.getDouble(local.getSlot()); + } + + @Specialization(guards = {"frame.isObject(local.getSlot())"}, + replaces = {"doBoolean", "doLong", "doDouble"}, + rewriteOn = {FrameSlotTypeException.class}) + public final Object doObject(final VirtualFrame frame, final Local local) + throws FrameSlotTypeException { + return frame.getObject(local.getSlot()); + } + } + + public abstract static class LocalPop extends Node { + + public abstract void execute(VirtualFrame frame, Local local, Object value); + + @Specialization(guards = "local.isBoolKind(frame)") + public final void writeBoolean(final VirtualFrame frame, final Local local, + final Boolean expValue) { + frame.setBoolean(local.getSlot(), expValue); + } + + @Specialization(guards = "local.isLongKind(frame)") + public final void writeLong(final VirtualFrame frame, final Local local, + final Long expValue) { + frame.setLong(local.getSlot(), expValue); + } + + @Specialization(guards = "local.isDoubleKind(frame)") + public final void writeDouble(final VirtualFrame frame, final Local local, + final Double expValue) { + frame.setDouble(local.getSlot(), expValue); + } + + @Specialization(replaces = {"writeBoolean", "writeLong", "writeDouble"}) + public final void writeGeneric(final VirtualFrame frame, final Local local, + final Object expValue) { + local.makeObject(); + frame.setObject(local.getSlot(), expValue); + } + + } +} From 2203e9b7827aa02119fd35b8dec8eb7e7172ddc9 Mon Sep 17 00:00:00 2001 From: Stefan Marr Date: Fri, 27 Aug 2021 00:05:10 +0100 Subject: [PATCH 2/2] Fix native image building Signed-off-by: Stefan Marr --- src/trufflesom/interpreter/nodes/bc/BytecodeLoopNode.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/trufflesom/interpreter/nodes/bc/BytecodeLoopNode.java b/src/trufflesom/interpreter/nodes/bc/BytecodeLoopNode.java index b5807967a..b749ba30d 100644 --- a/src/trufflesom/interpreter/nodes/bc/BytecodeLoopNode.java +++ b/src/trufflesom/interpreter/nodes/bc/BytecodeLoopNode.java @@ -269,6 +269,7 @@ public Object executeGeneric(final VirtualFrame frame) { case PUSH_LOCAL: { if (quickened[bytecodeIndex] == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); quickened[bytecodeIndex] = LocalPushNodeGen.create(); } byte localIdx = bytecodes[bytecodeIndex + 1]; @@ -287,6 +288,7 @@ public Object executeGeneric(final VirtualFrame frame) { case PUSH_LOCAL_0: { if (quickened[bytecodeIndex] == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); quickened[bytecodeIndex] = LocalPushNodeGen.create(); } @@ -297,6 +299,7 @@ public Object executeGeneric(final VirtualFrame frame) { } case PUSH_LOCAL_1: { if (quickened[bytecodeIndex] == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); quickened[bytecodeIndex] = LocalPushNodeGen.create(); } @@ -307,6 +310,7 @@ public Object executeGeneric(final VirtualFrame frame) { } case PUSH_LOCAL_2: { if (quickened[bytecodeIndex] == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); quickened[bytecodeIndex] = LocalPushNodeGen.create(); } @@ -477,6 +481,7 @@ public Object executeGeneric(final VirtualFrame frame) { case POP_LOCAL: { if (quickened[bytecodeIndex] == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); quickened[bytecodeIndex] = LocalPopNodeGen.create(); } @@ -496,6 +501,7 @@ public Object executeGeneric(final VirtualFrame frame) { case POP_LOCAL_0: { if (quickened[bytecodeIndex] == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); quickened[bytecodeIndex] = LocalPopNodeGen.create(); } @@ -506,6 +512,7 @@ public Object executeGeneric(final VirtualFrame frame) { } case POP_LOCAL_1: { if (quickened[bytecodeIndex] == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); quickened[bytecodeIndex] = LocalPopNodeGen.create(); } @@ -516,6 +523,7 @@ public Object executeGeneric(final VirtualFrame frame) { } case POP_LOCAL_2: { if (quickened[bytecodeIndex] == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); quickened[bytecodeIndex] = LocalPopNodeGen.create(); }