Skip to content

Commit

Permalink
Handle megamorphic case on FieldAccessorNode
Browse files Browse the repository at this point in the history
We haven’t handle those yet…

Signed-off-by: Stefan Marr <[email protected]>
  • Loading branch information
smarr committed Aug 26, 2024
1 parent 2089e48 commit 2e492a0
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 10 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package trufflesom.interpreter.objectstorage;

import com.oracle.truffle.api.CompilerAsserts;
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.HostCompilerDirectives.InliningCutoff;
import com.oracle.truffle.api.nodes.InvalidAssumptionException;
Expand All @@ -17,16 +18,18 @@


public abstract class FieldAccessorNode extends Node {
public final static int INLINE_CACHE_SIZE = 6;

protected final int fieldIndex;

@InliningCutoff
public static AbstractReadFieldNode createRead(final int fieldIndex) {
return new UninitializedReadFieldNode(fieldIndex);
return new UninitializedReadFieldNode(fieldIndex, 0);
}

@InliningCutoff
public static AbstractWriteFieldNode createWrite(final int fieldIndex) {
return new UninitializedWriteFieldNode(fieldIndex);
return new UninitializedWriteFieldNode(fieldIndex, 0);
}

@InliningCutoff
Expand Down Expand Up @@ -66,9 +69,16 @@ public double readDouble(final SObject obj) throws UnexpectedResultException {
}

@InliningCutoff
protected final AbstractReadFieldNode specialize(final SObject obj,
protected final AbstractReadFieldNode specialize(final SObject obj, int chainLength,
final String reason, final AbstractReadFieldNode next) {
CompilerDirectives.transferToInterpreterAndInvalidate();

if (chainLength >= INLINE_CACHE_SIZE) {
GenericReadFieldNode genericReplacement = new GenericReadFieldNode(fieldIndex);
replace(genericReplacement, "megamorphic read node");
return genericReplacement;
}

obj.updateLayoutToMatchClass();

final ObjectLayout layout = obj.getObjectLayout();
Expand All @@ -79,18 +89,39 @@ protected final AbstractReadFieldNode specialize(final SObject obj,
}
}

private static final class GenericReadFieldNode extends AbstractReadFieldNode {
GenericReadFieldNode(final int fieldIndex) {
super(fieldIndex);
}

@Override
public Object read(final SObject obj) {
if (obj.hasOutdatedLayout()) {
// this case is rare, we do not invalidate here, but also really don't want this to be
// in the compilation
CompilerDirectives.transferToInterpreter();
obj.updateLayoutToMatchClass();
}
StorageLocation location = obj.getLocation(fieldIndex);
return location.read(obj);
}
}

private static final class UninitializedReadFieldNode extends AbstractReadFieldNode {

UninitializedReadFieldNode(final int fieldIndex) {
private final int chainLength;

UninitializedReadFieldNode(final int fieldIndex, int chainLength) {
super(fieldIndex);
this.chainLength = chainLength;
}

@Override
@InliningCutoff
public Object read(final SObject obj) {
CompilerDirectives.transferToInterpreterAndInvalidate();
return specialize(obj, "uninitialized node",
new UninitializedReadFieldNode(fieldIndex)).read(obj);
return specialize(obj, chainLength, "uninitialized node",
new UninitializedReadFieldNode(fieldIndex, chainLength + 1)).read(obj);
}
}

Expand Down Expand Up @@ -269,6 +300,7 @@ public Object read(final SObject obj) {
if (hasExpectedLayout(obj)) {
return storage.read(obj);
} else {
CompilerAsserts.partialEvaluationConstant(nextInCache);
return nextInCache.read(obj);
}
} catch (InvalidAssumptionException e) {
Expand Down Expand Up @@ -321,27 +353,48 @@ protected final void writeUnexpectedTypeAndRespecialize(final SObject obj,
}

private static final class UninitializedWriteFieldNode extends AbstractWriteFieldNode {
UninitializedWriteFieldNode(final int fieldIndex) {
private final int chainLength;

UninitializedWriteFieldNode(final int fieldIndex, int chainLength) {
super(fieldIndex);
this.chainLength = chainLength;
}

@Override
@InliningCutoff
public Object write(final SObject obj, final Object value) {
CompilerDirectives.transferToInterpreterAndInvalidate();

obj.setField(fieldIndex, value);

if (chainLength >= INLINE_CACHE_SIZE) {
GenericWriteFieldNode generic = new GenericWriteFieldNode(fieldIndex);
replace(generic, "megamorphic write node");
return value;
}

final ObjectLayout layout = obj.getObjectLayout();
final StorageLocation location = layout.getStorageLocation(fieldIndex);
AbstractWriteFieldNode newNode = location.getWriteNode(fieldIndex, layout,
new UninitializedWriteFieldNode(fieldIndex));
new UninitializedWriteFieldNode(fieldIndex, chainLength + 1));
replace(newNode, "initialize write field node");

return value;
}
}

private final static class GenericWriteFieldNode extends AbstractWriteFieldNode {
GenericWriteFieldNode(final int fieldIndex) {
super(fieldIndex);
}

@Override
public Object write(final SObject obj, final Object value) {
StorageLocation location = obj.getLocation(fieldIndex);
location.write(obj, value);
return value;
}
}

private abstract static class WriteSpecializedFieldNode extends AbstractWriteFieldNode {

protected final ObjectLayout layout;
Expand Down
6 changes: 5 additions & 1 deletion src/trufflesom/src/trufflesom/vmobjects/SObject.java
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,10 @@ private void setAllFields(final Object[] fieldValues) {
}
}

public final boolean hasOutdatedLayout() {
return !objectLayout.isValid();
}

public final boolean updateLayoutToMatchClass() {
ObjectLayout layoutAtClass = clazz.getLayoutForInstances();
assert layoutAtClass.getNumberOfFields() == objectLayout.getNumberOfFields();
Expand Down Expand Up @@ -242,7 +246,7 @@ public final void markPrimAsSet(final int mask) {
primitiveUsedMap |= mask;
}

private StorageLocation getLocation(final long index) {
public StorageLocation getLocation(final long index) {
StorageLocation location = objectLayout.getStorageLocation(index);
assert location != null;
return location;
Expand Down

0 comments on commit 2e492a0

Please sign in to comment.