Decrease memory consumption

This commit is contained in:
Alexey Andreev 2018-12-29 19:02:03 +03:00
parent 97a1db1b79
commit f589b0035a
29 changed files with 298 additions and 255 deletions

View File

@ -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")),

View File

@ -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);
}

View File

@ -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);
}

View File

@ -35,4 +35,8 @@ public abstract class AbstractDependencyListener implements DependencyListener {
@Override
public void completing(DependencyAgent agent) {
}
@Override
public void complete() {
}
}

View File

@ -135,4 +135,8 @@ public class DependencyAgent implements DependencyInfo, ServiceRepository {
public IncrementalDependencyRegistration getIncrementalCache() {
return analyzer.incrementalCache;
}
void cleanup() {
analyzer = null;
}
}

View File

@ -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<>();

View File

@ -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() {

View File

@ -25,4 +25,6 @@ public interface DependencyListener {
void fieldReached(DependencyAgent agent, FieldDependency field);
void completing(DependencyAgent agent);
void complete();
}

View File

@ -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) {
annotations.remove(type);
if (annotations != null) {
annotations.remove(type);
}
}
@Override
public Iterable<AnnotationHolder> all() {
return annotations.values();
return annotations != null ? annotations.values() : Collections.emptyList();
}
}

View File

@ -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;
}
};

View File

@ -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);
}
}
}

View File

@ -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;

View File

@ -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() {

View File

@ -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;

View File

@ -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;
}

View File

@ -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() {

View File

@ -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) {
}
}

View File

@ -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);
}

View File

@ -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);
}
}
}

View File

@ -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);
}

View File

@ -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);

View File

@ -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":

View File

@ -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

View File

@ -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()) {

View File

@ -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 {

View File

@ -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) {

View File

@ -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());

View File

@ -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;
}

View File

@ -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);