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