Refactor TeaVM to support pluggable targets like JavaScript, WebAssembly, LLVM, etc (with only JavaScript target for now)

This commit is contained in:
Alexey Andreev 2016-07-22 16:33:25 +03:00
parent 1f30e5fd88
commit 52ace0c252
25 changed files with 417 additions and 566 deletions

View File

@ -24,15 +24,12 @@ import java.util.ServiceLoader;
import org.teavm.classlib.impl.lambda.LambdaMetafactorySubstitutor; import org.teavm.classlib.impl.lambda.LambdaMetafactorySubstitutor;
import org.teavm.classlib.impl.unicode.CLDRReader; import org.teavm.classlib.impl.unicode.CLDRReader;
import org.teavm.classlib.java.lang.reflect.AnnotationDependencyListener; import org.teavm.classlib.java.lang.reflect.AnnotationDependencyListener;
import org.teavm.javascript.target.TeaVMJavaScriptHost;
import org.teavm.model.MethodReference; import org.teavm.model.MethodReference;
import org.teavm.platform.PlatformClass; import org.teavm.platform.PlatformClass;
import org.teavm.vm.spi.TeaVMHost; import org.teavm.vm.spi.TeaVMHost;
import org.teavm.vm.spi.TeaVMPlugin; import org.teavm.vm.spi.TeaVMPlugin;
/**
*
* @author Alexey Andreev
*/
public class JCLPlugin implements TeaVMPlugin { public class JCLPlugin implements TeaVMPlugin {
@Override @Override
public void install(TeaVMHost host) { public void install(TeaVMHost host) {
@ -40,7 +37,11 @@ public class JCLPlugin implements TeaVMPlugin {
host.add(serviceLoaderSupp); host.add(serviceLoaderSupp);
MethodReference loadServicesMethod = new MethodReference(ServiceLoader.class, "loadServices", MethodReference loadServicesMethod = new MethodReference(ServiceLoader.class, "loadServices",
PlatformClass.class, Object[].class); PlatformClass.class, Object[].class);
host.add(loadServicesMethod, serviceLoaderSupp); TeaVMJavaScriptHost jsExtension = host.getExtension(TeaVMJavaScriptHost.class);
if (jsExtension != null) {
jsExtension.add(loadServicesMethod, serviceLoaderSupp);
}
JavacSupport javacSupport = new JavacSupport(); JavacSupport javacSupport = new JavacSupport();
host.add(javacSupport); host.add(javacSupport);

View File

@ -14,7 +14,7 @@
<property key="Bundle-Description" value="TeaVM Java class library emulation" /> <property key="Bundle-Description" value="TeaVM Java class library emulation" />
<property key="Export-Package" value="org.teavm.classlib.*" /> <property key="Export-Package" value="org.teavm.classlib.*" />
<property key="Bundle-Name" value="TeaVM Java class library" /> <property key="Bundle-Name" value="TeaVM Java class library" />
<property key="Include-Resource" value="html/jcl.html=$MODULE_DIR$/src/main/resources/html/jcl.html,html/annotation_obj.png=$MODULE_DIR$/src/main/resources/html/annotation_obj.png,html/enum_obj.png=$MODULE_DIR$/src/main/resources/html/enum_obj.png,html/jcl.css=$MODULE_DIR$/src/main/resources/html/jcl.css,html/package_obj.png=$MODULE_DIR$/src/main/resources/html/package_obj.png,html/field_public_obj.png=$MODULE_DIR$/src/main/resources/html/field_public_obj.png,html/class_obj.png=$MODULE_DIR$/src/main/resources/html/class_obj.png,html/int_obj.png=$MODULE_DIR$/src/main/resources/html/int_obj.png,html/jcl-class.html=$MODULE_DIR$/src/main/resources/html/jcl-class.html,html/methpro_obj.png=$MODULE_DIR$/src/main/resources/html/methpro_obj.png,html/methpub_obj.png=$MODULE_DIR$/src/main/resources/html/methpub_obj.png,html/field_protected_obj.png=$MODULE_DIR$/src/main/resources/html/field_protected_obj.png,META-INF/teavm.properties=$MODULE_DIR$/src/main/resources/META-INF/teavm.properties,META-INF/services/org.teavm.vm.spi.TeaVMPlugin=$MODULE_DIR$/src/main/resources/META-INF/services/org.teavm.vm.spi.TeaVMPlugin,org/teavm/classlib/impl/tz/tzdata2015d.zip=$MODULE_DIR$/src/main/resources/org/teavm/classlib/impl/tz/tzdata2015d.zip,org/teavm/classlib/impl/currency/iso4217.xml=$MODULE_DIR$/src/main/resources/org/teavm/classlib/impl/currency/iso4217.xml,org/teavm/classlib/impl/currency/iso3166.csv=$MODULE_DIR$/src/main/resources/org/teavm/classlib/impl/currency/iso3166.csv,org/teavm/classlib/impl/unicode/UnicodeData.txt=$MODULE_DIR$/src/main/resources/org/teavm/classlib/impl/unicode/UnicodeData.txt,org/teavm/classlib/impl/unicode/cldr-json.zip=$MODULE_DIR$/src/main/resources/org/teavm/classlib/impl/unicode/cldr-json.zip" /> <property key="Include-Resource" value="org/teavm/classlib/impl/tz/tzdata2015d.zip=$MODULE_DIR$/src/main/resources/org/teavm/classlib/impl/tz/tzdata2015d.zip,org/teavm/classlib/impl/currency/iso3166.csv=$MODULE_DIR$/src/main/resources/org/teavm/classlib/impl/currency/iso3166.csv,org/teavm/classlib/impl/currency/iso4217.xml=$MODULE_DIR$/src/main/resources/org/teavm/classlib/impl/currency/iso4217.xml,org/teavm/classlib/impl/unicode/cldr-json.zip=$MODULE_DIR$/src/main/resources/org/teavm/classlib/impl/unicode/cldr-json.zip,org/teavm/classlib/impl/unicode/UnicodeData.txt=$MODULE_DIR$/src/main/resources/org/teavm/classlib/impl/unicode/UnicodeData.txt,html/methpro_obj.png=$MODULE_DIR$/src/main/resources/html/methpro_obj.png,html/enum_obj.png=$MODULE_DIR$/src/main/resources/html/enum_obj.png,html/class_obj.png=$MODULE_DIR$/src/main/resources/html/class_obj.png,html/annotation_obj.png=$MODULE_DIR$/src/main/resources/html/annotation_obj.png,html/methpub_obj.png=$MODULE_DIR$/src/main/resources/html/methpub_obj.png,html/jcl-class.html=$MODULE_DIR$/src/main/resources/html/jcl-class.html,html/package_obj.png=$MODULE_DIR$/src/main/resources/html/package_obj.png,html/field_public_obj.png=$MODULE_DIR$/src/main/resources/html/field_public_obj.png,html/jcl.html=$MODULE_DIR$/src/main/resources/html/jcl.html,html/jcl.css=$MODULE_DIR$/src/main/resources/html/jcl.css,html/field_protected_obj.png=$MODULE_DIR$/src/main/resources/html/field_protected_obj.png,html/int_obj.png=$MODULE_DIR$/src/main/resources/html/int_obj.png,META-INF/teavm.properties=$MODULE_DIR$/src/main/resources/META-INF/teavm.properties,META-INF/services/org.teavm.vm.spi.TeaVMPlugin=$MODULE_DIR$/src/main/resources/META-INF/services/org.teavm.vm.spi.TeaVMPlugin" />
</additionalProperties> </additionalProperties>
<additionalJARContents /> <additionalJARContents />
</configuration> </configuration>

View File

@ -18,10 +18,6 @@ package org.teavm.debugging.information;
import org.teavm.codegen.LocationProvider; import org.teavm.codegen.LocationProvider;
import org.teavm.model.MethodDescriptor; import org.teavm.model.MethodDescriptor;
/**
*
* @author Alexey Andreev
*/
public interface DebugInformationEmitter { public interface DebugInformationEmitter {
void setLocationProvider(LocationProvider locationProvider); void setLocationProvider(LocationProvider locationProvider);

View File

@ -18,10 +18,6 @@ package org.teavm.vm;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
/**
*
* @author Alexey Andreev
*/
public interface BuildTarget { public interface BuildTarget {
OutputStream createResource(String fileName) throws IOException; OutputStream createResource(String fileName) throws IOException;
} }

View File

@ -19,58 +19,32 @@ import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Properties; import java.util.Properties;
import java.util.ServiceLoader; import java.util.ServiceLoader;
import java.util.Set; import java.util.stream.Collectors;
import org.teavm.cache.NoCache; import org.teavm.cache.NoCache;
import org.teavm.codegen.AliasProvider;
import org.teavm.codegen.DefaultAliasProvider;
import org.teavm.codegen.DefaultNamingStrategy;
import org.teavm.codegen.MinifyingAliasProvider;
import org.teavm.codegen.SourceWriter;
import org.teavm.codegen.SourceWriterBuilder;
import org.teavm.common.ServiceRepository; import org.teavm.common.ServiceRepository;
import org.teavm.debugging.information.DebugInformationEmitter;
import org.teavm.debugging.information.SourceLocation;
import org.teavm.dependency.BootstrapMethodSubstitutor; import org.teavm.dependency.BootstrapMethodSubstitutor;
import org.teavm.dependency.DependencyChecker; import org.teavm.dependency.DependencyChecker;
import org.teavm.dependency.DependencyInfo; import org.teavm.dependency.DependencyInfo;
import org.teavm.dependency.DependencyListener; import org.teavm.dependency.DependencyListener;
import org.teavm.dependency.Linker; import org.teavm.dependency.Linker;
import org.teavm.dependency.MethodDependency;
import org.teavm.diagnostics.AccumulationDiagnostics; import org.teavm.diagnostics.AccumulationDiagnostics;
import org.teavm.diagnostics.Diagnostics;
import org.teavm.diagnostics.ProblemProvider; import org.teavm.diagnostics.ProblemProvider;
import org.teavm.javascript.Decompiler;
import org.teavm.javascript.EmptyRegularMethodNodeCache;
import org.teavm.javascript.MethodNodeCache;
import org.teavm.javascript.Renderer;
import org.teavm.javascript.RenderingException; import org.teavm.javascript.RenderingException;
import org.teavm.javascript.ast.ClassNode;
import org.teavm.javascript.spi.GeneratedBy;
import org.teavm.javascript.spi.Generator;
import org.teavm.javascript.spi.InjectedBy;
import org.teavm.javascript.spi.Injector;
import org.teavm.model.BasicBlock;
import org.teavm.model.CallLocation;
import org.teavm.model.ClassHolder; import org.teavm.model.ClassHolder;
import org.teavm.model.ClassHolderSource; import org.teavm.model.ClassHolderSource;
import org.teavm.model.ClassHolderTransformer; import org.teavm.model.ClassHolderTransformer;
import org.teavm.model.ClassReader; import org.teavm.model.ClassReader;
import org.teavm.model.ClassReaderSource; import org.teavm.model.ClassReaderSource;
import org.teavm.model.ElementHolder;
import org.teavm.model.ElementModifier;
import org.teavm.model.InstructionLocation;
import org.teavm.model.ListableClassHolderSource; import org.teavm.model.ListableClassHolderSource;
import org.teavm.model.ListableClassReaderSource; import org.teavm.model.ListableClassReaderSource;
import org.teavm.model.MethodHolder; import org.teavm.model.MethodHolder;
@ -78,15 +52,6 @@ import org.teavm.model.MethodReference;
import org.teavm.model.MutableClassHolderSource; import org.teavm.model.MutableClassHolderSource;
import org.teavm.model.Program; import org.teavm.model.Program;
import org.teavm.model.ProgramCache; import org.teavm.model.ProgramCache;
import org.teavm.model.ValueType;
import org.teavm.model.Variable;
import org.teavm.model.instructions.ConstructInstruction;
import org.teavm.model.instructions.InvocationType;
import org.teavm.model.instructions.InvokeInstruction;
import org.teavm.model.instructions.RaiseInstruction;
import org.teavm.model.instructions.StringConstantInstruction;
import org.teavm.model.util.AsyncMethodFinder;
import org.teavm.model.util.ListingBuilder;
import org.teavm.model.util.MissingItemsProcessor; import org.teavm.model.util.MissingItemsProcessor;
import org.teavm.model.util.ModelUtils; import org.teavm.model.util.ModelUtils;
import org.teavm.model.util.ProgramUtils; import org.teavm.model.util.ProgramUtils;
@ -103,8 +68,8 @@ import org.teavm.optimization.MethodOptimization;
import org.teavm.optimization.RedundantJumpElimination; import org.teavm.optimization.RedundantJumpElimination;
import org.teavm.optimization.UnreachableBasicBlockElimination; import org.teavm.optimization.UnreachableBasicBlockElimination;
import org.teavm.optimization.UnusedVariableElimination; import org.teavm.optimization.UnusedVariableElimination;
import org.teavm.vm.spi.RendererListener;
import org.teavm.vm.spi.TeaVMHost; import org.teavm.vm.spi.TeaVMHost;
import org.teavm.vm.spi.TeaVMHostExtension;
import org.teavm.vm.spi.TeaVMPlugin; import org.teavm.vm.spi.TeaVMPlugin;
/** /**
@ -141,29 +106,24 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
private final DependencyChecker dependencyChecker; private final DependencyChecker dependencyChecker;
private final AccumulationDiagnostics diagnostics = new AccumulationDiagnostics(); private final AccumulationDiagnostics diagnostics = new AccumulationDiagnostics();
private final ClassLoader classLoader; private final ClassLoader classLoader;
private boolean minifying = true;
private boolean bytecodeLogging;
private final OutputStream logStream = System.out;
private final Map<String, TeaVMEntryPoint> entryPoints = new HashMap<>(); private final Map<String, TeaVMEntryPoint> entryPoints = new HashMap<>();
private final Map<String, TeaVMEntryPoint> readonlyEntryPoints = Collections.unmodifiableMap(entryPoints);
private final Map<String, String> exportedClasses = new HashMap<>(); private final Map<String, String> exportedClasses = new HashMap<>();
private final Map<MethodReference, Generator> methodGenerators = new HashMap<>(); private final Map<String, String> readonlyExportedClasses = Collections.unmodifiableMap(exportedClasses);
private final Map<MethodReference, Injector> methodInjectors = new HashMap<>();
private final List<RendererListener> rendererListeners = new ArrayList<>();
private final Map<Class<?>, Object> services = new HashMap<>(); private final Map<Class<?>, Object> services = new HashMap<>();
private final Properties properties = new Properties(); private final Properties properties = new Properties();
private DebugInformationEmitter debugEmitter;
private ProgramCache programCache; private ProgramCache programCache;
private MethodNodeCache astCache = new EmptyRegularMethodNodeCache();
private boolean incremental; private boolean incremental;
private TeaVMProgressListener progressListener; private TeaVMProgressListener progressListener;
private boolean cancelled; private boolean cancelled;
private ListableClassHolderSource writtenClasses; private ListableClassHolderSource writtenClasses;
private final Set<MethodReference> asyncMethods = new HashSet<>(); private TeaVMTarget target;
private final Set<MethodReference> asyncFamilyMethods = new HashSet<>(); private Map<Class<?>, TeaVMHostExtension> extensions = new HashMap<>();
TeaVM(ClassReaderSource classSource, ClassLoader classLoader) { TeaVM(TeaVMBuilder builder) {
this.classSource = classSource; target = builder.target;
this.classLoader = classLoader; classSource = builder.classSource;
classLoader = builder.classLoader;
dependencyChecker = new DependencyChecker(this.classSource, classLoader, this, diagnostics); dependencyChecker = new DependencyChecker(this.classSource, classLoader, this, diagnostics);
progressListener = new TeaVMProgressListener() { progressListener = new TeaVMProgressListener() {
@Override public TeaVMProgressFeedback progressReached(int progress) { @Override public TeaVMProgressFeedback progressReached(int progress) {
@ -173,6 +133,12 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
return TeaVMProgressFeedback.CONTINUE; return TeaVMProgressFeedback.CONTINUE;
} }
}; };
for (TeaVMHostExtension extension : target.getHostExtensions()) {
for (Class<?> extensionType : getExtensionTypes(extension)) {
extensions.put(extensionType, extension);
}
}
} }
@Override @Override
@ -185,59 +151,16 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
dependencyChecker.addClassTransformer(transformer); dependencyChecker.addClassTransformer(transformer);
} }
@Override
public void add(MethodReference methodRef, Generator generator) {
methodGenerators.put(methodRef, generator);
}
@Override
public void add(MethodReference methodRef, Injector injector) {
methodInjectors.put(methodRef, injector);
}
@Override @Override
public void add(MethodReference methodRef, BootstrapMethodSubstitutor substitutor) { public void add(MethodReference methodRef, BootstrapMethodSubstitutor substitutor) {
dependencyChecker.addBootstrapMethodSubstitutor(methodRef, substitutor); dependencyChecker.addBootstrapMethodSubstitutor(methodRef, substitutor);
} }
@Override
public void add(RendererListener listener) {
rendererListeners.add(listener);
}
@Override @Override
public ClassLoader getClassLoader() { public ClassLoader getClassLoader() {
return classLoader; return classLoader;
} }
/**
* Reports whether this TeaVM instance uses obfuscation when generating the JavaScript code.
*
* @see #setMinifying(boolean)
* @return whether TeaVM produces obfuscated code.
*/
public boolean isMinifying() {
return minifying;
}
/**
* Specifies whether this TeaVM instance uses obfuscation when generating the JavaScript code.
*
* @see #isMinifying()
* @param minifying whether TeaVM should obfuscate code.
*/
public void setMinifying(boolean minifying) {
this.minifying = minifying;
}
public boolean isBytecodeLogging() {
return bytecodeLogging;
}
public void setBytecodeLogging(boolean bytecodeLogging) {
this.bytecodeLogging = bytecodeLogging;
}
/** /**
* Specifies configuration properties for TeaVM and its plugins. You should call this method before * Specifies configuration properties for TeaVM and its plugins. You should call this method before
* installing any plugins or interceptors. * installing any plugins or interceptors.
@ -257,14 +180,6 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
return new Properties(properties); return new Properties(properties);
} }
public MethodNodeCache getAstCache() {
return astCache;
}
public void setAstCache(MethodNodeCache methodAstCache) {
this.astCache = methodAstCache;
}
public ProgramCache getProgramCache() { public ProgramCache getProgramCache() {
return programCache; return programCache;
} }
@ -391,14 +306,6 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
return writtenClasses; return writtenClasses;
} }
public DebugInformationEmitter getDebugEmitter() {
return debugEmitter;
}
public void setDebugEmitter(DebugInformationEmitter debugEmitter) {
this.debugEmitter = debugEmitter;
}
/** /**
* <p>Does actual build. Call this method after TeaVM is fully configured and all entry points * <p>Does actual build. Call this method after TeaVM is fully configured and all entry points
* are specified. This method may fail if there are items (classes, methods and fields) * are specified. This method may fail if there are items (classes, methods and fields)
@ -406,52 +313,23 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
* actual generation happens and no exceptions thrown, but you can further call * actual generation happens and no exceptions thrown, but you can further call
* {@link #getProblemProvider()} to learn the build state.</p> * {@link #getProblemProvider()} to learn the build state.</p>
* *
* @param writer where to generate JavaScript. Should not be null. * @param output where to generate JavaScript. Should not be null.
* @param target where to generate additional resources. Can be null, but if there are * @param buildTarget where to generate additional resources. Can be null, but if there are
* plugins or inteceptors that generate additional resources, the build process will fail. * plugins or inteceptors that generate additional resources, the build process will fail.
* *
* @throws RenderingException when something went wrong during rendering phase. * @throws RenderingException when something went wrong during rendering phase.
*/ */
public void build(Appendable writer, BuildTarget target) throws RenderingException { public void build(OutputStream output, BuildTarget buildTarget) throws RenderingException {
target.setController(targetController);
// Check dependencies // Check dependencies
reportPhase(TeaVMPhase.DEPENDENCY_CHECKING, 1); reportPhase(TeaVMPhase.DEPENDENCY_CHECKING, 1);
if (wasCancelled()) { if (wasCancelled()) {
return; return;
} }
AliasProvider aliasProvider = minifying ? new MinifyingAliasProvider() : new DefaultAliasProvider();
dependencyChecker.setInterruptor(() -> progressListener.progressReached(0) == TeaVMProgressFeedback.CONTINUE); dependencyChecker.setInterruptor(() -> progressListener.progressReached(0) == TeaVMProgressFeedback.CONTINUE);
dependencyChecker.linkMethod(new MethodReference(Class.class.getName(), "getClass", target.contributeDependencies(dependencyChecker);
ValueType.object("org.teavm.platform.PlatformClass"), ValueType.parse(Class.class)), null).use();
dependencyChecker.linkMethod(new MethodReference(String.class, "<init>", char[].class, void.class),
null).use();
dependencyChecker.linkMethod(new MethodReference(String.class, "getChars", int.class, int.class, char[].class,
int.class, void.class), null).use();
MethodDependency internDep = dependencyChecker.linkMethod(new MethodReference(String.class, "intern",
String.class), null);
internDep.getVariable(0).propagate(dependencyChecker.getType("java.lang.String"));
internDep.use();
dependencyChecker.linkMethod(new MethodReference(String.class, "length", int.class), null).use();
dependencyChecker.linkMethod(new MethodReference(Object.class, "clone", Object.class), null).use();
dependencyChecker.linkMethod(new MethodReference(Thread.class, "currentThread", Thread.class), null).use();
dependencyChecker.linkMethod(new MethodReference(Thread.class, "getMainThread", Thread.class), null).use();
dependencyChecker.linkMethod(
new MethodReference(Thread.class, "setCurrentThread", Thread.class, void.class), null).use();
MethodDependency exceptionCons = dependencyChecker.linkMethod(new MethodReference(
NoClassDefFoundError.class, "<init>", String.class, void.class), null);
exceptionCons.use();
exceptionCons.getVariable(0).propagate(dependencyChecker.getType(NoClassDefFoundError.class.getName()));
exceptionCons.getVariable(1).propagate(dependencyChecker.getType("java.lang.String"));
exceptionCons = dependencyChecker.linkMethod(new MethodReference(NoSuchFieldError.class, "<init>",
String.class, void.class), null);
exceptionCons.use();
exceptionCons.getVariable(0).propagate(dependencyChecker.getType(NoSuchFieldError.class.getName()));
exceptionCons.getVariable(1).propagate(dependencyChecker.getType("java.lang.String"));
exceptionCons = dependencyChecker.linkMethod(new MethodReference(NoSuchMethodError.class, "<init>",
String.class, void.class), null);
exceptionCons.use();
exceptionCons.getVariable(0).propagate(dependencyChecker.getType(NoSuchMethodError.class.getName()));
exceptionCons.getVariable(1).propagate(dependencyChecker.getType("java.lang.String"));
dependencyChecker.processDependencies(); dependencyChecker.processDependencies();
if (wasCancelled() || !diagnostics.getSevereProblems().isEmpty()) { if (wasCancelled() || !diagnostics.getSevereProblems().isEmpty()) {
return; return;
@ -469,73 +347,27 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
} }
// Optimize and allocate registers // Optimize and allocate registers
reportPhase(TeaVMPhase.OPTIMIZATION, 1);
if (!incremental) { if (!incremental) {
devirtualize(classSet, dependencyChecker); devirtualize(classSet, dependencyChecker);
if (wasCancelled()) { if (wasCancelled()) {
return; return;
} }
inline(classSet);
if (wasCancelled()) {
return;
}
} }
List<ClassNode> clsNodes = modelToAst(classSet); optimize(classSet);
// Render
reportPhase(TeaVMPhase.RENDERING, classSet.getClassNames().size());
if (wasCancelled()) { if (wasCancelled()) {
return; return;
} }
DefaultNamingStrategy naming = new DefaultNamingStrategy(aliasProvider, dependencyChecker.getClassSource());
SourceWriterBuilder builder = new SourceWriterBuilder(naming); // Render
builder.setMinified(minifying); target.emit(classSet, output, buildTarget);
SourceWriter sourceWriter = builder.build(writer);
Renderer renderer = new Renderer(sourceWriter, classSet, classLoader, this, asyncMethods, asyncFamilyMethods,
diagnostics);
renderer.setProperties(properties);
renderer.setMinifying(minifying);
if (debugEmitter != null) {
int classIndex = 0;
for (String className : classSet.getClassNames()) {
ClassHolder cls = classSet.get(className);
for (MethodHolder method : cls.getMethods()) {
if (method.getProgram() != null) {
emitCFG(debugEmitter, method.getProgram());
}
}
reportProgress(++classIndex);
if (wasCancelled()) {
return;
}
}
renderer.setDebugEmitter(debugEmitter);
}
renderer.getDebugEmitter().setLocationProvider(sourceWriter);
for (Map.Entry<MethodReference, Injector> entry : methodInjectors.entrySet()) {
renderer.addInjector(entry.getKey(), entry.getValue());
}
try {
for (RendererListener listener : rendererListeners) {
listener.begin(renderer, target);
}
sourceWriter.append("\"use strict\";").newLine();
renderer.renderRuntime();
renderer.render(clsNodes);
renderer.renderStringPool();
renderer.renderStringConstants();
for (Map.Entry<String, TeaVMEntryPoint> entry : entryPoints.entrySet()) {
sourceWriter.append("var ").append(entry.getKey()).ws().append("=").ws();
MethodReference ref = entry.getValue().reference;
sourceWriter.append(naming.getFullNameFor(ref));
sourceWriter.append(";").newLine();
}
for (Map.Entry<String, String> entry : exportedClasses.entrySet()) {
sourceWriter.append("var ").append(entry.getKey()).ws().append("=").ws()
.appendClass(entry.getValue()).append(";").newLine();
}
for (RendererListener listener : rendererListeners) {
listener.complete();
}
} catch (IOException e) {
throw new RenderingException("IO Error occured", e);
}
} }
@SuppressWarnings("WeakerAccess") @SuppressWarnings("WeakerAccess")
@ -568,38 +400,11 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
} }
} }
private void reportProgress(int progress) { private void devirtualize(ListableClassHolderSource classes, DependencyInfo dependency) {
if (progressListener.progressReached(progress) == TeaVMProgressFeedback.CANCEL) {
cancelled = true;
}
}
private void emitCFG(DebugInformationEmitter emitter, Program program) {
Map<InstructionLocation, InstructionLocation[]> cfg = ProgramUtils.getLocationCFG(program);
for (Map.Entry<InstructionLocation, InstructionLocation[]> entry : cfg.entrySet()) {
SourceLocation location = map(entry.getKey());
SourceLocation[] successors = new SourceLocation[entry.getValue().length];
for (int i = 0; i < entry.getValue().length; ++i) {
successors[i] = map(entry.getValue()[i]);
}
emitter.addSuccessors(location, successors);
}
}
private static SourceLocation map(InstructionLocation location) {
if (location == null) {
return null;
}
return new SourceLocation(location.getFileName(), location.getLine());
}
private void devirtualize(ListableClassHolderSource classes, DependencyInfo dependency) {
reportPhase(TeaVMPhase.DEVIRTUALIZATION, classes.getClassNames().size());
if (wasCancelled()) { if (wasCancelled()) {
return; return;
} }
Devirtualization devirtualization = new Devirtualization(dependency, classes); Devirtualization devirtualization = new Devirtualization(dependency, classes);
int index = 0;
for (String className : classes.getClassNames()) { for (String className : classes.getClassNames()) {
ClassHolder cls = classes.get(className); ClassHolder cls = classes.get(className);
for (final MethodHolder method : cls.getMethods()) { for (final MethodHolder method : cls.getMethods()) {
@ -607,12 +412,13 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
devirtualization.apply(method); devirtualization.apply(method);
} }
} }
reportProgress(++index);
if (wasCancelled()) { if (wasCancelled()) {
return; return;
} }
} }
}
private void inline(ListableClassHolderSource classes) {
Inlining inlining = new Inlining(); Inlining inlining = new Inlining();
for (String className : classes.getClassNames()) { for (String className : classes.getClassNames()) {
ClassHolder cls = classes.get(className); ClassHolder cls = classes.get(className);
@ -621,90 +427,22 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
inlining.apply(method.getProgram(), classes); inlining.apply(method.getProgram(), classes);
} }
} }
reportProgress(++index);
if (wasCancelled()) { if (wasCancelled()) {
return; return;
} }
} }
} }
private List<ClassNode> modelToAst(ListableClassHolderSource classes) { private void optimize(ListableClassHolderSource classSource) {
AsyncMethodFinder asyncFinder = new AsyncMethodFinder(dependencyChecker.getCallGraph(), diagnostics); for (String className : classSource.getClassNames()) {
asyncFinder.find(classes); ClassHolder cls = classSource.get(className);
asyncMethods.addAll(asyncFinder.getAsyncMethods()); for (MethodHolder method : cls.getMethods()) {
asyncFamilyMethods.addAll(asyncFinder.getAsyncFamilyMethods()); processMethod(method);
}
progressListener.phaseStarted(TeaVMPhase.DECOMPILATION, classes.getClassNames().size()); if (wasCancelled()) {
Decompiler decompiler = new Decompiler(classes, classLoader, asyncMethods, asyncFamilyMethods); return;
decompiler.setRegularMethodCache(incremental ? astCache : null);
for (Map.Entry<MethodReference, Generator> entry : methodGenerators.entrySet()) {
decompiler.addGenerator(entry.getKey(), entry.getValue());
}
for (MethodReference injectedMethod : methodInjectors.keySet()) {
decompiler.addMethodToPass(injectedMethod);
}
List<String> classOrder = decompiler.getClassOrdering(classes.getClassNames());
List<ClassNode> classNodes = new ArrayList<>();
int index = 0;
try (PrintWriter bytecodeLogger = bytecodeLogging
? new PrintWriter(new OutputStreamWriter(logStream, "UTF-8")) : null) {
for (String className : classOrder) {
ClassHolder cls = classes.get(className);
for (MethodHolder method : cls.getMethods()) {
processMethod(method);
preprocessNativeMethod(method);
if (bytecodeLogging) {
logMethodBytecode(bytecodeLogger, method);
}
}
classNodes.add(decompiler.decompile(cls));
progressListener.progressReached(++index);
} }
} catch (UnsupportedEncodingException e) {
throw new AssertionError("UTF-8 is expected to be supported");
} }
return classNodes;
}
private void preprocessNativeMethod(MethodHolder method) {
if (!method.getModifiers().contains(ElementModifier.NATIVE)
|| methodGenerators.get(method.getReference()) != null
|| methodInjectors.get(method.getReference()) != null
|| method.getAnnotations().get(GeneratedBy.class.getName()) != null
|| method.getAnnotations().get(InjectedBy.class.getName()) != null) {
return;
}
method.getModifiers().remove(ElementModifier.NATIVE);
Program program = new Program();
method.setProgram(program);
BasicBlock block = program.createBasicBlock();
Variable exceptionVar = program.createVariable();
ConstructInstruction newExceptionInsn = new ConstructInstruction();
newExceptionInsn.setType(NoSuchMethodError.class.getName());
newExceptionInsn.setReceiver(exceptionVar);
block.getInstructions().add(newExceptionInsn);
Variable constVar = program.createVariable();
StringConstantInstruction constInsn = new StringConstantInstruction();
constInsn.setConstant("Native method implementation not found: " + method.getReference());
constInsn.setReceiver(constVar);
block.getInstructions().add(constInsn);
InvokeInstruction initExceptionInsn = new InvokeInstruction();
initExceptionInsn.setInstance(exceptionVar);
initExceptionInsn.setMethod(new MethodReference(NoSuchMethodError.class, "<init>", String.class, void.class));
initExceptionInsn.setType(InvocationType.SPECIAL);
initExceptionInsn.getArguments().add(constVar);
block.getInstructions().add(initExceptionInsn);
RaiseInstruction raiseInsn = new RaiseInstruction();
raiseInsn.setException(exceptionVar);
block.getInstructions().add(raiseInsn);
diagnostics.error(new CallLocation(method.getReference()), "Native method {{m0}} has no implementation",
method.getReference());
} }
private void processMethod(MethodHolder method) { private void processMethod(MethodHolder method) {
@ -725,8 +463,11 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
changed |= optimization.optimize(method, optimizedProgram); changed |= optimization.optimize(method, optimizedProgram);
} }
} while (changed); } while (changed);
RegisterAllocator allocator = new RegisterAllocator();
allocator.allocateRegisters(method, optimizedProgram); if (target.requiresRegisterAllocation()) {
RegisterAllocator allocator = new RegisterAllocator();
allocator.allocateRegisters(method, optimizedProgram);
}
} }
if (incremental && programCache != null) { if (incremental && programCache != null) {
programCache.store(method.getReference(), optimizedProgram); programCache.store(method.getReference(), optimizedProgram);
@ -749,102 +490,9 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
new UnreachableBasicBlockElimination()); new UnreachableBasicBlockElimination());
} }
private void logMethodBytecode(PrintWriter writer, MethodHolder method) {
writer.print(" ");
printModifiers(writer, method);
writer.print(method.getName() + "(");
ValueType[] parameterTypes = method.getParameterTypes();
for (int i = 0; i < parameterTypes.length; ++i) {
if (i > 0) {
writer.print(", ");
}
printType(writer, parameterTypes[i]);
}
writer.println(")");
Program program = method.getProgram();
if (program != null && program.basicBlockCount() > 0) {
ListingBuilder builder = new ListingBuilder();
writer.print(builder.buildListing(program, " "));
writer.print(" Register allocation:");
for (int i = 0; i < program.variableCount(); ++i) {
writer.print(i + ":" + program.variableAt(i).getRegister() + " ");
}
writer.println();
writer.println();
writer.flush();
} else {
writer.println();
}
}
private void printType(PrintWriter writer, ValueType type) {
if (type instanceof ValueType.Object) {
writer.print(((ValueType.Object) type).getClassName());
} else if (type instanceof ValueType.Array) {
printType(writer, ((ValueType.Array) type).getItemType());
writer.print("[]");
} else if (type instanceof ValueType.Primitive) {
switch (((ValueType.Primitive) type).getKind()) {
case BOOLEAN:
writer.print("boolean");
break;
case SHORT:
writer.print("short");
break;
case BYTE:
writer.print("byte");
break;
case CHARACTER:
writer.print("char");
break;
case DOUBLE:
writer.print("double");
break;
case FLOAT:
writer.print("float");
break;
case INTEGER:
writer.print("int");
break;
case LONG:
writer.print("long");
break;
}
}
}
private void printModifiers(PrintWriter writer, ElementHolder element) {
switch (element.getLevel()) {
case PRIVATE:
writer.print("private ");
break;
case PUBLIC:
writer.print("public ");
break;
case PROTECTED:
writer.print("protected ");
break;
default:
break;
}
Set<ElementModifier> modifiers = element.getModifiers();
if (modifiers.contains(ElementModifier.ABSTRACT)) {
writer.print("abstract ");
}
if (modifiers.contains(ElementModifier.FINAL)) {
writer.print("final ");
}
if (modifiers.contains(ElementModifier.STATIC)) {
writer.print("static ");
}
if (modifiers.contains(ElementModifier.NATIVE)) {
writer.print("native ");
}
}
public void build(File dir, String fileName) throws RenderingException { public void build(File dir, String fileName) throws RenderingException {
try (Writer writer = new OutputStreamWriter(new FileOutputStream(new File(dir, fileName)), "UTF-8")) { try (OutputStream output = new FileOutputStream(new File(dir, fileName))) {
build(writer, new DirectoryBuildTarget(dir)); build(output, new DirectoryBuildTarget(dir));
} catch (UnsupportedEncodingException e) { } catch (UnsupportedEncodingException e) {
throw new RuntimeException("Platform does not support UTF-8", e); throw new RuntimeException("Platform does not support UTF-8", e);
} catch (IOException e) { } catch (IOException e) {
@ -877,4 +525,69 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
public <T> void registerService(Class<T> type, T instance) { public <T> void registerService(Class<T> type, T instance) {
services.put(type, instance); services.put(type, instance);
} }
@Override
public <T extends TeaVMHostExtension> T getExtension(Class<T> extensionType) {
Object extension = extensions.get(extensionType);
return extension != null ? extensionType.cast(extension) : null;
}
private Collection<Class<? extends TeaVMHostExtension>> getExtensionTypes(TeaVMHostExtension extension) {
return Arrays.stream(extension.getClass().getInterfaces())
.filter(cls -> cls.isInterface() && TeaVMHostExtension.class.isAssignableFrom(cls))
.<Class<? extends TeaVMHostExtension>>map(cls -> cls.asSubclass(TeaVMHostExtension.class))
.collect(Collectors.toSet());
}
private TeaVMTargetController targetController = new TeaVMTargetController() {
@Override
public boolean wasCancelled() {
return TeaVM.this.wasCancelled();
}
@Override
public ClassLoader getClassLoader() {
return classLoader;
}
@Override
public ClassReaderSource getUnprocessedClassSource() {
return dependencyChecker.getClassSource();
}
@Override
public DependencyInfo getDependencyInfo() {
return dependencyChecker;
}
@Override
public Diagnostics getDiagnostics() {
return diagnostics;
}
@Override
public Properties getProperties() {
return properties;
}
@Override
public ServiceRepository getServices() {
return TeaVM.this;
}
@Override
public boolean isIncremental() {
return incremental;
}
@Override
public Map<String, TeaVMEntryPoint> getEntryPoints() {
return readonlyEntryPoints;
}
@Override
public Map<String, String> getExportedClasses() {
return readonlyExportedClasses;
}
};
} }

View File

@ -18,15 +18,13 @@ package org.teavm.vm;
import org.teavm.model.ClassHolderSource; import org.teavm.model.ClassHolderSource;
import org.teavm.parsing.ClasspathClassHolderSource; import org.teavm.parsing.ClasspathClassHolderSource;
/**
*
* @author Alexey Andreev
*/
public class TeaVMBuilder { public class TeaVMBuilder {
TeaVMTarget target;
ClassHolderSource classSource; ClassHolderSource classSource;
ClassLoader classLoader; ClassLoader classLoader;
public TeaVMBuilder() { public TeaVMBuilder(TeaVMTarget target) {
this.target = target;
classLoader = TeaVMBuilder.class.getClassLoader(); classLoader = TeaVMBuilder.class.getClassLoader();
classSource = new ClasspathClassHolderSource(classLoader); classSource = new ClasspathClassHolderSource(classLoader);
} }
@ -50,6 +48,6 @@ public class TeaVMBuilder {
} }
public TeaVM build() { public TeaVM build() {
return new TeaVM(classSource, classLoader); return new TeaVM(this);
} }
} }

View File

@ -81,6 +81,10 @@ public class TeaVMEntryPoint {
method.use(); method.use();
} }
public MethodReference getReference() {
return reference;
}
String getPublicName() { String getPublicName() {
return publicName; return publicName;
} }

View File

@ -15,14 +15,10 @@
*/ */
package org.teavm.vm; package org.teavm.vm;
/**
*
* @author Alexey Andreev
*/
public enum TeaVMPhase { public enum TeaVMPhase {
DEPENDENCY_CHECKING, DEPENDENCY_CHECKING,
LINKING, LINKING,
DEVIRTUALIZATION, OPTIMIZATION,
DECOMPILATION, DECOMPILATION,
RENDERING RENDERING
} }

View File

@ -0,0 +1,34 @@
/*
* Copyright 2016 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.vm;
import java.io.OutputStream;
import java.util.List;
import org.teavm.dependency.DependencyChecker;
import org.teavm.model.ListableClassHolderSource;
import org.teavm.vm.spi.TeaVMHostExtension;
public interface TeaVMTarget {
void setController(TeaVMTargetController controller);
List<TeaVMHostExtension> getHostExtensions();
boolean requiresRegisterAllocation();
void contributeDependencies(DependencyChecker dependencyChecker);
void emit(ListableClassHolderSource classes, OutputStream output, BuildTarget buildTarget);
}

View File

@ -0,0 +1,45 @@
/*
* Copyright 2016 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.vm;
import java.util.Map;
import java.util.Properties;
import org.teavm.common.ServiceRepository;
import org.teavm.dependency.DependencyInfo;
import org.teavm.diagnostics.Diagnostics;
import org.teavm.model.ClassReaderSource;
public interface TeaVMTargetController {
boolean wasCancelled();
ClassLoader getClassLoader();
ClassReaderSource getUnprocessedClassSource();
DependencyInfo getDependencyInfo();
Diagnostics getDiagnostics();
Properties getProperties();
ServiceRepository getServices();
boolean isIncremental();
Map<String, TeaVMEntryPoint> getEntryPoints();
Map<String, String> getExportedClasses();
}

View File

@ -18,8 +18,6 @@ package org.teavm.vm.spi;
import java.util.Properties; import java.util.Properties;
import org.teavm.dependency.BootstrapMethodSubstitutor; import org.teavm.dependency.BootstrapMethodSubstitutor;
import org.teavm.dependency.DependencyListener; import org.teavm.dependency.DependencyListener;
import org.teavm.javascript.spi.Generator;
import org.teavm.javascript.spi.Injector;
import org.teavm.model.ClassHolderTransformer; import org.teavm.model.ClassHolderTransformer;
import org.teavm.model.MethodReference; import org.teavm.model.MethodReference;
import org.teavm.vm.TeaVM; import org.teavm.vm.TeaVM;
@ -36,13 +34,9 @@ public interface TeaVMHost {
void add(ClassHolderTransformer classTransformer); void add(ClassHolderTransformer classTransformer);
void add(MethodReference methodRef, Generator generator);
void add(MethodReference methodRef, Injector injector);
void add(MethodReference methodRef, BootstrapMethodSubstitutor substitutor); void add(MethodReference methodRef, BootstrapMethodSubstitutor substitutor);
void add(RendererListener listener); <T extends TeaVMHostExtension> T getExtension(Class<T> extensionType);
<T> void registerService(Class<T> type, T instance); <T> void registerService(Class<T> type, T instance);

View File

@ -0,0 +1,19 @@
/*
* Copyright 2016 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.vm.spi;
public interface TeaVMHostExtension {
}

View File

@ -15,10 +15,6 @@
*/ */
package org.teavm.vm.spi; package org.teavm.vm.spi;
/**
*
* @author Alexey Andreev
*/
public interface TeaVMPlugin { public interface TeaVMPlugin {
void install(TeaVMHost host); void install(TeaVMHost host);
} }

View File

@ -15,19 +15,20 @@
*/ */
package org.teavm.html4j; package org.teavm.html4j;
import org.teavm.javascript.target.TeaVMJavaScriptHost;
import org.teavm.vm.spi.TeaVMHost; import org.teavm.vm.spi.TeaVMHost;
import org.teavm.vm.spi.TeaVMPlugin; import org.teavm.vm.spi.TeaVMPlugin;
/**
*
* @author Alexey Andreev
*/
public class HTML4JPlugin implements TeaVMPlugin { public class HTML4JPlugin implements TeaVMPlugin {
@Override @Override
public void install(TeaVMHost host) { public void install(TeaVMHost host) {
if (host.getExtension(TeaVMJavaScriptHost.class) == null) {
return;
}
host.add(new JavaScriptBodyDependency()); host.add(new JavaScriptBodyDependency());
host.add(new JavaScriptBodyTransformer()); host.add(new JavaScriptBodyTransformer());
host.add(new JCLHacks()); host.add(new JCLHacks());
host.add(new JavaScriptResourceInterceptor());
host.getExtension(TeaVMJavaScriptHost.class).add(new JavaScriptResourceInterceptor());
} }
} }

View File

@ -15,22 +15,23 @@
*/ */
package org.teavm.jso.impl; package org.teavm.jso.impl;
import org.teavm.javascript.target.TeaVMJavaScriptHost;
import org.teavm.vm.spi.TeaVMHost; import org.teavm.vm.spi.TeaVMHost;
import org.teavm.vm.spi.TeaVMPlugin; import org.teavm.vm.spi.TeaVMPlugin;
/**
*
* @author Alexey Andreev
*/
public class JSOPlugin implements TeaVMPlugin { public class JSOPlugin implements TeaVMPlugin {
@Override @Override
public void install(TeaVMHost host) { public void install(TeaVMHost host) {
if (host.getExtension(TeaVMJavaScriptHost.class) == null) {
return;
}
JSBodyRepository repository = new JSBodyRepository(); JSBodyRepository repository = new JSBodyRepository();
host.registerService(JSBodyRepository.class, repository); host.registerService(JSBodyRepository.class, repository);
host.add(new JSObjectClassTransformer(repository)); host.add(new JSObjectClassTransformer(repository));
JSDependencyListener dependencyListener = new JSDependencyListener(repository); JSDependencyListener dependencyListener = new JSDependencyListener(repository);
JSAliasRenderer aliasRenderer = new JSAliasRenderer(dependencyListener); JSAliasRenderer aliasRenderer = new JSAliasRenderer(dependencyListener);
host.add(dependencyListener); host.add(dependencyListener);
host.add(aliasRenderer); host.getExtension(TeaVMJavaScriptHost.class).add(aliasRenderer);
} }
} }

View File

@ -18,10 +18,6 @@ package org.teavm.platform.plugin;
import org.teavm.vm.spi.TeaVMHost; import org.teavm.vm.spi.TeaVMHost;
import org.teavm.vm.spi.TeaVMPlugin; import org.teavm.vm.spi.TeaVMPlugin;
/**
*
* @author Alexey Andreev
*/
public class PlatformPlugin implements TeaVMPlugin { public class PlatformPlugin implements TeaVMPlugin {
@Override @Override
public void install(TeaVMHost host) { public void install(TeaVMHost host) {

View File

@ -16,18 +16,15 @@
package org.teavm.platform.plugin; package org.teavm.platform.plugin;
import org.teavm.diagnostics.Diagnostics; import org.teavm.diagnostics.Diagnostics;
import org.teavm.javascript.target.TeaVMJavaScriptHost;
import org.teavm.model.*; import org.teavm.model.*;
import org.teavm.vm.spi.TeaVMHost; import org.teavm.vm.spi.TeaVMHost;
/**
*
* @author Alexey Andreev
*/
class ResourceAccessorTransformer implements ClassHolderTransformer { class ResourceAccessorTransformer implements ClassHolderTransformer {
private TeaVMHost vm; private TeaVMJavaScriptHost vm;
public ResourceAccessorTransformer(TeaVMHost vm) { public ResourceAccessorTransformer(TeaVMHost vm) {
this.vm = vm; this.vm = vm.getExtension(TeaVMJavaScriptHost.class);
} }
@Override @Override

View File

@ -17,7 +17,9 @@ package org.teavm.dependency;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
import org.apache.commons.io.output.ByteArrayOutputStream;
import org.junit.Test; import org.junit.Test;
import org.teavm.javascript.target.JavaScriptTarget;
import org.teavm.model.MethodReference; import org.teavm.model.MethodReference;
import org.teavm.model.ValueType; import org.teavm.model.ValueType;
import org.teavm.tooling.TeaVMProblemRenderer; import org.teavm.tooling.TeaVMProblemRenderer;
@ -73,10 +75,10 @@ public class ClassValueTest {
} }
private DependencyInfo runTest(String methodName) { private DependencyInfo runTest(String methodName) {
TeaVM vm = new TeaVMBuilder().build(); TeaVM vm = new TeaVMBuilder(new JavaScriptTarget()).build();
vm.installPlugins(); vm.installPlugins();
vm.entryPoint(new MethodReference(getClass().getName(), methodName, ValueType.VOID)); vm.entryPoint(new MethodReference(getClass().getName(), methodName, ValueType.VOID));
vm.build(new StringBuilder(), null); vm.build(new ByteArrayOutputStream(), null);
if (!vm.getProblemProvider().getSevereProblems().isEmpty()) { if (!vm.getProblemProvider().getSevereProblems().isEmpty()) {
fail("Code compiled with errors:\n" + describeProblems(vm)); fail("Code compiled with errors:\n" + describeProblems(vm));
} }

View File

@ -15,15 +15,15 @@
*/ */
package org.teavm.tests; package org.teavm.tests;
import static org.hamcrest.CoreMatchers.*; import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.*; import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import java.io.ByteArrayOutputStream;
import java.util.List; import java.util.List;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith;
import org.teavm.diagnostics.Problem; import org.teavm.diagnostics.Problem;
import org.teavm.javascript.target.JavaScriptTarget;
import org.teavm.jso.JSBody; import org.teavm.jso.JSBody;
import org.teavm.junit.SkipJVM;
import org.teavm.junit.TeaVMTestRunner;
import org.teavm.model.MethodReference; import org.teavm.model.MethodReference;
import org.teavm.model.ValueType; import org.teavm.model.ValueType;
import org.teavm.vm.TeaVM; import org.teavm.vm.TeaVM;
@ -96,10 +96,10 @@ public class JSOTest {
private static native Object jsBodyWithWrongReturningType(String value); private static native Object jsBodyWithWrongReturningType(String value);
private List<Problem> build(String methodName) { private List<Problem> build(String methodName) {
TeaVM vm = new TeaVMBuilder().build(); TeaVM vm = new TeaVMBuilder(new JavaScriptTarget()).build();
vm.installPlugins(); vm.installPlugins();
vm.entryPoint("org/teavm/metaprogramming/test", new MethodReference(JSOTest.class, methodName, void.class)); vm.entryPoint("org/teavm/metaprogramming/test", new MethodReference(JSOTest.class, methodName, void.class));
vm.build(new StringBuilder(), null); vm.build(new ByteArrayOutputStream(), null);
return vm.getProblemProvider().getSevereProblems(); return vm.getProblemProvider().getSevereProblems();
} }
} }

View File

@ -27,10 +27,6 @@ import org.teavm.vm.TeaVMPhase;
import org.teavm.vm.TeaVMProgressFeedback; import org.teavm.vm.TeaVMProgressFeedback;
import org.teavm.vm.TeaVMProgressListener; import org.teavm.vm.TeaVMProgressListener;
/**
*
* @author Alexey Andreev
*/
public final class TeaVMRunner { public final class TeaVMRunner {
private static long startTime; private static long startTime;
private static long phaseStartTime; private static long phaseStartTime;
@ -69,10 +65,6 @@ public final class TeaVMRunner {
.withDescription("causes TeaVM to include default main page") .withDescription("causes TeaVM to include default main page")
.withLongOpt("mainpage") .withLongOpt("mainpage")
.create()); .create());
options.addOption(OptionBuilder
.withDescription("causes TeaVM to log bytecode")
.withLongOpt("logbytecode")
.create());
options.addOption(OptionBuilder options.addOption(OptionBuilder
.withDescription("Generate debug information") .withDescription("Generate debug information")
.withLongOpt("debug") .withLongOpt("debug")
@ -116,7 +108,6 @@ public final class TeaVMRunner {
} }
TeaVMTool tool = new TeaVMTool(); TeaVMTool tool = new TeaVMTool();
tool.setBytecodeLogging(commandLine.hasOption("logbytecode"));
if (commandLine.hasOption("d")) { if (commandLine.hasOption("d")) {
tool.setTargetDirectory(new File(commandLine.getOptionValue("d"))); tool.setTargetDirectory(new File(commandLine.getOptionValue("d")));
} }
@ -269,7 +260,7 @@ public final class TeaVMRunner {
case LINKING: case LINKING:
System.out.print("Linking methods..."); System.out.print("Linking methods...");
break; break;
case DEVIRTUALIZATION: case OPTIMIZATION:
System.out.print("Applying devirtualization..."); System.out.print("Applying devirtualization...");
break; break;
case DECOMPILATION: case DECOMPILATION:

View File

@ -0,0 +1,20 @@
/*
* Copyright 2016 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.tooling;
public enum TeaVMTargetType {
JAVASCRIPT
}

View File

@ -15,8 +15,24 @@
*/ */
package org.teavm.tooling; package org.teavm.tooling;
import java.io.*; import java.io.BufferedOutputStream;
import java.util.*; import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.StringWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Properties;
import java.util.Set;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.teavm.cache.DiskCachedClassHolderSource; import org.teavm.cache.DiskCachedClassHolderSource;
import org.teavm.cache.DiskProgramCache; import org.teavm.cache.DiskProgramCache;
@ -27,26 +43,37 @@ import org.teavm.debugging.information.DebugInformationBuilder;
import org.teavm.dependency.DependencyInfo; import org.teavm.dependency.DependencyInfo;
import org.teavm.diagnostics.ProblemProvider; import org.teavm.diagnostics.ProblemProvider;
import org.teavm.javascript.RenderingContext; import org.teavm.javascript.RenderingContext;
import org.teavm.model.*; import org.teavm.javascript.target.JavaScriptTarget;
import org.teavm.model.ClassHolderSource;
import org.teavm.model.ClassHolderTransformer;
import org.teavm.model.ClassReader;
import org.teavm.model.ClassReaderSource;
import org.teavm.model.MethodDescriptor;
import org.teavm.model.MethodReader;
import org.teavm.model.MethodReference;
import org.teavm.model.PreOptimizingClassHolderSource;
import org.teavm.model.ProgramReader;
import org.teavm.parsing.ClasspathClassHolderSource; import org.teavm.parsing.ClasspathClassHolderSource;
import org.teavm.tooling.sources.SourceFileProvider; import org.teavm.tooling.sources.SourceFileProvider;
import org.teavm.tooling.sources.SourceFilesCopier; import org.teavm.tooling.sources.SourceFilesCopier;
import org.teavm.vm.*; import org.teavm.vm.BuildTarget;
import org.teavm.vm.DirectoryBuildTarget;
import org.teavm.vm.TeaVM;
import org.teavm.vm.TeaVMBuilder;
import org.teavm.vm.TeaVMEntryPoint;
import org.teavm.vm.TeaVMProgressListener;
import org.teavm.vm.TeaVMTarget;
import org.teavm.vm.spi.AbstractRendererListener; import org.teavm.vm.spi.AbstractRendererListener;
/**
*
* @author Alexey Andreev
*/
public class TeaVMTool implements BaseTeaVMTool { public class TeaVMTool implements BaseTeaVMTool {
private File targetDirectory = new File("."); private File targetDirectory = new File(".");
private TeaVMTargetType targetType = TeaVMTargetType.JAVASCRIPT;
private String targetFileName = "classes.js"; private String targetFileName = "classes.js";
private boolean minifying = true; private boolean minifying = true;
private String mainClass; private String mainClass;
private RuntimeCopyOperation runtime = RuntimeCopyOperation.SEPARATE; private RuntimeCopyOperation runtime = RuntimeCopyOperation.SEPARATE;
private Properties properties = new Properties(); private Properties properties = new Properties();
private boolean mainPageIncluded; private boolean mainPageIncluded;
private boolean bytecodeLogging;
private boolean debugInformationGenerated; private boolean debugInformationGenerated;
private boolean sourceMapsFileGenerated; private boolean sourceMapsFileGenerated;
private boolean sourceFilesCopied; private boolean sourceFilesCopied;
@ -66,6 +93,8 @@ public class TeaVMTool implements BaseTeaVMTool {
private TeaVMProgressListener progressListener; private TeaVMProgressListener progressListener;
private TeaVM vm; private TeaVM vm;
private List<SourceFileProvider> sourceFileProviders = new ArrayList<>(); private List<SourceFileProvider> sourceFileProviders = new ArrayList<>();
private DebugInformationBuilder debugEmitter;
private JavaScriptTarget javaScriptTarget;
public File getTargetDirectory() { public File getTargetDirectory() {
return targetDirectory; return targetDirectory;
@ -126,14 +155,6 @@ public class TeaVMTool implements BaseTeaVMTool {
this.mainPageIncluded = mainPageIncluded; this.mainPageIncluded = mainPageIncluded;
} }
public boolean isBytecodeLogging() {
return bytecodeLogging;
}
public void setBytecodeLogging(boolean bytecodeLogging) {
this.bytecodeLogging = bytecodeLogging;
}
public boolean isDebugInformationGenerated() { public boolean isDebugInformationGenerated() {
return debugInformationGenerated; return debugInformationGenerated;
} }
@ -262,11 +283,34 @@ public class TeaVMTool implements BaseTeaVMTool {
sourceFileProviders.add(sourceFileProvider); sourceFileProviders.add(sourceFileProvider);
} }
private TeaVMTarget prepareTarget() {
switch (targetType) {
case JAVASCRIPT:
return prepareJavaScriptTarget();
}
throw new IllegalStateException("Unknown target type: " + targetType);
}
private TeaVMTarget prepareJavaScriptTarget() {
javaScriptTarget = new JavaScriptTarget();
javaScriptTarget.setMinifying(minifying);
DebugInformationBuilder debugEmitter = debugInformationGenerated || sourceMapsFileGenerated
? new DebugInformationBuilder() : null;
javaScriptTarget.setDebugEmitter(debugEmitter);
if (incremental) {
javaScriptTarget.setAstCache(astCache);
}
return javaScriptTarget;
}
public void generate() throws TeaVMToolException { public void generate() throws TeaVMToolException {
try { try {
cancelled = false; cancelled = false;
log.info("Building JavaScript file"); log.info("Building JavaScript file");
TeaVMBuilder vmBuilder = new TeaVMBuilder(); TeaVMBuilder vmBuilder = new TeaVMBuilder(prepareTarget());
if (incremental) { if (incremental) {
cacheDirectory.mkdirs(); cacheDirectory.mkdirs();
symbolTable = new FileSymbolTable(new File(cacheDirectory, "symbols")); symbolTable = new FileSymbolTable(new File(cacheDirectory, "symbols"));
@ -276,7 +320,10 @@ public class TeaVMTool implements BaseTeaVMTool {
cachedClassSource = new DiskCachedClassHolderSource(cacheDirectory, symbolTable, fileTable, cachedClassSource = new DiskCachedClassHolderSource(cacheDirectory, symbolTable, fileTable,
classSource, innerClassSource); classSource, innerClassSource);
programCache = new DiskProgramCache(cacheDirectory, symbolTable, fileTable, innerClassSource); programCache = new DiskProgramCache(cacheDirectory, symbolTable, fileTable, innerClassSource);
astCache = new DiskRegularMethodNodeCache(cacheDirectory, symbolTable, fileTable, innerClassSource);
if (targetType == TeaVMTargetType.JAVASCRIPT) {
astCache = new DiskRegularMethodNodeCache(cacheDirectory, symbolTable, fileTable, innerClassSource);
}
try { try {
symbolTable.update(); symbolTable.update();
fileTable.update(); fileTable.update();
@ -292,17 +339,11 @@ public class TeaVMTool implements BaseTeaVMTool {
if (progressListener != null) { if (progressListener != null) {
vm.setProgressListener(progressListener); vm.setProgressListener(progressListener);
} }
vm.setMinifying(minifying);
vm.setBytecodeLogging(bytecodeLogging);
vm.setProperties(properties); vm.setProperties(properties);
DebugInformationBuilder debugEmitter = debugInformationGenerated || sourceMapsFileGenerated vm.setProgramCache(programCache);
? new DebugInformationBuilder() : null;
vm.setDebugEmitter(debugEmitter);
vm.setIncremental(incremental); vm.setIncremental(incremental);
if (incremental) {
vm.setAstCache(astCache);
vm.setProgramCache(programCache);
}
vm.installPlugins(); vm.installPlugins();
for (ClassHolderTransformer transformer : transformers) { for (ClassHolderTransformer transformer : transformers) {
vm.add(transformer); vm.add(transformer);
@ -336,82 +377,96 @@ public class TeaVMTool implements BaseTeaVMTool {
} }
} }
targetDirectory.mkdirs(); targetDirectory.mkdirs();
try (Writer writer = new OutputStreamWriter(new BufferedOutputStream( try (OutputStream output = new BufferedOutputStream(
new FileOutputStream(new File(targetDirectory, targetFileName)), 65536), "UTF-8")) { new FileOutputStream(new File(targetDirectory, targetFileName)), 65536)) {
Writer writer = new OutputStreamWriter(output, "UTF-8");
if (runtime == RuntimeCopyOperation.MERGED) { if (runtime == RuntimeCopyOperation.MERGED) {
vm.add(runtimeInjector); javaScriptTarget.add(runtimeInjector);
} }
vm.build(writer, new DirectoryBuildTarget(targetDirectory)); vm.build(output, new DirectoryBuildTarget(targetDirectory));
if (vm.wasCancelled()) { if (vm.wasCancelled()) {
log.info("Build cancelled"); log.info("Build cancelled");
cancelled = true; cancelled = true;
return; return;
} }
if (mainClass != null) {
writer.append("main = $rt_mainStarter(main);\n");
}
ProblemProvider problemProvider = vm.getProblemProvider(); ProblemProvider problemProvider = vm.getProblemProvider();
if (problemProvider.getProblems().isEmpty()) { if (problemProvider.getProblems().isEmpty()) {
log.info("JavaScript file successfully built"); log.info("Output file successfully built");
} else if (problemProvider.getSevereProblems().isEmpty()) { } else if (problemProvider.getSevereProblems().isEmpty()) {
log.info("JavaScript file built with warnings"); log.info("Output file built with warnings");
TeaVMProblemRenderer.describeProblems(vm, log); TeaVMProblemRenderer.describeProblems(vm, log);
} else { } else {
log.info("JavaScript file built with errors"); log.info("Output file built with errors");
TeaVMProblemRenderer.describeProblems(vm, log); TeaVMProblemRenderer.describeProblems(vm, log);
} }
if (debugInformationGenerated) {
assert debugEmitter != null; if (targetType == TeaVMTargetType.JAVASCRIPT) {
DebugInformation debugInfo = debugEmitter.getDebugInformation(); additionalJavaScriptOutput(writer);
try (OutputStream debugInfoOut = new FileOutputStream(new File(targetDirectory,
targetFileName + ".teavmdbg"))) {
debugInfo.write(debugInfoOut);
}
log.info("Debug information successfully written");
}
if (sourceMapsFileGenerated) {
assert debugEmitter != null;
DebugInformation debugInfo = debugEmitter.getDebugInformation();
String sourceMapsFileName = targetFileName + ".map";
writer.append("\n//# sourceMappingURL=").append(sourceMapsFileName);
try (Writer sourceMapsOut = new OutputStreamWriter(new FileOutputStream(
new File(targetDirectory, sourceMapsFileName)), "UTF-8")) {
debugInfo.writeAsSourceMaps(sourceMapsOut, "src", targetFileName);
}
log.info("Source maps successfully written");
}
if (sourceFilesCopied) {
copySourceFiles();
log.info("Source files successfully written");
} }
if (incremental) { if (incremental) {
programCache.flush(); programCache.flush();
astCache.flush(); if (astCache != null) {
astCache.flush();
}
cachedClassSource.flush(); cachedClassSource.flush();
symbolTable.flush(); symbolTable.flush();
fileTable.flush(); fileTable.flush();
log.info("Cache updated"); log.info("Cache updated");
} }
} }
if (runtime == RuntimeCopyOperation.SEPARATE) {
resourceToFile("org/teavm/javascript/runtime.js", "runtime.js");
}
if (mainPageIncluded) {
String text;
try (Reader reader = new InputStreamReader(classLoader.getResourceAsStream(
"org/teavm/tooling/main.html"), "UTF-8")) {
text = IOUtils.toString(reader).replace("${classes.js}", targetFileName);
}
File mainPageFile = new File(targetDirectory, "main.html");
try (Writer writer = new OutputStreamWriter(new FileOutputStream(mainPageFile), "UTF-8")) {
writer.append(text);
}
}
} catch (IOException e) { } catch (IOException e) {
throw new TeaVMToolException("IO error occured", e); throw new TeaVMToolException("IO error occured", e);
} }
} }
private void additionalJavaScriptOutput(Writer writer) throws IOException {
if (mainClass != null) {
writer.append("main = $rt_mainStarter(main);\n");
}
if (debugInformationGenerated) {
assert debugEmitter != null;
DebugInformation debugInfo = debugEmitter.getDebugInformation();
try (OutputStream debugInfoOut = new FileOutputStream(new File(targetDirectory,
targetFileName + ".teavmdbg"))) {
debugInfo.write(debugInfoOut);
}
log.info("Debug information successfully written");
}
if (sourceMapsFileGenerated) {
assert debugEmitter != null;
DebugInformation debugInfo = debugEmitter.getDebugInformation();
String sourceMapsFileName = targetFileName + ".map";
writer.append("\n//# sourceMappingURL=").append(sourceMapsFileName);
try (Writer sourceMapsOut = new OutputStreamWriter(new FileOutputStream(
new File(targetDirectory, sourceMapsFileName)), "UTF-8")) {
debugInfo.writeAsSourceMaps(sourceMapsOut, "src", targetFileName);
}
log.info("Source maps successfully written");
}
if (sourceFilesCopied) {
copySourceFiles();
log.info("Source files successfully written");
}
if (runtime == RuntimeCopyOperation.SEPARATE) {
resourceToFile("org/teavm/javascript/runtime.js", "runtime.js");
}
if (mainPageIncluded) {
String text;
try (Reader reader = new InputStreamReader(classLoader.getResourceAsStream(
"org/teavm/tooling/main.html"), "UTF-8")) {
text = IOUtils.toString(reader).replace("${classes.js}", targetFileName);
}
File mainPageFile = new File(targetDirectory, "main.html");
try (Writer mainPageWriter = new OutputStreamWriter(new FileOutputStream(mainPageFile), "UTF-8")) {
mainPageWriter.append(text);
}
}
}
private void copySourceFiles() { private void copySourceFiles() {
if (vm.getWrittenClasses() == null) { if (vm.getWrittenClasses() == null) {
return; return;

View File

@ -7,7 +7,7 @@
<property key="Bundle-Description" value="TeaVM API that helps to create tooling" /> <property key="Bundle-Description" value="TeaVM API that helps to create tooling" />
<property key="Export-Package" value="org.teavm.*" /> <property key="Export-Package" value="org.teavm.*" />
<property key="Bundle-Name" value="TeaVM tooling core" /> <property key="Bundle-Name" value="TeaVM tooling core" />
<property key="Include-Resource" value="org/teavm/tooling/main.html=$MODULE_DIR$/src/main/resources/org/teavm/tooling/main.html,org/teavm/tooling/test/junit.html=$MODULE_DIR$/src/main/resources/org/teavm/tooling/test/junit.html,org/teavm/tooling/test/junit-client.html=$MODULE_DIR$/src/main/resources/org/teavm/tooling/test/junit-client.html,org/teavm/tooling/test/res/junit-support.js=$MODULE_DIR$/src/main/resources/org/teavm/tooling/test/res/junit-support.js,org/teavm/tooling/test/res/control-000-small.png=$MODULE_DIR$/src/main/resources/org/teavm/tooling/test/res/control-000-small.png,org/teavm/tooling/test/res/package_obj.png=$MODULE_DIR$/src/main/resources/org/teavm/tooling/test/res/package_obj.png,org/teavm/tooling/test/res/junit-client.js=$MODULE_DIR$/src/main/resources/org/teavm/tooling/test/res/junit-client.js,org/teavm/tooling/test/res/junit.css=$MODULE_DIR$/src/main/resources/org/teavm/tooling/test/res/junit.css,org/teavm/tooling/test/res/tick-small-red.png=$MODULE_DIR$/src/main/resources/org/teavm/tooling/test/res/tick-small-red.png,org/teavm/tooling/test/res/tick-small.png=$MODULE_DIR$/src/main/resources/org/teavm/tooling/test/res/tick-small.png,org/teavm/tooling/test/res/class_obj.png=$MODULE_DIR$/src/main/resources/org/teavm/tooling/test/res/class_obj.png,org/teavm/tooling/test/res/toggle-small.png=$MODULE_DIR$/src/main/resources/org/teavm/tooling/test/res/toggle-small.png,org/teavm/tooling/test/res/toggle-small-expand.png=$MODULE_DIR$/src/main/resources/org/teavm/tooling/test/res/toggle-small-expand.png,org/teavm/tooling/test/res/methpub_obj.png=$MODULE_DIR$/src/main/resources/org/teavm/tooling/test/res/methpub_obj.png" /> <property key="Include-Resource" value="org/teavm/tooling/test/junit.html=$MODULE_DIR$/src/main/resources/org/teavm/tooling/test/junit.html,org/teavm/tooling/test/junit-client.html=$MODULE_DIR$/src/main/resources/org/teavm/tooling/test/junit-client.html,org/teavm/tooling/test/res/tick-small-red.png=$MODULE_DIR$/src/main/resources/org/teavm/tooling/test/res/tick-small-red.png,org/teavm/tooling/test/res/class_obj.png=$MODULE_DIR$/src/main/resources/org/teavm/tooling/test/res/class_obj.png,org/teavm/tooling/test/res/junit.css=$MODULE_DIR$/src/main/resources/org/teavm/tooling/test/res/junit.css,org/teavm/tooling/test/res/junit-client.js=$MODULE_DIR$/src/main/resources/org/teavm/tooling/test/res/junit-client.js,org/teavm/tooling/test/res/methpub_obj.png=$MODULE_DIR$/src/main/resources/org/teavm/tooling/test/res/methpub_obj.png,org/teavm/tooling/test/res/tick-small.png=$MODULE_DIR$/src/main/resources/org/teavm/tooling/test/res/tick-small.png,org/teavm/tooling/test/res/control-000-small.png=$MODULE_DIR$/src/main/resources/org/teavm/tooling/test/res/control-000-small.png,org/teavm/tooling/test/res/junit-support.js=$MODULE_DIR$/src/main/resources/org/teavm/tooling/test/res/junit-support.js,org/teavm/tooling/test/res/package_obj.png=$MODULE_DIR$/src/main/resources/org/teavm/tooling/test/res/package_obj.png,org/teavm/tooling/test/res/toggle-small.png=$MODULE_DIR$/src/main/resources/org/teavm/tooling/test/res/toggle-small.png,org/teavm/tooling/test/res/toggle-small-expand.png=$MODULE_DIR$/src/main/resources/org/teavm/tooling/test/res/toggle-small-expand.png,org/teavm/tooling/main.html=$MODULE_DIR$/src/main/resources/org/teavm/tooling/main.html" />
</additionalProperties> </additionalProperties>
<additionalJARContents /> <additionalJARContents />
</configuration> </configuration>

View File

@ -20,8 +20,6 @@ import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.net.MalformedURLException; import java.net.MalformedURLException;
@ -49,6 +47,7 @@ import org.junit.runners.model.InitializationError;
import org.teavm.callgraph.CallGraph; import org.teavm.callgraph.CallGraph;
import org.teavm.diagnostics.DefaultProblemTextConsumer; import org.teavm.diagnostics.DefaultProblemTextConsumer;
import org.teavm.diagnostics.Problem; import org.teavm.diagnostics.Problem;
import org.teavm.javascript.target.JavaScriptTarget;
import org.teavm.model.ClassHolder; import org.teavm.model.ClassHolder;
import org.teavm.model.ClassHolderSource; import org.teavm.model.ClassHolderSource;
import org.teavm.model.MethodDescriptor; import org.teavm.model.MethodDescriptor;
@ -345,12 +344,13 @@ public class TeaVMTestRunner extends Runner {
MethodHolder methodHolder = classHolder.getMethod(getDescriptor(method)); MethodHolder methodHolder = classHolder.getMethod(getDescriptor(method));
Class<?> runnerType = testAdapter.getRunner(methodHolder); Class<?> runnerType = testAdapter.getRunner(methodHolder);
TeaVM vm = new TeaVMBuilder() JavaScriptTarget jsTarget = new JavaScriptTarget();
jsTarget.setMinifying(false);
TeaVM vm = new TeaVMBuilder(jsTarget)
.setClassLoader(classLoader) .setClassLoader(classLoader)
.setClassSource(classSource) .setClassSource(classSource)
.build(); .build();
vm.setIncremental(false); vm.setIncremental(false);
vm.setMinifying(false);
vm.installPlugins(); vm.installPlugins();
new TestExceptionPlugin().install(vm); new TestExceptionPlugin().install(vm);
@ -360,7 +360,7 @@ public class TeaVMTestRunner extends Runner {
applyProperties(method.getDeclaringClass(), properties); applyProperties(method.getDeclaringClass(), properties);
vm.setProperties(properties); vm.setProperties(properties);
try (Writer innerWriter = new OutputStreamWriter(new FileOutputStream(outputFile), "UTF-8")) { try (OutputStream innerWriter = new FileOutputStream(outputFile)) {
MethodReference exceptionMsg = new MethodReference(ExceptionHelper.class, "showException", MethodReference exceptionMsg = new MethodReference(ExceptionHelper.class, "showException",
Throwable.class, String.class); Throwable.class, String.class);
vm.entryPoint("runTest", new MethodReference(TestEntryPoint.class, "run", void.class)).async(); vm.entryPoint("runTest", new MethodReference(TestEntryPoint.class, "run", void.class)).async();

View File

@ -55,9 +55,6 @@ public class BuildJavascriptMojo extends AbstractJavascriptMojo {
@Parameter @Parameter
private boolean mainPageIncluded; private boolean mainPageIncluded;
@Parameter
private boolean bytecodeLogging;
@Parameter @Parameter
private ClassAlias[] classAliases; private ClassAlias[] classAliases;
@ -86,7 +83,6 @@ public class BuildJavascriptMojo extends AbstractJavascriptMojo {
setupTool(tool); setupTool(tool);
tool.setLog(new MavenTeaVMToolLog(log)); tool.setLog(new MavenTeaVMToolLog(log));
try { try {
tool.setBytecodeLogging(bytecodeLogging);
tool.setMainClass(mainClass); tool.setMainClass(mainClass);
tool.setMainPageIncluded(mainPageIncluded); tool.setMainPageIncluded(mainPageIncluded);
tool.setRuntime(runtime); tool.setRuntime(runtime);