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 6b855622b..e1b309eb9 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 @@ -266,8 +266,8 @@ public static final class MUTEX { } public static final class POINT { - public static final int X = 0; - public static final int Y = 1; + public static final long X = 0; + public static final long Y = 1; public static final int SIZE = 2; } diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/SqueakGuards.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/SqueakGuards.java index c8a5c5b72..ac7ce4de1 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/SqueakGuards.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/SqueakGuards.java @@ -151,6 +151,10 @@ public static boolean isLongMinValue(final long value) { return value == Long.MIN_VALUE; } + public static boolean isLShiftLongOverflow(final long receiver, final long arg) { + return Long.numberOfLeadingZeros(receiver) - 1 < arg; + } + @Idempotent public static boolean isMacOS() { return OS.isMacOS(); 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 c26d49c38..7297bd9b7 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 @@ -6,68 +6,94 @@ */ package de.hpi.swa.trufflesqueak.nodes.bytecodes; -import com.oracle.truffle.api.Assumption; +import static de.hpi.swa.trufflesqueak.nodes.primitives.impl.ArithmeticPrimitives.AbstractArithmeticPrimitiveNode.ensureFinite; + import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.debug.DebuggerTags; import com.oracle.truffle.api.dsl.Bind; import com.oracle.truffle.api.dsl.Cached; -import com.oracle.truffle.api.dsl.GenerateCached; +import com.oracle.truffle.api.dsl.Cached.Shared; +import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.instrumentation.StandardTags; import com.oracle.truffle.api.instrumentation.Tag; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.profiles.ConditionProfile; +import com.oracle.truffle.api.profiles.InlinedConditionProfile; -import de.hpi.swa.trufflesqueak.exceptions.PrimitiveFailed; +import de.hpi.swa.trufflesqueak.exceptions.RespecializeException; import de.hpi.swa.trufflesqueak.exceptions.Returns.NonLocalReturn; import de.hpi.swa.trufflesqueak.exceptions.Returns.NonVirtualReturn; import de.hpi.swa.trufflesqueak.image.SqueakImageContext; import de.hpi.swa.trufflesqueak.model.AbstractPointersObject; +import de.hpi.swa.trufflesqueak.model.ArrayObject; +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.LargeIntegerObject; import de.hpi.swa.trufflesqueak.model.NativeObject; -import de.hpi.swa.trufflesqueak.model.layout.ObjectLayouts.CONTEXT; +import de.hpi.swa.trufflesqueak.model.PointersObject; import de.hpi.swa.trufflesqueak.model.layout.ObjectLayouts.POINT; +import de.hpi.swa.trufflesqueak.nodes.AbstractNode; import de.hpi.swa.trufflesqueak.nodes.accessing.AbstractPointersObjectNodes.AbstractPointersObjectReadNode; +import de.hpi.swa.trufflesqueak.nodes.accessing.AbstractPointersObjectNodes.AbstractPointersObjectWriteNode; +import de.hpi.swa.trufflesqueak.nodes.accessing.ArrayObjectNodes.ArrayObjectSizeNode; +import de.hpi.swa.trufflesqueak.nodes.accessing.FloatObjectNodes.AsFloatObjectIfNessaryNode; import de.hpi.swa.trufflesqueak.nodes.accessing.SqueakObjectClassNode; -import de.hpi.swa.trufflesqueak.nodes.bytecodes.SendBytecodesFactory.SendSpecialSelectorQuickPointXNodeGen; -import de.hpi.swa.trufflesqueak.nodes.bytecodes.SendBytecodesFactory.SendSpecialSelectorQuickPointYNodeGen; +import de.hpi.swa.trufflesqueak.nodes.accessing.SqueakObjectIdentityNode; +import de.hpi.swa.trufflesqueak.nodes.bytecodes.SendBytecodesFactory.SendSpecial0NodeFactory.BytecodePrimClassNodeGen; +import de.hpi.swa.trufflesqueak.nodes.bytecodes.SendBytecodesFactory.SendSpecial0NodeFactory.BytecodePrimPointXNodeGen; +import de.hpi.swa.trufflesqueak.nodes.bytecodes.SendBytecodesFactory.SendSpecial0NodeFactory.BytecodePrimPointYNodeGen; +import de.hpi.swa.trufflesqueak.nodes.bytecodes.SendBytecodesFactory.SendSpecial0NodeFactory.BytecodePrimSizeNodeGen; +import de.hpi.swa.trufflesqueak.nodes.bytecodes.SendBytecodesFactory.SendSpecial1NodeFactory.BytecodePrimAddNodeGen; +import de.hpi.swa.trufflesqueak.nodes.bytecodes.SendBytecodesFactory.SendSpecial1NodeFactory.BytecodePrimBitAndNodeGen; +import de.hpi.swa.trufflesqueak.nodes.bytecodes.SendBytecodesFactory.SendSpecial1NodeFactory.BytecodePrimBitOrNodeGen; +import de.hpi.swa.trufflesqueak.nodes.bytecodes.SendBytecodesFactory.SendSpecial1NodeFactory.BytecodePrimBitShiftNodeGen; +import de.hpi.swa.trufflesqueak.nodes.bytecodes.SendBytecodesFactory.SendSpecial1NodeFactory.BytecodePrimDivNodeGen; +import de.hpi.swa.trufflesqueak.nodes.bytecodes.SendBytecodesFactory.SendSpecial1NodeFactory.BytecodePrimDivideNodeGen; +import de.hpi.swa.trufflesqueak.nodes.bytecodes.SendBytecodesFactory.SendSpecial1NodeFactory.BytecodePrimEqualNodeGen; +import de.hpi.swa.trufflesqueak.nodes.bytecodes.SendBytecodesFactory.SendSpecial1NodeFactory.BytecodePrimGreaterOrEqualNodeGen; +import de.hpi.swa.trufflesqueak.nodes.bytecodes.SendBytecodesFactory.SendSpecial1NodeFactory.BytecodePrimGreaterThanNodeGen; +import de.hpi.swa.trufflesqueak.nodes.bytecodes.SendBytecodesFactory.SendSpecial1NodeFactory.BytecodePrimIdenticalSistaV1NodeGen; +import de.hpi.swa.trufflesqueak.nodes.bytecodes.SendBytecodesFactory.SendSpecial1NodeFactory.BytecodePrimLessOrEqualNodeGen; +import de.hpi.swa.trufflesqueak.nodes.bytecodes.SendBytecodesFactory.SendSpecial1NodeFactory.BytecodePrimLessThanNodeGen; +import de.hpi.swa.trufflesqueak.nodes.bytecodes.SendBytecodesFactory.SendSpecial1NodeFactory.BytecodePrimMakePointNodeGen; +import de.hpi.swa.trufflesqueak.nodes.bytecodes.SendBytecodesFactory.SendSpecial1NodeFactory.BytecodePrimModNodeGen; +import de.hpi.swa.trufflesqueak.nodes.bytecodes.SendBytecodesFactory.SendSpecial1NodeFactory.BytecodePrimMultiplyNodeGen; +import de.hpi.swa.trufflesqueak.nodes.bytecodes.SendBytecodesFactory.SendSpecial1NodeFactory.BytecodePrimNotEqualNodeGen; +import de.hpi.swa.trufflesqueak.nodes.bytecodes.SendBytecodesFactory.SendSpecial1NodeFactory.BytecodePrimNotIdenticalSistaV1NodeGen; +import de.hpi.swa.trufflesqueak.nodes.bytecodes.SendBytecodesFactory.SendSpecial1NodeFactory.BytecodePrimSubtractNodeGen; import de.hpi.swa.trufflesqueak.nodes.context.frame.FrameStackPushNode; import de.hpi.swa.trufflesqueak.nodes.context.frame.FrameStackReadNode; import de.hpi.swa.trufflesqueak.nodes.context.frame.FrameStackWriteNode; +import de.hpi.swa.trufflesqueak.nodes.dispatch.DispatchSelector0Node.Dispatch0Node; +import de.hpi.swa.trufflesqueak.nodes.dispatch.DispatchSelector1Node.Dispatch1Node; import de.hpi.swa.trufflesqueak.nodes.dispatch.DispatchSelectorNode; -import de.hpi.swa.trufflesqueak.nodes.dispatch.LookupClassNode; -import de.hpi.swa.trufflesqueak.nodes.primitives.AbstractPrimitiveNode; -import de.hpi.swa.trufflesqueak.nodes.primitives.DispatchPrimitiveNode; -import de.hpi.swa.trufflesqueak.nodes.primitives.PrimitiveNodeFactory; -import de.hpi.swa.trufflesqueak.nodes.primitives.PrimitiveNodeFactory.ArgumentsLocation; import de.hpi.swa.trufflesqueak.nodes.primitives.impl.ControlPrimitives.PrimExitToDebuggerNode; import de.hpi.swa.trufflesqueak.util.FrameAccess; public final class SendBytecodes { public abstract static class AbstractSendNode extends AbstractInstrumentableBytecodeNode { - protected final int argumentCount; - @CompilationFinal private int stackPointer = -1; + private final int stackPointer; + private final ConditionProfile nlrProfile = ConditionProfile.create(); + private final ConditionProfile nvrProfile = ConditionProfile.create(); @Child protected DispatchSelectorNode dispatchNode; @Child private FrameStackPushNode pushNode; - private final ConditionProfile nlrProfile = ConditionProfile.create(); - private final ConditionProfile nvrProfile = ConditionProfile.create(); - - private AbstractSendNode(final CompiledCodeObject code, final int index, final int numBytecodes, final int numArgs) { + private AbstractSendNode(final VirtualFrame frame, final CompiledCodeObject code, final int index, final int numBytecodes, final int numArgs, final int numAdditional) { super(code, index, numBytecodes); - argumentCount = numArgs; + stackPointer = FrameAccess.getStackPointer(frame) - 1 - numArgs - numAdditional; + assert stackPointer >= 0 : "Bad stack pointer"; } @Override public final void executeVoid(final VirtualFrame frame) { Object result; try { - decrementStackPointer(frame); + FrameAccess.setStackPointer(frame, stackPointer); result = dispatchNode.execute(frame); } catch (final NonLocalReturn nlr) { if (nlrProfile.profile(nlr.getTargetContextOrMarker() == FrameAccess.getMarker(frame) || nlr.getTargetContextOrMarker() == FrameAccess.getContext(frame))) { @@ -86,19 +112,6 @@ public final void executeVoid(final VirtualFrame frame) { getPushNode().execute(frame, result); } - private void decrementStackPointer(final VirtualFrame frame) { - if (stackPointer == -1) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - stackPointer = FrameAccess.getStackPointer(frame) - numPop(); - assert stackPointer >= 0 : "Bad stack pointer"; - } - FrameAccess.setStackPointer(frame, stackPointer); - } - - protected int numPop() { - return 1 + argumentCount; - } - private FrameStackPushNode getPushNode() { if (pushNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); @@ -133,7 +146,7 @@ public final String toString() { public static final class SelfSendNode extends AbstractSendNode { public SelfSendNode(final VirtualFrame frame, final CompiledCodeObject code, final int index, final int numBytecodes, final NativeObject selector, final int numArgs) { - super(code, index, numBytecodes, numArgs); + super(frame, code, index, numBytecodes, numArgs, 0); dispatchNode = DispatchSelectorNode.create(frame, selector, numArgs); } @@ -145,7 +158,7 @@ protected String getBytecodeName() { public static final class SuperSendNode extends AbstractSendNode { public SuperSendNode(final VirtualFrame frame, final CompiledCodeObject code, final int index, final int numBytecodes, final int literalIndex, final int numArgs) { - super(code, index, numBytecodes, numArgs); + super(frame, code, index, numBytecodes, numArgs, 0); final NativeObject selector = (NativeObject) code.getLiteral(literalIndex); dispatchNode = DispatchSelectorNode.createSuper(frame, code, selector, numArgs); } @@ -158,361 +171,634 @@ protected String getBytecodeName() { public static final class DirectedSuperSendNode extends AbstractSendNode { public DirectedSuperSendNode(final VirtualFrame frame, final CompiledCodeObject code, final int index, final int numBytecodes, final int selectorLiteralIndex, final int numArgs) { - super(code, index, numBytecodes, numArgs); + super(frame, code, index, numBytecodes, numArgs, 1 /* directed class */); assert 0 <= selectorLiteralIndex && selectorLiteralIndex < 65535 : "selectorLiteralIndex out of range"; assert 0 <= numArgs && numArgs <= 31 : "numArgs out of range"; final NativeObject selector = (NativeObject) code.getLiteral(selectorLiteralIndex); dispatchNode = DispatchSelectorNode.createDirectedSuper(frame, selector, numArgs); } - @Override - protected int numPop() { - return 1 + 1 + argumentCount; // pop directed class, receiver, args - } - @Override protected String getBytecodeName() { return "directedSuperSend"; } } - /* - * Try to execute primitive for special selectors. Replaces itself with a normal send on - * primitive failure. Modifies the stack only once, primitives read their arguments directly - * from the stack. - */ - public abstract static class AbstractSendSpecialSelectorQuickNode extends AbstractInstrumentableBytecodeNode { - protected final int selectorIndex; + public static AbstractBytecodeNode createSpecialSelectorSend(final VirtualFrame frame, final CompiledCodeObject code, final int index, final int selectorIndex) { + return switch (selectorIndex) { + case 0 /* #+ */ -> new SendSpecial1Node(frame, code, index, selectorIndex, BytecodePrimAddNodeGen.create()); + case 1 /* #- */ -> new SendSpecial1Node(frame, code, index, selectorIndex, BytecodePrimSubtractNodeGen.create()); + case 2 /* #< */ -> new SendSpecial1Node(frame, code, index, selectorIndex, BytecodePrimLessThanNodeGen.create()); + case 3 /* #> */ -> new SendSpecial1Node(frame, code, index, selectorIndex, BytecodePrimGreaterThanNodeGen.create()); + case 4 /* #<= */ -> new SendSpecial1Node(frame, code, index, selectorIndex, BytecodePrimLessOrEqualNodeGen.create()); + case 5 /* #>= */ -> new SendSpecial1Node(frame, code, index, selectorIndex, BytecodePrimGreaterOrEqualNodeGen.create()); + case 6 /* #= */ -> new SendSpecial1Node(frame, code, index, selectorIndex, BytecodePrimEqualNodeGen.create()); + case 7 /* #~= */ -> new SendSpecial1Node(frame, code, index, selectorIndex, BytecodePrimNotEqualNodeGen.create()); + case 8 /* #* */ -> new SendSpecial1Node(frame, code, index, selectorIndex, BytecodePrimMultiplyNodeGen.create()); + case 9 /* #/ */ -> new SendSpecial1Node(frame, code, index, selectorIndex, BytecodePrimDivideNodeGen.create()); + case 10 /* #\\ */ -> new SendSpecial1Node(frame, code, index, selectorIndex, BytecodePrimModNodeGen.create()); + case 11 /* #@ */ -> new SendSpecial1Node(frame, code, index, selectorIndex, BytecodePrimMakePointNodeGen.create()); + case 12 /* #bitShift: */ -> new SendSpecial1Node(frame, code, index, selectorIndex, BytecodePrimBitShiftNodeGen.create()); + case 13 /* #// */ -> new SendSpecial1Node(frame, code, index, selectorIndex, BytecodePrimDivNodeGen.create()); + case 14 /* #bitAnd: */ -> new SendSpecial1Node(frame, code, index, selectorIndex, BytecodePrimBitAndNodeGen.create()); + case 15 /* #bitOr: */ -> new SendSpecial1Node(frame, code, index, selectorIndex, BytecodePrimBitOrNodeGen.create()); + // case 16 /* #at: */ -> fallthrough; + // case 17 /* #at:put: */ -> fallthrough; + case 18 /* #size */ -> new SendSpecial0Node(frame, code, index, selectorIndex, BytecodePrimSizeNodeGen.create()); + // case 19 /* #next */ -> fallthrough; + // case 20 /* #nextPut: */ -> fallthrough; + // case 21 /* #atEnd */ -> fallthrough; + case 22 /* #== */ -> new SendSpecial1Node(frame, code, index, selectorIndex, BytecodePrimIdenticalSistaV1NodeGen.create()); + case 23 /* #class */ -> new SendSpecial0Node(frame, code, index, selectorIndex, BytecodePrimClassNodeGen.create()); + case 24 /* #~~ */ -> new SendSpecial1Node(frame, code, index, selectorIndex, BytecodePrimNotIdenticalSistaV1NodeGen.create()); + // case 25 /* #value */ -> must go through SelfSendNode; + // case 26 /* #value: */ -> must go through SelfSendNode; + // case 27 /* #do: */ -> fallthrough; + // case 28 /* #new */ -> fallthrough; + // case 29 /* #new: */ -> fallthrough; + case 30 /* #x: */ -> new SendSpecial0Node(frame, code, index, selectorIndex, BytecodePrimPointXNodeGen.create()); + case 31 /* #y: */ -> new SendSpecial0Node(frame, code, index, selectorIndex, BytecodePrimPointYNodeGen.create()); + default -> { + final SqueakImageContext image = code.getSqueakClass().getImage(); + final NativeObject specialSelector = image.getSpecialSelector(selectorIndex); + final int numArguments = image.getSpecialSelectorNumArgs(selectorIndex); + yield new SelfSendNode(frame, code, index, 1, specialSelector, numArguments); + } + }; + } + + private abstract static class AbstractBytecodePrimXNode extends AbstractNode { + protected final NativeObject getSpecialSelector() { + return getContext().getSpecialSelector(getSelectorIndex()); + } + + abstract int getSelectorIndex(); + } - @Child protected FrameStackWriteNode writeNode; + protected static final class SendSpecial0Node extends AbstractInstrumentableBytecodeNode { + @Child private FrameStackReadNode receiverNode; + @Child private FrameStackWriteNode writeResultNode; + @Child private DispatchBytecodePrim0Node dispatchNode; - protected AbstractSendSpecialSelectorQuickNode(final CompiledCodeObject code, final int index, final int selectorIndex) { + SendSpecial0Node(final VirtualFrame frame, final CompiledCodeObject code, final int index, final int selectorIndex, final DispatchBytecodePrim0Node dispatchNode) { super(code, index, 1); - this.selectorIndex = selectorIndex; - } - - public static AbstractBytecodeNode create(final VirtualFrame frame, final CompiledCodeObject code, final int index, final int selectorIndex) { - int primitiveIndex = -1; - final SqueakImageContext image = code.getSqueakClass().getImage(); - final NativeObject specialSelector = image.getSpecialSelector(selectorIndex); - final int numArguments = image.getSpecialSelectorNumArgs(selectorIndex); - if (0 <= selectorIndex && selectorIndex <= 15) { // arithmetic primitives - /* - * Peek at receiver and only use a primitive if it is a SmallInteger (see - * #arithmeticSelectorPrimitive). - */ - final int receiverStackIndex = FrameAccess.getStackPointer(frame) - 2; - final Object receiver = FrameAccess.getStackValue(frame, receiverStackIndex, FrameAccess.getNumArguments(frame)); - if (receiver instanceof Long || receiver instanceof Double) { - // TODO: can this be expanded to Characters and others? - final Object lookupResult = SqueakObjectClassNode.executeUncached(receiver).lookupInMethodDictSlow(specialSelector); - if (lookupResult instanceof CompiledCodeObject method && method.hasPrimitive()) { - assert method.getNumArgs() == numArguments; - primitiveIndex = method.primitiveIndex(); - } - } - } else if (selectorIndex == 16 || selectorIndex == 17) { // #at:, #at:put: - return new SendSpecialSelectorQuickWithClassCheck1OrMoreArgumentsNode(code, index, selectorIndex); - } else if (selectorIndex == 18) { // #size - return new SendSpecialSelectorQuickWithClassCheck0ArgumentsNode(code, index, selectorIndex); - } else if (selectorIndex == 22) { // #== - primitiveIndex = 110; - } else if (selectorIndex == 23) { // #class - primitiveIndex = 111; - } else if (selectorIndex == 24) { // #~~ - primitiveIndex = 169; - } else if (selectorIndex == 25 || selectorIndex == 26) { // #value, #value: - /* - * Closure primitives must go through the normal send infrastructure. This node does - * not handle NonLocalReturn and NonVirtualReturn. - */ - } else if (selectorIndex == 28) { // #new - return new SendSpecialSelectorQuickWithClassCheck0ArgumentsNode(code, index, selectorIndex); - } else if (selectorIndex == 29) { // #new: - return new SendSpecialSelectorQuickWithClassCheck1OrMoreArgumentsNode(code, index, selectorIndex); - } else if (selectorIndex == 30) { // #x - return SendSpecialSelectorQuickPointXNodeGen.create(code, index, selectorIndex); - } else if (selectorIndex == 31) { // #y - return SendSpecialSelectorQuickPointYNodeGen.create(code, index, selectorIndex); - } - if (primitiveIndex > 0) { - final int numReceiverAndArguments = 1 + numArguments; - final AbstractPrimitiveNode primitiveNode = PrimitiveNodeFactory.getOrCreateIndexed(primitiveIndex, numReceiverAndArguments); - assert primitiveNode != null; - final DispatchPrimitiveNode dispatchPrimitiveNode = DispatchPrimitiveNode.create(primitiveNode, ArgumentsLocation.ON_STACK_REVERSED, numReceiverAndArguments); - if (numArguments == 0) { - return new SendSpecialSelectorQuick0ArgumentsNode(code, index, selectorIndex, dispatchPrimitiveNode); - } else { - return new SendSpecialSelectorQuick1OrMoreArgumentsNode(code, index, selectorIndex, dispatchPrimitiveNode); - } - } else { - return new SelfSendNode(frame, code, index, 1, specialSelector, numArguments); - } + final int stackPointer = FrameAccess.getStackPointer(frame); + receiverNode = FrameStackReadNode.create(frame, stackPointer - 1, false); // overwritten + writeResultNode = FrameStackWriteNode.create(frame, stackPointer - 1); + assert selectorIndex == dispatchNode.getSelectorIndex(); + this.dispatchNode = dispatchNode; } - protected final void replaceWithSend(final VirtualFrame frame) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - // Replace with normal send (pc needs to be written) - FrameAccess.setInstructionPointer(frame, getSuccessorIndex()); - // Lookup specialSelector and replace with normal send - final SqueakImageContext image = SqueakImageContext.get(this); - final NativeObject specialSelector = image.getSpecialSelector(selectorIndex); - final int numArguments = image.getSpecialSelectorNumArgs(selectorIndex); - final CompiledCodeObject code = FrameAccess.getCodeObject(frame); - replace(new SelfSendNode(frame, code, index - code.getInitialPC(), 1, specialSelector, numArguments)).executeVoid(frame); + @Override + public void executeVoid(final VirtualFrame frame) { + writeResultNode.executeWrite(frame, dispatchNode.execute(frame, receiverNode.executeRead(frame))); } - protected final int findNewStackPointer(final VirtualFrame frame) { - final int numArguments = findNumArguments(); - final int stackPointer = FrameAccess.getStackPointer(frame) - (1 + numArguments) + 1; - assert stackPointer <= CONTEXT.MAX_STACK_SIZE : "Bad stack pointer"; - return stackPointer; + @Override + public String toString() { + CompilerAsserts.neverPartOfCompilation(); + return "send: " + dispatchNode.getSpecialSelector().asStringUnsafe(); } - protected final FrameStackWriteNode createFrameSlotWriteNode(final VirtualFrame frame) { - return createFrameSlotWriteNode(frame, findNewStackPointer(frame)); + abstract static class DispatchBytecodePrim0Node extends AbstractBytecodePrimXNode { + abstract Object execute(VirtualFrame frame, Object receiver); } - protected static final FrameStackWriteNode createFrameSlotWriteNode(final VirtualFrame frame, final int newStackPointer) { - return FrameStackWriteNode.create(frame, newStackPointer - 1); + abstract static class BytecodePrimSizeNode extends DispatchBytecodePrim0Node { + @Override + protected final int getSelectorIndex() { + return 18; + } + + @Specialization(guards = "receiver.isByteType()") + protected static final long doNativeObjectByte(final NativeObject receiver) { + return receiver.getByteLength(); + } + + @Specialization + protected static final long doArray(final ArrayObject receiver, + @Bind("this") final Node node, + @Cached final ArrayObjectSizeNode sizeNode) { + return sizeNode.execute(node, receiver); + } + + @Specialization(replaces = {"doNativeObjectByte", "doArray"}) + protected static final Object doSend(final VirtualFrame frame, final Object receiver, + @Cached("create(getSpecialSelector())") final Dispatch0Node dispatch0Node) { + return dispatch0Node.execute(frame, receiver); + } } - protected final NativeObject findSelector() { - return SqueakImageContext.get(this).getSpecialSelector(selectorIndex); + abstract static class BytecodePrimClassNode extends DispatchBytecodePrim0Node { + @Override + protected final int getSelectorIndex() { + return 23; + } + + @Specialization + protected static final ClassObject doGeneric(final Object receiver, + @Bind("this") final Node node, + @Cached final SqueakObjectClassNode classNode) { + return classNode.executeLookup(node, receiver); + } } - protected final int findNumArguments() { - return SqueakImageContext.get(this).getSpecialSelectorNumArgs(selectorIndex); + abstract static class BytecodePrimPointXNode extends DispatchBytecodePrim0Node { + @Override + protected final int getSelectorIndex() { + return 30; + } + + @Specialization + protected static final Object doPointers(final AbstractPointersObject receiver, + @Bind("this") final Node node, + @Cached final AbstractPointersObjectReadNode readNode) { + return readNode.execute(node, receiver, POINT.X); + } + + @Fallback + protected static final Object doSend(final VirtualFrame frame, final Object receiver, + @Cached("create(getSpecialSelector())") final Dispatch0Node dispatch0Node) { + return dispatch0Node.execute(frame, receiver); + } } - @Override - public final String toString() { - CompilerAsserts.neverPartOfCompilation(); - return "send: " + findSelector().asStringUnsafe(); + abstract static class BytecodePrimPointYNode extends DispatchBytecodePrim0Node { + @Override + protected final int getSelectorIndex() { + return 31; + } + + @Specialization + protected static final Object doPointers(final AbstractPointersObject receiver, + @Bind("this") final Node node, + @Cached final AbstractPointersObjectReadNode readNode) { + return readNode.execute(node, receiver, POINT.Y); + } + + @Fallback + protected static final Object doSend(final VirtualFrame frame, final Object receiver, + @Cached("create(getSpecialSelector())") final Dispatch0Node dispatch0Node) { + return dispatch0Node.execute(frame, receiver); + } } } - private abstract static class SendSpecialSelectorQuickNode extends AbstractSendSpecialSelectorQuickNode { - @Child protected DispatchPrimitiveNode primitiveNode; + protected static final class SendSpecial1Node extends AbstractInstrumentableBytecodeNode { + private final int newStackPointer; + @Child private FrameStackReadNode receiverNode; + @Child private FrameStackReadNode arg1Node; + @Child private FrameStackWriteNode writeResultNode; + @Child private DispatchBytecodePrim1Node dispatchNode; - private SendSpecialSelectorQuickNode(final CompiledCodeObject code, final int index, final int selectorIndex, final DispatchPrimitiveNode primitiveNode) { - super(code, index, selectorIndex); - this.primitiveNode = primitiveNode; + SendSpecial1Node(final VirtualFrame frame, final CompiledCodeObject code, final int index, final int selectorIndex, final DispatchBytecodePrim1Node dispatchNode) { + super(code, index, 1); + final int stackPointer = FrameAccess.getStackPointer(frame); + newStackPointer = stackPointer - 1; // pop arg + receiverNode = FrameStackReadNode.create(frame, stackPointer - 2, false); // overwritten + arg1Node = FrameStackReadNode.create(frame, stackPointer - 1, true); + writeResultNode = FrameStackWriteNode.create(frame, stackPointer - 2); + assert selectorIndex == dispatchNode.getSelectorIndex(); + this.dispatchNode = dispatchNode; } @Override public void executeVoid(final VirtualFrame frame) { - try { - popArgumentAndPush(frame, primitiveNode.execute(frame)); - } catch (final PrimitiveFailed pf) { - replaceWithSend(frame); - } + final Object result = dispatchNode.execute(frame, receiverNode.executeRead(frame), arg1Node.executeRead(frame)); + FrameAccess.setStackPointer(frame, newStackPointer); + writeResultNode.executeWrite(frame, result); } - protected abstract void popArgumentAndPush(VirtualFrame frame, Object result); - } + @Override + public String toString() { + CompilerAsserts.neverPartOfCompilation(); + return "send: " + dispatchNode.getSpecialSelector().asStringUnsafe(); + } - private static final class SendSpecialSelectorQuick0ArgumentsNode extends SendSpecialSelectorQuickNode { - private SendSpecialSelectorQuick0ArgumentsNode(final CompiledCodeObject code, final int index, final int selectorIndex, final DispatchPrimitiveNode primitiveNode) { - super(code, index, selectorIndex, primitiveNode); + abstract static class DispatchBytecodePrim1Node extends AbstractBytecodePrimXNode { + abstract Object execute(VirtualFrame frame, Object receiver, Object arg1); } - @Override - protected void popArgumentAndPush(final VirtualFrame frame, final Object result) { - if (writeNode == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - assert findNumArguments() == 0; - writeNode = insert(createFrameSlotWriteNode(frame)); + abstract static class BytecodePrimAddNode extends DispatchBytecodePrim1Node { + @Override + protected final int getSelectorIndex() { + return 0; } - writeNode.executeWrite(frame, result); - } - } - private static final class SendSpecialSelectorQuick1OrMoreArgumentsNode extends SendSpecialSelectorQuickNode { - @CompilationFinal private int stackPointer; + @Specialization(rewriteOn = ArithmeticException.class) + protected static final long doLong(final long lhs, final long rhs) { + return Math.addExact(lhs, rhs); + } - private SendSpecialSelectorQuick1OrMoreArgumentsNode(final CompiledCodeObject code, final int index, final int selectorIndex, final DispatchPrimitiveNode primitiveNode) { - super(code, index, selectorIndex, primitiveNode); - } + @Specialization(replaces = "doLong") + protected final Object doLongWithOverflow(final long lhs, final long rhs) { + return LargeIntegerObject.add(getContext(), lhs, rhs); + } - @Override - protected void popArgumentAndPush(final VirtualFrame frame, final Object result) { - if (writeNode == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - assert findNumArguments() > 0; - stackPointer = findNewStackPointer(frame); - writeNode = insert(createFrameSlotWriteNode(frame, stackPointer)); + @Specialization + protected static final double doDouble(final double lhs, final double rhs) { + return lhs + rhs; + } + + @Specialization(replaces = {"doLong", "doLongWithOverflow", "doDouble"}) + protected static final Object doSend(final VirtualFrame frame, final Object receiver, final Object arg1, + @Cached("create(getSpecialSelector())") final Dispatch1Node dispatch1Node) { + return dispatch1Node.execute(frame, receiver, arg1); } - FrameAccess.setStackPointer(frame, stackPointer); - writeNode.executeWrite(frame, result); } - } - private abstract static class SendSpecialSelectorQuickWithClassCheckNode extends AbstractSendSpecialSelectorQuickNode { - @CompilationFinal private ClassObject cachedReceiverClass; - @CompilationFinal private Assumption cachedCallTargetStableAssumption; + abstract static class BytecodePrimSubtractNode extends DispatchBytecodePrim1Node { + @Override + protected final int getSelectorIndex() { + return 1; + } - @Child protected DispatchPrimitiveNode primitiveNode; - @Child private FrameStackReadNode peekAtReceiverNode; - @Child private LookupClassNode lookupClassNode = LookupClassNode.create(); + @Specialization(rewriteOn = ArithmeticException.class) + protected static final long doLong(final long lhs, final long rhs) { + return Math.subtractExact(lhs, rhs); + } + + @Specialization(replaces = "doLong") + protected final Object doLongWithOverflow(final long lhs, final long rhs) { + return LargeIntegerObject.subtract(getContext(), lhs, rhs); + } - private SendSpecialSelectorQuickWithClassCheckNode(final CompiledCodeObject code, final int index, final int selectorIndex) { - super(code, index, selectorIndex); + @Specialization + protected static final double doDouble(final double lhs, final double rhs) { + return lhs - rhs; + } + + @Specialization(replaces = {"doLong", "doLongWithOverflow", "doDouble"}) + protected static final Object doSend(final VirtualFrame frame, final Object receiver, final Object arg1, + @Cached("create(getSpecialSelector())") final Dispatch1Node dispatch1Node) { + return dispatch1Node.execute(frame, receiver, arg1); + } } - @Override - public void executeVoid(final VirtualFrame frame) { - final Object receiver = peekAtReceiver(frame); - if (doesNotMatchClassOrMethodInvalidated(lookupClassNode.execute(receiver))) { - replaceWithSend(frame); - return; + abstract static class BytecodePrimLessThanNode extends DispatchBytecodePrim1Node { + @Override + protected final int getSelectorIndex() { + return 2; } - try { - popArgumentsAndPush(frame, primitiveNode.execute(frame)); - } catch (final PrimitiveFailed pf) { - replaceWithSend(frame); + + @Specialization + protected static final boolean doLong(final long lhs, final long rhs) { + return BooleanObject.wrap(lhs < rhs); + } + + @Specialization + protected static final boolean doDouble(final double lhs, final double rhs) { + return BooleanObject.wrap(lhs < rhs); + } + + @Specialization(replaces = {"doLong", "doDouble"}) + protected static final Object doSend(final VirtualFrame frame, final Object receiver, final Object arg1, + @Cached("create(getSpecialSelector())") final Dispatch1Node dispatch1Node) { + return dispatch1Node.execute(frame, receiver, arg1); } } - protected abstract void popArgumentsAndPush(VirtualFrame frame, Object result); + abstract static class BytecodePrimGreaterThanNode extends DispatchBytecodePrim1Node { + @Override + protected final int getSelectorIndex() { + return 3; + } - private boolean doesNotMatchClassOrMethodInvalidated(final ClassObject actualClass) { - if (primitiveNode == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - assert actualClass != null; - final Object lookupResult = actualClass.lookupInMethodDictSlow(findSelector()); - if (lookupResult instanceof final CompiledCodeObject primitiveMethod && primitiveMethod.hasPrimitive()) { - assert primitiveMethod.getNumArgs() == findNumArguments(); - final DispatchPrimitiveNode node = PrimitiveNodeFactory.getOrCreateIndexedOrNamed(primitiveMethod, ArgumentsLocation.ON_STACK_REVERSED); - if (node == null) { - return true; // primitive not found / supported - } - primitiveNode = insert(node); - cachedReceiverClass = actualClass; - cachedCallTargetStableAssumption = primitiveMethod.getCallTargetStable(); - } else { - return true; - } + @Specialization + protected static final boolean doLong(final long lhs, final long rhs) { + return BooleanObject.wrap(lhs > rhs); + } + + @Specialization + protected static final boolean doDouble(final double lhs, final double rhs) { + return BooleanObject.wrap(lhs > rhs); + } + + @Specialization(replaces = {"doLong", "doDouble"}) + protected static final Object doSend(final VirtualFrame frame, final Object receiver, final Object arg1, + @Cached("create(getSpecialSelector())") final Dispatch1Node dispatch1Node) { + return dispatch1Node.execute(frame, receiver, arg1); } - return actualClass != cachedReceiverClass || !cachedCallTargetStableAssumption.isValid(); } - private Object peekAtReceiver(final VirtualFrame frame) { - if (peekAtReceiverNode == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - final int currentStackPointer = FrameAccess.getStackPointer(frame) - (1 + findNumArguments()); - peekAtReceiverNode = insert(FrameStackReadNode.create(frame, currentStackPointer, false)); + abstract static class BytecodePrimLessOrEqualNode extends DispatchBytecodePrim1Node { + @Override + protected final int getSelectorIndex() { + return 4; + } + + @Specialization + protected static final boolean doLong(final long lhs, final long rhs) { + return BooleanObject.wrap(lhs <= rhs); + } + + @Specialization + protected static final boolean doDouble(final double lhs, final double rhs) { + return BooleanObject.wrap(lhs <= rhs); + } + + @Specialization(replaces = {"doLong", "doDouble"}) + protected static final Object doSend(final VirtualFrame frame, final Object receiver, final Object arg1, + @Cached("create(getSpecialSelector())") final Dispatch1Node dispatch1Node) { + return dispatch1Node.execute(frame, receiver, arg1); } - return peekAtReceiverNode.executeRead(frame); } - } - private static final class SendSpecialSelectorQuickWithClassCheck0ArgumentsNode extends SendSpecialSelectorQuickWithClassCheckNode { - private SendSpecialSelectorQuickWithClassCheck0ArgumentsNode(final CompiledCodeObject code, final int index, final int selectorIndex) { - super(code, index, selectorIndex); + abstract static class BytecodePrimGreaterOrEqualNode extends DispatchBytecodePrim1Node { + @Override + protected final int getSelectorIndex() { + return 5; + } + + @Specialization + protected static final boolean doLong(final long lhs, final long rhs) { + return BooleanObject.wrap(lhs >= rhs); + } + + @Specialization + protected static final boolean doDouble(final double lhs, final double rhs) { + return BooleanObject.wrap(lhs >= rhs); + } + + @Specialization(replaces = {"doLong", "doDouble"}) + protected static final Object doSend(final VirtualFrame frame, final Object receiver, final Object arg1, + @Cached("create(getSpecialSelector())") final Dispatch1Node dispatch1Node) { + return dispatch1Node.execute(frame, receiver, arg1); + } } - @Override - protected void popArgumentsAndPush(final VirtualFrame frame, final Object result) { - if (writeNode == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - assert findNumArguments() == 0; - writeNode = insert(createFrameSlotWriteNode(frame)); + abstract static class BytecodePrimEqualNode extends DispatchBytecodePrim1Node { + @Override + protected final int getSelectorIndex() { + return 6; + } + + @Specialization + protected static final boolean doLong(final long lhs, final long rhs) { + return BooleanObject.wrap(lhs == rhs); + } + + @Specialization + protected static final boolean doDouble(final double lhs, final double rhs) { + return BooleanObject.wrap(lhs == rhs); + } + + @Specialization(replaces = {"doLong", "doDouble"}) + protected static final Object doSend(final VirtualFrame frame, final Object receiver, final Object arg1, + @Cached("create(getSpecialSelector())") final Dispatch1Node dispatch1Node) { + return dispatch1Node.execute(frame, receiver, arg1); } - writeNode.executeWrite(frame, result); } - } - private static final class SendSpecialSelectorQuickWithClassCheck1OrMoreArgumentsNode extends SendSpecialSelectorQuickWithClassCheckNode { - @CompilationFinal private int stackPointer; + abstract static class BytecodePrimNotEqualNode extends DispatchBytecodePrim1Node { + @Override + protected final int getSelectorIndex() { + return 7; + } - private SendSpecialSelectorQuickWithClassCheck1OrMoreArgumentsNode(final CompiledCodeObject code, final int index, final int selectorIndex) { - super(code, index, selectorIndex); + @Specialization + protected static final boolean doLong(final long lhs, final long rhs) { + return BooleanObject.wrap(lhs != rhs); + } + + @Specialization + protected static final boolean doDouble(final double lhs, final double rhs) { + return BooleanObject.wrap(lhs != rhs); + } + + @Specialization(replaces = {"doLong", "doDouble"}) + protected static final Object doSend(final VirtualFrame frame, final Object receiver, final Object arg1, + @Cached("create(getSpecialSelector())") final Dispatch1Node dispatch1Node) { + return dispatch1Node.execute(frame, receiver, arg1); + } } - @Override - protected void popArgumentsAndPush(final VirtualFrame frame, final Object result) { - if (writeNode == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - assert findNumArguments() > 0; - stackPointer = findNewStackPointer(frame); - writeNode = insert(createFrameSlotWriteNode(frame, stackPointer)); + abstract static class BytecodePrimMultiplyNode extends DispatchBytecodePrim1Node { + @Override + protected final int getSelectorIndex() { + return 8; + } + + @Specialization(rewriteOn = ArithmeticException.class) + protected static final long doLong(final long lhs, final long rhs) { + return Math.multiplyExact(lhs, rhs); + } + + @Specialization(replaces = "doLong") + protected final Object doLongWithOverflow(final long lhs, final long rhs) { + return LargeIntegerObject.multiply(getContext(), lhs, rhs); + } + + @Specialization(rewriteOn = RespecializeException.class) + protected static final double doDoubleFinite(final double lhs, final double rhs) throws RespecializeException { + return ensureFinite(lhs * rhs); + } + + @Specialization(replaces = "doDoubleFinite") + protected static final Object doDouble(final double lhs, final double rhs, + @Bind("this") final Node node, + @Cached final AsFloatObjectIfNessaryNode boxNode) { + return boxNode.execute(node, lhs * rhs); + } + + @Specialization(replaces = {"doLong", "doLongWithOverflow", "doDoubleFinite", "doDouble"}) + protected static final Object doSend(final VirtualFrame frame, final Object receiver, final Object arg1, + @Cached("create(getSpecialSelector())") final Dispatch1Node dispatch1Node) { + return dispatch1Node.execute(frame, receiver, arg1); } - FrameAccess.setStackPointer(frame, stackPointer); - writeNode.executeWrite(frame, result); } - } - @GenerateCached(false) - protected abstract static class AbstractSendSpecialSelectorQuickPointXYNode extends AbstractSendSpecialSelectorQuickNode { - @Child private FrameStackReadNode peekAtReceiverNode; - @Child private LookupClassNode lookupClassNode = LookupClassNode.create(); - @CompilationFinal private ClassObject pointClass; + abstract static class BytecodePrimDivideNode extends DispatchBytecodePrim1Node { + @Override + protected final int getSelectorIndex() { + return 9; + } + + @Specialization(guards = {"rhs != 0", "!isOverflowDivision(lhs, rhs)", "isIntegralWhenDividedBy(lhs, rhs)"}) + protected static final long doLong(final long lhs, final long rhs) { + return lhs / rhs; + } + + @Specialization(guards = "!isZero(rhs)", rewriteOn = RespecializeException.class) + protected static final double doDoubleFinite(final double lhs, final double rhs) throws RespecializeException { + return ensureFinite(lhs / rhs); + } + + @Specialization(guards = "!isZero(rhs)", replaces = "doDoubleFinite") + protected static final Object doDouble(final double lhs, final double rhs, + @Bind("this") final Node node, + @Cached final AsFloatObjectIfNessaryNode boxNode) { + return boxNode.execute(node, lhs / rhs); + } - protected AbstractSendSpecialSelectorQuickPointXYNode(final CompiledCodeObject code, final int index, final int selectorIndex) { - super(code, index, selectorIndex); + @Specialization(replaces = {"doLong", "doDoubleFinite", "doDouble"}) + protected static final Object doSend(final VirtualFrame frame, final Object receiver, final Object arg1, + @Cached("create(getSpecialSelector())") final Dispatch1Node dispatch1Node) { + return dispatch1Node.execute(frame, receiver, arg1); + } } - @Specialization - protected final void doSend(final VirtualFrame frame, - @Bind("this") final Node node, - @Cached final AbstractPointersObjectReadNode readNode) { - final Object receiver = peekAtReceiver(frame); - if (lookupClassNode.execute(receiver) != getPointClass()) { - replaceWithSend(frame); - return; + abstract static class BytecodePrimModNode extends DispatchBytecodePrim1Node { + @Override + protected final int getSelectorIndex() { + return 10; + } + + /** Profiled version of {@link Math#floorMod(long, long)}. */ + @Specialization(guards = "rhs != 0") + protected static final long doLong(final long lhs, final long rhs, + @Bind("this") final Node node, + @Cached final InlinedConditionProfile profile) { + final long r = lhs % rhs; + // if the signs are different and modulo not zero, adjust result + if (profile.profile(node, (lhs ^ rhs) < 0 && r != 0)) { + return r + rhs; + } else { + return r; + } + } + + @Specialization(replaces = {"doLong"}) + protected static final Object doSend(final VirtualFrame frame, final Object receiver, final Object arg1, + @Cached("create(getSpecialSelector())") final Dispatch1Node dispatch1Node) { + return dispatch1Node.execute(frame, receiver, arg1); } - popArgumentAndPush(frame, readNode.execute(node, (AbstractPointersObject) receiver, getPointInstVarIndex())); } - private ClassObject getPointClass() { - if (pointClass == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - pointClass = getContext().pointClass; + abstract static class BytecodePrimMakePointNode extends DispatchBytecodePrim1Node { + @Override + protected final int getSelectorIndex() { + return 11; + } + + @Specialization + protected static final PointersObject doLong(final long xPos, final long yPos, + @Bind("this") final Node node, + @Shared("writeNode") @Cached final AbstractPointersObjectWriteNode writeNode) { + return getContext(node).asPoint(writeNode, node, xPos, yPos); + } + + @Specialization + protected static final PointersObject doDouble(final double xPos, final double yPos, + @Bind("this") final Node node, + @Shared("writeNode") @Cached final AbstractPointersObjectWriteNode writeNode) { + return getContext(node).asPoint(writeNode, node, xPos, yPos); + } + + @Specialization(replaces = {"doLong", "doDouble"}) + protected static final Object doSend(final VirtualFrame frame, final Object receiver, final Object arg1, + @Cached("create(getSpecialSelector())") final Dispatch1Node dispatch1Node) { + return dispatch1Node.execute(frame, receiver, arg1); } - return pointClass; } - protected abstract int getPointInstVarIndex(); + abstract static class BytecodePrimBitShiftNode extends DispatchBytecodePrim1Node { + @Override + protected final int getSelectorIndex() { + return 12; + } - private void popArgumentAndPush(final VirtualFrame frame, final Object value) { - if (writeNode == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - assert findNumArguments() == 0; - writeNode = insert(createFrameSlotWriteNode(frame)); + @Specialization(guards = {"arg >= 0", "!isLShiftLongOverflow(receiver, arg)"}) + protected static final long doLongPositive(final long receiver, final long arg) { + return receiver << arg; + } + + @Specialization(replaces = {"doLongPositive"}) + protected static final Object doSend(final VirtualFrame frame, final Object receiver, final Object arg1, + @Cached("create(getSpecialSelector())") final Dispatch1Node dispatch1Node) { + return dispatch1Node.execute(frame, receiver, arg1); } - writeNode.executeWrite(frame, value); } - private Object peekAtReceiver(final VirtualFrame frame) { - if (peekAtReceiverNode == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - final int currentStackPointer = FrameAccess.getStackPointer(frame) - 1; - peekAtReceiverNode = insert(FrameStackReadNode.create(frame, currentStackPointer, false)); + abstract static class BytecodePrimDivNode extends DispatchBytecodePrim1Node { + @Override + protected final int getSelectorIndex() { + return 13; + } + + /** Profiled version of {@link Math#floorDiv(long, long)}. */ + @Specialization(guards = {"rhs != 0", "!isOverflowDivision(lhs, rhs)"}) + protected static final long doLong(final long lhs, final long rhs, + @Bind("this") final Node node, + @Cached final InlinedConditionProfile profile) { + final long q = lhs / rhs; + // if the signs are different and modulo not zero, round down + if (profile.profile(node, (lhs ^ rhs) < 0 && (q * rhs != lhs))) { + return q - 1; + } else { + return q; + } + } + + @Specialization(replaces = {"doLong"}) + protected static final Object doSend(final VirtualFrame frame, final Object receiver, final Object arg1, + @Cached("create(getSpecialSelector())") final Dispatch1Node dispatch1Node) { + return dispatch1Node.execute(frame, receiver, arg1); } - return peekAtReceiverNode.executeRead(frame); } - } - protected abstract static class SendSpecialSelectorQuickPointXNode extends AbstractSendSpecialSelectorQuickPointXYNode { - protected SendSpecialSelectorQuickPointXNode(final CompiledCodeObject code, final int index, final int selectorIndex) { - super(code, index, selectorIndex); + abstract static class BytecodePrimBitAndNode extends DispatchBytecodePrim1Node { + @Override + protected final int getSelectorIndex() { + return 14; + } + + @Specialization + protected static final long doLong(final long receiver, final long arg) { + return receiver & arg; + } + + @Specialization(replaces = {"doLong"}) + protected static final Object doSend(final VirtualFrame frame, final Object receiver, final Object arg1, + @Cached("create(getSpecialSelector())") final Dispatch1Node dispatch1Node) { + return dispatch1Node.execute(frame, receiver, arg1); + } } - @Override - protected final int getPointInstVarIndex() { - return POINT.X; + abstract static class BytecodePrimBitOrNode extends DispatchBytecodePrim1Node { + @Override + protected final int getSelectorIndex() { + return 15; + } + + @Specialization + protected static final long doLong(final long receiver, final long arg) { + return receiver | arg; + } + + @Specialization(replaces = {"doLong"}) + protected static final Object doSend(final VirtualFrame frame, final Object receiver, final Object arg1, + @Cached("create(getSpecialSelector())") final Dispatch1Node dispatch1Node) { + return dispatch1Node.execute(frame, receiver, arg1); + } } - } - protected abstract static class SendSpecialSelectorQuickPointYNode extends AbstractSendSpecialSelectorQuickPointXYNode { - protected SendSpecialSelectorQuickPointYNode(final CompiledCodeObject code, final int index, final int selectorIndex) { - super(code, index, selectorIndex); + abstract static class BytecodePrimIdenticalSistaV1Node extends DispatchBytecodePrim1Node { + @Override + protected final int getSelectorIndex() { + return 22; + } + + @Specialization + protected static final boolean doGeneric(final Object receiver, final Object arg1, + @Bind("this") final Node node, + @Cached final SqueakObjectIdentityNode identityNode) { + return identityNode.execute(node, receiver, arg1); + } } - @Override - protected final int getPointInstVarIndex() { - return POINT.Y; + abstract static class BytecodePrimNotIdenticalSistaV1Node extends DispatchBytecodePrim1Node { + @Override + protected final int getSelectorIndex() { + return 24; + } + + @Specialization + protected static final boolean doGeneric(final Object receiver, final Object arg1, + @Bind("this") final Node node, + @Cached final SqueakObjectIdentityNode identityNode) { + return !identityNode.execute(node, receiver, arg1); + } } } } 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 index 534c9daf0..11730bf97 100644 --- 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 @@ -79,7 +79,7 @@ private static AbstractBytecodeNode decodeBytecode(final VirtualFrame frame, fin } case 0x5F -> new MiscellaneousBytecodes.NopBytecodeNode(code, index); case 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F // - -> SendBytecodes.AbstractSendSpecialSelectorQuickNode.create(frame, code, index, b - 96); + -> SendBytecodes.createSpecialSelectorSend(frame, code, index, b - 96); case 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F // -> new SendBytecodes.SelfSendNode(frame, code, index, 1, (NativeObject) code.getLiteral(b & 0xF), 0); case 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F // diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/bytecodes/SqueakBytecodeV3PlusClosuresDecoder.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/bytecodes/SqueakBytecodeV3PlusClosuresDecoder.java index e05e3ea94..d71e3c48b 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/bytecodes/SqueakBytecodeV3PlusClosuresDecoder.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/bytecodes/SqueakBytecodeV3PlusClosuresDecoder.java @@ -93,7 +93,7 @@ public AbstractBytecodeNode decodeBytecode(final VirtualFrame frame, final Compi case 0xA8, 0xA9, 0xAA, 0xAB -> JumpBytecodes.ConditionalJumpOnTrueNode.createLong(code, index, b, bytecode[index + 1]); case 0xAC, 0xAD, 0xAE, 0xAF -> JumpBytecodes.ConditionalJumpOnFalseNode.createLong(code, index, b, bytecode[index + 1]); case 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF // - -> SendBytecodes.AbstractSendSpecialSelectorQuickNode.create(frame, code, index, b - 176); + -> SendBytecodes.createSpecialSelectorSend(frame, code, index, b - 176); case 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF // -> new SendBytecodes.SelfSendNode(frame, code, index, 1, (NativeObject) code.getLiteral(b & 0xF), 0); case 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF // diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/dispatch/LookupClassNode.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/dispatch/LookupClassNode.java deleted file mode 100644 index 0c2717cc3..000000000 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/dispatch/LookupClassNode.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2017-2025 Software Architecture Group, Hasso Plattner Institute - * Copyright (c) 2021-2025 Oracle and/or its affiliates - * - * Licensed under the MIT License. - */ -package de.hpi.swa.trufflesqueak.nodes.dispatch; - -import com.oracle.truffle.api.dsl.Bind; -import com.oracle.truffle.api.dsl.Cached; -import com.oracle.truffle.api.dsl.ImportStatic; -import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.api.nodes.Node; - -import de.hpi.swa.trufflesqueak.model.ClassObject; -import de.hpi.swa.trufflesqueak.nodes.AbstractNode; -import de.hpi.swa.trufflesqueak.nodes.accessing.SqueakObjectClassNode; -import de.hpi.swa.trufflesqueak.nodes.bytecodes.SendBytecodes.SelfSendNode; - -@SuppressWarnings("truffle-inlining") -@ImportStatic(SelfSendNode.class) -public abstract class LookupClassNode extends AbstractNode { - - public static LookupClassNode create() { - return LookupClassNodeGen.create(); - } - - public abstract ClassObject execute(Object receiver); - - @Specialization(guards = "guard.check(receiver)", assumptions = "guard.getIsValidAssumption()", limit = "INLINE_METHOD_CACHE_LIMIT") - protected static final ClassObject doCached(@SuppressWarnings("unused") final Object receiver, - @Bind("this") final Node node, - @Cached("create(receiver)") final LookupClassGuard guard) { - return guard.getSqueakClass(node); - } - - @Specialization(replaces = "doCached") - protected static final ClassObject doGeneric(final Object receiver, - @Bind("this") final Node node, - @Cached final SqueakObjectClassNode classNode) { - return classNode.executeLookup(node, receiver); - } -} diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/dispatch/LookupSelectorNode.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/dispatch/LookupSelectorNode.java deleted file mode 100644 index 4da5e9249..000000000 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/dispatch/LookupSelectorNode.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2017-2025 Software Architecture Group, Hasso Plattner Institute - * Copyright (c) 2021-2025 Oracle and/or its affiliates - * - * Licensed under the MIT License. - */ -package de.hpi.swa.trufflesqueak.nodes.dispatch; - -import java.util.ArrayList; - -import com.oracle.truffle.api.Assumption; -import com.oracle.truffle.api.dsl.Cached; -import com.oracle.truffle.api.dsl.ImportStatic; -import com.oracle.truffle.api.dsl.ReportPolymorphism; -import com.oracle.truffle.api.dsl.Specialization; - -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.nodes.AbstractNode; -import de.hpi.swa.trufflesqueak.nodes.bytecodes.SendBytecodes.SelfSendNode; -import de.hpi.swa.trufflesqueak.util.MethodCacheEntry; - -@ImportStatic(SelfSendNode.class) -public abstract class LookupSelectorNode extends AbstractNode { - protected final NativeObject selector; - - protected LookupSelectorNode(final NativeObject selector) { - this.selector = selector; - } - - public static LookupSelectorNode create(final NativeObject selector) { - return LookupSelectorNodeGen.create(selector); - } - - public abstract Object execute(ClassObject receiverClass); - - @SuppressWarnings("unused") - @Specialization(limit = "INLINE_METHOD_CACHE_LIMIT", guards = {"receiverClass == cachedClass"}, assumptions = {"assumptions"}) - protected static final Object doCached(final ClassObject receiverClass, - @Cached("receiverClass") final ClassObject cachedClass, - @Cached("receiverClass.lookupInMethodDictSlow(selector)") final Object cachedLookupResult, - @Cached(value = "createAssumptions(receiverClass, cachedLookupResult)", dimensions = 1) final Assumption[] assumptions) { - return cachedLookupResult; - } - - protected static final Assumption[] createAssumptions(final ClassObject receiverClass, final Object lookupResult) { - final ClassObject methodClass; - if (lookupResult instanceof final CompiledCodeObject method) { - assert method.isCompiledMethod(); - methodClass = method.getMethodClassSlow(); - } else { - /* DNU or OAM, return assumptions for all superclasses. */ - methodClass = null; - } - final ArrayList list = new ArrayList<>(); - ClassObject currentClass = receiverClass; - while (currentClass != null) { - list.add(currentClass.getClassHierarchyAndMethodDictStable()); - if (currentClass == methodClass) { - break; - } else { - currentClass = currentClass.getSuperclassOrNull(); - } - } - // TODO: the receiverClass can be an outdated version of methodClass. In this case, a list - // of assumptions for the entire class hierarchy is returned. Maybe this can/should be - // avoided. - return list.toArray(new Assumption[0]); - } - - @ReportPolymorphism.Megamorphic - @Specialization(replaces = "doCached") - protected final Object doUncached(final ClassObject receiverClass) { - final MethodCacheEntry cachedEntry = getContext().findMethodCacheEntry(receiverClass, selector); - if (cachedEntry.getResult() == null) { - cachedEntry.setResult(receiverClass.lookupInMethodDictSlow(selector)); - } - return cachedEntry.getResult(); - } -} diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/Matrix2x3Plugin.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/Matrix2x3Plugin.java index 1a1554259..76d7d1d16 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/Matrix2x3Plugin.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/Matrix2x3Plugin.java @@ -28,8 +28,8 @@ import de.hpi.swa.trufflesqueak.nodes.accessing.AbstractPointersObjectNodes.AbstractPointersObjectWriteNode; import de.hpi.swa.trufflesqueak.nodes.primitives.AbstractPrimitiveFactoryHolder; import de.hpi.swa.trufflesqueak.nodes.primitives.AbstractPrimitiveNode; -import de.hpi.swa.trufflesqueak.nodes.primitives.Primitive.Primitive1WithFallback; import de.hpi.swa.trufflesqueak.nodes.primitives.Primitive.Primitive0WithFallback; +import de.hpi.swa.trufflesqueak.nodes.primitives.Primitive.Primitive1WithFallback; import de.hpi.swa.trufflesqueak.nodes.primitives.Primitive.Primitive2WithFallback; import de.hpi.swa.trufflesqueak.nodes.primitives.SqueakPrimitive; @@ -72,7 +72,7 @@ protected final double loadArgumentPointY(final PointersObject point, final Abst return loadArgumentPointAt(point, POINT.Y, readNode, errorProfile, node); } - private double loadArgumentPointAt(final PointersObject point, final int index, final AbstractPointersObjectReadNode readNode, final InlinedBranchProfile errorProfile, final Node node) { + private double loadArgumentPointAt(final PointersObject point, final long index, final AbstractPointersObjectReadNode readNode, final InlinedBranchProfile errorProfile, final Node node) { if (isPoint(point)) { final Object value = readNode.execute(node, point, index); if (value instanceof final Long longValue) { diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/DispatchPrimitiveNode.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/DispatchPrimitiveNode.java deleted file mode 100644 index 682414592..000000000 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/DispatchPrimitiveNode.java +++ /dev/null @@ -1,380 +0,0 @@ -/* - * Copyright (c) 2024-2025 Software Architecture Group, Hasso Plattner Institute - * Copyright (c) 2024-2025 Oracle and/or its affiliates - * - * Licensed under the MIT License. - */ -package de.hpi.swa.trufflesqueak.nodes.primitives; - -import com.oracle.truffle.api.frame.VirtualFrame; - -import de.hpi.swa.trufflesqueak.exceptions.SqueakExceptions.SqueakException; -import de.hpi.swa.trufflesqueak.nodes.AbstractNode; -import de.hpi.swa.trufflesqueak.nodes.context.ArgumentNodes.AbstractArgumentNode; -import de.hpi.swa.trufflesqueak.nodes.primitives.Primitive.Primitive1; -import de.hpi.swa.trufflesqueak.nodes.primitives.Primitive.Primitive9; -import de.hpi.swa.trufflesqueak.nodes.primitives.Primitive.Primitive11; -import de.hpi.swa.trufflesqueak.nodes.primitives.Primitive.Primitive8; -import de.hpi.swa.trufflesqueak.nodes.primitives.Primitive.Primitive7; -import de.hpi.swa.trufflesqueak.nodes.primitives.Primitive.Primitive0; -import de.hpi.swa.trufflesqueak.nodes.primitives.Primitive.Primitive3; -import de.hpi.swa.trufflesqueak.nodes.primitives.Primitive.Primitive4; -import de.hpi.swa.trufflesqueak.nodes.primitives.Primitive.Primitive5; -import de.hpi.swa.trufflesqueak.nodes.primitives.Primitive.Primitive6; -import de.hpi.swa.trufflesqueak.nodes.primitives.Primitive.Primitive2; -import de.hpi.swa.trufflesqueak.nodes.primitives.Primitive.Primitive10; -import de.hpi.swa.trufflesqueak.nodes.primitives.PrimitiveNodeFactory.ArgumentsLocation; - -public abstract class DispatchPrimitiveNode extends AbstractNode { - @Child protected AbstractPrimitiveNode primitiveNode; - - private DispatchPrimitiveNode(final AbstractPrimitiveNode primitiveNode) { - this.primitiveNode = primitiveNode; - } - - public static DispatchPrimitiveNode create(final AbstractPrimitiveNode primitiveNode, final ArgumentsLocation location, final int numReceiverAndArguments) { - final AbstractArgumentNode[] argumentNodes = createArgumentNodes(location, numReceiverAndArguments); - return switch (numReceiverAndArguments) { - case 1 -> new DispatchPrimitive1Node(primitiveNode, argumentNodes); - case 2 -> new DispatchPrimitive2Node(primitiveNode, argumentNodes); - case 3 -> new DispatchPrimitive3Node(primitiveNode, argumentNodes); - case 4 -> new DispatchPrimitive4Node(primitiveNode, argumentNodes); - case 5 -> new DispatchPrimitive5Node(primitiveNode, argumentNodes); - case 6 -> new DispatchPrimitive6Node(primitiveNode, argumentNodes); - case 7 -> new DispatchPrimitive7Node(primitiveNode, argumentNodes); - case 8 -> new DispatchPrimitive8Node(primitiveNode, argumentNodes); - case 9 -> new DispatchPrimitive9Node(primitiveNode, argumentNodes); - case 10 -> new DispatchPrimitive10Node(primitiveNode, argumentNodes); - case 11 -> new DispatchPrimitive11Node(primitiveNode, argumentNodes); - case 12 -> new DispatchPrimitive12Node(primitiveNode, argumentNodes); - default -> throw SqueakException.create("Unexpected number of arguments " + numReceiverAndArguments); - }; - } - - private static AbstractArgumentNode[] createArgumentNodes(final ArgumentsLocation location, final int numReceiverAndArguments) { - final AbstractArgumentNode[] argumentNodes = new AbstractArgumentNode[numReceiverAndArguments]; - final boolean useStack = location == ArgumentsLocation.ON_STACK || location == ArgumentsLocation.ON_STACK_REVERSED; - final int offset = location == ArgumentsLocation.ON_STACK_REVERSED ? numReceiverAndArguments : 0; - for (int i = 0; i < numReceiverAndArguments; i++) { - argumentNodes[i] = AbstractArgumentNode.create(i - offset, useStack); - } - return argumentNodes; - } - - public abstract Object execute(VirtualFrame frame); - - public String getPrimitiveNodeClassSimpleName() { - return primitiveNode.getClass().getSimpleName(); - } - - private static final class DispatchPrimitive1Node extends DispatchPrimitiveNode { - @Child private AbstractArgumentNode receiverNode; - - private DispatchPrimitive1Node(final AbstractPrimitiveNode primitiveNode, final AbstractArgumentNode[] argumentNodes) { - super(primitiveNode); - receiverNode = argumentNodes[0]; - } - - @Override - public Object execute(final VirtualFrame frame) { - return ((Primitive0) primitiveNode).execute(frame, receiverNode.execute(frame)); - } - } - - private static final class DispatchPrimitive2Node extends DispatchPrimitiveNode { - @Child private AbstractArgumentNode receiverNode; - @Child private AbstractArgumentNode argument1Node; - - private DispatchPrimitive2Node(final AbstractPrimitiveNode primitiveNode, final AbstractArgumentNode[] argumentNodes) { - super(primitiveNode); - receiverNode = argumentNodes[0]; - argument1Node = argumentNodes[1]; - } - - @Override - public Object execute(final VirtualFrame frame) { - return ((Primitive1) primitiveNode).execute(frame, receiverNode.execute(frame), argument1Node.execute(frame)); - } - } - - private static final class DispatchPrimitive3Node extends DispatchPrimitiveNode { - @Child private AbstractArgumentNode receiverNode; - @Child private AbstractArgumentNode argument1Node; - @Child private AbstractArgumentNode argument2Node; - - private DispatchPrimitive3Node(final AbstractPrimitiveNode primitiveNode, final AbstractArgumentNode[] argumentNodes) { - super(primitiveNode); - receiverNode = argumentNodes[0]; - argument1Node = argumentNodes[1]; - argument2Node = argumentNodes[2]; - } - - @Override - public Object execute(final VirtualFrame frame) { - return ((Primitive2) primitiveNode).execute(frame, receiverNode.execute(frame), argument1Node.execute(frame), argument2Node.execute(frame)); - } - } - - private static final class DispatchPrimitive4Node extends DispatchPrimitiveNode { - @Child private AbstractArgumentNode receiverNode; - @Child private AbstractArgumentNode argument1Node; - @Child private AbstractArgumentNode argument2Node; - @Child private AbstractArgumentNode argument3Node; - - private DispatchPrimitive4Node(final AbstractPrimitiveNode primitiveNode, final AbstractArgumentNode[] argumentNodes) { - super(primitiveNode); - receiverNode = argumentNodes[0]; - argument1Node = argumentNodes[1]; - argument2Node = argumentNodes[2]; - argument3Node = argumentNodes[3]; - } - - @Override - public Object execute(final VirtualFrame frame) { - return ((Primitive3) primitiveNode).execute(frame, receiverNode.execute(frame), argument1Node.execute(frame), argument2Node.execute(frame), argument3Node.execute(frame)); - } - } - - private static final class DispatchPrimitive5Node extends DispatchPrimitiveNode { - @Child private AbstractArgumentNode receiverNode; - @Child private AbstractArgumentNode argument1Node; - @Child private AbstractArgumentNode argument2Node; - @Child private AbstractArgumentNode argument3Node; - @Child private AbstractArgumentNode argument4Node; - - private DispatchPrimitive5Node(final AbstractPrimitiveNode primitiveNode, final AbstractArgumentNode[] argumentNodes) { - super(primitiveNode); - receiverNode = argumentNodes[0]; - argument1Node = argumentNodes[1]; - argument2Node = argumentNodes[2]; - argument3Node = argumentNodes[3]; - argument4Node = argumentNodes[4]; - } - - @Override - public Object execute(final VirtualFrame frame) { - return ((Primitive4) primitiveNode).execute(frame, receiverNode.execute(frame), argument1Node.execute(frame), argument2Node.execute(frame), argument3Node.execute(frame), - argument4Node.execute(frame)); - } - } - - private static final class DispatchPrimitive6Node extends DispatchPrimitiveNode { - @Child private AbstractArgumentNode receiverNode; - @Child private AbstractArgumentNode argument1Node; - @Child private AbstractArgumentNode argument2Node; - @Child private AbstractArgumentNode argument3Node; - @Child private AbstractArgumentNode argument4Node; - @Child private AbstractArgumentNode argument5Node; - - private DispatchPrimitive6Node(final AbstractPrimitiveNode primitiveNode, final AbstractArgumentNode[] argumentNodes) { - super(primitiveNode); - receiverNode = argumentNodes[0]; - argument1Node = argumentNodes[1]; - argument2Node = argumentNodes[2]; - argument3Node = argumentNodes[3]; - argument4Node = argumentNodes[4]; - argument5Node = argumentNodes[5]; - } - - @Override - public Object execute(final VirtualFrame frame) { - return ((Primitive5) primitiveNode).execute(frame, receiverNode.execute(frame), argument1Node.execute(frame), argument2Node.execute(frame), argument3Node.execute(frame), - argument4Node.execute(frame), argument5Node.execute(frame)); - } - } - - private static final class DispatchPrimitive7Node extends DispatchPrimitiveNode { - @Child private AbstractArgumentNode receiverNode; - @Child private AbstractArgumentNode argument1Node; - @Child private AbstractArgumentNode argument2Node; - @Child private AbstractArgumentNode argument3Node; - @Child private AbstractArgumentNode argument4Node; - @Child private AbstractArgumentNode argument5Node; - @Child private AbstractArgumentNode argument6Node; - - private DispatchPrimitive7Node(final AbstractPrimitiveNode primitiveNode, final AbstractArgumentNode[] argumentNodes) { - super(primitiveNode); - receiverNode = argumentNodes[0]; - argument1Node = argumentNodes[1]; - argument2Node = argumentNodes[2]; - argument3Node = argumentNodes[3]; - argument4Node = argumentNodes[4]; - argument5Node = argumentNodes[5]; - argument6Node = argumentNodes[6]; - } - - @Override - public Object execute(final VirtualFrame frame) { - return ((Primitive6) primitiveNode).execute(frame, receiverNode.execute(frame), argument1Node.execute(frame), argument2Node.execute(frame), argument3Node.execute(frame), - argument4Node.execute(frame), argument5Node.execute(frame), argument6Node.execute(frame)); - } - } - - private static final class DispatchPrimitive8Node extends DispatchPrimitiveNode { - @Child private AbstractArgumentNode receiverNode; - @Child private AbstractArgumentNode argument1Node; - @Child private AbstractArgumentNode argument2Node; - @Child private AbstractArgumentNode argument3Node; - @Child private AbstractArgumentNode argument4Node; - @Child private AbstractArgumentNode argument5Node; - @Child private AbstractArgumentNode argument6Node; - @Child private AbstractArgumentNode argument7Node; - - private DispatchPrimitive8Node(final AbstractPrimitiveNode primitiveNode, final AbstractArgumentNode[] argumentNodes) { - super(primitiveNode); - receiverNode = argumentNodes[0]; - argument1Node = argumentNodes[1]; - argument2Node = argumentNodes[2]; - argument3Node = argumentNodes[3]; - argument4Node = argumentNodes[4]; - argument5Node = argumentNodes[5]; - argument6Node = argumentNodes[6]; - argument7Node = argumentNodes[7]; - } - - @Override - public Object execute(final VirtualFrame frame) { - return ((Primitive7) primitiveNode).execute(frame, receiverNode.execute(frame), argument1Node.execute(frame), argument2Node.execute(frame), argument3Node.execute(frame), - argument4Node.execute(frame), argument5Node.execute(frame), argument6Node.execute(frame), argument7Node.execute(frame)); - } - } - - private static final class DispatchPrimitive9Node extends DispatchPrimitiveNode { - @Child private AbstractArgumentNode receiverNode; - @Child private AbstractArgumentNode argument1Node; - @Child private AbstractArgumentNode argument2Node; - @Child private AbstractArgumentNode argument3Node; - @Child private AbstractArgumentNode argument4Node; - @Child private AbstractArgumentNode argument5Node; - @Child private AbstractArgumentNode argument6Node; - @Child private AbstractArgumentNode argument7Node; - @Child private AbstractArgumentNode argument8Node; - - private DispatchPrimitive9Node(final AbstractPrimitiveNode primitiveNode, final AbstractArgumentNode[] argumentNodes) { - super(primitiveNode); - receiverNode = argumentNodes[0]; - argument1Node = argumentNodes[1]; - argument2Node = argumentNodes[2]; - argument3Node = argumentNodes[3]; - argument4Node = argumentNodes[4]; - argument5Node = argumentNodes[5]; - argument6Node = argumentNodes[6]; - argument7Node = argumentNodes[7]; - argument8Node = argumentNodes[8]; - } - - @Override - public Object execute(final VirtualFrame frame) { - return ((Primitive8) primitiveNode).execute(frame, receiverNode.execute(frame), argument1Node.execute(frame), argument2Node.execute(frame), argument3Node.execute(frame), - argument4Node.execute(frame), argument5Node.execute(frame), argument6Node.execute(frame), argument7Node.execute(frame), argument8Node.execute(frame)); - } - } - - private static final class DispatchPrimitive10Node extends DispatchPrimitiveNode { - @Child private AbstractArgumentNode receiverNode; - @Child private AbstractArgumentNode argument1Node; - @Child private AbstractArgumentNode argument2Node; - @Child private AbstractArgumentNode argument3Node; - @Child private AbstractArgumentNode argument4Node; - @Child private AbstractArgumentNode argument5Node; - @Child private AbstractArgumentNode argument6Node; - @Child private AbstractArgumentNode argument7Node; - @Child private AbstractArgumentNode argument8Node; - @Child private AbstractArgumentNode argument9Node; - - private DispatchPrimitive10Node(final AbstractPrimitiveNode primitiveNode, final AbstractArgumentNode[] argumentNodes) { - super(primitiveNode); - receiverNode = argumentNodes[0]; - argument1Node = argumentNodes[1]; - argument2Node = argumentNodes[2]; - argument3Node = argumentNodes[3]; - argument4Node = argumentNodes[4]; - argument5Node = argumentNodes[5]; - argument6Node = argumentNodes[6]; - argument7Node = argumentNodes[7]; - argument8Node = argumentNodes[8]; - argument9Node = argumentNodes[9]; - } - - @Override - public Object execute(final VirtualFrame frame) { - return ((Primitive9) primitiveNode).execute(frame, receiverNode.execute(frame), argument1Node.execute(frame), argument2Node.execute(frame), argument3Node.execute(frame), - argument4Node.execute(frame), argument5Node.execute(frame), argument6Node.execute(frame), argument7Node.execute(frame), argument8Node.execute(frame), - argument9Node.execute(frame)); - } - } - - private static final class DispatchPrimitive11Node extends DispatchPrimitiveNode { - @Child private AbstractArgumentNode receiverNode; - @Child private AbstractArgumentNode argument1Node; - @Child private AbstractArgumentNode argument2Node; - @Child private AbstractArgumentNode argument3Node; - @Child private AbstractArgumentNode argument4Node; - @Child private AbstractArgumentNode argument5Node; - @Child private AbstractArgumentNode argument6Node; - @Child private AbstractArgumentNode argument7Node; - @Child private AbstractArgumentNode argument8Node; - @Child private AbstractArgumentNode argument9Node; - @Child private AbstractArgumentNode argument10Node; - - private DispatchPrimitive11Node(final AbstractPrimitiveNode primitiveNode, final AbstractArgumentNode[] argumentNodes) { - super(primitiveNode); - receiverNode = argumentNodes[0]; - argument1Node = argumentNodes[1]; - argument2Node = argumentNodes[2]; - argument3Node = argumentNodes[3]; - argument4Node = argumentNodes[4]; - argument5Node = argumentNodes[5]; - argument6Node = argumentNodes[6]; - argument7Node = argumentNodes[7]; - argument8Node = argumentNodes[8]; - argument9Node = argumentNodes[9]; - argument10Node = argumentNodes[10]; - } - - @Override - public Object execute(final VirtualFrame frame) { - return ((Primitive10) primitiveNode).execute(frame, receiverNode.execute(frame), argument1Node.execute(frame), argument2Node.execute(frame), argument3Node.execute(frame), - argument4Node.execute(frame), argument5Node.execute(frame), argument6Node.execute(frame), argument7Node.execute(frame), argument8Node.execute(frame), - argument9Node.execute(frame), argument10Node.execute(frame)); - } - } - - private static final class DispatchPrimitive12Node extends DispatchPrimitiveNode { - @Child private AbstractArgumentNode receiverNode; - @Child private AbstractArgumentNode argument1Node; - @Child private AbstractArgumentNode argument2Node; - @Child private AbstractArgumentNode argument3Node; - @Child private AbstractArgumentNode argument4Node; - @Child private AbstractArgumentNode argument5Node; - @Child private AbstractArgumentNode argument6Node; - @Child private AbstractArgumentNode argument7Node; - @Child private AbstractArgumentNode argument8Node; - @Child private AbstractArgumentNode argument9Node; - @Child private AbstractArgumentNode argument10Node; - @Child private AbstractArgumentNode argument11Node; - - private DispatchPrimitive12Node(final AbstractPrimitiveNode primitiveNode, final AbstractArgumentNode[] argumentNodes) { - super(primitiveNode); - receiverNode = argumentNodes[0]; - argument1Node = argumentNodes[1]; - argument2Node = argumentNodes[2]; - argument3Node = argumentNodes[3]; - argument4Node = argumentNodes[4]; - argument5Node = argumentNodes[5]; - argument6Node = argumentNodes[6]; - argument7Node = argumentNodes[7]; - argument8Node = argumentNodes[8]; - argument9Node = argumentNodes[9]; - argument10Node = argumentNodes[10]; - argument11Node = argumentNodes[11]; - } - - @Override - public Object execute(final VirtualFrame frame) { - return ((Primitive11) primitiveNode).execute(frame, receiverNode.execute(frame), argument1Node.execute(frame), argument2Node.execute(frame), argument3Node.execute(frame), - argument4Node.execute(frame), argument5Node.execute(frame), argument6Node.execute(frame), argument7Node.execute(frame), argument8Node.execute(frame), - argument9Node.execute(frame), argument10Node.execute(frame), argument11Node.execute(frame)); - } - } -} diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java index 01217c5ba..c5fbf0873 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java @@ -124,12 +124,6 @@ public final class PrimitiveNodeFactory { private PrimitiveNodeFactory() { } - public enum ArgumentsLocation { - IN_FRAME_ARGUMENTS, - ON_STACK, - ON_STACK_REVERSED, - } - public static String[] getPluginNames() { final Set target = new HashSet<>(); for (final String key : PLUGIN_MAP.getKeys()) { @@ -161,16 +155,6 @@ public static AbstractPrimitiveNode getOrCreateIndexedOrNamed(final CompiledCode } } - public static DispatchPrimitiveNode getOrCreateIndexedOrNamed(final CompiledCodeObject method, final ArgumentsLocation location) { - final AbstractPrimitiveNode primitiveNode = getOrCreateIndexedOrNamed(method); - if (primitiveNode != null) { - final int numReceiverAndArguments = 1 + method.getNumArgs(); - return DispatchPrimitiveNode.create(primitiveNode, location, numReceiverAndArguments); - } else { - return null; - } - } - public static AbstractPrimitiveNode getOrCreateIndexed(final int primitiveIndex, final int numReceiverAndArguments) { assert primitiveIndex <= MAX_PRIMITIVE_INDEX; if (isLoadInstVar(primitiveIndex)) { diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/impl/ArithmeticPrimitives.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/impl/ArithmeticPrimitives.java index 57c0d2a59..a8936ba43 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/impl/ArithmeticPrimitives.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/impl/ArithmeticPrimitives.java @@ -40,9 +40,9 @@ import de.hpi.swa.trufflesqueak.nodes.accessing.FloatObjectNodes.AsFloatObjectIfNessaryNode; import de.hpi.swa.trufflesqueak.nodes.primitives.AbstractPrimitiveFactoryHolder; import de.hpi.swa.trufflesqueak.nodes.primitives.AbstractPrimitiveNode; +import de.hpi.swa.trufflesqueak.nodes.primitives.Primitive.Primitive0WithFallback; import de.hpi.swa.trufflesqueak.nodes.primitives.Primitive.Primitive1; import de.hpi.swa.trufflesqueak.nodes.primitives.Primitive.Primitive1WithFallback; -import de.hpi.swa.trufflesqueak.nodes.primitives.Primitive.Primitive0WithFallback; import de.hpi.swa.trufflesqueak.nodes.primitives.Primitive.Primitive2WithFallback; import de.hpi.swa.trufflesqueak.nodes.primitives.SqueakPrimitive; import de.hpi.swa.trufflesqueak.util.MiscUtils; @@ -506,10 +506,6 @@ protected static final long doLongNegative(final long receiver, @SuppressWarning return receiver >= 0 ? 0L : -1L; } - protected static final boolean isLShiftLongOverflow(final long receiver, final long arg) { - return Long.numberOfLeadingZeros(receiver) - 1 < arg; - } - protected static final boolean inLongSizeRange(final long arg) { return -Long.SIZE < arg; } @@ -1616,7 +1612,7 @@ public abstract static class AbstractArithmeticPrimitiveNode extends AbstractPri private static final long MAX_SAFE_INTEGER_LONG = (1L << FloatObject.PRECISION) - 1; private static final long MIN_SAFE_INTEGER_LONG = -MAX_SAFE_INTEGER_LONG; - protected static final double ensureFinite(final double value) throws RespecializeException { + public static final double ensureFinite(final double value) throws RespecializeException { if (Double.isFinite(value)) { return value; } else { diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/impl/BlockClosurePrimitives.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/impl/BlockClosurePrimitives.java index 9a07f8070..f7fc4a901 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/impl/BlockClosurePrimitives.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/impl/BlockClosurePrimitives.java @@ -43,13 +43,11 @@ public abstract static class AbstractClosurePrimitiveNode extends AbstractPrimit @Child protected GetContextOrMarkerNode getContextOrMarkerNode = GetContextOrMarkerNode.create(); protected final Object[] createFrameArguments(final VirtualFrame frame, final BlockClosureObject closure) { - return FrameAccess.newClosureArgumentsTemplate(closure, getContextOrMarkerNode.execute(frame), 0); + return FrameAccess.createFrameArguments(frame, closure, getContextOrMarkerNode); } protected final Object[] createFrameArguments(final VirtualFrame frame, final BlockClosureObject closure, final Object arg1) { - final Object[] frameArguments = FrameAccess.newClosureArgumentsTemplate(closure, getContextOrMarkerNode.execute(frame), 1); - frameArguments[FrameAccess.getArgumentStartIndex() + 0] = arg1; - return frameArguments; + return FrameAccess.createFrameArguments(frame, closure, getContextOrMarkerNode, arg1); } protected final Object[] createFrameArguments(final VirtualFrame frame, final BlockClosureObject closure, final Object arg1, final Object arg2) { diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/FrameAccess.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/FrameAccess.java index cefa2ce9a..67e7e7fb9 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/FrameAccess.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/FrameAccess.java @@ -446,6 +446,16 @@ public static Object[] newClosureArgumentsTemplate(final BlockClosureObject clos return arguments; } + public static Object[] createFrameArguments(final VirtualFrame frame, final BlockClosureObject closure, final GetContextOrMarkerNode getContextOrMarkerNode) { + return FrameAccess.newClosureArgumentsTemplate(closure, getContextOrMarkerNode.execute(frame), 0); + } + + public static Object[] createFrameArguments(final VirtualFrame frame, final BlockClosureObject closure, final GetContextOrMarkerNode getContextOrMarkerNode, final Object arg1) { + final Object[] frameArguments = FrameAccess.newClosureArgumentsTemplate(closure, getContextOrMarkerNode.execute(frame), 1); + frameArguments[FrameAccess.getArgumentStartIndex()] = arg1; + return frameArguments; + } + public static int expectedArgumentSize(final int numArgsAndCopied) { return ArgumentIndicies.ARGUMENTS_START.ordinal() + numArgsAndCopied; }