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

Replace interpreter with partial evaluation #38

Open
wants to merge 27 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
4467331
Implement foundations of partial evaluation
viluon May 6, 2020
c6f5968
Throw on tail call
viluon May 6, 2020
4872a40
Fix incorrect stack frame accesses
viluon May 6, 2020
008fb92
Fix benchmark outputs
viluon May 6, 2020
5e69438
Refactor to use continuations
viluon May 6, 2020
52a961e
Support tail calls; Add basic profiling
viluon May 7, 2020
b594c7e
Lift branches out of lambdas
viluon May 7, 2020
24713e0
Specialise for loops
viluon May 7, 2020
9ffc493
Refactor Print; Avoid heavy closures
viluon May 7, 2020
c692efd
Fix for loop performance regression
viluon May 7, 2020
7caa48a
Add a workaround for incorrect PC treatment
viluon May 7, 2020
b34d919
Pass jumps in continuations
viluon May 8, 2020
ad7b12b
Avoid extraneous indirections
viluon May 8, 2020
0e23fd3
Revert "Avoid extraneous indirections"
viluon May 8, 2020
2489957
Fix incorrect assumption about debug state caching
viluon May 8, 2020
7e75b16
Fix orphaned thread memory leak
viluon May 8, 2020
8a98183
Fix global variable access
viluon May 9, 2020
cdfde22
Lift conditionals out of arithmetic instructions
viluon May 9, 2020
22ffbb0
Evaluate target FORLOOPs in FORPREPs
viluon May 9, 2020
cbf6884
Cache decoded parameters of NEWTABLE
viluon May 9, 2020
b712c52
Revert "Evaluate target FORLOOPs in FORPREPs"
viluon May 9, 2020
5fd9b71
Clean up
viluon May 9, 2020
c097657
Obliterate generic parameter
viluon May 9, 2020
c64fb09
Annihilate instruction hit counter
viluon May 9, 2020
518bc1b
Exterminate compiledInstr bit set
viluon May 9, 2020
4f5ed3d
Use a singleton continuation object
viluon May 9, 2020
ac6810d
Trim method signatures
viluon May 10, 2020
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
3 changes: 1 addition & 2 deletions src/main/java/org/squiddev/cobalt/LuaState.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@

import java.io.InputStream;
import java.io.PrintStream;
import java.util.Random;
import java.util.TimeZone;
import java.util.*;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
Expand Down
155 changes: 85 additions & 70 deletions src/main/java/org/squiddev/cobalt/Print.java
Original file line number Diff line number Diff line change
Expand Up @@ -88,65 +88,61 @@ public class Print {
};


static void printString(PrintStream ps, final LuaString s) {

ps.print('"');
static void showString(StringBuilder sb, final LuaString s) {
sb.append('"');
for (int i = 0, n = s.length; i < n; i++) {
int c = s.bytes[s.offset + i];
if (c >= ' ' && c <= '~' && c != '\"' && c != '\\') {
ps.print((char) c);
sb.append((char) c);
} else {
switch (c) {
case '"':
ps.print("\\\"");
sb.append("\\\"");
break;
case '\\':
ps.print("\\\\");
sb.append("\\\\");
break;
case 0x0007: /* bell */
ps.print("\\a");
sb.append("\\a");
break;
case '\b': /* backspace */
ps.print("\\b");
sb.append("\\b");
break;
case '\f': /* form feed */
ps.print("\\f");
sb.append("\\f");
break;
case '\t': /* tab */
ps.print("\\t");
sb.append("\\t");
break;
case '\r': /* carriage return */
ps.print("\\r");
sb.append("\\r");
break;
case '\n': /* newline */
ps.print("\\n");
sb.append("\\n");
break;
case 0x000B: /* vertical tab */
ps.print("\\v");
sb.append("\\v");
break;
default:
ps.print('\\');
ps.print(Integer.toString(1000 + 0xff & c).substring(1));
sb.append('\\');
sb.append(Integer.toString(1000 + 0xff & c).substring(1));
break;
}
}
}
ps.print('"');
sb.append('"');
}

static void printValue(PrintStream ps, LuaValue v) {
switch (v.type()) {
case Constants.TSTRING:
printString(ps, (LuaString) v);
break;
default:
ps.print(v.toString());

static void showValue(StringBuilder sb, LuaValue v) {
if (v.type() == Constants.TSTRING) {
showString(sb, (LuaString) v);
} else {
sb.append(v.toString());
}
}

static void printConstant(PrintStream ps, Prototype f, int i) {
printValue(ps, f.k[i]);
static void showConstant(StringBuilder sb, Prototype f, int i) {
showValue(sb, f.k[i]);
}

/**
Expand All @@ -155,11 +151,21 @@ static void printConstant(PrintStream ps, Prototype f, int i) {
* @param f the {@link Prototype}
*/
public static void printCode(Prototype f) {
ps.print(showCode(f));
}

public static String showCode(Prototype f) {
final StringBuilder sb = new StringBuilder();
showCode(sb, f);
return sb.toString();
}

public static void showCode(StringBuilder sb, Prototype f) {
int[] code = f.code;
int pc, n = code.length;
for (pc = 0; pc < n; pc++) {
printOpCode(f, pc);
ps.println();
showOpCode(sb, f, pc);
sb.append(System.lineSeparator());
}
}

Expand All @@ -170,17 +176,19 @@ public static void printCode(Prototype f) {
* @param pc the program counter to look up and print
*/
public static void printOpCode(Prototype f, int pc) {
printOpCode(ps, f, pc);
final StringBuilder sb = new StringBuilder();
showOpCode(sb, f, pc);
ps.print(sb);
}

/**
* Print an opcode in a prototype
*
* @param ps the {@link PrintStream} to print to
* @param sb the {@link StringBuilder} to print to
* @param f the {@link Prototype}
* @param pc the program counter to look up and print
*/
public static void printOpCode(PrintStream ps, Prototype f, int pc) {
public static void showOpCode(StringBuilder sb, Prototype f, int pc) {
int[] code = f.code;
int i = code[pc];
int o = GET_OPCODE(i);
Expand All @@ -190,62 +198,61 @@ public static void printOpCode(PrintStream ps, Prototype f, int pc) {
int bx = GETARG_Bx(i);
int sbx = GETARG_sBx(i);
int line = getline(f, pc);
ps.print(" " + (pc + 1) + " ");
sb.append(' ');
sb.append(f.compiledInstrs[pc] != null ? 'c' : ' ');
sb.append(pc + 1).append(" ");
if (line > 0) {
ps.print("[" + line + "] ");
sb.append("[").append(line).append("] ");
} else {
ps.print("[-] ");
sb.append("[-] ");
}
ps.print(OPNAMES[o] + " ");
sb.append(OPNAMES[o]).append(" ");
switch (getOpMode(o)) {
case iABC:
ps.print(a);
sb.append(a);
if (getBMode(o) != OpArgN) {
ps.print(" " + (ISK(b) ? (-1 - INDEXK(b)) : b));
sb.append(" ").append(ISK(b) ? (-1 - INDEXK(b)) : b);
}
if (getCMode(o) != OpArgN) {
ps.print(" " + (ISK(c) ? (-1 - INDEXK(c)) : c));
sb.append(" ").append(ISK(c) ? (-1 - INDEXK(c)) : c);
}
break;
case iABx:
if (getBMode(o) == OpArgK) {
ps.print(a + " " + (-1 - bx));
sb.append(a).append(" ").append(-1 - bx);
} else {
ps.print(a + " " + (bx));
sb.append(a).append(" ").append(bx);
}
break;
case iAsBx:
if (o == OP_JMP) {
ps.print(sbx);
sb.append(sbx);
} else {
ps.print(a + " " + sbx);
sb.append(a).append(" ").append(sbx);
}
break;
}
switch (o) {
case OP_LOADK:
ps.print(" ; ");
printConstant(ps, f, bx);
case OP_GETGLOBAL:
case OP_SETGLOBAL:
sb.append(" ; ");
showConstant(sb, f, bx);
break;
case OP_GETUPVAL:
case OP_SETUPVAL:
ps.print(" ; ");
sb.append(" ; ");
if (f.upvalues.length > b) {
printValue(ps, f.upvalues[b]);
showValue(sb, f.upvalues[b]);
} else {
ps.print("-");
sb.append("-");
}
break;
case OP_GETGLOBAL:
case OP_SETGLOBAL:
ps.print(" ; ");
printConstant(ps, f, bx);
break;
case OP_GETTABLE:
case OP_SELF:
if (ISK(c)) {
ps.print(" ; ");
printConstant(ps, f, INDEXK(c));
sb.append(" ; ");
showConstant(sb, f, INDEXK(c));
}
break;
case OP_SETTABLE:
Expand All @@ -258,45 +265,51 @@ public static void printOpCode(PrintStream ps, Prototype f, int pc) {
case OP_LT:
case OP_LE:
if (ISK(b) || ISK(c)) {
ps.print(" ; ");
sb.append(" ; ");
if (ISK(b)) {
printConstant(ps, f, INDEXK(b));
showConstant(sb, f, INDEXK(b));
} else {
ps.print("-");
sb.append("-");
}
ps.print(" ");
sb.append(" ");
if (ISK(c)) {
printConstant(ps, f, INDEXK(c));
showConstant(sb, f, INDEXK(c));
} else {
ps.print("-");
sb.append("-");
}
}
break;
case OP_JMP:
case OP_FORLOOP:
case OP_FORPREP:
ps.print(" ; to " + (sbx + pc + 2));
sb.append(" ; to ").append(sbx + pc + 2);
break;
case OP_CLOSURE:
ps.print(" ; " + f.p[bx].getClass().getName());
sb.append(" ; ").append(f.p[bx].getClass().getName());
break;
case OP_SETLIST:
if (c == 0) {
ps.print(" ; " + code[++pc]);
sb.append(" ; ").append(code[++pc]);
} else {
ps.print(" ; " + c);
sb.append(" ; ").append(c);
}
break;
case OP_VARARG:
ps.print(" ; is_vararg=" + f.is_vararg);
sb.append(" ; is_vararg=").append(f.is_vararg);
break;
default:
break;
}
}

public static String showOpCode(Prototype f, int pc) {
final StringBuilder sb = new StringBuilder();
showOpCode(sb, f, pc);
return sb.toString();
}

private static int getline(Prototype f, int pc) {
return pc > 0 && f.lineinfo != null && pc < f.lineinfo.length ? f.lineinfo[pc] : -1;
return pc >= 0 && f.lineinfo != null && pc < f.lineinfo.length ? f.lineinfo[pc] : -1;
}

static void printHeader(Prototype f) {
Expand All @@ -320,12 +333,14 @@ static void printHeader(Prototype f) {

static void printConstants(Prototype f) {
int i, n = f.k.length;
ps.print("constants (" + n + ") for " + id(f) + ":\n");
final StringBuilder sb = new StringBuilder();
sb.append("constants (").append(n).append(") for ").append(id(f)).append(":\n");
for (i = 0; i < n; i++) {
ps.print(" " + (i + 1) + " ");
printValue(ps, f.k[i]);
ps.print("\n");
sb.append(" ").append(i + 1).append(" ");
showValue(sb, f.k[i]);
sb.append("\n");
}
ps.print(sb.toString());
}

static void printLocals(Prototype f) {
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/org/squiddev/cobalt/Prototype.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

import org.squiddev.cobalt.function.LocalVariable;
import org.squiddev.cobalt.function.LuaInterpretedFunction;
import org.squiddev.cobalt.function.UnwindableCallable;

import static org.squiddev.cobalt.compiler.LoadState.getShortName;

Expand All @@ -44,6 +45,7 @@ public final class Prototype {
/* constants used by the function */
public LuaValue[] k;
public int[] code;
public UnwindableCallable[] compiledInstrs;
/* functions defined inside the function */
public Prototype[] p;
/* map from opcodes to source lines */
Expand Down
16 changes: 14 additions & 2 deletions src/main/java/org/squiddev/cobalt/compiler/BytecodeLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,25 @@
*/
package org.squiddev.cobalt.compiler;

import org.squiddev.cobalt.*;
import org.squiddev.cobalt.Constants;
import org.squiddev.cobalt.LuaDouble;
import org.squiddev.cobalt.LuaInteger;
import org.squiddev.cobalt.LuaString;
import org.squiddev.cobalt.LuaValue;
import org.squiddev.cobalt.Prototype;
import org.squiddev.cobalt.ValueFactory;
import org.squiddev.cobalt.function.LocalVariable;
import org.squiddev.cobalt.function.UnwindableCallable;

import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;

import static org.squiddev.cobalt.Constants.*;
import static org.squiddev.cobalt.Constants.TBOOLEAN;
import static org.squiddev.cobalt.Constants.TINT;
import static org.squiddev.cobalt.Constants.TNIL;
import static org.squiddev.cobalt.Constants.TNUMBER;
import static org.squiddev.cobalt.Constants.TSTRING;

/**
* Parser for bytecode
Expand Down Expand Up @@ -293,6 +304,7 @@ public Prototype loadFunction(LuaString p) throws IOException {
f.is_vararg = is.readUnsignedByte();
f.maxstacksize = is.readUnsignedByte();
f.code = loadIntArray();
f.compiledInstrs = new UnwindableCallable[f.code.length];
loadConstants(f);
loadDebug(f);

Expand Down
Loading