Skip to content
This repository has been archived by the owner on Apr 19, 2019. It is now read-only.

Commit

Permalink
Merge branch 'master' into cobalt
Browse files Browse the repository at this point in the history
  • Loading branch information
SquidDev committed Aug 29, 2016
2 parents 0bbcd8b + 54ec899 commit 13e88b3
Show file tree
Hide file tree
Showing 8 changed files with 881 additions and 13 deletions.
49 changes: 48 additions & 1 deletion src/main/java/org/squiddev/cobalt/luajc/CompileOptions.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,16 @@ public class CompileOptions {
*/
public static final int THRESHOLD = 10;

/**
* Default value for {@link #maximumCount}
*/
public static final int MAXIMUM_COUNT = 2000;

/**
* Default value for {@link #threadedThreshold}
*/
public static final int THREADED_THRESHOLD = 500;

/**
* The prefix for all classes in slash form
*/
Expand All @@ -31,6 +41,20 @@ public class CompileOptions {
*/
public final int compileThreshold;

/**
* Maximum number of instructions that can be compiled.
* This is to prevent there being more than 16384 (64kb) Java instructions.
* Set to 0 or less to have no maximum.
*/
public final int maximumCount;

/**
* Number of instructions before compilation is delegated to a thread.
* This prevents delays when compiling.
* Set to 0 or less to never delegate in a thread.
*/
public final int threadedThreshold;

/**
* Verify the compiled sources
* This helps debug but will slow down compilation massively
Expand All @@ -54,12 +78,35 @@ public class CompileOptions {
public CompileOptions(String prefix, int compileThreshold, boolean verify, ErrorHandler handler) {
this.prefix = prefix;
this.compileThreshold = compileThreshold;
this.maximumCount = MAXIMUM_COUNT;
this.threadedThreshold = THREADED_THRESHOLD;
this.verify = verify;
this.handler = handler;
dotPrefix = prefix.replace('/', '.');
}


/**
* Create a new compilation options
*
* @param prefix Set {@link #prefix}. The default is {@link #PREFIX}.
* @param compileThreshold Set {@link #compileThreshold}. The default is {@link #THRESHOLD}.
* @param maximumCount Set {@link #maximumCount}. The default is {@link #MAXIMUM_COUNT}
* @param threadedThreshold Set {@link #threadedThreshold}. The default is {@link #THREADED_THRESHOLD}.
* @param verify Set {@link #verify}. The default is true.
* @param handler Set {@link #handler}. The default is {@code null}.
*/
public CompileOptions(String prefix, int compileThreshold, int maximumCount, int threadedThreshold, boolean verify, ErrorHandler handler) {
this.prefix = prefix;
this.compileThreshold = compileThreshold;
this.maximumCount = maximumCount;
this.threadedThreshold = threadedThreshold;
this.verify = verify;
this.handler = handler;
dotPrefix = prefix.replace('/', '.');
}

public CompileOptions() {
this(PREFIX, THRESHOLD, true, null);
this(PREFIX, THRESHOLD, MAXIMUM_COUNT, THREADED_THRESHOLD, true, null);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@

import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.util.List;

/**
* Prototype information for static single-assignment analysis
Expand Down Expand Up @@ -103,8 +102,6 @@ public final class ProtoInfo {
* List of upvalues from outer scope
*/
public final UpvalueInfo[] upvalues;

public final List<PhiInfo> phis;
//endregion

public ProtoInfo(Prototype p, JavaLoader loader) {
Expand All @@ -129,7 +126,7 @@ protected ProtoInfo(Prototype p, JavaLoader loader, String name, UpvalueInfo[] u

AnalysisBuilder builder = new AnalysisBuilder(this);
builder.fillArguments();
phis = builder.findVariables();
builder.findVariables();
builder.findUpvalues();

if (loader.options.compileThreshold <= 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,33 @@ public FunctionWrapper load(LuaTable env, Prototype prototype) throws Exception
return new FunctionWrapper(info, env);
}

public FunctionExecutor include(JavaGen jg) throws Exception {
private FunctionExecutor include(JavaGen jg) throws Exception {
String wholeName = options.dotPrefix + name.replace('/', '.') + jg.prototype.name;

Class<?> klass = defineClass(wholeName, jg.bytecode);
return (FunctionExecutor) klass.getConstructor().newInstance();
}

/**
* Compile the prototype and set its executor
*
* @param info The prototype to compile
* @return The compiled executor (the result or {@link ProtoInfo#executor}).
*/
public FunctionExecutor include(ProtoInfo info) {
int length = info.prototype.code.length;
if (options.maximumCount > 0 && length >= options.maximumCount) {
return info.executor = FallbackExecutor.INSTANCE;
} else if (options.threadedThreshold > 0 && length >= options.threadedThreshold) {
info.executor = FallbackExecutor.INSTANCE;
ThreadedCompilation.scheduleCompilation(info, this);
return FallbackExecutor.INSTANCE;
} else {
return info.executor = includeImpl(info);
}
}

FunctionExecutor includeImpl(ProtoInfo info) {
try {
return include(new JavaGen(info, this, filename));
} catch (RuntimeException e) {
Expand All @@ -83,7 +102,7 @@ public FunctionExecutor include(ProtoInfo info) {
}
}

protected Class<?> defineClass(String className, byte[] bytes) {
private Class<?> defineClass(String className, byte[] bytes) {
if (options.verify) AsmUtils.validateClass(bytes, this);
return defineClass(className, bytes, 0, bytes.length);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package org.squiddev.cobalt.luajc.compilation;

import org.squiddev.cobalt.luajc.analysis.ProtoInfo;

import java.lang.ref.WeakReference;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;

/**
* Delegates compilation into a separate thread
*/
public class ThreadedCompilation {
private static int THREAD_PRIORITY = Thread.MIN_PRIORITY + (Thread.NORM_PRIORITY - Thread.MIN_PRIORITY) / 2;
private static int THREADS = 1;

private static ScheduledExecutorService createThread(String name, int threads) {
final String prefix = "luaj.luajc-" + name + "-";
final AtomicInteger counter = new AtomicInteger(1);

SecurityManager manager = System.getSecurityManager();
final ThreadGroup group = manager == null ? Thread.currentThread().getThreadGroup() : manager.getThreadGroup();
return Executors.newScheduledThreadPool(threads, new ThreadFactory() {
@Override
public Thread newThread(Runnable runnable) {
Thread thread = new Thread(group, runnable, prefix + counter.getAndIncrement());
if (!thread.isDaemon()) thread.setDaemon(true);
if (thread.getPriority() != THREAD_PRIORITY) thread.setPriority(THREAD_PRIORITY);

return thread;
}
});
}

private static final ScheduledExecutorService COMPILATION_THREAD = createThread("compiler", THREADS);

public static void scheduleCompilation(ProtoInfo info, JavaLoader loader) {
final WeakReference<ProtoInfo> infoRef = new WeakReference<ProtoInfo>(info);
final WeakReference<JavaLoader> loaderRef = new WeakReference<JavaLoader>(loader);

COMPILATION_THREAD.submit(new Runnable() {
@Override
public void run() {
ProtoInfo info = infoRef.get();
JavaLoader loader = loaderRef.get();
if (info == null || loader == null) return;

info.executor = loader.includeImpl(info);
}
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public final class ClosureExecutor extends FunctionExecutor {
public final LuaValue execute(LuaState state, FunctionWrapper function) {
ProtoInfo info = function.info;
if (++info.calledClosure >= info.threshold) {
FunctionExecutor executor = info.executor = info.loader.include(info);
FunctionExecutor executor = info.loader.include(info);
return executor.execute(state, function);
}

Expand All @@ -40,7 +40,7 @@ public final LuaValue execute(LuaState state, FunctionWrapper function) {
public final LuaValue execute(LuaState state, FunctionWrapper function, LuaValue arg) {
ProtoInfo info = function.info;
if (++info.calledClosure >= info.threshold) {
FunctionExecutor executor = info.executor = info.loader.include(info);
FunctionExecutor executor = info.loader.include(info);
return executor.execute(state, function, arg);
}

Expand All @@ -63,7 +63,7 @@ public final LuaValue execute(LuaState state, FunctionWrapper function, LuaValue
public final LuaValue execute(LuaState state, FunctionWrapper function, LuaValue arg1, LuaValue arg2) {
ProtoInfo info = function.info;
if (++info.calledClosure >= info.threshold) {
FunctionExecutor executor = info.executor = info.loader.include(info);
FunctionExecutor executor = info.loader.include(info);
return executor.execute(state, function, arg1, arg2);
}

Expand All @@ -90,7 +90,7 @@ public final LuaValue execute(LuaState state, FunctionWrapper function, LuaValue
public final LuaValue execute(LuaState state, FunctionWrapper function, LuaValue arg1, LuaValue arg2, LuaValue arg3) {
ProtoInfo info = function.info;
if (++info.calledClosure >= info.threshold) {
FunctionExecutor executor = info.executor = info.loader.include(info);
FunctionExecutor executor = info.loader.include(info);
return executor.execute(state, function, arg1, arg2, arg3);
}

Expand Down Expand Up @@ -122,7 +122,7 @@ public final LuaValue execute(LuaState state, FunctionWrapper function, LuaValue
public final Varargs execute(LuaState state, FunctionWrapper function, Varargs varargs) {
ProtoInfo info = function.info;
if (++info.calledClosure >= info.threshold) {
FunctionExecutor executor = info.executor = info.loader.include(info);
FunctionExecutor executor = info.loader.include(info);
return executor.execute(state, function, varargs);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ public static Collection<Object[]> getLua() {
{"vBenchmark"},
{"Howl"},
{"luaide"},
{"kristwallet"},
});
}

Expand Down
2 changes: 1 addition & 1 deletion src/test/java/org/squiddev/cobalt/luajc/Loader.java
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public void handleError(ProtoInfo info, Throwable throwable) {
};

public static CompileOptions getOptions(int threshold) {
return new CompileOptions(CompileOptions.PREFIX, threshold, true, handler);
return new CompileOptions(CompileOptions.PREFIX, threshold, CompileOptions.MAXIMUM_COUNT, 0, true, handler);
}

public static void install(LuaState state, int threshold) {
Expand Down
Loading

0 comments on commit 13e88b3

Please sign in to comment.