, TeaVMHostExtension> extensions = new HashMap<>();
- TeaVM(ClassReaderSource classSource, ClassLoader classLoader) {
- this.classSource = classSource;
- this.classLoader = classLoader;
+ TeaVM(TeaVMBuilder builder) {
+ target = builder.target;
+ classSource = builder.classSource;
+ classLoader = builder.classLoader;
dependencyChecker = new DependencyChecker(this.classSource, classLoader, this, diagnostics);
progressListener = new TeaVMProgressListener() {
@Override public TeaVMProgressFeedback progressReached(int progress) {
@@ -173,6 +133,12 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
return TeaVMProgressFeedback.CONTINUE;
}
};
+
+ for (TeaVMHostExtension extension : target.getHostExtensions()) {
+ for (Class> extensionType : getExtensionTypes(extension)) {
+ extensions.put(extensionType, extension);
+ }
+ }
}
@Override
@@ -185,59 +151,16 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
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
public void add(MethodReference methodRef, BootstrapMethodSubstitutor substitutor) {
dependencyChecker.addBootstrapMethodSubstitutor(methodRef, substitutor);
}
- @Override
- public void add(RendererListener listener) {
- rendererListeners.add(listener);
- }
-
@Override
public ClassLoader getClassLoader() {
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
* installing any plugins or interceptors.
@@ -257,14 +180,6 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
return new Properties(properties);
}
- public MethodNodeCache getAstCache() {
- return astCache;
- }
-
- public void setAstCache(MethodNodeCache methodAstCache) {
- this.astCache = methodAstCache;
- }
-
public ProgramCache getProgramCache() {
return programCache;
}
@@ -391,14 +306,6 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
return writtenClasses;
}
- public DebugInformationEmitter getDebugEmitter() {
- return debugEmitter;
- }
-
- public void setDebugEmitter(DebugInformationEmitter debugEmitter) {
- this.debugEmitter = debugEmitter;
- }
-
/**
* 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)
@@ -406,52 +313,23 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
* actual generation happens and no exceptions thrown, but you can further call
* {@link #getProblemProvider()} to learn the build state.
*
- * @param writer where to generate JavaScript. Should not be null.
- * @param target where to generate additional resources. Can be null, but if there are
+ * @param output where to generate JavaScript. Should not be null.
+ * @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.
*
* @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
reportPhase(TeaVMPhase.DEPENDENCY_CHECKING, 1);
if (wasCancelled()) {
return;
}
- AliasProvider aliasProvider = minifying ? new MinifyingAliasProvider() : new DefaultAliasProvider();
dependencyChecker.setInterruptor(() -> progressListener.progressReached(0) == TeaVMProgressFeedback.CONTINUE);
- dependencyChecker.linkMethod(new MethodReference(Class.class.getName(), "getClass",
- ValueType.object("org.teavm.platform.PlatformClass"), ValueType.parse(Class.class)), null).use();
- dependencyChecker.linkMethod(new MethodReference(String.class, "", 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, "", 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, "",
- 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, "",
- 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"));
+ target.contributeDependencies(dependencyChecker);
dependencyChecker.processDependencies();
if (wasCancelled() || !diagnostics.getSevereProblems().isEmpty()) {
return;
@@ -469,73 +347,27 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
}
// Optimize and allocate registers
+ reportPhase(TeaVMPhase.OPTIMIZATION, 1);
+
if (!incremental) {
devirtualize(classSet, dependencyChecker);
if (wasCancelled()) {
return;
}
+
+ inline(classSet);
+ if (wasCancelled()) {
+ return;
+ }
}
- List clsNodes = modelToAst(classSet);
-
- // Render
- reportPhase(TeaVMPhase.RENDERING, classSet.getClassNames().size());
+ optimize(classSet);
if (wasCancelled()) {
return;
}
- DefaultNamingStrategy naming = new DefaultNamingStrategy(aliasProvider, dependencyChecker.getClassSource());
- SourceWriterBuilder builder = new SourceWriterBuilder(naming);
- builder.setMinified(minifying);
- 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 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 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 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);
- }
+
+ // Render
+ target.emit(classSet, output, buildTarget);
}
@SuppressWarnings("WeakerAccess")
@@ -568,38 +400,11 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
}
}
- private void reportProgress(int progress) {
- if (progressListener.progressReached(progress) == TeaVMProgressFeedback.CANCEL) {
- cancelled = true;
- }
- }
-
- private void emitCFG(DebugInformationEmitter emitter, Program program) {
- Map cfg = ProgramUtils.getLocationCFG(program);
- for (Map.Entry 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());
+ private void devirtualize(ListableClassHolderSource classes, DependencyInfo dependency) {
if (wasCancelled()) {
return;
}
Devirtualization devirtualization = new Devirtualization(dependency, classes);
- int index = 0;
for (String className : classes.getClassNames()) {
ClassHolder cls = classes.get(className);
for (final MethodHolder method : cls.getMethods()) {
@@ -607,12 +412,13 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
devirtualization.apply(method);
}
}
- reportProgress(++index);
if (wasCancelled()) {
return;
}
}
+ }
+ private void inline(ListableClassHolderSource classes) {
Inlining inlining = new Inlining();
for (String className : classes.getClassNames()) {
ClassHolder cls = classes.get(className);
@@ -621,90 +427,22 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
inlining.apply(method.getProgram(), classes);
}
}
- reportProgress(++index);
if (wasCancelled()) {
return;
}
}
}
- private List modelToAst(ListableClassHolderSource classes) {
- AsyncMethodFinder asyncFinder = new AsyncMethodFinder(dependencyChecker.getCallGraph(), diagnostics);
- asyncFinder.find(classes);
- asyncMethods.addAll(asyncFinder.getAsyncMethods());
- asyncFamilyMethods.addAll(asyncFinder.getAsyncFamilyMethods());
-
- progressListener.phaseStarted(TeaVMPhase.DECOMPILATION, classes.getClassNames().size());
- Decompiler decompiler = new Decompiler(classes, classLoader, asyncMethods, asyncFamilyMethods);
- decompiler.setRegularMethodCache(incremental ? astCache : null);
-
- for (Map.Entry entry : methodGenerators.entrySet()) {
- decompiler.addGenerator(entry.getKey(), entry.getValue());
- }
- for (MethodReference injectedMethod : methodInjectors.keySet()) {
- decompiler.addMethodToPass(injectedMethod);
- }
- List classOrder = decompiler.getClassOrdering(classes.getClassNames());
- List 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);
+ private void optimize(ListableClassHolderSource classSource) {
+ for (String className : classSource.getClassNames()) {
+ ClassHolder cls = classSource.get(className);
+ for (MethodHolder method : cls.getMethods()) {
+ processMethod(method);
+ }
+ if (wasCancelled()) {
+ return;
}
- } 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, "", 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) {
@@ -725,8 +463,11 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
changed |= optimization.optimize(method, optimizedProgram);
}
} 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) {
programCache.store(method.getReference(), optimizedProgram);
@@ -749,102 +490,9 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
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 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 {
- try (Writer writer = new OutputStreamWriter(new FileOutputStream(new File(dir, fileName)), "UTF-8")) {
- build(writer, new DirectoryBuildTarget(dir));
+ try (OutputStream output = new FileOutputStream(new File(dir, fileName))) {
+ build(output, new DirectoryBuildTarget(dir));
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("Platform does not support UTF-8", e);
} catch (IOException e) {
@@ -877,4 +525,69 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
public void registerService(Class type, T instance) {
services.put(type, instance);
}
+
+ @Override
+ public T getExtension(Class extensionType) {
+ Object extension = extensions.get(extensionType);
+ return extension != null ? extensionType.cast(extension) : null;
+ }
+
+ private Collection> getExtensionTypes(TeaVMHostExtension extension) {
+ return Arrays.stream(extension.getClass().getInterfaces())
+ .filter(cls -> cls.isInterface() && TeaVMHostExtension.class.isAssignableFrom(cls))
+ .>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 getEntryPoints() {
+ return readonlyEntryPoints;
+ }
+
+ @Override
+ public Map getExportedClasses() {
+ return readonlyExportedClasses;
+ }
+ };
}
diff --git a/core/src/main/java/org/teavm/vm/TeaVMBuilder.java b/core/src/main/java/org/teavm/vm/TeaVMBuilder.java
index ad926fcbf..fbc7599c4 100644
--- a/core/src/main/java/org/teavm/vm/TeaVMBuilder.java
+++ b/core/src/main/java/org/teavm/vm/TeaVMBuilder.java
@@ -18,15 +18,13 @@ package org.teavm.vm;
import org.teavm.model.ClassHolderSource;
import org.teavm.parsing.ClasspathClassHolderSource;
-/**
- *
- * @author Alexey Andreev
- */
public class TeaVMBuilder {
+ TeaVMTarget target;
ClassHolderSource classSource;
ClassLoader classLoader;
- public TeaVMBuilder() {
+ public TeaVMBuilder(TeaVMTarget target) {
+ this.target = target;
classLoader = TeaVMBuilder.class.getClassLoader();
classSource = new ClasspathClassHolderSource(classLoader);
}
@@ -50,6 +48,6 @@ public class TeaVMBuilder {
}
public TeaVM build() {
- return new TeaVM(classSource, classLoader);
+ return new TeaVM(this);
}
}
diff --git a/core/src/main/java/org/teavm/vm/TeaVMEntryPoint.java b/core/src/main/java/org/teavm/vm/TeaVMEntryPoint.java
index 0c8f40bbc..dec5d52db 100644
--- a/core/src/main/java/org/teavm/vm/TeaVMEntryPoint.java
+++ b/core/src/main/java/org/teavm/vm/TeaVMEntryPoint.java
@@ -81,6 +81,10 @@ public class TeaVMEntryPoint {
method.use();
}
+ public MethodReference getReference() {
+ return reference;
+ }
+
String getPublicName() {
return publicName;
}
diff --git a/core/src/main/java/org/teavm/vm/TeaVMPhase.java b/core/src/main/java/org/teavm/vm/TeaVMPhase.java
index a74621432..482b6243c 100644
--- a/core/src/main/java/org/teavm/vm/TeaVMPhase.java
+++ b/core/src/main/java/org/teavm/vm/TeaVMPhase.java
@@ -15,14 +15,10 @@
*/
package org.teavm.vm;
-/**
- *
- * @author Alexey Andreev
- */
public enum TeaVMPhase {
DEPENDENCY_CHECKING,
LINKING,
- DEVIRTUALIZATION,
+ OPTIMIZATION,
DECOMPILATION,
RENDERING
}
diff --git a/core/src/main/java/org/teavm/vm/TeaVMTarget.java b/core/src/main/java/org/teavm/vm/TeaVMTarget.java
new file mode 100644
index 000000000..496757937
--- /dev/null
+++ b/core/src/main/java/org/teavm/vm/TeaVMTarget.java
@@ -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 getHostExtensions();
+
+ boolean requiresRegisterAllocation();
+
+ void contributeDependencies(DependencyChecker dependencyChecker);
+
+ void emit(ListableClassHolderSource classes, OutputStream output, BuildTarget buildTarget);
+}
diff --git a/core/src/main/java/org/teavm/vm/TeaVMTargetController.java b/core/src/main/java/org/teavm/vm/TeaVMTargetController.java
new file mode 100644
index 000000000..28ff0125c
--- /dev/null
+++ b/core/src/main/java/org/teavm/vm/TeaVMTargetController.java
@@ -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 getEntryPoints();
+
+ Map getExportedClasses();
+}
diff --git a/core/src/main/java/org/teavm/vm/spi/TeaVMHost.java b/core/src/main/java/org/teavm/vm/spi/TeaVMHost.java
index e4877202e..b247b296f 100644
--- a/core/src/main/java/org/teavm/vm/spi/TeaVMHost.java
+++ b/core/src/main/java/org/teavm/vm/spi/TeaVMHost.java
@@ -18,8 +18,6 @@ package org.teavm.vm.spi;
import java.util.Properties;
import org.teavm.dependency.BootstrapMethodSubstitutor;
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.MethodReference;
import org.teavm.vm.TeaVM;
@@ -36,13 +34,9 @@ public interface TeaVMHost {
void add(ClassHolderTransformer classTransformer);
- void add(MethodReference methodRef, Generator generator);
-
- void add(MethodReference methodRef, Injector injector);
-
void add(MethodReference methodRef, BootstrapMethodSubstitutor substitutor);
- void add(RendererListener listener);
+ T getExtension(Class extensionType);
void registerService(Class type, T instance);
diff --git a/core/src/main/java/org/teavm/vm/spi/TeaVMHostExtension.java b/core/src/main/java/org/teavm/vm/spi/TeaVMHostExtension.java
new file mode 100644
index 000000000..9bc35477d
--- /dev/null
+++ b/core/src/main/java/org/teavm/vm/spi/TeaVMHostExtension.java
@@ -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 {
+}
diff --git a/core/src/main/java/org/teavm/vm/spi/TeaVMPlugin.java b/core/src/main/java/org/teavm/vm/spi/TeaVMPlugin.java
index 63c1e61ba..eca296c71 100644
--- a/core/src/main/java/org/teavm/vm/spi/TeaVMPlugin.java
+++ b/core/src/main/java/org/teavm/vm/spi/TeaVMPlugin.java
@@ -15,10 +15,6 @@
*/
package org.teavm.vm.spi;
-/**
- *
- * @author Alexey Andreev
- */
public interface TeaVMPlugin {
void install(TeaVMHost host);
}
diff --git a/html4j/src/main/java/org/teavm/html4j/HTML4JPlugin.java b/html4j/src/main/java/org/teavm/html4j/HTML4JPlugin.java
index 1530d308d..9c935dc2f 100644
--- a/html4j/src/main/java/org/teavm/html4j/HTML4JPlugin.java
+++ b/html4j/src/main/java/org/teavm/html4j/HTML4JPlugin.java
@@ -15,19 +15,20 @@
*/
package org.teavm.html4j;
+import org.teavm.javascript.target.TeaVMJavaScriptHost;
import org.teavm.vm.spi.TeaVMHost;
import org.teavm.vm.spi.TeaVMPlugin;
-/**
- *
- * @author Alexey Andreev
- */
public class HTML4JPlugin implements TeaVMPlugin {
@Override
public void install(TeaVMHost host) {
+ if (host.getExtension(TeaVMJavaScriptHost.class) == null) {
+ return;
+ }
host.add(new JavaScriptBodyDependency());
host.add(new JavaScriptBodyTransformer());
host.add(new JCLHacks());
- host.add(new JavaScriptResourceInterceptor());
+
+ host.getExtension(TeaVMJavaScriptHost.class).add(new JavaScriptResourceInterceptor());
}
}
diff --git a/jso/impl/src/main/java/org/teavm/jso/impl/JSOPlugin.java b/jso/impl/src/main/java/org/teavm/jso/impl/JSOPlugin.java
index 4535f4349..d16904468 100644
--- a/jso/impl/src/main/java/org/teavm/jso/impl/JSOPlugin.java
+++ b/jso/impl/src/main/java/org/teavm/jso/impl/JSOPlugin.java
@@ -15,22 +15,23 @@
*/
package org.teavm.jso.impl;
+import org.teavm.javascript.target.TeaVMJavaScriptHost;
import org.teavm.vm.spi.TeaVMHost;
import org.teavm.vm.spi.TeaVMPlugin;
-/**
- *
- * @author Alexey Andreev
- */
public class JSOPlugin implements TeaVMPlugin {
@Override
public void install(TeaVMHost host) {
+ if (host.getExtension(TeaVMJavaScriptHost.class) == null) {
+ return;
+ }
+
JSBodyRepository repository = new JSBodyRepository();
host.registerService(JSBodyRepository.class, repository);
host.add(new JSObjectClassTransformer(repository));
JSDependencyListener dependencyListener = new JSDependencyListener(repository);
JSAliasRenderer aliasRenderer = new JSAliasRenderer(dependencyListener);
host.add(dependencyListener);
- host.add(aliasRenderer);
+ host.getExtension(TeaVMJavaScriptHost.class).add(aliasRenderer);
}
}
diff --git a/platform/src/main/java/org/teavm/platform/plugin/PlatformPlugin.java b/platform/src/main/java/org/teavm/platform/plugin/PlatformPlugin.java
index 0c7c3e080..34b51f4fb 100644
--- a/platform/src/main/java/org/teavm/platform/plugin/PlatformPlugin.java
+++ b/platform/src/main/java/org/teavm/platform/plugin/PlatformPlugin.java
@@ -18,10 +18,6 @@ package org.teavm.platform.plugin;
import org.teavm.vm.spi.TeaVMHost;
import org.teavm.vm.spi.TeaVMPlugin;
-/**
- *
- * @author Alexey Andreev
- */
public class PlatformPlugin implements TeaVMPlugin {
@Override
public void install(TeaVMHost host) {
diff --git a/platform/src/main/java/org/teavm/platform/plugin/ResourceAccessorTransformer.java b/platform/src/main/java/org/teavm/platform/plugin/ResourceAccessorTransformer.java
index 9e4afdd3a..bbf83dbbe 100644
--- a/platform/src/main/java/org/teavm/platform/plugin/ResourceAccessorTransformer.java
+++ b/platform/src/main/java/org/teavm/platform/plugin/ResourceAccessorTransformer.java
@@ -16,18 +16,15 @@
package org.teavm.platform.plugin;
import org.teavm.diagnostics.Diagnostics;
+import org.teavm.javascript.target.TeaVMJavaScriptHost;
import org.teavm.model.*;
import org.teavm.vm.spi.TeaVMHost;
-/**
- *
- * @author Alexey Andreev
- */
class ResourceAccessorTransformer implements ClassHolderTransformer {
- private TeaVMHost vm;
+ private TeaVMJavaScriptHost vm;
public ResourceAccessorTransformer(TeaVMHost vm) {
- this.vm = vm;
+ this.vm = vm.getExtension(TeaVMJavaScriptHost.class);
}
@Override
diff --git a/tests/src/test/java/org/teavm/dependency/ClassValueTest.java b/tests/src/test/java/org/teavm/dependency/ClassValueTest.java
index 2dbb914ae..c78af0db5 100644
--- a/tests/src/test/java/org/teavm/dependency/ClassValueTest.java
+++ b/tests/src/test/java/org/teavm/dependency/ClassValueTest.java
@@ -17,7 +17,9 @@ package org.teavm.dependency;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import org.apache.commons.io.output.ByteArrayOutputStream;
import org.junit.Test;
+import org.teavm.javascript.target.JavaScriptTarget;
import org.teavm.model.MethodReference;
import org.teavm.model.ValueType;
import org.teavm.tooling.TeaVMProblemRenderer;
@@ -73,10 +75,10 @@ public class ClassValueTest {
}
private DependencyInfo runTest(String methodName) {
- TeaVM vm = new TeaVMBuilder().build();
+ TeaVM vm = new TeaVMBuilder(new JavaScriptTarget()).build();
vm.installPlugins();
vm.entryPoint(new MethodReference(getClass().getName(), methodName, ValueType.VOID));
- vm.build(new StringBuilder(), null);
+ vm.build(new ByteArrayOutputStream(), null);
if (!vm.getProblemProvider().getSevereProblems().isEmpty()) {
fail("Code compiled with errors:\n" + describeProblems(vm));
}
diff --git a/tests/src/test/java/org/teavm/tests/JSOTest.java b/tests/src/test/java/org/teavm/tests/JSOTest.java
index 5e9a14ef4..1a183edf3 100644
--- a/tests/src/test/java/org/teavm/tests/JSOTest.java
+++ b/tests/src/test/java/org/teavm/tests/JSOTest.java
@@ -15,15 +15,15 @@
*/
package org.teavm.tests;
-import static org.hamcrest.CoreMatchers.*;
-import static org.junit.Assert.*;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+import java.io.ByteArrayOutputStream;
import java.util.List;
import org.junit.Test;
-import org.junit.runner.RunWith;
import org.teavm.diagnostics.Problem;
+import org.teavm.javascript.target.JavaScriptTarget;
import org.teavm.jso.JSBody;
-import org.teavm.junit.SkipJVM;
-import org.teavm.junit.TeaVMTestRunner;
import org.teavm.model.MethodReference;
import org.teavm.model.ValueType;
import org.teavm.vm.TeaVM;
@@ -96,10 +96,10 @@ public class JSOTest {
private static native Object jsBodyWithWrongReturningType(String value);
private List build(String methodName) {
- TeaVM vm = new TeaVMBuilder().build();
+ TeaVM vm = new TeaVMBuilder(new JavaScriptTarget()).build();
vm.installPlugins();
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();
}
}
diff --git a/tools/cli/src/main/java/org/teavm/cli/TeaVMRunner.java b/tools/cli/src/main/java/org/teavm/cli/TeaVMRunner.java
index 9062cd5cf..1bda04d5a 100644
--- a/tools/cli/src/main/java/org/teavm/cli/TeaVMRunner.java
+++ b/tools/cli/src/main/java/org/teavm/cli/TeaVMRunner.java
@@ -27,10 +27,6 @@ import org.teavm.vm.TeaVMPhase;
import org.teavm.vm.TeaVMProgressFeedback;
import org.teavm.vm.TeaVMProgressListener;
-/**
- *
- * @author Alexey Andreev
- */
public final class TeaVMRunner {
private static long startTime;
private static long phaseStartTime;
@@ -69,10 +65,6 @@ public final class TeaVMRunner {
.withDescription("causes TeaVM to include default main page")
.withLongOpt("mainpage")
.create());
- options.addOption(OptionBuilder
- .withDescription("causes TeaVM to log bytecode")
- .withLongOpt("logbytecode")
- .create());
options.addOption(OptionBuilder
.withDescription("Generate debug information")
.withLongOpt("debug")
@@ -116,7 +108,6 @@ public final class TeaVMRunner {
}
TeaVMTool tool = new TeaVMTool();
- tool.setBytecodeLogging(commandLine.hasOption("logbytecode"));
if (commandLine.hasOption("d")) {
tool.setTargetDirectory(new File(commandLine.getOptionValue("d")));
}
@@ -269,7 +260,7 @@ public final class TeaVMRunner {
case LINKING:
System.out.print("Linking methods...");
break;
- case DEVIRTUALIZATION:
+ case OPTIMIZATION:
System.out.print("Applying devirtualization...");
break;
case DECOMPILATION:
diff --git a/tools/core/src/main/java/org/teavm/tooling/TeaVMTargetType.java b/tools/core/src/main/java/org/teavm/tooling/TeaVMTargetType.java
new file mode 100644
index 000000000..32f774dbe
--- /dev/null
+++ b/tools/core/src/main/java/org/teavm/tooling/TeaVMTargetType.java
@@ -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
+}
diff --git a/tools/core/src/main/java/org/teavm/tooling/TeaVMTool.java b/tools/core/src/main/java/org/teavm/tooling/TeaVMTool.java
index a7bf85646..e508e1ede 100644
--- a/tools/core/src/main/java/org/teavm/tooling/TeaVMTool.java
+++ b/tools/core/src/main/java/org/teavm/tooling/TeaVMTool.java
@@ -15,8 +15,24 @@
*/
package org.teavm.tooling;
-import java.io.*;
-import java.util.*;
+import java.io.BufferedOutputStream;
+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.teavm.cache.DiskCachedClassHolderSource;
import org.teavm.cache.DiskProgramCache;
@@ -27,26 +43,37 @@ import org.teavm.debugging.information.DebugInformationBuilder;
import org.teavm.dependency.DependencyInfo;
import org.teavm.diagnostics.ProblemProvider;
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.tooling.sources.SourceFileProvider;
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;
-/**
- *
- * @author Alexey Andreev
- */
public class TeaVMTool implements BaseTeaVMTool {
private File targetDirectory = new File(".");
+ private TeaVMTargetType targetType = TeaVMTargetType.JAVASCRIPT;
private String targetFileName = "classes.js";
private boolean minifying = true;
private String mainClass;
private RuntimeCopyOperation runtime = RuntimeCopyOperation.SEPARATE;
private Properties properties = new Properties();
private boolean mainPageIncluded;
- private boolean bytecodeLogging;
private boolean debugInformationGenerated;
private boolean sourceMapsFileGenerated;
private boolean sourceFilesCopied;
@@ -66,6 +93,8 @@ public class TeaVMTool implements BaseTeaVMTool {
private TeaVMProgressListener progressListener;
private TeaVM vm;
private List sourceFileProviders = new ArrayList<>();
+ private DebugInformationBuilder debugEmitter;
+ private JavaScriptTarget javaScriptTarget;
public File getTargetDirectory() {
return targetDirectory;
@@ -126,14 +155,6 @@ public class TeaVMTool implements BaseTeaVMTool {
this.mainPageIncluded = mainPageIncluded;
}
- public boolean isBytecodeLogging() {
- return bytecodeLogging;
- }
-
- public void setBytecodeLogging(boolean bytecodeLogging) {
- this.bytecodeLogging = bytecodeLogging;
- }
-
public boolean isDebugInformationGenerated() {
return debugInformationGenerated;
}
@@ -262,11 +283,34 @@ public class TeaVMTool implements BaseTeaVMTool {
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 {
try {
cancelled = false;
log.info("Building JavaScript file");
- TeaVMBuilder vmBuilder = new TeaVMBuilder();
+ TeaVMBuilder vmBuilder = new TeaVMBuilder(prepareTarget());
if (incremental) {
cacheDirectory.mkdirs();
symbolTable = new FileSymbolTable(new File(cacheDirectory, "symbols"));
@@ -276,7 +320,10 @@ public class TeaVMTool implements BaseTeaVMTool {
cachedClassSource = new DiskCachedClassHolderSource(cacheDirectory, symbolTable, fileTable,
classSource, 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 {
symbolTable.update();
fileTable.update();
@@ -292,17 +339,11 @@ public class TeaVMTool implements BaseTeaVMTool {
if (progressListener != null) {
vm.setProgressListener(progressListener);
}
- vm.setMinifying(minifying);
- vm.setBytecodeLogging(bytecodeLogging);
+
vm.setProperties(properties);
- DebugInformationBuilder debugEmitter = debugInformationGenerated || sourceMapsFileGenerated
- ? new DebugInformationBuilder() : null;
- vm.setDebugEmitter(debugEmitter);
+ vm.setProgramCache(programCache);
vm.setIncremental(incremental);
- if (incremental) {
- vm.setAstCache(astCache);
- vm.setProgramCache(programCache);
- }
+
vm.installPlugins();
for (ClassHolderTransformer transformer : transformers) {
vm.add(transformer);
@@ -336,82 +377,96 @@ public class TeaVMTool implements BaseTeaVMTool {
}
}
targetDirectory.mkdirs();
- try (Writer writer = new OutputStreamWriter(new BufferedOutputStream(
- new FileOutputStream(new File(targetDirectory, targetFileName)), 65536), "UTF-8")) {
+ try (OutputStream output = new BufferedOutputStream(
+ new FileOutputStream(new File(targetDirectory, targetFileName)), 65536)) {
+ Writer writer = new OutputStreamWriter(output, "UTF-8");
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()) {
log.info("Build cancelled");
cancelled = true;
return;
}
- if (mainClass != null) {
- writer.append("main = $rt_mainStarter(main);\n");
- }
+
ProblemProvider problemProvider = vm.getProblemProvider();
if (problemProvider.getProblems().isEmpty()) {
- log.info("JavaScript file successfully built");
+ log.info("Output file successfully built");
} else if (problemProvider.getSevereProblems().isEmpty()) {
- log.info("JavaScript file built with warnings");
+ log.info("Output file built with warnings");
TeaVMProblemRenderer.describeProblems(vm, log);
} else {
- log.info("JavaScript file built with errors");
+ log.info("Output file built with errors");
TeaVMProblemRenderer.describeProblems(vm, log);
}
- 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 (targetType == TeaVMTargetType.JAVASCRIPT) {
+ additionalJavaScriptOutput(writer);
}
+
if (incremental) {
programCache.flush();
- astCache.flush();
+ if (astCache != null) {
+ astCache.flush();
+ }
cachedClassSource.flush();
symbolTable.flush();
fileTable.flush();
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) {
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() {
if (vm.getWrittenClasses() == null) {
return;
diff --git a/tools/core/teavm-tooling.iml b/tools/core/teavm-tooling.iml
index a636e0d00..45225ea38 100644
--- a/tools/core/teavm-tooling.iml
+++ b/tools/core/teavm-tooling.iml
@@ -7,7 +7,7 @@
-
+
diff --git a/tools/junit/src/main/java/org/teavm/junit/TeaVMTestRunner.java b/tools/junit/src/main/java/org/teavm/junit/TeaVMTestRunner.java
index d8856ee71..787b559eb 100644
--- a/tools/junit/src/main/java/org/teavm/junit/TeaVMTestRunner.java
+++ b/tools/junit/src/main/java/org/teavm/junit/TeaVMTestRunner.java
@@ -20,8 +20,6 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.Writer;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
@@ -49,6 +47,7 @@ import org.junit.runners.model.InitializationError;
import org.teavm.callgraph.CallGraph;
import org.teavm.diagnostics.DefaultProblemTextConsumer;
import org.teavm.diagnostics.Problem;
+import org.teavm.javascript.target.JavaScriptTarget;
import org.teavm.model.ClassHolder;
import org.teavm.model.ClassHolderSource;
import org.teavm.model.MethodDescriptor;
@@ -345,12 +344,13 @@ public class TeaVMTestRunner extends Runner {
MethodHolder methodHolder = classHolder.getMethod(getDescriptor(method));
Class> runnerType = testAdapter.getRunner(methodHolder);
- TeaVM vm = new TeaVMBuilder()
+ JavaScriptTarget jsTarget = new JavaScriptTarget();
+ jsTarget.setMinifying(false);
+ TeaVM vm = new TeaVMBuilder(jsTarget)
.setClassLoader(classLoader)
.setClassSource(classSource)
.build();
vm.setIncremental(false);
- vm.setMinifying(false);
vm.installPlugins();
new TestExceptionPlugin().install(vm);
@@ -360,7 +360,7 @@ public class TeaVMTestRunner extends Runner {
applyProperties(method.getDeclaringClass(), 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",
Throwable.class, String.class);
vm.entryPoint("runTest", new MethodReference(TestEntryPoint.class, "run", void.class)).async();
diff --git a/tools/maven/plugin/src/main/java/org/teavm/maven/BuildJavascriptMojo.java b/tools/maven/plugin/src/main/java/org/teavm/maven/BuildJavascriptMojo.java
index dbc1dac6d..cc90bbc03 100644
--- a/tools/maven/plugin/src/main/java/org/teavm/maven/BuildJavascriptMojo.java
+++ b/tools/maven/plugin/src/main/java/org/teavm/maven/BuildJavascriptMojo.java
@@ -55,9 +55,6 @@ public class BuildJavascriptMojo extends AbstractJavascriptMojo {
@Parameter
private boolean mainPageIncluded;
- @Parameter
- private boolean bytecodeLogging;
-
@Parameter
private ClassAlias[] classAliases;
@@ -86,7 +83,6 @@ public class BuildJavascriptMojo extends AbstractJavascriptMojo {
setupTool(tool);
tool.setLog(new MavenTeaVMToolLog(log));
try {
- tool.setBytecodeLogging(bytecodeLogging);
tool.setMainClass(mainClass);
tool.setMainPageIncluded(mainPageIncluded);
tool.setRuntime(runtime);