diff --git a/teavm-core/src/main/java/org/teavm/dependency/DataFlowGraphBuilder.java b/teavm-core/src/main/java/org/teavm/dependency/DataFlowGraphBuilder.java index 7fb34216b..882000dfc 100644 --- a/teavm-core/src/main/java/org/teavm/dependency/DataFlowGraphBuilder.java +++ b/teavm-core/src/main/java/org/teavm/dependency/DataFlowGraphBuilder.java @@ -36,14 +36,20 @@ public class DataFlowGraphBuilder implements InstructionReader { private ObjectIntMap methodNodes = new ObjectIntOpenHashMap<>(); private ObjectIntMap fieldNodes = new ObjectIntOpenHashMap<>(); private int[] arrayNodes; + private int returnIndex = -1; + private int exceptionIndex; public void important(int node) { importantNodes.add(node); } - public int[] buildMapping(ProgramReader program, int paramCount) { + public int[] buildMapping(ProgramReader program, int paramCount, boolean needsReturn) { lastIndex = program.variableCount(); arrayNodes = new int[lastIndex]; + if (needsReturn) { + returnIndex = lastIndex++; + } + exceptionIndex = lastIndex++; Arrays.fill(arrayNodes, -1); for (int i = 0; i < program.basicBlockCount(); ++i) { BasicBlockReader block = program.basicBlockAt(i); @@ -52,6 +58,11 @@ public class DataFlowGraphBuilder implements InstructionReader { builder.addEdge(incoming.getValue().getIndex(), phi.getReceiver().getIndex()); } } + for (TryCatchBlockReader tryCatch : block.readTryCatchBlocks()) { + if (tryCatch.getExceptionVariable() != null) { + important(tryCatch.getExceptionVariable().getIndex()); + } + } block.readAllInstructions(this); } Graph graph = builder.build(); @@ -76,6 +87,17 @@ public class DataFlowGraphBuilder implements InstructionReader { importantNodes.add(newCls); } } + for (int succ : graph.outgoingEdges(i)) { + boolean succImportant = importantNodes.contains(classes.find(succ)); + boolean nodeImportant = importantNodes.contains(classes.find(i)); + if (succImportant && nodeImportant) { + continue; + } + int newCls = classes.union(succ, i); + if (nodeImportant || succImportant) { + importantNodes.add(newCls); + } + } } int[][] sccs = GraphUtils.findStronglyConnectedComponents(graph, startNodes.getAll()); @@ -88,7 +110,25 @@ public class DataFlowGraphBuilder implements InstructionReader { last = last < 0 ? node : classes.union(node, last); } } - return classes.pack(program.variableCount()); + + int[] classMap = new int[classes.size()]; + Arrays.fill(classMap, -1); + int[] result = new int[program.variableCount()]; + int classCount = 0; + for (int i = 0; i < program.variableCount(); ++i) { + int cls = classes.find(i); + if (!importantNodes.contains(cls)) { + result[i] = -1; + continue; + } + int packedCls = classMap[cls]; + if (packedCls < 0) { + packedCls = classCount++; + classMap[cls] = packedCls; + } + result[i] = packedCls; + } + return result; } @Override @@ -178,14 +218,16 @@ public class DataFlowGraphBuilder implements InstructionReader { @Override public void exit(VariableReader valueToReturn) { - if (valueToReturn != null) { - important(valueToReturn.getIndex()); + if (valueToReturn != null && returnIndex >= 0) { + important(returnIndex); + builder.addEdge(valueToReturn.getIndex(), returnIndex); } } @Override public void raise(VariableReader exception) { - important(exception.getIndex()); + builder.addEdge(exception.getIndex(), exceptionIndex); + important(exceptionIndex); } @Override @@ -212,13 +254,18 @@ public class DataFlowGraphBuilder implements InstructionReader { @Override public void getField(VariableReader receiver, VariableReader instance, FieldReference field, ValueType fieldType) { + if (fieldType instanceof ValueType.Primitive) { + return; + } int fieldNode = getFieldNode(field); builder.addEdge(fieldNode, receiver.getIndex()); } - @Override - public void putField(VariableReader instance, FieldReference field, VariableReader value) { + public void putField(VariableReader instance, FieldReference field, VariableReader value, ValueType fieldType) { + if (fieldType instanceof ValueType.Primitive) { + return; + } int fieldNode = getFieldNode(field); builder.addEdge(value.getIndex(), fieldNode); } @@ -274,7 +321,18 @@ public class DataFlowGraphBuilder implements InstructionReader { public void invoke(VariableReader receiver, VariableReader instance, MethodReference method, List arguments, InvocationType type) { if (receiver != null) { - builder.addEdge(getMethodNode(method), receiver.getIndex()); + if (!(method.getReturnType() instanceof ValueType.Primitive)) { + builder.addEdge(getMethodNode(method), receiver.getIndex()); + } + } + ValueType[] paramTypes = method.getParameterTypes(); + for (int i = 0; i < paramTypes.length; ++i) { + if (!(paramTypes[i] instanceof ValueType.Primitive)) { + important(arguments.get(i).getIndex()); + } + } + if (instance != null) { + important(instance.getIndex()); } } @@ -293,9 +351,11 @@ public class DataFlowGraphBuilder implements InstructionReader { @Override public void monitorEnter(VariableReader objectRef) { + important(objectRef.getIndex()); } @Override public void monitorExit(VariableReader objectRef) { + important(objectRef.getIndex()); } } diff --git a/teavm-core/src/main/java/org/teavm/dependency/DependencyChecker.java b/teavm-core/src/main/java/org/teavm/dependency/DependencyChecker.java index 3174539ca..f2b9e96df 100644 --- a/teavm-core/src/main/java/org/teavm/dependency/DependencyChecker.java +++ b/teavm-core/src/main/java/org/teavm/dependency/DependencyChecker.java @@ -62,6 +62,8 @@ public class DependencyChecker implements DependencyInfo { private Diagnostics diagnostics; DefaultCallGraph callGraph = new DefaultCallGraph(); private DependencyAgent agent; + List nodes = new ArrayList<>(); + List typeBitSets = new ArrayList<>(); public DependencyChecker(ClassReaderSource classSource, ClassLoader classLoader, ServiceRepository services, Diagnostics diagnostics) { @@ -128,13 +130,16 @@ public class DependencyChecker implements DependencyInfo { if (type == null) { type = new DependencyType(this, name, types.size()); types.add(type); + typeBitSets.add(new BitSet(nodes.size())); typeMap.put(name, type); } return type; } public DependencyNode createNode() { - return new DependencyNode(this); + DependencyNode node = new DependencyNode(this, nodes.size()); + nodes.add(node); + return node; } @Override @@ -336,11 +341,9 @@ public class DependencyChecker implements DependencyInfo { private MethodDependency createMethodDep(MethodReference methodRef, MethodReader method) { ValueType[] arguments = methodRef.getParameterTypes(); int paramCount = arguments.length + 1; - int varCount = Math.max(paramCount, method != null && method.getProgram() != null ? - method.getProgram().variableCount() : 0); - DependencyNode[] parameterNodes = new DependencyNode[varCount]; - for (int i = 0; i < varCount; ++i) { - parameterNodes[i] = new DependencyNode(this); + DependencyNode[] parameterNodes = new DependencyNode[arguments.length + 1]; + for (int i = 0; i < parameterNodes.length; ++i) { + parameterNodes[i] = createNode(); if (shouldLog) { parameterNodes[i].setTag(methodRef + ":" + i); } @@ -349,7 +352,7 @@ public class DependencyChecker implements DependencyInfo { if (methodRef.getDescriptor().getResultType() == ValueType.VOID) { resultNode = null; } else { - resultNode = new DependencyNode(this); + resultNode = createNode(); if (shouldLog) { resultNode.setTag(methodRef + ":RESULT"); } @@ -431,7 +434,7 @@ public class DependencyChecker implements DependencyInfo { } private FieldDependency createFieldNode(final FieldReference fieldRef, FieldReader field) { - DependencyNode node = new DependencyNode(this); + DependencyNode node = createNode(); if (shouldLog) { node.setTag(fieldRef.getClassName() + "#" + fieldRef.getFieldName()); } @@ -501,6 +504,7 @@ public class DependencyChecker implements DependencyInfo { index = 0; } } + return; } public T getService(Class type) { diff --git a/teavm-core/src/main/java/org/teavm/dependency/DependencyGraphBuilder.java b/teavm-core/src/main/java/org/teavm/dependency/DependencyGraphBuilder.java index cad81ed31..159d30425 100644 --- a/teavm-core/src/main/java/org/teavm/dependency/DependencyGraphBuilder.java +++ b/teavm-core/src/main/java/org/teavm/dependency/DependencyGraphBuilder.java @@ -15,6 +15,7 @@ */ package org.teavm.dependency; +import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -48,20 +49,29 @@ class DependencyGraphBuilder { } program = method.getProgram(); if (DependencyChecker.shouldLog) { - System.out.println("Method achieved: " + method.getReference()); + System.out.println("Method reached: " + method.getReference()); System.out.println(new ListingBuilder().buildListing(program, " ")); } resultNode = dep.getResult(); - DependencyNode[] origNodes = dep.getVariables(); DataFlowGraphBuilder dfgBuilder = new DataFlowGraphBuilder(); for (int i = 0; i < dep.getParameterCount(); ++i) { dfgBuilder.important(i); } - int[] nodeMapping = dfgBuilder.buildMapping(program, dep.getParameterCount()); - nodes = new DependencyNode[origNodes.length]; + int[] nodeMapping = dfgBuilder.buildMapping(program, dep.getParameterCount(), + !(method.getResultType() instanceof ValueType.Primitive) && method.getResultType() != ValueType.VOID); + int nodeClassCount = 0; + for (int i = 0; i < nodeMapping.length; ++i) { + nodeClassCount = Math.max(nodeClassCount, nodeMapping[i] + 1); + } + DependencyNode[] nodeClasses = Arrays.copyOf(dep.getVariables(), nodeClassCount); + for (int i = dep.getVariableCount(); i < nodeClasses.length; ++i) { + nodeClasses[i] = dependencyChecker.createNode(); + } + nodes = new DependencyNode[dep.getMethod().getProgram().variableCount()]; for (int i = 0; i < nodes.length; ++i) { - nodes[i] = origNodes[nodeMapping[i]]; + int mappedNode = nodeMapping[i]; + nodes[i] = mappedNode >= 0 ? nodeClasses[mappedNode] : null; } dep.setVariables(nodes); @@ -71,7 +81,11 @@ class DependencyGraphBuilder { block.readAllInstructions(reader); for (PhiReader phi : block.readPhis()) { for (IncomingReader incoming : phi.readIncomings()) { - nodes[incoming.getValue().getIndex()].connect(nodes[phi.getReceiver().getIndex()]); + DependencyNode incomingNode = nodes[incoming.getValue().getIndex()]; + DependencyNode receiverNode = nodes[phi.getReceiver().getIndex()]; + if (incomingNode != null || receiverNode != null) { + nodes[incoming.getValue().getIndex()].connect(nodes[phi.getReceiver().getIndex()]); + } } } for (TryCatchBlockReader tryCatch : block.readTryCatchBlocks()) { @@ -169,7 +183,9 @@ class DependencyGraphBuilder { methodDep.use(); DependencyNode[] targetParams = methodDep.getVariables(); for (int i = 0; i < parameters.length; ++i) { - parameters[i].connect(targetParams[i]); + if (parameters[i] != null) { + parameters[i].connect(targetParams[i]); + } } if (result != null && methodDep.getResult() != null) { methodDep.getResult().connect(result); @@ -211,7 +227,10 @@ class DependencyGraphBuilder { @Override public void classConstant(VariableReader receiver, ValueType cst) { - nodes[receiver.getIndex()].propagate(dependencyChecker.getType("java.lang.Class")); + DependencyNode node = nodes[receiver.getIndex()]; + if (node != null) { + node.propagate(dependencyChecker.getType("java.lang.Class")); + } while (cst instanceof ValueType.Array) { cst = ((ValueType.Array)cst).getItemType(); } @@ -243,7 +262,10 @@ class DependencyGraphBuilder { @Override public void stringConstant(VariableReader receiver, String cst) { - nodes[receiver.getIndex()].propagate(dependencyChecker.getType("java.lang.String")); + DependencyNode node = nodes[receiver.getIndex()]; + if (node != null) { + node.propagate(dependencyChecker.getType("java.lang.String")); + } MethodDependency method = dependencyChecker.linkMethod(new MethodReference(String.class, "", char[].class, void.class), new CallLocation(caller.getMethod(), currentLocation)); method.use(); @@ -262,7 +284,9 @@ class DependencyGraphBuilder { public void assign(VariableReader receiver, VariableReader assignee) { DependencyNode valueNode = nodes[assignee.getIndex()]; DependencyNode receiverNode = nodes[receiver.getIndex()]; - valueNode.connect(receiverNode); + if (valueNode != null && receiverNode != null) { + valueNode.connect(receiverNode); + } } @Override @@ -319,7 +343,10 @@ class DependencyGraphBuilder { @Override public void exit(VariableReader valueToReturn) { if (valueToReturn != null) { - nodes[valueToReturn.getIndex()].connect(resultNode); + DependencyNode node = nodes[valueToReturn.getIndex()]; + if (node != null) { + node.connect(resultNode); + } } } @@ -330,7 +357,10 @@ class DependencyGraphBuilder { @Override public void createArray(VariableReader receiver, ValueType itemType, VariableReader size) { - nodes[receiver.getIndex()].propagate(dependencyChecker.getType("[" + itemType)); + DependencyNode node = nodes[receiver.getIndex()]; + if (node != null) { + node.propagate(dependencyChecker.getType("[" + itemType)); + } String className = extractClassName(itemType); if (className != null) { dependencyChecker.linkClass(className, new CallLocation(caller.getMethod(), currentLocation)); @@ -361,6 +391,9 @@ class DependencyGraphBuilder { sb.append(itemTypeStr); DependencyNode node = nodes[receiver.getIndex()]; for (int i = 0; i < dimensions.size(); ++i) { + if (node == null) { + break; + } node.propagate(dependencyChecker.getType(sb.substring(i, sb.length()))); node = node.getArrayItem(); } @@ -373,25 +406,37 @@ class DependencyGraphBuilder { @Override public void create(VariableReader receiver, String type) { dependencyChecker.linkClass(type, new CallLocation(caller.getMethod(), currentLocation)); - nodes[receiver.getIndex()].propagate(dependencyChecker.getType(type)); + DependencyNode node = nodes[receiver.getIndex()]; + if (node != null) { + node.propagate(dependencyChecker.getType(type)); + } } @Override public void getField(VariableReader receiver, VariableReader instance, FieldReference field, ValueType fieldType) { - FieldDependency fieldDep = dependencyChecker.linkField(field, - new CallLocation(caller.getMethod(), currentLocation)); - DependencyNode receiverNode = nodes[receiver.getIndex()]; - fieldDep.getValue().connect(receiverNode); + if (!(fieldType instanceof ValueType.Primitive)) { + FieldDependency fieldDep = dependencyChecker.linkField(field, + new CallLocation(caller.getMethod(), currentLocation)); + DependencyNode receiverNode = nodes[receiver.getIndex()]; + if (receiverNode != null) { + fieldDep.getValue().connect(receiverNode); + } + } initClass(field.getClassName()); } @Override - public void putField(VariableReader instance, FieldReference field, VariableReader value) { - FieldDependency fieldDep = dependencyChecker.linkField(field, - new CallLocation(caller.getMethod(), currentLocation)); - DependencyNode valueNode = nodes[value.getIndex()]; - valueNode.connect(fieldDep.getValue()); + public void putField(VariableReader instance, FieldReference field, VariableReader value, + ValueType fieldType) { + if (!(fieldType instanceof ValueType.Primitive)) { + FieldDependency fieldDep = dependencyChecker.linkField(field, + new CallLocation(caller.getMethod(), currentLocation)); + DependencyNode valueNode = nodes[value.getIndex()]; + if (valueNode != null) { + valueNode.connect(fieldDep.getValue()); + } + } initClass(field.getClassName()); } @@ -403,33 +448,41 @@ class DependencyGraphBuilder { public void cloneArray(VariableReader receiver, VariableReader array) { DependencyNode arrayNode = nodes[array.getIndex()]; final DependencyNode receiverNode = nodes[receiver.getIndex()]; - arrayNode.addConsumer(new DependencyConsumer() { - @Override public void consume(DependencyType type) { - receiverNode.propagate(type); - } - }); - arrayNode.getArrayItem().connect(receiverNode.getArrayItem()); + if (arrayNode != null && receiverNode != null) { + arrayNode.addConsumer(new DependencyConsumer() { + @Override public void consume(DependencyType type) { + receiverNode.propagate(type); + } + }); + arrayNode.getArrayItem().connect(receiverNode.getArrayItem()); + } } @Override public void unwrapArray(VariableReader receiver, VariableReader array, ArrayElementType elementType) { DependencyNode arrayNode = nodes[array.getIndex()]; DependencyNode receiverNode = nodes[receiver.getIndex()]; - arrayNode.connect(receiverNode); + if (arrayNode != null && receiverNode != null) { + arrayNode.connect(receiverNode); + } } @Override public void getElement(VariableReader receiver, VariableReader array, VariableReader index) { DependencyNode arrayNode = nodes[array.getIndex()]; DependencyNode receiverNode = nodes[receiver.getIndex()]; - arrayNode.getArrayItem().connect(receiverNode); + if (arrayNode != null && receiverNode != null) { + arrayNode.getArrayItem().connect(receiverNode); + } } @Override public void putElement(VariableReader array, VariableReader index, VariableReader value) { DependencyNode valueNode = nodes[value.getIndex()]; DependencyNode arrayNode = nodes[array.getIndex()]; - valueNode.connect(arrayNode.getArrayItem()); + if (valueNode != null && arrayNode != null) { + valueNode.connect(arrayNode.getArrayItem()); + } } @Override @@ -460,13 +513,20 @@ class DependencyGraphBuilder { methodDep.use(); DependencyNode[] targetParams = methodDep.getVariables(); for (int i = 0; i < arguments.size(); ++i) { - nodes[arguments.get(i).getIndex()].connect(targetParams[i + 1]); + DependencyNode value = nodes[arguments.get(i).getIndex()]; + DependencyNode param = targetParams[i + 1]; + if (value != null && param != null) { + value.connect(param); + } } if (instance != null) { nodes[instance.getIndex()].connect(targetParams[0]); } if (methodDep.getResult() != null && receiver != null) { - methodDep.getResult().connect(nodes[receiver.getIndex()]); + DependencyNode receiverNode = nodes[receiver.getIndex()]; + if (methodDep.getResult() != null && receiverNode != null) { + methodDep.getResult().connect(receiverNode); + } } methodDep.getThrown().addConsumer(currentExceptionConsumer); initClass(method.getClassName()); diff --git a/teavm-core/src/main/java/org/teavm/dependency/DependencyNode.java b/teavm-core/src/main/java/org/teavm/dependency/DependencyNode.java index d5d4f8dbc..a4522c30b 100644 --- a/teavm-core/src/main/java/org/teavm/dependency/DependencyNode.java +++ b/teavm-core/src/main/java/org/teavm/dependency/DependencyNode.java @@ -23,19 +23,21 @@ import java.util.*; */ public class DependencyNode implements ValueDependencyInfo { private DependencyChecker dependencyChecker; - private Set followers = new HashSet<>(); + private List followers; private BitSet types; - private Map transitions = new HashMap<>(); + private List transitions; private volatile String tag; private DependencyNode arrayItemNode; private int degree; + int index; - DependencyNode(DependencyChecker dependencyChecker) { - this(dependencyChecker, 0); + DependencyNode(DependencyChecker dependencyChecker, int index) { + this(dependencyChecker, index, 0); } - DependencyNode(DependencyChecker dependencyChecker, int degree) { + DependencyNode(DependencyChecker dependencyChecker, int index, int degree) { this.dependencyChecker = dependencyChecker; + this.index = index; this.degree = degree; } @@ -54,8 +56,10 @@ public class DependencyNode implements ValueDependencyInfo { if (DependencyChecker.shouldLog) { System.out.println(tag + " -> " + type.getName()); } - for (DependencyConsumer consumer : followers.toArray(new DependencyConsumer[followers.size()])) { - dependencyChecker.schedulePropagation(consumer, type); + if (followers != null) { + for (DependencyConsumer consumer : followers.toArray(new DependencyConsumer[followers.size()])) { + dependencyChecker.schedulePropagation(consumer, type); + } } } } @@ -81,13 +85,22 @@ public class DependencyNode implements ValueDependencyInfo { System.out.println(tag + " -> " + types[i].getName()); } } - for (DependencyConsumer consumer : followers.toArray(new DependencyConsumer[followers.size()])) { - dependencyChecker.schedulePropagation(consumer, Arrays.copyOf(types, j)); + if (followers != null) { + for (DependencyConsumer consumer : followers.toArray(new DependencyConsumer[followers.size()])) { + dependencyChecker.schedulePropagation(consumer, Arrays.copyOf(types, j)); + } } } public void addConsumer(DependencyConsumer consumer) { - if (followers.add(consumer) && this.types != null) { + if (followers == null) { + followers = new ArrayList<>(); + } + if (followers.contains(consumer)) { + return; + } + followers.add(consumer); + if (this.types != null) { List types = new ArrayList<>(); for (int index = this.types.nextSetBit(0); index >= 0; index = this.types.nextSetBit(index + 1)) { types.add(dependencyChecker.types.get(index)); @@ -100,14 +113,26 @@ public class DependencyNode implements ValueDependencyInfo { if (this == node) { return; } - DependencyNodeToNodeTransition transition = new DependencyNodeToNodeTransition(this, node, filter); - if (!transitions.containsKey(node)) { - transitions.put(node, transition); - if (DependencyChecker.shouldLog) { - System.out.println("Connecting " + tag + " to " + node.tag); - } - addConsumer(transition); + if (node == null) { + throw new IllegalArgumentException("Node must not be null"); } + if (transitions != null) { + for (DependencyNodeToNodeTransition transition : transitions) { + if (transition.destination == node) { + return; + } + } + } + DependencyNodeToNodeTransition transition = new DependencyNodeToNodeTransition(this, node, filter); + if (transitions == null) { + transitions = new ArrayList<>(); + } + + transitions.add(transition); + if (DependencyChecker.shouldLog) { + System.out.println("Connecting " + tag + " to " + node.tag); + } + addConsumer(transition); } public void connect(DependencyNode node) { @@ -117,7 +142,8 @@ public class DependencyNode implements ValueDependencyInfo { @Override public DependencyNode getArrayItem() { if (arrayItemNode == null) { - arrayItemNode = new DependencyNode(dependencyChecker, degree + 1); + arrayItemNode = new DependencyNode(dependencyChecker, dependencyChecker.nodes.size(), degree + 1); + dependencyChecker.nodes.add(arrayItemNode); if (DependencyChecker.shouldLog) { arrayItemNode.tag = tag + "["; } diff --git a/teavm-core/src/main/java/org/teavm/dependency/DependencyNodeToNodeTransition.java b/teavm-core/src/main/java/org/teavm/dependency/DependencyNodeToNodeTransition.java index 98543636e..e20b478cf 100644 --- a/teavm-core/src/main/java/org/teavm/dependency/DependencyNodeToNodeTransition.java +++ b/teavm-core/src/main/java/org/teavm/dependency/DependencyNodeToNodeTransition.java @@ -20,8 +20,8 @@ package org.teavm.dependency; * @author Alexey Andreev */ class DependencyNodeToNodeTransition implements DependencyConsumer { - private DependencyNode source; - private DependencyNode destination; + DependencyNode source; + DependencyNode destination; private DependencyTypeFilter filter; public DependencyNodeToNodeTransition(DependencyNode source, DependencyNode destination, diff --git a/teavm-core/src/main/java/org/teavm/model/InstructionReadVisitor.java b/teavm-core/src/main/java/org/teavm/model/InstructionReadVisitor.java index 5d7627469..b5a8ff811 100644 --- a/teavm-core/src/main/java/org/teavm/model/InstructionReadVisitor.java +++ b/teavm-core/src/main/java/org/teavm/model/InstructionReadVisitor.java @@ -153,7 +153,7 @@ class InstructionReadVisitor implements InstructionVisitor { @Override public void visit(PutFieldInstruction insn) { - reader.putField(insn.getInstance(), insn.getField(), insn.getValue()); + reader.putField(insn.getInstance(), insn.getField(), insn.getValue(), insn.getFieldType()); } @Override diff --git a/teavm-core/src/main/java/org/teavm/model/MethodReference.java b/teavm-core/src/main/java/org/teavm/model/MethodReference.java index 66ab8a600..05092683c 100644 --- a/teavm-core/src/main/java/org/teavm/model/MethodReference.java +++ b/teavm-core/src/main/java/org/teavm/model/MethodReference.java @@ -99,6 +99,10 @@ public class MethodReference { return Arrays.copyOf(signature, signature.length); } + public ValueType getReturnType() { + return signature[signature.length - 1]; + } + public String getName() { return name; } diff --git a/teavm-core/src/main/java/org/teavm/model/instructions/InstructionReader.java b/teavm-core/src/main/java/org/teavm/model/instructions/InstructionReader.java index 2b022cf8b..afdea1647 100644 --- a/teavm-core/src/main/java/org/teavm/model/instructions/InstructionReader.java +++ b/teavm-core/src/main/java/org/teavm/model/instructions/InstructionReader.java @@ -79,7 +79,7 @@ public interface InstructionReader { void getField(VariableReader receiver, VariableReader instance, FieldReference field, ValueType fieldType); - void putField(VariableReader instance, FieldReference field, VariableReader value); + void putField(VariableReader instance, FieldReference field, VariableReader value, ValueType fieldType); void arrayLength(VariableReader receiver, VariableReader array); @@ -100,8 +100,8 @@ public interface InstructionReader { void initClass(String className); void nullCheck(VariableReader receiver, VariableReader value); - + void monitorEnter(VariableReader objectRef); - + void monitorExit(VariableReader objectRef); } diff --git a/teavm-core/src/main/java/org/teavm/model/instructions/PutFieldInstruction.java b/teavm-core/src/main/java/org/teavm/model/instructions/PutFieldInstruction.java index 016217576..6308e284f 100644 --- a/teavm-core/src/main/java/org/teavm/model/instructions/PutFieldInstruction.java +++ b/teavm-core/src/main/java/org/teavm/model/instructions/PutFieldInstruction.java @@ -17,6 +17,7 @@ package org.teavm.model.instructions; import org.teavm.model.FieldReference; import org.teavm.model.Instruction; +import org.teavm.model.ValueType; import org.teavm.model.Variable; /** @@ -27,6 +28,7 @@ public class PutFieldInstruction extends Instruction { private Variable instance; private FieldReference field; private Variable value; + private ValueType fieldType; public Variable getInstance() { return instance; @@ -52,6 +54,14 @@ public class PutFieldInstruction extends Instruction { this.value = value; } + public ValueType getFieldType() { + return fieldType; + } + + public void setFieldType(ValueType fieldType) { + this.fieldType = fieldType; + } + @Override public void acceptVisitor(InstructionVisitor visitor) { visitor.visit(this); diff --git a/teavm-core/src/main/java/org/teavm/model/util/AsyncMethodFinder.java b/teavm-core/src/main/java/org/teavm/model/util/AsyncMethodFinder.java index e882cbdf6..610b5ce6b 100644 --- a/teavm-core/src/main/java/org/teavm/model/util/AsyncMethodFinder.java +++ b/teavm-core/src/main/java/org/teavm/model/util/AsyncMethodFinder.java @@ -330,7 +330,8 @@ public class AsyncMethodFinder { } @Override - public void putField(VariableReader instance, FieldReference field, VariableReader value) { + public void putField(VariableReader instance, FieldReference field, VariableReader value, + ValueType fieldType) { } @Override diff --git a/teavm-core/src/main/java/org/teavm/model/util/InstructionStringifier.java b/teavm-core/src/main/java/org/teavm/model/util/InstructionStringifier.java index c3a2a1a54..812b354e7 100644 --- a/teavm-core/src/main/java/org/teavm/model/util/InstructionStringifier.java +++ b/teavm-core/src/main/java/org/teavm/model/util/InstructionStringifier.java @@ -280,7 +280,7 @@ public class InstructionStringifier implements InstructionReader { } @Override - public void putField(VariableReader instance, FieldReference field, VariableReader value) { + public void putField(VariableReader instance, FieldReference field, VariableReader value, ValueType fieldType) { if (instance != null) { sb.append("@").append(instance.getIndex()); } else { diff --git a/teavm-core/src/main/java/org/teavm/model/util/ProgramUtils.java b/teavm-core/src/main/java/org/teavm/model/util/ProgramUtils.java index 4f5a2b80e..357bb68d1 100644 --- a/teavm-core/src/main/java/org/teavm/model/util/ProgramUtils.java +++ b/teavm-core/src/main/java/org/teavm/model/util/ProgramUtils.java @@ -398,11 +398,13 @@ public final class ProgramUtils { } @Override - public void putField(VariableReader instance, FieldReference field, VariableReader value) { + public void putField(VariableReader instance, FieldReference field, VariableReader value, + ValueType fieldType) { PutFieldInstruction insnCopy = new PutFieldInstruction(); insnCopy.setField(field); insnCopy.setInstance(instance != null ? copyVar(instance) : null); insnCopy.setValue(copyVar(value)); + insnCopy.setFieldType(fieldType); copy = insnCopy; copy.setLocation(location); } diff --git a/teavm-core/src/main/java/org/teavm/parsing/ProgramParser.java b/teavm-core/src/main/java/org/teavm/parsing/ProgramParser.java index 8a9f92ea4..a379c459a 100644 --- a/teavm-core/src/main/java/org/teavm/parsing/ProgramParser.java +++ b/teavm-core/src/main/java/org/teavm/parsing/ProgramParser.java @@ -1568,7 +1568,7 @@ public class ProgramParser implements VariableDebugInformation { addInstruction(insn); break; } - + } } @@ -1611,6 +1611,7 @@ public class ProgramParser implements VariableDebugInformation { insn.setInstance(getVariable(instance)); insn.setField(new FieldReference(ownerCls, name)); insn.setValue(getVariable(value)); + insn.setFieldType(ValueType.parse(desc)); addInstruction(insn); break; } diff --git a/teavm-core/src/main/java/org/teavm/tooling/ProgramSourceAggregator.java b/teavm-core/src/main/java/org/teavm/tooling/ProgramSourceAggregator.java index 9dc33d3d6..c2e5fb3bc 100644 --- a/teavm-core/src/main/java/org/teavm/tooling/ProgramSourceAggregator.java +++ b/teavm-core/src/main/java/org/teavm/tooling/ProgramSourceAggregator.java @@ -77,7 +77,8 @@ class ProgramSourceAggregator implements InstructionReader { @Override public void create(VariableReader receiver, String type) { } @Override public void getField(VariableReader receiver, VariableReader instance, FieldReference field, ValueType fieldType) { } - @Override public void putField(VariableReader instance, FieldReference field, VariableReader value) { } + @Override public void putField(VariableReader instance, FieldReference field, VariableReader value, + ValueType fieldType) { } @Override public void arrayLength(VariableReader receiver, VariableReader array) { } @Override public void cloneArray(VariableReader receiver, VariableReader array) { } @Override public void unwrapArray(VariableReader receiver, VariableReader array, ArrayElementType elementType) { } @@ -91,11 +92,11 @@ class ProgramSourceAggregator implements InstructionReader { @Override public void monitorEnter(VariableReader objectRef) { - + } @Override public void monitorExit(VariableReader objectRef) { - + } }