Skip to content

Commit

Permalink
Revise classTable handling
Browse files Browse the repository at this point in the history
  • Loading branch information
fniephaus committed Aug 20, 2022
1 parent fddca4e commit af8564a
Show file tree
Hide file tree
Showing 9 changed files with 105 additions and 90 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ public final class SqueakImageConstants {
/** Class Table. */
/* 22-bit class mask => ~ 4M classes */
public static final int CLASS_INDEX_FIELD_WIDTH = 22;
public static final int CLASS_INDEX_MASK = (1 << CLASS_INDEX_FIELD_WIDTH) - 1;
/* 1024 entries per page (2^10); 22 bit classIndex implies 2^12 pages. */
public static final int CLASS_TABLE_MAJOR_INDEX_SHIFT = 10;
public static final int CLASS_TABLE_MINOR_INDEX_MASK = (1 << CLASS_TABLE_MAJOR_INDEX_SHIFT) - 1;
Expand All @@ -78,6 +79,10 @@ public static int minorClassIndexOf(final int classIndex) {
return classIndex & CLASS_TABLE_MINOR_INDEX_MASK;
}

public static int classTableIndexFor(final int majorIndex, final int minorIndex) {
return majorIndex << CLASS_TABLE_MAJOR_INDEX_SHIFT | minorIndex & CLASS_TABLE_MINOR_INDEX_MASK;
}

/**
* Object Header Specification (see SpurMemoryManager).
*
Expand All @@ -93,7 +98,7 @@ public static int minorClassIndexOf(final int classIndex) {
*/
public static final class ObjectHeader {
private static final int NUM_SLOTS_SIZE = 1 << 8;
private static final int HASH_AND_CLASS_INDEX_SIZE = 1 << 22;
public static final int HASH_AND_CLASS_INDEX_SIZE = 1 << 22;
private static final int FORMAT_SIZE = 1 << 5;
private static final int PINNED_BIT_SHIFT = 30;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,8 @@ public final class SqueakImageContext {
public NativeObject clipboardTextHeadless = asByteString("");
private boolean currentMarkingFlag;
private ArrayObject hiddenRoots;
private int globalClassCounter = -1;
public int classTableIndex = SqueakImageConstants.CLASS_TABLE_PAGE_SIZE; // first page is
// special
@CompilationFinal private SqueakDisplay display;
public final CheckForInterruptsState interrupt;
public final long startUpMillis = System.currentTimeMillis();
Expand Down Expand Up @@ -393,6 +394,59 @@ public ArrayObject getHiddenRoots() {
return hiddenRoots;
}

/* SpurMemoryManager>>#enterIntoClassTable: */
@TruffleBoundary
public void enterIntoClassTable(final ClassObject clazz) {
int majorIndex = SqueakImageConstants.majorClassIndexOf(classTableIndex);
final int initialMajorIndex = majorIndex;
assert initialMajorIndex > 0 : "classTableIndex should never index the first page; it's reserved for known classes";
int minorIndex = SqueakImageConstants.minorClassIndexOf(classTableIndex);
while (true) {
if (hiddenRoots.getObject(majorIndex) == NilObject.SINGLETON) {
ensureConsecutiveClassPagesUpTo(majorIndex);
minorIndex = 0;
}
final ArrayObject page = (ArrayObject) hiddenRoots.getObject(majorIndex);
for (int i = minorIndex; i < SqueakImageConstants.CLASS_TABLE_PAGE_SIZE; i++) {
if (page.getObject(i) == NilObject.SINGLETON) {
classTableIndex = SqueakImageConstants.classTableIndexFor(majorIndex, i);
assert classTableIndex >= 1 << SqueakImageConstants.CLASS_TABLE_MAJOR_INDEX_SHIFT : "classTableIndex must never index the first page, which is reserved for classes known to the VM";
page.setObject(i, this);
clazz.setSqueakHash(classTableIndex);
assert lookupClassIndex(classTableIndex) == this;
return;
}
}
majorIndex = Math.max(majorIndex + 1 & SqueakImageConstants.CLASS_INDEX_MASK, 1);
assert majorIndex != initialMajorIndex : "wrapped; table full";
}
}

/* Are all entries up to numClassTablePages must not be nil (see validClassTableRootPages). */
private void ensureConsecutiveClassPagesUpTo(final long majorIndex) {
for (int i = 0; i < majorIndex; i++) {
if (hiddenRoots.getObject(majorIndex) == NilObject.SINGLETON) {
hiddenRoots.setObject(majorIndex, newClassTablePage());
}
}
}

private ArrayObject newClassTablePage() {
return asArrayOfObjects(ArrayUtils.withAll(SqueakImageConstants.CLASS_TABLE_PAGE_SIZE, NilObject.SINGLETON));
}

private Object lookupClassIndex(final int classIndex) {
final long majorIndex = SqueakImageConstants.majorClassIndexOf(classIndex);
final Object classTablePageOrNil = hiddenRoots.getObject(majorIndex);
if (classTablePageOrNil instanceof ArrayObject) {
final long minorIndex = SqueakImageConstants.minorClassIndexOf(classIndex);
return ((ArrayObject) classTablePageOrNil).getObject(minorIndex);
} else {
assert classTablePageOrNil == NilObject.SINGLETON;
return NilObject.SINGLETON;
}
}

public TruffleFile getHomePath() {
return homePath;
}
Expand Down Expand Up @@ -425,19 +479,6 @@ private void ensureResourcesDirectoryAndPathInitialized() {
}
}

public long getGlobalClassCounter() {
return globalClassCounter;
}

public void setGlobalClassCounter(final int newValue) {
assert globalClassCounter < 0 : "globalClassCounter should only be set once";
globalClassCounter = newValue;
}

public int getNextClassHash() {
return ++globalClassCounter;
}

public NativeObject getDebugErrorSelector() {
return debugErrorSelector;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ private SqueakImageChunk readObject() {
} else {
assert classIndex == SqueakImageConstants.ARRAY_CLASS_INDEX_PUN &&
size == SqueakImageConstants.CLASS_TABLE_ROOT_SLOTS + SqueakImageConstants.HIDDEN_ROOT_SLOTS : "hiddenRootsObj has unexpected size";
hiddenRootsChunk = chunk; /* Seconds hidden object. */
hiddenRootsChunk = chunk; /* Second hidden object. */
}
}
return chunk;
Expand Down Expand Up @@ -385,7 +385,7 @@ private void fillInClassObjects() {
}
}
assert highestKnownClassIndex > 0 : "Failed to find highestKnownClassIndex";
image.setGlobalClassCounter(highestKnownClassIndex);
image.classTableIndex = highestKnownClassIndex;

/** Fill in metaClass. */
final SqueakImageChunk specialObjectsChunk = getChunk(specialObjectsPointer);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
import de.hpi.swa.trufflesqueak.exceptions.SqueakExceptions.SqueakException;
import de.hpi.swa.trufflesqueak.model.AbstractSqueakObject;
import de.hpi.swa.trufflesqueak.model.AbstractSqueakObjectWithClassAndHash;
import de.hpi.swa.trufflesqueak.model.ArrayObject;
import de.hpi.swa.trufflesqueak.model.BooleanObject;
import de.hpi.swa.trufflesqueak.model.CharacterObject;
import de.hpi.swa.trufflesqueak.model.ClassObject;
Expand All @@ -35,7 +34,6 @@
import de.hpi.swa.trufflesqueak.model.PointersObject;
import de.hpi.swa.trufflesqueak.model.layout.ObjectLayouts.PROCESS;
import de.hpi.swa.trufflesqueak.nodes.accessing.AbstractPointersObjectNodes.AbstractPointersObjectWriteNode;
import de.hpi.swa.trufflesqueak.util.ArrayUtils;
import de.hpi.swa.trufflesqueak.util.MiscUtils;
import de.hpi.swa.trufflesqueak.util.ObjectGraphUtils;
import de.hpi.swa.trufflesqueak.util.UnsafeUtils;
Expand Down Expand Up @@ -257,48 +255,6 @@ public long toWord(final Object object) {
}
}

private void insertIntoClassTable(final ClassObject classObject) {
final int classHash = (int) classObject.getSqueakHash();
final long majorIndex = SqueakImageConstants.majorClassIndexOf(classHash);
final long minorIndex = SqueakImageConstants.minorClassIndexOf(classHash);
if (image.getHiddenRoots().getObject(majorIndex) == NilObject.SINGLETON) {
ensureConsecutiveClassPagesUpTo(majorIndex);
}
final ArrayObject classTablePage = (ArrayObject) image.getHiddenRoots().getObject(majorIndex);
final Object pageEntry = classTablePage.getObject(minorIndex);
if (pageEntry == classObject) {
return; /* Found myself in page (possible because we are re-using hiddenRoots). */
} else if (pageEntry == NilObject.SINGLETON) {
/* Free slot found in classTable. */
classTablePage.setObject(minorIndex, classObject);
} else {
/* classIndex clashed, re-hash class until there's no longer a clash. */
long newMajorIndex = majorIndex;
long newMinorIndex = minorIndex;
while (image.getHiddenRoots().getObject(newMajorIndex) != NilObject.SINGLETON || classTablePage.getObject(newMinorIndex) != NilObject.SINGLETON) {
final int newHash = (int) classObject.rehashForClassTable(image);
newMajorIndex = SqueakImageConstants.majorClassIndexOf(newHash);
newMinorIndex = SqueakImageConstants.minorClassIndexOf(newHash);
}
insertIntoClassTable(classObject);
}
}

private ArrayObject newClassPage() {
final ArrayObject newClassPage = image.asArrayOfObjects(ArrayUtils.withAll(SqueakImageConstants.CLASS_TABLE_PAGE_SIZE, NilObject.SINGLETON));
reserve(newClassPage);
return newClassPage;
}

/* Are all entries up to numClassTablePages must not be nil (see validClassTableRootPages). */
private void ensureConsecutiveClassPagesUpTo(final long majorIndex) {
for (int i = 0; i < majorIndex; i++) {
if (image.getHiddenRoots().getObject(majorIndex) == NilObject.SINGLETON) {
image.getHiddenRoots().setObject(majorIndex, newClassPage());
}
}
}

private long reserve(final AbstractSqueakObjectWithClassAndHash object) {
final int numSlots = object.getNumSlots();
final int padding = SqueakImageReader.calculateObjectPadding(object.getSqueakClass().getInstanceSpecification());
Expand All @@ -313,9 +269,6 @@ private long reserve(final AbstractSqueakObjectWithClassAndHash object) {
allTracedObjects.add(object);
traceQueue.addLast(object);

if (object instanceof ClassObject) {
insertIntoClassTable((ClassObject) object);
}
return oop;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@
import de.hpi.swa.trufflesqueak.util.ObjectGraphUtils.ObjectTracer;

public abstract class AbstractSqueakObjectWithClassAndHash extends AbstractSqueakObject {
public static final int SQUEAK_HASH_MASK = (1 << 22) - 1;
public static final int MARK_BIT = 1 << 24;
public static final int SQUEAK_HASH_MASK = ObjectHeader.HASH_AND_CLASS_INDEX_SIZE - 1;
private static final int MARK_BIT = 1 << 24;
/* Generate new hash if hash is 0 (see SpurMemoryManager>>#hashBitsOf:). */
public static final int HASH_UNINITIALIZED = 0;
protected static final int HASH_UNINITIALIZED = 0;

/**
* Spur uses an 64-bit object header (see {@link ObjectHeader}). In TruffleSqueak, we only care
Expand Down Expand Up @@ -107,7 +107,7 @@ public final long getSqueakHash() {
/** Lazily initialize squeakHash and derive value from hashCode. */
initializeSqueakHash();
}
return getSqueakHashValue();
return getSqueakHashOrZero();
}

public final long getSqueakHash(final BranchProfile needsHashProfile) {
Expand All @@ -116,10 +116,10 @@ public final long getSqueakHash(final BranchProfile needsHashProfile) {
needsHashProfile.enter();
initializeSqueakHash();
}
return getSqueakHashValue();
return getSqueakHashOrZero();
}

private long getSqueakHashValue() {
public long getSqueakHashOrZero() {
return squeahHashAndBits & SQUEAK_HASH_MASK;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.profiles.BranchProfile;
import com.oracle.truffle.api.utilities.CyclicAssumption;

import de.hpi.swa.trufflesqueak.exceptions.SqueakExceptions.SqueakException;
import de.hpi.swa.trufflesqueak.image.SqueakImageChunk;
import de.hpi.swa.trufflesqueak.image.SqueakImageConstants;
import de.hpi.swa.trufflesqueak.image.SqueakImageContext;
import de.hpi.swa.trufflesqueak.image.SqueakImageReader;
import de.hpi.swa.trufflesqueak.image.SqueakImageWriter;
Expand Down Expand Up @@ -74,7 +76,7 @@ private ClassObject(final ClassObject original, final ArrayObject copiedInstance
}

public ClassObject(final SqueakImageContext image, final ClassObject classObject, final int size) {
super(image, image.getNextClassHash(), classObject);
super(image, classObject);
this.image = image;
pointers = ArrayUtils.withAll(Math.max(size - CLASS_DESCRIPTION.SIZE, 0), NilObject.SINGLETON);
instancesAreClasses = image.isMetaClass(classObject);
Expand All @@ -85,12 +87,6 @@ public SqueakImageContext getImage() {
return image;
}

public long rehashForClassTable(final SqueakImageContext i) {
final int newHash = i.getNextClassHash();
setSqueakHash(newHash);
return newHash;
}

/* Used by TruffleSqueakTest. */
public boolean hasLayout() {
return layout != null;
Expand Down Expand Up @@ -262,10 +258,8 @@ public boolean includesExternalFunctionBehavior(final SqueakImageContext i) {
@Override
public void fillin(final SqueakImageChunk chunk) {
if (methodDict == null) {
if (needsSqueakHash()) {
final int hash = chunk.getHash();
/* Generate class hashes if unknown. */
setSqueakHash(hash != 0 ? hash : chunk.getImage().getNextClassHash());
if (needsSqueakHash() && chunk.getHash() != 0) {
setSqueakHash(chunk.getHash());
}
final Object[] chunkPointers = chunk.getPointers();
superclass = chunkPointers[CLASS_DESCRIPTION.SUPERCLASS] == NilObject.SINGLETON ? null : (ClassObject) chunkPointers[CLASS_DESCRIPTION.SUPERCLASS];
Expand All @@ -274,8 +268,21 @@ public void fillin(final SqueakImageChunk chunk) {
instanceVariables = chunkPointers[CLASS_DESCRIPTION.INSTANCE_VARIABLES] == NilObject.SINGLETON ? null : (ArrayObject) chunkPointers[CLASS_DESCRIPTION.INSTANCE_VARIABLES];
organization = chunkPointers[CLASS_DESCRIPTION.ORGANIZATION] == NilObject.SINGLETON ? null : (PointersObject) chunkPointers[CLASS_DESCRIPTION.ORGANIZATION];
pointers = Arrays.copyOfRange(chunkPointers, CLASS_DESCRIPTION.SIZE, chunkPointers.length);
} else if (needsSqueakHash()) {
setSqueakHash(chunk.getImage().getNextClassHash());
}
}

/* see SpurMemoryManager>>#ensureBehaviorHash: */
public void ensureBehaviorHash() {
if (getSqueakHash() == SqueakImageConstants.FREE_OBJECT_CLASS_INDEX_PUN) {
image.enterIntoClassTable(this);
}
}

/* see SpurMemoryManager>>#ensureBehaviorHash: */
public void ensureBehaviorHash(final SqueakImageContext theImage, final BranchProfile needsHashProfile) {
if (getSqueakHash() == SqueakImageConstants.FREE_OBJECT_CLASS_INDEX_PUN) {
needsHashProfile.enter();
theImage.enterIntoClassTable(this);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import com.oracle.truffle.api.profiles.ConditionProfile;

import de.hpi.swa.trufflesqueak.exceptions.PrimitiveExceptions.PrimitiveFailed;
import de.hpi.swa.trufflesqueak.image.SqueakImageConstants;
import de.hpi.swa.trufflesqueak.image.SqueakImageContext;
import de.hpi.swa.trufflesqueak.io.SqueakDisplay;
import de.hpi.swa.trufflesqueak.model.AbstractPointersObject;
Expand Down Expand Up @@ -105,6 +106,9 @@ protected static final Object doImmeditate(final ClassObject classObject) {

@Specialization(guards = "!classObject.isImmediateClassType()")
protected final AbstractSqueakObject doSomeInstance(final ClassObject classObject) {
if (classObject.getSqueakHashOrZero() == SqueakImageConstants.FREE_OBJECT_CLASS_INDEX_PUN) {
return NilObject.SINGLETON; // Class has not been instantiated yet
}
try {
return ObjectGraphUtils.someInstanceOf(getContext(), classObject);
} catch (final IndexOutOfBoundsException e) {
Expand Down Expand Up @@ -747,7 +751,11 @@ protected final ArrayObject allInstances(final ClassObject classObject,
if (isNilClass.profile(image.isNilClass(classObject))) {
return getContext().asArrayOfObjects(NilObject.SINGLETON);
} else {
return image.asArrayOfObjects(ObjectGraphUtils.allInstancesOf(image, classObject));
if (classObject.getSqueakHashOrZero() == SqueakImageConstants.FREE_OBJECT_CLASS_INDEX_PUN) {
return getContext().newEmptyArray(); // Class has not been instantiated yet
} else {
return image.asArrayOfObjects(ObjectGraphUtils.allInstancesOf(image, classObject));
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -565,9 +565,10 @@ protected static final Object doSlotAtPut(@SuppressWarnings("unused") final Obje
protected abstract static class PrimBehaviorHashNode extends AbstractPrimitiveNode implements UnaryPrimitiveFallback {

@Specialization
protected static final long doClass(final ClassObject receiver,
protected final long doClass(final ClassObject receiver,
@Cached final BranchProfile needsHashProfile) {
return receiver.getSqueakHash(needsHashProfile);
receiver.ensureBehaviorHash(getContext(), needsHashProfile);
return receiver.getSqueakHashOrZero();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,13 @@ public static void pointersBecomeOneWay(final SqueakImageContext image, final Ob
}

@TruffleBoundary
public static Object[] allInstancesOf(final SqueakImageContext image, final ClassObject classObj) {
public static Object[] allInstancesOf(final SqueakImageContext image, final ClassObject targetClass) {
final ArrayDeque<AbstractSqueakObjectWithClassAndHash> result = new ArrayDeque<>();
final ObjectTracer pending = new ObjectTracer(image);
AbstractSqueakObjectWithClassAndHash currentObject;
while ((currentObject = pending.getNextPending()) != null) {
if (currentObject.tryToMark(pending.getCurrentMarkingFlag())) {
if (classObj == currentObject.getSqueakClass()) {
if (targetClass == currentObject.getSqueakClass()) {
result.add(currentObject);
}
pending.tracePointers(currentObject);
Expand All @@ -77,12 +77,12 @@ public static Object[] allInstancesOf(final SqueakImageContext image, final Clas
}

@TruffleBoundary
public static AbstractSqueakObject someInstanceOf(final SqueakImageContext image, final ClassObject classObj) {
public static AbstractSqueakObject someInstanceOf(final SqueakImageContext image, final ClassObject targetClass) {
final ObjectTracer pending = new ObjectTracer(image);
AbstractSqueakObjectWithClassAndHash currentObject;
while ((currentObject = pending.getNextPending()) != null) {
if (currentObject.tryToMark(pending.getCurrentMarkingFlag())) {
if (classObj == currentObject.getSqueakClass()) {
if (targetClass == currentObject.getSqueakClass()) {
return currentObject;
}
pending.tracePointers(currentObject);
Expand Down

0 comments on commit af8564a

Please sign in to comment.