mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2025-01-09 00:14:10 -08:00
Refactoring that introduces ability to generate new classes from
dependency interceptors.
This commit is contained in:
parent
00d160e92b
commit
ae60a7b4a0
|
@ -19,6 +19,7 @@ import org.teavm.classlib.impl.charset.ByteBuffer;
|
||||||
import org.teavm.classlib.impl.charset.CharBuffer;
|
import org.teavm.classlib.impl.charset.CharBuffer;
|
||||||
import org.teavm.classlib.impl.charset.Charset;
|
import org.teavm.classlib.impl.charset.Charset;
|
||||||
import org.teavm.classlib.java.lang.TMath;
|
import org.teavm.classlib.java.lang.TMath;
|
||||||
|
import org.teavm.classlib.java.lang.TObject;
|
||||||
import org.teavm.classlib.java.lang.TString;
|
import org.teavm.classlib.java.lang.TString;
|
||||||
import org.teavm.classlib.java.lang.TStringBuilder;
|
import org.teavm.classlib.java.lang.TStringBuilder;
|
||||||
|
|
||||||
|
@ -175,6 +176,11 @@ public class TPrintStream extends TFilterOutputStream {
|
||||||
printSB();
|
printSB();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void println(TObject s) {
|
||||||
|
sb.append(s).append('\n');
|
||||||
|
printSB();
|
||||||
|
}
|
||||||
|
|
||||||
public void println() {
|
public void println() {
|
||||||
print('\n');
|
print('\n');
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,14 +25,14 @@ import org.teavm.model.*;
|
||||||
*/
|
*/
|
||||||
public class DefaultNamingStrategy implements NamingStrategy {
|
public class DefaultNamingStrategy implements NamingStrategy {
|
||||||
private AliasProvider aliasProvider;
|
private AliasProvider aliasProvider;
|
||||||
private ClassHolderSource classSource;
|
private ClassReaderSource classSource;
|
||||||
private Map<String, String> aliases = new HashMap<>();
|
private Map<String, String> aliases = new HashMap<>();
|
||||||
private Map<String, String> privateAliases = new HashMap<>();
|
private Map<String, String> privateAliases = new HashMap<>();
|
||||||
private Map<String, String> classAliases = new HashMap<>();
|
private Map<String, String> classAliases = new HashMap<>();
|
||||||
private Map<String, String> fieldAliases = new HashMap<>();
|
private Map<String, String> fieldAliases = new HashMap<>();
|
||||||
private boolean minifying;
|
private boolean minifying;
|
||||||
|
|
||||||
public DefaultNamingStrategy(AliasProvider aliasProvider, ClassHolderSource classSource) {
|
public DefaultNamingStrategy(AliasProvider aliasProvider, ClassReaderSource classSource) {
|
||||||
this.aliasProvider = aliasProvider;
|
this.aliasProvider = aliasProvider;
|
||||||
this.classSource = classSource;
|
this.classSource = classSource;
|
||||||
}
|
}
|
||||||
|
@ -62,9 +62,9 @@ public class DefaultNamingStrategy implements NamingStrategy {
|
||||||
if (method == null) {
|
if (method == null) {
|
||||||
throw new NamingException("Can't provide name for method as it was not found: " + origMethod);
|
throw new NamingException("Can't provide name for method as it was not found: " + origMethod);
|
||||||
}
|
}
|
||||||
ClassHolder clsHolder = classSource.get(method.getClassName());
|
ClassReader clsHolder = classSource.get(method.getClassName());
|
||||||
MethodHolder methodHolder = clsHolder.getMethod(method.getDescriptor());
|
MethodReader methodHolder = clsHolder.getMethod(method.getDescriptor());
|
||||||
if (methodHolder.getModifiers().contains(ElementModifier.STATIC) ||
|
if (methodHolder.hasModifier(ElementModifier.STATIC) ||
|
||||||
method.getDescriptor().getName().equals("<init>") ||
|
method.getDescriptor().getName().equals("<init>") ||
|
||||||
methodHolder.getLevel() == AccessLevel.PRIVATE) {
|
methodHolder.getLevel() == AccessLevel.PRIVATE) {
|
||||||
String key = method.toString();
|
String key = method.toString();
|
||||||
|
@ -125,11 +125,11 @@ public class DefaultNamingStrategy implements NamingStrategy {
|
||||||
private MethodReference getRealMethod(MethodReference methodRef) {
|
private MethodReference getRealMethod(MethodReference methodRef) {
|
||||||
String className = methodRef.getClassName();
|
String className = methodRef.getClassName();
|
||||||
while (className != null) {
|
while (className != null) {
|
||||||
ClassHolder cls = classSource.get(className);
|
ClassReader cls = classSource.get(className);
|
||||||
if (cls == null) {
|
if (cls == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
MethodHolder method = cls.getMethod(methodRef.getDescriptor());
|
MethodReader method = cls.getMethod(methodRef.getDescriptor());
|
||||||
if (method != null) {
|
if (method != null) {
|
||||||
if (method.getLevel() == AccessLevel.PRIVATE && !className.equals(methodRef.getClassName())) {
|
if (method.getLevel() == AccessLevel.PRIVATE && !className.equals(methodRef.getClassName())) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -144,7 +144,7 @@ public class DefaultNamingStrategy implements NamingStrategy {
|
||||||
private String getRealFieldOwner(String cls, String field) {
|
private String getRealFieldOwner(String cls, String field) {
|
||||||
String initialCls = cls;
|
String initialCls = cls;
|
||||||
while (!fieldExists(cls, field)) {
|
while (!fieldExists(cls, field)) {
|
||||||
ClassHolder clsHolder = classSource.get(cls);
|
ClassReader clsHolder = classSource.get(cls);
|
||||||
cls = clsHolder.getParent();
|
cls = clsHolder.getParent();
|
||||||
if (cls == null) {
|
if (cls == null) {
|
||||||
throw new NamingException("Can't provide name for field as the field not found: " +
|
throw new NamingException("Can't provide name for field as the field not found: " +
|
||||||
|
@ -155,7 +155,7 @@ public class DefaultNamingStrategy implements NamingStrategy {
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean fieldExists(String cls, String field) {
|
private boolean fieldExists(String cls, String field) {
|
||||||
ClassHolder classHolder = classSource.get(cls);
|
ClassReader classHolder = classSource.get(cls);
|
||||||
return classHolder.getField(field) != null;
|
return classHolder.getField(field) != null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,21 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
package org.teavm.dependency;
|
||||||
|
|
||||||
import org.teavm.model.ClassHolder;
|
import org.teavm.model.ClassHolder;
|
||||||
import org.teavm.model.ClassReaderSource;
|
|
||||||
import org.teavm.model.FieldReference;
|
import org.teavm.model.FieldReference;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
|
|
||||||
|
@ -12,8 +26,6 @@ import org.teavm.model.MethodReference;
|
||||||
public interface DependencyAgent extends DependencyInfo {
|
public interface DependencyAgent extends DependencyInfo {
|
||||||
DependencyNode createNode();
|
DependencyNode createNode();
|
||||||
|
|
||||||
ClassReaderSource getClassSource();
|
|
||||||
|
|
||||||
String generateClassName();
|
String generateClassName();
|
||||||
|
|
||||||
void submitClass(ClassHolder cls);
|
void submitClass(ClassHolder cls);
|
||||||
|
|
|
@ -49,11 +49,11 @@ public class DependencyChecker implements DependencyInfo, DependencyAgent {
|
||||||
ConcurrentMap<String, DependencyStack> missingClasses = new ConcurrentHashMap<>();
|
ConcurrentMap<String, DependencyStack> missingClasses = new ConcurrentHashMap<>();
|
||||||
ConcurrentMap<FieldReference, DependencyStack> missingFields = new ConcurrentHashMap<>();
|
ConcurrentMap<FieldReference, DependencyStack> missingFields = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
public DependencyChecker(ClassHolderSource classSource, ClassLoader classLoader) {
|
public DependencyChecker(ClassReaderSource classSource, ClassLoader classLoader) {
|
||||||
this(classSource, classLoader, new SimpleFiniteExecutor());
|
this(classSource, classLoader, new SimpleFiniteExecutor());
|
||||||
}
|
}
|
||||||
|
|
||||||
public DependencyChecker(ClassHolderSource classSource, ClassLoader classLoader, FiniteExecutor executor) {
|
public DependencyChecker(ClassReaderSource classSource, ClassLoader classLoader, FiniteExecutor executor) {
|
||||||
this.classSource = new DependencyClassSource(classSource);
|
this.classSource = new DependencyClassSource(classSource);
|
||||||
this.classLoader = classLoader;
|
this.classLoader = classLoader;
|
||||||
this.executor = executor;
|
this.executor = executor;
|
||||||
|
@ -135,6 +135,10 @@ public class DependencyChecker implements DependencyInfo, DependencyAgent {
|
||||||
listener.started(this);
|
listener.started(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addClassTransformer(ClassHolderTransformer transformer) {
|
||||||
|
classSource.addTransformer(transformer);
|
||||||
|
}
|
||||||
|
|
||||||
public void addEntryPoint(MethodReference methodRef, String... argumentTypes) {
|
public void addEntryPoint(MethodReference methodRef, String... argumentTypes) {
|
||||||
ValueType[] parameters = methodRef.getDescriptor().getParameterTypes();
|
ValueType[] parameters = methodRef.getDescriptor().getParameterTypes();
|
||||||
if (parameters.length != argumentTypes.length) {
|
if (parameters.length != argumentTypes.length) {
|
||||||
|
@ -438,14 +442,4 @@ public class DependencyChecker implements DependencyInfo, DependencyAgent {
|
||||||
sb.append('\n');
|
sb.append('\n');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Collection<ClassHolder> getGeneratedClasses() {
|
|
||||||
Collection<ClassHolder> classes = classSource.getGeneratedClasses();
|
|
||||||
List<ClassHolder> copies = new ArrayList<>(classes.size());
|
|
||||||
for (ClassHolder cls : classes) {
|
|
||||||
copies.add(ModelUtils.copyClass(cls));
|
|
||||||
}
|
|
||||||
return classes;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,14 +15,18 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.dependency;
|
package org.teavm.dependency;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
import org.teavm.common.ConcurrentCachedMapper;
|
import org.teavm.common.ConcurrentCachedMapper;
|
||||||
import org.teavm.common.Mapper;
|
import org.teavm.common.Mapper;
|
||||||
import org.teavm.model.ClassHolder;
|
import org.teavm.model.ClassHolder;
|
||||||
|
import org.teavm.model.ClassHolderTransformer;
|
||||||
import org.teavm.model.ClassReader;
|
import org.teavm.model.ClassReader;
|
||||||
import org.teavm.model.ClassReaderSource;
|
import org.teavm.model.ClassReaderSource;
|
||||||
|
import org.teavm.model.util.ModelUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -31,10 +35,11 @@ import org.teavm.model.ClassReaderSource;
|
||||||
class DependencyClassSource implements ClassReaderSource {
|
class DependencyClassSource implements ClassReaderSource {
|
||||||
private ClassReaderSource innerSource;
|
private ClassReaderSource innerSource;
|
||||||
private ConcurrentMap<String, ClassHolder> generatedClasses = new ConcurrentHashMap<>();
|
private ConcurrentMap<String, ClassHolder> generatedClasses = new ConcurrentHashMap<>();
|
||||||
|
private List<ClassHolderTransformer> transformers = new ArrayList<>();
|
||||||
private ConcurrentCachedMapper<String, ClassReader> cache = new ConcurrentCachedMapper<>(
|
private ConcurrentCachedMapper<String, ClassReader> cache = new ConcurrentCachedMapper<>(
|
||||||
new Mapper<String, ClassReader>() {
|
new Mapper<String, ClassReader>() {
|
||||||
@Override public ClassReader map(String preimage) {
|
@Override public ClassReader map(String preimage) {
|
||||||
return findClass(preimage);
|
return findAndTransformClass(preimage);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -56,15 +61,30 @@ class DependencyClassSource implements ClassReaderSource {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private ClassReader findClass(String name) {
|
private ClassReader findAndTransformClass(String name) {
|
||||||
ClassReader cls = innerSource.get(name);
|
ClassHolder cls = findClass(name);
|
||||||
if (cls == null) {
|
if (cls != null && !transformers.isEmpty()) {
|
||||||
cls = generatedClasses.get(name);
|
for (ClassHolderTransformer transformer : transformers) {
|
||||||
|
transformer.transformClass(cls, innerSource);
|
||||||
|
}
|
||||||
|
cls = ModelUtils.copyClass(cls);
|
||||||
}
|
}
|
||||||
return cls;
|
return cls;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ClassHolder findClass(String name) {
|
||||||
|
ClassReader cls = innerSource.get(name);
|
||||||
|
if (cls != null) {
|
||||||
|
return ModelUtils.copyClass(cls);
|
||||||
|
}
|
||||||
|
return generatedClasses.get(name);
|
||||||
|
}
|
||||||
|
|
||||||
public Collection<ClassHolder> getGeneratedClasses() {
|
public Collection<ClassHolder> getGeneratedClasses() {
|
||||||
return generatedClasses.values();
|
return generatedClasses.values();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addTransformer(ClassHolderTransformer transformer) {
|
||||||
|
transformers.add(transformer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
package org.teavm.dependency;
|
package org.teavm.dependency;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import org.teavm.model.ClassHolder;
|
import org.teavm.model.ClassReaderSource;
|
||||||
import org.teavm.model.FieldReference;
|
import org.teavm.model.FieldReference;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
|
|
||||||
|
@ -25,6 +25,8 @@ import org.teavm.model.MethodReference;
|
||||||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||||
*/
|
*/
|
||||||
public interface DependencyInfo {
|
public interface DependencyInfo {
|
||||||
|
ClassReaderSource getClassSource();
|
||||||
|
|
||||||
boolean isMethodAchievable(MethodReference methodRef);
|
boolean isMethodAchievable(MethodReference methodRef);
|
||||||
|
|
||||||
Collection<MethodReference> getAchievableMethods();
|
Collection<MethodReference> getAchievableMethods();
|
||||||
|
@ -36,6 +38,4 @@ public interface DependencyInfo {
|
||||||
FieldDependencyInfo getField(FieldReference fieldRef);
|
FieldDependencyInfo getField(FieldReference fieldRef);
|
||||||
|
|
||||||
MethodDependencyInfo getMethod(MethodReference methodRef);
|
MethodDependencyInfo getMethod(MethodReference methodRef);
|
||||||
|
|
||||||
Collection<ClassHolder> getGeneratedClasses();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,33 +19,24 @@ import org.teavm.model.*;
|
||||||
import org.teavm.model.instructions.GetFieldInstruction;
|
import org.teavm.model.instructions.GetFieldInstruction;
|
||||||
import org.teavm.model.instructions.InvokeInstruction;
|
import org.teavm.model.instructions.InvokeInstruction;
|
||||||
import org.teavm.model.instructions.PutFieldInstruction;
|
import org.teavm.model.instructions.PutFieldInstruction;
|
||||||
|
import org.teavm.model.util.ModelUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Alexey Andreev
|
* @author Alexey Andreev
|
||||||
*/
|
*/
|
||||||
public class Linker {
|
public class Linker {
|
||||||
private DependencyInfo dependency;
|
public ListableClassHolderSource link(DependencyInfo dependency) {
|
||||||
|
|
||||||
public Linker(DependencyInfo dependency) {
|
|
||||||
this.dependency = dependency;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ListableClassHolderSource link(ClassHolderSource classes) {
|
|
||||||
MutableClassHolderSource cutClasses = new MutableClassHolderSource();
|
MutableClassHolderSource cutClasses = new MutableClassHolderSource();
|
||||||
for (String className : dependency.getAchievableClasses()) {
|
for (String className : dependency.getAchievableClasses()) {
|
||||||
ClassHolder classHolder = classes.get(className);
|
ClassHolder cls = ModelUtils.copyClass(dependency.getClassSource().get(className));
|
||||||
cutClasses.putClassHolder(classHolder);
|
cutClasses.putClassHolder(cls);
|
||||||
link(classHolder);
|
link(dependency, cls);
|
||||||
}
|
|
||||||
for (ClassHolder generatedClass : dependency.getGeneratedClasses()) {
|
|
||||||
cutClasses.putClassHolder(generatedClass);
|
|
||||||
link(generatedClass);
|
|
||||||
}
|
}
|
||||||
return cutClasses;
|
return cutClasses;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void link(ClassHolder cls) {
|
private void link(DependencyInfo dependency, ClassHolder cls) {
|
||||||
for (MethodHolder method : cls.getMethods().toArray(new MethodHolder[0])) {
|
for (MethodHolder method : cls.getMethods().toArray(new MethodHolder[0])) {
|
||||||
MethodReference methodRef = new MethodReference(cls.getName(), method.getDescriptor());
|
MethodReference methodRef = new MethodReference(cls.getName(), method.getDescriptor());
|
||||||
MethodDependencyInfo methodDep = dependency.getMethod(methodRef);
|
MethodDependencyInfo methodDep = dependency.getMethod(methodRef);
|
||||||
|
@ -55,7 +46,7 @@ public class Linker {
|
||||||
method.getModifiers().add(ElementModifier.ABSTRACT);
|
method.getModifiers().add(ElementModifier.ABSTRACT);
|
||||||
method.setProgram(null);
|
method.setProgram(null);
|
||||||
} else if (method.getProgram() != null) {
|
} else if (method.getProgram() != null) {
|
||||||
link(method);
|
link(dependency, method);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (FieldHolder field : cls.getFields().toArray(new FieldHolder[0])) {
|
for (FieldHolder field : cls.getFields().toArray(new FieldHolder[0])) {
|
||||||
|
@ -66,7 +57,7 @@ public class Linker {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void link(MethodHolder method) {
|
private void link(DependencyInfo dependency, MethodHolder method) {
|
||||||
Program program = method.getProgram();
|
Program program = method.getProgram();
|
||||||
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
||||||
BasicBlock block = program.basicBlockAt(i);
|
BasicBlock block = program.basicBlockAt(i);
|
||||||
|
|
|
@ -24,14 +24,14 @@ import org.teavm.resource.MapperClassHolderSource;
|
||||||
* @author Alexey Andreev
|
* @author Alexey Andreev
|
||||||
*/
|
*/
|
||||||
public class CopyClassHolderSource implements ClassHolderSource {
|
public class CopyClassHolderSource implements ClassHolderSource {
|
||||||
private ClassHolderSource innerSource;
|
private ClassReaderSource innerSource;
|
||||||
private MapperClassHolderSource mapperSource = new MapperClassHolderSource(new Mapper<String, ClassHolder>() {
|
private MapperClassHolderSource mapperSource = new MapperClassHolderSource(new Mapper<String, ClassHolder>() {
|
||||||
@Override public ClassHolder map(String preimage) {
|
@Override public ClassHolder map(String preimage) {
|
||||||
return copyClass(preimage);
|
return copyClass(preimage);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
public CopyClassHolderSource(ClassHolderSource innerSource) {
|
public CopyClassHolderSource(ClassReaderSource innerSource) {
|
||||||
this.innerSource = innerSource;
|
this.innerSource = innerSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ public class CopyClassHolderSource implements ClassHolderSource {
|
||||||
}
|
}
|
||||||
|
|
||||||
private ClassHolder copyClass(String className) {
|
private ClassHolder copyClass(String className) {
|
||||||
ClassHolder original = innerSource.get(className);
|
ClassReader original = innerSource.get(className);
|
||||||
if (original == null) {
|
if (original == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,7 +97,7 @@ class InstructionReadVisitor implements InstructionVisitor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(CastIntegerInstruction insn) {
|
public void visit(CastIntegerInstruction insn) {
|
||||||
reader.cast(insn.getReceiver(), insn.getReceiver(), insn.getTargetType(), insn.getDirection());
|
reader.cast(insn.getReceiver(), insn.getValue(), insn.getTargetType(), insn.getDirection());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,8 +1,22 @@
|
||||||
|
/*
|
||||||
|
* 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.util;
|
package org.teavm.model.util;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import org.teavm.model.*;
|
import org.teavm.model.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -13,16 +27,16 @@ public final class ModelUtils {
|
||||||
private ModelUtils() {
|
private ModelUtils() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ClassHolder copyClass(ClassHolder original) {
|
public static ClassHolder copyClass(ClassReader original) {
|
||||||
ClassHolder copy = new ClassHolder(original.getName());
|
ClassHolder copy = new ClassHolder(original.getName());
|
||||||
copy.setLevel(original.getLevel());
|
copy.setLevel(original.getLevel());
|
||||||
copy.getModifiers().addAll(original.getModifiers());
|
copy.getModifiers().addAll(original.readModifiers());
|
||||||
copy.setParent(original.getParent());
|
copy.setParent(original.getParent());
|
||||||
copy.getInterfaces().addAll(original.getInterfaces());
|
copy.getInterfaces().addAll(original.getInterfaces());
|
||||||
for (MethodHolder method : original.getMethods()) {
|
for (MethodReader method : original.getMethods()) {
|
||||||
copy.addMethod(copyMethod(method));
|
copy.addMethod(copyMethod(method));
|
||||||
}
|
}
|
||||||
for (FieldHolder field : original.getFields()) {
|
for (FieldReader field : original.getFields()) {
|
||||||
copy.addField(copyField(field));
|
copy.addField(copyField(field));
|
||||||
}
|
}
|
||||||
copy.setOwnerName(original.getOwnerName());
|
copy.setOwnerName(original.getOwnerName());
|
||||||
|
@ -30,35 +44,37 @@ public final class ModelUtils {
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MethodHolder copyMethod(MethodHolder method) {
|
public static MethodHolder copyMethod(MethodReader method) {
|
||||||
MethodHolder copy = new MethodHolder(method.getDescriptor());
|
MethodHolder copy = new MethodHolder(method.getDescriptor());
|
||||||
copy.setLevel(method.getLevel());
|
copy.setLevel(method.getLevel());
|
||||||
copy.getModifiers().addAll(method.getModifiers());
|
copy.getModifiers().addAll(method.readModifiers());
|
||||||
copy.setProgram(ProgramUtils.copy(method.getProgram()));
|
if (method.getProgram() != null) {
|
||||||
|
copy.setProgram(ProgramUtils.copy(method.getProgram()));
|
||||||
|
}
|
||||||
copyAnnotations(method.getAnnotations(), copy.getAnnotations());
|
copyAnnotations(method.getAnnotations(), copy.getAnnotations());
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static FieldHolder copyField(FieldHolder field) {
|
public static FieldHolder copyField(FieldReader field) {
|
||||||
FieldHolder copy = new FieldHolder(field.getName());
|
FieldHolder copy = new FieldHolder(field.getName());
|
||||||
copy.setLevel(field.getLevel());
|
copy.setLevel(field.getLevel());
|
||||||
copy.getModifiers().addAll(field.getModifiers());
|
copy.getModifiers().addAll(field.readModifiers());
|
||||||
copy.setType(field.getType());
|
copy.setType(field.getType());
|
||||||
copy.setInitialValue(field.getInitialValue());
|
copy.setInitialValue(field.getInitialValue());
|
||||||
copyAnnotations(field.getAnnotations(), copy.getAnnotations());
|
copyAnnotations(field.getAnnotations(), copy.getAnnotations());
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void copyAnnotations(AnnotationContainer src, AnnotationContainer dst) {
|
private static void copyAnnotations(AnnotationContainerReader src, AnnotationContainer dst) {
|
||||||
for (AnnotationHolder annot : src.all()) {
|
for (AnnotationReader annot : src.all()) {
|
||||||
dst.add(copyAnnotation(annot));
|
dst.add(copyAnnotation(annot));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static AnnotationHolder copyAnnotation(AnnotationHolder annot) {
|
private static AnnotationHolder copyAnnotation(AnnotationReader annot) {
|
||||||
AnnotationHolder copy = new AnnotationHolder(annot.getType());
|
AnnotationHolder copy = new AnnotationHolder(annot.getType());
|
||||||
for (Map.Entry<String, AnnotationValue> entry : annot.getValues().entrySet()) {
|
for (String fieldName : annot.getAvailableFields()) {
|
||||||
copy.getValues().put(entry.getKey(), copyAnnotationValue(entry.getValue()));
|
copy.getValues().put(fieldName, copyAnnotationValue(annot.getValue(fieldName)));
|
||||||
}
|
}
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
|
@ -417,6 +417,5 @@ public final class ProgramUtils {
|
||||||
insnCopy.setValue(copyVar(value));
|
insnCopy.setValue(copyVar(value));
|
||||||
copy = insnCopy;
|
copy = insnCopy;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,67 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.vm;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
import org.teavm.common.ConcurrentCachedMapper;
|
|
||||||
import org.teavm.common.Mapper;
|
|
||||||
import org.teavm.model.ClassHolder;
|
|
||||||
import org.teavm.model.ClassHolderSource;
|
|
||||||
import org.teavm.model.ClassHolderTransformer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author Alexey Andreev
|
|
||||||
*/
|
|
||||||
class JavascriptProcessedClassSource implements ClassHolderSource {
|
|
||||||
private ClassHolderSource innerSource;
|
|
||||||
private List<ClassHolderTransformer> transformers = new ArrayList<>();
|
|
||||||
private ConcurrentCachedMapper<String, ClassHolder> mapper = new ConcurrentCachedMapper<>(
|
|
||||||
new Mapper<String, ClassHolder>() {
|
|
||||||
@Override public ClassHolder map(String preimage) {
|
|
||||||
return getTransformed(preimage);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
public JavascriptProcessedClassSource(ClassHolderSource innerSource) {
|
|
||||||
this.innerSource = innerSource;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addTransformer(ClassHolderTransformer transformer) {
|
|
||||||
transformers.add(transformer);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ClassHolder get(String name) {
|
|
||||||
return mapper.map(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
private ClassHolder getTransformed(String name) {
|
|
||||||
ClassHolder cls = innerSource.get(name);
|
|
||||||
if (cls != null) {
|
|
||||||
transformClass(cls);
|
|
||||||
}
|
|
||||||
return cls;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void transformClass(ClassHolder cls) {
|
|
||||||
for (ClassHolderTransformer transformer : transformers) {
|
|
||||||
transformer.transformClass(cls, innerSource);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -63,7 +63,7 @@ import org.teavm.vm.spi.TeaVMPlugin;
|
||||||
* @author Alexey Andreev
|
* @author Alexey Andreev
|
||||||
*/
|
*/
|
||||||
public class TeaVM implements TeaVMHost {
|
public class TeaVM implements TeaVMHost {
|
||||||
private JavascriptProcessedClassSource classSource;
|
private ClassReaderSource classSource;
|
||||||
private DependencyChecker dependencyChecker;
|
private DependencyChecker dependencyChecker;
|
||||||
private FiniteExecutor executor;
|
private FiniteExecutor executor;
|
||||||
private ClassLoader classLoader;
|
private ClassLoader classLoader;
|
||||||
|
@ -76,8 +76,8 @@ public class TeaVM implements TeaVMHost {
|
||||||
private List<RendererListener> rendererListeners = new ArrayList<>();
|
private List<RendererListener> rendererListeners = new ArrayList<>();
|
||||||
private Properties properties = new Properties();
|
private Properties properties = new Properties();
|
||||||
|
|
||||||
TeaVM(ClassHolderSource classSource, ClassLoader classLoader, FiniteExecutor executor) {
|
TeaVM(ClassReaderSource classSource, ClassLoader classLoader, FiniteExecutor executor) {
|
||||||
this.classSource = new JavascriptProcessedClassSource(classSource);
|
this.classSource = classSource;
|
||||||
this.classLoader = classLoader;
|
this.classLoader = classLoader;
|
||||||
dependencyChecker = new DependencyChecker(this.classSource, classLoader, executor);
|
dependencyChecker = new DependencyChecker(this.classSource, classLoader, executor);
|
||||||
this.executor = executor;
|
this.executor = executor;
|
||||||
|
@ -90,7 +90,7 @@ public class TeaVM implements TeaVMHost {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void add(ClassHolderTransformer transformer) {
|
public void add(ClassHolderTransformer transformer) {
|
||||||
classSource.addTransformer(transformer);
|
dependencyChecker.addClassTransformer(transformer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -137,6 +137,9 @@ public class TeaVM implements TeaVMHost {
|
||||||
/**
|
/**
|
||||||
* Specifies configuration properties for TeaVM and its plugins. You should call this method before
|
* Specifies configuration properties for TeaVM and its plugins. You should call this method before
|
||||||
* installing any plugins or interceptors.
|
* installing any plugins or interceptors.
|
||||||
|
*
|
||||||
|
* @param properties configuration properties to set. These properties will be copied into this VM instance,
|
||||||
|
* so VM won't see any further changes in this object.
|
||||||
*/
|
*/
|
||||||
public void setProperties(Properties properties) {
|
public void setProperties(Properties properties) {
|
||||||
this.properties.clear();
|
this.properties.clear();
|
||||||
|
@ -196,10 +199,10 @@ public class TeaVM implements TeaVMHost {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a {@link ClassHolderSource} which is used by this TeaVM instance. It is exactly what was
|
* Gets a {@link ClassReaderSource} which is used by this TeaVM instance. It is exactly what was
|
||||||
* passed to {@link TeaVMBuilder#setClassSource(ClassHolderSource)}.
|
* passed to {@link TeaVMBuilder#setClassSource(ClassHolderSource)}.
|
||||||
*/
|
*/
|
||||||
public ClassHolderSource getClassSource() {
|
public ClassReaderSource getClassSource() {
|
||||||
return classSource;
|
return classSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -216,6 +219,8 @@ public class TeaVM implements TeaVMHost {
|
||||||
* <p>After building allows to build report on all items (classes, methods, fields) that are missing.
|
* <p>After building allows to build report on all items (classes, methods, fields) that are missing.
|
||||||
* This can happen when you forgot some items in class path or when your code uses unimplemented
|
* This can happen when you forgot some items in class path or when your code uses unimplemented
|
||||||
* Java class library methods. The behavior of this method before building is not specified.</p>
|
* Java class library methods. The behavior of this method before building is not specified.</p>
|
||||||
|
*
|
||||||
|
* @param target where to append all dependency diagnostics errors.
|
||||||
*/
|
*/
|
||||||
public void showMissingItems(Appendable target) throws IOException {
|
public void showMissingItems(Appendable target) throws IOException {
|
||||||
dependencyChecker.showMissingItems(target);
|
dependencyChecker.showMissingItems(target);
|
||||||
|
@ -243,12 +248,8 @@ public class TeaVM implements TeaVMHost {
|
||||||
* plugins or inteceptors that generate additional resources, the build process will fail.
|
* plugins or inteceptors that generate additional resources, the build process will fail.
|
||||||
*/
|
*/
|
||||||
public void build(Appendable writer, BuildTarget target) throws RenderingException {
|
public void build(Appendable writer, BuildTarget target) throws RenderingException {
|
||||||
|
// Check dependencies
|
||||||
AliasProvider aliasProvider = minifying ? new MinifyingAliasProvider() : new DefaultAliasProvider();
|
AliasProvider aliasProvider = minifying ? new MinifyingAliasProvider() : new DefaultAliasProvider();
|
||||||
DefaultNamingStrategy naming = new DefaultNamingStrategy(aliasProvider, classSource);
|
|
||||||
naming.setMinifying(minifying);
|
|
||||||
SourceWriterBuilder builder = new SourceWriterBuilder(naming);
|
|
||||||
builder.setMinified(minifying);
|
|
||||||
SourceWriter sourceWriter = builder.build(writer);
|
|
||||||
dependencyChecker.linkMethod(new MethodReference("java.lang.Class", "createNew",
|
dependencyChecker.linkMethod(new MethodReference("java.lang.Class", "createNew",
|
||||||
ValueType.object("java.lang.Class")), DependencyStack.ROOT).use();
|
ValueType.object("java.lang.Class")), DependencyStack.ROOT).use();
|
||||||
dependencyChecker.linkMethod(new MethodReference("java.lang.String", "<init>",
|
dependencyChecker.linkMethod(new MethodReference("java.lang.String", "<init>",
|
||||||
|
@ -268,9 +269,12 @@ public class TeaVM implements TeaVMHost {
|
||||||
if (hasMissingItems()) {
|
if (hasMissingItems()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Linker linker = new Linker(dependencyChecker);
|
|
||||||
ListableClassHolderSource classSet = linker.link(classSource);
|
// Link
|
||||||
Decompiler decompiler = new Decompiler(classSet, classLoader, executor);
|
Linker linker = new Linker();
|
||||||
|
ListableClassHolderSource classSet = linker.link(dependencyChecker);
|
||||||
|
|
||||||
|
// Optimize and allocate registers
|
||||||
devirtualize(classSet, dependencyChecker);
|
devirtualize(classSet, dependencyChecker);
|
||||||
executor.complete();
|
executor.complete();
|
||||||
ClassSetOptimizer optimizer = new ClassSetOptimizer(executor);
|
ClassSetOptimizer optimizer = new ClassSetOptimizer(executor);
|
||||||
|
@ -285,10 +289,20 @@ public class TeaVM implements TeaVMHost {
|
||||||
// Just don't do anything
|
// Just don't do anything
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Decompile
|
||||||
|
Decompiler decompiler = new Decompiler(classSet, classLoader, executor);
|
||||||
for (Map.Entry<MethodReference, Generator> entry : methodGenerators.entrySet()) {
|
for (Map.Entry<MethodReference, Generator> entry : methodGenerators.entrySet()) {
|
||||||
decompiler.addGenerator(entry.getKey(), entry.getValue());
|
decompiler.addGenerator(entry.getKey(), entry.getValue());
|
||||||
}
|
}
|
||||||
List<ClassNode> clsNodes = decompiler.decompile(classSet.getClassNames());
|
List<ClassNode> clsNodes = decompiler.decompile(classSet.getClassNames());
|
||||||
|
|
||||||
|
// Render
|
||||||
|
DefaultNamingStrategy naming = new DefaultNamingStrategy(aliasProvider, dependencyChecker.getClassSource());
|
||||||
|
naming.setMinifying(minifying);
|
||||||
|
SourceWriterBuilder builder = new SourceWriterBuilder(naming);
|
||||||
|
builder.setMinified(minifying);
|
||||||
|
SourceWriter sourceWriter = builder.build(writer);
|
||||||
Renderer renderer = new Renderer(sourceWriter, classSet, classLoader);
|
Renderer renderer = new Renderer(sourceWriter, classSet, classLoader);
|
||||||
try {
|
try {
|
||||||
for (RendererListener listener : rendererListeners) {
|
for (RendererListener listener : rendererListeners) {
|
||||||
|
@ -321,7 +335,6 @@ public class TeaVM implements TeaVMHost {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: repair devirtualization
|
|
||||||
private void devirtualize(ListableClassHolderSource classes, DependencyInfo dependency) {
|
private void devirtualize(ListableClassHolderSource classes, DependencyInfo dependency) {
|
||||||
final Devirtualization devirtualization = new Devirtualization(dependency, classes);
|
final Devirtualization devirtualization = new Devirtualization(dependency, classes);
|
||||||
for (String className : classes.getClassNames()) {
|
for (String className : classes.getClassNames()) {
|
||||||
|
|
|
@ -26,6 +26,7 @@ import org.teavm.vm.TeaVMBuilder;
|
||||||
/**
|
/**
|
||||||
* <p>A host of plugins for TeaVM. Plugins are provided with this interface
|
* <p>A host of plugins for TeaVM. Plugins are provided with this interface
|
||||||
* in order to give them ability to extend TeaVM.</p>
|
* in order to give them ability to extend TeaVM.</p>
|
||||||
|
*
|
||||||
* @author Alexey Andreev
|
* @author Alexey Andreev
|
||||||
*/
|
*/
|
||||||
public interface TeaVMHost {
|
public interface TeaVMHost {
|
||||||
|
@ -45,7 +46,10 @@ public interface TeaVMHost {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets configuration properties. These properties are usually specified by
|
* Gets configuration properties. These properties are usually specified by
|
||||||
* {@link TeaVM#setProperties(Properties)}
|
* {@link TeaVM#setProperties(Properties)}.
|
||||||
|
*
|
||||||
|
* @return a copy of all of the VM properties. Any further changes to returned objects will not be
|
||||||
|
* visible to VM.
|
||||||
*/
|
*/
|
||||||
Properties getProperties();
|
Properties getProperties();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user