mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
Adds pluggable system to extend TeaVM compiler
This commit is contained in:
parent
8c4514a200
commit
e13accc7e4
|
@ -15,8 +15,10 @@
|
|||
*/
|
||||
package org.teavm.dependency;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import org.teavm.common.*;
|
||||
|
@ -38,6 +40,7 @@ public class DependencyChecker implements DependencyInformation {
|
|||
private ConcurrentCachedMapper<FieldReference, DependencyNode> fieldCache;
|
||||
private ConcurrentMap<String, Object> achievableClasses = new ConcurrentHashMap<>();
|
||||
private ConcurrentMap<String, Object> initializedClasses = new ConcurrentHashMap<>();
|
||||
private List<DependencyListener> listeners = new ArrayList<>();
|
||||
|
||||
public DependencyChecker(ClassHolderSource classSource, ClassLoader classLoader) {
|
||||
this(classSource, classLoader, new SimpleFiniteExecutor());
|
||||
|
@ -59,9 +62,19 @@ public class DependencyChecker implements DependencyInformation {
|
|||
});
|
||||
methodCache.addKeyListener(new KeyListener<MethodReference>() {
|
||||
@Override public void keyAdded(MethodReference key) {
|
||||
for (DependencyListener listener : listeners) {
|
||||
listener.methodAchieved(DependencyChecker.this, key);
|
||||
}
|
||||
activateDependencyPlugin(key);
|
||||
}
|
||||
});
|
||||
fieldCache.addKeyListener(new KeyListener<FieldReference>() {
|
||||
@Override public void keyAdded(FieldReference key) {
|
||||
for (DependencyListener listener : listeners) {
|
||||
listener.fieldAchieved(DependencyChecker.this, key);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public DependencyNode createNode() {
|
||||
|
@ -72,6 +85,10 @@ public class DependencyChecker implements DependencyInformation {
|
|||
return classSource;
|
||||
}
|
||||
|
||||
public void addDependencyListener(DependencyListener listener) {
|
||||
listeners.add(listener);
|
||||
}
|
||||
|
||||
public void addEntryPoint(MethodReference methodRef, String... argumentTypes) {
|
||||
ValueType[] parameters = methodRef.getDescriptor().getParameterTypes();
|
||||
if (parameters.length != argumentTypes.length) {
|
||||
|
@ -98,7 +115,13 @@ public class DependencyChecker implements DependencyInformation {
|
|||
}
|
||||
|
||||
boolean achieveClass(String className) {
|
||||
return achievableClasses.putIfAbsent(className, dummyValue) == null;
|
||||
boolean result = achievableClasses.putIfAbsent(className, dummyValue) == null;
|
||||
if (result) {
|
||||
for (DependencyListener listener : listeners) {
|
||||
listener.classAchieved(this, className);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public MethodGraph attachMethodGraph(MethodReference methodRef) {
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright 2014 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.dependency;
|
||||
|
||||
import org.teavm.model.FieldReference;
|
||||
import org.teavm.model.MethodReference;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public interface DependencyListener {
|
||||
void classAchieved(DependencyChecker dependencyChecker, String className);
|
||||
|
||||
void methodAchieved(DependencyChecker dependencyChecker, MethodReference method);
|
||||
|
||||
void fieldAchieved(DependencyChecker dependencyChecker, FieldReference field);
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright 2014 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.javascript;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public class DirectoryBuildTarget implements JavascriptBuildTarget {
|
||||
private File directory;
|
||||
|
||||
public DirectoryBuildTarget(File directory) {
|
||||
this.directory = directory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OutputStream createResource(String fileName) throws IOException {
|
||||
return new FileOutputStream(new File(directory, fileName));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright 2014 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.javascript;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public interface JavascriptBuildTarget {
|
||||
OutputStream createResource(String fileName) throws IOException;
|
||||
}
|
|
@ -16,14 +16,12 @@
|
|||
package org.teavm.javascript;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
import org.teavm.codegen.*;
|
||||
import org.teavm.common.FiniteExecutor;
|
||||
import org.teavm.dependency.DependencyChecker;
|
||||
import org.teavm.dependency.DependencyInformation;
|
||||
import org.teavm.dependency.DependencyListener;
|
||||
import org.teavm.javascript.ast.ClassNode;
|
||||
import org.teavm.model.*;
|
||||
import org.teavm.model.util.*;
|
||||
|
@ -34,8 +32,8 @@ import org.teavm.optimization.Devirtualization;
|
|||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public class JavascriptBuilder {
|
||||
private ClassHolderSource classSource;
|
||||
public class JavascriptBuilder implements JavascriptBuilderHost {
|
||||
private JavascriptProcessedClassSource classSource;
|
||||
private DependencyChecker dependencyChecker;
|
||||
private FiniteExecutor executor;
|
||||
private ClassLoader classLoader;
|
||||
|
@ -44,6 +42,7 @@ public class JavascriptBuilder {
|
|||
private OutputStream logStream = System.out;
|
||||
private Map<String, JavascriptEntryPoint> entryPoints = new HashMap<>();
|
||||
private Map<String, String> exportedClasses = new HashMap<>();
|
||||
private List<JavascriptResourceRenderer> ressourceRenderers = new ArrayList<>();
|
||||
|
||||
JavascriptBuilder(ClassHolderSource classSource, ClassLoader classLoader, FiniteExecutor executor) {
|
||||
this.classSource = new JavascriptProcessedClassSource(classSource);
|
||||
|
@ -52,6 +51,21 @@ public class JavascriptBuilder {
|
|||
this.executor = executor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(DependencyListener listener) {
|
||||
dependencyChecker.addDependencyListener(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(ClassHolderTransformer transformer) {
|
||||
classSource.addTransformer(transformer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(JavascriptResourceRenderer resourceRenderer) {
|
||||
ressourceRenderers.add(resourceRenderer);
|
||||
}
|
||||
|
||||
public boolean isMinifying() {
|
||||
return minifying;
|
||||
}
|
||||
|
@ -91,7 +105,7 @@ public class JavascriptBuilder {
|
|||
return classSource;
|
||||
}
|
||||
|
||||
public void build(Appendable writer) throws RenderingException {
|
||||
public void build(Appendable writer, JavascriptBuildTarget target) throws RenderingException {
|
||||
AliasProvider aliasProvider = minifying ? new MinifyingAliasProvider() : new DefaultAliasProvider();
|
||||
DefaultNamingStrategy naming = new DefaultNamingStrategy(aliasProvider, classSource);
|
||||
naming.setMinifying(minifying);
|
||||
|
@ -134,6 +148,9 @@ public class JavascriptBuilder {
|
|||
sourceWriter.append(entry.getKey()).ws().append("=").ws().appendClass(entry.getValue()).append(";")
|
||||
.softNewLine();
|
||||
}
|
||||
for (JavascriptResourceRenderer resourceRenderer : ressourceRenderers) {
|
||||
resourceRenderer.render(target);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RenderingException("IO Error occured", e);
|
||||
}
|
||||
|
@ -275,13 +292,19 @@ public class JavascriptBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
public void build(File file) throws RenderingException {
|
||||
try (Writer writer = new OutputStreamWriter(new FileOutputStream(file), "UTF-8")) {
|
||||
build(writer);
|
||||
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));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new RuntimeException("Platform does not support UTF-8", e);
|
||||
} catch (IOException e) {
|
||||
throw new RenderingException("IO error occured", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void installPlugins() {
|
||||
for (JavascriptBuilderPlugin plugin : ServiceLoader.load(JavascriptBuilderPlugin.class)) {
|
||||
plugin.install(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright 2014 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.javascript;
|
||||
|
||||
import org.teavm.dependency.DependencyListener;
|
||||
import org.teavm.model.ClassHolderTransformer;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public interface JavascriptBuilderHost {
|
||||
void add(DependencyListener dependencyListener);
|
||||
|
||||
void add(ClassHolderTransformer classTransformer);
|
||||
|
||||
void add(JavascriptResourceRenderer resourceRenderer);
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* Copyright 2014 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.javascript;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public interface JavascriptBuilderPlugin {
|
||||
void install(JavascriptBuilderHost host);
|
||||
}
|
|
@ -15,22 +15,30 @@
|
|||
*/
|
||||
package org.teavm.javascript;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.teavm.model.ClassHolder;
|
||||
import org.teavm.model.ClassHolderSource;
|
||||
import org.teavm.model.ClassHolderTransformer;
|
||||
import org.teavm.model.MethodHolder;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public class JavascriptProcessedClassSource implements ClassHolderSource {
|
||||
class JavascriptProcessedClassSource implements ClassHolderSource {
|
||||
private ThreadLocal<JavascriptNativeProcessor> processor = new ThreadLocal<>();
|
||||
private ClassHolderSource innerSource;
|
||||
private List<ClassHolderTransformer> transformers = new ArrayList<>();
|
||||
|
||||
public JavascriptProcessedClassSource(ClassHolderSource innerSource) {
|
||||
this.innerSource = innerSource;
|
||||
}
|
||||
|
||||
public void addTransformer(ClassHolderTransformer transformer) {
|
||||
transformers.add(transformer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassHolder get(String name) {
|
||||
ClassHolder cls = innerSource.get(name);
|
||||
|
@ -48,6 +56,9 @@ public class JavascriptProcessedClassSource implements ClassHolderSource {
|
|||
processor.processProgram(method.getProgram());
|
||||
}
|
||||
}
|
||||
for (ClassHolderTransformer transformer : transformers) {
|
||||
transformer.transformClass(cls);
|
||||
}
|
||||
}
|
||||
|
||||
private JavascriptNativeProcessor getProcessor() {
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Copyright 2014 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.javascript;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public interface JavascriptResourceRenderer {
|
||||
void render(JavascriptBuildTarget buildTarget) throws IOException;
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* Copyright 2014 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.model;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public interface ClassHolderTransformer {
|
||||
void transformClass(ClassHolder cls);
|
||||
}
|
|
@ -37,6 +37,7 @@ import org.junit.Test;
|
|||
import org.teavm.common.FiniteExecutor;
|
||||
import org.teavm.common.SimpleFiniteExecutor;
|
||||
import org.teavm.common.ThreadPoolFiniteExecutor;
|
||||
import org.teavm.javascript.DirectoryBuildTarget;
|
||||
import org.teavm.javascript.JavascriptBuilder;
|
||||
import org.teavm.javascript.JavascriptBuilderFactory;
|
||||
import org.teavm.model.*;
|
||||
|
@ -234,6 +235,7 @@ public class BuildJavascriptJUnitMojo extends AbstractMojo {
|
|||
builderFactory.setExecutor(executor);
|
||||
JavascriptBuilder builder = builderFactory.create();
|
||||
builder.setMinifying(minifying);
|
||||
builder.installPlugins();
|
||||
File file = new File(outputDir, targetName);
|
||||
try (Writer innerWriter = new OutputStreamWriter(new FileOutputStream(file), "UTF-8")) {
|
||||
MethodReference cons = new MethodReference(methodRef.getClassName(),
|
||||
|
@ -241,7 +243,7 @@ public class BuildJavascriptJUnitMojo extends AbstractMojo {
|
|||
builder.entryPoint("initInstance", cons);
|
||||
builder.entryPoint("runTest", methodRef).withValue(0, cons.getClassName());
|
||||
builder.exportType("TestClass", cons.getClassName());
|
||||
builder.build(innerWriter);
|
||||
builder.build(innerWriter, new DirectoryBuildTarget(outputDir));
|
||||
innerWriter.append("\n");
|
||||
innerWriter.append("\nJUnitClient.run();");
|
||||
innerWriter.close();
|
||||
|
|
|
@ -132,12 +132,13 @@ public class BuildJavascriptMojo extends AbstractMojo {
|
|||
JavascriptBuilder builder = builderFactory.create();
|
||||
builder.setMinifying(minifying);
|
||||
builder.setBytecodeLogging(bytecodeLogging);
|
||||
builder.installPlugins();
|
||||
MethodDescriptor mainMethodDesc = new MethodDescriptor("main", ValueType.arrayOf(
|
||||
ValueType.object("java.lang.String")), ValueType.VOID);
|
||||
builder.entryPoint("main", new MethodReference(mainClass, mainMethodDesc))
|
||||
.withValue(1, "java.lang.String");
|
||||
targetDirectory.mkdirs();
|
||||
builder.build(new File(targetDirectory, targetFileName));
|
||||
builder.build(targetDirectory, targetFileName);
|
||||
log.info("JavaScript file successfully built");
|
||||
if (!runtimeSuppressed) {
|
||||
resourceToFile("org/teavm/javascript/runtime.js", "runtime.js");
|
||||
|
@ -194,7 +195,7 @@ public class BuildJavascriptMojo extends AbstractMojo {
|
|||
}
|
||||
|
||||
private void resourceToFile(String resource, String fileName) throws IOException {
|
||||
try (InputStream input = BuildJavascriptJUnitMojo.class.getClassLoader().getResourceAsStream(resource)) {
|
||||
try (InputStream input = BuildJavascriptMojo.class.getClassLoader().getResourceAsStream(resource)) {
|
||||
try (OutputStream output = new FileOutputStream(new File(targetDirectory, fileName))) {
|
||||
IOUtils.copy(input, output);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user