Skip to content

Commit

Permalink
Read pointers directly from chunks.
Browse files Browse the repository at this point in the history
This reduces the amount of Object[] allocated, and thus memory pressure, during startup.
  • Loading branch information
fniephaus committed Oct 14, 2024
1 parent 0ae803a commit 09245cb
Show file tree
Hide file tree
Showing 11 changed files with 59 additions and 67 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -173,25 +173,21 @@ public void setSqueakClass(final ClassObject baseSqueakObject) {
squeakClass = baseSqueakObject;
}

public Object[] getPointers() {
if (pointers == null) {
final int length = getWordSize();
pointers = new Object[length];
for (int i = 0; i < length; i++) {
pointers[i] = decodePointer(getWord(i));
}
}
return pointers;
public Object getPointer(final int index) {
return decodePointer(getWord(index));
}

public Object[] getPointers(final int end) {
if (pointers == null) {
pointers = new Object[end];
for (int i = 0; i < end; i++) {
pointers[i] = decodePointer(getWord(i));
}
public Object[] getPointers(final int start) {
return getPointers(start, getWordSize());
}

public Object[] getPointers(final int start, final int end) {
final int numObjects = end - start;
final Object[] result = new Object[numObjects];
for (int i = 0; i < numObjects; i++) {
result[i] = getPointer(start + i);
}
return pointers;
return result;
}

private Object decodePointer(final long ptr) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,16 +119,15 @@ public final void fillin(final SqueakImageChunk chunk) {
primitiveExtension = layout.getFreshPrimitiveExtension();
objectExtension = layout.getFreshObjectExtension();
final AbstractPointersObjectWriteNode writeNode = AbstractPointersObjectWriteNode.getUncached();
final Object[] pointers = chunk.getPointers();
final int instSize = instsize();
for (int i = 0; i < instSize; i++) {
writeNode.execute(null, this, i, pointers[i]);
writeNode.execute(null, this, i, chunk.getPointer(i));
}
fillInVariablePart(pointers, instSize);
assert size() == pointers.length;
fillInVariablePart(chunk, instSize);
assert size() == chunk.getWordSize();
}

protected abstract void fillInVariablePart(Object[] pointers, int instSize);
protected abstract void fillInVariablePart(SqueakImageChunk chunk, int instSize);

public final ObjectLayout getLayout() {
if (layout == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,9 @@
*/
package de.hpi.swa.trufflesqueak.model;

import java.util.Arrays;

import com.oracle.truffle.api.nodes.Node;

import de.hpi.swa.trufflesqueak.image.SqueakImageChunk;
import de.hpi.swa.trufflesqueak.image.SqueakImageContext;
import de.hpi.swa.trufflesqueak.model.layout.ObjectLayout;
import de.hpi.swa.trufflesqueak.nodes.accessing.SqueakObjectIdentityNode;
Expand All @@ -34,8 +33,8 @@ protected AbstractVariablePointersObject(final AbstractVariablePointersObject or
}

@Override
protected void fillInVariablePart(final Object[] pointers, final int instSize) {
variablePart = Arrays.copyOfRange(pointers, instSize, pointers.length);
protected void fillInVariablePart(final SqueakImageChunk chunk, final int instSize) {
variablePart = chunk.getPointers(instSize);
}

public final void become(final AbstractVariablePointersObject other) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,14 +77,13 @@ public static boolean isLongNilTag(final long value) {

@Override
public void fillin(final SqueakImageChunk chunk) {
final Object[] pointers = chunk.getPointers();
final int valuesLength = pointers.length;
final int valuesLength = chunk.getWordSize();
storage = valuesLength;
if (valuesLength > 0) {
// Use a fresh write node because uncached node is too generic.
final ArrayObjectWriteNode writeNode = ArrayObjectWriteNode.create();
for (int i = 0; i < valuesLength; i++) {
writeNode.execute(writeNode, this, i, pointers[i]);
writeNode.execute(writeNode, this, i, chunk.getPointer(i));
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@
*/
package de.hpi.swa.trufflesqueak.model;

import java.util.Arrays;

import com.oracle.truffle.api.CompilerAsserts;
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
Expand Down Expand Up @@ -72,18 +70,18 @@ public static BlockClosureObject create(final SqueakImageContext image, final Cl
@Override
public void fillin(final SqueakImageChunk chunk) {
CompilerDirectives.transferToInterpreterAndInvalidate();
final Object[] pointers = chunk.getPointers();
assert pointers.length >= BLOCK_CLOSURE.FIRST_COPIED_VALUE;
outerContext = (ContextObject) pointers[BLOCK_CLOSURE.OUTER_CONTEXT];
if (pointers[BLOCK_CLOSURE.START_PC_OR_METHOD] instanceof final CompiledCodeObject code) {
assert chunk.getWordSize() >= BLOCK_CLOSURE.FIRST_COPIED_VALUE;
outerContext = (ContextObject) chunk.getPointer(BLOCK_CLOSURE.OUTER_CONTEXT);
final Object startPCOrMethod = chunk.getPointer(BLOCK_CLOSURE.START_PC_OR_METHOD);
if (startPCOrMethod instanceof final CompiledCodeObject code) {
block = code;
receiver = pointers[BLOCK_CLOSURE.FULL_RECEIVER];
copiedValues = Arrays.copyOfRange(pointers, BLOCK_CLOSURE.FULL_FIRST_COPIED_VALUE, pointers.length);
receiver = chunk.getPointer(BLOCK_CLOSURE.FULL_RECEIVER);
copiedValues = chunk.getPointers(BLOCK_CLOSURE.FULL_FIRST_COPIED_VALUE);
} else {
startPC = (long) pointers[BLOCK_CLOSURE.START_PC_OR_METHOD];
copiedValues = Arrays.copyOfRange(pointers, BLOCK_CLOSURE.FIRST_COPIED_VALUE, pointers.length);
startPC = (long) startPCOrMethod;
copiedValues = chunk.getPointers(BLOCK_CLOSURE.FIRST_COPIED_VALUE);
}
numArgs = (long) pointers[BLOCK_CLOSURE.ARGUMENT_COUNT];
numArgs = (long) chunk.getPointer(BLOCK_CLOSURE.ARGUMENT_COUNT);
}

public AbstractSqueakObject getOuterContext() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@
*/
package de.hpi.swa.trufflesqueak.model;

import java.util.Arrays;

import com.oracle.truffle.api.Assumption;
import com.oracle.truffle.api.CompilerAsserts;
import com.oracle.truffle.api.CompilerDirectives;
Expand Down Expand Up @@ -257,13 +255,12 @@ public void fillin(final SqueakImageChunk chunk) {
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];
methodDict = (VariablePointersObject) chunkPointers[CLASS_DESCRIPTION.METHOD_DICT];
format = (long) chunkPointers[CLASS_DESCRIPTION.FORMAT];
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);
superclass = (ClassObject) NilObject.nilToNull(chunk.getPointer(CLASS_DESCRIPTION.SUPERCLASS));
methodDict = (VariablePointersObject) chunk.getPointer(CLASS_DESCRIPTION.METHOD_DICT);
format = (long) chunk.getPointer(CLASS_DESCRIPTION.FORMAT);
instanceVariables = (ArrayObject) NilObject.nilToNull(chunk.getPointer(CLASS_DESCRIPTION.INSTANCE_VARIABLES));
organization = (PointersObject) NilObject.nilToNull(chunk.getPointer(CLASS_DESCRIPTION.ORGANIZATION));
pointers = chunk.getPointers(CLASS_DESCRIPTION.SIZE);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ public void fillin(final SqueakImageChunk chunk) {
final long header = chunk.getWord(0) >> SqueakImageConstants.NUM_TAG_BITS;
numLiterals = CompiledCodeHeaderDecoder.getNumLiterals(header);
assert literals == null;
literals = chunk.getPointers(1 + numLiterals);
literals = chunk.getPointers(0, 1 + numLiterals);
decodeHeader();
assert bytes == null;
bytes = Arrays.copyOfRange(chunk.getBytes(), literals.length * SqueakImageConstants.WORD_SIZE, chunk.getBytes().length);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,13 +111,12 @@ public void fillin(final SqueakImageChunk chunk) {
}

public void fillinContext(final SqueakImageChunk chunk) {
final Object[] pointers = chunk.getPointers();
size = pointers.length;
size = chunk.getWordSize();
assert size > CONTEXT.TEMP_FRAME_START;
final CompiledCodeObject method = (CompiledCodeObject) pointers[CONTEXT.METHOD];
final AbstractSqueakObject sender = (AbstractSqueakObject) pointers[CONTEXT.SENDER_OR_NIL];
final CompiledCodeObject method = (CompiledCodeObject) chunk.getPointer(CONTEXT.METHOD);
final AbstractSqueakObject sender = (AbstractSqueakObject) chunk.getPointer(CONTEXT.SENDER_OR_NIL);
assert sender != null : "sender should not be null";
final Object closureOrNil = pointers[CONTEXT.CLOSURE_OR_NIL];
final Object closureOrNil = chunk.getPointer(CONTEXT.CLOSURE_OR_NIL);
final BlockClosureObject closure;
final int numArgs;
final CompiledCodeObject methodOrBlock;
Expand All @@ -136,22 +135,22 @@ public void fillinContext(final SqueakImageChunk chunk) {
}
}
final int endArguments = CONTEXT.TEMP_FRAME_START + numArgs;
final Object[] arguments = Arrays.copyOfRange(pointers, CONTEXT.RECEIVER, endArguments);
final Object[] arguments = chunk.getPointers(CONTEXT.RECEIVER, endArguments);
final Object[] frameArguments = FrameAccess.newWith(sender, closure, arguments);
CompilerDirectives.transferToInterpreterAndInvalidate();
truffleFrame = Truffle.getRuntime().createMaterializedFrame(frameArguments, methodOrBlock.getFrameDescriptor());
FrameAccess.initializeMarker(truffleFrame);
FrameAccess.setContext(truffleFrame, this);
final Object pc = pointers[CONTEXT.INSTRUCTION_POINTER];
final Object pc = chunk.getPointer(CONTEXT.INSTRUCTION_POINTER);
if (pc == NilObject.SINGLETON) {
removeInstructionPointer();
} else {
setInstructionPointer(MiscUtils.toIntExact((long) pc));
}
final int stackPointer = MiscUtils.toIntExact((long) pointers[CONTEXT.STACKPOINTER]);
final int stackPointer = MiscUtils.toIntExact((long) chunk.getPointer(CONTEXT.STACKPOINTER));
setStackPointer(stackPointer);
for (int i = 0; i < stackPointer; i++) {
atTempPut(i, pointers[CONTEXT.TEMP_FRAME_START + i]);
atTempPut(i, chunk.getPointer(CONTEXT.TEMP_FRAME_START + i));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ public static Object nullToNil(final Object object) {
return object == null ? SINGLETON : object;
}

public static Object nilToNull(final Object object) {
return object == SINGLETON ? null : object;
}

@Override
public long getOrCreateSqueakHash() {
return SQUEAK_HASH;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import com.oracle.truffle.api.CompilerAsserts;
import com.oracle.truffle.api.nodes.Node;

import de.hpi.swa.trufflesqueak.image.SqueakImageChunk;
import de.hpi.swa.trufflesqueak.image.SqueakImageContext;
import de.hpi.swa.trufflesqueak.image.SqueakImageWriter;
import de.hpi.swa.trufflesqueak.model.layout.ObjectLayout;
Expand Down Expand Up @@ -58,9 +59,9 @@ public void setHiddenObject(final Object value) {
}

@Override
protected void fillInVariablePart(final Object[] pointers, final int instSize) {
protected void fillInVariablePart(final SqueakImageChunk chunk, final int instSize) {
// No variable part to fill in
assert pointers.length == instSize : "Unexpected number of pointers found for " + this;
assert chunk.getWordSize() == instSize : "Unexpected number of pointers found for " + this;
}

public void become(final PointersObject other) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.profiles.InlinedConditionProfile;

import de.hpi.swa.trufflesqueak.image.SqueakImageChunk;
import de.hpi.swa.trufflesqueak.image.SqueakImageContext;
import de.hpi.swa.trufflesqueak.image.SqueakImageWriter;
import de.hpi.swa.trufflesqueak.model.layout.ObjectLayout;
Expand All @@ -39,13 +40,12 @@ private WeakVariablePointersObject(final WeakVariablePointersObject original) {
}

@Override
protected void fillInVariablePart(final Object[] pointers, final int instSize) {
super.fillInVariablePart(pointers, instSize);
for (int i = 0; i < variablePart.length; i++) {
final Object value = variablePart[i];
if (value instanceof final AbstractSqueakObject o) {
variablePart[i] = new WeakRef(o, weakPointersQueue);
}
protected void fillInVariablePart(final SqueakImageChunk chunk, final int instSize) {
final int numVariableSlots = chunk.getWordSize() - instSize;
variablePart = new Object[numVariableSlots];
for (int i = 0; i < numVariableSlots; i++) {
final Object value = chunk.getPointer(instSize + i);
variablePart[i] = value instanceof final AbstractSqueakObject o ? new WeakRef(o, weakPointersQueue) : value;
}
}

Expand Down

0 comments on commit 09245cb

Please sign in to comment.