Skip to content

Commit

Permalink
Fix and improve pushLiteralVariable bytecode
Browse files Browse the repository at this point in the history
for ClassBinding and ReadOnlyVariableBinding. The values of these two objects are readonly, so they can be directly cached in the AST. This, in turn, avoids a field read and makes SqueakProfiles redundant.
  • Loading branch information
fniephaus committed Oct 21, 2021
1 parent e82f144 commit 9ad0347
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 121 deletions.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public static AbstractInstrumentableBytecodeNode create(final CompiledCodeObject
case 3:
return new PushLiteralConstantNode(code, index, numBytecodes, third);
case 4:
return new PushLiteralVariableNode(code, index, numBytecodes, third);
return PushLiteralVariableNode.create(code, index, numBytecodes, third);
case 5:
return new StoreIntoReceiverVariableNode(code, index, numBytecodes, third);
case 6:
Expand Down Expand Up @@ -129,7 +129,7 @@ public static AbstractInstrumentableBytecodeNode createPush(final CompiledCodeOb
case 2:
return new PushLiteralConstantNode(code, index, numBytecodes, variableIndex);
case 3:
return new PushLiteralVariableNode(code, index, numBytecodes, variableIndex);
return PushLiteralVariableNode.create(code, index, numBytecodes, variableIndex);
default:
throw SqueakException.create("unexpected type for ExtendedPush");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.NodeCost;
import com.oracle.truffle.api.nodes.NodeInfo;
import com.oracle.truffle.api.profiles.ValueProfile;

import de.hpi.swa.trufflesqueak.image.SqueakImageContext;
import de.hpi.swa.trufflesqueak.model.AbstractSqueakObjectWithClassAndHash;
import de.hpi.swa.trufflesqueak.model.ArrayObject;
import de.hpi.swa.trufflesqueak.model.BlockClosureObject;
import de.hpi.swa.trufflesqueak.model.BooleanObject;
Expand All @@ -21,13 +23,13 @@
import de.hpi.swa.trufflesqueak.model.NilObject;
import de.hpi.swa.trufflesqueak.model.layout.ObjectLayouts.ASSOCIATION;
import de.hpi.swa.trufflesqueak.nodes.AbstractNode;
import de.hpi.swa.trufflesqueak.nodes.SqueakProfiles.SqueakProfile;
import de.hpi.swa.trufflesqueak.nodes.accessing.SqueakObjectAt0Node;
import de.hpi.swa.trufflesqueak.nodes.context.frame.FrameStackPopNNode;
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.FrameStackReadNode;
import de.hpi.swa.trufflesqueak.nodes.context.frame.GetOrCreateContextNode;
import de.hpi.swa.trufflesqueak.util.ArrayUtils;
import de.hpi.swa.trufflesqueak.util.FrameAccess;

public final class PushBytecodes {
Expand Down Expand Up @@ -377,27 +379,64 @@ public String toString() {
}

@NodeInfo(cost = NodeCost.NONE)
public static final class PushLiteralVariableNode extends AbstractPushNode {
@Child private SqueakObjectAt0Node at0Node = SqueakObjectAt0Node.create();
private final SqueakProfile valueProfile;
private final Object literal;
public abstract static class PushLiteralVariableNode extends AbstractPushNode {
private static final String[] READONLY_CLASSES = new String[]{"ClassBinding", "ReadOnlyVariableBinding"};
protected final Object literal;

public PushLiteralVariableNode(final CompiledCodeObject code, final int index, final int numBytecodes, final int literalIndex) {
private PushLiteralVariableNode(final CompiledCodeObject code, final int index, final int numBytecodes, final Object literal) {
super(code, index, numBytecodes);
literal = code.getLiteral(literalIndex);
valueProfile = SqueakProfile.createLiteralProfile(literal);
this.literal = literal;
}

@Override
public void executeVoid(final VirtualFrame frame) {
pushNode.execute(frame, valueProfile.profile(at0Node.execute(literal, ASSOCIATION.VALUE)));
public static final AbstractPushNode create(final CompiledCodeObject code, final int index, final int numBytecodes, final int literalIndex) {
final Object literal = code.getLiteral(literalIndex);
if (literal instanceof AbstractSqueakObjectWithClassAndHash) {
final String squeakClassName = ((AbstractSqueakObjectWithClassAndHash) literal).getSqueakClassName();
if (ArrayUtils.containsEqual(READONLY_CLASSES, squeakClassName)) {
return new PushLiteralVariableReadonlyNode(code, index, numBytecodes, literal);
}
}
return new PushLiteralVariableWritableNode(code, index, numBytecodes, literal);
}

@Override
public String toString() {
public final String toString() {
CompilerAsserts.neverPartOfCompilation();
return "pushLitVar: " + literal;
}

private static final class PushLiteralVariableWritableNode extends PushLiteralVariableNode {
@Child private SqueakObjectAt0Node at0Node = SqueakObjectAt0Node.create();
private final ValueProfile valueProfile = ValueProfile.createIdentityProfile();

protected PushLiteralVariableWritableNode(final CompiledCodeObject code, final int index, final int numBytecodes, final Object literal) {
super(code, index, numBytecodes, literal);
}

@Override
public void executeVoid(final VirtualFrame frame) {
pushNode.execute(frame, valueProfile.profile(at0Node.execute(literal, ASSOCIATION.VALUE)));
}
}

private static final class PushLiteralVariableReadonlyNode extends PushLiteralVariableNode {
private final Object pushValue;

protected PushLiteralVariableReadonlyNode(final CompiledCodeObject code, final int index, final int numBytecodes, final Object literal) {
super(code, index, numBytecodes, literal);
pushValue = getPushValue(literal);
}

@Override
public void executeVoid(final VirtualFrame frame) {
assert pushValue == getPushValue(literal) : "value of binding changed unexpectedly";
pushNode.execute(frame, pushValue);
}

private static Object getPushValue(final Object literal) {
return SqueakObjectAt0Node.getUncached().execute(literal, ASSOCIATION.VALUE);
}
}
}

public static final class PushNewArrayNode extends AbstractPushNode {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ private static AbstractBytecodeNode decodeBytecode(final VirtualFrame frame, fin
return PushBytecodes.PushReceiverVariableNode.create(code, index, 1, b & 0xF);
case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
case 0x18: case 0x19: case 0x1A: case 0x1B: case 0x1C: case 0x1D: case 0x1E: case 0x1F:
return new PushBytecodes.PushLiteralVariableNode(code, index, 1, b & 0xF);
return PushBytecodes.PushLiteralVariableNode.create(code, index, 1, b & 0xF);
case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27:
case 0x28: case 0x29: case 0x2A: case 0x2B: case 0x2C: case 0x2D: case 0x2E: case 0x2F:
case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
Expand Down Expand Up @@ -189,7 +189,7 @@ private static AbstractBytecodeNode decodeBytecode(final VirtualFrame frame, fin
case 0xE2:
return PushBytecodes.PushReceiverVariableNode.create(code, index, 2 + extBytes, Byte.toUnsignedInt(bytecode[indexWithExt + 1]) + (extA << 8));
case 0xE3:
return new PushBytecodes.PushLiteralVariableNode(code, index, 2 + extBytes, Byte.toUnsignedInt(bytecode[indexWithExt + 1]) + (extA << 8));
return PushBytecodes.PushLiteralVariableNode.create(code, index, 2 + extBytes, Byte.toUnsignedInt(bytecode[indexWithExt + 1]) + (extA << 8));
case 0xE4:
return new PushBytecodes.PushLiteralConstantNode(code, index, 2 + extBytes, Byte.toUnsignedInt(bytecode[indexWithExt + 1]) + (extA << 8));
case 0xE5:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ public AbstractBytecodeNode decodeBytecode(final VirtualFrame frame, final Compi
case 0x48: case 0x49: case 0x4A: case 0x4B: case 0x4C: case 0x4D: case 0x4E: case 0x4F:
case 0x50: case 0x51: case 0x52: case 0x53: case 0x54: case 0x55: case 0x56: case 0x57:
case 0x58: case 0x59: case 0x5A: case 0x5B: case 0x5C: case 0x5D: case 0x5E: case 0x5F:
return new PushBytecodes.PushLiteralVariableNode(code, index, 1, b & 31);
return PushBytecodes.PushLiteralVariableNode.create(code, index, 1, b & 31);
case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: case 0x65: case 0x66: case 0x67:
return new StoreBytecodes.PopIntoReceiverVariableNode(code, index, 1, b & 7);
case 0x68: case 0x69: case 0x6A: case 0x6B: case 0x6C: case 0x6D: case 0x6E: case 0x6F:
Expand Down

1 comment on commit 9ad0347

@TruffleSqueak-Bot
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Performance Report (9ad0347)

Benchmarks ran on graalvm-ce-java11-21.3.0.

Steady (after 50 iterations)

Benchmark Name Min Geomean Median Mean Max Total (ms) Total (min)
Bounce 181 212 183.18 182 183.11 36635 0.61
DeltaBlue 272 405 369.36 369 369.06 73871 1.23
Havlak 1535 1656 1597.33 1605.5 1597.09 319466 5.32
Json 498 537 504.81 503 504.77 100961 1.68
List 893 962 902.33 901 902.3 180466 3.01
Mandelbrot 146 167 147.75 147 147.73 29549 0.49
NBody 272 317 278.35 274 278.23 55670 0.93
Permute 234 266 237.61 235 237.52 47522 0.79
Queens 256 296 260.81 258 260.67 52161 0.87
Richards 1092 1136 1098.08 1094 1098.05 219615 3.66
Sieve 214 318 219.16 215 218.77 43831 0.73
Storage 297 326 301.64 298 301.56 60327 1.01
Towers 368 400 371.61 370 371.56 74321 1.24
6258 6998 6471.97 6451.5 6470.41 1294395 21.57

9ad0347-2-steady.svg

Warmup (first 50 iterations)

9ad0347-3-warmup.svg

Please sign in to comment.