mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
Decrease memory consumption
This commit is contained in:
parent
97a1db1b79
commit
f589b0035a
|
@ -70,7 +70,7 @@ public class JCLPlugin implements TeaVMPlugin {
|
|||
ValueType.arrayOf(ValueType.object("java.lang.Object")),
|
||||
ValueType.object("java.lang.invoke.CallSite")), lms);
|
||||
|
||||
StringConcatFactorySubstritutor stringConcatSubstitutor = new StringConcatFactorySubstritutor();
|
||||
StringConcatFactorySubstitutor stringConcatSubstitutor = new StringConcatFactorySubstitutor();
|
||||
host.add(new MethodReference("java.lang.invoke.StringConcatFactory", "makeConcat",
|
||||
ValueType.object("java.lang.invoke.MethodHandles$Lookup"), ValueType.object("java.lang.String"),
|
||||
ValueType.object("java.lang.invoke.MethodType"), ValueType.object("java.lang.invoke.CallSite")),
|
||||
|
|
|
@ -18,12 +18,14 @@ package org.teavm.classlib.impl;
|
|||
import org.teavm.dependency.BootstrapMethodSubstitutor;
|
||||
import org.teavm.dependency.DynamicCallSite;
|
||||
import org.teavm.model.MethodReference;
|
||||
import org.teavm.model.ReferenceCache;
|
||||
import org.teavm.model.RuntimeConstant;
|
||||
import org.teavm.model.ValueType;
|
||||
import org.teavm.model.emit.ProgramEmitter;
|
||||
import org.teavm.model.emit.ValueEmitter;
|
||||
|
||||
public class StringConcatFactorySubstritutor implements BootstrapMethodSubstitutor {
|
||||
public class StringConcatFactorySubstitutor implements BootstrapMethodSubstitutor {
|
||||
private ReferenceCache referenceCache = new ReferenceCache();
|
||||
private static final String STRING_BUILDER = "java.lang.StringBuilder";
|
||||
private static final char VALUE_ARGUMENT = '\1';
|
||||
private static final char CONST_ARGUMENT = '\2';
|
||||
|
@ -100,7 +102,8 @@ public class StringConcatFactorySubstritutor implements BootstrapMethodSubstitut
|
|||
if (!(type instanceof ValueType.Primitive)) {
|
||||
type = ValueType.object("java.lang.Object");
|
||||
}
|
||||
MethodReference method = new MethodReference(STRING_BUILDER, "append", type, ValueType.object(STRING_BUILDER));
|
||||
MethodReference method = referenceCache.getCached(new MethodReference(STRING_BUILDER, "append", type,
|
||||
ValueType.object(STRING_BUILDER)));
|
||||
return sb.invokeSpecial(method, argument);
|
||||
}
|
||||
|
|
@ -162,7 +162,7 @@ public class ProgramIO {
|
|||
for (int i = 0; i < varCount; ++i) {
|
||||
Variable var = program.createVariable();
|
||||
var.setRegister(data.readShort());
|
||||
var.setDebugName(data.readUTF());
|
||||
var.setDebugName(referenceCache.getCached(data.readUTF()));
|
||||
if (var.getDebugName().isEmpty()) {
|
||||
var.setDebugName(null);
|
||||
}
|
||||
|
|
|
@ -35,4 +35,8 @@ public abstract class AbstractDependencyListener implements DependencyListener {
|
|||
@Override
|
||||
public void completing(DependencyAgent agent) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void complete() {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -135,4 +135,8 @@ public class DependencyAgent implements DependencyInfo, ServiceRepository {
|
|||
public IncrementalDependencyRegistration getIncrementalCache() {
|
||||
return analyzer.incrementalCache;
|
||||
}
|
||||
|
||||
void cleanup() {
|
||||
analyzer = null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -700,6 +700,10 @@ public abstract class DependencyAnalyzer implements DependencyInfo {
|
|||
}
|
||||
}
|
||||
|
||||
for (DependencyListener listener : listeners) {
|
||||
listener.complete();
|
||||
}
|
||||
|
||||
if (dependencyReport) {
|
||||
reportDependencies();
|
||||
}
|
||||
|
@ -745,6 +749,8 @@ public abstract class DependencyAnalyzer implements DependencyInfo {
|
|||
}
|
||||
|
||||
allNodes.clear();
|
||||
classSource.cleanup();
|
||||
agent.cleanup();
|
||||
}
|
||||
|
||||
static class ReportEntry {
|
||||
|
@ -903,7 +909,7 @@ public abstract class DependencyAnalyzer implements DependencyInfo {
|
|||
splitter.fixProgram();
|
||||
}
|
||||
|
||||
class IncrementalCache implements IncrementalDependencyProvider, IncrementalDependencyRegistration {
|
||||
static class IncrementalCache implements IncrementalDependencyProvider, IncrementalDependencyRegistration {
|
||||
private final String[] emptyArray = new String[0];
|
||||
private Map<String, IncrementalItem> classes = new HashMap<>();
|
||||
private Map<MethodReference, IncrementalItem> methods = new HashMap<>();
|
||||
|
|
|
@ -105,6 +105,10 @@ class DependencyClassSource implements ClassHolderSource {
|
|||
transformers.add(transformer);
|
||||
}
|
||||
|
||||
public void cleanup() {
|
||||
transformers.clear();
|
||||
}
|
||||
|
||||
final ClassHolderTransformerContext transformContext = new ClassHolderTransformerContext() {
|
||||
@Override
|
||||
public ClassHierarchy getHierarchy() {
|
||||
|
|
|
@ -25,4 +25,6 @@ public interface DependencyListener {
|
|||
void fieldReached(DependencyAgent agent, FieldDependency field);
|
||||
|
||||
void completing(DependencyAgent agent);
|
||||
|
||||
void complete();
|
||||
}
|
||||
|
|
|
@ -15,13 +15,17 @@
|
|||
*/
|
||||
package org.teavm.model;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class AnnotationContainer implements AnnotationContainerReader {
|
||||
private Map<String, AnnotationHolder> annotations = new LinkedHashMap<>();
|
||||
private Map<String, AnnotationHolder> annotations;
|
||||
|
||||
public void add(AnnotationHolder annotation) {
|
||||
if (annotations == null) {
|
||||
annotations = new LinkedHashMap<>();
|
||||
}
|
||||
if (annotations.containsKey(annotation.getType())) {
|
||||
throw new IllegalArgumentException("Annotation of type " + annotation.getType() + " is already there");
|
||||
}
|
||||
|
@ -30,7 +34,7 @@ public class AnnotationContainer implements AnnotationContainerReader {
|
|||
|
||||
@Override
|
||||
public AnnotationHolder get(String type) {
|
||||
return annotations.get(type);
|
||||
return annotations != null ? annotations.get(type) : null;
|
||||
}
|
||||
|
||||
public void remove(AnnotationHolder annotation) {
|
||||
|
@ -42,11 +46,13 @@ public class AnnotationContainer implements AnnotationContainerReader {
|
|||
}
|
||||
|
||||
public void remove(String type) {
|
||||
if (annotations != null) {
|
||||
annotations.remove(type);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<AnnotationHolder> all() {
|
||||
return annotations.values();
|
||||
return annotations != null ? annotations.values() : Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,6 @@ package org.teavm.model;
|
|||
|
||||
import java.util.AbstractList;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
|
@ -28,8 +27,8 @@ import org.teavm.model.util.TransitionExtractor;
|
|||
public class BasicBlock implements BasicBlockReader, Iterable<Instruction> {
|
||||
private Program program;
|
||||
private int index;
|
||||
private List<Phi> phis = new ArrayList<>();
|
||||
private List<TryCatchBlock> tryCatchBlocks = new ArrayList<>();
|
||||
private List<Phi> phis;
|
||||
private List<TryCatchBlock> tryCatchBlocks;
|
||||
private Variable exceptionVariable;
|
||||
private String label;
|
||||
Instruction firstInstruction;
|
||||
|
@ -172,12 +171,15 @@ public class BasicBlock implements BasicBlockReader, Iterable<Instruction> {
|
|||
private List<Phi> safePhis = new AbstractList<Phi>() {
|
||||
@Override
|
||||
public Phi get(int index) {
|
||||
if (phis == null) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
return phis.get(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return phis.size();
|
||||
return phis != null ? phis.size() : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -186,6 +188,9 @@ public class BasicBlock implements BasicBlockReader, Iterable<Instruction> {
|
|||
throw new IllegalArgumentException("This phi is already in some basic block");
|
||||
}
|
||||
e.setBasicBlock(BasicBlock.this);
|
||||
if (phis == null) {
|
||||
phis = new ArrayList<>(1);
|
||||
}
|
||||
phis.add(index, e);
|
||||
}
|
||||
|
||||
|
@ -194,6 +199,9 @@ public class BasicBlock implements BasicBlockReader, Iterable<Instruction> {
|
|||
if (element.getBasicBlock() != null) {
|
||||
throw new IllegalArgumentException("This phi is already in some basic block");
|
||||
}
|
||||
if (phis == null) {
|
||||
phis = new ArrayList<>(1);
|
||||
}
|
||||
Phi oldPhi = phis.get(index);
|
||||
oldPhi.setBasicBlock(null);
|
||||
element.setBasicBlock(BasicBlock.this);
|
||||
|
@ -202,6 +210,9 @@ public class BasicBlock implements BasicBlockReader, Iterable<Instruction> {
|
|||
|
||||
@Override
|
||||
public Phi remove(int index) {
|
||||
if (phis == null) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
Phi phi = phis.remove(index);
|
||||
phi.setBasicBlock(null);
|
||||
return phi;
|
||||
|
@ -209,10 +220,13 @@ public class BasicBlock implements BasicBlockReader, Iterable<Instruction> {
|
|||
|
||||
@Override
|
||||
public void clear() {
|
||||
if (phis == null) {
|
||||
return;
|
||||
}
|
||||
for (Phi phi : phis) {
|
||||
phi.setBasicBlock(null);
|
||||
}
|
||||
phis.clear();
|
||||
phis = null;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -220,7 +234,20 @@ public class BasicBlock implements BasicBlockReader, Iterable<Instruction> {
|
|||
return safePhis;
|
||||
}
|
||||
|
||||
private List<Phi> immutablePhis = Collections.unmodifiableList(phis);
|
||||
private List<Phi> immutablePhis = new AbstractList<Phi>() {
|
||||
@Override
|
||||
public Phi get(int index) {
|
||||
if (phis == null) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
return phis.get(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return phis != null ? phis.size() : 0;
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public List<? extends PhiReader> readPhis() {
|
||||
|
@ -299,7 +326,20 @@ public class BasicBlock implements BasicBlockReader, Iterable<Instruction> {
|
|||
}
|
||||
}
|
||||
|
||||
private List<TryCatchBlock> immutableTryCatchBlocks = Collections.unmodifiableList(tryCatchBlocks);
|
||||
private List<TryCatchBlock> immutableTryCatchBlocks = new AbstractList<TryCatchBlock>() {
|
||||
@Override
|
||||
public TryCatchBlock get(int index) {
|
||||
if (tryCatchBlocks == null) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
return tryCatchBlocks.get(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return tryCatchBlocks != null ? tryCatchBlocks.size() : 0;
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public List<TryCatchBlock> readTryCatchBlocks() {
|
||||
|
@ -307,25 +347,43 @@ public class BasicBlock implements BasicBlockReader, Iterable<Instruction> {
|
|||
}
|
||||
|
||||
private List<TryCatchBlock> safeTryCatchBlocks = new AbstractList<TryCatchBlock>() {
|
||||
@Override public TryCatchBlock get(int index) {
|
||||
@Override
|
||||
public TryCatchBlock get(int index) {
|
||||
if (tryCatchBlocks == null) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
return tryCatchBlocks.get(index);
|
||||
}
|
||||
@Override public int size() {
|
||||
return tryCatchBlocks.size();
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return tryCatchBlocks != null ? tryCatchBlocks.size() : 0;
|
||||
}
|
||||
@Override public void add(int index, TryCatchBlock element) {
|
||||
|
||||
@Override
|
||||
public void add(int index, TryCatchBlock element) {
|
||||
if (element.protectedBlock == BasicBlock.this) {
|
||||
throw new IllegalStateException("This try/catch block is already added to basic block");
|
||||
}
|
||||
element.protectedBlock = BasicBlock.this;
|
||||
if (tryCatchBlocks == null) {
|
||||
tryCatchBlocks = new ArrayList<>(1);
|
||||
}
|
||||
tryCatchBlocks.add(index, element);
|
||||
}
|
||||
@Override public TryCatchBlock remove(int index) {
|
||||
|
||||
@Override
|
||||
public TryCatchBlock remove(int index) {
|
||||
if (tryCatchBlocks == null) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
TryCatchBlock tryCatch = tryCatchBlocks.remove(index);
|
||||
tryCatch.protectedBlock = null;
|
||||
return tryCatch;
|
||||
}
|
||||
@Override public TryCatchBlock set(int index, TryCatchBlock element) {
|
||||
|
||||
@Override
|
||||
public TryCatchBlock set(int index, TryCatchBlock element) {
|
||||
TryCatchBlock oldTryCatch = tryCatchBlocks.get(index);
|
||||
if (oldTryCatch == element) {
|
||||
return oldTryCatch;
|
||||
|
@ -335,14 +393,22 @@ public class BasicBlock implements BasicBlockReader, Iterable<Instruction> {
|
|||
}
|
||||
oldTryCatch.protectedBlock = null;
|
||||
element.protectedBlock = BasicBlock.this;
|
||||
if (tryCatchBlocks == null) {
|
||||
tryCatchBlocks = new ArrayList<>(1);
|
||||
}
|
||||
tryCatchBlocks.set(index, element);
|
||||
return oldTryCatch;
|
||||
}
|
||||
@Override public void clear() {
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
if (tryCatchBlocks == null) {
|
||||
return;
|
||||
}
|
||||
for (TryCatchBlock tryCatch : tryCatchBlocks) {
|
||||
tryCatch.protectedBlock = null;
|
||||
}
|
||||
tryCatchBlocks.clear();
|
||||
tryCatchBlocks = null;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ public class FieldHolder extends MemberHolder implements FieldReader {
|
|||
private ValueType type;
|
||||
private Object initialValue;
|
||||
private ClassHolder owner;
|
||||
private FieldReference reference;
|
||||
|
||||
public FieldHolder(String name) {
|
||||
super(name);
|
||||
|
@ -48,6 +49,7 @@ public class FieldHolder extends MemberHolder implements FieldReader {
|
|||
|
||||
void setOwner(ClassHolder owner) {
|
||||
this.owner = owner;
|
||||
reference = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -57,6 +59,16 @@ public class FieldHolder extends MemberHolder implements FieldReader {
|
|||
|
||||
@Override
|
||||
public FieldReference getReference() {
|
||||
return new FieldReference(getOwnerName(), getName());
|
||||
if (reference == null && owner != null) {
|
||||
reference = new FieldReference(getOwnerName(), getName());
|
||||
}
|
||||
return reference;
|
||||
}
|
||||
|
||||
public void updateReference(ReferenceCache cache) {
|
||||
FieldReference reference = getReference();
|
||||
if (reference != null) {
|
||||
this.reference = cache.getCached(reference);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -101,6 +101,13 @@ public class MethodHolder extends MemberHolder implements MethodReader {
|
|||
return reference;
|
||||
}
|
||||
|
||||
public void updateReference(ReferenceCache cache) {
|
||||
MethodReference reference = getReference();
|
||||
if (reference != null) {
|
||||
this.reference = cache.getCached(reference);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Program getProgram() {
|
||||
return program;
|
||||
|
|
|
@ -23,7 +23,7 @@ import java.util.List;
|
|||
public class Phi implements PhiReader {
|
||||
private BasicBlock basicBlock;
|
||||
private Variable receiver;
|
||||
private List<Incoming> incomings = new ArrayList<>();
|
||||
private List<Incoming> incomings = new ArrayList<>(2);
|
||||
|
||||
@Override
|
||||
public BasicBlock getBasicBlock() {
|
||||
|
|
|
@ -19,7 +19,7 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
|
||||
public class Program implements ProgramReader {
|
||||
private List<BasicBlock> basicBlocks = new ArrayList<>();
|
||||
private List<BasicBlock> basicBlocks = new ArrayList<>(2);
|
||||
private List<Variable> variables = new ArrayList<>();
|
||||
private MethodHolder method;
|
||||
private boolean packed;
|
||||
|
|
|
@ -23,7 +23,7 @@ public class ReferenceCache {
|
|||
private Map<FieldReference, FieldReference> fieldRefenceCache = new HashMap<>();
|
||||
private Map<MethodDescriptor, MethodDescriptor> descriptorCache = new HashMap<>();
|
||||
private Map<ValueType, ValueType> valueTypeCache = new HashMap<>();
|
||||
private Map<String, String> classCache = new HashMap<>();
|
||||
private Map<String, String> stringCache = new HashMap<>();
|
||||
private Map<String, MethodReference> referenceParseCache = new HashMap<>();
|
||||
private Map<String, MethodDescriptor> descriptorParseCache = new HashMap<>();
|
||||
private Map<String, ValueType> valueTypeParseCache = new HashMap<>();
|
||||
|
@ -103,11 +103,11 @@ public class ReferenceCache {
|
|||
return result;
|
||||
}
|
||||
|
||||
public String getCached(String className) {
|
||||
String result = classCache.get(className);
|
||||
public String getCached(String s) {
|
||||
String result = stringCache.get(s);
|
||||
if (result == null) {
|
||||
result = className;
|
||||
classCache.put(result, result);
|
||||
result = s;
|
||||
stringCache.put(result, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ public class InvokeInstruction extends Instruction {
|
|||
private InvocationType type;
|
||||
private MethodReference method;
|
||||
private Variable instance;
|
||||
private List<Variable> arguments = new ArrayList<>();
|
||||
private List<Variable> arguments = new ArrayList<>(1);
|
||||
private Variable receiver;
|
||||
|
||||
public InvocationType getType() {
|
||||
|
|
|
@ -35,51 +35,28 @@ import org.teavm.model.MethodHandle;
|
|||
import org.teavm.model.MethodHolder;
|
||||
import org.teavm.model.MethodReference;
|
||||
import org.teavm.model.Program;
|
||||
import org.teavm.model.ReferenceCache;
|
||||
import org.teavm.model.RuntimeConstant;
|
||||
import org.teavm.model.TryCatchBlock;
|
||||
import org.teavm.model.ValueType;
|
||||
import org.teavm.model.instructions.ArrayLengthInstruction;
|
||||
import org.teavm.model.instructions.AssignInstruction;
|
||||
import org.teavm.model.instructions.BinaryBranchingInstruction;
|
||||
import org.teavm.model.instructions.BinaryInstruction;
|
||||
import org.teavm.model.instructions.BranchingInstruction;
|
||||
import org.teavm.model.instructions.AbstractInstructionVisitor;
|
||||
import org.teavm.model.instructions.CastInstruction;
|
||||
import org.teavm.model.instructions.CastIntegerInstruction;
|
||||
import org.teavm.model.instructions.CastNumberInstruction;
|
||||
import org.teavm.model.instructions.ClassConstantInstruction;
|
||||
import org.teavm.model.instructions.CloneArrayInstruction;
|
||||
import org.teavm.model.instructions.ConstructArrayInstruction;
|
||||
import org.teavm.model.instructions.ConstructInstruction;
|
||||
import org.teavm.model.instructions.ConstructMultiArrayInstruction;
|
||||
import org.teavm.model.instructions.DoubleConstantInstruction;
|
||||
import org.teavm.model.instructions.EmptyInstruction;
|
||||
import org.teavm.model.instructions.ExitInstruction;
|
||||
import org.teavm.model.instructions.FloatConstantInstruction;
|
||||
import org.teavm.model.instructions.GetElementInstruction;
|
||||
import org.teavm.model.instructions.GetFieldInstruction;
|
||||
import org.teavm.model.instructions.InitClassInstruction;
|
||||
import org.teavm.model.instructions.InstructionVisitor;
|
||||
import org.teavm.model.instructions.IntegerConstantInstruction;
|
||||
import org.teavm.model.instructions.InvokeInstruction;
|
||||
import org.teavm.model.instructions.IsInstanceInstruction;
|
||||
import org.teavm.model.instructions.JumpInstruction;
|
||||
import org.teavm.model.instructions.LongConstantInstruction;
|
||||
import org.teavm.model.instructions.MonitorEnterInstruction;
|
||||
import org.teavm.model.instructions.MonitorExitInstruction;
|
||||
import org.teavm.model.instructions.NegateInstruction;
|
||||
import org.teavm.model.instructions.NullCheckInstruction;
|
||||
import org.teavm.model.instructions.NullConstantInstruction;
|
||||
import org.teavm.model.instructions.PutElementInstruction;
|
||||
import org.teavm.model.instructions.PutFieldInstruction;
|
||||
import org.teavm.model.instructions.RaiseInstruction;
|
||||
import org.teavm.model.instructions.StringConstantInstruction;
|
||||
import org.teavm.model.instructions.SwitchInstruction;
|
||||
import org.teavm.model.instructions.UnwrapArrayInstruction;
|
||||
|
||||
public class ClassRefsRenamer implements InstructionVisitor {
|
||||
public class ClassRefsRenamer extends AbstractInstructionVisitor {
|
||||
private ReferenceCache referenceCache;
|
||||
private Mapper<String, String> classNameMapper;
|
||||
|
||||
public ClassRefsRenamer(Mapper<String, String> classNameMapper) {
|
||||
public ClassRefsRenamer(ReferenceCache referenceCache, Mapper<String, String> classNameMapper) {
|
||||
this.referenceCache = referenceCache;
|
||||
this.classNameMapper = classNameMapper;
|
||||
}
|
||||
|
||||
|
@ -153,10 +130,10 @@ public class ClassRefsRenamer implements InstructionVisitor {
|
|||
private ValueType rename(ValueType type) {
|
||||
if (type instanceof ValueType.Array) {
|
||||
ValueType itemType = ((ValueType.Array) type).getItemType();
|
||||
return ValueType.arrayOf(rename(itemType));
|
||||
return referenceCache.getCached(ValueType.arrayOf(rename(itemType)));
|
||||
} else if (type instanceof ValueType.Object) {
|
||||
String className = ((ValueType.Object) type).getClassName();
|
||||
return ValueType.object(classNameMapper.map(className));
|
||||
return referenceCache.getCached(ValueType.object(classNameMapper.map(className)));
|
||||
} else {
|
||||
return type;
|
||||
}
|
||||
|
@ -245,88 +222,16 @@ public class ClassRefsRenamer implements InstructionVisitor {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(EmptyInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ClassConstantInstruction insn) {
|
||||
insn.setConstant(rename(insn.getConstant()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(NullConstantInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(IntegerConstantInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(LongConstantInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(FloatConstantInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(DoubleConstantInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(StringConstantInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(BinaryInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(NegateInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(AssignInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(CastInstruction insn) {
|
||||
insn.setTargetType(rename(insn.getTargetType()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(CastNumberInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(CastIntegerInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(BranchingInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(BinaryBranchingInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(JumpInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(SwitchInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ExitInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(RaiseInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ConstructArrayInstruction insn) {
|
||||
insn.setItemType(rename(insn.getItemType()));
|
||||
|
@ -345,43 +250,33 @@ public class ClassRefsRenamer implements InstructionVisitor {
|
|||
@Override
|
||||
public void visit(GetFieldInstruction insn) {
|
||||
String className = classNameMapper.map(insn.getField().getClassName());
|
||||
insn.setField(new FieldReference(className, insn.getField().getFieldName()));
|
||||
insn.setField(referenceCache.getCached(new FieldReference(className, insn.getField().getFieldName())));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(PutFieldInstruction insn) {
|
||||
String className = classNameMapper.map(insn.getField().getClassName());
|
||||
insn.setField(new FieldReference(className, insn.getField().getFieldName()));
|
||||
if (className != insn.getField().getClassName()) {
|
||||
insn.setField(referenceCache.getCached(new FieldReference(className, insn.getField().getFieldName())));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ArrayLengthInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(CloneArrayInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(GetElementInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(PutElementInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(UnwrapArrayInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(InvokeInstruction insn) {
|
||||
String className = classNameMapper.map(insn.getMethod().getClassName());
|
||||
ValueType[] signature = insn.getMethod().getSignature();
|
||||
boolean changed = true;
|
||||
for (int i = 0; i < signature.length; ++i) {
|
||||
signature[i] = rename(signature[i]);
|
||||
ValueType type = signature[i];
|
||||
ValueType newType = rename(type);
|
||||
if (newType != null) {
|
||||
changed = true;
|
||||
}
|
||||
signature[i] = newType;
|
||||
}
|
||||
if (changed) {
|
||||
insn.setMethod(referenceCache.getCached(new MethodReference(className,
|
||||
new MethodDescriptor(insn.getMethod().getName(), signature))));
|
||||
}
|
||||
insn.setMethod(new MethodReference(className, new MethodDescriptor(insn.getMethod().getName(), signature)));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -405,16 +300,4 @@ public class ClassRefsRenamer implements InstructionVisitor {
|
|||
public void visit(InitClassInstruction insn) {
|
||||
insn.setClassName(classNameMapper.map(insn.getClassName()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(NullCheckInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(MonitorEnterInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(MonitorExitInstruction insn) {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ package org.teavm.parsing;
|
|||
import java.util.Date;
|
||||
import org.teavm.model.ClassHolder;
|
||||
import org.teavm.model.ClassHolderSource;
|
||||
import org.teavm.model.ReferenceCache;
|
||||
import org.teavm.parsing.resource.ClasspathResourceReader;
|
||||
import org.teavm.parsing.resource.MapperClassHolderSource;
|
||||
import org.teavm.parsing.resource.ResourceClassHolderMapper;
|
||||
|
@ -27,9 +28,10 @@ public class ClasspathClassHolderSource implements ClassHolderSource, ClassDateP
|
|||
private ClasspathResourceMapper classPathMapper;
|
||||
|
||||
public ClasspathClassHolderSource(ClassLoader classLoader) {
|
||||
ReferenceCache referenceCache = new ReferenceCache();
|
||||
ClasspathResourceReader reader = new ClasspathResourceReader(classLoader);
|
||||
ResourceClassHolderMapper rawMapper = new ResourceClassHolderMapper(reader);
|
||||
classPathMapper = new ClasspathResourceMapper(classLoader, rawMapper);
|
||||
ResourceClassHolderMapper rawMapper = new ResourceClassHolderMapper(reader, referenceCache);
|
||||
classPathMapper = new ClasspathResourceMapper(classLoader, referenceCache, rawMapper);
|
||||
innerClassSource = new MapperClassHolderSource(classPathMapper);
|
||||
}
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ import java.util.*;
|
|||
import org.teavm.common.CachedMapper;
|
||||
import org.teavm.common.Mapper;
|
||||
import org.teavm.model.ClassHolder;
|
||||
import org.teavm.model.ReferenceCache;
|
||||
|
||||
public class ClasspathResourceMapper implements Mapper<String, ClassHolder>, ClassDateProvider {
|
||||
private static final String PACKAGE_PREFIX = "packagePrefix.";
|
||||
|
@ -33,6 +34,7 @@ public class ClasspathResourceMapper implements Mapper<String, ClassHolder>, Cla
|
|||
private ClassRefsRenamer renamer;
|
||||
private ClassLoader classLoader;
|
||||
private Map<String, ModificationDate> modificationDates = new HashMap<>();
|
||||
private ReferenceCache referenceCache;
|
||||
|
||||
private static class Transformation {
|
||||
String packageName;
|
||||
|
@ -41,8 +43,10 @@ public class ClasspathResourceMapper implements Mapper<String, ClassHolder>, Cla
|
|||
String classPrefix = "";
|
||||
}
|
||||
|
||||
public ClasspathResourceMapper(ClassLoader classLoader, Mapper<String, ClassHolder> innerMapper) {
|
||||
public ClasspathResourceMapper(ClassLoader classLoader, ReferenceCache referenceCache,
|
||||
Mapper<String, ClassHolder> innerMapper) {
|
||||
this.innerMapper = innerMapper;
|
||||
this.referenceCache = referenceCache;
|
||||
try {
|
||||
Enumeration<URL> resources = classLoader.getResources("META-INF/teavm.properties");
|
||||
Map<String, Transformation> transformationMap = new HashMap<>();
|
||||
|
@ -58,16 +62,18 @@ public class ClasspathResourceMapper implements Mapper<String, ClassHolder>, Cla
|
|||
} catch (IOException e) {
|
||||
throw new RuntimeException("Error reading resources", e);
|
||||
}
|
||||
renamer = new ClassRefsRenamer(new CachedMapper<>(classNameMapper));
|
||||
renamer = new ClassRefsRenamer(referenceCache, new CachedMapper<>(classNameMapper));
|
||||
this.classLoader = classLoader;
|
||||
}
|
||||
|
||||
public ClasspathResourceMapper(Properties properties, Mapper<String, ClassHolder> innerMapper) {
|
||||
public ClasspathResourceMapper(Properties properties, ReferenceCache referenceCache,
|
||||
Mapper<String, ClassHolder> innerMapper) {
|
||||
this.innerMapper = innerMapper;
|
||||
this.referenceCache = referenceCache;
|
||||
Map<String, Transformation> transformationMap = new HashMap<>();
|
||||
loadProperties(properties, transformationMap);
|
||||
transformations.addAll(transformationMap.values());
|
||||
renamer = new ClassRefsRenamer(new CachedMapper<>(classNameMapper));
|
||||
renamer = new ClassRefsRenamer(referenceCache, new CachedMapper<>(classNameMapper));
|
||||
}
|
||||
|
||||
private void loadProperties(Properties properties, Map<String, Transformation> cache) {
|
||||
|
@ -121,8 +127,9 @@ public class ClasspathResourceMapper implements Mapper<String, ClassHolder>, Cla
|
|||
String className = name.substring(index + 1);
|
||||
String packageName = name.substring(0, index);
|
||||
if (className.startsWith(transformation.classPrefix)) {
|
||||
return packageName.substring(transformation.packagePrefix.length()) + "."
|
||||
String newName = packageName.substring(transformation.packagePrefix.length()) + "."
|
||||
+ className.substring(transformation.classPrefix.length());
|
||||
return referenceCache.getCached(newName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ import java.io.File;
|
|||
import java.util.Properties;
|
||||
import org.teavm.model.ClassHolder;
|
||||
import org.teavm.model.ClassHolderSource;
|
||||
import org.teavm.model.ReferenceCache;
|
||||
import org.teavm.parsing.resource.DirectoryResourceReader;
|
||||
import org.teavm.parsing.resource.MapperClassHolderSource;
|
||||
import org.teavm.parsing.resource.ResourceClassHolderMapper;
|
||||
|
@ -29,9 +30,10 @@ public class DirectoryClasspathClassHolderSource implements ClassHolderSource {
|
|||
private ClasspathResourceMapper classPathMapper;
|
||||
|
||||
public DirectoryClasspathClassHolderSource(File baseDir, Properties properties) {
|
||||
ReferenceCache referenceCache = new ReferenceCache();
|
||||
DirectoryResourceReader reader = new DirectoryResourceReader(baseDir);
|
||||
ResourceClassHolderMapper rawMapper = new ResourceClassHolderMapper(reader);
|
||||
classPathMapper = new ClasspathResourceMapper(properties, rawMapper);
|
||||
ResourceClassHolderMapper rawMapper = new ResourceClassHolderMapper(reader, referenceCache);
|
||||
classPathMapper = new ClasspathResourceMapper(properties, referenceCache, rawMapper);
|
||||
innerClassSource = new MapperClassHolderSource(classPathMapper);
|
||||
}
|
||||
|
||||
|
|
|
@ -74,7 +74,7 @@ public class Parser {
|
|||
node.accept(adapter);
|
||||
node = nodeWithoutJsr;
|
||||
ValueType[] signature = MethodDescriptor.parseSignature(node.desc);
|
||||
MethodHolder method = new MethodHolder(node.name, signature);
|
||||
MethodHolder method = new MethodHolder(referenceCache.getCached(new MethodDescriptor(node.name, signature)));
|
||||
parseModifiers(node.access, method, DECL_METHOD);
|
||||
|
||||
ProgramParser programParser = new ProgramParser(referenceCache);
|
||||
|
@ -229,26 +229,31 @@ public class Parser {
|
|||
}
|
||||
|
||||
public ClassHolder parseClass(ClassNode node) {
|
||||
ClassHolder cls = new ClassHolder(node.name.replace('/', '.'));
|
||||
ClassHolder cls = new ClassHolder(referenceCache.getCached(node.name.replace('/', '.')));
|
||||
parseModifiers(node.access, cls, DECL_CLASS);
|
||||
if (node.superName != null) {
|
||||
cls.setParent(node.superName.replace('/', '.'));
|
||||
cls.setParent(referenceCache.getCached(node.superName.replace('/', '.')));
|
||||
}
|
||||
if (cls.getName().equals("java.lang.Object")) {
|
||||
cls.setParent(null);
|
||||
}
|
||||
if (node.interfaces != null) {
|
||||
for (String iface : node.interfaces) {
|
||||
cls.getInterfaces().add(iface.replace('/', '.'));
|
||||
cls.getInterfaces().add(referenceCache.getCached(iface.replace('/', '.')));
|
||||
}
|
||||
}
|
||||
for (Object obj : node.fields) {
|
||||
FieldNode fieldNode = (FieldNode) obj;
|
||||
cls.addField(parseField(fieldNode));
|
||||
FieldHolder field = parseField(fieldNode);
|
||||
cls.addField(field);
|
||||
field.updateReference(referenceCache);
|
||||
}
|
||||
String fullFileName = node.name.substring(0, node.name.lastIndexOf('/') + 1) + node.sourceFile;
|
||||
String fullFileName = referenceCache.getCached(node.name.substring(0, node.name.lastIndexOf('/') + 1)
|
||||
+ node.sourceFile);
|
||||
for (MethodNode methodNode : node.methods) {
|
||||
cls.addMethod(parseMethod(methodNode, fullFileName));
|
||||
MethodHolder method = parseMethod(methodNode, fullFileName);
|
||||
cls.addMethod(method);
|
||||
method.updateReference(referenceCache);
|
||||
}
|
||||
if (node.outerClass != null) {
|
||||
cls.setOwnerName(node.outerClass.replace('/', '.'));
|
||||
|
@ -263,8 +268,8 @@ public class Parser {
|
|||
}
|
||||
|
||||
public FieldHolder parseField(FieldNode node) {
|
||||
FieldHolder field = new FieldHolder(node.name);
|
||||
field.setType(ValueType.parse(node.desc));
|
||||
FieldHolder field = new FieldHolder(referenceCache.getCached(node.name));
|
||||
field.setType(referenceCache.getCached(ValueType.parse(node.desc)));
|
||||
field.setInitialValue(node.value);
|
||||
parseModifiers(node.access, field, DECL_FIELD);
|
||||
parseAnnotations(field.getAnnotations(), node.visibleAnnotations, node.invisibleAnnotations);
|
||||
|
@ -358,7 +363,7 @@ public class Parser {
|
|||
continue;
|
||||
}
|
||||
|
||||
AnnotationHolder annot = new AnnotationHolder(desc);
|
||||
AnnotationHolder annot = new AnnotationHolder(referenceCache.getCached(desc));
|
||||
parseAnnotationValues(annot, annotNode.values);
|
||||
annotations.add(annot);
|
||||
}
|
||||
|
@ -379,10 +384,11 @@ public class Parser {
|
|||
if (value instanceof String[]) {
|
||||
String[] enumInfo = (String[]) value;
|
||||
ValueType.Object object = (ValueType.Object) ValueType.parse(enumInfo[0]);
|
||||
return new AnnotationValue(new FieldReference(object.getClassName(), enumInfo[1]));
|
||||
return new AnnotationValue(referenceCache.getCached(new FieldReference(object.getClassName(),
|
||||
enumInfo[1])));
|
||||
} else if (value instanceof Type) {
|
||||
Type cls = (Type) value;
|
||||
return new AnnotationValue(ValueType.parse(cls.getDescriptor()));
|
||||
return new AnnotationValue(referenceCache.getCached(ValueType.parse(cls.getDescriptor())));
|
||||
} else if (value instanceof List<?>) {
|
||||
List<?> originalList = (List<?>) value;
|
||||
List<AnnotationValue> resultList = new ArrayList<>();
|
||||
|
@ -392,7 +398,7 @@ public class Parser {
|
|||
return new AnnotationValue(resultList);
|
||||
} else if (value instanceof AnnotationNode) {
|
||||
AnnotationNode annotNode = (AnnotationNode) value;
|
||||
ValueType.Object object = (ValueType.Object) ValueType.parse(annotNode.desc);
|
||||
ValueType.Object object = (ValueType.Object) referenceCache.getCached(ValueType.parse(annotNode.desc));
|
||||
AnnotationHolder annotation = new AnnotationHolder(object.getClassName());
|
||||
parseAnnotationValues(annotation, annotNode.values);
|
||||
return new AnnotationValue(annotation);
|
||||
|
|
|
@ -321,7 +321,7 @@ public class ProgramParser {
|
|||
if (block != null) {
|
||||
TryCatchBlock tryCatch = new TryCatchBlock();
|
||||
if (tryCatchNode.type != null) {
|
||||
tryCatch.setExceptionType(tryCatchNode.type.replace('/', '.'));
|
||||
tryCatch.setExceptionType(referenceCache.getCached(tryCatchNode.type.replace('/', '.')));
|
||||
}
|
||||
tryCatch.setHandler(getBasicBlock(labelIndexes.get(tryCatchNode.handler.getLabel())));
|
||||
tryCatch.getHandler().setExceptionVariable(program.variableAt(minLocal + method.maxLocals));
|
||||
|
@ -359,7 +359,7 @@ public class ProgramParser {
|
|||
Map<Integer, String> debugNames = new HashMap<>();
|
||||
variableDebugNames.put(builtInstructions.get(0), debugNames);
|
||||
for (LocalVariableNode localVar : localVarNodes) {
|
||||
debugNames.put(localVar.index + minLocal, localVar.name);
|
||||
debugNames.put(localVar.index + minLocal, referenceCache.getCached(localVar.name));
|
||||
}
|
||||
accumulatedDebugNames.putAll(debugNames);
|
||||
}
|
||||
|
@ -474,7 +474,7 @@ public class ProgramParser {
|
|||
String cls = type.replace('/', '.');
|
||||
ConstructInstruction insn = new ConstructInstruction();
|
||||
insn.setReceiver(getVariable(pushSingle()));
|
||||
insn.setType(cls);
|
||||
insn.setType(referenceCache.getCached(cls));
|
||||
addInstruction(insn);
|
||||
break;
|
||||
}
|
||||
|
@ -602,7 +602,7 @@ public class ProgramParser {
|
|||
} else if (value instanceof Type) {
|
||||
Type type = (Type) value;
|
||||
if (type.getSort() == Type.METHOD) {
|
||||
return new RuntimeConstant(MethodDescriptor.parseSignature(type.getDescriptor()));
|
||||
return new RuntimeConstant(parseSignature(type.getDescriptor()));
|
||||
} else {
|
||||
return new RuntimeConstant(referenceCache.parseValueTypeCached(type.getDescriptor()));
|
||||
}
|
||||
|
@ -725,7 +725,7 @@ public class ProgramParser {
|
|||
pushConstant((Double) cst);
|
||||
} else if (cst instanceof String) {
|
||||
StringConstantInstruction insn = new StringConstantInstruction();
|
||||
insn.setConstant((String) cst);
|
||||
insn.setConstant(referenceCache.getCached((String) cst));
|
||||
insn.setReceiver(getVariable(pushSingle()));
|
||||
addInstruction(insn);
|
||||
} else if (cst instanceof Type) {
|
||||
|
@ -1800,40 +1800,45 @@ public class ProgramParser {
|
|||
}
|
||||
};
|
||||
|
||||
private static MethodHandle parseHandle(Handle handle) {
|
||||
private MethodHandle parseHandle(Handle handle) {
|
||||
String owner = referenceCache.getCached(handle.getOwner().replace('/', '.'));
|
||||
String name = referenceCache.getCached(handle.getName());
|
||||
switch (handle.getTag()) {
|
||||
case Opcodes.H_GETFIELD:
|
||||
return MethodHandle.fieldGetter(handle.getOwner().replace('/', '.'), handle.getName(),
|
||||
ValueType.parse(handle.getDesc()));
|
||||
return MethodHandle.fieldGetter(owner, name,
|
||||
referenceCache.getCached(ValueType.parse(handle.getDesc())));
|
||||
case Opcodes.H_GETSTATIC:
|
||||
return MethodHandle.staticFieldGetter(handle.getOwner().replace('/', '.'), handle.getName(),
|
||||
ValueType.parse(handle.getDesc()));
|
||||
return MethodHandle.staticFieldGetter(owner, name,
|
||||
referenceCache.getCached(ValueType.parse(handle.getDesc())));
|
||||
case Opcodes.H_PUTFIELD:
|
||||
return MethodHandle.fieldSetter(handle.getOwner().replace('/', '.'), handle.getName(),
|
||||
ValueType.parse(handle.getDesc()));
|
||||
return MethodHandle.fieldSetter(owner, name,
|
||||
referenceCache.getCached(ValueType.parse(handle.getDesc())));
|
||||
case Opcodes.H_PUTSTATIC:
|
||||
return MethodHandle.staticFieldSetter(handle.getOwner().replace('/', '.'), handle.getName(),
|
||||
ValueType.parse(handle.getDesc()));
|
||||
return MethodHandle.staticFieldSetter(owner, name,
|
||||
referenceCache.getCached(ValueType.parse(handle.getDesc())));
|
||||
case Opcodes.H_INVOKEVIRTUAL:
|
||||
return MethodHandle.virtualCaller(handle.getOwner().replace('/', '.'), handle.getName(),
|
||||
MethodDescriptor.parseSignature(handle.getDesc()));
|
||||
return MethodHandle.virtualCaller(owner, name, parseSignature(handle.getDesc()));
|
||||
case Opcodes.H_INVOKESTATIC:
|
||||
return MethodHandle.staticCaller(handle.getOwner().replace('/', '.'), handle.getName(),
|
||||
MethodDescriptor.parseSignature(handle.getDesc()));
|
||||
return MethodHandle.staticCaller(owner, name, parseSignature(handle.getDesc()));
|
||||
case Opcodes.H_INVOKESPECIAL:
|
||||
return MethodHandle.specialCaller(handle.getOwner().replace('/', '.'), handle.getName(),
|
||||
MethodDescriptor.parseSignature(handle.getDesc()));
|
||||
return MethodHandle.specialCaller(owner, name, parseSignature(handle.getDesc()));
|
||||
case Opcodes.H_NEWINVOKESPECIAL:
|
||||
return MethodHandle.constructorCaller(handle.getOwner().replace('/', '.'), handle.getName(),
|
||||
MethodDescriptor.parseSignature(handle.getDesc()));
|
||||
return MethodHandle.constructorCaller(owner, name, parseSignature(handle.getDesc()));
|
||||
case Opcodes.H_INVOKEINTERFACE:
|
||||
return MethodHandle.interfaceCaller(handle.getOwner().replace('/', '.'), handle.getName(),
|
||||
MethodDescriptor.parseSignature(handle.getDesc()));
|
||||
return MethodHandle.interfaceCaller(owner, name, parseSignature(handle.getDesc()));
|
||||
default:
|
||||
throw new IllegalArgumentException("Unknown handle tag: " + handle.getTag());
|
||||
}
|
||||
}
|
||||
|
||||
private ValueType[] parseSignature(String desc) {
|
||||
ValueType[] signature = MethodDescriptor.parseSignature(desc);
|
||||
for (int i = 0; i < signature.length; ++i) {
|
||||
signature[i] = referenceCache.getCached(signature[i]);
|
||||
}
|
||||
return signature;
|
||||
}
|
||||
|
||||
private static ValueType getPrimitiveTypeField(String fieldName) {
|
||||
switch (fieldName) {
|
||||
case "java/lang/Boolean.TYPE":
|
||||
|
|
|
@ -25,11 +25,12 @@ import org.teavm.model.ReferenceCache;
|
|||
import org.teavm.parsing.Parser;
|
||||
|
||||
public class ResourceClassHolderMapper implements Mapper<String, ClassHolder> {
|
||||
private Parser parser = new Parser(new ReferenceCache());
|
||||
private Parser parser;
|
||||
private ResourceReader resourceReader;
|
||||
|
||||
public ResourceClassHolderMapper(ResourceReader resourceReader) {
|
||||
public ResourceClassHolderMapper(ResourceReader resourceReader, ReferenceCache referenceCache) {
|
||||
this.resourceReader = resourceReader;
|
||||
parser = new Parser(referenceCache);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -377,6 +377,7 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
|
|||
cacheStatus = new AnnotationAwareCacheStatus(rawCacheStatus, dependencyAnalyzer.getIncrementalDependencies(),
|
||||
dependencyAnalyzer.getClassSource());
|
||||
cacheStatus.addSynthesizedClasses(dependencyAnalyzer::isSynthesizedClass);
|
||||
dependencyAnalyzer.setInterruptor(null);
|
||||
|
||||
// Link
|
||||
if (wasCancelled()) {
|
||||
|
|
|
@ -18,6 +18,7 @@ package org.teavm.jso.impl;
|
|||
import java.util.Arrays;
|
||||
import java.util.function.Function;
|
||||
import org.teavm.jso.JSObject;
|
||||
import org.teavm.jso.core.JSArray;
|
||||
import org.teavm.jso.core.JSArrayReader;
|
||||
import org.teavm.model.MethodReference;
|
||||
import org.teavm.model.ValueType;
|
||||
|
@ -95,7 +96,8 @@ public final class JSMethods {
|
|||
public static final MethodReference FUNCTION_AS_OBJECT = new MethodReference(JS.class, "functionAsObject",
|
||||
JSObject.class, JSObject.class, JSObject.class);
|
||||
|
||||
private static final ValueType JS_OBJECT = ValueType.object(JSObject.class.getName());
|
||||
public static final ValueType JS_OBJECT = ValueType.object(JSObject.class.getName());
|
||||
public static final ValueType JS_ARRAY = ValueType.object(JSArray.class.getName());
|
||||
private static final MethodReference[] INVOKE_METHODS = new MethodReference[13];
|
||||
|
||||
static {
|
||||
|
|
|
@ -20,7 +20,6 @@ import java.util.function.Function;
|
|||
import org.teavm.diagnostics.Diagnostics;
|
||||
import org.teavm.jso.JSFunctor;
|
||||
import org.teavm.jso.JSObject;
|
||||
import org.teavm.jso.core.JSArray;
|
||||
import org.teavm.jso.core.JSArrayReader;
|
||||
import org.teavm.model.CallLocation;
|
||||
import org.teavm.model.ClassReader;
|
||||
|
@ -29,6 +28,7 @@ import org.teavm.model.ElementModifier;
|
|||
import org.teavm.model.Instruction;
|
||||
import org.teavm.model.MethodReference;
|
||||
import org.teavm.model.Program;
|
||||
import org.teavm.model.ReferenceCache;
|
||||
import org.teavm.model.TextLocation;
|
||||
import org.teavm.model.ValueType;
|
||||
import org.teavm.model.Variable;
|
||||
|
@ -39,6 +39,8 @@ import org.teavm.model.instructions.InvokeInstruction;
|
|||
import org.teavm.model.instructions.StringConstantInstruction;
|
||||
|
||||
class JSValueMarshaller {
|
||||
private static final ValueType stringType = ValueType.parse(String.class);
|
||||
private ReferenceCache referenceCache = new ReferenceCache();
|
||||
private Diagnostics diagnostics;
|
||||
private JSTypeHelper typeHelper;
|
||||
private ClassReaderSource classSource;
|
||||
|
@ -123,8 +125,8 @@ class JSValueMarshaller {
|
|||
|
||||
if (degree <= 1) {
|
||||
InvokeInstruction insn = new InvokeInstruction();
|
||||
insn.setMethod(new MethodReference(JS.class.getName(), "wrap", getWrappedType(type),
|
||||
getWrapperType(type)));
|
||||
insn.setMethod(referenceCache.getCached(new MethodReference(JS.class.getName(), "wrap",
|
||||
getWrappedType(type), getWrapperType(type))));
|
||||
insn.getArguments().add(var);
|
||||
insn.setReceiver(result);
|
||||
insn.setType(InvocationType.SPECIAL);
|
||||
|
@ -152,8 +154,8 @@ class JSValueMarshaller {
|
|||
}
|
||||
|
||||
insn = new InvokeInstruction();
|
||||
insn.setMethod(new MethodReference(JS.class.getName(), "map", getWrappedType(type),
|
||||
ValueType.parse(Function.class), getWrapperType(type)));
|
||||
insn.setMethod(referenceCache.getCached(new MethodReference(JS.class.getName(), "map",
|
||||
getWrappedType(type), ValueType.parse(Function.class), getWrapperType(type))));
|
||||
insn.getArguments().add(var);
|
||||
insn.getArguments().add(function);
|
||||
insn.setReceiver(result);
|
||||
|
@ -176,7 +178,7 @@ class JSValueMarshaller {
|
|||
if (type.isObject(String.class)) {
|
||||
return type;
|
||||
} else {
|
||||
return ValueType.parse(JSObject.class);
|
||||
return JSMethods.JS_OBJECT;
|
||||
}
|
||||
} else {
|
||||
return type;
|
||||
|
@ -185,9 +187,9 @@ class JSValueMarshaller {
|
|||
|
||||
private ValueType getWrapperType(ValueType type) {
|
||||
if (type instanceof ValueType.Array) {
|
||||
return ValueType.parse(JSArray.class);
|
||||
return JSMethods.JS_ARRAY;
|
||||
} else {
|
||||
return ValueType.parse(JSObject.class);
|
||||
return JSMethods.JS_OBJECT;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -232,25 +234,25 @@ class JSValueMarshaller {
|
|||
if (type instanceof ValueType.Primitive) {
|
||||
switch (((ValueType.Primitive) type).getKind()) {
|
||||
case BOOLEAN:
|
||||
return unwrap(var, "unwrapBoolean", ValueType.parse(JSObject.class), ValueType.BOOLEAN,
|
||||
return unwrap(var, "unwrapBoolean", JSMethods.JS_OBJECT, ValueType.BOOLEAN,
|
||||
location.getSourceLocation());
|
||||
case BYTE:
|
||||
return unwrap(var, "unwrapByte", ValueType.parse(JSObject.class), ValueType.BYTE,
|
||||
return unwrap(var, "unwrapByte", JSMethods.JS_OBJECT, ValueType.BYTE,
|
||||
location.getSourceLocation());
|
||||
case SHORT:
|
||||
return unwrap(var, "unwrapShort", ValueType.parse(JSObject.class), ValueType.SHORT,
|
||||
return unwrap(var, "unwrapShort", JSMethods.JS_OBJECT, ValueType.SHORT,
|
||||
location.getSourceLocation());
|
||||
case INTEGER:
|
||||
return unwrap(var, "unwrapInt", ValueType.parse(JSObject.class), ValueType.INTEGER,
|
||||
return unwrap(var, "unwrapInt", JSMethods.JS_OBJECT, ValueType.INTEGER,
|
||||
location.getSourceLocation());
|
||||
case CHARACTER:
|
||||
return unwrap(var, "unwrapCharacter", ValueType.parse(JSObject.class), ValueType.CHARACTER,
|
||||
return unwrap(var, "unwrapCharacter", JSMethods.JS_OBJECT, ValueType.CHARACTER,
|
||||
location.getSourceLocation());
|
||||
case DOUBLE:
|
||||
return unwrap(var, "unwrapDouble", ValueType.parse(JSObject.class), ValueType.DOUBLE,
|
||||
return unwrap(var, "unwrapDouble", JSMethods.JS_OBJECT, ValueType.DOUBLE,
|
||||
location.getSourceLocation());
|
||||
case FLOAT:
|
||||
return unwrap(var, "unwrapFloat", ValueType.parse(JSObject.class), ValueType.FLOAT,
|
||||
return unwrap(var, "unwrapFloat", JSMethods.JS_OBJECT, ValueType.FLOAT,
|
||||
location.getSourceLocation());
|
||||
case LONG:
|
||||
break;
|
||||
|
@ -260,8 +262,7 @@ class JSValueMarshaller {
|
|||
if (className.equals(JSObject.class.getName())) {
|
||||
return var;
|
||||
} else if (className.equals("java.lang.String")) {
|
||||
return unwrap(var, "unwrapString", ValueType.parse(JSObject.class), ValueType.parse(String.class),
|
||||
location.getSourceLocation());
|
||||
return unwrap(var, "unwrapString", JSMethods.JS_OBJECT, stringType, location.getSourceLocation());
|
||||
} else if (typeHelper.isJavaScriptClass(className)) {
|
||||
Variable result = program.createVariable();
|
||||
CastInstruction castInsn = new CastInstruction();
|
||||
|
@ -451,7 +452,8 @@ class JSValueMarshaller {
|
|||
}
|
||||
Variable result = program.createVariable();
|
||||
InvokeInstruction insn = new InvokeInstruction();
|
||||
insn.setMethod(new MethodReference(JS.class.getName(), methodName, argType, resultType));
|
||||
insn.setMethod(referenceCache.getCached(referenceCache.getCached(new MethodReference(
|
||||
JS.class.getName(), methodName, argType, resultType))));
|
||||
insn.getArguments().add(var);
|
||||
insn.setReceiver(result);
|
||||
insn.setType(InvocationType.SPECIAL);
|
||||
|
@ -482,7 +484,7 @@ class JSValueMarshaller {
|
|||
}
|
||||
|
||||
Variable addStringWrap(Variable var, TextLocation location) {
|
||||
return wrap(var, ValueType.object("java.lang.String"), location, false);
|
||||
return wrap(var, stringType, location, false);
|
||||
}
|
||||
|
||||
Variable addString(String str, TextLocation location) {
|
||||
|
|
|
@ -47,11 +47,21 @@ public class MetaprogrammingDependencyListener extends AbstractDependencyListene
|
|||
MetaprogrammingImpl.classLoader = proxyClassLoader;
|
||||
MetaprogrammingImpl.classSource = agent.getClassSource();
|
||||
MetaprogrammingImpl.hierarchy = agent.getClassHierarchy();
|
||||
MetaprogrammingImpl.incrementaDependencies = agent.getIncrementalCache();
|
||||
MetaprogrammingImpl.incrementalDependencies = agent.getIncrementalCache();
|
||||
MetaprogrammingImpl.agent = agent;
|
||||
MetaprogrammingImpl.reflectContext = new ReflectContext(agent.getClassHierarchy(), proxyClassLoader);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void complete() {
|
||||
MetaprogrammingImpl.classLoader = null;
|
||||
MetaprogrammingImpl.classSource = null;
|
||||
MetaprogrammingImpl.hierarchy = null;
|
||||
MetaprogrammingImpl.incrementalDependencies = null;
|
||||
MetaprogrammingImpl.agent = null;
|
||||
MetaprogrammingImpl.reflectContext = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void methodReached(DependencyAgent agent, MethodDependency methodDep) {
|
||||
MethodModel proxy = describer.getMethod(methodDep.getReference());
|
||||
|
|
|
@ -65,7 +65,7 @@ public final class MetaprogrammingImpl {
|
|||
static ClassLoader classLoader;
|
||||
static ClassReaderSource classSource;
|
||||
static ClassHierarchy hierarchy;
|
||||
static IncrementalDependencyRegistration incrementaDependencies;
|
||||
static IncrementalDependencyRegistration incrementalDependencies;
|
||||
static ReflectContext reflectContext;
|
||||
static DependencyAgent agent;
|
||||
static VariableContext varContext;
|
||||
|
@ -320,7 +320,7 @@ public final class MetaprogrammingImpl {
|
|||
|
||||
ValueImpl<T> result = new ValueImpl<>(nestedVarContext.createInstance(generator), varContext, innerType);
|
||||
|
||||
incrementaDependencies.setNoCache(cls.getName());
|
||||
incrementalDependencies.setNoCache(cls.getName());
|
||||
agent.submitClass(cls);
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -23,6 +23,19 @@ import org.teavm.platform.metadata.ResourceArray;
|
|||
import org.teavm.platform.metadata.ResourceMap;
|
||||
|
||||
class ResourceProgramTransformer {
|
||||
private static final MethodReference CAST_TO_STRING = new MethodReference(ResourceAccessor.class, "castToString",
|
||||
Object.class, String.class);
|
||||
private static final MethodReference CAST_FROM_STRING = new MethodReference(ResourceAccessor.class,
|
||||
"castFromString", String.class, Object.class);
|
||||
private static final MethodReference PUT = new MethodReference(ResourceAccessor.class, "put",
|
||||
Object.class, String.class, Object.class, void.class);
|
||||
private static final MethodReference KEYS = new MethodReference(ResourceAccessor.class, "keys",
|
||||
Object.class, Object.class);
|
||||
private static final MethodReference KEYS_TO_STRINGS = new MethodReference(ResourceAccessor.class, "keysToStrings",
|
||||
Object.class, String[].class);
|
||||
private static final MethodReference GET_PROPERTY = new MethodReference(ResourceAccessor.class, "getProperty",
|
||||
Object.class, String.class, Object.class);
|
||||
|
||||
private ClassHierarchy hierarchy;
|
||||
private Program program;
|
||||
|
||||
|
@ -97,14 +110,13 @@ class ResourceProgramTransformer {
|
|||
|
||||
InvokeInstruction keysInsn = new InvokeInstruction();
|
||||
keysInsn.setType(InvocationType.SPECIAL);
|
||||
keysInsn.setMethod(new MethodReference(ResourceAccessor.class, "keys", Object.class, Object.class));
|
||||
keysInsn.setMethod(KEYS);
|
||||
keysInsn.getArguments().add(insn.getInstance());
|
||||
keysInsn.setReceiver(tmp);
|
||||
|
||||
InvokeInstruction transformInsn = new InvokeInstruction();
|
||||
transformInsn.setType(InvocationType.SPECIAL);
|
||||
transformInsn.setMethod(new MethodReference(ResourceAccessor.class, "keysToStrings",
|
||||
Object.class, String[].class));
|
||||
transformInsn.setMethod(KEYS_TO_STRINGS);
|
||||
transformInsn.getArguments().add(tmp);
|
||||
transformInsn.setReceiver(insn.getReceiver());
|
||||
|
||||
|
@ -148,8 +160,7 @@ class ResourceProgramTransformer {
|
|||
getProperty(insn, property, instructions, resultVar);
|
||||
InvokeInstruction castInvoke = new InvokeInstruction();
|
||||
castInvoke.setType(InvocationType.SPECIAL);
|
||||
castInvoke.setMethod(new MethodReference(ResourceAccessor.class, "castToString",
|
||||
Object.class, String.class));
|
||||
castInvoke.setMethod(CAST_TO_STRING);
|
||||
castInvoke.getArguments().add(resultVar);
|
||||
castInvoke.setReceiver(insn.getReceiver());
|
||||
instructions.add(castInvoke);
|
||||
|
@ -179,8 +190,7 @@ class ResourceProgramTransformer {
|
|||
instructions.add(nameInsn);
|
||||
InvokeInstruction accessorInvoke = new InvokeInstruction();
|
||||
accessorInvoke.setType(InvocationType.SPECIAL);
|
||||
accessorInvoke.setMethod(new MethodReference(ResourceAccessor.class, "getProperty",
|
||||
Object.class, String.class, Object.class));
|
||||
accessorInvoke.setMethod(GET_PROPERTY);
|
||||
accessorInvoke.getArguments().add(insn.getInstance());
|
||||
accessorInvoke.getArguments().add(nameVar);
|
||||
accessorInvoke.setReceiver(resultVar);
|
||||
|
@ -236,8 +246,7 @@ class ResourceProgramTransformer {
|
|||
Variable castVar = insn.getProgram().createVariable();
|
||||
InvokeInstruction castInvoke = new InvokeInstruction();
|
||||
castInvoke.setType(InvocationType.SPECIAL);
|
||||
castInvoke.setMethod(new MethodReference(ResourceAccessor.class, "castFromString",
|
||||
String.class, Object.class));
|
||||
castInvoke.setMethod(CAST_FROM_STRING);
|
||||
castInvoke.getArguments().add(insn.getArguments().get(0));
|
||||
castInvoke.setReceiver(castVar);
|
||||
instructions.add(castInvoke);
|
||||
|
@ -262,8 +271,7 @@ class ResourceProgramTransformer {
|
|||
instructions.add(nameInsn);
|
||||
InvokeInstruction accessorInvoke = new InvokeInstruction();
|
||||
accessorInvoke.setType(InvocationType.SPECIAL);
|
||||
accessorInvoke.setMethod(new MethodReference(ResourceAccessor.class, "put",
|
||||
Object.class, String.class, Object.class, void.class));
|
||||
accessorInvoke.setMethod(PUT);
|
||||
accessorInvoke.getArguments().add(insn.getInstance());
|
||||
accessorInvoke.getArguments().add(nameVar);
|
||||
accessorInvoke.getArguments().add(valueVar);
|
||||
|
|
Loading…
Reference in New Issue
Block a user