Skip to content

Commit

Permalink
WIP - immutable Instruction
Browse files Browse the repository at this point in the history
  • Loading branch information
andreaTP committed Aug 19, 2024
1 parent 88151d2 commit cb8172b
Show file tree
Hide file tree
Showing 6 changed files with 227 additions and 104 deletions.
69 changes: 38 additions & 31 deletions aot/src/main/java/com/dylibso/chicory/aot/AotMachine.java
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,12 @@
public final class AotMachine implements Machine {

public static final String DEFAULT_CLASS_NAME = "com.dylibso.chicory.$gen.CompiledModule";
private static final Instruction FUNCTION_SCOPE = new Instruction(-1, OpCode.NOP, new long[0]);
private static final Instruction FUNCTION_SCOPE =
Instruction.builder()
.withAddress(-1)
.withOpcode(OpCode.NOP)
.withOperands(new long[0])
.build();

private final Module module;
private final Instance instance;
Expand Down Expand Up @@ -642,17 +647,15 @@ private void compileBody(
// allocate labels for all label targets
Map<Integer, Label> labels = new HashMap<>();
for (Instruction ins : body.instructions()) {
if (ins.labelTrue() != null) {
labels.put(ins.labelTrue(), new Label());
}
if (ins.labelFalse() != null) {
labels.put(ins.labelFalse(), new Label());
}
if (ins.labelTable() != null) {
for (int label : ins.labelTable()) {
labels.put(label, new Label());
}
}
ins.labelTrue().ifPresent(l -> labels.put(l, new Label()));
ins.labelFalse().ifPresent(l -> labels.put(l, new Label()));
ins.labelTable()
.ifPresent(
l -> {
for (int label : l) {
labels.put(label, new Label());
}
});
}

// fake instruction to use for the function's implicit block
Expand Down Expand Up @@ -688,10 +691,10 @@ private void compileBody(
break;
case BLOCK:
case LOOP:
ctx.enterScope(ins.scope(), blockType(ins));
ctx.enterScope(ins.scope().get(), blockType(ins));
break;
case END:
ctx.exitScope(ins.scope());
ctx.exitScope(ins.scope().get());
break;
case UNREACHABLE:
exitBlockDepth = ins.depth();
Expand All @@ -704,55 +707,59 @@ private void compileBody(
break;
case IF:
ctx.popStackSize();
ctx.enterScope(ins.scope(), blockType(ins));
asm.visitJumpInsn(Opcodes.IFEQ, labels.get(ins.labelFalse()));
ctx.enterScope(ins.scope().get(), blockType(ins));
asm.visitJumpInsn(Opcodes.IFEQ, labels.get(ins.labelFalse().get()));
// use the same starting stack sizes for both sides of the branch
if (body.instructions().get(ins.labelFalse() - 1).opcode() == OpCode.ELSE) {
if (body.instructions().get(ins.labelFalse().get() - 1).opcode()
== OpCode.ELSE) {
ctx.pushStackSizesStack();
}
break;
case ELSE:
asm.visitJumpInsn(Opcodes.GOTO, labels.get(ins.labelTrue()));
asm.visitJumpInsn(Opcodes.GOTO, labels.get(ins.labelTrue().get()));
ctx.popStackSizesStack();
break;
case BR:
exitBlockDepth = ins.depth();
if (ins.labelTrue() < idx) {
if (ins.labelTrue().get() < idx) {
emitInvokeStatic(asm, CHECK_INTERRUPTION);
}
emitUnwindStack(asm, type, body, ins, ins.labelTrue(), ctx);
asm.visitJumpInsn(Opcodes.GOTO, labels.get(ins.labelTrue()));
emitUnwindStack(asm, type, body, ins, ins.labelTrue().get(), ctx);
asm.visitJumpInsn(Opcodes.GOTO, labels.get(ins.labelTrue().get()));
break;
case BR_IF:
ctx.popStackSize();
Label falseLabel = new Label();
asm.visitJumpInsn(Opcodes.IFEQ, falseLabel);
if (ins.labelTrue() < idx) {
if (ins.labelTrue().get() < idx) {
emitInvokeStatic(asm, CHECK_INTERRUPTION);
}
emitUnwindStack(asm, type, body, ins, ins.labelTrue(), ctx);
asm.visitJumpInsn(Opcodes.GOTO, labels.get(ins.labelTrue()));
emitUnwindStack(asm, type, body, ins, ins.labelTrue().get(), ctx);
asm.visitJumpInsn(Opcodes.GOTO, labels.get(ins.labelTrue().get()));
asm.visitLabel(falseLabel);
break;
case BR_TABLE:
exitBlockDepth = ins.depth();
ctx.popStackSize();
emitInvokeStatic(asm, CHECK_INTERRUPTION);
// skip table switch if it only has a default
if (ins.labelTable().length == 1) {
if (ins.labelTable().get().size() == 1) {
asm.visitInsn(Opcodes.POP);
emitUnwindStack(asm, type, body, ins, ins.labelTable()[0], ctx);
asm.visitJumpInsn(Opcodes.GOTO, labels.get(ins.labelTable()[0]));
emitUnwindStack(asm, type, body, ins, ins.labelTable().get().get(0), ctx);
asm.visitJumpInsn(Opcodes.GOTO, labels.get(ins.labelTable().get().get(0)));
break;
}
// collect unique target labels
Map<Integer, Label> targets = new HashMap<>();
Label[] table = new Label[ins.labelTable().length - 1];
Label[] table = new Label[ins.labelTable().get().size() - 1];
for (int i = 0; i < table.length; i++) {
table[i] = targets.computeIfAbsent(ins.labelTable()[i], x -> new Label());
table[i] =
targets.computeIfAbsent(
ins.labelTable().get().get(i), x -> new Label());
}
// table switch using the last entry of the label table as the default
int defaultTarget = ins.labelTable()[ins.labelTable().length - 1];
int defaultTarget =
ins.labelTable().get().get(ins.labelTable().get().size() - 1);
Label defaultLabel = targets.computeIfAbsent(defaultTarget, x -> new Label());
asm.visitTableSwitchInsn(0, table.length - 1, defaultLabel, table);
// generate separate unwinds for each target
Expand Down Expand Up @@ -814,7 +821,7 @@ private void emitUnwindStack(
target = body.instructions().get(label - 1);
forward = false;
}
var scope = target.scope();
var scope = target.scope().get();

FunctionType blockType;
if (scope.opcode() == OpCode.END) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ static void eval(MStack stack, Instance instance, ArrayDeque<StackFrame> callSta
IF(frame, stack, instance, instruction);
break;
case ELSE:
frame.jumpTo(instruction.labelTrue());
frame.jumpTo(instruction.labelTrue().get());
break;
case BR:
BR(frame, stack, instruction);
Expand Down Expand Up @@ -1883,7 +1883,10 @@ private static void IF(
var returnsSize = numberOfValuesToReturn(instance, instruction);
frame.pushCtrl(instruction.opcode(), paramsSize, returnsSize, stack.size() - paramsSize);

frame.jumpTo(predValue.asInt() == 0 ? instruction.labelFalse() : instruction.labelTrue());
frame.jumpTo(
predValue.asInt() == 0
? instruction.labelFalse().get()
: instruction.labelTrue().get());
}

private static void ctrlJump(StackFrame frame, MStack stack, int n) {
Expand All @@ -1898,7 +1901,7 @@ private static void ctrlJump(StackFrame frame, MStack stack, int n) {
private static void BR(StackFrame frame, MStack stack, Instruction instruction) {
checkInterruption();
ctrlJump(frame, stack, (int) instruction.operands()[0]);
frame.jumpTo(instruction.labelTrue());
frame.jumpTo(instruction.labelTrue().get());
}

private static void BR_TABLE(StackFrame frame, MStack stack, Instruction instruction) {
Expand All @@ -1909,10 +1912,10 @@ private static void BR_TABLE(StackFrame frame, MStack stack, Instruction instruc
if (pred < 0 || pred >= defaultIdx) {
// choose default
ctrlJump(frame, stack, (int) instruction.operands()[defaultIdx]);
frame.jumpTo(instruction.labelTable()[defaultIdx]);
frame.jumpTo(instruction.labelTable().get().get(defaultIdx));
} else {
ctrlJump(frame, stack, (int) instruction.operands()[pred]);
frame.jumpTo(instruction.labelTable()[pred]);
frame.jumpTo(instruction.labelTable().get().get(pred));
}
}

Expand All @@ -1921,10 +1924,13 @@ private static void BR_IF(StackFrame frame, MStack stack, Instruction instructio
var pred = predValue.asInt();

if (pred == 0) {
frame.jumpTo(instruction.labelFalse());
frame.jumpTo(instruction.labelFalse().get());
} else {
ctrlJump(frame, stack, (int) instruction.operands()[0]);
frame.jumpTo(instruction.labelTrue());
if (instruction.labelTrue().isEmpty()) {
System.out.println("debug me");
}
frame.jumpTo(instruction.labelTrue().get());
}
}

Expand Down
13 changes: 7 additions & 6 deletions wasm/src/main/java/com/dylibso/chicory/wasm/ControlTree.java
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
* </pre>
*/
final class ControlTree {
private final Instruction instruction;
private final Instruction.Builder instruction;
private final int initialInstructionNumber;
private int finalInstructionNumber = -1; // to be set when END is reached
private final ControlTree parent;
Expand All @@ -66,15 +66,16 @@ public ControlTree() {
this.callbacks = new ArrayList<>();
}

private ControlTree(int initialInstructionNumber, Instruction instruction, ControlTree parent) {
private ControlTree(
int initialInstructionNumber, Instruction.Builder instruction, ControlTree parent) {
this.instruction = instruction;
this.initialInstructionNumber = initialInstructionNumber;
this.parent = parent;
this.nested = new ArrayList<>();
this.callbacks = new ArrayList<>();
}

public ControlTree spawn(int initialInstructionNumber, Instruction instruction) {
public ControlTree spawn(int initialInstructionNumber, Instruction.Builder instruction) {
var node = new ControlTree(initialInstructionNumber, instruction, this);
this.addNested(node);
return node;
Expand All @@ -84,7 +85,7 @@ public boolean isRoot() {
return this.parent == null;
}

public Instruction instruction() {
public Instruction.Builder instruction() {
return instruction;
}

Expand All @@ -108,10 +109,10 @@ public void addCallback(Consumer<Integer> callback) {
this.callbacks.add(callback);
}

public void setFinalInstructionNumber(int finalInstructionNumber, Instruction end) {
public void setFinalInstructionNumber(int finalInstructionNumber, Instruction.Builder end) {
this.finalInstructionNumber = finalInstructionNumber;

if (end.scope().opcode() == OpCode.LOOP) {
if (end.scope().isPresent() && end.scope().get().opcode() == OpCode.LOOP) {
var lastLoopInstruction = 0;
for (var ct : this.parent.nested) {
if (ct.instruction().opcode() == OpCode.LOOP) {
Expand Down
Loading

0 comments on commit cb8172b

Please sign in to comment.