mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-23 00:24:11 -08:00
Multithreading support refactoring
This commit is contained in:
parent
c9a891d9cd
commit
915add4d97
|
@ -53,6 +53,7 @@
|
||||||
<phase>process-test-classes</phase>
|
<phase>process-test-classes</phase>
|
||||||
<configuration>
|
<configuration>
|
||||||
<minifying>false</minifying>
|
<minifying>false</minifying>
|
||||||
|
<numThreads>1</numThreads>
|
||||||
</configuration>
|
</configuration>
|
||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2014 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.common;
|
||||||
|
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev
|
||||||
|
*/
|
||||||
|
public interface FiniteExecutor extends Executor {
|
||||||
|
void complete();
|
||||||
|
|
||||||
|
void executeFast(Runnable runnable);
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2014 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.common;
|
||||||
|
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.Queue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev
|
||||||
|
*/
|
||||||
|
public class SimpleFiniteExecutor implements FiniteExecutor {
|
||||||
|
private Queue<Runnable> queue = new LinkedList<>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(Runnable command) {
|
||||||
|
queue.add(command);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void executeFast(Runnable runnable) {
|
||||||
|
execute(runnable);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void complete() {
|
||||||
|
while (!queue.isEmpty()) {
|
||||||
|
queue.remove().run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,115 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2014 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.common;
|
||||||
|
|
||||||
|
import java.util.ArrayDeque;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Queue;
|
||||||
|
import java.util.concurrent.BlockingQueue;
|
||||||
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev
|
||||||
|
*/
|
||||||
|
public class ThreadPoolFiniteExecutor implements FiniteExecutor {
|
||||||
|
private List<Thread> threads = new ArrayList<>();
|
||||||
|
private BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>();
|
||||||
|
private AtomicInteger runningTasks = new AtomicInteger();
|
||||||
|
private final Object monitor = new Object();
|
||||||
|
private AtomicReference<RuntimeException> thrownException = new AtomicReference<>();
|
||||||
|
private ThreadLocal<Queue<Runnable>> localQueueues = new ThreadLocal<>();
|
||||||
|
|
||||||
|
public ThreadPoolFiniteExecutor(int numThreads) {
|
||||||
|
for (int i = 0; i < numThreads; ++i) {
|
||||||
|
Thread thread = new Thread() {
|
||||||
|
@Override public void run() {
|
||||||
|
takeTask();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
threads.add(thread);
|
||||||
|
thread.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(Runnable command) {
|
||||||
|
runningTasks.incrementAndGet();
|
||||||
|
try {
|
||||||
|
queue.put(command);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void executeFast(Runnable runnable) {
|
||||||
|
localQueueues.get().add(runnable);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void complete() {
|
||||||
|
synchronized (monitor) {
|
||||||
|
try {
|
||||||
|
monitor.wait();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (thrownException.get() != null) {
|
||||||
|
throw thrownException.get();
|
||||||
|
}
|
||||||
|
if (runningTasks.get() == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void takeTask() {
|
||||||
|
Queue<Runnable> localQueue = new ArrayDeque<>();
|
||||||
|
localQueueues.set(localQueue);
|
||||||
|
try {
|
||||||
|
while (true) {
|
||||||
|
Runnable task = queue.take();
|
||||||
|
try {
|
||||||
|
task.run();
|
||||||
|
while (!localQueue.isEmpty()) {
|
||||||
|
localQueue.remove().run();
|
||||||
|
}
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
thrownException.set(e);
|
||||||
|
} finally {
|
||||||
|
if (runningTasks.decrementAndGet() == 0 || thrownException.get() != null) {
|
||||||
|
synchronized (monitor) {
|
||||||
|
monitor.notifyAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stop() {
|
||||||
|
for (Thread thread : threads) {
|
||||||
|
thread.interrupt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,10 +18,10 @@ package org.teavm.dependency;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.concurrent.*;
|
import java.util.concurrent.*;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
|
||||||
import org.teavm.common.ConcurrentCachedMapper;
|
import org.teavm.common.ConcurrentCachedMapper;
|
||||||
|
import org.teavm.common.FiniteExecutor;
|
||||||
import org.teavm.common.Mapper;
|
import org.teavm.common.Mapper;
|
||||||
|
import org.teavm.common.SimpleFiniteExecutor;
|
||||||
import org.teavm.common.ConcurrentCachedMapper.KeyListener;
|
import org.teavm.common.ConcurrentCachedMapper.KeyListener;
|
||||||
import org.teavm.model.*;
|
import org.teavm.model.*;
|
||||||
|
|
||||||
|
@ -34,31 +34,21 @@ public class DependencyChecker {
|
||||||
static final boolean shouldLog = System.getProperty("org.teavm.logDependencies", "false").equals("true");
|
static final boolean shouldLog = System.getProperty("org.teavm.logDependencies", "false").equals("true");
|
||||||
private ClassHolderSource classSource;
|
private ClassHolderSource classSource;
|
||||||
private ClassLoader classLoader;
|
private ClassLoader classLoader;
|
||||||
private ScheduledThreadPoolExecutor executor;
|
private FiniteExecutor executor;
|
||||||
private ConcurrentMap<MethodReference, Object> abstractMethods = new ConcurrentHashMap<>();
|
private ConcurrentMap<MethodReference, Object> abstractMethods = new ConcurrentHashMap<>();
|
||||||
private ConcurrentCachedMapper<MethodReference, MethodGraph> methodCache;
|
private ConcurrentCachedMapper<MethodReference, MethodGraph> methodCache;
|
||||||
private ConcurrentCachedMapper<FieldReference, DependencyNode> fieldCache;
|
private ConcurrentCachedMapper<FieldReference, DependencyNode> fieldCache;
|
||||||
private ConcurrentMap<String, Object> achievableClasses = new ConcurrentHashMap<>();
|
private ConcurrentMap<String, Object> achievableClasses = new ConcurrentHashMap<>();
|
||||||
private ConcurrentMap<String, Object> initializedClasses = new ConcurrentHashMap<>();
|
private ConcurrentMap<String, Object> initializedClasses = new ConcurrentHashMap<>();
|
||||||
private AtomicReference<RuntimeException> exceptionOccured = new AtomicReference<>();
|
|
||||||
private AtomicInteger activeTaskCount = new AtomicInteger(0);
|
|
||||||
private final Object activeTaskMonitor = new Object();
|
|
||||||
|
|
||||||
public DependencyChecker(ClassHolderSource classSource, ClassLoader classLoader) {
|
public DependencyChecker(ClassHolderSource classSource, ClassLoader classLoader) {
|
||||||
this(classSource, classLoader, Runtime.getRuntime().availableProcessors());
|
this(classSource, classLoader, new SimpleFiniteExecutor());
|
||||||
}
|
}
|
||||||
|
|
||||||
public DependencyChecker(ClassHolderSource classSource, ClassLoader classLoader, int numThreads) {
|
public DependencyChecker(ClassHolderSource classSource, ClassLoader classLoader, FiniteExecutor executor) {
|
||||||
this.classSource = classSource;
|
this.classSource = classSource;
|
||||||
this.classLoader = classLoader;
|
this.classLoader = classLoader;
|
||||||
executor = new ScheduledThreadPoolExecutor(numThreads);
|
this.executor = executor;
|
||||||
executor.setThreadFactory(new ThreadFactory() {
|
|
||||||
@Override public Thread newThread(Runnable r) {
|
|
||||||
Thread thread = new Thread(r);
|
|
||||||
thread.setDaemon(true);
|
|
||||||
return thread;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
methodCache = new ConcurrentCachedMapper<>(new Mapper<MethodReference, MethodGraph>() {
|
methodCache = new ConcurrentCachedMapper<>(new Mapper<MethodReference, MethodGraph>() {
|
||||||
@Override public MethodGraph map(MethodReference preimage) {
|
@Override public MethodGraph map(MethodReference preimage) {
|
||||||
return createMethodGraph(preimage);
|
return createMethodGraph(preimage);
|
||||||
|
@ -98,58 +88,15 @@ public class DependencyChecker {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void schedulePropagation(final DependencyConsumer consumer, final String type) {
|
public void schedulePropagation(final DependencyConsumer consumer, final String type) {
|
||||||
schedule(new Runnable() {
|
executor.executeFast(new Runnable() {
|
||||||
@Override public void run() {
|
@Override public void run() {
|
||||||
consumer.consume(type);
|
consumer.consume(type);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void schedule(final Runnable runnable) {
|
public FiniteExecutor getExecutor() {
|
||||||
synchronized (activeTaskMonitor) {
|
return executor;
|
||||||
activeTaskCount.incrementAndGet();
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
executor.execute(new Runnable() {
|
|
||||||
@Override public void run() {
|
|
||||||
try {
|
|
||||||
runnable.run();
|
|
||||||
} catch (RuntimeException e) {
|
|
||||||
activeTaskMonitor.notifyAll();
|
|
||||||
exceptionOccured.compareAndSet(null, e);
|
|
||||||
executor.shutdownNow();
|
|
||||||
}
|
|
||||||
synchronized (activeTaskMonitor) {
|
|
||||||
if (activeTaskCount.decrementAndGet() == 0) {
|
|
||||||
activeTaskMonitor.notifyAll();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (RejectedExecutionException e) {
|
|
||||||
throw exceptionOccured.get();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void checkDependencies() {
|
|
||||||
while (true) {
|
|
||||||
try {
|
|
||||||
synchronized (activeTaskMonitor) {
|
|
||||||
if (activeTaskCount.get() == 0 || exceptionOccured.get() != null) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
activeTaskMonitor.wait();
|
|
||||||
}
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
Thread.currentThread().interrupt();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
RuntimeException e = exceptionOccured.get();
|
|
||||||
if (e != null) {
|
|
||||||
throw exceptionOccured.get();
|
|
||||||
}
|
|
||||||
executor.shutdown();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean achieveClass(String className) {
|
boolean achieveClass(String className) {
|
||||||
|
@ -226,7 +173,7 @@ public class DependencyChecker {
|
||||||
}
|
}
|
||||||
final MethodGraph graph = new MethodGraph(parameterNodes, paramCount, resultNode, this);
|
final MethodGraph graph = new MethodGraph(parameterNodes, paramCount, resultNode, this);
|
||||||
final MethodHolder currentMethod = method;
|
final MethodHolder currentMethod = method;
|
||||||
schedule(new Runnable() {
|
executor.execute(new Runnable() {
|
||||||
@Override public void run() {
|
@Override public void run() {
|
||||||
DependencyGraphBuilder graphBuilder = new DependencyGraphBuilder(DependencyChecker.this);
|
DependencyGraphBuilder graphBuilder = new DependencyGraphBuilder(DependencyChecker.this);
|
||||||
graphBuilder.buildGraph(currentMethod, graph);
|
graphBuilder.buildGraph(currentMethod, graph);
|
||||||
|
|
|
@ -21,10 +21,10 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import org.teavm.codegen.*;
|
import org.teavm.codegen.*;
|
||||||
|
import org.teavm.common.FiniteExecutor;
|
||||||
import org.teavm.dependency.DependencyChecker;
|
import org.teavm.dependency.DependencyChecker;
|
||||||
import org.teavm.javascript.ast.ClassNode;
|
import org.teavm.javascript.ast.ClassNode;
|
||||||
import org.teavm.model.*;
|
import org.teavm.model.*;
|
||||||
import org.teavm.model.resource.ClasspathClassHolderSource;
|
|
||||||
import org.teavm.model.util.*;
|
import org.teavm.model.util.*;
|
||||||
import org.teavm.optimization.ClassSetOptimizer;
|
import org.teavm.optimization.ClassSetOptimizer;
|
||||||
|
|
||||||
|
@ -35,25 +35,19 @@ import org.teavm.optimization.ClassSetOptimizer;
|
||||||
public class JavascriptBuilder {
|
public class JavascriptBuilder {
|
||||||
private ClassHolderSource classSource;
|
private ClassHolderSource classSource;
|
||||||
private DependencyChecker dependencyChecker;
|
private DependencyChecker dependencyChecker;
|
||||||
|
private FiniteExecutor executor;
|
||||||
private ClassLoader classLoader;
|
private ClassLoader classLoader;
|
||||||
private boolean minifying = true;
|
private boolean minifying = true;
|
||||||
private boolean bytecodeLogging = true;
|
private boolean bytecodeLogging;
|
||||||
private OutputStream logStream = System.out;
|
private OutputStream logStream = System.out;
|
||||||
private Map<String, JavascriptEntryPoint> entryPoints = new HashMap<>();
|
private Map<String, JavascriptEntryPoint> entryPoints = new HashMap<>();
|
||||||
private Map<String, String> exportedClasses = new HashMap<>();
|
private Map<String, String> exportedClasses = new HashMap<>();
|
||||||
|
|
||||||
public JavascriptBuilder(ClassHolderSource classSource, ClassLoader classLoader) {
|
JavascriptBuilder(ClassHolderSource classSource, ClassLoader classLoader, FiniteExecutor executor) {
|
||||||
this.classSource = classSource;
|
this.classSource = classSource;
|
||||||
this.classLoader = classLoader;
|
this.classLoader = classLoader;
|
||||||
dependencyChecker = new DependencyChecker(classSource, classLoader);
|
dependencyChecker = new DependencyChecker(classSource, classLoader, executor);
|
||||||
}
|
this.executor = executor;
|
||||||
|
|
||||||
public JavascriptBuilder(ClassLoader classLoader) {
|
|
||||||
this(new ClasspathClassHolderSource(classLoader), classLoader);
|
|
||||||
}
|
|
||||||
|
|
||||||
public JavascriptBuilder() {
|
|
||||||
this(JavascriptBuilder.class.getClassLoader());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isMinifying() {
|
public boolean isMinifying() {
|
||||||
|
@ -107,7 +101,7 @@ public class JavascriptBuilder {
|
||||||
ValueType.object("java.lang.Class"))));
|
ValueType.object("java.lang.Class"))));
|
||||||
dependencyChecker.attachMethodGraph(new MethodReference("java.lang.String", new MethodDescriptor("<init>",
|
dependencyChecker.attachMethodGraph(new MethodReference("java.lang.String", new MethodDescriptor("<init>",
|
||||||
ValueType.arrayOf(ValueType.CHARACTER), ValueType.VOID)));
|
ValueType.arrayOf(ValueType.CHARACTER), ValueType.VOID)));
|
||||||
dependencyChecker.checkDependencies();
|
executor.complete();
|
||||||
ListableClassHolderSource classSet = dependencyChecker.cutUnachievableClasses();
|
ListableClassHolderSource classSet = dependencyChecker.cutUnachievableClasses();
|
||||||
Decompiler decompiler = new Decompiler(classSet, classLoader);
|
Decompiler decompiler = new Decompiler(classSet, classLoader);
|
||||||
ClassSetOptimizer optimizer = new ClassSetOptimizer();
|
ClassSetOptimizer optimizer = new ClassSetOptimizer();
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2014 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.javascript;
|
||||||
|
|
||||||
|
import org.teavm.common.FiniteExecutor;
|
||||||
|
import org.teavm.common.SimpleFiniteExecutor;
|
||||||
|
import org.teavm.model.ClassHolderSource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev
|
||||||
|
*/
|
||||||
|
public class JavascriptBuilderFactory {
|
||||||
|
ClassHolderSource classSource;
|
||||||
|
ClassLoader classLoader;
|
||||||
|
FiniteExecutor executor = new SimpleFiniteExecutor();
|
||||||
|
|
||||||
|
public ClassHolderSource getClassSource() {
|
||||||
|
return classSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setClassSource(ClassHolderSource classSource) {
|
||||||
|
this.classSource = classSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ClassLoader getClassLoader() {
|
||||||
|
return classLoader;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setClassLoader(ClassLoader classLoader) {
|
||||||
|
this.classLoader = classLoader;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FiniteExecutor getExecutor() {
|
||||||
|
return executor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setExecutor(FiniteExecutor executor) {
|
||||||
|
this.executor = executor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JavascriptBuilder create() {
|
||||||
|
return new JavascriptBuilder(classSource, classLoader, executor);
|
||||||
|
}
|
||||||
|
}
|
|
@ -34,7 +34,11 @@ import org.apache.maven.plugins.annotations.Parameter;
|
||||||
import org.apache.maven.plugins.annotations.ResolutionScope;
|
import org.apache.maven.plugins.annotations.ResolutionScope;
|
||||||
import org.apache.maven.project.MavenProject;
|
import org.apache.maven.project.MavenProject;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import org.teavm.common.FiniteExecutor;
|
||||||
|
import org.teavm.common.SimpleFiniteExecutor;
|
||||||
|
import org.teavm.common.ThreadPoolFiniteExecutor;
|
||||||
import org.teavm.javascript.JavascriptBuilder;
|
import org.teavm.javascript.JavascriptBuilder;
|
||||||
|
import org.teavm.javascript.JavascriptBuilderFactory;
|
||||||
import org.teavm.model.*;
|
import org.teavm.model.*;
|
||||||
import org.teavm.model.resource.ClasspathClassHolderSource;
|
import org.teavm.model.resource.ClasspathClassHolderSource;
|
||||||
|
|
||||||
|
@ -68,6 +72,9 @@ public class BuildJavascriptJUnitMojo extends AbstractMojo {
|
||||||
@Parameter
|
@Parameter
|
||||||
private boolean minifying = true;
|
private boolean minifying = true;
|
||||||
|
|
||||||
|
@Parameter
|
||||||
|
private int numThreads = 1;
|
||||||
|
|
||||||
public void setProject(MavenProject project) {
|
public void setProject(MavenProject project) {
|
||||||
this.project = project;
|
this.project = project;
|
||||||
}
|
}
|
||||||
|
@ -88,8 +95,13 @@ public class BuildJavascriptJUnitMojo extends AbstractMojo {
|
||||||
this.minifying = minifying;
|
this.minifying = minifying;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setNumThreads(int numThreads) {
|
||||||
|
this.numThreads = numThreads;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute() throws MojoExecutionException, MojoFailureException {
|
public void execute() throws MojoExecutionException, MojoFailureException {
|
||||||
|
Runnable finalizer = null;
|
||||||
try {
|
try {
|
||||||
ClassLoader classLoader = prepareClassLoader();
|
ClassLoader classLoader = prepareClassLoader();
|
||||||
getLog().info("Searching for tests in the directory `" + testFiles.getAbsolutePath() + "'");
|
getLog().info("Searching for tests in the directory `" + testFiles.getAbsolutePath() + "'");
|
||||||
|
@ -146,14 +158,29 @@ public class BuildJavascriptJUnitMojo extends AbstractMojo {
|
||||||
}
|
}
|
||||||
int methodsGenerated = 0;
|
int methodsGenerated = 0;
|
||||||
log.info("Generating test files");
|
log.info("Generating test files");
|
||||||
|
FiniteExecutor executor = new SimpleFiniteExecutor();
|
||||||
|
if (numThreads != 1) {
|
||||||
|
int threads = numThreads != 0 ? numThreads : Runtime.getRuntime().availableProcessors();
|
||||||
|
final ThreadPoolFiniteExecutor threadedExecutor = new ThreadPoolFiniteExecutor(threads);
|
||||||
|
finalizer = new Runnable() {
|
||||||
|
@Override public void run() {
|
||||||
|
threadedExecutor.stop();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
executor = threadedExecutor;
|
||||||
|
}
|
||||||
for (MethodReference method : testMethods) {
|
for (MethodReference method : testMethods) {
|
||||||
log.debug("Building test for " + method);
|
log.debug("Building test for " + method);
|
||||||
decompileClassesForTest(classLoader, method, fileNames.get(method));
|
decompileClassesForTest(classLoader, method, fileNames.get(method), executor);
|
||||||
++methodsGenerated;
|
++methodsGenerated;
|
||||||
}
|
}
|
||||||
log.info("Test files successfully generated for " + methodsGenerated + " method(s)");
|
log.info("Test files successfully generated for " + methodsGenerated + " method(s)");
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new MojoFailureException("IO error occured generating JavaScript files", e);
|
throw new MojoFailureException("IO error occured generating JavaScript files", e);
|
||||||
|
} finally {
|
||||||
|
if (finalizer != null) {
|
||||||
|
finalizer.run();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,9 +216,13 @@ public class BuildJavascriptJUnitMojo extends AbstractMojo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void decompileClassesForTest(ClassLoader classLoader, MethodReference methodRef, String targetName)
|
private void decompileClassesForTest(ClassLoader classLoader, MethodReference methodRef, String targetName,
|
||||||
throws IOException {
|
FiniteExecutor executor) throws IOException {
|
||||||
JavascriptBuilder builder = new JavascriptBuilder(classLoader);
|
JavascriptBuilderFactory builderFactory = new JavascriptBuilderFactory();
|
||||||
|
builderFactory.setClassLoader(classLoader);
|
||||||
|
builderFactory.setClassSource(new ClasspathClassHolderSource(classLoader));
|
||||||
|
builderFactory.setExecutor(executor);
|
||||||
|
JavascriptBuilder builder = builderFactory.create();
|
||||||
builder.setMinifying(minifying);
|
builder.setMinifying(minifying);
|
||||||
File file = new File(outputDir, targetName);
|
File file = new File(outputDir, targetName);
|
||||||
try (Writer innerWriter = new OutputStreamWriter(new FileOutputStream(file), "UTF-8")) {
|
try (Writer innerWriter = new OutputStreamWriter(new FileOutputStream(file), "UTF-8")) {
|
||||||
|
|
|
@ -30,10 +30,13 @@ import org.apache.maven.plugins.annotations.Mojo;
|
||||||
import org.apache.maven.plugins.annotations.Parameter;
|
import org.apache.maven.plugins.annotations.Parameter;
|
||||||
import org.apache.maven.plugins.annotations.ResolutionScope;
|
import org.apache.maven.plugins.annotations.ResolutionScope;
|
||||||
import org.apache.maven.project.MavenProject;
|
import org.apache.maven.project.MavenProject;
|
||||||
|
import org.teavm.common.ThreadPoolFiniteExecutor;
|
||||||
import org.teavm.javascript.JavascriptBuilder;
|
import org.teavm.javascript.JavascriptBuilder;
|
||||||
|
import org.teavm.javascript.JavascriptBuilderFactory;
|
||||||
import org.teavm.model.MethodDescriptor;
|
import org.teavm.model.MethodDescriptor;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
import org.teavm.model.ValueType;
|
import org.teavm.model.ValueType;
|
||||||
|
import org.teavm.model.resource.ClasspathClassHolderSource;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -71,6 +74,9 @@ public class BuildJavascriptMojo extends AbstractMojo {
|
||||||
@Parameter
|
@Parameter
|
||||||
private boolean bytecodeLogging;
|
private boolean bytecodeLogging;
|
||||||
|
|
||||||
|
@Parameter(required = false)
|
||||||
|
private int numThreads = 1;
|
||||||
|
|
||||||
public void setProject(MavenProject project) {
|
public void setProject(MavenProject project) {
|
||||||
this.project = project;
|
this.project = project;
|
||||||
}
|
}
|
||||||
|
@ -99,13 +105,31 @@ public class BuildJavascriptMojo extends AbstractMojo {
|
||||||
this.mainPageIncluded = mainPageIncluded;
|
this.mainPageIncluded = mainPageIncluded;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setNumThreads(int numThreads) {
|
||||||
|
this.numThreads = numThreads;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute() throws MojoExecutionException {
|
public void execute() throws MojoExecutionException {
|
||||||
Log log = getLog();
|
Log log = getLog();
|
||||||
|
Runnable finalizer = null;
|
||||||
try {
|
try {
|
||||||
ClassLoader classLoader = prepareClassLoader();
|
ClassLoader classLoader = prepareClassLoader();
|
||||||
log.info("Building JavaScript file");
|
log.info("Building JavaScript file");
|
||||||
JavascriptBuilder builder = new JavascriptBuilder(classLoader);
|
JavascriptBuilderFactory builderFactory = new JavascriptBuilderFactory();
|
||||||
|
builderFactory.setClassLoader(classLoader);
|
||||||
|
builderFactory.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();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
builderFactory.setExecutor(executor);
|
||||||
|
}
|
||||||
|
JavascriptBuilder builder = builderFactory.create();
|
||||||
builder.setMinifying(minifying);
|
builder.setMinifying(minifying);
|
||||||
builder.setBytecodeLogging(bytecodeLogging);
|
builder.setBytecodeLogging(bytecodeLogging);
|
||||||
MethodDescriptor mainMethodDesc = new MethodDescriptor("main", ValueType.arrayOf(
|
MethodDescriptor mainMethodDesc = new MethodDescriptor("main", ValueType.arrayOf(
|
||||||
|
@ -133,6 +157,10 @@ public class BuildJavascriptMojo extends AbstractMojo {
|
||||||
throw new MojoExecutionException("Unexpected error occured", e);
|
throw new MojoExecutionException("Unexpected error occured", e);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new MojoExecutionException("IO error occured", e);
|
throw new MojoExecutionException("IO error occured", e);
|
||||||
|
} finally {
|
||||||
|
if (finalizer != null) {
|
||||||
|
finalizer.run();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user