From 2089e48d9c414f6e6fb529e8039e3e61255e58b0 Mon Sep 17 00:00:00 2001 From: Stefan Marr Date: Sun, 25 Aug 2024 01:27:26 +0100 Subject: [PATCH] Improve the specialization logic for field accesses MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Things to consider: - what to do when the expected layout is invalid? - what to do when the accesses object is outdated? don’t want a cache entry for that, since it gets removed immedietly - how to handle the transition from expected primitive write to something else? Signed-off-by: Stefan Marr --- .../objectstorage/FieldAccessorNode.java | 86 +++++++++---------- 1 file changed, 40 insertions(+), 46 deletions(-) diff --git a/src/trufflesom/src/trufflesom/interpreter/objectstorage/FieldAccessorNode.java b/src/trufflesom/src/trufflesom/interpreter/objectstorage/FieldAccessorNode.java index 50645eed4..e00fecb5a 100644 --- a/src/trufflesom/src/trufflesom/interpreter/objectstorage/FieldAccessorNode.java +++ b/src/trufflesom/src/trufflesom/interpreter/objectstorage/FieldAccessorNode.java @@ -65,11 +65,6 @@ public double readDouble(final SObject obj) throws UnexpectedResultException { return TypesGen.expectDouble(read(obj)); } - protected final Object specializeAndRead(final SObject obj, final String reason, - final AbstractReadFieldNode next) { - return specialize(obj, reason, next).read(obj); - } - @InliningCutoff protected final AbstractReadFieldNode specialize(final SObject obj, final String reason, final AbstractReadFieldNode next) { @@ -94,8 +89,8 @@ private static final class UninitializedReadFieldNode extends AbstractReadFieldN @InliningCutoff public Object read(final SObject obj) { CompilerDirectives.transferToInterpreterAndInvalidate(); - return specializeAndRead(obj, "uninitalized node", - new UninitializedReadFieldNode(fieldIndex)); + return specialize(obj, "uninitialized node", + new UninitializedReadFieldNode(fieldIndex)).read(obj); } } @@ -115,14 +110,6 @@ protected final boolean hasExpectedLayout(final SObject obj) layout.checkIsLatest(); return layout == obj.getObjectLayout(); } - - protected final AbstractReadFieldNode respecializedNodeOrNext(final SObject obj) { - if (layout.layoutForSameClass(obj.getObjectLayout())) { - return specialize(obj, "update outdated read node", nextInCache); - } else { - return nextInCache; - } - } } public static final class ReadUnwrittenFieldNode extends ReadSpecializedFieldNode { @@ -137,7 +124,7 @@ public Object read(final SObject obj) { if (hasExpectedLayout(obj)) { return Nil.nilObject; } else { - return respecializedNodeOrNext(obj).read(obj); + return nextInCache.read(obj); } } catch (InvalidAssumptionException e) { CompilerDirectives.transferToInterpreterAndInvalidate(); @@ -168,7 +155,7 @@ public long readLong(final SObject obj) throws UnexpectedResultException { if (hasExpectedLayout(obj)) { return storage.readLong(obj); } else { - return respecializedNodeOrNext(obj).readLong(obj); + return nextInCache.readLong(obj); } } catch (InvalidAssumptionException e) { CompilerDirectives.transferToInterpreterAndInvalidate(); @@ -200,7 +187,7 @@ public Object read(final SObject obj) { return storage.readLongSet(obj); } else { - return respecializedNodeOrNext(obj).read(obj); + return nextInCache.read(obj); } } catch (InvalidAssumptionException e) { CompilerDirectives.transferToInterpreterAndInvalidate(); @@ -226,7 +213,7 @@ public double readDouble(final SObject obj) throws UnexpectedResultException { if (hasExpectedLayout(obj)) { return storage.readDouble(obj); } else { - return respecializedNodeOrNext(obj).readDouble(obj); + return nextInCache.readDouble(obj); } } catch (InvalidAssumptionException e) { CompilerDirectives.transferToInterpreterAndInvalidate(); @@ -258,7 +245,7 @@ public Object read(final SObject obj) { return storage.readDoubleSet(obj); } else { - return respecializedNodeOrNext(obj).read(obj); + return nextInCache.read(obj); } } catch (InvalidAssumptionException e) { CompilerDirectives.transferToInterpreterAndInvalidate(); @@ -282,7 +269,7 @@ public Object read(final SObject obj) { if (hasExpectedLayout(obj)) { return storage.read(obj); } else { - return respecializedNodeOrNext(obj).read(obj); + return nextInCache.read(obj); } } catch (InvalidAssumptionException e) { CompilerDirectives.transferToInterpreterAndInvalidate(); @@ -314,16 +301,22 @@ public double write(final SObject obj, final double value) { } @InliningCutoff - protected final void writeAndRespecialize(final SObject obj, final Object value, - final String reason, final AbstractWriteFieldNode next) { - CompilerDirectives.transferToInterpreterAndInvalidate(); + protected final void writeToOutdated(final SObject obj, final Object value) { + CompilerDirectives.transferToInterpreter(); + assert !obj.getObjectLayout().isValid(); + obj.setField(fieldIndex, value); + } + @InliningCutoff + protected final void writeUnexpectedTypeAndRespecialize(final SObject obj, + final Object value, final AbstractWriteFieldNode next) { + CompilerDirectives.transferToInterpreterAndInvalidate(); obj.setField(fieldIndex, value); final ObjectLayout layout = obj.getObjectLayout(); final StorageLocation location = layout.getStorageLocation(fieldIndex); AbstractWriteFieldNode newNode = location.getWriteNode(fieldIndex, layout, next); - replace(newNode, reason); + replace(newNode, "update outdated read node"); } } @@ -336,8 +329,15 @@ private static final class UninitializedWriteFieldNode extends AbstractWriteFiel @InliningCutoff public Object write(final SObject obj, final Object value) { CompilerDirectives.transferToInterpreterAndInvalidate(); - writeAndRespecialize(obj, value, "initialize write field node", + + obj.setField(fieldIndex, value); + + final ObjectLayout layout = obj.getObjectLayout(); + final StorageLocation location = layout.getStorageLocation(fieldIndex); + AbstractWriteFieldNode newNode = location.getWriteNode(fieldIndex, layout, new UninitializedWriteFieldNode(fieldIndex)); + replace(newNode, "initialize write field node"); + return value; } } @@ -362,10 +362,10 @@ protected final boolean hasExpectedLayout(final SObject obj) } public static final class IncrementLongFieldNode extends FieldAccessorNode { - protected final ObjectLayout layout; + private final ObjectLayout layout; private final LongStorageLocation storage; - @Child protected IncrementLongFieldNode nextInCache; + @Child private IncrementLongFieldNode nextInCache; public IncrementLongFieldNode(final int fieldIndex, final ObjectLayout layout) { super(fieldIndex); @@ -373,7 +373,7 @@ public IncrementLongFieldNode(final int fieldIndex, final ObjectLayout layout) { this.storage = (LongStorageLocation) layout.getStorageLocation(fieldIndex); } - protected boolean hasExpectedLayout(final SObject obj) + private boolean hasExpectedLayout(final SObject obj) throws InvalidAssumptionException { layout.checkIsLatest(); return layout == obj.getObjectLayout(); @@ -424,7 +424,7 @@ public long write(final SObject obj, final long value) { storage.writeLong(obj, value); } else { if (layout.layoutForSameClass(obj.getObjectLayout())) { - writeAndRespecialize(obj, value, "update outdated write node", nextInCache); + writeToOutdated(obj, value); } else { nextInCache.write(obj, value); } @@ -445,12 +445,10 @@ private void dropAndWriteNext(final SObject obj, final long value) { public Object write(final SObject obj, final Object value) { if (value instanceof Long) { write(obj, (long) value); + } else if (layout.layoutForSameClass(obj.getObjectLayout())) { + writeUnexpectedTypeAndRespecialize(obj, value, nextInCache); } else { - if (layout.layoutForSameClass(obj.getObjectLayout())) { - writeAndRespecialize(obj, value, "update outdated read node", nextInCache); - } else { - nextInCache.write(obj, (long) value); - } + nextInCache.write(obj, value); } return value; } @@ -472,7 +470,7 @@ public double write(final SObject obj, final double value) { storage.writeDouble(obj, value); } else { if (layout.layoutForSameClass(obj.getObjectLayout())) { - writeAndRespecialize(obj, value, "update outdated read node", nextInCache); + writeToOutdated(obj, value); } else { nextInCache.write(obj, value); } @@ -493,12 +491,10 @@ private void dropAndWriteNext(final SObject obj, final double value) { public Object write(final SObject obj, final Object value) { if (value instanceof Double) { write(obj, (double) value); + } else if (layout.layoutForSameClass(obj.getObjectLayout())) { + writeUnexpectedTypeAndRespecialize(obj, value, nextInCache); } else { - if (layout.layoutForSameClass(obj.getObjectLayout())) { - writeAndRespecialize(obj, value, "update outdated read node", nextInCache); - } else { - nextInCache.write(obj, (double) value); - } + nextInCache.write(obj, value); } return value; } @@ -518,12 +514,10 @@ public Object write(final SObject obj, final Object value) { try { if (hasExpectedLayout(obj)) { storage.write(obj, value); + } else if (layout.layoutForSameClass(obj.getObjectLayout())) { + writeToOutdated(obj, value); } else { - if (layout.layoutForSameClass(obj.getObjectLayout())) { - writeAndRespecialize(obj, value, "update outdated read node", nextInCache); - } else { - nextInCache.write(obj, value); - } + nextInCache.write(obj, value); } } catch (InvalidAssumptionException e) { CompilerDirectives.transferToInterpreterAndInvalidate();