Removes threading

This commit is contained in:
konsoletyper 2014-09-04 11:25:39 +04:00
parent e60be5d518
commit 7a36799b99
13 changed files with 56 additions and 178 deletions

View File

@ -69,12 +69,6 @@ public final class TeaVMRunner {
.withDescription("Generate source maps")
.withLongOpt("sourcemaps")
.create());
options.addOption(OptionBuilder
.withArgName("number")
.hasArg()
.withDescription("how many threads should TeaVM run")
.withLongOpt("threads")
.create("t"));
if (args.length == 0) {
printUsage(options);
@ -122,15 +116,6 @@ public final class TeaVMRunner {
if (commandLine.hasOption("mainpage")) {
tool.setMainPageIncluded(true);
}
if (commandLine.hasOption("t")) {
try {
tool.setNumThreads(Integer.parseInt(commandLine.getOptionValue("t")));
} catch (NumberFormatException e) {
System.err.println("Wrong parameter for -t option specified");
printUsage(options);
return;
}
}
if (commandLine.hasOption('D')) {
tool.setDebugInformation(new File(tool.getTargetDirectory(), tool.getTargetFileName() + ".teavmdbg"));
if (commandLine.hasOption("sourcemaps")) {

View File

@ -15,29 +15,23 @@
*/
package org.teavm.common;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CountDownLatch;
import java.util.*;
/**
*
* @author Alexey Andreev <konsoletyper@gmail.com>
*/
public class ConcurrentCachedMapper<T, R> implements Mapper<T, R> {
public class CachedMapper<T, R> implements Mapper<T, R> {
private Mapper<T, R> innerMapper;
private ConcurrentMap<T, Wrapper<R>> cache = new ConcurrentHashMap<>();
private Map<T, Wrapper<R>> cache = new HashMap<>();
private List<KeyListener<T>> keyListeners = new ArrayList<>();
private static class Wrapper<S> {
volatile S value;
volatile CountDownLatch latch = new CountDownLatch(1);
S value;
boolean computed;
}
public ConcurrentCachedMapper(Mapper<T, R> innerMapper) {
public CachedMapper(Mapper<T, R> innerMapper) {
this.innerMapper = innerMapper;
}
@ -51,25 +45,12 @@ public class ConcurrentCachedMapper<T, R> implements Mapper<T, R> {
Wrapper<R> wrapper = cache.get(preimage);
if (wrapper == null) {
wrapper = new Wrapper<>();
Wrapper<R> oldWrapper = cache.putIfAbsent(preimage, wrapper);
if (oldWrapper == null) {
wrapper.value = innerMapper.map(preimage);
wrapper.latch.countDown();
wrapper.latch = null;
for (KeyListener<T> listener : keyListeners) {
listener.keyAdded(preimage);
}
} else {
wrapper = oldWrapper;
}
cache.put(preimage, wrapper);
wrapper.value = innerMapper.map(preimage);
wrapper.computed = true;
}
CountDownLatch latch = wrapper.latch;
if (latch != null) {
try {
latch.await();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
if (!wrapper.computed) {
throw new IllegalStateException("Recursive calls are not allowed");
}
return wrapper.value;
}

View File

@ -20,7 +20,7 @@ import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import org.teavm.common.*;
import org.teavm.common.ConcurrentCachedMapper.KeyListener;
import org.teavm.common.CachedMapper.KeyListener;
import org.teavm.model.*;
import org.teavm.model.util.ModelUtils;
@ -34,43 +34,37 @@ public class DependencyChecker implements DependencyInfo, DependencyAgent {
private int classNameSuffix;
private DependencyClassSource classSource;
private ClassLoader classLoader;
private FiniteExecutor executor;
private Mapper<MethodReference, MethodReader> methodReaderCache;
private Mapper<FieldReference, FieldReader> fieldReaderCache;
private ConcurrentMap<MethodReference, DependencyStack> stacks = new ConcurrentHashMap<>();
private ConcurrentMap<FieldReference, DependencyStack> fieldStacks = new ConcurrentHashMap<>();
private ConcurrentMap<String, DependencyStack> classStacks = new ConcurrentHashMap<>();
private ConcurrentCachedMapper<MethodReference, MethodDependency> methodCache;
private ConcurrentCachedMapper<FieldReference, FieldDependency> fieldCache;
private CachedMapper<MethodReference, MethodDependency> methodCache;
private CachedMapper<FieldReference, FieldDependency> fieldCache;
private ConcurrentMap<String, Object> achievableClasses = new ConcurrentHashMap<>();
private ConcurrentMap<String, Object> initializedClasses = new ConcurrentHashMap<>();
private List<DependencyListener> listeners = new ArrayList<>();
private ServiceRepository services;
private Queue<Runnable> tasks = new ArrayDeque<>();
ConcurrentMap<MethodReference, DependencyStack> missingMethods = new ConcurrentHashMap<>();
ConcurrentMap<String, DependencyStack> missingClasses = new ConcurrentHashMap<>();
ConcurrentMap<FieldReference, DependencyStack> missingFields = new ConcurrentHashMap<>();
public DependencyChecker(ClassReaderSource classSource, ClassLoader classLoader, ServiceRepository services) {
this(classSource, classLoader, services, new SimpleFiniteExecutor());
}
public DependencyChecker(ClassReaderSource classSource, ClassLoader classLoader, ServiceRepository services,
FiniteExecutor executor) {
this.classSource = new DependencyClassSource(classSource);
this.classLoader = classLoader;
this.executor = executor;
this.services = services;
methodReaderCache = new ConcurrentCachedMapper<>(new Mapper<MethodReference, MethodReader>() {
methodReaderCache = new CachedMapper<>(new Mapper<MethodReference, MethodReader>() {
@Override public MethodReader map(MethodReference preimage) {
return findMethodReader(preimage);
}
});
fieldReaderCache = new ConcurrentCachedMapper<>(new Mapper<FieldReference, FieldReader>() {
fieldReaderCache = new CachedMapper<>(new Mapper<FieldReference, FieldReader>() {
@Override public FieldReader map(FieldReference preimage) {
return findFieldReader(preimage);
}
});
methodCache = new ConcurrentCachedMapper<>(new Mapper<MethodReference, MethodDependency>() {
methodCache = new CachedMapper<>(new Mapper<MethodReference, MethodDependency>() {
@Override public MethodDependency map(MethodReference preimage) {
MethodReader method = methodReaderCache.map(preimage);
if (method != null && !method.getReference().equals(preimage)) {
@ -80,7 +74,7 @@ public class DependencyChecker implements DependencyInfo, DependencyAgent {
return createMethodDep(preimage, method, stacks.get(preimage));
}
});
fieldCache = new ConcurrentCachedMapper<>(new Mapper<FieldReference, FieldDependency>() {
fieldCache = new CachedMapper<>(new Mapper<FieldReference, FieldDependency>() {
@Override public FieldDependency map(FieldReference preimage) {
FieldReader field = fieldReaderCache.map(preimage);
if (field != null && !field.getReference().equals(preimage)) {
@ -162,17 +156,13 @@ public class DependencyChecker implements DependencyInfo, DependencyAgent {
}
void schedulePropagation(final DependencyConsumer consumer, final String type) {
executor.executeFast(new Runnable() {
tasks.add(new Runnable() {
@Override public void run() {
consumer.consume(type);
}
});
}
public FiniteExecutor getExecutor() {
return executor;
}
boolean achieveClass(String className, DependencyStack stack) {
classStacks.putIfAbsent(className, stack);
boolean result = achievableClasses.putIfAbsent(className, dummyValue) == null;
@ -210,7 +200,7 @@ public class DependencyChecker implements DependencyInfo, DependencyAgent {
}
if (cls.getMethod(clinitDesc) != null) {
final MethodReference methodRef = new MethodReference(className, clinitDesc);
executor.executeFast(new Runnable() {
tasks.add(new Runnable() {
@Override public void run() {
linkMethod(methodRef, new DependencyStack(methodRef, stack)).use();
}
@ -309,7 +299,7 @@ public class DependencyChecker implements DependencyInfo, DependencyAgent {
final MethodDependency dep = new MethodDependency(parameterNodes, paramCount, resultNode, thrown,
stack, method, methodRef);
if (method != null) {
executor.execute(new Runnable() {
tasks.add(new Runnable() {
@Override public void run() {
DependencyGraphBuilder graphBuilder = new DependencyGraphBuilder(DependencyChecker.this);
graphBuilder.buildGraph(dep);
@ -320,7 +310,7 @@ public class DependencyChecker implements DependencyInfo, DependencyAgent {
}
if (method != null) {
final DependencyStack callerStack = stack;
executor.execute(new Runnable() {
tasks.add(new Runnable() {
@Override public void run() {
initClass(dep.getReference().getClassName(), callerStack);
}
@ -451,6 +441,12 @@ public class DependencyChecker implements DependencyInfo, DependencyAgent {
}
}
public void processDependencies() {
while (!tasks.isEmpty()) {
tasks.poll().run();
}
}
@Override
public <T> T getService(Class<T> type) {
return services.getService(type);

View File

@ -20,7 +20,7 @@ import java.util.Collection;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import org.teavm.common.ConcurrentCachedMapper;
import org.teavm.common.CachedMapper;
import org.teavm.common.Mapper;
import org.teavm.model.ClassHolder;
import org.teavm.model.ClassHolderTransformer;
@ -36,7 +36,7 @@ class DependencyClassSource implements ClassReaderSource {
private ClassReaderSource innerSource;
private ConcurrentMap<String, ClassHolder> generatedClasses = new ConcurrentHashMap<>();
private List<ClassHolderTransformer> transformers = new ArrayList<>();
private ConcurrentCachedMapper<String, ClassReader> cache = new ConcurrentCachedMapper<>(
private CachedMapper<String, ClassReader> cache = new CachedMapper<>(
new Mapper<String, ClassReader>() {
@Override public ClassReader map(String preimage) {
return findAndTransformClass(preimage);

View File

@ -42,14 +42,12 @@ public class Decompiler {
private RangeTree codeTree;
private RangeTree.Node currentNode;
private RangeTree.Node parentNode;
private FiniteExecutor executor;
private Map<MethodReference, Generator> generators = new HashMap<>();
private Set<MethodReference> methodsToPass = new HashSet<>();
public Decompiler(ClassHolderSource classSource, ClassLoader classLoader, FiniteExecutor executor) {
public Decompiler(ClassHolderSource classSource, ClassLoader classLoader) {
this.classSource = classSource;
this.classLoader = classLoader;
this.executor = executor;
}
public int getGraphSize() {
@ -79,18 +77,8 @@ public class Decompiler {
final List<ClassNode> result = new ArrayList<>();
for (int i = 0; i < sequence.size(); ++i) {
final String className = sequence.get(i);
result.add(null);
final int index = i;
executor.execute(new Runnable() {
@Override public void run() {
Decompiler copy = new Decompiler(classSource, classLoader, executor);
copy.generators = generators;
copy.methodsToPass = methodsToPass;
result.set(index, copy.decompile(classSource.get(className)));
}
});
result.add(decompile(classSource.get(className)));
}
executor.complete();
return result;
}

View File

@ -17,7 +17,6 @@ package org.teavm.optimization;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Executor;
import org.teavm.model.ClassHolder;
import org.teavm.model.ListableClassHolderSource;
import org.teavm.model.MethodHolder;
@ -29,12 +28,6 @@ import org.teavm.model.util.ProgramUtils;
* @author Alexey Andreev <konsoletyper@gmail.com>
*/
public class ClassSetOptimizer {
private Executor executor;
public ClassSetOptimizer(Executor executor) {
this.executor = executor;
}
private List<MethodOptimization> getOptimizations() {
return Arrays.<MethodOptimization>asList(new ArrayUnwrapMotion(), new LoopInvariantMotion(),
new GlobalValueNumbering(), new UnusedVariableElimination());
@ -43,18 +36,13 @@ public class ClassSetOptimizer {
public void optimizeAll(ListableClassHolderSource classSource) {
for (String className : classSource.getClassNames()) {
ClassHolder cls = classSource.get(className);
for (final MethodHolder method : cls.getMethods()) {
for (MethodHolder method : cls.getMethods()) {
if (method.getProgram() != null && method.getProgram().basicBlockCount() > 0) {
executor.execute(new Runnable() {
@Override
public void run() {
Program program = ProgramUtils.copy(method.getProgram());
for (MethodOptimization optimization : getOptimizations()) {
optimization.optimize(method, program);
}
method.setProgram(program);
}
});
Program program = ProgramUtils.copy(method.getProgram());
for (MethodOptimization optimization : getOptimizations()) {
optimization.optimize(method, program);
}
method.setProgram(program);
}
}
}

View File

@ -19,7 +19,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.*;
import org.teavm.common.ConcurrentCachedMapper;
import org.teavm.common.CachedMapper;
import org.teavm.common.Mapper;
import org.teavm.model.ClassHolder;
@ -58,7 +58,7 @@ public class ClasspathResourceMapper implements Mapper<String, ClassHolder> {
} catch (IOException e) {
throw new RuntimeException("Error reading resources", e);
}
renamer = new ClassRefsRenamer(new ConcurrentCachedMapper<>(classNameMapper));
renamer = new ClassRefsRenamer(new CachedMapper<>(classNameMapper));
}
private void loadProperties(Properties properties, Map<String, Transformation> cache) {

View File

@ -15,7 +15,7 @@
*/
package org.teavm.resource;
import org.teavm.common.ConcurrentCachedMapper;
import org.teavm.common.CachedMapper;
import org.teavm.common.Mapper;
import org.teavm.model.ClassHolder;
import org.teavm.model.ClassHolderSource;
@ -28,7 +28,7 @@ public class MapperClassHolderSource implements ClassHolderSource {
private Mapper<String, ClassHolder> mapper;
public MapperClassHolderSource(Mapper<String, ClassHolder> mapper) {
this.mapper = new ConcurrentCachedMapper<>(mapper);
this.mapper = new CachedMapper<>(mapper);
}
@Override

View File

@ -208,7 +208,7 @@ public class TeaVMTestTool {
log.debug("Building test for " + method);
try {
decompileClassesForTest(classLoader, new CopyClassHolderSource(classSource), method,
fileNames.get(method), new SimpleFiniteExecutor());
fileNames.get(method));
} catch (IOException e) {
log.error("Error generating JavaScript", e);
}
@ -275,11 +275,10 @@ public class TeaVMTestTool {
}
private void decompileClassesForTest(ClassLoader classLoader, ClassHolderSource classSource,
MethodReference methodRef, String targetName, FiniteExecutor executor) throws IOException {
MethodReference methodRef, String targetName) throws IOException {
TeaVM vm = new TeaVMBuilder()
.setClassLoader(classLoader)
.setClassSource(classSource)
.setExecutor(executor)
.build();
vm.setProperties(properties);
vm.setMinifying(minifying);

View File

@ -20,7 +20,6 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import org.apache.commons.io.IOUtils;
import org.teavm.common.ThreadPoolFiniteExecutor;
import org.teavm.debugging.information.DebugInformation;
import org.teavm.debugging.information.DebugInformationBuilder;
import org.teavm.javascript.RenderingContext;
@ -48,7 +47,6 @@ public class TeaVMTool {
private File debugInformation;
private String sourceMapsFileName;
private boolean sourceMapsFileGenerated;
private int numThreads = 1;
private List<ClassHolderTransformer> transformers = new ArrayList<>();
private List<ClassAlias> classAliases = new ArrayList<>();
private List<MethodAlias> methodAliases = new ArrayList<>();
@ -119,14 +117,6 @@ public class TeaVMTool {
this.debugInformation = debugInformation;
}
public int getNumThreads() {
return numThreads;
}
public void setNumThreads(int numThreads) {
this.numThreads = numThreads;
}
public String getSourceMapsFileName() {
return sourceMapsFileName;
}
@ -176,21 +166,10 @@ public class TeaVMTool {
}
public void generate() throws TeaVMToolException {
Runnable finalizer = null;
try {
log.info("Building JavaScript file");
TeaVMBuilder vmBuilder = new TeaVMBuilder();
vmBuilder.setClassLoader(classLoader).setClassSource(new ClasspathClassHolderSource(classLoader));
if (numThreads != 1) {
int threads = numThreads != 0 ? numThreads : Runtime.getRuntime().availableProcessors();
final ThreadPoolFiniteExecutor executor = new ThreadPoolFiniteExecutor(threads);
finalizer = new Runnable() {
@Override public void run() {
executor.stop();
}
};
vmBuilder.setExecutor(executor);
}
TeaVM vm = vmBuilder.build();
vm.setMinifying(minifying);
vm.setBytecodeLogging(bytecodeLogging);
@ -272,10 +251,6 @@ public class TeaVMTool {
}
} catch (IOException e) {
throw new TeaVMToolException("IO error occured", e);
} finally {
if (finalizer != null) {
finalizer.run();
}
}
}

View File

@ -18,7 +18,6 @@ package org.teavm.vm;
import java.io.*;
import java.util.*;
import org.teavm.codegen.*;
import org.teavm.common.FiniteExecutor;
import org.teavm.common.ServiceRepository;
import org.teavm.debugging.information.DebugInformationEmitter;
import org.teavm.debugging.information.SourceLocation;
@ -71,7 +70,6 @@ import org.teavm.vm.spi.TeaVMPlugin;
public class TeaVM implements TeaVMHost, ServiceRepository {
private ClassReaderSource classSource;
private DependencyChecker dependencyChecker;
private FiniteExecutor executor;
private ClassLoader classLoader;
private boolean minifying = true;
private boolean bytecodeLogging;
@ -85,11 +83,10 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
private Properties properties = new Properties();
private DebugInformationEmitter debugEmitter;
TeaVM(ClassReaderSource classSource, ClassLoader classLoader, FiniteExecutor executor) {
TeaVM(ClassReaderSource classSource, ClassLoader classLoader) {
this.classSource = classSource;
this.classLoader = classLoader;
dependencyChecker = new DependencyChecker(this.classSource, classLoader, this, executor);
this.executor = executor;
dependencyChecker = new DependencyChecker(this.classSource, classLoader, this);
}
@Override
@ -307,7 +304,7 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
DependencyStack.ROOT).use();
dependencyChecker.linkMethod(new MethodReference("java.lang.Object", new MethodDescriptor("clone",
ValueType.object("java.lang.Object"))), DependencyStack.ROOT).use();
executor.complete();
dependencyChecker.processDependencies();
if (hasMissingItems()) {
return;
}
@ -318,12 +315,9 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
// Optimize and allocate registers
devirtualize(classSet, dependencyChecker);
executor.complete();
ClassSetOptimizer optimizer = new ClassSetOptimizer(executor);
ClassSetOptimizer optimizer = new ClassSetOptimizer();
optimizer.optimizeAll(classSet);
executor.complete();
allocateRegisters(classSet);
executor.complete();
if (bytecodeLogging) {
try {
logBytecode(new PrintWriter(new OutputStreamWriter(logStream, "UTF-8")), classSet);
@ -333,7 +327,7 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
}
// Decompile
Decompiler decompiler = new Decompiler(classSet, classLoader, executor);
Decompiler decompiler = new Decompiler(classSet, classLoader);
for (Map.Entry<MethodReference, Generator> entry : methodGenerators.entrySet()) {
decompiler.addGenerator(entry.getKey(), entry.getValue());
}
@ -421,11 +415,7 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
ClassHolder cls = classes.get(className);
for (final MethodHolder method : cls.getMethods()) {
if (method.getProgram() != null) {
executor.execute(new Runnable() {
@Override public void run() {
devirtualization.apply(method);
}
});
devirtualization.apply(method);
}
}
}
@ -436,14 +426,10 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
ClassHolder cls = classes.get(className);
for (final MethodHolder method : cls.getMethods()) {
if (method.getProgram() != null && method.getProgram().basicBlockCount() > 0) {
executor.execute(new Runnable() {
@Override public void run() {
RegisterAllocator allocator = new RegisterAllocator();
Program program = ProgramUtils.copy(method.getProgram());
allocator.allocateRegisters(method, program);
method.setProgram(program);
}
});
RegisterAllocator allocator = new RegisterAllocator();
Program program = ProgramUtils.copy(method.getProgram());
allocator.allocateRegisters(method, program);
method.setProgram(program);
}
}
}

View File

@ -15,8 +15,6 @@
*/
package org.teavm.vm;
import org.teavm.common.FiniteExecutor;
import org.teavm.common.SimpleFiniteExecutor;
import org.teavm.model.ClassHolderSource;
import org.teavm.parsing.ClasspathClassHolderSource;
@ -27,7 +25,6 @@ import org.teavm.parsing.ClasspathClassHolderSource;
public class TeaVMBuilder {
ClassHolderSource classSource;
ClassLoader classLoader;
FiniteExecutor executor = new SimpleFiniteExecutor();
public TeaVMBuilder() {
classLoader = TeaVMBuilder.class.getClassLoader();
@ -52,16 +49,7 @@ public class TeaVMBuilder {
return this;
}
public FiniteExecutor getExecutor() {
return executor;
}
public TeaVMBuilder setExecutor(FiniteExecutor executor) {
this.executor = executor;
return this;
}
public TeaVM build() {
return new TeaVM(classSource, classLoader, executor);
return new TeaVM(classSource, classLoader);
}
}

View File

@ -80,9 +80,6 @@ public class BuildJavascriptMojo extends AbstractMojo {
@Parameter
private File debugInformationFile;
@Parameter(required = false)
private int numThreads = 1;
@Parameter
private String[] transformers;
@ -126,10 +123,6 @@ public class BuildJavascriptMojo extends AbstractMojo {
this.mainPageIncluded = mainPageIncluded;
}
public void setNumThreads(int numThreads) {
this.numThreads = numThreads;
}
public String[] getTransformers() {
return transformers;
}
@ -177,7 +170,6 @@ public class BuildJavascriptMojo extends AbstractMojo {
tool.setMainClass(mainClass);
tool.setMainPageIncluded(mainPageIncluded);
tool.setMinifying(minifying);
tool.setNumThreads(numThreads);
tool.setRuntime(runtime);
tool.setTargetDirectory(targetDirectory);
tool.setTargetFileName(targetFileName);