diff --git a/src/de.hpi.swa.trufflesqueak.test/src/de/hpi/swa/trufflesqueak/test/AbstractSqueakTestCase.java b/src/de.hpi.swa.trufflesqueak.test/src/de/hpi/swa/trufflesqueak/test/AbstractSqueakTestCase.java index c47cfcd3e..d58e8aaa1 100644 --- a/src/de.hpi.swa.trufflesqueak.test/src/de/hpi/swa/trufflesqueak/test/AbstractSqueakTestCase.java +++ b/src/de.hpi.swa.trufflesqueak.test/src/de/hpi/swa/trufflesqueak/test/AbstractSqueakTestCase.java @@ -57,7 +57,7 @@ protected static CompiledCodeObject makeMethod(final Object[] literals, final in } protected static long makeHeader(final int numArgs, final int numTemps, final int numLiterals, final boolean hasPrimitive, final boolean needsLargeFrame) { // shortcut - return CompiledCodeObject.makeHeader(numArgs, numTemps, numLiterals, hasPrimitive, needsLargeFrame); + return CompiledCodeObject.makeHeader(true, numArgs, numTemps, numLiterals, hasPrimitive, needsLargeFrame); } protected CompiledCodeObject makeMethod(final int... intbytes) { diff --git a/src/de.hpi.swa.trufflesqueak.test/src/de/hpi/swa/trufflesqueak/test/SqueakMiscellaneousTest.java b/src/de.hpi.swa.trufflesqueak.test/src/de/hpi/swa/trufflesqueak/test/SqueakMiscellaneousTest.java index 2a7014f0f..68c2257c6 100644 --- a/src/de.hpi.swa.trufflesqueak.test/src/de/hpi/swa/trufflesqueak/test/SqueakMiscellaneousTest.java +++ b/src/de.hpi.swa.trufflesqueak.test/src/de/hpi/swa/trufflesqueak/test/SqueakMiscellaneousTest.java @@ -17,14 +17,14 @@ import de.hpi.swa.trufflesqueak.model.NilObject; import de.hpi.swa.trufflesqueak.model.layout.ObjectLayouts.CONTEXT; import de.hpi.swa.trufflesqueak.nodes.bytecodes.AbstractBytecodeNode; -import de.hpi.swa.trufflesqueak.nodes.bytecodes.JumpBytecodes.ConditionalFalseJumpNode; +import de.hpi.swa.trufflesqueak.nodes.bytecodes.JumpBytecodes.ConditionalJumpOnFalseNode; import de.hpi.swa.trufflesqueak.nodes.bytecodes.MiscellaneousBytecodes.DupNode; import de.hpi.swa.trufflesqueak.nodes.bytecodes.MiscellaneousBytecodes.PopNode; -import de.hpi.swa.trufflesqueak.nodes.bytecodes.PushBytecodes.PushConstantNode.PushConstantNilNode; -import de.hpi.swa.trufflesqueak.nodes.bytecodes.PushBytecodes.PushConstantNode.PushConstantOneNode; -import de.hpi.swa.trufflesqueak.nodes.bytecodes.PushBytecodes.PushConstantNode.PushConstantTrueNode; +import de.hpi.swa.trufflesqueak.nodes.bytecodes.PushBytecodes.PushConstantNilNode; +import de.hpi.swa.trufflesqueak.nodes.bytecodes.PushBytecodes.PushConstantOneNode; +import de.hpi.swa.trufflesqueak.nodes.bytecodes.PushBytecodes.PushConstantTrueNode; import de.hpi.swa.trufflesqueak.nodes.bytecodes.ReturnBytecodes.ReturnReceiverNode; -import de.hpi.swa.trufflesqueak.util.SqueakBytecodeDecoder; +import de.hpi.swa.trufflesqueak.nodes.bytecodes.SqueakBytecodeV3PlusClosuresDecoder; import de.hpi.swa.trufflesqueak.util.UnsafeUtils; public class SqueakMiscellaneousTest extends AbstractSqueakTestCaseWithDummyImage { @@ -118,7 +118,7 @@ public void testIfNil() { // pushConstant: true, send: class, pop, returnSelf final int[] bytes = {0x76, 0x88, 0x73, 0xc6, 0x99, 0x87, 0x71, 0xc7, 0x87, 0x78}; final CompiledCodeObject code = makeMethod(bytes); - final AbstractBytecodeNode[] bytecodeNodes = SqueakBytecodeDecoder.decode(code); + final AbstractBytecodeNode[] bytecodeNodes = SqueakBytecodeV3PlusClosuresDecoder.decode(code); assertEquals(bytes.length, bytecodeNodes.length); assertSame(PushConstantOneNode.class, bytecodeNodes[0].getClass()); assertSame(DupNode.class, bytecodeNodes[1].getClass()); @@ -126,7 +126,7 @@ public void testIfNil() { assertEquals("send: ==", bytecodeNodes[3].toString()); - assertSame(ConditionalFalseJumpNode.class, bytecodeNodes[4].getClass()); + assertSame(ConditionalJumpOnFalseNode.class, bytecodeNodes[4].getClass()); assertSame(PopNode.class, bytecodeNodes[5].getClass()); assertSame(PushConstantTrueNode.class, bytecodeNodes[6].getClass()); @@ -142,7 +142,7 @@ public void testSource() { // with // numTemp=55 final CompiledCodeObject code = makeMethod(literals, 0x70, 0x68, 0x10, 0x8F, 0x10, 0x00, 0x02, 0x10, 0x7D, 0xC9, 0x7C); - final CharSequence source = SqueakBytecodeDecoder.decodeToString(code); + final CharSequence source = SqueakBytecodeV3PlusClosuresDecoder.decodeToString(code); assertEquals(String.join("\n", "1 <70> self", "2 <68> popIntoTemp: 0", @@ -186,7 +186,7 @@ public void testSourceAllBytecodes() { 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 225, 240); - final CharSequence source = SqueakBytecodeDecoder.decodeToString(code); + final CharSequence source = SqueakBytecodeV3PlusClosuresDecoder.decodeToString(code); assertEquals(ALL_BYTECODES_EXPECTED_RESULT, source); } diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/image/SqueakImageContext.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/image/SqueakImageContext.java index 46ce5285e..9af62f7b4 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/image/SqueakImageContext.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/image/SqueakImageContext.java @@ -101,7 +101,7 @@ public final class SqueakImageContext { public final ClassObject metaClass = new ClassObject(this); public final ClassObject nilClass = new ClassObject(this); - public final CompiledCodeObject dummyMethod = new CompiledCodeObject(this, null, new Object[]{CompiledCodeObject.makeHeader(1, 0, 0, false, true)}, compiledMethodClass); + public final CompiledCodeObject dummyMethod = new CompiledCodeObject(this, null, new Object[]{CompiledCodeObject.makeHeader(true, 1, 0, 0, false, true)}, compiledMethodClass); /* Method Cache */ private static final int METHOD_CACHE_SIZE = 1024; diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/model/BlockClosureObject.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/model/BlockClosureObject.java index 5ff2fee4f..01fee5183 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/model/BlockClosureObject.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/model/BlockClosureObject.java @@ -168,9 +168,16 @@ private void initializeCompiledBlock(final CompiledCodeObject method) { CompilerDirectives.transferToInterpreterAndInvalidate(); assert startPC >= 0; final int offset = (int) startPC - method.getInitialPC(); - final int j = method.getBytes()[offset - 2]; - final int k = method.getBytes()[offset - 1]; - final int blockSize = j << 8 | k & 0xff; + final int blockSize; + if (method.getSignFlag()) { + final int j = method.getBytes()[offset - 2]; + final int k = method.getBytes()[offset - 1]; + blockSize = j << 8 | k & 0xff; + } else { + final int possibleExtBIndex = offset - 5; + assert possibleExtBIndex < 0 || method.getBytes()[possibleExtBIndex] != 225 : "FIXME: should calculate extB from bytecode"; + blockSize = Byte.toUnsignedInt(method.getBytes()[offset - 1]); + } block = CompiledCodeObject.createBlock(method, method, (int) numArgs, copied.length, offset, blockSize); /* Ensure fields dependent on block are initialized. */ getStartPC(); diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/model/CompiledCodeObject.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/model/CompiledCodeObject.java index 1c40cfc39..5b5dd3cb7 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/model/CompiledCodeObject.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/model/CompiledCodeObject.java @@ -40,11 +40,13 @@ import de.hpi.swa.trufflesqueak.nodes.ResumeContextNode.ResumeContextRootNode; import de.hpi.swa.trufflesqueak.nodes.accessing.AbstractPointersObjectNodes.AbstractPointersObjectReadNode; import de.hpi.swa.trufflesqueak.nodes.accessing.AbstractPointersObjectNodes.AbstractPointersObjectWriteNode; +import de.hpi.swa.trufflesqueak.nodes.bytecodes.AbstractBytecodeNode; +import de.hpi.swa.trufflesqueak.nodes.bytecodes.SqueakBytecodeSistaV1Decoder; +import de.hpi.swa.trufflesqueak.nodes.bytecodes.SqueakBytecodeV3PlusClosuresDecoder; import de.hpi.swa.trufflesqueak.nodes.dispatch.DispatchUneagerlyNode; import de.hpi.swa.trufflesqueak.shared.SqueakLanguageConfig; import de.hpi.swa.trufflesqueak.util.MiscUtils; import de.hpi.swa.trufflesqueak.util.ObjectGraphUtils.ObjectTracer; -import de.hpi.swa.trufflesqueak.util.SqueakBytecodeDecoder; @ExportLibrary(InteropLibrary.class) public final class CompiledCodeObject extends AbstractSqueakObjectWithClassAndHash { @@ -118,7 +120,7 @@ private CompiledCodeObject(final SqueakImageContext image, final CompiledCodeObj final Object[] outerLiterals = outerMethod.getLiterals(); final int outerLiteralsLength = outerLiterals.length; literals = new Object[outerLiteralsLength + 1]; - literals[0] = makeHeader(numArguments, numCopied, code.numLiterals, false, outerMethod.needsLargeFrame); + literals[0] = makeHeader(outerMethod.getSignFlag(), numArguments, numCopied, code.numLiterals, false, outerMethod.needsLargeFrame); System.arraycopy(outerLiterals, 1, literals, 1, outerLiteralsLength - 1); literals[outerLiteralsLength] = outerMethod; // Last literal is back pointer to method. bytes = Arrays.copyOfRange(code.getBytes(), bytecodeOffset, bytecodeOffset + blockSize); @@ -175,7 +177,7 @@ public Source getSource() { String contents; try { name = toString(); - contents = SqueakBytecodeDecoder.decodeToString(this); + contents = SqueakBytecodeV3PlusClosuresDecoder.decodeToString(this); } catch (final RuntimeException e) { if (name == null) { name = SOURCE_UNAVAILABLE_NAME; @@ -272,6 +274,10 @@ public int getNumLiterals() { return numLiterals; } + public boolean getSignFlag() { + return CompiledCodeHeaderDecoder.getSignFlag((long) literals[0]); + } + public FrameSlot getStackSlot(final int i) { assert 0 <= i && i < stackSlots.length : "Bad stack access"; if (stackSlots[i] == null) { @@ -309,13 +315,41 @@ public void fillin(final SqueakImageChunk chunk) { assert innerBlocks == null : "Should not have any inner blocks yet"; } - private int getHeader() { - return MiscUtils.toIntExact((long) literals[0]); + public AbstractBytecodeNode[] asBytecodeNodes() { + if (getSignFlag()) { + return SqueakBytecodeV3PlusClosuresDecoder.decode(this); + } else { + return SqueakBytecodeSistaV1Decoder.decode(this); + } + } + + public AbstractBytecodeNode[] asBytecodeNodesEmpty() { + if (getSignFlag()) { + return new AbstractBytecodeNode[SqueakBytecodeV3PlusClosuresDecoder.trailerPosition(this)]; + } else { + return new AbstractBytecodeNode[SqueakBytecodeSistaV1Decoder.trailerPosition(this)]; + } + } + + public AbstractBytecodeNode bytecodeNodeAt(final int pc) { + if (getSignFlag()) { + return SqueakBytecodeV3PlusClosuresDecoder.decodeBytecode(this, pc); + } else { + return SqueakBytecodeSistaV1Decoder.decodeBytecode(this, pc); + } + } + + public int findLineNumber(final int index) { + if (getSignFlag()) { + return SqueakBytecodeV3PlusClosuresDecoder.findLineNumber(this, index); + } else { + return SqueakBytecodeSistaV1Decoder.findLineNumber(this, index); + } } protected void decodeHeader() { CompilerDirectives.transferToInterpreterAndInvalidate(); - final int header = getHeader(); + final long header = (long) literals[0]; numLiterals = CompiledCodeHeaderDecoder.getNumLiterals(header); hasPrimitive = CompiledCodeHeaderDecoder.getHasPrimitive(header); needsLargeFrame = CompiledCodeHeaderDecoder.getNeedsLargeFrame(header); @@ -483,8 +517,8 @@ public byte[] getBytes() { return bytes; } - public static long makeHeader(final int numArgs, final int numTemps, final int numLiterals, final boolean hasPrimitive, final boolean needsLargeFrame) { - return (numArgs & 0x0F) << 24 | (numTemps & 0x3F) << 18 | numLiterals & 0x7FFF | (needsLargeFrame ? 0x20000 : 0) | (hasPrimitive ? 0x10000 : 0); + public static long makeHeader(final boolean signFlag, final int numArgs, final int numTemps, final int numLiterals, final boolean hasPrimitive, final boolean needsLargeFrame) { + return (signFlag ? 0 : 1) << 31 | (numArgs & 0x0F) << 24 | (numTemps & 0x3F) << 18 | numLiterals & 0x7FFF | (needsLargeFrame ? 0x20000 : 0) | (hasPrimitive ? 0x10000 : 0); } public CompiledCodeObject findBlock(final CompiledCodeObject method, final int numClosureArgs, final int numCopied, final int successorIndex, final int blockSize) { @@ -786,5 +820,9 @@ private static int getNumTemps(final long headerWord) { private static int getNumArguments(final long headerWord) { return MiscUtils.bitSplit(headerWord, 24, NUM_ARGUMENTS_SIZE); } + + private static boolean getSignFlag(final long headerWord) { + return headerWord >= 0; + } } } diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/model/layout/ObjectLayouts.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/model/layout/ObjectLayouts.java index fcebe5960..d56c708f5 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/model/layout/ObjectLayouts.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/model/layout/ObjectLayouts.java @@ -342,6 +342,12 @@ public static final class SPECIAL_OBJECT { public static final int INVOKE_CALLBACK_SELECTOR = 53; public static final int CLASS_UNSAFE_ALIEN = 54; public static final int CLASS_WEAK_FINALIZER = 55; + public static final int FOREIGN_CALLBACK_PROCESS = 56; + public static final int SELECTOR_UNKNOWN_BYTECODE = 57; + public static final int SELECTOR_COUNTER_TRIPPED = 58; + public static final int SELECTOR_SISTA_TRAP = 59; + public static final int LOWCODE_CONTEXT_MARK = 60; + public static final int LOWCODE_NATIVE_CONTEXT_CLASS = 61; } public static final class SPECIAL_OBJECT_TAG { diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/ExecuteContextNode.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/ExecuteContextNode.java index f52b4c2ad..61163cd3c 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/ExecuteContextNode.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/ExecuteContextNode.java @@ -38,7 +38,6 @@ import de.hpi.swa.trufflesqueak.util.FrameAccess; import de.hpi.swa.trufflesqueak.util.InterruptHandlerNode; import de.hpi.swa.trufflesqueak.util.LogUtils; -import de.hpi.swa.trufflesqueak.util.SqueakBytecodeDecoder; public final class ExecuteContextNode extends AbstractExecuteContextNode { private static final int LOCAL_RETURN_PC = -2; @@ -60,7 +59,7 @@ public final class ExecuteContextNode extends AbstractExecuteContextNode { protected ExecuteContextNode(final CompiledCodeObject code, final boolean resume) { this.code = code; - bytecodeNodes = new AbstractBytecodeNode[SqueakBytecodeDecoder.trailerPosition(code)]; + bytecodeNodes = code.asBytecodeNodesEmpty(); frameInitializationNode = resume ? null : FrameStackInitializationNode.create(); /* * Only check for interrupts if method is relatively large. Avoid check if a closure is @@ -318,7 +317,7 @@ protected boolean hasModifiedSender(final VirtualFrame frame) { private AbstractBytecodeNode fetchNextBytecodeNode(final int pc) { if (bytecodeNodes[pc] == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - bytecodeNodes[pc] = insert(SqueakBytecodeDecoder.decodeBytecode(code, pc)); + bytecodeNodes[pc] = insert(code.bytecodeNodeAt(pc)); notifyInserted(bytecodeNodes[pc]); } return bytecodeNodes[pc]; diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/bytecodes/AbstractBytecodeNode.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/bytecodes/AbstractBytecodeNode.java index 5c501a0fc..df58aa284 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/bytecodes/AbstractBytecodeNode.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/bytecodes/AbstractBytecodeNode.java @@ -15,7 +15,6 @@ import de.hpi.swa.trufflesqueak.model.FrameMarker; import de.hpi.swa.trufflesqueak.nodes.AbstractNode; import de.hpi.swa.trufflesqueak.util.FrameAccess; -import de.hpi.swa.trufflesqueak.util.SqueakBytecodeDecoder; public abstract class AbstractBytecodeNode extends AbstractNode { protected final CompiledCodeObject code; @@ -71,7 +70,7 @@ public final SourceSection getSourceSection() { if (CompiledCodeObject.SOURCE_UNAVAILABLE_CONTENTS.contentEquals(source.getCharacters())) { sourceSection = source.createUnavailableSection(); } else { - final int lineNumber = SqueakBytecodeDecoder.findLineNumber(code, index); + final int lineNumber = code.findLineNumber(index); sourceSection = source.createSection(lineNumber); } } diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/bytecodes/InlinePrimitiveBytecodes.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/bytecodes/InlinePrimitiveBytecodes.java new file mode 100644 index 000000000..7f7be6e20 --- /dev/null +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/bytecodes/InlinePrimitiveBytecodes.java @@ -0,0 +1,584 @@ +/* + * Copyright (c) 2017-2020 Software Architecture Group, Hasso Plattner Institute + * + * Licensed under the MIT License. + */ +package de.hpi.swa.trufflesqueak.nodes.bytecodes; + +import org.bouncycastle.util.Arrays; + +import com.oracle.truffle.api.frame.VirtualFrame; + +import de.hpi.swa.trufflesqueak.model.AbstractSqueakObjectWithClassAndHash; +import de.hpi.swa.trufflesqueak.model.BooleanObject; +import de.hpi.swa.trufflesqueak.model.ClassObject; +import de.hpi.swa.trufflesqueak.model.CompiledCodeObject; +import de.hpi.swa.trufflesqueak.model.NativeObject; +import de.hpi.swa.trufflesqueak.model.PointersObject; +import de.hpi.swa.trufflesqueak.nodes.accessing.SqueakObjectAtPut0Node; +import de.hpi.swa.trufflesqueak.nodes.accessing.SqueakObjectClassNode; +import de.hpi.swa.trufflesqueak.nodes.context.frame.FrameStackPopNode; +import de.hpi.swa.trufflesqueak.nodes.context.frame.FrameStackPushNode; + +public final class InlinePrimitiveBytecodes { + protected abstract static class AbstractPushNode extends AbstractInstrumentableBytecodeNode { + @Child protected FrameStackPushNode pushNode = FrameStackPushNode.create(); + + protected AbstractPushNode(final CompiledCodeObject code, final int index) { + super(code, index, 1); + } + } + + protected abstract static class AbstractNullaryInlinePrimitiveNode extends AbstractPushNode { + @Child protected FrameStackPopNode popNode = FrameStackPopNode.create(); + + protected AbstractNullaryInlinePrimitiveNode(final CompiledCodeObject code, final int index) { + super(code, index); + } + } + + protected abstract static class AbstractUnaryInlinePrimitiveNode extends AbstractPushNode { + @Child protected FrameStackPopNode pop1Node = FrameStackPopNode.create(); + @Child protected FrameStackPopNode pop2Node = FrameStackPopNode.create(); + + protected AbstractUnaryInlinePrimitiveNode(final CompiledCodeObject code, final int index) { + super(code, index); + } + } + + protected abstract static class AbstractTrinaryInlinePrimitiveNode extends AbstractPushNode { + @Child protected FrameStackPopNode pop1Node = FrameStackPopNode.create(); + @Child protected FrameStackPopNode pop2Node = FrameStackPopNode.create(); + @Child protected FrameStackPopNode pop3Node = FrameStackPopNode.create(); + + protected AbstractTrinaryInlinePrimitiveNode(final CompiledCodeObject code, final int index) { + super(code, index); + } + } + + protected abstract static class AbstractQuaternaryInlinePrimitiveNode extends AbstractPushNode { + @Child protected FrameStackPopNode pop1Node = FrameStackPopNode.create(); + @Child protected FrameStackPopNode pop2Node = FrameStackPopNode.create(); + @Child protected FrameStackPopNode pop3Node = FrameStackPopNode.create(); + @Child protected FrameStackPopNode pop4Node = FrameStackPopNode.create(); + + protected AbstractQuaternaryInlinePrimitiveNode(final CompiledCodeObject code, final int index) { + super(code, index); + } + } + + protected static final class PrimClassNode extends AbstractNullaryInlinePrimitiveNode { + @Child private SqueakObjectClassNode classNode = SqueakObjectClassNode.create(); + + protected PrimClassNode(final CompiledCodeObject code, final int index) { + super(code, index); + } + + @Override + public void executeVoid(final VirtualFrame frame) { + pushNode.execute(frame, classNode.executeLookup(popNode.execute(frame))); + } + } + + protected static final class PrimNumSlotsNode extends AbstractNullaryInlinePrimitiveNode { + protected PrimNumSlotsNode(final CompiledCodeObject code, final int index) { + super(code, index); + } + + @Override + public void executeVoid(final VirtualFrame frame) { + pushNode.execute(frame, (long) ((PointersObject) popNode.execute(frame)).size()); // FIXME + } + } + + protected static final class PrimBasicSizeNode extends AbstractNullaryInlinePrimitiveNode { + protected PrimBasicSizeNode(final CompiledCodeObject code, final int index) { + super(code, index); + } + + @Override + public void executeVoid(final VirtualFrame frame) { + pushNode.execute(frame, (long) ((PointersObject) popNode.execute(frame)).getNumSlots()); // FIXME + } + } + + protected static final class PrimNumBytesNode extends AbstractNullaryInlinePrimitiveNode { + protected PrimNumBytesNode(final CompiledCodeObject code, final int index) { + super(code, index); + } + + @Override + public void executeVoid(final VirtualFrame frame) { + final Object receiver = popNode.execute(frame); + final long numBytes; + if (receiver instanceof CompiledCodeObject) { + numBytes = ((CompiledCodeObject) receiver).getBytes().length; + } else { + numBytes = ((NativeObject) receiver).getByteLength(); + } + pushNode.execute(frame, numBytes); + } + } + + protected static final class PrimNumShortsNode extends AbstractNullaryInlinePrimitiveNode { + protected PrimNumShortsNode(final CompiledCodeObject code, final int index) { + super(code, index); + } + + @Override + public void executeVoid(final VirtualFrame frame) { + pushNode.execute(frame, (long) ((NativeObject) popNode.execute(frame)).getShortLength()); + } + } + + protected static final class PrimNumWordsNode extends AbstractNullaryInlinePrimitiveNode { + protected PrimNumWordsNode(final CompiledCodeObject code, final int index) { + super(code, index); + } + + @Override + public void executeVoid(final VirtualFrame frame) { + pushNode.execute(frame, (long) ((NativeObject) popNode.execute(frame)).getIntLength()); + } + } + + protected static final class PrimNumDoubleWordsNode extends AbstractNullaryInlinePrimitiveNode { + protected PrimNumDoubleWordsNode(final CompiledCodeObject code, final int index) { + super(code, index); + } + + @Override + public void executeVoid(final VirtualFrame frame) { + pushNode.execute(frame, (long) ((NativeObject) popNode.execute(frame)).getLongLength()); + } + } + + protected static final class PrimIdentityHashNode extends AbstractNullaryInlinePrimitiveNode { + protected PrimIdentityHashNode(final CompiledCodeObject code, final int index) { + super(code, index); + } + + @Override + public void executeVoid(final VirtualFrame frame) { + pushNode.execute(frame, ((AbstractSqueakObjectWithClassAndHash) popNode.execute(frame)).getSqueakHash()); + } + } + + protected static final class PrimIdentityHashSmallIntegerNode extends AbstractNullaryInlinePrimitiveNode { + protected PrimIdentityHashSmallIntegerNode(final CompiledCodeObject code, final int index) { + super(code, index); + } + + @Override + public void executeVoid(final VirtualFrame frame) { + pushNode.execute(frame, popNode.execute(frame)); + } + } + + protected static final class PrimIdentityHashCharacterNode extends AbstractNullaryInlinePrimitiveNode { + protected PrimIdentityHashCharacterNode(final CompiledCodeObject code, final int index) { + super(code, index); + } + + @Override + public void executeVoid(final VirtualFrame frame) { + pushNode.execute(frame, (long) (char) popNode.execute(frame)); + } + } + + protected static final class PrimIdentityHashSmallFloatNode extends AbstractNullaryInlinePrimitiveNode { + protected PrimIdentityHashSmallFloatNode(final CompiledCodeObject code, final int index) { + super(code, index); + } + + @Override + public void executeVoid(final VirtualFrame frame) { + pushNode.execute(frame, Double.doubleToRawLongBits((double) popNode.execute(frame))); + } + } + + protected static final class PrimIdentityHashBehaviorNode extends AbstractNullaryInlinePrimitiveNode { + protected PrimIdentityHashBehaviorNode(final CompiledCodeObject code, final int index) { + super(code, index); + } + + @Override + public void executeVoid(final VirtualFrame frame) { + pushNode.execute(frame, ((ClassObject) popNode.execute(frame)).getSqueakHash()); + } + } + + protected static final class PrimImmediateAsIntegerCharacterNode extends AbstractNullaryInlinePrimitiveNode { + protected PrimImmediateAsIntegerCharacterNode(final CompiledCodeObject code, final int index) { + super(code, index); + } + + @Override + public void executeVoid(final VirtualFrame frame) { + pushNode.execute(frame, (long) (char) popNode.execute(frame)); + } + } + + protected static final class PrimImmediateAsIntegerSmallFloatNode extends AbstractNullaryInlinePrimitiveNode { + protected PrimImmediateAsIntegerSmallFloatNode(final CompiledCodeObject code, final int index) { + super(code, index); + } + + @Override + public void executeVoid(final VirtualFrame frame) { + pushNode.execute(frame, Double.doubleToRawLongBits((double) popNode.execute(frame))); + } + } + + protected static final class PrimImmediateAsFloatNode extends AbstractNullaryInlinePrimitiveNode { + protected PrimImmediateAsFloatNode(final CompiledCodeObject code, final int index) { + super(code, index); + } + + @Override + public void executeVoid(final VirtualFrame frame) { + pushNode.execute(frame, (double) (long) popNode.execute(frame)); + } + } + + protected static final class PrimSmallIntegerAddNode extends AbstractUnaryInlinePrimitiveNode { + protected PrimSmallIntegerAddNode(final CompiledCodeObject code, final int index) { + super(code, index); + } + + @Override + public void executeVoid(final VirtualFrame frame) { + pushNode.execute(frame, (long) pop1Node.execute(frame) + (long) pop2Node.execute(frame)); + } + } + + protected static final class PrimSmallIntegerSubtractNode extends AbstractUnaryInlinePrimitiveNode { + protected PrimSmallIntegerSubtractNode(final CompiledCodeObject code, final int index) { + super(code, index); + } + + @Override + public void executeVoid(final VirtualFrame frame) { + pushNode.execute(frame, (long) pop1Node.execute(frame) - (long) pop2Node.execute(frame)); + } + } + + protected static final class PrimSmallIntegerMultiplyNode extends AbstractUnaryInlinePrimitiveNode { + protected PrimSmallIntegerMultiplyNode(final CompiledCodeObject code, final int index) { + super(code, index); + } + + @Override + public void executeVoid(final VirtualFrame frame) { + pushNode.execute(frame, (long) pop1Node.execute(frame) * (long) pop2Node.execute(frame)); + } + } + + protected static final class PrimSmallIntegerDivideNode extends AbstractUnaryInlinePrimitiveNode { + protected PrimSmallIntegerDivideNode(final CompiledCodeObject code, final int index) { + super(code, index); + } + + @Override + public void executeVoid(final VirtualFrame frame) { + pushNode.execute(frame, (long) pop1Node.execute(frame) / (long) pop2Node.execute(frame)); + } + } + + protected static final class PrimSmallIntegerFloorDivideNode extends AbstractUnaryInlinePrimitiveNode { + protected PrimSmallIntegerFloorDivideNode(final CompiledCodeObject code, final int index) { + super(code, index); + } + + @Override + public void executeVoid(final VirtualFrame frame) { + pushNode.execute(frame, Math.floorDiv((long) pop1Node.execute(frame), (long) pop2Node.execute(frame))); + } + } + + protected static final class PrimSmallIntegerFloorModNode extends AbstractUnaryInlinePrimitiveNode { + protected PrimSmallIntegerFloorModNode(final CompiledCodeObject code, final int index) { + super(code, index); + } + + @Override + public void executeVoid(final VirtualFrame frame) { + pushNode.execute(frame, Math.floorMod((long) pop1Node.execute(frame), (long) pop2Node.execute(frame))); + } + } + + protected static final class PrimSmallIntegerQuoNode extends AbstractUnaryInlinePrimitiveNode { + protected PrimSmallIntegerQuoNode(final CompiledCodeObject code, final int index) { + super(code, index); + } + + @Override + public void executeVoid(final VirtualFrame frame) { + pushNode.execute(frame, (long) pop1Node.execute(frame) / (long) pop2Node.execute(frame)); + } + } + + protected static final class PrimSmallIntegerBitAndNode extends AbstractUnaryInlinePrimitiveNode { + protected PrimSmallIntegerBitAndNode(final CompiledCodeObject code, final int index) { + super(code, index); + } + + @Override + public void executeVoid(final VirtualFrame frame) { + pushNode.execute(frame, (long) pop1Node.execute(frame) & (long) pop2Node.execute(frame)); + } + } + + protected static final class PrimSmallIntegerBitOrNode extends AbstractUnaryInlinePrimitiveNode { + protected PrimSmallIntegerBitOrNode(final CompiledCodeObject code, final int index) { + super(code, index); + } + + @Override + public void executeVoid(final VirtualFrame frame) { + pushNode.execute(frame, (long) pop1Node.execute(frame) | (long) pop2Node.execute(frame)); + } + } + + protected static final class PrimSmallIntegerBitXorNode extends AbstractUnaryInlinePrimitiveNode { + protected PrimSmallIntegerBitXorNode(final CompiledCodeObject code, final int index) { + super(code, index); + } + + @Override + public void executeVoid(final VirtualFrame frame) { + pushNode.execute(frame, (long) pop1Node.execute(frame) ^ (long) pop2Node.execute(frame)); + } + } + + protected static final class PrimSmallIntegerBitShiftLeftNode extends AbstractUnaryInlinePrimitiveNode { + protected PrimSmallIntegerBitShiftLeftNode(final CompiledCodeObject code, final int index) { + super(code, index); + } + + @Override + public void executeVoid(final VirtualFrame frame) { + pushNode.execute(frame, (long) pop1Node.execute(frame) << (long) pop2Node.execute(frame)); + } + } + + protected static final class PrimSmallIntegerBitShiftRightNode extends AbstractUnaryInlinePrimitiveNode { + protected PrimSmallIntegerBitShiftRightNode(final CompiledCodeObject code, final int index) { + super(code, index); + } + + @Override + public void executeVoid(final VirtualFrame frame) { + pushNode.execute(frame, (long) pop1Node.execute(frame) >> (long) pop2Node.execute(frame)); + } + } + + protected static final class PrimSmallIntegerGreaterThanNode extends AbstractUnaryInlinePrimitiveNode { + protected PrimSmallIntegerGreaterThanNode(final CompiledCodeObject code, final int index) { + super(code, index); + } + + @Override + public void executeVoid(final VirtualFrame frame) { + pushNode.execute(frame, BooleanObject.wrap((long) pop1Node.execute(frame) > (long) pop2Node.execute(frame))); + } + } + + protected static final class PrimSmallIntegerLessThanNode extends AbstractUnaryInlinePrimitiveNode { + protected PrimSmallIntegerLessThanNode(final CompiledCodeObject code, final int index) { + super(code, index); + } + + @Override + public void executeVoid(final VirtualFrame frame) { + pushNode.execute(frame, BooleanObject.wrap((long) pop1Node.execute(frame) < (long) pop2Node.execute(frame))); + } + } + + protected static final class PrimSmallIntegerGreaterOrEqualNode extends AbstractUnaryInlinePrimitiveNode { + protected PrimSmallIntegerGreaterOrEqualNode(final CompiledCodeObject code, final int index) { + super(code, index); + } + + @Override + public void executeVoid(final VirtualFrame frame) { + pushNode.execute(frame, BooleanObject.wrap((long) pop1Node.execute(frame) >= (long) pop2Node.execute(frame))); + } + } + + protected static final class PrimSmallIntegerLessOrEqualNode extends AbstractUnaryInlinePrimitiveNode { + protected PrimSmallIntegerLessOrEqualNode(final CompiledCodeObject code, final int index) { + super(code, index); + } + + @Override + public void executeVoid(final VirtualFrame frame) { + pushNode.execute(frame, BooleanObject.wrap((long) pop1Node.execute(frame) <= (long) pop2Node.execute(frame))); + } + } + + protected static final class PrimSmallIntegerEqualNode extends AbstractUnaryInlinePrimitiveNode { + protected PrimSmallIntegerEqualNode(final CompiledCodeObject code, final int index) { + super(code, index); + } + + @Override + public void executeVoid(final VirtualFrame frame) { + pushNode.execute(frame, BooleanObject.wrap((long) pop1Node.execute(frame) == (long) pop2Node.execute(frame))); + } + } + + protected static final class PrimSmallIntegerNotEqualNode extends AbstractUnaryInlinePrimitiveNode { + protected PrimSmallIntegerNotEqualNode(final CompiledCodeObject code, final int index) { + super(code, index); + } + + @Override + public void executeVoid(final VirtualFrame frame) { + pushNode.execute(frame, BooleanObject.wrap((long) pop1Node.execute(frame) != (long) pop2Node.execute(frame))); + } + } + + protected static final class PrimByteAtNode extends AbstractUnaryInlinePrimitiveNode { + protected PrimByteAtNode(final CompiledCodeObject code, final int index) { + super(code, index); + } + + @Override + public void executeVoid(final VirtualFrame frame) { + final long atIndex = (long) pop2Node.execute(frame); + final NativeObject receiver = (NativeObject) pop1Node.execute(frame); + pushNode.execute(frame, (long) receiver.getByte(atIndex)); + } + } + + protected static final class PrimShortAtNode extends AbstractUnaryInlinePrimitiveNode { + protected PrimShortAtNode(final CompiledCodeObject code, final int index) { + super(code, index); + } + + @Override + public void executeVoid(final VirtualFrame frame) { + final long atIndex = (long) pop2Node.execute(frame); + final NativeObject receiver = (NativeObject) pop1Node.execute(frame); + pushNode.execute(frame, (long) receiver.getShort(atIndex)); + } + } + + protected static final class PrimWordAtNode extends AbstractUnaryInlinePrimitiveNode { + protected PrimWordAtNode(final CompiledCodeObject code, final int index) { + super(code, index); + } + + @Override + public void executeVoid(final VirtualFrame frame) { + final long atIndex = (long) pop2Node.execute(frame); + final NativeObject receiver = (NativeObject) pop1Node.execute(frame); + pushNode.execute(frame, (long) receiver.getInt(atIndex)); + } + } + + protected static final class PrimDoubleWordAtNode extends AbstractUnaryInlinePrimitiveNode { + protected PrimDoubleWordAtNode(final CompiledCodeObject code, final int index) { + super(code, index); + } + + @Override + public void executeVoid(final VirtualFrame frame) { + final long atIndex = (long) pop2Node.execute(frame); + final NativeObject receiver = (NativeObject) pop1Node.execute(frame); + pushNode.execute(frame, receiver.getLong(atIndex)); + } + } + + protected static final class PrimByteAtPutNode extends AbstractTrinaryInlinePrimitiveNode { + protected PrimByteAtPutNode(final CompiledCodeObject code, final int index) { + super(code, index); + } + + @Override + public void executeVoid(final VirtualFrame frame) { + final long value = (long) pop3Node.execute(frame); + final long atIndex = (long) pop2Node.execute(frame); + final NativeObject receiver = (NativeObject) pop1Node.execute(frame); + receiver.setByte(atIndex, (byte) value); + } + } + + protected static final class PrimShortAtPutNode extends AbstractTrinaryInlinePrimitiveNode { + protected PrimShortAtPutNode(final CompiledCodeObject code, final int index) { + super(code, index); + } + + @Override + public void executeVoid(final VirtualFrame frame) { + final long value = (long) pop3Node.execute(frame); + final long atIndex = (long) pop2Node.execute(frame); + final NativeObject receiver = (NativeObject) pop1Node.execute(frame); + receiver.setShort(atIndex, (short) value); + } + } + + protected static final class PrimWordAtPutNode extends AbstractTrinaryInlinePrimitiveNode { + protected PrimWordAtPutNode(final CompiledCodeObject code, final int index) { + super(code, index); + } + + @Override + public void executeVoid(final VirtualFrame frame) { + final long value = (long) pop3Node.execute(frame); + final long atIndex = (long) pop2Node.execute(frame); + final NativeObject receiver = (NativeObject) pop1Node.execute(frame); + receiver.setInt(atIndex, (int) value); + } + } + + protected static final class PrimDoubleWordAtPutNode extends AbstractTrinaryInlinePrimitiveNode { + protected PrimDoubleWordAtPutNode(final CompiledCodeObject code, final int index) { + super(code, index); + } + + @Override + public void executeVoid(final VirtualFrame frame) { + final long value = (long) pop3Node.execute(frame); + final long atIndex = (long) pop2Node.execute(frame); + final NativeObject receiver = (NativeObject) pop1Node.execute(frame); + receiver.setLong(atIndex, value); + } + } + + protected static final class PrimByteEqualsNode extends AbstractTrinaryInlinePrimitiveNode { + protected PrimByteEqualsNode(final CompiledCodeObject code, final int index) { + super(code, index); + } + + @Override + public void executeVoid(final VirtualFrame frame) { + // TODO: Make use of `final long length = (long) pop3Node.execute(frame);` + final NativeObject argument = (NativeObject) pop2Node.execute(frame); + final NativeObject receiver = (NativeObject) pop1Node.execute(frame); + pushNode.execute(frame, BooleanObject.wrap(Arrays.areEqual(receiver.getByteStorage(), argument.getByteStorage()))); + } + } + + protected static final class PrimFillFromToWithNode extends AbstractQuaternaryInlinePrimitiveNode { + @Child private SqueakObjectAtPut0Node atPutNode = SqueakObjectAtPut0Node.create(); + + protected PrimFillFromToWithNode(final CompiledCodeObject code, final int index) { + super(code, index); + } + + @Override + public void executeVoid(final VirtualFrame frame) { + final Object value = (long) pop3Node.execute(frame); + final long to = (long) pop3Node.execute(frame); + final long from = (long) pop2Node.execute(frame); + final Object receiver = pop1Node.execute(frame); + // TODO: maybe there's a more efficient way to fill pointers object? + for (long i = from; i < to; i++) { + atPutNode.execute(receiver, i, value); + } + pushNode.execute(frame, receiver); + } + } +} diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/bytecodes/JumpBytecodes.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/bytecodes/JumpBytecodes.java index 6f81399dc..1b86b2c4b 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/bytecodes/JumpBytecodes.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/bytecodes/JumpBytecodes.java @@ -23,14 +23,9 @@ public abstract static class ConditionalJumpNode extends AbstractBytecodeNode { @Child private FrameStackPopNode popNode = FrameStackPopNode.create(); - protected ConditionalJumpNode(final CompiledCodeObject code, final int index, final int numBytecodes, final int bytecode) { + protected ConditionalJumpNode(final CompiledCodeObject code, final int index, final int numBytecodes, final int offset) { super(code, index, numBytecodes); - offset = (bytecode & 7) + 1; - } - - protected ConditionalJumpNode(final CompiledCodeObject code, final int index, final int numBytecodes, final int bytecode, final byte parameter) { - super(code, index, numBytecodes); - offset = ((bytecode & 3) << 8) + Byte.toUnsignedInt(parameter); + this.offset = offset; } @Override @@ -57,19 +52,27 @@ public final int getJumpSuccessorIndex() { } } - public static final class ConditionalFalseJumpNode extends ConditionalJumpNode { - public ConditionalFalseJumpNode(final CompiledCodeObject code, final int index, final int bytecode) { - super(code, index, 1, bytecode); + public static final class ConditionalJumpOnFalseNode extends ConditionalJumpNode { + private ConditionalJumpOnFalseNode(final CompiledCodeObject code, final int index, final int numBytecodes, final int offset) { + super(code, index, numBytecodes, offset); } - public ConditionalFalseJumpNode(final CompiledCodeObject code, final int index, final int bytecode, final byte parameter) { - super(code, index, 2, bytecode, parameter); + public static ConditionalJumpOnFalseNode createShort(final CompiledCodeObject code, final int index, final int bytecode) { + return new ConditionalJumpOnFalseNode(code, index, 1, calculateShortOffset(bytecode)); + } + + public static ConditionalJumpOnFalseNode createLong(final CompiledCodeObject code, final int index, final int bytecode, final byte parameter) { + return new ConditionalJumpOnFalseNode(code, index, 2, ((bytecode & 3) << 8) + Byte.toUnsignedInt(parameter)); + } + + public static ConditionalJumpOnFalseNode createLongExtended(final CompiledCodeObject code, final int index, final int numBytecodes, final byte bytecode, final int extB) { + return new ConditionalJumpOnFalseNode(code, index, numBytecodes, Byte.toUnsignedInt(bytecode) + (extB << 8)); } @Override public String toString() { CompilerAsserts.neverPartOfCompilation(); - return "jumpTrue: " + offset; + return "jumpFalse: " + offset; } @Override @@ -78,9 +81,21 @@ protected boolean check(final boolean value) { } } - public static final class ConditionalTrueJumpNode extends ConditionalJumpNode { - public ConditionalTrueJumpNode(final CompiledCodeObject code, final int index, final int bytecode, final byte parameter) { - super(code, index, 2, bytecode, parameter); + public static final class ConditionalJumpOnTrueNode extends ConditionalJumpNode { + private ConditionalJumpOnTrueNode(final CompiledCodeObject code, final int index, final int numBytecodes, final int offset) { + super(code, index, numBytecodes, offset); + } + + public static ConditionalJumpOnTrueNode createShort(final CompiledCodeObject code, final int index, final int bytecode) { + return new ConditionalJumpOnTrueNode(code, index, 1, calculateShortOffset(bytecode)); + } + + public static ConditionalJumpOnTrueNode createLong(final CompiledCodeObject code, final int index, final int bytecode, final byte parameter) { + return new ConditionalJumpOnTrueNode(code, index, 2, ((bytecode & 3) << 8) + Byte.toUnsignedInt(parameter)); + } + + public static ConditionalJumpOnTrueNode createLongExtended(final CompiledCodeObject code, final int index, final int numBytecodes, final byte bytecode, final int extB) { + return new ConditionalJumpOnTrueNode(code, index, numBytecodes, Byte.toUnsignedInt(bytecode) + (extB << 8)); } @Override @@ -98,14 +113,21 @@ protected boolean check(final boolean value) { public static final class UnconditionalJumpNode extends AbstractBytecodeNode { private final int offset; - public UnconditionalJumpNode(final CompiledCodeObject code, final int index, final int numBytecodes, final int bytecode) { + private UnconditionalJumpNode(final CompiledCodeObject code, final int index, final int numBytecodes, final int offset) { super(code, index, numBytecodes); - offset = (bytecode & 7) + 1; + this.offset = offset; } - public UnconditionalJumpNode(final CompiledCodeObject code, final int index, final int numBytecodes, final int bytecode, final byte parameter) { - super(code, index, numBytecodes); - offset = ((bytecode & 7) - 4 << 8) + Byte.toUnsignedInt(parameter); + public static UnconditionalJumpNode createShort(final CompiledCodeObject code, final int index, final int bytecode) { + return new UnconditionalJumpNode(code, index, 1, calculateShortOffset(bytecode)); + } + + public static UnconditionalJumpNode createLong(final CompiledCodeObject code, final int index, final int bytecode, final byte parameter) { + return new UnconditionalJumpNode(code, index, 2, ((bytecode & 7) - 4 << 8) + Byte.toUnsignedInt(parameter)); + } + + public static UnconditionalJumpNode createLongExtended(final CompiledCodeObject code, final int index, final int numBytecodes, final byte bytecode, final int extB) { + return new UnconditionalJumpNode(code, index, numBytecodes, Byte.toUnsignedInt(bytecode) + (extB << 8)); } @Override @@ -123,4 +145,8 @@ public String toString() { return "jumpTo: " + offset; } } + + private static int calculateShortOffset(final int bytecode) { + return (bytecode & 7) + 1; + } } diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/bytecodes/MiscellaneousBytecodes.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/bytecodes/MiscellaneousBytecodes.java index 54ee4cfc4..a21de1f06 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/bytecodes/MiscellaneousBytecodes.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/bytecodes/MiscellaneousBytecodes.java @@ -16,12 +16,12 @@ import de.hpi.swa.trufflesqueak.nodes.bytecodes.PushBytecodes.PushTemporaryLocationNode; import de.hpi.swa.trufflesqueak.nodes.bytecodes.SendBytecodes.SendSelfSelectorNode; import de.hpi.swa.trufflesqueak.nodes.bytecodes.SendBytecodes.SingleExtendedSuperNode; -import de.hpi.swa.trufflesqueak.nodes.bytecodes.StoreBytecodes.PopIntoAssociationNode; +import de.hpi.swa.trufflesqueak.nodes.bytecodes.StoreBytecodes.PopIntoLiteralVariableNode; import de.hpi.swa.trufflesqueak.nodes.bytecodes.StoreBytecodes.PopIntoReceiverVariableNode; import de.hpi.swa.trufflesqueak.nodes.bytecodes.StoreBytecodes.PopIntoTemporaryLocationNode; -import de.hpi.swa.trufflesqueak.nodes.bytecodes.StoreBytecodes.StoreIntoAssociationNode; +import de.hpi.swa.trufflesqueak.nodes.bytecodes.StoreBytecodes.StoreIntoLiteralVariableNode; import de.hpi.swa.trufflesqueak.nodes.bytecodes.StoreBytecodes.StoreIntoReceiverVariableNode; -import de.hpi.swa.trufflesqueak.nodes.bytecodes.StoreBytecodes.StoreIntoTempNode; +import de.hpi.swa.trufflesqueak.nodes.bytecodes.StoreBytecodes.StoreIntoTemporaryLocationNode; import de.hpi.swa.trufflesqueak.nodes.context.frame.FrameStackPopNode; import de.hpi.swa.trufflesqueak.nodes.context.frame.FrameStackPushNode; import de.hpi.swa.trufflesqueak.nodes.context.frame.FrameStackTopNode; @@ -36,16 +36,16 @@ public static final class CallPrimitiveNode extends AbstractBytecodeNode { @Child public AbstractPrimitiveNode primitiveNode; private final int primitiveIndex; - public CallPrimitiveNode(final CompiledCodeObject method, final int index, final byte byte1, final byte byte2) { + public CallPrimitiveNode(final CompiledCodeObject method, final int index, final int primitiveIndex) { super(method, index, NUM_BYTECODES); assert method.hasPrimitive(); - primitiveIndex = Byte.toUnsignedInt(byte1) + (Byte.toUnsignedInt(byte2) << 8); + this.primitiveIndex = primitiveIndex; primitiveNode = PrimitiveNodeFactory.forIndex(method, false, primitiveIndex); assert method.hasPrimitive(); } public static CallPrimitiveNode create(final CompiledCodeObject code, final int index, final byte byte1, final byte byte2) { - return new CallPrimitiveNode(code, index, byte1, byte2); + return new CallPrimitiveNode(code, index, Byte.toUnsignedInt(byte1) + (Byte.toUnsignedInt(byte2) << 8)); } @Override @@ -81,7 +81,7 @@ public static AbstractInstrumentableBytecodeNode create(final CompiledCodeObject case 6: return new PopIntoReceiverVariableNode(code, index, numBytecodes, third); case 7: - return new StoreIntoAssociationNode(code, index, numBytecodes, third); + return new StoreIntoLiteralVariableNode(code, index, numBytecodes, third); default: return new UnknownBytecodeNode(code, index, numBytecodes, second); } @@ -92,8 +92,8 @@ public static final class DupNode extends AbstractInstrumentableBytecodeNode { @Child private FrameStackPushNode pushNode = FrameStackPushNode.create(); @Child private FrameStackTopNode topNode = FrameStackTopNode.create(); - public DupNode(final CompiledCodeObject code, final int index, final int numBytecodes) { - super(code, index, numBytecodes); + public DupNode(final CompiledCodeObject code, final int index) { + super(code, index, 1); } @Override @@ -120,7 +120,7 @@ public static AbstractInstrumentableBytecodeNode createPopInto(final CompiledCod case 2: return new UnknownBytecodeNode(code, index, numBytecodes, nextByte); case 3: - return new PopIntoAssociationNode(code, index, numBytecodes, variableIndex); + return new PopIntoLiteralVariableNode(code, index, numBytecodes, variableIndex); default: throw SqueakException.create("illegal ExtendedStore bytecode"); } @@ -148,11 +148,11 @@ public static AbstractInstrumentableBytecodeNode createStoreInto(final CompiledC case 0: return new StoreIntoReceiverVariableNode(code, index, numBytecodes, variableIndex); case 1: - return new StoreIntoTempNode(code, index, numBytecodes, variableIndex); + return new StoreIntoTemporaryLocationNode(code, index, numBytecodes, variableIndex); case 2: return new UnknownBytecodeNode(code, index, numBytecodes, nextByte); case 3: - return new StoreIntoAssociationNode(code, index, numBytecodes, variableIndex); + return new StoreIntoLiteralVariableNode(code, index, numBytecodes, variableIndex); default: throw SqueakException.create("illegal ExtendedStore bytecode"); } @@ -170,8 +170,8 @@ public static byte variableType(final byte i) { public static final class PopNode extends AbstractInstrumentableBytecodeNode { @Child private FrameStackPopNode popNode = FrameStackPopNode.create(); - public PopNode(final CompiledCodeObject code, final int index, final int numBytecodes) { - super(code, index, numBytecodes); + public PopNode(final CompiledCodeObject code, final int index) { + super(code, index, 1); } @Override @@ -186,6 +186,22 @@ public String toString() { } } + public static final class NopBytecodeNode extends AbstractInstrumentableBytecodeNode { + public NopBytecodeNode(final CompiledCodeObject code, final int index) { + super(code, index, 1); + } + + @Override + public void executeVoid(final VirtualFrame frame) { + } + + @Override + public String toString() { + CompilerAsserts.neverPartOfCompilation(); + return "nop"; + } + } + public static final class UnknownBytecodeNode extends AbstractInstrumentableBytecodeNode { private final long bytecode; diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/bytecodes/PushBytecodes.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/bytecodes/PushBytecodes.java index 3d30432d9..a498d3f09 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/bytecodes/PushBytecodes.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/bytecodes/PushBytecodes.java @@ -27,6 +27,7 @@ import de.hpi.swa.trufflesqueak.model.ArrayObject; import de.hpi.swa.trufflesqueak.model.BlockClosureObject; import de.hpi.swa.trufflesqueak.model.BooleanObject; +import de.hpi.swa.trufflesqueak.model.CharacterObject; import de.hpi.swa.trufflesqueak.model.CompiledCodeObject; import de.hpi.swa.trufflesqueak.model.ContextObject; import de.hpi.swa.trufflesqueak.model.NilObject; @@ -90,11 +91,11 @@ public static class PushClosureNode extends AbstractBytecodeNode implements Inst @Child private GetOrCreateContextNode getOrCreateContextNode = GetOrCreateContextNode.create(true); @CompilationFinal private ContextReference contextReference; - private PushClosureNode(final CompiledCodeObject code, final int index, final int numBytecodes, final byte i, final byte j, final byte k) { + private PushClosureNode(final CompiledCodeObject code, final int index, final int numBytecodes, final int numArgs, final int numCopied, final int blockSize) { super(code, index, numBytecodes); - numArgs = i & 0xF; - numCopied = Byte.toUnsignedInt(i) >> 4 & 0xF; - blockSize = Byte.toUnsignedInt(j) << 8 | Byte.toUnsignedInt(k); + this.numArgs = numArgs; + this.numCopied = numCopied; + this.blockSize = blockSize; popNNode = FrameStackPopNNode.create(numCopied); } @@ -107,7 +108,14 @@ public PushClosureNode(final PushClosureNode node) { } public static PushClosureNode create(final CompiledCodeObject code, final int index, final int numBytecodes, final byte i, final byte j, final byte k) { - return new PushClosureNode(code, index, numBytecodes, i, j, k); + return new PushClosureNode(code, index, numBytecodes, i & 0xF, Byte.toUnsignedInt(i) >> 4 & 0xF, Byte.toUnsignedInt(j) << 8 | Byte.toUnsignedInt(k)); + } + + public static PushClosureNode createExtended(final CompiledCodeObject code, final int index, final int numBytecodes, final int extA, final int extB, final byte byteA, final byte byteB) { + final int numArgs = (byteA & 7) + Math.floorMod(extA, 16) * 8; + final int numCopied = (Byte.toUnsignedInt(byteA) >> 3 & 0x7) + Math.floorDiv(extA, 16) * 8; + final int blockSize = Byte.toUnsignedInt(byteB) + (extB << 8); + return new PushClosureNode(code, index, numBytecodes, numArgs, numCopied, blockSize); } private CompiledCodeObject getBlock(final VirtualFrame frame) { @@ -175,7 +183,7 @@ public String toString() { } @NodeInfo(cost = NodeCost.NONE) - public abstract static class PushConstantNode extends AbstractPushNode { + private abstract static class PushConstantNode extends AbstractPushNode { private PushConstantNode(final CompiledCodeObject code, final int index) { super(code, index); } @@ -192,82 +200,82 @@ public final String toString() { CompilerAsserts.neverPartOfCompilation(); return "pushConstant: " + getConstant().toString(); } + } - public static final class PushConstantTrueNode extends PushConstantNode { - public PushConstantTrueNode(final CompiledCodeObject code, final int index) { - super(code, index); - } + public static final class PushConstantTrueNode extends PushConstantNode { + public PushConstantTrueNode(final CompiledCodeObject code, final int index) { + super(code, index); + } - @Override - protected Object getConstant() { - return BooleanObject.TRUE; - } + @Override + protected Object getConstant() { + return BooleanObject.TRUE; } + } - public static final class PushConstantFalseNode extends PushConstantNode { - public PushConstantFalseNode(final CompiledCodeObject code, final int index) { - super(code, index); - } + public static final class PushConstantFalseNode extends PushConstantNode { + public PushConstantFalseNode(final CompiledCodeObject code, final int index) { + super(code, index); + } - @Override - protected Object getConstant() { - return BooleanObject.FALSE; - } + @Override + protected Object getConstant() { + return BooleanObject.FALSE; } + } - public static final class PushConstantNilNode extends PushConstantNode { - public PushConstantNilNode(final CompiledCodeObject code, final int index) { - super(code, index); - } + public static final class PushConstantNilNode extends PushConstantNode { + public PushConstantNilNode(final CompiledCodeObject code, final int index) { + super(code, index); + } - @Override - protected Object getConstant() { - return NilObject.SINGLETON; - } + @Override + protected Object getConstant() { + return NilObject.SINGLETON; } + } - public static final class PushConstantMinusOneNode extends PushConstantNode { - public PushConstantMinusOneNode(final CompiledCodeObject code, final int index) { - super(code, index); - } + public static final class PushConstantMinusOneNode extends PushConstantNode { + public PushConstantMinusOneNode(final CompiledCodeObject code, final int index) { + super(code, index); + } - @Override - protected Object getConstant() { - return -1L; - } + @Override + protected Object getConstant() { + return -1L; } + } - public static final class PushConstantZeroNode extends PushConstantNode { - public PushConstantZeroNode(final CompiledCodeObject code, final int index) { - super(code, index); - } + public static final class PushConstantZeroNode extends PushConstantNode { + public PushConstantZeroNode(final CompiledCodeObject code, final int index) { + super(code, index); + } - @Override - protected Object getConstant() { - return 0L; - } + @Override + protected Object getConstant() { + return 0L; } + } - public static final class PushConstantOneNode extends PushConstantNode { - public PushConstantOneNode(final CompiledCodeObject code, final int index) { - super(code, index); - } + public static final class PushConstantOneNode extends PushConstantNode { + public PushConstantOneNode(final CompiledCodeObject code, final int index) { + super(code, index); + } - @Override - protected Object getConstant() { - return 1L; - } + @Override + protected Object getConstant() { + return 1L; } + } - public static final class PushConstantTwoNode extends PushConstantNode { - public PushConstantTwoNode(final CompiledCodeObject code, final int index) { - super(code, index); - } + public static final class PushConstantTwoNode extends PushConstantNode { + public PushConstantTwoNode(final CompiledCodeObject code, final int index) { + super(code, index); + } - @Override - protected Object getConstant() { - return 2L; - } + @Override + protected Object getConstant() { + return 2L; } } @@ -288,7 +296,7 @@ public void executeVoid(final VirtualFrame frame) { @Override public String toString() { CompilerAsserts.neverPartOfCompilation(); - return "pushConstant: " + code.getLiteral(literalIndex).toString(); + return "pushConstant: " + code.getLiteral(literalIndex); } } @@ -482,4 +490,46 @@ public String toString() { return "pushTemp: " + tempIndex; } } + + @NodeInfo(cost = NodeCost.NONE) + public static final class PushSmallIntegerNode extends AbstractPushNode { + private final long value; + + public PushSmallIntegerNode(final CompiledCodeObject code, final int index, final int numBytecodes, final int value) { + super(code, index, numBytecodes); + this.value = value; + } + + @Override + public void executeVoid(final VirtualFrame frame) { + pushNode.execute(frame, value); + } + + @Override + public String toString() { + CompilerAsserts.neverPartOfCompilation(); + return "pushConstant: " + value; + } + } + + @NodeInfo(cost = NodeCost.NONE) + public static final class PushCharacterNode extends AbstractPushNode { + private final Object value; + + public PushCharacterNode(final CompiledCodeObject code, final int index, final int numBytecodes, final long value) { + super(code, index, numBytecodes); + this.value = CharacterObject.valueOf(value); + } + + @Override + public void executeVoid(final VirtualFrame frame) { + pushNode.execute(frame, value); + } + + @Override + public String toString() { + CompilerAsserts.neverPartOfCompilation(); + return "pushConstant: $" + value; + } + } } diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/bytecodes/ReturnBytecodes.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/bytecodes/ReturnBytecodes.java index 7b834a5bf..bd4290a64 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/bytecodes/ReturnBytecodes.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/bytecodes/ReturnBytecodes.java @@ -17,9 +17,9 @@ import de.hpi.swa.trufflesqueak.model.CompiledCodeObject; import de.hpi.swa.trufflesqueak.model.ContextObject; import de.hpi.swa.trufflesqueak.model.NilObject; -import de.hpi.swa.trufflesqueak.nodes.bytecodes.ReturnBytecodesFactory.ReturnConstantNodeGen.ReturnConstantFalseNodeGen; -import de.hpi.swa.trufflesqueak.nodes.bytecodes.ReturnBytecodesFactory.ReturnConstantNodeGen.ReturnConstantNilNodeGen; -import de.hpi.swa.trufflesqueak.nodes.bytecodes.ReturnBytecodesFactory.ReturnConstantNodeGen.ReturnConstantTrueNodeGen; +import de.hpi.swa.trufflesqueak.nodes.bytecodes.ReturnBytecodesFactory.ReturnConstantFalseNodeGen; +import de.hpi.swa.trufflesqueak.nodes.bytecodes.ReturnBytecodesFactory.ReturnConstantNilNodeGen; +import de.hpi.swa.trufflesqueak.nodes.bytecodes.ReturnBytecodesFactory.ReturnConstantTrueNodeGen; import de.hpi.swa.trufflesqueak.nodes.bytecodes.ReturnBytecodesFactory.ReturnReceiverNodeGen; import de.hpi.swa.trufflesqueak.nodes.bytecodes.ReturnBytecodesFactory.ReturnTopFromBlockNodeGen; import de.hpi.swa.trufflesqueak.nodes.bytecodes.ReturnBytecodesFactory.ReturnTopFromMethodNodeGen; @@ -92,8 +92,8 @@ protected final Object doClosureReturnFromMaterialized(final VirtualFrame frame, } } - public abstract static class ReturnConstantNode extends AbstractReturnWithSpecializationsNode { - protected ReturnConstantNode(final CompiledCodeObject code, final int index) { + protected abstract static class AbstractReturnConstantNode extends AbstractReturnWithSpecializationsNode { + protected AbstractReturnConstantNode(final CompiledCodeObject code, final int index) { super(code, index); } @@ -102,50 +102,50 @@ public final String toString() { CompilerAsserts.neverPartOfCompilation(); return "return: " + getReturnValue(null).toString(); } + } - public abstract static class ReturnConstantTrueNode extends ReturnConstantNode { - protected ReturnConstantTrueNode(final CompiledCodeObject code, final int index) { - super(code, index); - } + public abstract static class ReturnConstantTrueNode extends AbstractReturnConstantNode { + protected ReturnConstantTrueNode(final CompiledCodeObject code, final int index) { + super(code, index); + } - public static ReturnConstantTrueNode create(final CompiledCodeObject code, final int index) { - return ReturnConstantTrueNodeGen.create(code, index); - } + public static ReturnConstantTrueNode create(final CompiledCodeObject code, final int index) { + return ReturnConstantTrueNodeGen.create(code, index); + } - @Override - protected final Object getReturnValue(final VirtualFrame frame) { - return BooleanObject.TRUE; - } + @Override + protected final Object getReturnValue(final VirtualFrame frame) { + return BooleanObject.TRUE; } + } - public abstract static class ReturnConstantFalseNode extends ReturnConstantNode { - protected ReturnConstantFalseNode(final CompiledCodeObject code, final int index) { - super(code, index); - } + public abstract static class ReturnConstantFalseNode extends AbstractReturnConstantNode { + protected ReturnConstantFalseNode(final CompiledCodeObject code, final int index) { + super(code, index); + } - public static ReturnConstantFalseNode create(final CompiledCodeObject code, final int index) { - return ReturnConstantFalseNodeGen.create(code, index); - } + public static ReturnConstantFalseNode create(final CompiledCodeObject code, final int index) { + return ReturnConstantFalseNodeGen.create(code, index); + } - @Override - protected final Object getReturnValue(final VirtualFrame frame) { - return BooleanObject.FALSE; - } + @Override + protected final Object getReturnValue(final VirtualFrame frame) { + return BooleanObject.FALSE; } + } - public abstract static class ReturnConstantNilNode extends ReturnConstantNode { - protected ReturnConstantNilNode(final CompiledCodeObject code, final int index) { - super(code, index); - } + public abstract static class ReturnConstantNilNode extends AbstractReturnConstantNode { + protected ReturnConstantNilNode(final CompiledCodeObject code, final int index) { + super(code, index); + } - public static ReturnConstantNilNode create(final CompiledCodeObject code, final int index) { - return ReturnConstantNilNodeGen.create(code, index); - } + public static ReturnConstantNilNode create(final CompiledCodeObject code, final int index) { + return ReturnConstantNilNodeGen.create(code, index); + } - @Override - protected final Object getReturnValue(final VirtualFrame frame) { - return NilObject.SINGLETON; - } + @Override + protected final Object getReturnValue(final VirtualFrame frame) { + return NilObject.SINGLETON; } } diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/bytecodes/SendBytecodes.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/bytecodes/SendBytecodes.java index 54e6cdb61..04692ca8c 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/bytecodes/SendBytecodes.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/bytecodes/SendBytecodes.java @@ -25,6 +25,7 @@ import de.hpi.swa.trufflesqueak.nodes.context.frame.FrameStackPushNode; import de.hpi.swa.trufflesqueak.nodes.dispatch.DispatchLookupResultNode; import de.hpi.swa.trufflesqueak.nodes.dispatch.DispatchSuperSendNode; +import de.hpi.swa.trufflesqueak.nodes.dispatch.DispatchSuperSendStackedNode; import de.hpi.swa.trufflesqueak.nodes.dispatch.LookupClassNode; import de.hpi.swa.trufflesqueak.nodes.dispatch.LookupSelectorNode; import de.hpi.swa.trufflesqueak.nodes.primitives.impl.ControlPrimitives.PrimExitToDebuggerNode; @@ -221,4 +222,30 @@ public String toString() { return "sendSuper: " + getSelector().asStringUnsafe(); } } + + public static final class SendToSuperclassStackedNode extends AbstractSendNode { + @Child private DispatchSuperSendStackedNode dispatchNode; + + public SendToSuperclassStackedNode(final CompiledCodeObject code, final int index, final int numBytecodes, final int literalIndex, final int numArgs) { + super(code, index, numBytecodes, numArgs); + final NativeObject selector = (NativeObject) code.getLiteral(literalIndex); + dispatchNode = DispatchSuperSendStackedNode.create(selector, numArgs); + } + + @Override + protected Object dispatchSend(final VirtualFrame frame) { + return dispatchNode.execute(frame); + } + + @Override + public NativeObject getSelector() { + return dispatchNode.getSelector(); + } + + @Override + public String toString() { + CompilerAsserts.neverPartOfCompilation(); + return "sendSuper: " + getSelector().asStringUnsafe(); + } + } } diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/bytecodes/SqueakBytecodeSistaV1Decoder.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/bytecodes/SqueakBytecodeSistaV1Decoder.java new file mode 100644 index 000000000..b08676f11 --- /dev/null +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/bytecodes/SqueakBytecodeSistaV1Decoder.java @@ -0,0 +1,550 @@ +/* + * Copyright (c) 2017-2020 Software Architecture Group, Hasso Plattner Institute + * + * Licensed under the MIT License. + */ +package de.hpi.swa.trufflesqueak.nodes.bytecodes; + +import com.oracle.truffle.api.CompilerAsserts; + +import de.hpi.swa.trufflesqueak.exceptions.SqueakExceptions.SqueakException; +import de.hpi.swa.trufflesqueak.model.CompiledCodeObject; +import de.hpi.swa.trufflesqueak.model.layout.ObjectLayouts.SPECIAL_OBJECT; + +public final class SqueakBytecodeSistaV1Decoder { + private SqueakBytecodeSistaV1Decoder() { + } + + public static AbstractBytecodeNode[] decode(final CompiledCodeObject code) { + final int trailerPosition = trailerPosition(code); + final AbstractBytecodeNode[] nodes = new AbstractBytecodeNode[trailerPosition]; + int index = 0; + while (index < trailerPosition) { + final AbstractBytecodeNode bytecodeNode = decodeBytecode(code, index); + nodes[index] = bytecodeNode; + index = bytecodeNode.getSuccessorIndex(); + } + return nodes; + } + + public static int findLineNumber(final CompiledCodeObject code, final int targetIndex) { + final int trailerPosition = trailerPosition(code); + assert 0 <= targetIndex && targetIndex <= trailerPosition; + int index = 0; + int lineNumber = 1; + while (index != targetIndex) { + index += decodeNumBytes(code, index); + lineNumber++; + } + assert lineNumber <= trailerPosition; + return lineNumber; + } + + public static int trailerPosition(final CompiledCodeObject code) { + return code.isCompiledBlock() ? code.getBytes().length : trailerPosition(code.getBytes()); + } + + private static int trailerPosition(final byte[] bytecode) { + final int bytecodeLength = bytecode.length; + final int flagByte = Byte.toUnsignedInt(bytecode[bytecodeLength - 1]); + final int index = (flagByte >> 2) + 1; + switch (index) { + case 1: // #decodeNoTrailer + case 5: // #decodeSourceBySelector + return bytecodeLength - 1; + case 2: // #decodeClearedTrailer + case 3: // #decodeTempsNamesQCompress + case 4: // #decodeTempsNamesZip + case 6: // #decodeSourceByStringIdentifier + case 7: // #decodeEmbeddedSourceQCompress + case 8: // #decodeEmbeddedSourceZip + return decodeLengthField(bytecode, bytecodeLength, flagByte); + case 9: // decodeVarLengthSourcePointer + int pos = bytecodeLength - 2; + while (bytecode[pos] < 0) { + pos--; + } + return pos; + case 64: // decodeSourcePointer + return bytecodeLength - 4; + default: + throw SqueakException.create("Undefined method encoding (see CompiledMethodTrailer)."); + } + } + + private static int decodeLengthField(final byte[] bytecode, final int bytecodeLength, final int flagByte) { + final int numBytes = (flagByte & 3) + 1; + int length = 0; + final int firstLengthValueIndex = bytecodeLength - 2; + for (int i = 0; i < numBytes; i++) { + length = (length << 8) + Byte.toUnsignedInt(bytecode[firstLengthValueIndex - i]); + } + return bytecodeLength - (1 + numBytes + length); + } + + public static AbstractBytecodeNode decodeBytecode(final CompiledCodeObject code, final int index) { + return decodeBytecode(code, index, 0, 0, 0); + } + + public static AbstractBytecodeNode decodeBytecode(final CompiledCodeObject code, final int index, final int extBytes, final int extA, final int extB) { + CompilerAsserts.neverPartOfCompilation(); + final byte[] bytecode = code.getBytes(); + final int indexWithExt = index + extBytes; + final int b = Byte.toUnsignedInt(bytecode[indexWithExt]); + //@formatter:off + switch (b) { + case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: + case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15: + return PushBytecodes.PushReceiverVariableNode.create(code, index, 1, b & 15); + case 16: case 17: case 18: case 19: case 20: case 21: case 22: case 23: + case 24: case 25: case 26: case 27: case 28: case 29: case 30: case 31: + return new PushBytecodes.PushLiteralVariableNode(code, index, 1, b & 15); + case 32: case 33: case 34: case 35: case 36: case 37: case 38: case 39: + case 40: case 41: case 42: case 43: case 44: case 45: case 46: case 47: + case 48: case 49: case 50: case 51: case 52: case 53: case 54: case 55: + case 56: case 57: case 58: case 59: case 60: case 61: case 62: case 63: + return new PushBytecodes.PushLiteralConstantNode(code, index, 1, b & 31); + case 64: case 65: case 66: case 67: case 68: case 69: case 70: case 71: + return new PushBytecodes.PushTemporaryLocationNode(code, index, 1, b & 7); + case 72: case 73: case 74: case 75: + return new PushBytecodes.PushTemporaryLocationNode(code, index, 1, (b & 3) + 8); + case 76: + return PushBytecodes.PushReceiverNode.create(code, index); + case 77: + return new PushBytecodes.PushConstantTrueNode(code, index); + case 78: + return new PushBytecodes.PushConstantFalseNode(code, index); + case 79: + return new PushBytecodes.PushConstantNilNode(code, index); + case 80: + return new PushBytecodes.PushConstantZeroNode(code, index); + case 81: + return new PushBytecodes.PushConstantOneNode(code, index); + case 82: + return new PushBytecodes.PushActiveContextNode(code, index); // FIXME: Push thisContext, (then Extend B = 1 => push thisProcess) + case 83: + return new MiscellaneousBytecodes.DupNode(code, index); + case 84: case 85: case 86: case 87: + return new MiscellaneousBytecodes.UnknownBytecodeNode(code, index, 1, b); + case 88: + return ReturnBytecodes.ReturnReceiverNode.create(code, index); + case 89: + return ReturnBytecodes.ReturnConstantTrueNode.create(code, index); + case 90: + return ReturnBytecodes.ReturnConstantFalseNode.create(code, index); + case 91: + return ReturnBytecodes.ReturnConstantNilNode.create(code, index); + case 92: + return ReturnBytecodes.ReturnTopFromMethodNode.create(code, index); + case 93: + return ReturnBytecodes.ReturnTopFromBlockNode.create(code, index); // FIXME: BlockReturn nil + case 94: + return ReturnBytecodes.ReturnTopFromBlockNode.create(code, index); // FIXME: BlockReturn Top [* return from enclosing block N, N = Extend A, then jump by Ext B ] + case 95: + return new MiscellaneousBytecodes.NopBytecodeNode(code, index); + case 96: case 97: case 98: case 99: case 100: case 101: case 102: case 103: + case 104: case 105: case 106: case 107: case 108: case 109: case 110: case 111: + case 112: case 113: case 114: case 115: case 116: case 117: case 118: case 119: + case 120: case 121: case 122: case 123: case 124: case 125: case 126: case 127: + return SendBytecodes.SendSpecialSelectorNode.create(code, index, b - 96); + case 128: case 129: case 130: case 131: case 132: case 133: case 134: case 135: + case 136: case 137: case 138: case 139: case 140: case 141: case 142: case 143: + return SendBytecodes.SendLiteralSelectorNode.create(code, index, 1, b & 0xF, 0); + case 144: case 145: case 146: case 147: case 148: case 149: case 150: case 151: + case 152: case 153: case 154: case 155: case 156: case 157: case 158: case 159: + return SendBytecodes.SendLiteralSelectorNode.create(code, index, 1, b & 0xF, 1); + case 160: case 161: case 162: case 163: case 164: case 165: case 166: case 167: + case 168: case 169: case 170: case 171: case 172: case 173: case 174: case 175: + return SendBytecodes.SendLiteralSelectorNode.create(code, index, 1, b & 0xF, 2); + case 176: case 177: case 178: case 179: case 180: case 181: case 182: case 183: + return JumpBytecodes.UnconditionalJumpNode.createShort(code, index, b); + case 184: case 185: case 186: case 187: case 188: case 189: case 190: case 191: + return JumpBytecodes.ConditionalJumpOnTrueNode.createShort(code, index, b); + case 192: case 193: case 194: case 195: case 196: case 197: case 198: case 199: + return JumpBytecodes.ConditionalJumpOnFalseNode.createShort(code, index, b); + case 200: case 201: case 202: case 203: case 204: case 205: case 206: case 207: + return new StoreBytecodes.PopIntoReceiverVariableNode(code, index, 1, b & 7); + case 208: case 209: case 210: case 211: case 212: case 213: case 214: case 215: + return new StoreBytecodes.PopIntoTemporaryLocationNode(code, index, 1, b & 7); + case 216: + return new MiscellaneousBytecodes.PopNode(code, index); + case 217: + return new SendBytecodes.SendSelfSelectorNode(code, index, 1, code.getSqueakClass().getImage().getSpecialSelector(SPECIAL_OBJECT.SELECTOR_SISTA_TRAP), 1); // FIXME: Unconditional trap + case 218: case 219: case 220: case 221: case 222: case 223: + return new MiscellaneousBytecodes.UnknownBytecodeNode(code, index, 1, b); + case 224: + return decodeBytecode(code, index, extBytes + 2, (extA << 8) + Byte.toUnsignedInt(bytecode[indexWithExt + 1]), extB); + case 225: + return decodeBytecode(code, index, extBytes + 2, extA, (extB << 8) + bytecode[indexWithExt + 1]); + case 226: + return PushBytecodes.PushReceiverVariableNode.create(code, index, 2 + extBytes, Byte.toUnsignedInt(bytecode[indexWithExt + 1]) + (extA << 8)); + case 227: + return new PushBytecodes.PushLiteralVariableNode(code, index, 2 + extBytes, Byte.toUnsignedInt(bytecode[indexWithExt + 1]) + (extA << 8)); + case 228: + return new PushBytecodes.PushLiteralConstantNode(code, index, 2 + extBytes, Byte.toUnsignedInt(bytecode[indexWithExt + 1]) + (extA << 8)); + case 229: + return new PushBytecodes.PushTemporaryLocationNode(code, index, 2, Byte.toUnsignedInt(bytecode[indexWithExt + 1])); + case 230: + return new MiscellaneousBytecodes.UnknownBytecodeNode(code, index, 1, b); + case 231: + return PushBytecodes.PushNewArrayNode.create(code, index, 2, bytecode[indexWithExt + 1]); + case 232: + return new PushBytecodes.PushSmallIntegerNode(code, index, 2 + extBytes, Byte.toUnsignedInt(bytecode[indexWithExt + 1]) + (extB << 8)); + case 233: + return new PushBytecodes.PushCharacterNode(code, index, 2 + extBytes, Byte.toUnsignedInt(bytecode[indexWithExt + 1]) + (extB << 8)); + case 234: { + final int nextByte = Byte.toUnsignedInt(bytecode[indexWithExt + 1]); + return SendBytecodes.SendLiteralSelectorNode.create(code, index, 2 + extBytes, (nextByte >> 3) + (extA << 5), (nextByte & 7) + (extB << 3)); + } + case 235: { + final int intValue = Byte.toUnsignedInt(bytecode[indexWithExt + 1]); + final int i = intValue >> 3; + final int j = intValue & 7; + if (extB < 64) { + return new SendBytecodes.SingleExtendedSuperNode(code, index, 2 + extBytes, i + (extA << 8), j + (extB << 3)); + } else { + return new SendBytecodes.SendToSuperclassStackedNode(code, index, 2 + extBytes, i + (extA << 8), j + ((extB & 63) << 3)); + } + } + case 236: + return new MiscellaneousBytecodes.UnknownBytecodeNode(code, index, 1, b); + case 237: + return JumpBytecodes.UnconditionalJumpNode.createLongExtended(code, index, 2 + extBytes, bytecode[indexWithExt + 1], extB); + case 238: + return JumpBytecodes.ConditionalJumpOnTrueNode.createLongExtended(code, index, 2 + extBytes, bytecode[indexWithExt + 1], extB); + case 239: + return JumpBytecodes.ConditionalJumpOnFalseNode.createLongExtended(code, index, 2 + extBytes, bytecode[indexWithExt + 1], extB); + case 240: + return new StoreBytecodes.PopIntoReceiverVariableNode(code, index, 2 + extBytes, bytecode[indexWithExt + 1] + (extA << 8)); + case 241: + return new StoreBytecodes.PopIntoLiteralVariableNode(code, index, 2 + extBytes, bytecode[indexWithExt + 1] + (extA << 8)); + case 242: + return new StoreBytecodes.PopIntoTemporaryLocationNode(code, index, 2 + extBytes, bytecode[indexWithExt + 1] + (extA << 8)); + case 243: + return new StoreBytecodes.StoreIntoReceiverVariableNode(code, index, 2 + extBytes, bytecode[indexWithExt + 1] + (extA << 8)); + case 244: + return new StoreBytecodes.StoreIntoLiteralVariableNode(code, index, 2 + extBytes, bytecode[indexWithExt + 1] + (extA << 8)); + case 245: + return new StoreBytecodes.StoreIntoTemporaryLocationNode(code, index, 2 + extBytes, bytecode[indexWithExt + 1] + (extA << 8)); + case 246: + case 247: + return new MiscellaneousBytecodes.UnknownBytecodeNode(code, index, 2, b); + case 248: { + // TODO: use `final boolean m = bytecode[indexWithExt + 2] >> 8 == 0;` + // TODO: use `final int s = bytecode[indexWithExt + 2] >> 5 & 3;` + final int j = bytecode[indexWithExt + 2] & 31; + final int primitiveIndex = Byte.toUnsignedInt(bytecode[indexWithExt + 1]) + j; + if (primitiveIndex < 1000) { + return new MiscellaneousBytecodes.CallPrimitiveNode(code, index, primitiveIndex); + } + switch (primitiveIndex) { + case 1000: + return new InlinePrimitiveBytecodes.PrimClassNode(code, index); + case 1001: + return new InlinePrimitiveBytecodes.PrimNumSlotsNode(code, index); + case 1002: + return new InlinePrimitiveBytecodes.PrimBasicSizeNode(code, index); + case 1003: + return new InlinePrimitiveBytecodes.PrimNumBytesNode(code, index); + case 1004: + return new InlinePrimitiveBytecodes.PrimNumShortsNode(code, index); + case 1005: + return new InlinePrimitiveBytecodes.PrimNumWordsNode(code, index); + case 1006: + return new InlinePrimitiveBytecodes.PrimNumDoubleWordsNode(code, index); + case 1020: + return new InlinePrimitiveBytecodes.PrimIdentityHashNode(code, index); + case 1021: + return new InlinePrimitiveBytecodes.PrimIdentityHashSmallIntegerNode(code, index); + case 1022: + return new InlinePrimitiveBytecodes.PrimIdentityHashCharacterNode(code, index); + case 1023: + return new InlinePrimitiveBytecodes.PrimIdentityHashSmallFloatNode(code, index); + case 1024: + return new InlinePrimitiveBytecodes.PrimIdentityHashBehaviorNode(code, index); + case 1030: + return new InlinePrimitiveBytecodes.PrimImmediateAsIntegerCharacterNode(code, index); + case 1031: + return new InlinePrimitiveBytecodes.PrimImmediateAsIntegerSmallFloatNode(code, index); + case 1032: + return new InlinePrimitiveBytecodes.PrimImmediateAsFloatNode(code, index); + case 2000: + return new InlinePrimitiveBytecodes.PrimSmallIntegerAddNode(code, index); + case 2001: + return new InlinePrimitiveBytecodes.PrimSmallIntegerSubtractNode(code, index); + case 2002: + return new InlinePrimitiveBytecodes.PrimSmallIntegerMultiplyNode(code, index); + case 2003: + return new InlinePrimitiveBytecodes.PrimSmallIntegerDivideNode(code, index); + case 2004: + return new InlinePrimitiveBytecodes.PrimSmallIntegerFloorDivideNode(code, index); + case 2005: + return new InlinePrimitiveBytecodes.PrimSmallIntegerFloorModNode(code, index); + case 2006: + return new InlinePrimitiveBytecodes.PrimSmallIntegerQuoNode(code, index); + case 2016: + return new InlinePrimitiveBytecodes.PrimSmallIntegerBitAndNode(code, index); + case 2017: + return new InlinePrimitiveBytecodes.PrimSmallIntegerBitOrNode(code, index); + case 2018: + return new InlinePrimitiveBytecodes.PrimSmallIntegerBitXorNode(code, index); + case 2019: + return new InlinePrimitiveBytecodes.PrimSmallIntegerBitShiftLeftNode(code, index); + case 2020: + return new InlinePrimitiveBytecodes.PrimSmallIntegerBitShiftRightNode(code, index); + case 2032: + return new InlinePrimitiveBytecodes.PrimSmallIntegerGreaterThanNode(code, index); + case 2033: + return new InlinePrimitiveBytecodes.PrimSmallIntegerLessThanNode(code, index); + case 2034: + return new InlinePrimitiveBytecodes.PrimSmallIntegerGreaterOrEqualNode(code, index); + case 2035: + return new InlinePrimitiveBytecodes.PrimSmallIntegerLessOrEqualNode(code, index); + case 2036: + return new InlinePrimitiveBytecodes.PrimSmallIntegerEqualNode(code, index); + case 2037: + return new InlinePrimitiveBytecodes.PrimSmallIntegerNotEqualNode(code, index); + case 2065: + return new InlinePrimitiveBytecodes.PrimByteAtNode(code, index); + case 2066: + return new InlinePrimitiveBytecodes.PrimShortAtNode(code, index); + case 2067: + return new InlinePrimitiveBytecodes.PrimWordAtNode(code, index); + case 2068: + return new InlinePrimitiveBytecodes.PrimDoubleWordAtNode(code, index); + case 3001: + return new InlinePrimitiveBytecodes.PrimByteAtPutNode(code, index); + case 3002: + return new InlinePrimitiveBytecodes.PrimShortAtPutNode(code, index); + case 3003: + return new InlinePrimitiveBytecodes.PrimWordAtPutNode(code, index); + case 3004: + return new InlinePrimitiveBytecodes.PrimDoubleWordAtPutNode(code, index); + case 3021: + return new InlinePrimitiveBytecodes.PrimByteEqualsNode(code, index); + case 4000: + return new InlinePrimitiveBytecodes.PrimFillFromToWithNode(code, index); + default: + return new MiscellaneousBytecodes.UnknownBytecodeNode(code, index, 3, b); + } + } + case 249: + return new MiscellaneousBytecodes.UnknownBytecodeNode(code, index, 3, b); // FIXME: PushBytecodes.PushClosureNode.createExtended(code, index, 3, bytecode[indexWithExt + 1], bytecode[indexWithExt + 2]); + case 250: + return PushBytecodes.PushClosureNode.createExtended(code, index, 3 + extBytes, extA, extB, bytecode[indexWithExt + 1], bytecode[indexWithExt + 2]); + case 251: + return new PushBytecodes.PushRemoteTempNode(code, index, 3, bytecode[indexWithExt + 1], bytecode[indexWithExt + 2]); + case 252: + return new StoreBytecodes.StoreIntoRemoteTempNode(code, index, 3, bytecode[indexWithExt + 1], bytecode[indexWithExt + 2]); + case 253: + return new StoreBytecodes.PopIntoRemoteTempNode(code, index, 3, bytecode[indexWithExt + 1], bytecode[indexWithExt + 2]); + case 254: + case 255: + return new MiscellaneousBytecodes.UnknownBytecodeNode(code, index, 3, b); + default: + throw SqueakException.create("Unknown bytecode:", b); + } + //@formatter:on + } + + public static String decodeToString(final CompiledCodeObject code) { + CompilerAsserts.neverPartOfCompilation(); + final StringBuilder sb = new StringBuilder(); + final int trailerPosition = trailerPosition(code); + int bytecodeIndex = 0; + int lineIndex = 1; + int indent = 0; + final byte[] bytes = code.getBytes(); + while (bytecodeIndex < trailerPosition) { + final int currentByte = Byte.toUnsignedInt(bytes[bytecodeIndex]); + sb.append(lineIndex); + for (int j = 0; j < 1 + indent; j++) { + sb.append(' '); + } + final int numBytecodes = decodeNumBytes(code, bytecodeIndex); + sb.append('<'); + for (int j = bytecodeIndex; j < bytecodeIndex + numBytecodes; j++) { + if (j > bytecodeIndex) { + sb.append(' '); + } + if (j < bytes.length) { + sb.append(String.format("%02X", bytes[j])); + } + } + sb.append("> "); + sb.append(decodeBytecodeToString(code, currentByte, bytecodeIndex)); + if (currentByte == 143) { + indent++; // increment indent on push closure + } else if (currentByte == 125) { + indent--; // decrement indent on block return + } + lineIndex++; + bytecodeIndex += numBytecodes; + if (bytecodeIndex < trailerPosition) { + sb.append('\n'); + } + } + return sb.toString(); + } + + private static String decodeBytecodeToString(final CompiledCodeObject code, final int b, final int index) { + final byte[] bytecode = code.getBytes(); + //@formatter:off + switch (b) { + case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: + case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15: + return "pushRcvr: " + (b & 15); + case 16: case 17: case 18: case 19: case 20: case 21: case 22: case 23: + case 24: case 25: case 26: case 27: case 28: case 29: case 30: case 31: + return "pushLitVar: " + code.getLiteral(b & 15); + case 32: case 33: case 34: case 35: case 36: case 37: case 38: case 39: + case 40: case 41: case 42: case 43: case 44: case 45: case 46: case 47: + case 48: case 49: case 50: case 51: case 52: case 53: case 54: case 55: + case 56: case 57: case 58: case 59: case 60: case 61: case 62: case 63: + return "pushConstant: " + code.getLiteral(b & 31); + case 64: case 65: case 66: case 67: case 68: case 69: case 70: case 71: + return "pushTemp: " + (b & 7); + case 72: case 73: case 74: case 75: + return "pushTemp: " + (b & 3) + 8; + case 76: + return "self"; + case 77: + return "pushConstant: true"; + case 78: + return "pushConstant: false"; + case 79: + return "pushConstant: nil"; + case 80: + return "pushConstant: 0"; + case 81: + return "pushConstant: 1"; + case 82: + return "pushThisContext:"; + case 83: + return "dup"; + case 84: case 85: case 86: case 87: + return "unknown"; + case 88: + return "returnSelf"; + case 89: + return "return: true"; + case 90: + return "return: false"; + case 91: + return "return: nil"; + case 92: + return "returnTop"; + case 93: + case 94: + return "blockReturn"; + case 95: + return "nop"; + case 96: case 97: case 98: case 99: case 100: case 101: case 102: case 103: + case 104: case 105: case 106: case 107: case 108: case 109: case 110: case 111: + case 112: case 113: case 114: case 115: case 116: case 117: case 118: case 119: + case 120: case 121: case 122: case 123: case 124: case 125: case 126: case 127: + return "send: " + code.getSqueakClass().getImage().getSpecialSelector(b - 96).asStringUnsafe(); + case 128: case 129: case 130: case 131: case 132: case 133: case 134: case 135: + case 136: case 137: case 138: case 139: case 140: case 141: case 142: case 143: + case 144: case 145: case 146: case 147: case 148: case 149: case 150: case 151: + case 152: case 153: case 154: case 155: case 156: case 157: case 158: case 159: + case 160: case 161: case 162: case 163: case 164: case 165: case 166: case 167: + case 168: case 169: case 170: case 171: case 172: case 173: case 174: case 175: + return "send: " + code.getLiteral(b & 0xF); + case 176: case 177: case 178: case 179: case 180: case 181: case 182: case 183: + return "jumpTo: "; + case 184: case 185: case 186: case 187: case 188: case 189: case 190: case 191: + return "jumpTrue: "; + case 192: case 193: case 194: case 195: case 196: case 197: case 198: case 199: + return "jumpFalse: "; + case 200: case 201: case 202: case 203: case 204: case 205: case 206: case 207: + return "popIntoRcvr: " + (b & 7); + case 208: case 209: case 210: case 211: case 212: case 213: case 214: case 215: + return "popIntoTemp: " + (b & 7); + case 216: + return "pop"; + case 217: + return "send: " + code.getSqueakClass().getImage().getSpecialSelector(SPECIAL_OBJECT.SELECTOR_SISTA_TRAP).asStringUnsafe(); + case 218: case 219: case 220: case 221: case 222: case 223: + return "unknown"; + case 224: + return "extA"; + case 225: + return "extB"; + case 226: + return "pushRcvr: "; + case 227: + return "pushLitVar: "; + case 228: + return "pushConstant: "; + case 229: + return "pushTemp: "; + case 230: + return "unknown"; + case 231: + return "push: (Array new: " + (bytecode[index + 1] & 127) + ")"; + case 232: + return "pushConstant: "; + case 233: + return "pushConstant: $"; + case 234: + return "send: "; + case 235: + return "sendSuper: "; + case 236: + return "unknown"; + case 237: + return "jumpTo: "; + case 238: + return "jumpTrue: "; + case 239: + return "jumpFalse: "; + case 240: + return "popIntoRcvr: "; + case 241: + return "popIntoLit: "; + case 242: + return "popIntoTemp: "; + case 243: + return "storeIntoRcvr: "; + case 244: + return "storeIntoLit: "; + case 245: + return "storeIntoTemp: "; + case 246: + case 247: + return "unknown"; + case 248: { + final int j = bytecode[index + 2] & 31; + final int primitiveIndex = Byte.toUnsignedInt(bytecode[index + 1]) + j; + return "callPrimitive: " + primitiveIndex; + } + case 249: + case 250: + return "closureNumCopied: numArgs: bytes to "; + case 251: + return "pushTemp: inVectorAt: "; + case 252: + return "storeTemp: inVectorAt: "; + case 253: + return "popTemp: inVectorAt: "; + case 254: + case 255: + return "unknown"; + default: + throw SqueakException.create("Unknown bytecode:", b); + } + //@formatter:on + } + + private static int decodeNumBytes(final CompiledCodeObject code, final int index) { + final int b = Byte.toUnsignedInt(code.getBytes()[index]); + if (b <= 223) { + return 1; + } else if (b <= 247) { + return 2; + } else { + return 3; + } + } +} diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/SqueakBytecodeDecoder.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/bytecodes/SqueakBytecodeV3PlusClosuresDecoder.java similarity index 72% rename from src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/SqueakBytecodeDecoder.java rename to src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/bytecodes/SqueakBytecodeV3PlusClosuresDecoder.java index def34d26b..60fea07be 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/SqueakBytecodeDecoder.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/bytecodes/SqueakBytecodeV3PlusClosuresDecoder.java @@ -3,56 +3,15 @@ * * Licensed under the MIT License. */ -package de.hpi.swa.trufflesqueak.util; +package de.hpi.swa.trufflesqueak.nodes.bytecodes; import com.oracle.truffle.api.CompilerAsserts; import de.hpi.swa.trufflesqueak.exceptions.SqueakExceptions.SqueakException; import de.hpi.swa.trufflesqueak.model.CompiledCodeObject; -import de.hpi.swa.trufflesqueak.nodes.bytecodes.AbstractBytecodeNode; -import de.hpi.swa.trufflesqueak.nodes.bytecodes.JumpBytecodes.ConditionalFalseJumpNode; -import de.hpi.swa.trufflesqueak.nodes.bytecodes.JumpBytecodes.ConditionalTrueJumpNode; -import de.hpi.swa.trufflesqueak.nodes.bytecodes.JumpBytecodes.UnconditionalJumpNode; -import de.hpi.swa.trufflesqueak.nodes.bytecodes.MiscellaneousBytecodes.CallPrimitiveNode; -import de.hpi.swa.trufflesqueak.nodes.bytecodes.MiscellaneousBytecodes.DoubleExtendedDoAnythingNode; -import de.hpi.swa.trufflesqueak.nodes.bytecodes.MiscellaneousBytecodes.DupNode; -import de.hpi.swa.trufflesqueak.nodes.bytecodes.MiscellaneousBytecodes.ExtendedBytecodes; -import de.hpi.swa.trufflesqueak.nodes.bytecodes.MiscellaneousBytecodes.PopNode; -import de.hpi.swa.trufflesqueak.nodes.bytecodes.MiscellaneousBytecodes.UnknownBytecodeNode; -import de.hpi.swa.trufflesqueak.nodes.bytecodes.PushBytecodes.PushActiveContextNode; -import de.hpi.swa.trufflesqueak.nodes.bytecodes.PushBytecodes.PushClosureNode; -import de.hpi.swa.trufflesqueak.nodes.bytecodes.PushBytecodes.PushConstantNode.PushConstantFalseNode; -import de.hpi.swa.trufflesqueak.nodes.bytecodes.PushBytecodes.PushConstantNode.PushConstantMinusOneNode; -import de.hpi.swa.trufflesqueak.nodes.bytecodes.PushBytecodes.PushConstantNode.PushConstantNilNode; -import de.hpi.swa.trufflesqueak.nodes.bytecodes.PushBytecodes.PushConstantNode.PushConstantOneNode; -import de.hpi.swa.trufflesqueak.nodes.bytecodes.PushBytecodes.PushConstantNode.PushConstantTrueNode; -import de.hpi.swa.trufflesqueak.nodes.bytecodes.PushBytecodes.PushConstantNode.PushConstantTwoNode; -import de.hpi.swa.trufflesqueak.nodes.bytecodes.PushBytecodes.PushConstantNode.PushConstantZeroNode; -import de.hpi.swa.trufflesqueak.nodes.bytecodes.PushBytecodes.PushLiteralConstantNode; -import de.hpi.swa.trufflesqueak.nodes.bytecodes.PushBytecodes.PushLiteralVariableNode; -import de.hpi.swa.trufflesqueak.nodes.bytecodes.PushBytecodes.PushNewArrayNode; -import de.hpi.swa.trufflesqueak.nodes.bytecodes.PushBytecodes.PushReceiverNode; -import de.hpi.swa.trufflesqueak.nodes.bytecodes.PushBytecodes.PushReceiverVariableNode; -import de.hpi.swa.trufflesqueak.nodes.bytecodes.PushBytecodes.PushRemoteTempNode; -import de.hpi.swa.trufflesqueak.nodes.bytecodes.PushBytecodes.PushTemporaryLocationNode; -import de.hpi.swa.trufflesqueak.nodes.bytecodes.ReturnBytecodes.ReturnConstantNode.ReturnConstantFalseNode; -import de.hpi.swa.trufflesqueak.nodes.bytecodes.ReturnBytecodes.ReturnConstantNode.ReturnConstantNilNode; -import de.hpi.swa.trufflesqueak.nodes.bytecodes.ReturnBytecodes.ReturnConstantNode.ReturnConstantTrueNode; -import de.hpi.swa.trufflesqueak.nodes.bytecodes.ReturnBytecodes.ReturnReceiverNode; -import de.hpi.swa.trufflesqueak.nodes.bytecodes.ReturnBytecodes.ReturnTopFromBlockNode; -import de.hpi.swa.trufflesqueak.nodes.bytecodes.ReturnBytecodes.ReturnTopFromMethodNode; -import de.hpi.swa.trufflesqueak.nodes.bytecodes.SendBytecodes.SecondExtendedSendNode; -import de.hpi.swa.trufflesqueak.nodes.bytecodes.SendBytecodes.SendLiteralSelectorNode; -import de.hpi.swa.trufflesqueak.nodes.bytecodes.SendBytecodes.SendSpecialSelectorNode; -import de.hpi.swa.trufflesqueak.nodes.bytecodes.SendBytecodes.SingleExtendedSendNode; -import de.hpi.swa.trufflesqueak.nodes.bytecodes.SendBytecodes.SingleExtendedSuperNode; -import de.hpi.swa.trufflesqueak.nodes.bytecodes.StoreBytecodes.PopIntoReceiverVariableNode; -import de.hpi.swa.trufflesqueak.nodes.bytecodes.StoreBytecodes.PopIntoRemoteTempNode; -import de.hpi.swa.trufflesqueak.nodes.bytecodes.StoreBytecodes.PopIntoTemporaryLocationNode; -import de.hpi.swa.trufflesqueak.nodes.bytecodes.StoreBytecodes.StoreIntoRemoteTempNode; -public final class SqueakBytecodeDecoder { - private SqueakBytecodeDecoder() { +public final class SqueakBytecodeV3PlusClosuresDecoder { + private SqueakBytecodeV3PlusClosuresDecoder() { } public static AbstractBytecodeNode[] decode(final CompiledCodeObject code) { @@ -130,111 +89,111 @@ public static AbstractBytecodeNode decodeBytecode(final CompiledCodeObject code, switch (b) { case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15: - return PushReceiverVariableNode.create(code, index, 1, b & 15); + return PushBytecodes.PushReceiverVariableNode.create(code, index, 1, b & 15); case 16: case 17: case 18: case 19: case 20: case 21: case 22: case 23: case 24: case 25: case 26: case 27: case 28: case 29: case 30: case 31: - return new PushTemporaryLocationNode(code, index, 1, b & 15); + return new PushBytecodes.PushTemporaryLocationNode(code, index, 1, b & 15); case 32: case 33: case 34: case 35: case 36: case 37: case 38: case 39: case 40: case 41: case 42: case 43: case 44: case 45: case 46: case 47: case 48: case 49: case 50: case 51: case 52: case 53: case 54: case 55: case 56: case 57: case 58: case 59: case 60: case 61: case 62: case 63: - return new PushLiteralConstantNode(code, index, 1, b & 31); + return new PushBytecodes.PushLiteralConstantNode(code, index, 1, b & 31); case 64: case 65: case 66: case 67: case 68: case 69: case 70: case 71: case 72: case 73: case 74: case 75: case 76: case 77: case 78: case 79: case 80: case 81: case 82: case 83: case 84: case 85: case 86: case 87: case 88: case 89: case 90: case 91: case 92: case 93: case 94: case 95: - return new PushLiteralVariableNode(code, index, 1, b & 31); + return new PushBytecodes.PushLiteralVariableNode(code, index, 1, b & 31); case 96: case 97: case 98: case 99: case 100: case 101: case 102: case 103: - return new PopIntoReceiverVariableNode(code, index, 1, b & 7); + return new StoreBytecodes.PopIntoReceiverVariableNode(code, index, 1, b & 7); case 104: case 105: case 106: case 107: case 108: case 109: case 110: case 111: - return new PopIntoTemporaryLocationNode(code, index, 1, b & 7); + return new StoreBytecodes.PopIntoTemporaryLocationNode(code, index, 1, b & 7); case 112: - return PushReceiverNode.create(code, index); + return PushBytecodes.PushReceiverNode.create(code, index); case 113: - return new PushConstantTrueNode(code, index); + return new PushBytecodes.PushConstantTrueNode(code, index); case 114: - return new PushConstantFalseNode(code, index); + return new PushBytecodes.PushConstantFalseNode(code, index); case 115: - return new PushConstantNilNode(code, index); + return new PushBytecodes.PushConstantNilNode(code, index); case 116: - return new PushConstantMinusOneNode(code, index); + return new PushBytecodes.PushConstantMinusOneNode(code, index); case 117: - return new PushConstantZeroNode(code, index); + return new PushBytecodes.PushConstantZeroNode(code, index); case 118: - return new PushConstantOneNode(code, index); + return new PushBytecodes.PushConstantOneNode(code, index); case 119: - return new PushConstantTwoNode(code, index); + return new PushBytecodes.PushConstantTwoNode(code, index); case 120: - return ReturnReceiverNode.create(code, index); + return ReturnBytecodes.ReturnReceiverNode.create(code, index); case 121: - return ReturnConstantTrueNode.create(code, index); + return ReturnBytecodes.ReturnConstantTrueNode.create(code, index); case 122: - return ReturnConstantFalseNode.create(code, index); + return ReturnBytecodes.ReturnConstantFalseNode.create(code, index); case 123: - return ReturnConstantNilNode.create(code, index); + return ReturnBytecodes.ReturnConstantNilNode.create(code, index); case 124: - return ReturnTopFromMethodNode.create(code, index); + return ReturnBytecodes.ReturnTopFromMethodNode.create(code, index); case 125: - return ReturnTopFromBlockNode.create(code, index); + return ReturnBytecodes.ReturnTopFromBlockNode.create(code, index); case 126: case 127: - return new UnknownBytecodeNode(code, index, 1, b); + return new MiscellaneousBytecodes.UnknownBytecodeNode(code, index, 1, b); case 128: - return ExtendedBytecodes.createPush(code, index, 2, bytecode[index + 1]); + return MiscellaneousBytecodes.ExtendedBytecodes.createPush(code, index, 2, bytecode[index + 1]); case 129: - return ExtendedBytecodes.createStoreInto(code, index, 2, bytecode[index + 1]); + return MiscellaneousBytecodes.ExtendedBytecodes.createStoreInto(code, index, 2, bytecode[index + 1]); case 130: - return ExtendedBytecodes.createPopInto(code, index, 2, bytecode[index + 1]); + return MiscellaneousBytecodes.ExtendedBytecodes.createPopInto(code, index, 2, bytecode[index + 1]); case 131: - return new SingleExtendedSendNode(code, index, 2, bytecode[index + 1]); + return new SendBytecodes.SingleExtendedSendNode(code, index, 2, bytecode[index + 1]); case 132: - return DoubleExtendedDoAnythingNode.create(code, index, 3, bytecode[index + 1], bytecode[index + 2]); + return MiscellaneousBytecodes.DoubleExtendedDoAnythingNode.create(code, index, 3, bytecode[index + 1], bytecode[index + 2]); case 133: - return new SingleExtendedSuperNode(code, index, 2, bytecode[index + 1]); + return new SendBytecodes.SingleExtendedSuperNode(code, index, 2, bytecode[index + 1]); case 134: - return new SecondExtendedSendNode(code, index, 2, bytecode[index + 1]); + return new SendBytecodes.SecondExtendedSendNode(code, index, 2, bytecode[index + 1]); case 135: - return new PopNode(code, index, 1); + return new MiscellaneousBytecodes.PopNode(code, index); case 136: - return new DupNode(code, index, 1); + return new MiscellaneousBytecodes.DupNode(code, index); case 137: - return new PushActiveContextNode(code, index); + return new PushBytecodes.PushActiveContextNode(code, index); case 138: - return PushNewArrayNode.create(code, index, 2, bytecode[index + 1]); + return PushBytecodes.PushNewArrayNode.create(code, index, 2, bytecode[index + 1]); case 139: - return CallPrimitiveNode.create(code, index, bytecode[index + 1], bytecode[index + 2]); + return MiscellaneousBytecodes.CallPrimitiveNode.create(code, index, bytecode[index + 1], bytecode[index + 2]); case 140: - return new PushRemoteTempNode(code, index, 3, bytecode[index + 1], bytecode[index + 2]); + return new PushBytecodes.PushRemoteTempNode(code, index, 3, bytecode[index + 1], bytecode[index + 2]); case 141: - return new StoreIntoRemoteTempNode(code, index, 3, bytecode[index + 1], bytecode[index + 2]); + return new StoreBytecodes.StoreIntoRemoteTempNode(code, index, 3, bytecode[index + 1], bytecode[index + 2]); case 142: - return new PopIntoRemoteTempNode(code, index, 3, bytecode[index + 1], bytecode[index + 2]); + return new StoreBytecodes.PopIntoRemoteTempNode(code, index, 3, bytecode[index + 1], bytecode[index + 2]); case 143: - return PushClosureNode.create(code, index, 4, bytecode[index + 1], bytecode[index + 2], bytecode[index + 3]); + return PushBytecodes.PushClosureNode.create(code, index, 4, bytecode[index + 1], bytecode[index + 2], bytecode[index + 3]); case 144: case 145: case 146: case 147: case 148: case 149: case 150: case 151: - return new UnconditionalJumpNode(code, index, 1, b); + return JumpBytecodes.UnconditionalJumpNode.createShort(code, index, b); case 152: case 153: case 154: case 155: case 156: case 157: case 158: case 159: - return new ConditionalFalseJumpNode(code, index, b); + return JumpBytecodes.ConditionalJumpOnFalseNode.createShort(code, index, b); case 160: case 161: case 162: case 163: case 164: case 165: case 166: case 167: - return new UnconditionalJumpNode(code, index, 2, b, bytecode[index + 1]); + return JumpBytecodes.UnconditionalJumpNode.createLong(code, index, b, bytecode[index + 1]); case 168: case 169: case 170: case 171: - return new ConditionalTrueJumpNode(code, index, b, bytecode[index + 1]); + return JumpBytecodes.ConditionalJumpOnTrueNode.createLong(code, index, b, bytecode[index + 1]); case 172: case 173: case 174: case 175: - return new ConditionalFalseJumpNode(code, index, b, bytecode[index + 1]); + return JumpBytecodes.ConditionalJumpOnFalseNode.createLong(code, index, b, bytecode[index + 1]); case 176: case 177: case 178: case 179: case 180: case 181: case 182: case 183: case 184: case 185: case 186: case 187: case 188: case 189: case 190: case 191: case 192: case 193: case 194: case 195: case 196: case 197: case 198: case 199: case 200: case 201: case 202: case 203: case 204: case 205: case 206: case 207: - return SendSpecialSelectorNode.create(code, index, b - 176); + return SendBytecodes.SendSpecialSelectorNode.create(code, index, b - 176); case 208: case 209: case 210: case 211: case 212: case 213: case 214: case 215: case 216: case 217: case 218: case 219: case 220: case 221: case 222: case 223: - return SendLiteralSelectorNode.create(code, index, 1, b & 0xF, 0); + return SendBytecodes.SendLiteralSelectorNode.create(code, index, 1, b & 0xF, 0); case 224: case 225: case 226: case 227: case 228: case 229: case 230: case 231: case 232: case 233: case 234: case 235: case 236: case 237: case 238: case 239: - return SendLiteralSelectorNode.create(code, index, 1, b & 0xF, 1); + return SendBytecodes.SendLiteralSelectorNode.create(code, index, 1, b & 0xF, 1); case 240: case 241: case 242: case 243: case 244: case 245: case 246: case 247: case 248: case 249: case 250: case 251: case 252: case 253: case 254: case 255: - return SendLiteralSelectorNode.create(code, index, 1, b & 0xF, 2); + return SendBytecodes.SendLiteralSelectorNode.create(code, index, 1, b & 0xF, 2); default: throw SqueakException.create("Unknown bytecode:", b); } @@ -338,8 +297,8 @@ private static String decodeBytecodeToString(final CompiledCodeObject code, fina return "unknown: " + b0; case 128: { final byte b1 = bytecode[index + 1]; - final int variableIndex = ExtendedBytecodes.variableIndex(b1); - switch (ExtendedBytecodes.variableType(b1)) { + final int variableIndex = MiscellaneousBytecodes.ExtendedBytecodes.variableIndex(b1); + switch (MiscellaneousBytecodes.ExtendedBytecodes.variableType(b1)) { case 0: return "pushRcvr: " + variableIndex; case 1: @@ -354,8 +313,8 @@ private static String decodeBytecodeToString(final CompiledCodeObject code, fina } case 129: { final byte b1 = bytecode[index + 1]; - final int variableIndex = ExtendedBytecodes.variableIndex(b1); - switch (ExtendedBytecodes.variableType(b1)) { + final int variableIndex = MiscellaneousBytecodes.ExtendedBytecodes.variableIndex(b1); + switch (MiscellaneousBytecodes.ExtendedBytecodes.variableType(b1)) { case 0: return "storeIntoRcvr: " + variableIndex; case 1: @@ -370,8 +329,8 @@ private static String decodeBytecodeToString(final CompiledCodeObject code, fina } case 130: { final byte b1 = bytecode[index + 1]; - final int variableIndex = ExtendedBytecodes.variableIndex(b1); - switch (ExtendedBytecodes.variableType(b1)) { + final int variableIndex = MiscellaneousBytecodes.ExtendedBytecodes.variableIndex(b1); + switch (MiscellaneousBytecodes.ExtendedBytecodes.variableType(b1)) { case 0: return "popIntoRcvr: " + variableIndex; case 1: @@ -432,7 +391,7 @@ private static String decodeBytecodeToString(final CompiledCodeObject code, fina return "popIntoTemp: " + Byte.toUnsignedInt(bytecode[index + 1]) + " inVectorAt: " + Byte.toUnsignedInt(bytecode[index + 2]); case 143: { final byte b1 = bytecode[index + 1]; - final int start = index + PushClosureNode.NUM_BYTECODES; + final int start = index + PushBytecodes.PushClosureNode.NUM_BYTECODES; final int end = start + (Byte.toUnsignedInt(bytecode[index + 2]) << 8 | Byte.toUnsignedInt(bytecode[index + 3])); return "closureNumCopied: " + (b1 >> 4 & 0xF) + " numArgs: " + (b1 & 0xF) + " bytes " + start + " to " + end; } @@ -499,7 +458,7 @@ private static int decodeNumBytes(final CompiledCodeObject code, final int index case 139: case 140: case 141: case 142: return 3; case 143: - return PushClosureNode.NUM_BYTECODES; + return PushBytecodes.PushClosureNode.NUM_BYTECODES; case 144: case 145: case 146: case 147: case 148: case 149: case 150: case 151: case 152: case 153: case 154: case 155: case 156: case 157: case 158: case 159: return 1; diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/bytecodes/StoreBytecodes.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/bytecodes/StoreBytecodes.java index 102860d77..f2fdfd695 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/bytecodes/StoreBytecodes.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/bytecodes/StoreBytecodes.java @@ -106,10 +106,10 @@ public final String toString() { } } - public static final class PopIntoAssociationNode extends AbstractStoreIntoAssociationNode { + public static final class PopIntoLiteralVariableNode extends AbstractStoreIntoAssociationNode { @Child private FrameStackPopNode popNode = FrameStackPopNode.create(); - public PopIntoAssociationNode(final CompiledCodeObject code, final int index, final int numBytecodes, final long variableIndex) { + public PopIntoLiteralVariableNode(final CompiledCodeObject code, final int index, final int numBytecodes, final long variableIndex) { super(code, index, numBytecodes, variableIndex); } @@ -178,10 +178,10 @@ protected String getTypeName() { } } - public static final class StoreIntoAssociationNode extends AbstractStoreIntoAssociationNode { + public static final class StoreIntoLiteralVariableNode extends AbstractStoreIntoAssociationNode { @Child private FrameStackTopNode topNode = FrameStackTopNode.create(); - public StoreIntoAssociationNode(final CompiledCodeObject code, final int index, final int numBytecodes, final long variableIndex) { + public StoreIntoLiteralVariableNode(final CompiledCodeObject code, final int index, final int numBytecodes, final long variableIndex) { super(code, index, numBytecodes, variableIndex); } @@ -232,10 +232,10 @@ protected String getTypeName() { } } - public static final class StoreIntoTempNode extends AbstractStoreIntoTempNode { + public static final class StoreIntoTemporaryLocationNode extends AbstractStoreIntoTempNode { @Child private FrameStackTopNode topNode = FrameStackTopNode.create(); - public StoreIntoTempNode(final CompiledCodeObject code, final int index, final int numBytecodes, final int tempIndex) { + public StoreIntoTemporaryLocationNode(final CompiledCodeObject code, final int index, final int numBytecodes, final int tempIndex) { super(code, index, numBytecodes, tempIndex); } diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/dispatch/DispatchSuperSendStackedNode.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/dispatch/DispatchSuperSendStackedNode.java new file mode 100644 index 000000000..406d314c1 --- /dev/null +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/dispatch/DispatchSuperSendStackedNode.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2017-2020 Software Architecture Group, Hasso Plattner Institute + * + * Licensed under the MIT License. + */ +package de.hpi.swa.trufflesqueak.nodes.dispatch; + +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; +import com.oracle.truffle.api.dsl.Cached; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.frame.FrameSlot; +import com.oracle.truffle.api.frame.VirtualFrame; + +import de.hpi.swa.trufflesqueak.model.ClassObject; +import de.hpi.swa.trufflesqueak.model.NativeObject; +import de.hpi.swa.trufflesqueak.nodes.LookupMethodNode; +import de.hpi.swa.trufflesqueak.nodes.accessing.AbstractPointersObjectNodes.AbstractPointersObjectReadNode; +import de.hpi.swa.trufflesqueak.nodes.context.frame.FrameSlotReadNode; +import de.hpi.swa.trufflesqueak.util.FrameAccess; + +public abstract class DispatchSuperSendStackedNode extends AbstractDispatchNode { + @CompilationFinal private FrameSlot stackPointerSlot; + @CompilationFinal private int stackPointer; + + @Child private FrameSlotReadNode readStackNode; + + public DispatchSuperSendStackedNode(final NativeObject selector, final int argumentCount) { + super(selector, argumentCount); + } + + public static DispatchSuperSendStackedNode create(final NativeObject selector, final int argumentCount) { + return DispatchSuperSendStackedNodeGen.create(selector, argumentCount); + } + + public abstract Object execute(VirtualFrame frame); + + @Specialization(guards = {"peekAtStackTop(frame) == cachedClass"}, assumptions = {"cachedClass.getClassHierarchyStable()", "dispatchNode.getCallTargetStable()"}) + protected final Object doCached(final VirtualFrame frame, + @SuppressWarnings("unused") @Cached final AbstractPointersObjectReadNode readNode, + @SuppressWarnings("unused") @Cached("peekAtStackTop(frame)") final ClassObject cachedClass, + @Cached("create(frame, selector, argumentCount, cachedClass, lookupSlow(cachedClass.getSuperclassOrNull()))") final CachedDispatchNode dispatchNode) { + popStackTop(frame); + return dispatchNode.execute(frame); + } + + protected final Object lookupSlow(final ClassObject receiver) { + assert receiver != null; + return LookupMethodNode.getUncached().executeLookup(receiver, selector); + } + + protected final ClassObject peekAtStackTop(final VirtualFrame frame) { + if (stackPointerSlot == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + stackPointerSlot = FrameAccess.getStackPointerSlot(frame); + stackPointer = FrameAccess.getStackPointer(frame, stackPointerSlot) - 1; + readStackNode = insert(FrameSlotReadNode.create(frame, stackPointer)); + } + return (ClassObject) readStackNode.executeRead(frame); + } + + protected final void popStackTop(final VirtualFrame frame) { + FrameAccess.setStackPointer(frame, stackPointerSlot, stackPointer); + } +}