package org.dynjs.compiler.jit; import java.util.concurrent.Executor; import java.util.concurrent.Executors; import java.util.concurrent.ThreadFactory; import java.util.concurrent.atomic.AtomicInteger; import org.dynjs.Config; import org.dynjs.codegen.CodeGeneratingVisitorFactory; import org.dynjs.compiler.BasicBlockCompiler; import org.dynjs.compiler.CompilationContext; import org.dynjs.compiler.bytecode.BytecodeBasicBlockCompiler; import org.dynjs.parser.Statement; import org.dynjs.runtime.BasicBlock; import org.dynjs.runtime.BlockManager.Entry; import org.dynjs.runtime.CompilableBasicBlock; import org.dynjs.runtime.ExecutionContext; import org.dynjs.runtime.interp.InterpretedBasicBlock; import org.dynjs.runtime.interp.InterpretingVisitorFactory; public class JITBasicBlockCompiler implements BasicBlockCompiler { private InterpretingVisitorFactory interpFactory; private BytecodeBasicBlockCompiler jitCompiler; private static final Executor compilationQueue = Executors.newFixedThreadPool(8, new ThreadFactory() { private final AtomicInteger count = new AtomicInteger(1); public Thread newThread(Runnable runnable) { Thread thread = new Thread(runnable); thread.setName("JITBasicBlockCompiler-" + count.getAndIncrement()); thread.setDaemon(true); return thread; } }); public JITBasicBlockCompiler(Config config, InterpretingVisitorFactory interpFactory, CodeGeneratingVisitorFactory factory) { this.interpFactory = interpFactory; this.jitCompiler = new BytecodeBasicBlockCompiler(config, factory); } @Override public BasicBlock compile(CompilationContext context, String grist, Statement body, boolean strict) { int statementNumber = body.getStatementNumber(); Entry entry = context.getBlockManager().retrieve(statementNumber); BasicBlock code = entry.getCompiled(); if (code != null) { return code; } InterpretedBasicBlock initial = new InterpretedBasicBlock(this.interpFactory, body, strict); code = new CompilableBasicBlock(this, grist, initial); entry.setCompiled(code); return code; } private BasicBlock jitCompile(CompilationContext context, String grist, Statement body, boolean strict) { return this.jitCompiler.compile(context, grist, body, strict); } public void requestJitCompilation(CompilationContext context, CompilableBasicBlock block) { this.compilationQueue.execute(new CompileRequest(context, block)); } private class CompileRequest implements Runnable { private CompilationContext context; private CompilableBasicBlock block; public CompileRequest(CompilationContext context, CompilableBasicBlock block) { this.context = context; this.block = block; } @Override public void run() { BasicBlock delegate = this.block.getDelegate(); if (delegate instanceof InterpretedBasicBlock) { BasicBlock compiled = jitCompile(this.context, block.getGrist(), ((InterpretedBasicBlock) delegate).getBody(), block.isStrict()); this.block.setDelegate(compiled); } } } }