Skip to content

Commit

Permalink
Improve AbstractPointersObjectNodes
Browse files Browse the repository at this point in the history
and drop getValidLayoutOrNull()
  • Loading branch information
fniephaus committed Feb 25, 2025
1 parent b63865b commit d67cae3
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 47 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -137,11 +137,6 @@ public final ObjectLayout getLayout() {
return layout;
}

public final ObjectLayout getValidLayoutOrNull() {
CompilerAsserts.neverPartOfCompilation();
return layout.isValid() ? layout : null;
}

public final void changeClassTo(final ClassObject newClass) {
setSqueakClass(newClass);
migrateToLayout(newClass.getLayout());
Expand All @@ -155,7 +150,7 @@ public final void updateLayout() {
}

@TruffleBoundary
public final ObjectLayout updateLayout(final long index, final Object value) {
public final void updateLayout(final long index, final Object value) {
assert !layout.getLocation(index).canStore(value);
final ClassObject squeakClass = getSqueakClass();
ObjectLayout latestLayout = squeakClass.getLayout();
Expand All @@ -165,7 +160,6 @@ public final ObjectLayout updateLayout(final long index, final Object value) {
assert !layout.isValid() && layout != latestLayout : "Layout must have changed";
}
migrateToLayout(latestLayout);
return squeakClass.getLayout(); /* Layout may have evolved again during migration. */
}

@TruffleBoundary
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,10 @@ public final int executeInt(final Node node, final AbstractPointersObject obj, f
}

@SuppressWarnings("unused")
@Specialization(guards = {"cachedIndex == index", "cachedLayout != null", "object.getLayout() == cachedLayout"}, //
assumptions = "cachedLayout.getValidAssumption()", limit = "POINTERS_LAYOUT_CACHE_LIMIT")
@Specialization(guards = {"cachedIndex == index", "object.getLayout() == cachedLayout"}, assumptions = "cachedLayout.getValidAssumption()", limit = "POINTERS_LAYOUT_CACHE_LIMIT")
protected static final Object doReadCached(final AbstractPointersObject object, final long index,
@Cached("index") final long cachedIndex,
@Cached("object.getValidLayoutOrNull()") final ObjectLayout cachedLayout,
@Cached("object.getLayout()") final ObjectLayout cachedLayout,
@Cached("create(cachedLayout.getLocation(index), true)") final AbstractSlotLocationAccessorNode accessorNode) {
return accessorNode.executeRead(object);
}
Expand Down Expand Up @@ -107,36 +106,32 @@ public final void executeNil(final Node node, final AbstractPointersObject obj,
}

@SuppressWarnings("unused")
@Specialization(guards = {"cachedIndex == index", "cachedLayout != null", "object.getLayout() == cachedLayout"}, //
assumptions = "cachedLayout.getValidAssumption()", limit = "POINTERS_LAYOUT_CACHE_LIMIT")
@Specialization(guards = {"cachedIndex == index", "object.getLayout() == cachedLayout"}, assumptions = "cachedLayout.getValidAssumption()", limit = "POINTERS_LAYOUT_CACHE_LIMIT")
protected static final void doWriteCached(final AbstractPointersObject object, final long index,
final Object value,
@Cached("index") final long cachedIndex,
@Cached("object.getValidLayoutOrNull()") final ObjectLayout cachedLayout,
@Cached("object.getLayout()") final ObjectLayout cachedLayout,
@Cached("create(cachedLayout.getLocation(index), false)") final AbstractSlotLocationAccessorNode accessorNode) {
if (!accessorNode.canStore(value)) {
if (accessorNode.canStore(value)) {
try {
accessorNode.executeWrite(object, value);
} catch (final IllegalWriteException e) {
throw CompilerDirectives.shouldNotReachHere("write must succeed", e);
}
} else {
/*
* Update layout in interpreter if it is not stable yet. This will also invalidate
* the assumption and therefore this particular instance of the specialization will
* be removed from the cache and replaced by an updated version.
*/
CompilerDirectives.transferToInterpreter();
object.updateLayout(index, value);
object.getLayout().getLocation(index).writeMustSucceed(object, value);
return;
}
try {
accessorNode.executeWrite(object, value);
} catch (final IllegalWriteException e) {
CompilerDirectives.transferToInterpreter();
e.printStackTrace();
transferToInterpreterUpdateLocationAndWrite(object, index, value);
}
}

@TruffleBoundary
@Specialization(guards = "!object.getLayout().isValid()")
protected static final void doWriteInvalid(final AbstractPointersObject object, final long index, final Object value) {
object.updateLayout(); // ensure layout is updated
object.updateLayout();
doWriteGeneric(object, index, value);
}

Expand All @@ -151,11 +146,15 @@ protected static final void doWriteGeneric(final AbstractPointersObject object,
* Although the layout was valid, it is possible that the location cannot store the
* value. Generialize location in the interpreter.
*/
CompilerDirectives.transferToInterpreter();
object.updateLayout(index, value);
object.getLayout().getLocation(index).writeMustSucceed(object, value);
transferToInterpreterUpdateLocationAndWrite(object, index, value);
}
}

private static void transferToInterpreterUpdateLocationAndWrite(final AbstractPointersObject object, final long index, final Object value) {
CompilerDirectives.transferToInterpreter();
object.updateLayout(index, value);
object.getLayout().getLocation(index).writeMustSucceed(object, value);
}
}

@GenerateInline
Expand All @@ -164,10 +163,9 @@ protected static final void doWriteGeneric(final AbstractPointersObject object,
public abstract static class AbstractPointersObjectInstSizeNode extends AbstractNode {
public abstract int execute(Node node, AbstractPointersObject obj);

@Specialization(guards = {"cachedLayout != null", "object.getLayout() == cachedLayout"}, //
assumptions = "cachedLayout.getValidAssumption()", limit = "1")
@Specialization(guards = {"object.getLayout() == cachedLayout"}, assumptions = "cachedLayout.getValidAssumption()", limit = "POINTERS_LAYOUT_CACHE_LIMIT")
protected static final int doSizeCached(@SuppressWarnings("unused") final AbstractPointersObject object,
@Cached("object.getValidLayoutOrNull()") final ObjectLayout cachedLayout) {
@Cached("object.getLayout()") final ObjectLayout cachedLayout) {
return cachedLayout.getInstSize();
}

Expand All @@ -192,11 +190,11 @@ public abstract static class VariablePointersObjectReadNode extends AbstractNode

public abstract Object execute(Node node, VariablePointersObject object, long index);

@Specialization(guards = {"cachedLayout != null", "cachedIndex < cachedLayout.getInstSize()", "cachedIndex == index", "object.getLayout() == cachedLayout"}, //
@Specialization(guards = {"cachedIndex < cachedLayout.getInstSize()", "cachedIndex == index", "object.getLayout() == cachedLayout"}, //
assumptions = "cachedLayout.getValidAssumption()", limit = "POINTERS_LAYOUT_CACHE_LIMIT")
protected static final Object doReadCached(final Node node, final VariablePointersObject object, @SuppressWarnings("unused") final long index,
@Cached("index") final long cachedIndex,
@SuppressWarnings("unused") @Cached("object.getValidLayoutOrNull()") final ObjectLayout cachedLayout,
@SuppressWarnings("unused") @Cached("object.getLayout()") final ObjectLayout cachedLayout,
@Exclusive @Cached final AbstractPointersObjectReadNode readNode) {
return readNode.execute(node, object, cachedIndex);
}
Expand All @@ -216,11 +214,11 @@ protected static final Object doReadGeneric(final Node node, final VariablePoint
return readNode.execute(node, object, index);
}

@Specialization(guards = {"cachedLayout != null", "cachedIndex >= cachedLayout.getInstSize()", "cachedIndex == index", "object.getLayout() == cachedLayout"}, //
@Specialization(guards = {"cachedIndex >= cachedLayout.getInstSize()", "cachedIndex == index", "object.getLayout() == cachedLayout"}, //
assumptions = "cachedLayout.getValidAssumption()", limit = "POINTERS_VARIABLE_PART_CACHE_LIMIT")
protected static final Object doReadFromVariablePartCached(final VariablePointersObject object, @SuppressWarnings("unused") final long index,
@Cached("index") final long cachedIndex,
@Cached("object.getValidLayoutOrNull()") final ObjectLayout cachedLayout) {
@Cached("object.getLayout()") final ObjectLayout cachedLayout) {
return object.getFromVariablePart(cachedIndex - cachedLayout.getInstSize());
}

Expand All @@ -244,11 +242,11 @@ public abstract static class VariablePointersObjectWriteNode extends AbstractNod

public abstract void execute(Node node, VariablePointersObject object, long index, Object value);

@Specialization(guards = {"cachedLayout != null", "cachedIndex < cachedLayout.getInstSize()", "cachedIndex == index", "object.getLayout() == cachedLayout"}, //
@Specialization(guards = {"cachedIndex < cachedLayout.getInstSize()", "cachedIndex == index", "object.getLayout() == cachedLayout"}, //
assumptions = "cachedLayout.getValidAssumption()", limit = "POINTERS_LAYOUT_CACHE_LIMIT")
protected static final void doWriteCached(final Node node, final VariablePointersObject object, @SuppressWarnings("unused") final long index, final Object value,
@Cached("index") final long cachedIndex,
@SuppressWarnings("unused") @Cached("object.getValidLayoutOrNull()") final ObjectLayout cachedLayout,
@SuppressWarnings("unused") @Cached("object.getLayout()") final ObjectLayout cachedLayout,
@Exclusive @Cached final AbstractPointersObjectWriteNode writeNode) {
writeNode.execute(node, object, cachedIndex, value);
}
Expand All @@ -268,11 +266,11 @@ protected static final void doWriteGeneric(final Node node, final VariablePointe
writeNode.execute(node, object, index, value);
}

@Specialization(guards = {"cachedLayout != null", "cachedIndex >= cachedLayout.getInstSize()", "cachedIndex == index", "object.getLayout() == cachedLayout"}, //
@Specialization(guards = {"cachedIndex >= cachedLayout.getInstSize()", "cachedIndex == index", "object.getLayout() == cachedLayout"}, //
assumptions = "cachedLayout.getValidAssumption()", limit = "POINTERS_VARIABLE_PART_CACHE_LIMIT")
protected static final void doWriteIntoVariablePartCached(final VariablePointersObject object, @SuppressWarnings("unused") final long index, final Object value,
@Cached("index") final long cachedIndex,
@Cached("object.getValidLayoutOrNull()") final ObjectLayout cachedLayout) {
@Cached("object.getLayout()") final ObjectLayout cachedLayout) {
object.putIntoVariablePart(cachedIndex - cachedLayout.getInstSize(), value);
}

Expand All @@ -296,11 +294,11 @@ public abstract static class WeakVariablePointersObjectReadNode extends Abstract

public abstract Object execute(Node node, WeakVariablePointersObject object, long index);

@Specialization(guards = {"cachedLayout != null", "cachedIndex < cachedLayout.getInstSize()", "cachedIndex == index", "object.getLayout() == cachedLayout"}, //
@Specialization(guards = {"cachedIndex < cachedLayout.getInstSize()", "cachedIndex == index", "object.getLayout() == cachedLayout"}, //
assumptions = "cachedLayout.getValidAssumption()", limit = "POINTERS_LAYOUT_CACHE_LIMIT")
protected static final Object doReadCached(final Node node, final WeakVariablePointersObject object, @SuppressWarnings("unused") final long index,
@Cached("index") final long cachedIndex,
@SuppressWarnings("unused") @Cached("object.getValidLayoutOrNull()") final ObjectLayout cachedLayout,
@SuppressWarnings("unused") @Cached("object.getLayout()") final ObjectLayout cachedLayout,
@Exclusive @Cached final AbstractPointersObjectReadNode readNode) {
return readNode.execute(node, object, cachedIndex);
}
Expand All @@ -320,11 +318,11 @@ protected static final Object doReadGeneric(final Node node, final WeakVariableP
return readNode.execute(node, object, index);
}

@Specialization(guards = {"cachedLayout != null", "cachedIndex >= cachedLayout.getInstSize()", "cachedIndex == index", "object.getLayout() == cachedLayout"}, //
@Specialization(guards = {"cachedIndex >= cachedLayout.getInstSize()", "cachedIndex == index", "object.getLayout() == cachedLayout"}, //
assumptions = "cachedLayout.getValidAssumption()", limit = "POINTERS_VARIABLE_PART_CACHE_LIMIT")
protected static final Object doReadFromVariablePartCached(final Node node, final WeakVariablePointersObject object, @SuppressWarnings("unused") final long index,
@Cached("index") final long cachedIndex,
@Cached("object.getValidLayoutOrNull()") final ObjectLayout cachedLayout,
@Cached("object.getLayout()") final ObjectLayout cachedLayout,
@Exclusive @Cached final InlinedConditionProfile weakRefProfile) {
return object.getFromVariablePart(cachedIndex - cachedLayout.getInstSize(), weakRefProfile, node);
}
Expand All @@ -351,11 +349,11 @@ public abstract static class WeakVariablePointersObjectWriteNode extends Abstrac

public abstract void execute(Node node, WeakVariablePointersObject object, long index, Object value);

@Specialization(guards = {"cachedLayout != null", "cachedIndex < cachedLayout.getInstSize()", "cachedIndex == index", "object.getLayout() == cachedLayout"}, //
@Specialization(guards = {"cachedIndex < cachedLayout.getInstSize()", "cachedIndex == index", "object.getLayout() == cachedLayout"}, //
assumptions = "cachedLayout.getValidAssumption()", limit = "POINTERS_LAYOUT_CACHE_LIMIT")
protected static final void doWriteCached(final Node node, final WeakVariablePointersObject object, @SuppressWarnings("unused") final long index, final Object value,
@Cached("index") final long cachedIndex,
@SuppressWarnings("unused") @Cached("object.getValidLayoutOrNull()") final ObjectLayout cachedLayout,
@SuppressWarnings("unused") @Cached("object.getLayout()") final ObjectLayout cachedLayout,
@Exclusive @Cached final AbstractPointersObjectWriteNode writeNode) {
writeNode.execute(node, object, cachedIndex, value);
}
Expand All @@ -375,11 +373,11 @@ protected static final void doWriteGeneric(final Node node, final WeakVariablePo
writeNode.execute(node, object, index, value);
}

@Specialization(guards = {"cachedLayout != null", "cachedIndex >= cachedLayout.getInstSize()", "cachedIndex == index", "object.getLayout() == cachedLayout"}, //
@Specialization(guards = {"cachedIndex >= cachedLayout.getInstSize()", "cachedIndex == index", "object.getLayout() == cachedLayout"}, //
assumptions = "cachedLayout.getValidAssumption()", limit = "POINTERS_VARIABLE_PART_CACHE_LIMIT")
protected static final void doWriteIntoVariablePartCached(final Node node, final WeakVariablePointersObject object, @SuppressWarnings("unused") final long index, final Object value,
@Cached("index") final long cachedIndex,
@Cached("object.getValidLayoutOrNull()") final ObjectLayout cachedLayout,
@Cached("object.getLayout()") final ObjectLayout cachedLayout,
@Exclusive @Cached final InlinedConditionProfile primitiveProfile) {
object.putIntoVariablePart(cachedIndex - cachedLayout.getInstSize(), value, primitiveProfile, node);
}
Expand Down

1 comment on commit d67cae3

@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 (d67cae3)

Benchmarks ran on 23.0.2-graal.

Steady (after 100 iterations)

Benchmark Name Min Geomean Median Mean Max Total (ms) Total (min)
Bounce 549 566 552.78 550 552.76 110556 1.84
CD 601 624 607.18 603 607.15 121437 2.02
DeltaBlue 301 482 426.7 426 425.38 85340 1.42
Havlak 1048 1101 1074.79 1074 1074.75 214958 3.58
Json 326 342 330.16 327.5 330.11 66031 1.1
List 358 388 360.92 359 360.88 72184 1.2
Mandelbrot 129 152 130.68 130 130.64 26135 0.44
NBody 252 272 256.64 253 256.58 51328 0.86
Permute 163 178 164.3 164 164.28 32859 0.55
Queens 230 261 233.04 232 232.99 46608 0.78
Richards 909 967 914.73 911 914.7 182946 3.05
Sieve 170 186 171.16 170 171.13 34231 0.57
Storage 143 159 145.99 144 145.93 29198 0.49
Towers 205 229 208.67 206 208.6 41733 0.7
5384 5907 5577.72 5549.5 5575.89 1115544 18.59

d67cae3-2-steady.svg

Warmup (first 100 iterations)

d67cae3-3-warmup.svg

Please sign in to comment.