mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-31 12:24:10 -08:00
Fixes for html4j/ko4j
1. Replace Class.forName(cls.getName) with class initializer 2. Reduce set of compiled annotations to classes that actually get called getAnnotations()
This commit is contained in:
parent
f347de44a9
commit
653caa00b3
|
@ -0,0 +1,126 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2017 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 java.util.Arrays;
|
||||||
|
import org.teavm.common.DisjointSet;
|
||||||
|
import org.teavm.diagnostics.Diagnostics;
|
||||||
|
import org.teavm.model.BasicBlock;
|
||||||
|
import org.teavm.model.ClassHolder;
|
||||||
|
import org.teavm.model.ClassHolderTransformer;
|
||||||
|
import org.teavm.model.ClassReaderSource;
|
||||||
|
import org.teavm.model.Instruction;
|
||||||
|
import org.teavm.model.MethodHolder;
|
||||||
|
import org.teavm.model.MethodReference;
|
||||||
|
import org.teavm.model.Program;
|
||||||
|
import org.teavm.model.Variable;
|
||||||
|
import org.teavm.model.instructions.AssignInstruction;
|
||||||
|
import org.teavm.model.instructions.InvocationType;
|
||||||
|
import org.teavm.model.instructions.InvokeInstruction;
|
||||||
|
|
||||||
|
public class ClassForNameTransformer implements ClassHolderTransformer {
|
||||||
|
private static final MethodReference getNameMethod = new MethodReference(Class.class, "getName", String.class);
|
||||||
|
private static final MethodReference forNameMethod = new MethodReference(Class.class, "forName", String.class,
|
||||||
|
boolean.class, ClassLoader.class, Class.class);
|
||||||
|
private static final MethodReference initMethod = new MethodReference(Class.class, "initialize", void.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void transformClass(ClassHolder cls, ClassReaderSource innerSource, Diagnostics diagnostics) {
|
||||||
|
for (MethodHolder method : cls.getMethods()) {
|
||||||
|
Program program = method.getProgram();
|
||||||
|
if (program != null) {
|
||||||
|
transformProgram(program);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void transformProgram(Program program) {
|
||||||
|
DisjointSet varSet = new DisjointSet();
|
||||||
|
for (int i = 0; i < program.variableCount(); i++) {
|
||||||
|
varSet.create();
|
||||||
|
}
|
||||||
|
int[] nameIndexes = new int[program.variableCount()];
|
||||||
|
Arrays.fill(nameIndexes, -1);
|
||||||
|
|
||||||
|
for (BasicBlock block : program.getBasicBlocks()) {
|
||||||
|
for (Instruction instruction : block) {
|
||||||
|
if (instruction instanceof InvokeInstruction) {
|
||||||
|
InvokeInstruction invoke = (InvokeInstruction) instruction;
|
||||||
|
if (invoke.getMethod().equals(getNameMethod)) {
|
||||||
|
if (invoke.getReceiver() != null) {
|
||||||
|
nameIndexes[invoke.getReceiver().getIndex()] = invoke.getInstance().getIndex();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (instruction instanceof AssignInstruction) {
|
||||||
|
AssignInstruction assign = (AssignInstruction) instruction;
|
||||||
|
varSet.union(assign.getAssignee().getIndex(), assign.getReceiver().getIndex());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nameIndexes = Arrays.copyOf(nameIndexes, varSet.size());
|
||||||
|
int[] nameRepresentatives = new int[nameIndexes.length];
|
||||||
|
Arrays.fill(nameRepresentatives, -1);
|
||||||
|
|
||||||
|
for (int i = 0; i < program.variableCount(); i++) {
|
||||||
|
int varClass = varSet.find(i);
|
||||||
|
if (nameRepresentatives[varClass] < 0) {
|
||||||
|
nameRepresentatives[varClass] = i;
|
||||||
|
}
|
||||||
|
if (nameIndexes[i] >= 0) {
|
||||||
|
nameIndexes[varClass] = varSet.find(nameIndexes[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (BasicBlock block : program.getBasicBlocks()) {
|
||||||
|
for (Instruction instruction : block) {
|
||||||
|
if (!(instruction instanceof InvokeInstruction)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
InvokeInstruction invoke = (InvokeInstruction) instruction;
|
||||||
|
|
||||||
|
if (!invoke.getMethod().equals(forNameMethod)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int classNameIndex = invoke.getArguments().get(0).getIndex();
|
||||||
|
int nameIndex = nameIndexes[classNameIndex];
|
||||||
|
if (nameIndex < 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Variable representative = program.variableAt(nameRepresentatives[nameIndex]);
|
||||||
|
|
||||||
|
InvokeInstruction initInvoke = new InvokeInstruction();
|
||||||
|
initInvoke.setLocation(invoke.getLocation());
|
||||||
|
initInvoke.setType(InvocationType.SPECIAL);
|
||||||
|
initInvoke.setMethod(initMethod);
|
||||||
|
initInvoke.setInstance(representative);
|
||||||
|
invoke.insertPrevious(initInvoke);
|
||||||
|
|
||||||
|
if (invoke.getReceiver() == null) {
|
||||||
|
invoke.delete();
|
||||||
|
} else {
|
||||||
|
AssignInstruction assign = new AssignInstruction();
|
||||||
|
assign.setLocation(invoke.getLocation());
|
||||||
|
assign.setAssignee(representative);
|
||||||
|
assign.setReceiver(invoke.getReceiver());
|
||||||
|
invoke.replace(assign);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -21,10 +21,10 @@ import java.lang.invoke.MethodHandle;
|
||||||
import java.lang.invoke.MethodHandles;
|
import java.lang.invoke.MethodHandles;
|
||||||
import java.lang.invoke.MethodType;
|
import java.lang.invoke.MethodType;
|
||||||
import java.util.ServiceLoader;
|
import java.util.ServiceLoader;
|
||||||
|
import org.teavm.backend.javascript.TeaVMJavaScriptHost;
|
||||||
import org.teavm.classlib.impl.lambda.LambdaMetafactorySubstitutor;
|
import org.teavm.classlib.impl.lambda.LambdaMetafactorySubstitutor;
|
||||||
import org.teavm.classlib.impl.unicode.CLDRReader;
|
import org.teavm.classlib.impl.unicode.CLDRReader;
|
||||||
import org.teavm.classlib.java.lang.reflect.AnnotationDependencyListener;
|
import org.teavm.classlib.java.lang.reflect.AnnotationDependencyListener;
|
||||||
import org.teavm.backend.javascript.TeaVMJavaScriptHost;
|
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
import org.teavm.platform.PlatformClass;
|
import org.teavm.platform.PlatformClass;
|
||||||
import org.teavm.vm.spi.TeaVMHost;
|
import org.teavm.vm.spi.TeaVMHost;
|
||||||
|
@ -47,6 +47,7 @@ public class JCLPlugin implements TeaVMPlugin {
|
||||||
|
|
||||||
host.registerService(CLDRReader.class, new CLDRReader(host.getProperties(), host.getClassLoader()));
|
host.registerService(CLDRReader.class, new CLDRReader(host.getProperties(), host.getClassLoader()));
|
||||||
|
|
||||||
|
host.add(new ClassForNameTransformer());
|
||||||
host.add(new AnnotationDependencyListener());
|
host.add(new AnnotationDependencyListener());
|
||||||
host.add(new MethodReference(LambdaMetafactory.class, "metafactory", MethodHandles.Lookup.class,
|
host.add(new MethodReference(LambdaMetafactory.class, "metafactory", MethodHandles.Lookup.class,
|
||||||
String.class, MethodType.class, MethodType.class, MethodHandle.class, MethodType.class,
|
String.class, MethodType.class, MethodType.class, MethodHandle.class, MethodType.class,
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2017 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.java.lang;
|
||||||
|
|
||||||
|
import org.teavm.dependency.DependencyAgent;
|
||||||
|
import org.teavm.dependency.DependencyPlugin;
|
||||||
|
import org.teavm.dependency.MethodDependency;
|
||||||
|
import org.teavm.model.CallLocation;
|
||||||
|
|
||||||
|
public class ClassDependencyListener implements DependencyPlugin {
|
||||||
|
@Override
|
||||||
|
public void methodReached(DependencyAgent agent, MethodDependency method, CallLocation location) {
|
||||||
|
switch (method.getMethod().getName()) {
|
||||||
|
case "initialize":
|
||||||
|
method.getVariable(0).getClassValueNode().addConsumer(type -> agent
|
||||||
|
.linkClass(type.getName(), location)
|
||||||
|
.initClass(location));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -21,6 +21,7 @@ import java.util.Map;
|
||||||
import org.teavm.classlib.impl.DeclaringClassMetadataGenerator;
|
import org.teavm.classlib.impl.DeclaringClassMetadataGenerator;
|
||||||
import org.teavm.classlib.java.lang.annotation.TAnnotation;
|
import org.teavm.classlib.java.lang.annotation.TAnnotation;
|
||||||
import org.teavm.classlib.java.lang.reflect.TAnnotatedElement;
|
import org.teavm.classlib.java.lang.reflect.TAnnotatedElement;
|
||||||
|
import org.teavm.dependency.PluggableDependency;
|
||||||
import org.teavm.interop.Address;
|
import org.teavm.interop.Address;
|
||||||
import org.teavm.interop.DelegateTo;
|
import org.teavm.interop.DelegateTo;
|
||||||
import org.teavm.platform.Platform;
|
import org.teavm.platform.Platform;
|
||||||
|
@ -159,6 +160,11 @@ public class TClass<T> extends TObject implements TAnnotatedElement {
|
||||||
return forName(name);
|
return forName(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PluggableDependency(ClassDependencyListener.class)
|
||||||
|
void initialize() {
|
||||||
|
Platform.initClass(platformClass);
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressWarnings({ "unchecked", "unused" })
|
@SuppressWarnings({ "unchecked", "unused" })
|
||||||
public T newInstance() throws TInstantiationException, TIllegalAccessException {
|
public T newInstance() throws TInstantiationException, TIllegalAccessException {
|
||||||
Object instance = Platform.newInstance(platformClass);
|
Object instance = Platform.newInstance(platformClass);
|
||||||
|
|
|
@ -21,6 +21,7 @@ import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import org.teavm.dependency.AbstractDependencyListener;
|
import org.teavm.dependency.AbstractDependencyListener;
|
||||||
import org.teavm.dependency.DependencyAgent;
|
import org.teavm.dependency.DependencyAgent;
|
||||||
|
import org.teavm.dependency.DependencyNode;
|
||||||
import org.teavm.dependency.MethodDependency;
|
import org.teavm.dependency.MethodDependency;
|
||||||
import org.teavm.model.AccessLevel;
|
import org.teavm.model.AccessLevel;
|
||||||
import org.teavm.model.AnnotationReader;
|
import org.teavm.model.AnnotationReader;
|
||||||
|
@ -33,26 +34,13 @@ import org.teavm.model.ElementModifier;
|
||||||
import org.teavm.model.FieldHolder;
|
import org.teavm.model.FieldHolder;
|
||||||
import org.teavm.model.MethodHolder;
|
import org.teavm.model.MethodHolder;
|
||||||
import org.teavm.model.MethodReader;
|
import org.teavm.model.MethodReader;
|
||||||
|
import org.teavm.model.MethodReference;
|
||||||
import org.teavm.model.ValueType;
|
import org.teavm.model.ValueType;
|
||||||
import org.teavm.model.emit.ProgramEmitter;
|
import org.teavm.model.emit.ProgramEmitter;
|
||||||
import org.teavm.model.emit.ValueEmitter;
|
import org.teavm.model.emit.ValueEmitter;
|
||||||
import org.teavm.platform.PlatformAnnotationProvider;
|
import org.teavm.platform.PlatformAnnotationProvider;
|
||||||
|
|
||||||
public class AnnotationDependencyListener extends AbstractDependencyListener {
|
public class AnnotationDependencyListener extends AbstractDependencyListener {
|
||||||
@Override
|
|
||||||
public void classReached(DependencyAgent agent, String className, CallLocation location) {
|
|
||||||
ClassReader cls = agent.getClassSource().get(className);
|
|
||||||
if (cls == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (AnnotationReader annotation : cls.getAnnotations().all()) {
|
|
||||||
agent.linkClass(annotation.getType(), location);
|
|
||||||
}
|
|
||||||
|
|
||||||
createAnnotationClass(agent, className);
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getAnnotationImplementor(DependencyAgent agent, String annotationType) {
|
private String getAnnotationImplementor(DependencyAgent agent, String annotationType) {
|
||||||
String implementorName = annotationType + "$$_impl";
|
String implementorName = annotationType + "$$_impl";
|
||||||
if (agent.getClassSource().get(implementorName) == null) {
|
if (agent.getClassSource().get(implementorName) == null) {
|
||||||
|
@ -145,6 +133,28 @@ public class AnnotationDependencyListener extends AbstractDependencyListener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MethodReference methodRef = method.getMethod().getReference();
|
||||||
|
if (methodRef.getClassName().equals("java.lang.Class") && methodRef.getName().equals("getAnnotations")) {
|
||||||
|
reachGetAnnotations(agent, location, method.getVariable(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void reachGetAnnotations(DependencyAgent agent, CallLocation location, DependencyNode node) {
|
||||||
|
node.getClassValueNode().addConsumer(type -> {
|
||||||
|
String className = type.getName();
|
||||||
|
|
||||||
|
ClassReader cls = agent.getClassSource().get(className);
|
||||||
|
if (cls == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (AnnotationReader annotation : cls.getAnnotations().all()) {
|
||||||
|
agent.linkClass(annotation.getType(), location);
|
||||||
|
}
|
||||||
|
|
||||||
|
createAnnotationClass(agent, className);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createAnnotationClass(DependencyAgent agent, String className) {
|
private void createAnnotationClass(DependencyAgent agent, String className) {
|
||||||
|
|
|
@ -108,8 +108,8 @@ public final class Platform {
|
||||||
@PluggableDependency(PlatformGenerator.class)
|
@PluggableDependency(PlatformGenerator.class)
|
||||||
public static native PlatformClass lookupClass(String name);
|
public static native PlatformClass lookupClass(String name);
|
||||||
|
|
||||||
@GeneratedBy(PlatformGenerator.class)
|
|
||||||
@PluggableDependency(PlatformGenerator.class)
|
@PluggableDependency(PlatformGenerator.class)
|
||||||
|
@InjectedBy(PlatformGenerator.class)
|
||||||
public static native void initClass(PlatformClass cls);
|
public static native void initClass(PlatformClass cls);
|
||||||
|
|
||||||
@InjectedBy(PlatformGenerator.class)
|
@InjectedBy(PlatformGenerator.class)
|
||||||
|
|
|
@ -35,10 +35,6 @@ import org.teavm.platform.Platform;
|
||||||
import org.teavm.platform.PlatformClass;
|
import org.teavm.platform.PlatformClass;
|
||||||
import org.teavm.platform.PlatformRunnable;
|
import org.teavm.platform.PlatformRunnable;
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author Alexey Andreev
|
|
||||||
*/
|
|
||||||
public class PlatformGenerator implements Generator, Injector, DependencyPlugin {
|
public class PlatformGenerator implements Generator, Injector, DependencyPlugin {
|
||||||
@Override
|
@Override
|
||||||
public void methodReached(DependencyAgent agent, MethodDependency method, CallLocation location) {
|
public void methodReached(DependencyAgent agent, MethodDependency method, CallLocation location) {
|
||||||
|
@ -73,6 +69,10 @@ public class PlatformGenerator implements Generator, Injector, DependencyPlugin
|
||||||
case "getPlatformObject":
|
case "getPlatformObject":
|
||||||
context.writeExpr(context.getArgument(0));
|
context.writeExpr(context.getArgument(0));
|
||||||
break;
|
break;
|
||||||
|
case "initClass":
|
||||||
|
context.writeExpr(context.getArgument(0));
|
||||||
|
context.getWriter().append(".$clinit()");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user