Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement #to:do: inlining #82

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 19 additions & 10 deletions src/trufflesom/compiler/ParserBc.java
Original file line number Diff line number Diff line change
Expand Up @@ -279,25 +279,34 @@ private void keywordMessage(final BytecodeMethodGenContext mgenc)
boolean isSuperSend = superSend;
superSend = false;

int numArgs = 0;
StringBuilder kw = new StringBuilder();
do {
kw.append(keyword());
formula(mgenc);
numArgs += 1;
} while (sym == Keyword);

String kwStr = kw.toString();

if (!isSuperSend) {
if (("ifTrue:".equals(kwStr) && mgenc.inlineIfTrueOrIfFalse(this, true)) ||
("ifFalse:".equals(kwStr) && mgenc.inlineIfTrueOrIfFalse(this, false)) ||
("ifTrue:ifFalse:".equals(kwStr) && mgenc.inlineIfTrueIfFalse(this, true)) ||
("ifFalse:ifTrue:".equals(kwStr) && mgenc.inlineIfTrueIfFalse(this, false)) ||
("whileTrue:".equals(kwStr) && mgenc.inlineWhileTrueOrFalse(this, true)) ||
("whileFalse:".equals(kwStr) && mgenc.inlineWhileTrueOrFalse(this, false)) ||
("or:".equals(kwStr) && mgenc.inlineAndOr(this, true)) ||
("and:".equals(kwStr) && mgenc.inlineAndOr(this, false))) {
// all done
return;
if (numArgs == 1) {
if (("ifTrue:".equals(kwStr) && mgenc.inlineIfTrueOrIfFalse(this, true)) ||
("ifFalse:".equals(kwStr) && mgenc.inlineIfTrueOrIfFalse(this, false)) ||
("whileTrue:".equals(kwStr) && mgenc.inlineWhileTrueOrFalse(this, true)) ||
("whileFalse:".equals(kwStr) && mgenc.inlineWhileTrueOrFalse(this, false)) ||
("or:".equals(kwStr) && mgenc.inlineAndOr(this, true)) ||
("and:".equals(kwStr) && mgenc.inlineAndOr(this, false))) {
// all done
return;
}
} else if (numArgs == 2) {
if (("ifTrue:ifFalse:".equals(kwStr) && mgenc.inlineIfTrueIfFalse(this, true)) ||
("ifFalse:ifTrue:".equals(kwStr) && mgenc.inlineIfTrueIfFalse(this, false)) ||
("to:do:".equals(kwStr) && mgenc.inlineToDo(this))) {
// all done
return;
}
}
}

Expand Down
45 changes: 45 additions & 0 deletions src/trufflesom/compiler/Variable.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import com.oracle.truffle.api.frame.FrameDescriptor;
import com.oracle.truffle.api.frame.FrameSlot;
import com.oracle.truffle.api.frame.FrameSlotKind;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.source.SourceSection;

import bd.inlining.NodeState;
Expand Down Expand Up @@ -163,6 +164,50 @@ public void init(final FrameSlot slot, final FrameDescriptor descriptor) {
this.descriptor = descriptor;
}

public boolean isBoolKind(final VirtualFrame frame) {
FrameSlotKind kind = descriptor.getFrameSlotKind(slot);
if (kind == FrameSlotKind.Boolean) {
return true;
}
if (kind == FrameSlotKind.Illegal) {
descriptor.setFrameSlotKind(slot, FrameSlotKind.Boolean);
return true;
}
return false;
}

public boolean isLongKind(final VirtualFrame frame) {
FrameSlotKind kind = descriptor.getFrameSlotKind(slot);
if (kind == FrameSlotKind.Long) {
return true;
}
if (kind == FrameSlotKind.Illegal) {
descriptor.setFrameSlotKind(slot, FrameSlotKind.Long);
return true;
}
return false;
}

public boolean isDoubleKind(final VirtualFrame frame) {
FrameSlotKind kind = descriptor.getFrameSlotKind(slot);
if (kind == FrameSlotKind.Double) {
return true;
}
if (kind == FrameSlotKind.Illegal) {
descriptor.setFrameSlotKind(slot, FrameSlotKind.Double);
return true;
}
return false;
}

public boolean isUninitialized(final VirtualFrame frame) {
return descriptor.getFrameSlotKind(slot) == FrameSlotKind.Illegal;
}

public void makeObject() {
descriptor.setFrameSlotKind(slot, FrameSlotKind.Object);
}

@Override
public ExpressionNode getReadNode(final int contextLevel, final SourceSection source) {
transferToInterpreterAndInvalidate("Variable.getReadNode");
Expand Down
21 changes: 17 additions & 4 deletions src/trufflesom/compiler/bc/BytecodeGenerator.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,15 @@

import static trufflesom.interpreter.bc.Bytecodes.DEC;
import static trufflesom.interpreter.bc.Bytecodes.DUP;
import static trufflesom.interpreter.bc.Bytecodes.DUP_SECOND;
import static trufflesom.interpreter.bc.Bytecodes.HALT;
import static trufflesom.interpreter.bc.Bytecodes.INC;
import static trufflesom.interpreter.bc.Bytecodes.INC_FIELD_PUSH;
import static trufflesom.interpreter.bc.Bytecodes.JUMP;
import static trufflesom.interpreter.bc.Bytecodes.JUMP2;
import static trufflesom.interpreter.bc.Bytecodes.JUMP2_BACKWARDS;
import static trufflesom.interpreter.bc.Bytecodes.JUMP_BACKWARDS;
import static trufflesom.interpreter.bc.Bytecodes.JUMP_IF_GREATER;
import static trufflesom.interpreter.bc.Bytecodes.JUMP_ON_FALSE_POP;
import static trufflesom.interpreter.bc.Bytecodes.JUMP_ON_FALSE_TOP_NIL;
import static trufflesom.interpreter.bc.Bytecodes.JUMP_ON_TRUE_POP;
Expand Down Expand Up @@ -94,6 +96,14 @@ public static void emitHALT(final BytecodeMethodGenContext mgenc) {
emit1(mgenc, HALT, 0);
}

public static void emitDUP(final BytecodeMethodGenContext mgenc) {
emit1(mgenc, DUP, 1);
}

public static void emitDUPSECOND(final BytecodeMethodGenContext mgenc) {
emit1(mgenc, DUP_SECOND, 1);
}

public static void emitINC(final BytecodeMethodGenContext mgenc) {
emit1(mgenc, INC, 0);
}
Expand Down Expand Up @@ -163,10 +173,6 @@ public static void emitRETURNFIELD(final BytecodeMethodGenContext mgenc, final b
throw new IllegalArgumentException("RETURN_FIELD bytecode does not support idx=" + idx);
}

public static void emitDUP(final BytecodeMethodGenContext mgenc) {
emit1(mgenc, DUP, 1);
}

public static void emitPUSHBLOCK(final BytecodeMethodGenContext mgenc,
final SMethod blockMethod, final boolean withContext) {
byte litIdx = mgenc.findLiteralIndex(blockMethod);
Expand Down Expand Up @@ -369,6 +375,13 @@ public static void emitJumpWithOffset(final BytecodeMethodGenContext mgenc,
emit3(mgenc, offset2 == 0 ? JUMP : JUMP2, offset1, offset2, 0);
}

public static int emitJumpIfGreaterWithDummyOffset(final BytecodeMethodGenContext mgenc) {
emit1(mgenc, JUMP_IF_GREATER, 0);
int idx = mgenc.addBytecodeArgumentAndGetIndex((byte) 0);
mgenc.addBytecodeArgument((byte) 0);
return idx;
}

public static void emitJumpBackwardsWithOffset(final BytecodeMethodGenContext mgenc,
final byte offset1, final byte offset2) {
emit3(mgenc, offset2 == 0 ? JUMP_BACKWARDS : JUMP2_BACKWARDS, offset1, offset2, 0);
Expand Down
66 changes: 57 additions & 9 deletions src/trufflesom/compiler/bc/BytecodeMethodGenContext.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
package trufflesom.compiler.bc;

import static trufflesom.compiler.bc.BytecodeGenerator.emitDUP;
import static trufflesom.compiler.bc.BytecodeGenerator.emitDUPSECOND;
import static trufflesom.compiler.bc.BytecodeGenerator.emitINC;
import static trufflesom.compiler.bc.BytecodeGenerator.emitJumpBackwardsWithOffset;
import static trufflesom.compiler.bc.BytecodeGenerator.emitJumpIfGreaterWithDummyOffset;
import static trufflesom.compiler.bc.BytecodeGenerator.emitJumpOnBoolWithDummyOffset;
import static trufflesom.compiler.bc.BytecodeGenerator.emitJumpWithDummyOffset;
import static trufflesom.compiler.bc.BytecodeGenerator.emitPOP;
import static trufflesom.compiler.bc.BytecodeGenerator.emitPOPLOCAL;
import static trufflesom.compiler.bc.BytecodeGenerator.emitPUSHCONSTANT;
import static trufflesom.interpreter.bc.Bytecodes.DUP;
import static trufflesom.interpreter.bc.Bytecodes.INC;
Expand Down Expand Up @@ -69,6 +74,7 @@
import trufflesom.compiler.Variable;
import trufflesom.compiler.Variable.Argument;
import trufflesom.compiler.Variable.Local;
import trufflesom.interpreter.Method;
import trufflesom.interpreter.bc.Bytecodes;
import trufflesom.interpreter.nodes.ArgumentReadNode.LocalArgumentReadNode;
import trufflesom.interpreter.nodes.ExpressionNode;
Expand Down Expand Up @@ -326,7 +332,7 @@ public void updateLiteral(final SAbstractObject oldVal, final byte index,
literals.set(index, newVal);
}

private byte getPositionIn(final Local local, final LinkedHashMap<SSymbol, Local> map) {
private byte getPositionIn(final Variable local, final LinkedHashMap<SSymbol, Local> map) {
byte i = 0;
for (Local l : map.values()) {
if (l.equals(local)) {
Expand All @@ -337,6 +343,10 @@ private byte getPositionIn(final Local local, final LinkedHashMap<SSymbol, Local
return -1;
}

public byte getVarIndex(final Variable var) {
return getPositionIn(var, localAndOuterVars);
}

/**
* Record the access, and also manage the tracking of outer access.
*/
Expand Down Expand Up @@ -373,13 +383,7 @@ private BytecodeLoopNode constructBytecodeBody(final SourceSection sourceSection
byte[] bytecodes = getBytecodeArray();

Object[] literalsArr = literals.toArray();
FrameSlot[] localsAndOuters = new FrameSlot[localAndOuterVars.size()];

int i = 0;
for (Local l : localAndOuterVars.values()) {
localsAndOuters[i] = l.getSlot();
i += 1;
}
Local[] localsAndOuters = localAndOuterVars.values().toArray(new Local[0]);

FrameSlot frameOnStackMarker =
throwsNonLocalReturn ? getFrameOnStackMarker(sourceSection).getSlot() : null;
Expand All @@ -388,7 +392,7 @@ private BytecodeLoopNode constructBytecodeBody(final SourceSection sourceSection

return new BytecodeLoopNode(
bytecodes, locals.size(), localsAndOuters, literalsArr, maxStackDepth,
frameOnStackMarker, loops, universe);
frameOnStackMarker, loops, currentScope, universe);
}

public byte[] getBytecodeArray() {
Expand Down Expand Up @@ -958,6 +962,50 @@ public boolean inlineAndOr(final ParserBc parser, final boolean isOr) throws Par
return true;
}

public boolean inlineToDo(final ParserBc parser) throws ParseError {
// HACK: We do assume that the receiver on the stack is a integer,
// HACK: similar to the other inlined messages.
// HACK: We don't support anything but integer at the moment.
byte pushBlockCandidate = lastBytecodeIsOneOf(0, PUSH_BLOCK_BYTECODES);
if (pushBlockCandidate == INVALID) {
return false;
}

assert getBytecodeLength(pushBlockCandidate) == 2;
byte blockLiteralIdx = bytecode.get(bytecode.size() - 1);
SMethod toBeInlined = (SMethod) literals.get(blockLiteralIdx);
Method toBeInlinedMethod = (Method) toBeInlined.getInvokable();

removeLastBytecodes(1);

isCurrentlyInliningBlock = true;

emitDUPSECOND(this);

int loopBeginIdx = offsetOfNextInstruction();
int jumpOffsetIdxToEnd = emitJumpIfGreaterWithDummyOffset(this);

emitDUP(this);

toBeInlinedMethod.mergeScopeInto(this, toBeInlined);

Argument blockArg = (Argument) toBeInlinedMethod.getScope().getVariables()[1];

emitPOPLOCAL(this, getVarIndex(blockArg), (byte) 0);

toBeInlinedMethod.inlineScopeAlreadyMerged(this, toBeInlined);

emitPOP(this);
emitINC(this);

emitBackwardsJumpOffsetToTarget(loopBeginIdx, parser);
patchJumpOffsetToPointToNextInstruction(jumpOffsetIdxToEnd, parser);

isCurrentlyInliningBlock = false;

return true;
}

public boolean inlineWhileTrueOrFalse(final ParserBc parser, final boolean isWhileTrue)
throws ParseError {
if (!hasTwoLiteralBlockArguments()) {
Expand Down
6 changes: 5 additions & 1 deletion src/trufflesom/compiler/bc/Disassembler.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,13 @@
import static trufflesom.interpreter.bc.Bytecodes.JUMP;
import static trufflesom.interpreter.bc.Bytecodes.JUMP2;
import static trufflesom.interpreter.bc.Bytecodes.JUMP2_BACKWARDS;
import static trufflesom.interpreter.bc.Bytecodes.JUMP2_IF_GREATER;
import static trufflesom.interpreter.bc.Bytecodes.JUMP2_ON_FALSE_POP;
import static trufflesom.interpreter.bc.Bytecodes.JUMP2_ON_FALSE_TOP_NIL;
import static trufflesom.interpreter.bc.Bytecodes.JUMP2_ON_TRUE_POP;
import static trufflesom.interpreter.bc.Bytecodes.JUMP2_ON_TRUE_TOP_NIL;
import static trufflesom.interpreter.bc.Bytecodes.JUMP_BACKWARDS;
import static trufflesom.interpreter.bc.Bytecodes.JUMP_IF_GREATER;
import static trufflesom.interpreter.bc.Bytecodes.JUMP_ON_FALSE_POP;
import static trufflesom.interpreter.bc.Bytecodes.JUMP_ON_FALSE_TOP_NIL;
import static trufflesom.interpreter.bc.Bytecodes.JUMP_ON_TRUE_POP;
Expand Down Expand Up @@ -249,11 +251,13 @@ public static void dumpMethod(final List<Byte> bytecodes, final String indent,
case JUMP_ON_FALSE_TOP_NIL:
case JUMP_ON_TRUE_POP:
case JUMP_ON_FALSE_POP:
case JUMP_IF_GREATER:
case JUMP2:
case JUMP2_ON_TRUE_TOP_NIL:
case JUMP2_ON_FALSE_TOP_NIL:
case JUMP2_ON_TRUE_POP:
case JUMP2_ON_FALSE_POP: {
case JUMP2_ON_FALSE_POP:
case JUMP2_IF_GREATER: {
int offset = getJumpOffset(bytecodes.get(b + 1), bytecodes.get(b + 2));

Universe.errorPrintln(
Expand Down
7 changes: 7 additions & 0 deletions src/trufflesom/interpreter/LexicalScope.java
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,13 @@ public Variable[] getVariables() {
return variables;
}

public Variable getVariable(final int idx, final int ctxLevel) {
if (ctxLevel == 0) {
return variables[idx];
}
return outerScope.getVariable(idx, ctxLevel - 1);
}

@Override
public LexicalScope getScope(final Method method) {
if (method.equals(this.method)) {
Expand Down
10 changes: 10 additions & 0 deletions src/trufflesom/interpreter/Method.java
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,16 @@ public ExpressionNode inline(final MethodGenerationContext mgenc,
getLanguage(SomLanguage.class));
}

public void mergeScopeInto(final MethodGenerationContext mgenc, final SMethod toBeInlined) {
mgenc.mergeIntoScope(currentLexicalScope, toBeInlined);
}

public ExpressionNode inlineScopeAlreadyMerged(final MethodGenerationContext mgenc,
final SMethod toBeInlined) {
return ScopeAdaptationVisitor.adapt(uninitializedBody, mgenc, 0, true,
getLanguage(SomLanguage.class));
}

@Override
public boolean isTrivial() {
if (currentLexicalScope.isBlock()) {
Expand Down
Loading