mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
Don't generate virtual wrappers for methods that aren't ever called virtually
This commit is contained in:
parent
681e21ecca
commit
b66053f5ce
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright 2018 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.classlib.impl;
|
||||
|
||||
import org.teavm.backend.javascript.spi.VirtualMethodContributor;
|
||||
import org.teavm.backend.javascript.spi.VirtualMethodContributorContext;
|
||||
import org.teavm.model.ClassReader;
|
||||
import org.teavm.model.MethodReference;
|
||||
import org.teavm.platform.PlatformAnnotationProvider;
|
||||
|
||||
public class AnnotationVirtualMethods implements VirtualMethodContributor {
|
||||
@Override
|
||||
public boolean isVirtual(VirtualMethodContributorContext context, MethodReference methodRef) {
|
||||
ClassReader cls = context.getClassSource().get(methodRef.getClassName());
|
||||
if (cls == null || !cls.getInterfaces().contains(PlatformAnnotationProvider.class.getName())) {
|
||||
return false;
|
||||
}
|
||||
return methodRef.getName().equals("getAnnotations");
|
||||
}
|
||||
}
|
|
@ -46,6 +46,7 @@ public class JCLPlugin implements TeaVMPlugin {
|
|||
TeaVMJavaScriptHost jsExtension = host.getExtension(TeaVMJavaScriptHost.class);
|
||||
if (jsExtension != null) {
|
||||
jsExtension.add(loadServicesMethod, serviceLoaderSupp);
|
||||
jsExtension.addVirtualMethods(new AnnotationVirtualMethods());
|
||||
}
|
||||
|
||||
JavacSupport javacSupport = new JavacSupport();
|
||||
|
|
|
@ -267,17 +267,19 @@ public class ClassGenerator implements Generator, Injector, DependencyPlugin {
|
|||
if (method.getResultType() != ValueType.VOID) {
|
||||
writer.append("return ");
|
||||
}
|
||||
if (method.hasModifier(ElementModifier.STATIC)) {
|
||||
writer.appendMethodBody(method.getReference());
|
||||
} else {
|
||||
writer.append("obj.").appendMethod(method.getDescriptor());
|
||||
}
|
||||
writer.appendMethodBody(method.getReference());
|
||||
|
||||
writer.append('(');
|
||||
boolean first = true;
|
||||
if (!method.hasModifier(ElementModifier.STATIC)) {
|
||||
writer.append("obj").ws();
|
||||
first = false;
|
||||
}
|
||||
for (int i = 0; i < method.parameterCount(); ++i) {
|
||||
if (i > 0) {
|
||||
if (!first) {
|
||||
writer.append(',').ws();
|
||||
}
|
||||
first = false;
|
||||
int index = i;
|
||||
unboxIfNecessary(writer, method.parameterType(i), () -> writer.append("args[" + index + "]"));
|
||||
}
|
||||
|
|
|
@ -24,7 +24,6 @@ import org.teavm.dependency.DependencyPlugin;
|
|||
import org.teavm.dependency.MethodDependency;
|
||||
import org.teavm.model.CallLocation;
|
||||
import org.teavm.model.ClassReader;
|
||||
import org.teavm.model.MethodDescriptor;
|
||||
import org.teavm.model.MethodReference;
|
||||
import org.teavm.model.ValueType;
|
||||
|
||||
|
@ -40,13 +39,18 @@ public class ArrayNativeGenerator implements Generator, DependencyPlugin {
|
|||
public void methodReached(DependencyAgent agent, MethodDependency method, CallLocation location) {
|
||||
switch (method.getReference().getName()) {
|
||||
case "getLength":
|
||||
achieveGetLength(agent, method);
|
||||
reachGetLength(agent, method);
|
||||
break;
|
||||
case "newInstance":
|
||||
method.getVariable(1).getClassValueNode().addConsumer(t -> {
|
||||
String arrayTypeName = t.getName().startsWith("[")
|
||||
? t.getName()
|
||||
: ValueType.object(t.getName()).toString();
|
||||
String arrayTypeName;
|
||||
if (t.getName().startsWith("[")) {
|
||||
arrayTypeName = t.getName();
|
||||
} else if (t.getName().startsWith("~")) {
|
||||
arrayTypeName = t.getName().substring(1);
|
||||
} else {
|
||||
arrayTypeName = ValueType.object(t.getName()).toString();
|
||||
}
|
||||
method.getResult().propagate(agent.getType("[" + arrayTypeName));
|
||||
});
|
||||
break;
|
||||
|
@ -81,14 +85,13 @@ public class ArrayNativeGenerator implements Generator, DependencyPlugin {
|
|||
String array = context.getParameterName(1);
|
||||
writer.append("if (" + array + " === null || " + array + ".constructor.$meta.item === undefined) {")
|
||||
.softNewLine().indent();
|
||||
String clsName = "java.lang.IllegalArgumentException";
|
||||
MethodDescriptor cons = new MethodDescriptor("<init>", ValueType.VOID);
|
||||
writer.append("$rt_throw(").appendClass(clsName).append(".").appendMethod(cons).append("());").softNewLine();
|
||||
MethodReference cons = new MethodReference("java.lang.IllegalArgumentException", "<init>", ValueType.VOID);
|
||||
writer.append("$rt_throw(").append(writer.getNaming().getNameForInit(cons)).append("());").softNewLine();
|
||||
writer.outdent().append("}").softNewLine();
|
||||
writer.append("return " + array + ".data.length;").softNewLine();
|
||||
}
|
||||
|
||||
private void achieveGetLength(final DependencyAgent agent, final MethodDependency method) {
|
||||
private void reachGetLength(final DependencyAgent agent, final MethodDependency method) {
|
||||
method.getVariable(1).addConsumer(type -> {
|
||||
if (!type.getName().startsWith("[")) {
|
||||
MethodReference cons = new MethodReference(IllegalArgumentException.class, "<init>", void.class);
|
||||
|
|
|
@ -49,6 +49,8 @@ import org.teavm.backend.javascript.spi.GeneratedBy;
|
|||
import org.teavm.backend.javascript.spi.Generator;
|
||||
import org.teavm.backend.javascript.spi.InjectedBy;
|
||||
import org.teavm.backend.javascript.spi.Injector;
|
||||
import org.teavm.backend.javascript.spi.VirtualMethodContributor;
|
||||
import org.teavm.backend.javascript.spi.VirtualMethodContributorContext;
|
||||
import org.teavm.debugging.information.DebugInformationEmitter;
|
||||
import org.teavm.debugging.information.DummyDebugInformationEmitter;
|
||||
import org.teavm.debugging.information.SourceLocation;
|
||||
|
@ -104,6 +106,7 @@ public class JavaScriptTarget implements TeaVMTarget, TeaVMJavaScriptHost {
|
|||
private final Set<MethodReference> asyncMethods = new HashSet<>();
|
||||
private final Set<MethodReference> asyncFamilyMethods = new HashSet<>();
|
||||
private ClassInitializerInsertionTransformer clinitInsertionTransformer;
|
||||
private List<VirtualMethodContributor> customVirtualMethods = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public List<ClassHolderTransformer> getTransformers() {
|
||||
|
@ -194,19 +197,35 @@ public class JavaScriptTarget implements TeaVMTarget, TeaVMJavaScriptHost {
|
|||
|
||||
@Override
|
||||
public void contributeDependencies(DependencyAnalyzer dependencyAnalyzer) {
|
||||
dependencyAnalyzer.linkMethod(new MethodReference(Class.class.getName(), "getClass",
|
||||
ValueType.object("org.teavm.platform.PlatformClass"), ValueType.parse(Class.class)), null).use();
|
||||
dependencyAnalyzer.linkMethod(new MethodReference(String.class, "<init>", char[].class, void.class),
|
||||
null).use();
|
||||
dependencyAnalyzer.linkMethod(new MethodReference(String.class, "getChars", int.class, int.class, char[].class,
|
||||
int.class, void.class), null).use();
|
||||
MethodDependency dep;
|
||||
|
||||
dep = dependencyAnalyzer.linkMethod(new MethodReference(Class.class.getName(), "getClass",
|
||||
ValueType.object("org.teavm.platform.PlatformClass"), ValueType.parse(Class.class)), null);
|
||||
dep.getVariable(0).propagate(dependencyAnalyzer.getType("org.teavm.platform.PlatformClass"));
|
||||
dep.getResult().propagate(dependencyAnalyzer.getType("java.lang.Class"));
|
||||
dep.use();
|
||||
|
||||
dep = dependencyAnalyzer.linkMethod(new MethodReference(String.class, "<init>", char[].class, void.class),
|
||||
null);
|
||||
dep.getVariable(0).propagate(dependencyAnalyzer.getType("java.lang.String"));
|
||||
dep.getVariable(1).propagate(dependencyAnalyzer.getType("[C"));
|
||||
dep.use();
|
||||
|
||||
dep = dependencyAnalyzer.linkMethod(new MethodReference(String.class, "getChars", int.class, int.class,
|
||||
char[].class, int.class, void.class), null);
|
||||
dep.getVariable(0).propagate(dependencyAnalyzer.getType("java.lang.String"));
|
||||
dep.getVariable(3).propagate(dependencyAnalyzer.getType("[C"));
|
||||
dep.use();
|
||||
|
||||
MethodDependency internDep = dependencyAnalyzer.linkMethod(new MethodReference(String.class, "intern",
|
||||
String.class), null);
|
||||
internDep.getVariable(0).propagate(dependencyAnalyzer.getType("java.lang.String"));
|
||||
internDep.use();
|
||||
|
||||
dependencyAnalyzer.linkMethod(new MethodReference(String.class, "length", int.class), null).use();
|
||||
dep = dependencyAnalyzer.linkMethod(new MethodReference(String.class, "length", int.class), null);
|
||||
dep.getVariable(0).propagate(dependencyAnalyzer.getType("java.lang.String"));
|
||||
dep.use();
|
||||
|
||||
dependencyAnalyzer.linkMethod(new MethodReference(Object.class, "clone", Object.class), null).use();
|
||||
dependencyAnalyzer.linkMethod(new MethodReference(Thread.class, "currentThread", Thread.class), null).use();
|
||||
dependencyAnalyzer.linkMethod(new MethodReference(Thread.class, "getMainThread", Thread.class), null).use();
|
||||
|
@ -264,10 +283,12 @@ public class JavaScriptTarget implements TeaVMTarget, TeaVMJavaScriptHost {
|
|||
if (debugEmitterToUse == null) {
|
||||
debugEmitterToUse = new DummyDebugInformationEmitter();
|
||||
}
|
||||
VirtualMethodContributorContext virtualMethodContributorContext = new VirtualMethodContributorContextImpl(
|
||||
classes);
|
||||
RenderingContext renderingContext = new RenderingContext(debugEmitterToUse,
|
||||
controller.getUnprocessedClassSource(), classes,
|
||||
controller.getClassLoader(), controller.getServices(), controller.getProperties(), naming,
|
||||
controller.getDependencyInfo());
|
||||
controller.getDependencyInfo(), m -> isVirtual(virtualMethodContributorContext, m));
|
||||
renderingContext.setMinifying(minifying);
|
||||
Renderer renderer = new Renderer(sourceWriter, asyncMethods, asyncFamilyMethods,
|
||||
controller.getDiagnostics(), renderingContext);
|
||||
|
@ -505,8 +526,38 @@ public class JavaScriptTarget implements TeaVMTarget, TeaVMJavaScriptHost {
|
|||
return new String[] { PlatformMarkers.JAVASCRIPT };
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addVirtualMethods(VirtualMethodContributor virtualMethods) {
|
||||
customVirtualMethods.add(virtualMethods);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAsyncSupported() {
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean isVirtual(VirtualMethodContributorContext context, MethodReference method) {
|
||||
if (controller.isVirtual(method)) {
|
||||
return true;
|
||||
}
|
||||
for (VirtualMethodContributor predicate : customVirtualMethods) {
|
||||
if (predicate.isVirtual(context, method)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static class VirtualMethodContributorContextImpl implements VirtualMethodContributorContext {
|
||||
private ClassReaderSource classSource;
|
||||
|
||||
VirtualMethodContributorContextImpl(ClassReaderSource classSource) {
|
||||
this.classSource = classSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassReaderSource getClassSource() {
|
||||
return classSource;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ package org.teavm.backend.javascript;
|
|||
import java.util.function.Function;
|
||||
import org.teavm.backend.javascript.spi.Generator;
|
||||
import org.teavm.backend.javascript.spi.Injector;
|
||||
import org.teavm.backend.javascript.spi.VirtualMethodContributor;
|
||||
import org.teavm.model.MethodReference;
|
||||
import org.teavm.vm.spi.RendererListener;
|
||||
import org.teavm.vm.spi.TeaVMHostExtension;
|
||||
|
@ -32,4 +33,6 @@ public interface TeaVMJavaScriptHost extends TeaVMHostExtension {
|
|||
void addInjectorProvider(Function<ProviderContext, Injector> provider);
|
||||
|
||||
void add(RendererListener listener);
|
||||
|
||||
void addVirtualMethods(VirtualMethodContributor virtualMethods);
|
||||
}
|
||||
|
|
|
@ -118,10 +118,6 @@ public class SourceWriter implements Appendable, LocationProvider {
|
|||
return append(naming.getNameFor(method));
|
||||
}
|
||||
|
||||
public SourceWriter appendMethod(String name, ValueType... params) throws NamingException, IOException {
|
||||
return append(naming.getNameFor(new MethodDescriptor(name, params)));
|
||||
}
|
||||
|
||||
public SourceWriter appendMethod(String name, Class<?>... params) throws NamingException, IOException {
|
||||
return append(naming.getNameFor(new MethodDescriptor(name, params)));
|
||||
}
|
||||
|
|
|
@ -741,6 +741,9 @@ public class Renderer implements RenderingManager {
|
|||
writer.append("[");
|
||||
boolean first = true;
|
||||
for (MethodReference method : methods) {
|
||||
if (!isVirtual(method)) {
|
||||
continue;
|
||||
}
|
||||
debugEmitter.emitMethod(method.getDescriptor());
|
||||
if (!first) {
|
||||
writer.append(",").ws();
|
||||
|
@ -1069,4 +1072,8 @@ public class Renderer implements RenderingManager {
|
|||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isVirtual(MethodReference method) {
|
||||
return context.isVirtual(method);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ import java.util.HashMap;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.function.Predicate;
|
||||
import org.teavm.backend.javascript.codegen.NamingStrategy;
|
||||
import org.teavm.backend.javascript.spi.InjectedBy;
|
||||
import org.teavm.backend.javascript.spi.Injector;
|
||||
|
@ -50,6 +51,7 @@ public class RenderingContext {
|
|||
private Properties properties;
|
||||
private NamingStrategy naming;
|
||||
private DependencyInfo dependencyInfo;
|
||||
private Predicate<MethodReference> virtualPredicate;
|
||||
private final Deque<LocationStackEntry> locationStack = new ArrayDeque<>();
|
||||
private final Map<String, Integer> stringPoolMap = new HashMap<>();
|
||||
private final List<String> stringPool = new ArrayList<>();
|
||||
|
@ -60,7 +62,8 @@ public class RenderingContext {
|
|||
public RenderingContext(DebugInformationEmitter debugEmitter,
|
||||
ClassReaderSource initialClassSource, ListableClassReaderSource classSource,
|
||||
ClassLoader classLoader, ServiceRepository services, Properties properties,
|
||||
NamingStrategy naming, DependencyInfo dependencyInfo) {
|
||||
NamingStrategy naming, DependencyInfo dependencyInfo,
|
||||
Predicate<MethodReference> virtualPredicate) {
|
||||
this.debugEmitter = debugEmitter;
|
||||
this.initialClassSource = initialClassSource;
|
||||
this.classSource = classSource;
|
||||
|
@ -69,6 +72,7 @@ public class RenderingContext {
|
|||
this.properties = properties;
|
||||
this.naming = naming;
|
||||
this.dependencyInfo = dependencyInfo;
|
||||
this.virtualPredicate = virtualPredicate;
|
||||
}
|
||||
|
||||
public ClassReaderSource getInitialClassSource() {
|
||||
|
@ -107,6 +111,10 @@ public class RenderingContext {
|
|||
return debugEmitter;
|
||||
}
|
||||
|
||||
public boolean isVirtual(MethodReference method) {
|
||||
return virtualPredicate.test(method);
|
||||
}
|
||||
|
||||
public void pushLocation(TextLocation location) {
|
||||
LocationStackEntry prevEntry = locationStack.peek();
|
||||
if (location != null) {
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Copyright 2018 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.backend.javascript.spi;
|
||||
|
||||
import org.teavm.model.MethodReference;
|
||||
|
||||
public interface VirtualMethodContributor {
|
||||
boolean isVirtual(VirtualMethodContributorContext context, MethodReference methodRef);
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Copyright 2018 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.backend.javascript.spi;
|
||||
|
||||
import org.teavm.model.ClassReaderSource;
|
||||
|
||||
public interface VirtualMethodContributorContext {
|
||||
ClassReaderSource getClassSource();
|
||||
}
|
|
@ -112,7 +112,11 @@ public class DependencyAnalyzer implements DependencyInfo {
|
|||
if (field != null && !field.getReference().equals(preimage)) {
|
||||
return fieldCache.map(field.getReference());
|
||||
}
|
||||
return createFieldNode(preimage, field);
|
||||
FieldDependency node = createFieldNode(preimage, field);
|
||||
if (field != null && field.getInitialValue() instanceof String) {
|
||||
node.getValue().propagate(getType("java.lang.String"));
|
||||
}
|
||||
return node;
|
||||
});
|
||||
|
||||
classCache = new CachedMapper<>(this::createClassDependency);
|
||||
|
|
|
@ -403,6 +403,8 @@ class DependencyGraphBuilder {
|
|||
sb.append(cst.toString());
|
||||
}
|
||||
node.getClassValueNode().propagate(dependencyAnalyzer.getType(sb.toString()));
|
||||
} else {
|
||||
node.getClassValueNode().propagate(dependencyAnalyzer.getType("~" + cst.toString()));
|
||||
}
|
||||
}
|
||||
while (cst instanceof ValueType.Array) {
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
*/
|
||||
package org.teavm.model.optimization;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import org.teavm.dependency.DependencyInfo;
|
||||
|
@ -33,6 +34,8 @@ import org.teavm.model.instructions.InvokeInstruction;
|
|||
public class Devirtualization {
|
||||
private DependencyInfo dependency;
|
||||
private ClassReaderSource classSource;
|
||||
private Set<MethodReference> virtualMethods = new HashSet<>();
|
||||
private Set<? extends MethodReference> readonlyVirtualMethods = Collections.unmodifiableSet(virtualMethods);
|
||||
|
||||
public Devirtualization(DependencyInfo dependency, ClassReaderSource classSource) {
|
||||
this.dependency = dependency;
|
||||
|
@ -61,6 +64,8 @@ public class Devirtualization {
|
|||
if (implementations.size() == 1) {
|
||||
invoke.setType(InvocationType.SPECIAL);
|
||||
invoke.setMethod(implementations.iterator().next());
|
||||
} else {
|
||||
virtualMethods.addAll(implementations);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -84,4 +89,8 @@ public class Devirtualization {
|
|||
}
|
||||
return methods;
|
||||
}
|
||||
|
||||
public Set<? extends MethodReference> getVirtualMethods() {
|
||||
return readonlyVirtualMethods;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -124,6 +124,7 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
|
|||
private ListableClassHolderSource writtenClasses;
|
||||
private TeaVMTarget target;
|
||||
private Map<Class<?>, TeaVMHostExtension> extensions = new HashMap<>();
|
||||
private Set<? extends MethodReference> virtualMethods;
|
||||
|
||||
TeaVM(TeaVMBuilder builder) {
|
||||
target = builder.target;
|
||||
|
@ -457,6 +458,7 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
|
|||
return;
|
||||
}
|
||||
}
|
||||
virtualMethods = devirtualization.getVirtualMethods();
|
||||
}
|
||||
|
||||
private void inline(ListableClassHolderSource classes, DependencyInfo dependencyInfo) {
|
||||
|
@ -692,5 +694,10 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
|
|||
public boolean isFriendlyToDebugger() {
|
||||
return optimizationLevel == TeaVMOptimizationLevel.SIMPLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVirtual(MethodReference method) {
|
||||
return incremental || virtualMethods == null || virtualMethods.contains(method);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ import org.teavm.common.ServiceRepository;
|
|||
import org.teavm.dependency.DependencyInfo;
|
||||
import org.teavm.diagnostics.Diagnostics;
|
||||
import org.teavm.model.ClassReaderSource;
|
||||
import org.teavm.model.MethodReference;
|
||||
|
||||
public interface TeaVMTargetController {
|
||||
boolean wasCancelled();
|
||||
|
@ -45,4 +46,6 @@ public interface TeaVMTargetController {
|
|||
Map<? extends String, ? extends TeaVMEntryPoint> getEntryPoints();
|
||||
|
||||
Set<? extends String> getPreservedClasses();
|
||||
|
||||
boolean isVirtual(MethodReference method);
|
||||
}
|
||||
|
|
|
@ -20,6 +20,8 @@ import java.util.HashMap;
|
|||
import java.util.Map;
|
||||
import org.teavm.backend.javascript.codegen.SourceWriter;
|
||||
import org.teavm.backend.javascript.rendering.RenderingManager;
|
||||
import org.teavm.backend.javascript.spi.VirtualMethodContributor;
|
||||
import org.teavm.backend.javascript.spi.VirtualMethodContributorContext;
|
||||
import org.teavm.model.AnnotationReader;
|
||||
import org.teavm.model.ClassReader;
|
||||
import org.teavm.model.FieldReader;
|
||||
|
@ -27,16 +29,17 @@ import org.teavm.model.FieldReference;
|
|||
import org.teavm.model.ListableClassReaderSource;
|
||||
import org.teavm.model.MethodDescriptor;
|
||||
import org.teavm.model.MethodReader;
|
||||
import org.teavm.model.MethodReference;
|
||||
import org.teavm.vm.BuildTarget;
|
||||
import org.teavm.vm.spi.RendererListener;
|
||||
|
||||
class JSAliasRenderer implements RendererListener {
|
||||
class JSAliasRenderer implements RendererListener, VirtualMethodContributor {
|
||||
private static String variableChars = "abcdefghijklmnopqrstuvwxyz";
|
||||
private SourceWriter writer;
|
||||
private ListableClassReaderSource classSource;
|
||||
|
||||
@Override
|
||||
public void begin(RenderingManager context, BuildTarget buildTarget) throws IOException {
|
||||
public void begin(RenderingManager context, BuildTarget buildTarget) {
|
||||
writer = context.getWriter();
|
||||
classSource = context.getClassSource();
|
||||
}
|
||||
|
@ -172,4 +175,19 @@ class JSAliasRenderer implements RendererListener {
|
|||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVirtual(VirtualMethodContributorContext context, MethodReference methodRef) {
|
||||
ClassReader classReader = context.getClassSource().get(methodRef.getClassName());
|
||||
if (classReader == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (getFunctorField(classReader) != null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
MethodReader methodReader = classReader.getMethod(methodRef.getDescriptor());
|
||||
return methodReader != null && getPublicAlias(methodReader) != null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,12 +35,12 @@ public class JSOPlugin implements TeaVMPlugin {
|
|||
JSAliasRenderer aliasRenderer = new JSAliasRenderer();
|
||||
host.add(dependencyListener);
|
||||
|
||||
|
||||
jsHost.add(aliasRenderer);
|
||||
jsHost.addGeneratorProvider(new GeneratorAnnotationInstaller<>(new JSBodyGenerator(),
|
||||
DynamicGenerator.class.getName()));
|
||||
jsHost.addInjectorProvider(new GeneratorAnnotationInstaller<>(new JSBodyGenerator(),
|
||||
DynamicInjector.class.getName()));
|
||||
jsHost.addVirtualMethods(aliasRenderer);
|
||||
|
||||
TeaVMPluginUtil.handleNatives(host, JS.class);
|
||||
}
|
||||
|
|
|
@ -19,6 +19,8 @@ import java.io.IOException;
|
|||
import org.teavm.backend.javascript.codegen.SourceWriter;
|
||||
import org.teavm.backend.javascript.spi.Generator;
|
||||
import org.teavm.backend.javascript.spi.GeneratorContext;
|
||||
import org.teavm.backend.javascript.spi.VirtualMethodContributor;
|
||||
import org.teavm.backend.javascript.spi.VirtualMethodContributorContext;
|
||||
import org.teavm.dependency.DependencyAgent;
|
||||
import org.teavm.dependency.DependencyPlugin;
|
||||
import org.teavm.dependency.MethodDependency;
|
||||
|
@ -30,7 +32,7 @@ import org.teavm.model.MethodReference;
|
|||
import org.teavm.model.ValueType;
|
||||
import org.teavm.platform.async.AsyncCallback;
|
||||
|
||||
public class AsyncMethodGenerator implements Generator, DependencyPlugin {
|
||||
public class AsyncMethodGenerator implements Generator, DependencyPlugin, VirtualMethodContributor {
|
||||
private static final MethodReference completeMethod = new MethodReference(AsyncCallback.class, "complete",
|
||||
Object.class, void.class);
|
||||
private static final MethodReference errorMethod = new MethodReference(AsyncCallback.class, "error",
|
||||
|
@ -122,4 +124,9 @@ public class AsyncMethodGenerator implements Generator, DependencyPlugin {
|
|||
|
||||
asyncMethod.use();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVirtual(VirtualMethodContributorContext context, MethodReference methodRef) {
|
||||
return methodRef.equals(completeMethod) || methodRef.equals(errorMethod);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,12 @@ import org.teavm.backend.javascript.spi.InjectorContext;
|
|||
import org.teavm.dependency.DependencyAgent;
|
||||
import org.teavm.dependency.DependencyPlugin;
|
||||
import org.teavm.dependency.MethodDependency;
|
||||
import org.teavm.model.*;
|
||||
import org.teavm.model.CallLocation;
|
||||
import org.teavm.model.ClassReader;
|
||||
import org.teavm.model.MethodDescriptor;
|
||||
import org.teavm.model.MethodReader;
|
||||
import org.teavm.model.MethodReference;
|
||||
import org.teavm.model.ValueType;
|
||||
import org.teavm.platform.Platform;
|
||||
import org.teavm.platform.PlatformClass;
|
||||
import org.teavm.platform.PlatformRunnable;
|
||||
|
|
|
@ -43,7 +43,8 @@ public class PlatformPlugin implements TeaVMPlugin {
|
|||
host.add(new ResourceTransformer());
|
||||
host.add(new ResourceAccessorTransformer(host));
|
||||
host.add(new ResourceAccessorDependencyListener());
|
||||
host.getExtension(TeaVMJavaScriptHost.class).addGeneratorProvider(context -> {
|
||||
TeaVMJavaScriptHost jsHost = host.getExtension(TeaVMJavaScriptHost.class);
|
||||
jsHost.addGeneratorProvider(context -> {
|
||||
ClassReader cls = context.getClassSource().get(context.getMethod().getClassName());
|
||||
if (cls == null) {
|
||||
return null;
|
||||
|
@ -55,6 +56,7 @@ public class PlatformPlugin implements TeaVMPlugin {
|
|||
return method.getAnnotations().get(Async.class.getName()) != null
|
||||
? new AsyncMethodGenerator() : null;
|
||||
});
|
||||
jsHost.addVirtualMethods(new AsyncMethodGenerator());
|
||||
} else if (!isBootstrap()) {
|
||||
host.add(new StringAmplifierTransformer());
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user