Skip to content

Commit

Permalink
Revise image reading
Browse files Browse the repository at this point in the history
  • Loading branch information
fniephaus committed Aug 20, 2022
1 parent af8564a commit 1cd3049
Show file tree
Hide file tree
Showing 18 changed files with 123 additions and 129 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import org.junit.Test;

import de.hpi.swa.trufflesqueak.image.SqueakImageChunk;
import de.hpi.swa.trufflesqueak.image.SqueakImageConstants.ObjectHeader;
import de.hpi.swa.trufflesqueak.model.CompiledCodeObject;
import de.hpi.swa.trufflesqueak.model.FloatObject;
import de.hpi.swa.trufflesqueak.model.NilObject;
Expand Down Expand Up @@ -178,13 +179,11 @@ private static SqueakImageChunk newFloatChunk(final byte[] data) {
final SqueakImageChunk chunk = new SqueakImageChunk(
null,
image,
10, // float format, 32-bit words without padding word
34, // classid of BoxedFloat64
3833906, // identityHash for 1.0
ObjectHeader.getHeader(0, 3833906, 10, 34),
0, // position
data // 2 words
);
chunk.setSqClass(image.floatClass);
chunk.setSqueakClass(image.floatClass);
return chunk;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;

import de.hpi.swa.trufflesqueak.exceptions.SqueakExceptions.SqueakException;
import de.hpi.swa.trufflesqueak.image.SqueakImageConstants.ObjectHeader;
import de.hpi.swa.trufflesqueak.model.ArrayObject;
import de.hpi.swa.trufflesqueak.model.BlockClosureObject;
import de.hpi.swa.trufflesqueak.model.CharacterObject;
Expand All @@ -26,45 +27,42 @@
import de.hpi.swa.trufflesqueak.util.UnsafeUtils;

public final class SqueakImageChunk {
private Object object;
private ClassObject sqClass;
private Object[] pointers;

private final int classIndex;
private final int position;

private final SqueakImageContext image;
private final SqueakImageReader reader;
private final int format;
private final int hash;
private final SqueakImageContext image;
private final long header;
private final int position;
private final byte[] bytes;

private Object object;
private ClassObject squeakClass;
private Object[] pointers;

public SqueakImageChunk(final SqueakImageReader reader,
final SqueakImageContext image,
final int format,
final int classIndex,
final int hash,
final long header,
final int position,
final byte[] bytes) {
this.reader = reader;
this.image = image;
this.format = format;
this.classIndex = classIndex;
this.hash = hash;
this.header = header;
this.position = position;
this.bytes = bytes;
if (bytes == null) { /* Ignored object (see SqueakImageReader#ignoreObjectData) */
assert SqueakImageReader.isHiddenObject(getClassIndex());
object = NilObject.SINGLETON;
}
}

public static SqueakImageChunk createDummyChunk(final SqueakImageContext image, final Object[] pointers) {
final SqueakImageChunk chunk = new SqueakImageChunk(null, image, 0, 0, 0, 0, new byte[0]);
final SqueakImageChunk chunk = new SqueakImageChunk(null, image, 0, 0, new byte[0]);
chunk.pointers = pointers;
return chunk;
}

public ClassObject asClassObject(final ClassObject metaClassObject) {
if (object == null) {
assert format == 1;
object = new ClassObject(image, hash, metaClassObject);
assert getFormat() == 1;
object = new ClassObject(image, header, metaClassObject);
} else if (object == NilObject.SINGLETON) {
return null;
}
Expand All @@ -73,60 +71,56 @@ public ClassObject asClassObject(final ClassObject metaClassObject) {

public Object asObject() {
if (object == null) {
if (bytes == null) {
assert SqueakImageReader.isHiddenObject(classIndex);
/* Ignored object (see SqueakImageReader#ignoreObjectData) */
return NilObject.SINGLETON;
}
final ClassObject squeakClass = getSqClass();
final int format = getFormat();
final ClassObject classObject = getSqueakClass();
if (format == 0) { // no fields
object = new EmptyObject(image, hash, squeakClass);
object = new EmptyObject(header, classObject);
} else if (format == 1) { // fixed pointers
if (squeakClass.instancesAreClasses()) {
if (classObject.instancesAreClasses()) {
/*
* In rare cases, there are still some classes that are not in the class table
* for some reason (e.g. not completely removed from the system yet).
*/
object = new ClassObject(image, hash, squeakClass);
object = new ClassObject(image, header, classObject);
} else {
// classes should already be instantiated at this point, check a bit
assert squeakClass != image.metaClass && squeakClass.getSqueakClass() != image.metaClass;
object = new PointersObject(image, hash, squeakClass);
assert classObject != image.metaClass && classObject.getSqueakClass() != image.metaClass;
object = new PointersObject(header, classObject);
}
} else if (format == 2) { // indexable fields
object = new ArrayObject(image, hash, squeakClass);
object = new ArrayObject(header, classObject);
} else if (format == 3) { // fixed and indexable fields
if (squeakClass == image.methodContextClass) {
object = ContextObject.createWithHash(image, hash);
} else if (image.isBlockClosureClass(squeakClass) || image.isFullBlockClosureClass(squeakClass)) {
object = BlockClosureObject.createWithHash(image, hash, squeakClass);
if (classObject == image.methodContextClass) {
object = ContextObject.createWithHeader(image, header);
} else if (image.isBlockClosureClass(classObject) || image.isFullBlockClosureClass(classObject)) {
object = BlockClosureObject.createWithHeaderAndClass(header, classObject);
} else {
object = new VariablePointersObject(image, hash, squeakClass);
object = new VariablePointersObject(header, classObject);
}
} else if (format == 4) { // indexable weak fields
object = new WeakVariablePointersObject(image, hash, squeakClass);
object = new WeakVariablePointersObject(image, header, classObject);
} else if (format == 5) { // fixed weak fields
throw SqueakException.create("Ephemerons not (yet) supported");
} else if (format <= 8) {
assert false : "Should never happen (unused format)";
} else if (format == 9) { // 64-bit integers
object = NativeObject.newNativeLongs(this);
} else if (format <= 11) { // 32-bit integers
if (squeakClass == image.floatClass) {
if (classObject == image.floatClass) {
object = FloatObject.newFrom(this);
} else {
object = NativeObject.newNativeInts(this);
}
} else if (format <= 15) { // 16-bit integers
object = NativeObject.newNativeShorts(this);
} else if (format <= 23) { // bytes
if (squeakClass == image.largePositiveIntegerClass || squeakClass == image.largeNegativeIntegerClass) {
object = new LargeIntegerObject(image, hash, squeakClass, getBytes()).reduceIfPossible();
if (classObject == image.largePositiveIntegerClass || classObject == image.largeNegativeIntegerClass) {
object = new LargeIntegerObject(image, header, classObject, getBytes()).reduceIfPossible();
} else {
object = NativeObject.newNativeBytes(this);
}
} else if (format <= 31) { // compiled methods
object = new CompiledCodeObject(image, hash, squeakClass);
object = new CompiledCodeObject(header, classObject);
}
}
return object;
Expand All @@ -141,19 +135,21 @@ public boolean isNil() {
return object == NilObject.SINGLETON;
}

public int getFormat() {
private int getFormat() {
final int format = ObjectHeader.getFormat(header);
assert 0 <= format && format != 6 && format != 8 && format <= 31 : "Unexpected format";
return format;
}

public int getHash() {
return hash;
return ObjectHeader.getHash(header);
}

public ClassObject getSqClass() {
if (sqClass == null) {
sqClass = getClassChunk().asClassObject(null);
public ClassObject getSqueakClass() {
if (squeakClass == null) {
squeakClass = getClassChunk().asClassObject(null);
}
return sqClass;
return squeakClass;
}

public SqueakImageContext getImage() {
Expand All @@ -169,16 +165,17 @@ public int getPosition() {
}

public SqueakImageChunk getClassChunk() {
final int majorIdx = SqueakImageConstants.majorClassIndexOf(classIndex);
final int minorIdx = SqueakImageConstants.minorClassIndexOf(classIndex);
final SqueakImageChunk classTablePage = reader.getChunk(reader.hiddenRootsChunk.getWord(majorIdx));
final SqueakImageChunk classChunk = reader.getChunk(classTablePage.getWord(minorIdx));
final int classIndex = getClassIndex();
final int majorIndex = SqueakImageConstants.majorClassIndexOf(classIndex);
final int minorIndex = SqueakImageConstants.minorClassIndexOf(classIndex);
final SqueakImageChunk classTablePage = reader.getChunk(reader.hiddenRootsChunk.getWord(majorIndex));
final SqueakImageChunk classChunk = reader.getChunk(classTablePage.getWord(minorIndex));
assert classChunk != null : "Unable to find class chunk.";
return classChunk;
}

public void setSqClass(final ClassObject baseSqueakObject) {
sqClass = baseSqueakObject;
public void setSqueakClass(final ClassObject baseSqueakObject) {
squeakClass = baseSqueakObject;
}

public Object[] getPointers() {
Expand Down Expand Up @@ -237,7 +234,7 @@ private void logBogusPointer(final long ptr) {
}

public int getClassIndex() {
return classIndex;
return ObjectHeader.getClassIndex(header);
}

public byte[] getBytes() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,12 +76,12 @@ public final class SqueakImageContext {
/* Special objects */
public final ClassObject trueClass = new ClassObject(this);
public final ClassObject falseClass = new ClassObject(this);
public final PointersObject schedulerAssociation = new PointersObject(this);
public final PointersObject schedulerAssociation = new PointersObject();
public final ClassObject bitmapClass = new ClassObject(this);
public final ClassObject smallIntegerClass = new ClassObject(this);
public final ClassObject byteStringClass = new ClassObject(this);
public final ClassObject arrayClass = new ClassObject(this);
public final PointersObject smalltalk = new PointersObject(this);
public final PointersObject smalltalk = new PointersObject();
public final ClassObject floatClass = new ClassObject(this);
public final ClassObject methodContextClass = new ClassObject(this);
public final ClassObject pointClass = new ClassObject(this);
Expand All @@ -90,23 +90,23 @@ public final class SqueakImageContext {
public final ClassObject compiledMethodClass = new ClassObject(this);
public final ClassObject semaphoreClass = new ClassObject(this);
public final ClassObject characterClass = new ClassObject(this);
public final NativeObject doesNotUnderstand = new NativeObject(this);
public final NativeObject cannotReturn = new NativeObject(this);
public final NativeObject mustBeBooleanSelector = new NativeObject(this);
public final NativeObject doesNotUnderstand = new NativeObject();
public final NativeObject cannotReturn = new NativeObject();
public final NativeObject mustBeBooleanSelector = new NativeObject();
public final ClassObject byteArrayClass = new ClassObject(this);
public final ClassObject processClass = new ClassObject(this);
public final ClassObject blockClosureClass = new ClassObject(this);
public final ClassObject largeNegativeIntegerClass = new ClassObject(this);
public final NativeObject aboutToReturnSelector = new NativeObject(this);
public final NativeObject runWithInSelector = new NativeObject(this);
public final ArrayObject primitiveErrorTable = new ArrayObject(this);
public final ArrayObject specialSelectors = new ArrayObject(this);
public final NativeObject aboutToReturnSelector = new NativeObject();
public final NativeObject runWithInSelector = new NativeObject();
public final ArrayObject primitiveErrorTable = new ArrayObject();
public final ArrayObject specialSelectors = new ArrayObject();
@CompilationFinal public ClassObject fullBlockClosureClass;
@CompilationFinal public ClassObject smallFloatClass;
@CompilationFinal private ClassObject byteSymbolClass;
@CompilationFinal private ClassObject foreignObjectClass;

public final ArrayObject specialObjectsArray = new ArrayObject(this);
public final ArrayObject specialObjectsArray = new ArrayObject();
public final ClassObject metaClass = new ClassObject(this);
public final ClassObject nilClass = new ClassObject(this);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -248,19 +248,16 @@ private SqueakImageChunk readObject() {
final int size = numSlots;
assert size >= 0 : "Negative object size";
final int classIndex = SqueakImageConstants.ObjectHeader.getClassIndex(headerWord);
final int format = SqueakImageConstants.ObjectHeader.getFormat(headerWord);
assert 0 <= format && format != 6 && format != 8 && format <= 31 : "Unexpected format";
assert format != 0 || classIndex == 0 || size == 0 : "Empty objects must not have slots";
final int hash = SqueakImageConstants.ObjectHeader.getHash(headerWord);
final byte[] objectData;
if (ignoreObjectData(headerWord, classIndex, size)) {
/* Skip some hidden objects for performance reasons. */
objectData = null;
skipBytes(size * SqueakImageConstants.WORD_SIZE);
} else {
final int format = SqueakImageConstants.ObjectHeader.getFormat(headerWord);
objectData = nextObjectData(size, format);
}
final SqueakImageChunk chunk = new SqueakImageChunk(this, image, format, classIndex, hash, pos, objectData);
final SqueakImageChunk chunk = new SqueakImageChunk(this, image, headerWord, pos, objectData);
if (hiddenRootsChunk == null && isHiddenObject(classIndex)) {
if (freePageList == null) {
assert classIndex == SqueakImageConstants.WORD_SIZE_CLASS_INDEX_PUN && size == SqueakImageConstants.NUM_FREE_LISTS;
Expand Down Expand Up @@ -373,7 +370,7 @@ private void fillInClassObjects() {
final long potentialClassPtr = classTablePage.getWord(i);
assert potentialClassPtr != 0;
final SqueakImageChunk classChunk = getChunk(potentialClassPtr);
if (classChunk != null && classChunk.getSqClass() == image.metaClass) {
if (classChunk != null && classChunk.getSqueakClass() == image.metaClass) {
/* Derive classIndex from current position in class table. */
highestKnownClassIndex = p << SqueakImageConstants.CLASS_TABLE_MAJOR_INDEX_SHIFT | i;
assert classChunk.getWordSize() == METACLASS.INST_SIZE;
Expand Down Expand Up @@ -412,7 +409,7 @@ private void fillInClassObjects() {
final long potentialClassPtr = classTablePage.getWord(i);
assert potentialClassPtr != 0;
final SqueakImageChunk classChunk = getChunk(potentialClassPtr);
if (classChunk != null && classChunk.getSqClass() == image.metaClass) {
if (classChunk != null && classChunk.getSqueakClass() == image.metaClass) {
assert classChunk.getWordSize() == METACLASS.INST_SIZE;
final SqueakImageChunk classInstance = getChunk(classChunk.getWord(METACLASS.THIS_CLASS));
final ClassObject metaClassObject = classChunk.asClassObject(image.metaClass);
Expand All @@ -439,7 +436,7 @@ private void fillInObjects() {
if (chunkObject instanceof AbstractSqueakObjectWithClassAndHash) {
final AbstractSqueakObjectWithClassAndHash obj = (AbstractSqueakObjectWithClassAndHash) chunkObject;
if (obj.needsSqueakClass()) {
obj.setSqueakClass(chunk.getSqClass());
obj.setSqueakClass(chunk.getSqueakClass());
}
if (obj.needsSqueakHash()) {
obj.setSqueakHash(chunk.getHash());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ public abstract class AbstractPointersObject extends AbstractSqueakObjectWithCla
public long[] primitiveExtension;
public Object[] objectExtension;

protected AbstractPointersObject(final SqueakImageContext image) {
super(image);
protected AbstractPointersObject() {
super();
}

protected AbstractPointersObject(final SqueakImageContext image, final ClassObject classObject, final ObjectLayout layout) {
Expand All @@ -70,8 +70,8 @@ protected AbstractPointersObject(final SqueakImageContext image, final ClassObje
objectExtension = this.layout.getFreshObjectExtension();
}

protected AbstractPointersObject(final SqueakImageContext image, final int hash, final ClassObject classObject) {
super(image, hash, classObject);
protected AbstractPointersObject(final long header, final ClassObject classObject) {
super(header, classObject);
}

protected AbstractPointersObject(final AbstractPointersObject original) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public abstract class AbstractSqueakObjectWithClassAndHash extends AbstractSquea
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:). */
protected static final int HASH_UNINITIALIZED = 0;
private static final int HASH_UNINITIALIZED = 0;

/**
* Spur uses an 64-bit object header (see {@link ObjectHeader}). In TruffleSqueak, we only care
Expand All @@ -40,13 +40,14 @@ public abstract class AbstractSqueakObjectWithClassAndHash extends AbstractSquea
private int squeahHashAndBits;

// For special/well-known objects only.
protected AbstractSqueakObjectWithClassAndHash(final SqueakImageContext image) {
this(image, null);
protected AbstractSqueakObjectWithClassAndHash() {
this(HASH_UNINITIALIZED, null);
}

protected AbstractSqueakObjectWithClassAndHash(final SqueakImageContext image, final int hash, final ClassObject klass) {
this(image.getCurrentMarkingFlag(), hash, klass);
assert hash >= 0 : "Squeak hashes should not be negative (will mess up object headers)";
protected AbstractSqueakObjectWithClassAndHash(final long header, final ClassObject klass) {
squeahHashAndBits = ObjectHeader.getHash(header);
squeakClass = klass;
// mark bit zero when loading image
}

protected AbstractSqueakObjectWithClassAndHash(final SqueakImageContext image, final ClassObject klass) {
Expand Down
Loading

0 comments on commit 1cd3049

Please sign in to comment.