Refactoring RTTI, add type annotation to array subscription instructions

This commit is contained in:
Alexey Andreev 2016-08-15 18:49:24 +03:00
parent 73d4a389b7
commit 164ebeb629
31 changed files with 246 additions and 195 deletions

View File

@ -0,0 +1,27 @@
/*
* Copyright 2016 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.ast;
public enum ArrayType {
BYTE,
SHORT,
CHAR,
INT,
LONG,
FLOAT,
DOUBLE,
OBJECT
}

View File

@ -75,10 +75,11 @@ public abstract class Expr implements Cloneable {
return result; return result;
} }
public static Expr subscript(Expr array, Expr index) { public static Expr subscript(Expr array, Expr index, ArrayType type) {
SubscriptExpr expr = new SubscriptExpr(); SubscriptExpr expr = new SubscriptExpr();
expr.setArray(array); expr.setArray(array);
expr.setIndex(index); expr.setIndex(index);
expr.setType(type);
return expr; return expr;
} }

View File

@ -17,13 +17,10 @@ package org.teavm.ast;
import java.util.Map; import java.util.Map;
/**
*
* @author Alexey Andreev
*/
public class SubscriptExpr extends Expr { public class SubscriptExpr extends Expr {
private Expr array; private Expr array;
private Expr index; private Expr index;
private ArrayType type;
public Expr getArray() { public Expr getArray() {
return array; return array;
@ -41,6 +38,14 @@ public class SubscriptExpr extends Expr {
this.index = index; this.index = index;
} }
public ArrayType getType() {
return type;
}
public void setType(ArrayType type) {
this.type = type;
}
@Override @Override
public void acceptVisitor(ExprVisitor visitor) { public void acceptVisitor(ExprVisitor visitor) {
visitor.visit(this); visitor.visit(this);
@ -55,6 +60,7 @@ public class SubscriptExpr extends Expr {
SubscriptExpr copy = new SubscriptExpr(); SubscriptExpr copy = new SubscriptExpr();
copy.setArray(array != null ? array.clone(cache) : null); copy.setArray(array != null ? array.clone(cache) : null);
copy.setIndex(index != null ? index.clone(cache) : null); copy.setIndex(index != null ? index.clone(cache) : null);
copy.setType(type);
return copy; return copy;
} }
} }

View File

@ -21,6 +21,7 @@ import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.teavm.ast.ArrayType;
import org.teavm.ast.AssignmentStatement; import org.teavm.ast.AssignmentStatement;
import org.teavm.ast.BinaryOperation; import org.teavm.ast.BinaryOperation;
import org.teavm.ast.BreakStatement; import org.teavm.ast.BreakStatement;
@ -49,6 +50,7 @@ import org.teavm.model.MethodReference;
import org.teavm.model.Program; import org.teavm.model.Program;
import org.teavm.model.ValueType; import org.teavm.model.ValueType;
import org.teavm.model.Variable; import org.teavm.model.Variable;
import org.teavm.model.instructions.ArrayElementType;
import org.teavm.model.instructions.ArrayLengthInstruction; import org.teavm.model.instructions.ArrayLengthInstruction;
import org.teavm.model.instructions.AssignInstruction; import org.teavm.model.instructions.AssignInstruction;
import org.teavm.model.instructions.BinaryBranchingInstruction; import org.teavm.model.instructions.BinaryBranchingInstruction;
@ -442,18 +444,42 @@ class StatementGenerator implements InstructionVisitor {
@Override @Override
public void visit(GetElementInstruction insn) { public void visit(GetElementInstruction insn) {
assign(Expr.subscript(Expr.var(insn.getArray().getIndex()), Expr.var(insn.getIndex().getIndex())), Expr subscript = Expr.subscript(Expr.var(insn.getArray().getIndex()), Expr.var(insn.getIndex().getIndex()),
insn.getReceiver()); map(insn.getType()));
assign(subscript, insn.getReceiver());
} }
@Override @Override
public void visit(PutElementInstruction insn) { public void visit(PutElementInstruction insn) {
AssignmentStatement stmt = Statement.assign(Expr.subscript(Expr.var(insn.getArray().getIndex()), Expr subscript = Expr.subscript(Expr.var(insn.getArray().getIndex()),
Expr.var(insn.getIndex().getIndex())), Expr.var(insn.getValue().getIndex())); Expr.var(insn.getIndex().getIndex()), map(insn.getType()));
AssignmentStatement stmt = Statement.assign(subscript, Expr.var(insn.getValue().getIndex()));
stmt.setLocation(currentLocation); stmt.setLocation(currentLocation);
statements.add(stmt); statements.add(stmt);
} }
private static ArrayType map(ArrayElementType type) {
switch (type) {
case BYTE:
return ArrayType.BYTE;
case SHORT:
return ArrayType.SHORT;
case CHAR:
return ArrayType.SHORT;
case INT:
return ArrayType.INT;
case LONG:
return ArrayType.LONG;
case FLOAT:
return ArrayType.FLOAT;
case DOUBLE:
return ArrayType.DOUBLE;
case OBJECT:
return ArrayType.OBJECT;
}
throw new AssertionError();
}
@Override @Override
public void visit(InvokeInstruction insn) { public void visit(InvokeInstruction insn) {
Expr[] exprArgs = new Expr[insn.getMethod().getParameterTypes().length]; Expr[] exprArgs = new Expr[insn.getMethod().getParameterTypes().length];

View File

@ -24,6 +24,7 @@ import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import org.teavm.ast.ArrayType;
import org.teavm.ast.AssignmentStatement; import org.teavm.ast.AssignmentStatement;
import org.teavm.ast.AsyncMethodNode; import org.teavm.ast.AsyncMethodNode;
import org.teavm.ast.AsyncMethodPart; import org.teavm.ast.AsyncMethodPart;
@ -509,6 +510,7 @@ public class AstIO {
output.writeByte(11); output.writeByte(11);
writeExpr(expr.getArray()); writeExpr(expr.getArray());
writeExpr(expr.getIndex()); writeExpr(expr.getIndex());
output.writeByte(expr.getType().ordinal());
} catch (IOException e) { } catch (IOException e) {
throw new IOExceptionWrapper(e); throw new IOExceptionWrapper(e);
} }
@ -899,6 +901,7 @@ public class AstIO {
SubscriptExpr expr = new SubscriptExpr(); SubscriptExpr expr = new SubscriptExpr();
expr.setArray(readExpr(input)); expr.setArray(readExpr(input));
expr.setIndex(readExpr(input)); expr.setIndex(readExpr(input));
expr.setType(ArrayType.values()[input.readByte()]);
return expr; return expr;
} }
case 12: { case 12: {

View File

@ -536,6 +536,7 @@ public class ProgramIO {
public void visit(GetElementInstruction insn) { public void visit(GetElementInstruction insn) {
try { try {
output.writeByte(31); output.writeByte(31);
output.writeByte(insn.getType().ordinal());
output.writeShort(insn.getReceiver().getIndex()); output.writeShort(insn.getReceiver().getIndex());
output.writeShort(insn.getArray().getIndex()); output.writeShort(insn.getArray().getIndex());
output.writeShort(insn.getIndex().getIndex()); output.writeShort(insn.getIndex().getIndex());
@ -548,6 +549,7 @@ public class ProgramIO {
public void visit(PutElementInstruction insn) { public void visit(PutElementInstruction insn) {
try { try {
output.writeByte(32); output.writeByte(32);
output.writeByte(insn.getType().ordinal());
output.writeShort(insn.getArray().getIndex()); output.writeShort(insn.getArray().getIndex());
output.writeShort(insn.getIndex().getIndex()); output.writeShort(insn.getIndex().getIndex());
output.writeShort(insn.getValue().getIndex()); output.writeShort(insn.getValue().getIndex());
@ -965,14 +967,14 @@ public class ProgramIO {
return insn; return insn;
} }
case 31: { case 31: {
GetElementInstruction insn = new GetElementInstruction(); GetElementInstruction insn = new GetElementInstruction(arrayElementTypes[input.readByte()]);
insn.setReceiver(program.variableAt(input.readShort())); insn.setReceiver(program.variableAt(input.readShort()));
insn.setArray(program.variableAt(input.readShort())); insn.setArray(program.variableAt(input.readShort()));
insn.setIndex(program.variableAt(input.readShort())); insn.setIndex(program.variableAt(input.readShort()));
return insn; return insn;
} }
case 32: { case 32: {
PutElementInstruction insn = new PutElementInstruction(); PutElementInstruction insn = new PutElementInstruction(arrayElementTypes[input.readByte()]);
insn.setArray(program.variableAt(input.readShort())); insn.setArray(program.variableAt(input.readShort()));
insn.setIndex(program.variableAt(input.readShort())); insn.setIndex(program.variableAt(input.readShort()));
insn.setValue(program.variableAt(input.readShort())); insn.setValue(program.variableAt(input.readShort()));

View File

@ -284,12 +284,13 @@ public class DataFlowGraphBuilder implements InstructionReader {
} }
@Override @Override
public void getElement(VariableReader receiver, VariableReader array, VariableReader index) { public void getElement(VariableReader receiver, VariableReader array, VariableReader index,
ArrayElementType type) {
builder.addEdge(array.getIndex(), receiver.getIndex()); builder.addEdge(array.getIndex(), receiver.getIndex());
} }
@Override @Override
public void putElement(VariableReader array, VariableReader index, VariableReader value) { public void putElement(VariableReader array, VariableReader index, VariableReader value, ArrayElementType type) {
builder.addEdge(value.getIndex(), array.getIndex()); builder.addEdge(value.getIndex(), array.getIndex());
} }

View File

@ -655,7 +655,8 @@ class DependencyGraphBuilder {
} }
@Override @Override
public void getElement(VariableReader receiver, VariableReader array, VariableReader index) { public void getElement(VariableReader receiver, VariableReader array, VariableReader index,
ArrayElementType type) {
DependencyNode arrayNode = nodes[array.getIndex()]; DependencyNode arrayNode = nodes[array.getIndex()];
DependencyNode receiverNode = nodes[receiver.getIndex()]; DependencyNode receiverNode = nodes[receiver.getIndex()];
if (arrayNode != null && receiverNode != null && receiverNode != arrayNode.getArrayItem()) { if (arrayNode != null && receiverNode != null && receiverNode != arrayNode.getArrayItem()) {
@ -664,7 +665,8 @@ class DependencyGraphBuilder {
} }
@Override @Override
public void putElement(VariableReader array, VariableReader index, VariableReader value) { public void putElement(VariableReader array, VariableReader index, VariableReader value,
ArrayElementType type) {
DependencyNode valueNode = nodes[value.getIndex()]; DependencyNode valueNode = nodes[value.getIndex()];
DependencyNode arrayNode = nodes[array.getIndex()]; DependencyNode arrayNode = nodes[array.getIndex()];
if (valueNode != null && arrayNode != null && valueNode != arrayNode.getArrayItem()) { if (valueNode != null && arrayNode != null && valueNode != arrayNode.getArrayItem()) {

View File

@ -173,12 +173,12 @@ class InstructionReadVisitor implements InstructionVisitor {
@Override @Override
public void visit(GetElementInstruction insn) { public void visit(GetElementInstruction insn) {
reader.getElement(insn.getReceiver(), insn.getArray(), insn.getIndex()); reader.getElement(insn.getReceiver(), insn.getArray(), insn.getIndex(), insn.getType());
} }
@Override @Override
public void visit(PutElementInstruction insn) { public void visit(PutElementInstruction insn) {
reader.putElement(insn.getArray(), insn.getIndex(), insn.getValue()); reader.putElement(insn.getArray(), insn.getIndex(), insn.getValue(), insn.getType());
} }
@Override @Override

View File

@ -696,14 +696,16 @@ public class Interpreter {
} }
@Override @Override
public void getElement(VariableReader receiver, VariableReader array, VariableReader index) { public void getElement(VariableReader receiver, VariableReader array, VariableReader index,
ArrayElementType type) {
Object jvmArray = variables[array.getIndex()]; Object jvmArray = variables[array.getIndex()];
int indexValue = (Integer) variables[index.getIndex()]; int indexValue = (Integer) variables[index.getIndex()];
variables[receiver.getIndex()] = Array.get(jvmArray, indexValue); variables[receiver.getIndex()] = Array.get(jvmArray, indexValue);
} }
@Override @Override
public void putElement(VariableReader array, VariableReader index, VariableReader value) { public void putElement(VariableReader array, VariableReader index, VariableReader value,
ArrayElementType type) {
Object jvmArray = variables[array.getIndex()]; Object jvmArray = variables[array.getIndex()];
int indexValue = (Integer) variables[index.getIndex()]; int indexValue = (Integer) variables[index.getIndex()];
Array.set(jvmArray, indexValue, variables[value.getIndex()]); Array.set(jvmArray, indexValue, variables[value.getIndex()]);

View File

@ -844,7 +844,8 @@ public class ValueEmitter {
ValueEmitter array = unwrapArray(); ValueEmitter array = unwrapArray();
Variable result = pe.getProgram().createVariable(); Variable result = pe.getProgram().createVariable();
GetElementInstruction insn = new GetElementInstruction(); ValueType.Array arrayType = (ValueType.Array) array.getType();
GetElementInstruction insn = new GetElementInstruction(getArrayElementType(arrayType.getItemType()));
insn.setArray(array.variable); insn.setArray(array.variable);
insn.setIndex(index.widenToInteger().variable); insn.setIndex(index.widenToInteger().variable);
insn.setReceiver(result); insn.setReceiver(result);
@ -861,7 +862,7 @@ public class ValueEmitter {
throw new EmitException("Can't set element of non-array type: " + type); throw new EmitException("Can't set element of non-array type: " + type);
} }
PutElementInstruction insn = new PutElementInstruction(); PutElementInstruction insn = new PutElementInstruction(getArrayElementType(value.getType()));
insn.setArray(unwrapArray().variable); insn.setArray(unwrapArray().variable);
insn.setIndex(index.widenToInteger().variable); insn.setIndex(index.widenToInteger().variable);
insn.setValue(value.variable); insn.setValue(value.variable);

View File

@ -18,15 +18,20 @@ package org.teavm.model.instructions;
import org.teavm.model.Instruction; import org.teavm.model.Instruction;
import org.teavm.model.Variable; import org.teavm.model.Variable;
/**
*
* @author Alexey Andreev
*/
public class GetElementInstruction extends Instruction { public class GetElementInstruction extends Instruction {
private ArrayElementType type;
private Variable array; private Variable array;
private Variable index; private Variable index;
private Variable receiver; private Variable receiver;
public GetElementInstruction(ArrayElementType type) {
this.type = type;
}
public ArrayElementType getType() {
return type;
}
public Variable getArray() { public Variable getArray() {
return array; return array;
} }

View File

@ -18,10 +18,6 @@ package org.teavm.model.instructions;
import java.util.List; import java.util.List;
import org.teavm.model.*; import org.teavm.model.*;
/**
*
* @author Alexey Andreev
*/
public interface InstructionReader { public interface InstructionReader {
void location(InstructionLocation location); void location(InstructionLocation location);
@ -87,9 +83,9 @@ public interface InstructionReader {
void unwrapArray(VariableReader receiver, VariableReader array, ArrayElementType elementType); void unwrapArray(VariableReader receiver, VariableReader array, ArrayElementType elementType);
void getElement(VariableReader receiver, VariableReader array, VariableReader index); void getElement(VariableReader receiver, VariableReader array, VariableReader index, ArrayElementType elementType);
void putElement(VariableReader array, VariableReader index, VariableReader value); void putElement(VariableReader array, VariableReader index, VariableReader value, ArrayElementType elementType);
void invoke(VariableReader receiver, VariableReader instance, MethodReference method, void invoke(VariableReader receiver, VariableReader instance, MethodReference method,
List<? extends VariableReader> arguments, InvocationType type); List<? extends VariableReader> arguments, InvocationType type);

View File

@ -18,15 +18,20 @@ package org.teavm.model.instructions;
import org.teavm.model.Instruction; import org.teavm.model.Instruction;
import org.teavm.model.Variable; import org.teavm.model.Variable;
/**
*
* @author Alexey Andreev
*/
public class PutElementInstruction extends Instruction { public class PutElementInstruction extends Instruction {
private ArrayElementType type;
private Variable array; private Variable array;
private Variable index; private Variable index;
private Variable value; private Variable value;
public PutElementInstruction(ArrayElementType type) {
this.type = type;
}
public ArrayElementType getType() {
return type;
}
public Variable getArray() { public Variable getArray() {
return array; return array;
} }

View File

@ -362,11 +362,13 @@ public class AsyncMethodFinder {
} }
@Override @Override
public void getElement(VariableReader receiver, VariableReader array, VariableReader index) { public void getElement(VariableReader receiver, VariableReader array, VariableReader index,
ArrayElementType type) {
} }
@Override @Override
public void putElement(VariableReader array, VariableReader index, VariableReader value) { public void putElement(VariableReader array, VariableReader index, VariableReader value,
ArrayElementType type) {
} }
@Override @Override

View File

@ -386,8 +386,9 @@ public class InstructionCopyReader implements InstructionReader {
} }
@Override @Override
public void getElement(VariableReader receiver, VariableReader array, VariableReader index) { public void getElement(VariableReader receiver, VariableReader array, VariableReader index,
GetElementInstruction insnCopy = new GetElementInstruction(); ArrayElementType type) {
GetElementInstruction insnCopy = new GetElementInstruction(type);
insnCopy.setArray(copyVar(array)); insnCopy.setArray(copyVar(array));
insnCopy.setReceiver(copyVar(receiver)); insnCopy.setReceiver(copyVar(receiver));
insnCopy.setIndex(copyVar(index)); insnCopy.setIndex(copyVar(index));
@ -396,8 +397,8 @@ public class InstructionCopyReader implements InstructionReader {
} }
@Override @Override
public void putElement(VariableReader array, VariableReader index, VariableReader value) { public void putElement(VariableReader array, VariableReader index, VariableReader value, ArrayElementType type) {
PutElementInstruction insnCopy = new PutElementInstruction(); PutElementInstruction insnCopy = new PutElementInstruction(type);
insnCopy.setArray(copyVar(array)); insnCopy.setArray(copyVar(array));
insnCopy.setValue(copyVar(value)); insnCopy.setValue(copyVar(value));
insnCopy.setIndex(copyVar(index)); insnCopy.setIndex(copyVar(index));

View File

@ -307,13 +307,14 @@ public class InstructionStringifier implements InstructionReader {
} }
@Override @Override
public void getElement(VariableReader receiver, VariableReader array, VariableReader index) { public void getElement(VariableReader receiver, VariableReader array, VariableReader index,
ArrayElementType type) {
sb.append("@").append(receiver.getIndex()).append(" := @").append(array.getIndex()).append("[@") sb.append("@").append(receiver.getIndex()).append(" := @").append(array.getIndex()).append("[@")
.append(index.getIndex()).append("]"); .append(index.getIndex()).append("]");
} }
@Override @Override
public void putElement(VariableReader array, VariableReader index, VariableReader value) { public void putElement(VariableReader array, VariableReader index, VariableReader value, ArrayElementType type) {
sb.append("@").append(array.getIndex()).append("[@").append(index.getIndex()).append("] := @") sb.append("@").append(array.getIndex()).append("[@").append(index.getIndex()).append("] := @")
.append(value.getIndex()); .append(value.getIndex());
} }

View File

@ -234,7 +234,8 @@ public class TypeInferer {
} }
@Override @Override
public void putElement(VariableReader array, VariableReader index, VariableReader value) { public void putElement(VariableReader array, VariableReader index, VariableReader value,
ArrayElementType type) {
} }
@Override @Override
@ -325,7 +326,8 @@ public class TypeInferer {
} }
@Override @Override
public void getElement(VariableReader receiver, VariableReader array, VariableReader index) { public void getElement(VariableReader receiver, VariableReader array, VariableReader index,
ArrayElementType type) {
arrayElemBuilder.addEdge(array.getIndex(), receiver.getIndex()); arrayElemBuilder.addEdge(array.getIndex(), receiver.getIndex());
} }

View File

@ -905,7 +905,7 @@ public class ProgramParser {
unwrapInsn.setArray(getVariable(array)); unwrapInsn.setArray(getVariable(array));
unwrapInsn.setReceiver(unwrapInsn.getArray()); unwrapInsn.setReceiver(unwrapInsn.getArray());
addInstruction(unwrapInsn); addInstruction(unwrapInsn);
GetElementInstruction insn = new GetElementInstruction(); GetElementInstruction insn = new GetElementInstruction(type);
insn.setArray(getVariable(array)); insn.setArray(getVariable(array));
insn.setIndex(getVariable(arrIndex)); insn.setIndex(getVariable(arrIndex));
insn.setReceiver(getVariable(var)); insn.setReceiver(getVariable(var));
@ -920,7 +920,7 @@ public class ProgramParser {
unwrapInsn.setArray(getVariable(array)); unwrapInsn.setArray(getVariable(array));
unwrapInsn.setReceiver(unwrapInsn.getArray()); unwrapInsn.setReceiver(unwrapInsn.getArray());
addInstruction(unwrapInsn); addInstruction(unwrapInsn);
PutElementInstruction insn = new PutElementInstruction(); PutElementInstruction insn = new PutElementInstruction(type);
insn.setArray(getVariable(array)); insn.setArray(getVariable(array));
insn.setIndex(getVariable(arrIndex)); insn.setIndex(getVariable(arrIndex));
insn.setValue(getVariable(value)); insn.setValue(getVariable(value));

View File

@ -33,16 +33,14 @@ public final class Allocator {
return result; return result;
} }
public static Address allocateArray(RuntimeClass tag, int size, byte depth) { public static Address allocateArray(RuntimeClass tag, int size) {
Address result = address; Address result = address;
int sizeInBytes = (size + 1) * 4 + Structure.sizeOf(RuntimeArray.class); int sizeInBytes = tag.size * 4 + Structure.sizeOf(RuntimeArray.class);
address = result.add(sizeInBytes); address = result.add(sizeInBytes);
RuntimeArray array = result.toStructure(); RuntimeArray array = result.toStructure();
array.classReference = RuntimeClass.getArrayClass().toAddress().toInt() >> 3; array.classReference = tag.toAddress().toInt() >> 3;
array.componentClassReference = tag.toAddress().toInt() >> 3;
array.size = size; array.size = size;
address.add(Structure.sizeOf(RuntimeArray.class)).putByte(depth);
return result; return result;
} }

View File

@ -16,6 +16,5 @@
package org.teavm.runtime; package org.teavm.runtime;
public class RuntimeArray extends RuntimeObject { public class RuntimeArray extends RuntimeObject {
public int componentClassReference;
int size; int size;
} }

View File

@ -19,20 +19,14 @@ import org.teavm.interop.Structure;
public class RuntimeClass extends Structure { public class RuntimeClass extends Structure {
public static int INITIALIZED = 1; public static int INITIALIZED = 1;
public static int PRIMITIVE = 1;
public static int BOOLEAN_CLASS = -1;
public static int BYTE_CLASS = -2;
public static int SHORT_CLASS = -3;
public static int CHAR_CLASS = -4;
public static int INT_CLASS = -5;
public static int LONG_CLASS = -6;
public static int FLOAT_CLASS = -7;
public static int DOUBLE_CLASS = -8;
public int size; public int size;
public int flags; public int flags;
public int tag; public int tag;
public int canary; public int canary;
public RuntimeClass itemType;
public RuntimeClass arrayType;
public static int computeCanary(int size, int tag) { public static int computeCanary(int size, int tag) {
return size ^ (tag << 8) ^ (tag >>> 24) ^ (0xAAAAAAAA); return size ^ (tag << 8) ^ (tag >>> 24) ^ (0xAAAAAAAA);
@ -41,6 +35,4 @@ public class RuntimeClass extends Structure {
public int computeCanary() { public int computeCanary() {
return computeCanary(size, tag); return computeCanary(size, tag);
} }
public static native RuntimeClass getArrayClass();
} }

View File

@ -43,6 +43,7 @@ import org.teavm.model.MethodHolder;
import org.teavm.model.MethodReader; import org.teavm.model.MethodReader;
import org.teavm.model.MethodReference; import org.teavm.model.MethodReference;
import org.teavm.model.Program; import org.teavm.model.Program;
import org.teavm.model.ValueType;
import org.teavm.model.classes.TagRegistry; import org.teavm.model.classes.TagRegistry;
import org.teavm.model.classes.VirtualTableProvider; import org.teavm.model.classes.VirtualTableProvider;
import org.teavm.model.instructions.InvocationType; import org.teavm.model.instructions.InvocationType;
@ -62,7 +63,6 @@ import org.teavm.wasm.generate.WasmGenerationContext;
import org.teavm.wasm.generate.WasmGenerator; import org.teavm.wasm.generate.WasmGenerator;
import org.teavm.wasm.generate.WasmMangling; import org.teavm.wasm.generate.WasmMangling;
import org.teavm.wasm.intrinsics.WasmAddressIntrinsic; import org.teavm.wasm.intrinsics.WasmAddressIntrinsic;
import org.teavm.wasm.intrinsics.WasmRuntimeClassIntrinsic;
import org.teavm.wasm.intrinsics.WasmRuntimeIntrinsic; import org.teavm.wasm.intrinsics.WasmRuntimeIntrinsic;
import org.teavm.wasm.intrinsics.WasmStructureIntrinsic; import org.teavm.wasm.intrinsics.WasmStructureIntrinsic;
import org.teavm.wasm.model.WasmFunction; import org.teavm.wasm.model.WasmFunction;
@ -118,7 +118,7 @@ public class WasmTarget implements TeaVMTarget {
dependencyChecker.linkMethod(new MethodReference(Allocator.class, "allocate", dependencyChecker.linkMethod(new MethodReference(Allocator.class, "allocate",
RuntimeClass.class, Address.class), null).use(); RuntimeClass.class, Address.class), null).use();
dependencyChecker.linkMethod(new MethodReference(Allocator.class, "allocateArray", dependencyChecker.linkMethod(new MethodReference(Allocator.class, "allocateArray",
RuntimeClass.class, int.class, byte.class, Address.class), null).use(); RuntimeClass.class, int.class, Address.class), null).use();
dependencyChecker.linkMethod(new MethodReference(Allocator.class, "<clinit>", void.class), null).use(); dependencyChecker.linkMethod(new MethodReference(Allocator.class, "<clinit>", void.class), null).use();
} }
@ -131,22 +131,14 @@ public class WasmTarget implements TeaVMTarget {
VirtualTableProvider vtableProvider = createVirtualTableProvider(classes); VirtualTableProvider vtableProvider = createVirtualTableProvider(classes);
TagRegistry tagRegistry = new TagRegistry(classes); TagRegistry tagRegistry = new TagRegistry(classes);
BinaryWriter binaryWriter = new BinaryWriter(256); BinaryWriter binaryWriter = new BinaryWriter(256);
WasmClassGenerator classGenerator = new WasmClassGenerator(classes, vtableProvider, tagRegistry, WasmClassGenerator classGenerator = new WasmClassGenerator(controller.getUnprocessedClassSource(),
binaryWriter); vtableProvider, tagRegistry, binaryWriter);
for (String className : classes.getClassNames()) {
classGenerator.addClass(className);
if (controller.wasCancelled()) {
return;
}
}
classGenerator.addArrayClass();
Decompiler decompiler = new Decompiler(classes, controller.getClassLoader(), new HashSet<>(), Decompiler decompiler = new Decompiler(classes, controller.getClassLoader(), new HashSet<>(),
new HashSet<>()); new HashSet<>());
WasmGenerationContext context = new WasmGenerationContext(classes, vtableProvider, tagRegistry); WasmGenerationContext context = new WasmGenerationContext(classes, vtableProvider, tagRegistry);
context.addIntrinsic(new WasmAddressIntrinsic()); context.addIntrinsic(new WasmAddressIntrinsic());
context.addIntrinsic(new WasmRuntimeClassIntrinsic(classGenerator));
context.addIntrinsic(new WasmStructureIntrinsic(classGenerator)); context.addIntrinsic(new WasmStructureIntrinsic(classGenerator));
context.addIntrinsic(new WasmRuntimeIntrinsic()); context.addIntrinsic(new WasmRuntimeIntrinsic());
@ -263,7 +255,7 @@ public class WasmTarget implements TeaVMTarget {
WasmBlock block = new WasmBlock(false); WasmBlock block = new WasmBlock(false);
int index = classGenerator.getClassPointer(className); int index = classGenerator.getClassPointer(ValueType.object(className));
WasmExpression initFlag = new WasmLoadInt32(4, new WasmInt32Constant(index), WasmInt32Subtype.INT32); WasmExpression initFlag = new WasmLoadInt32(4, new WasmInt32Constant(index), WasmInt32Subtype.INT32);
initFlag = new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.AND, initFlag, initFlag = new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.AND, initFlag,
new WasmInt32Constant(RuntimeClass.INITIALIZED)); new WasmInt32Constant(RuntimeClass.INITIALIZED));

View File

@ -45,8 +45,7 @@ import org.teavm.wasm.binary.DataValue;
public class WasmClassGenerator { public class WasmClassGenerator {
private ClassReaderSource classSource; private ClassReaderSource classSource;
private Map<String, ClassBinaryData> binaryDataMap = new LinkedHashMap<>(); private Map<ValueType, ClassBinaryData> binaryDataMap = new LinkedHashMap<>();
private ClassBinaryData arrayClassData;
private BinaryWriter binaryWriter; private BinaryWriter binaryWriter;
private Map<MethodReference, Integer> functions = new HashMap<>(); private Map<MethodReference, Integer> functions = new HashMap<>();
private List<String> functionTable = new ArrayList<>(); private List<String> functionTable = new ArrayList<>();
@ -57,7 +56,9 @@ public class WasmClassGenerator {
DataPrimitives.INT, /* size */ DataPrimitives.INT, /* size */
DataPrimitives.INT, /* flags */ DataPrimitives.INT, /* flags */
DataPrimitives.INT, /* tag */ DataPrimitives.INT, /* tag */
DataPrimitives.INT /* canary */); DataPrimitives.INT, /* canary */
DataPrimitives.ADDRESS, /* item type */
DataPrimitives.ADDRESS /* array type */);
public WasmClassGenerator(ClassReaderSource classSource, VirtualTableProvider vtableProvider, public WasmClassGenerator(ClassReaderSource classSource, VirtualTableProvider vtableProvider,
TagRegistry tagRegistry, BinaryWriter binaryWriter) { TagRegistry tagRegistry, BinaryWriter binaryWriter) {
@ -67,31 +68,69 @@ public class WasmClassGenerator {
this.binaryWriter = binaryWriter; this.binaryWriter = binaryWriter;
} }
public void addClass(String className) { private void addClass(ValueType type) {
if (binaryDataMap.containsKey(className)) { if (binaryDataMap.containsKey(type)) {
return; return;
} }
ClassReader cls = classSource.get(className);
ClassBinaryData binaryData = new ClassBinaryData(); ClassBinaryData binaryData = new ClassBinaryData();
binaryData.name = className; binaryData.type = type;
binaryDataMap.put(className, binaryData); binaryDataMap.put(type, binaryData);
calculateLayout(cls, binaryData); if (type instanceof ValueType.Primitive) {
if (binaryData.start < 0) { int size = 0;
return; switch (((ValueType.Primitive) type).getKind()) {
case BOOLEAN:
case BYTE:
size = 1;
break;
case SHORT:
case CHARACTER:
size = 2;
break;
case INTEGER:
case FLOAT:
size = 4;
break;
case LONG:
case DOUBLE:
size = 5;
break;
}
binaryData.data = createPrimitiveClassData(size);
binaryData.start = binaryWriter.append(binaryData.data);
} else if (type == ValueType.VOID) {
binaryData.data = createPrimitiveClassData(0);
binaryData.start = binaryWriter.append(binaryData.data);
} else if (type instanceof ValueType.Object) {
String className = ((ValueType.Object) type).getClassName();
ClassReader cls = classSource.get(className);
calculateLayout(cls, binaryData);
if (binaryData.start >= 0) {
binaryData.start = binaryWriter.append(createStructure(binaryData));
}
} else if (type instanceof ValueType.Array) {
ValueType itemType = ((ValueType.Array) type).getItemType();
addClass(itemType);
ClassBinaryData itemBinaryData = binaryDataMap.get(itemType);
binaryData.size = 4;
binaryData.data = classStructure.createValue();
binaryData.data.setInt(0, 4);
binaryData.data.setAddress(4, itemBinaryData.start);
binaryData.start = binaryWriter.append(binaryData.data);
itemBinaryData.data.setAddress(5, binaryData.start);
} }
binaryData.start = binaryWriter.append(createStructure(binaryData));
} }
public void addArrayClass() { private DataValue createPrimitiveClassData(int size) {
if (arrayClassData != null) { DataValue value = classStructure.createValue();
return; value.setInt(0, size);
} value.setInt(1, RuntimeClass.PRIMITIVE);
return value;
arrayClassData = new ClassBinaryData();
arrayClassData.start = binaryWriter.append(classStructure.createValue());
} }
public List<String> getFunctionTable() { public List<String> getFunctionTable() {
@ -99,16 +138,19 @@ public class WasmClassGenerator {
} }
private DataValue createStructure(ClassBinaryData binaryData) { private DataValue createStructure(ClassBinaryData binaryData) {
VirtualTable vtable = vtableProvider.lookup(binaryData.name); String name = ((ValueType.Object) binaryData.type).getClassName();
VirtualTable vtable = vtableProvider.lookup(name);
int vtableSize = vtable != null ? vtable.getEntries().size() : 0; int vtableSize = vtable != null ? vtable.getEntries().size() : 0;
DataType arrayType = new DataArray(DataPrimitives.INT, vtableSize); DataType arrayType = new DataArray(DataPrimitives.INT, vtableSize);
DataValue wrapper = new DataStructure((byte) 0, classStructure, arrayType).createValue(); DataValue wrapper = new DataStructure((byte) 0, classStructure, arrayType).createValue();
DataValue array = wrapper.getValue(1); DataValue array = wrapper.getValue(1);
DataValue header = wrapper.getValue(0); DataValue header = wrapper.getValue(0);
binaryData.data = header;
header.setInt(0, binaryData.size); header.setInt(0, binaryData.size);
List<TagRegistry.Range> ranges = tagRegistry.getRanges(binaryData.name); List<TagRegistry.Range> ranges = tagRegistry.getRanges(name);
int tag = ranges.stream().mapToInt(range -> range.lower).min().orElse(0); int tag = ranges.stream().mapToInt(range -> range.lower).min().orElse(0);
header.setInt(2, tag); header.setInt(2, tag);
header.setInt(3, RuntimeClass.computeCanary(binaryData.size, tag)); header.setInt(3, RuntimeClass.computeCanary(binaryData.size, tag));
@ -135,27 +177,30 @@ public class WasmClassGenerator {
return wrapper; return wrapper;
} }
public int getClassPointer(String className) { public int getClassPointer(ValueType type) {
ClassBinaryData data = binaryDataMap.get(className); addClass(type);
ClassBinaryData data = binaryDataMap.get(type);
return data.start; return data.start;
} }
public int getFieldOffset(FieldReference field) { public int getFieldOffset(FieldReference field) {
ClassBinaryData data = binaryDataMap.get(field.getClassName()); ValueType type = ValueType.object(field.getClassName());
addClass(type);
ClassBinaryData data = binaryDataMap.get(type);
return data.fieldLayout.get(field.getFieldName()); return data.fieldLayout.get(field.getFieldName());
} }
public int getClassSize(String className) { public int getClassSize(String className) {
ClassBinaryData data = binaryDataMap.get(className); ValueType type = ValueType.object(className);
addClass(type);
ClassBinaryData data = binaryDataMap.get(type);
return data.size; return data.size;
} }
public int getArrayClassPointer() {
return arrayClassData.start;
}
public boolean isStructure(String className) { public boolean isStructure(String className) {
ClassBinaryData data = binaryDataMap.get(className); ValueType type = ValueType.object(className);
addClass(type);
ClassBinaryData data = binaryDataMap.get(type);
return data.start < 0; return data.start < 0;
} }
@ -164,8 +209,8 @@ public class WasmClassGenerator {
data.size = 0; data.size = 0;
data.start = -1; data.start = -1;
} else if (cls.getParent() != null && !cls.getParent().equals(cls.getName())) { } else if (cls.getParent() != null && !cls.getParent().equals(cls.getName())) {
addClass(cls.getParent()); addClass(ValueType.object(cls.getParent()));
ClassBinaryData parentData = binaryDataMap.get(cls.getParent()); ClassBinaryData parentData = binaryDataMap.get(ValueType.object(cls.getParent()));
data.size = parentData.size; data.size = parentData.size;
if (parentData.start == -1) { if (parentData.start == -1) {
data.start = -1; data.start = -1;
@ -237,9 +282,10 @@ public class WasmClassGenerator {
} }
private class ClassBinaryData { private class ClassBinaryData {
String name; ValueType type;
int size; int size;
int start; int start;
ObjectIntMap<String> fieldLayout = new ObjectIntOpenHashMap<>(); ObjectIntMap<String> fieldLayout = new ObjectIntOpenHashMap<>();
DataValue data;
} }
} }

View File

@ -528,7 +528,6 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
indexExpr.acceptVisitor(this); indexExpr.acceptVisitor(this);
WasmExpression index = result; WasmExpression index = result;
classGenerator.addClass(RuntimeArray.class.getName());
int base = classGenerator.getClassSize(RuntimeArray.class.getName()); int base = classGenerator.getClassSize(RuntimeArray.class.getName());
array = new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.ADD, array, new WasmInt32Constant(base)); array = new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.ADD, array, new WasmInt32Constant(base));
index = new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.SHL, index, new WasmInt32Constant(2)); index = new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.SHL, index, new WasmInt32Constant(2));
@ -673,7 +672,7 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
VirtualTableEntry vtableEntry = context.getVirtualTableProvider().lookup(expr.getMethod()); VirtualTableEntry vtableEntry = context.getVirtualTableProvider().lookup(expr.getMethod());
WasmExpression methodIndex = new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.ADD, WasmExpression methodIndex = new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.ADD,
getReferenceToClass(instance), new WasmInt32Constant(vtableEntry.getIndex() * 4 + 16)); getReferenceToClass(instance), new WasmInt32Constant(vtableEntry.getIndex() * 4 + 24));
methodIndex = new WasmLoadInt32(4, methodIndex, WasmInt32Subtype.INT32); methodIndex = new WasmLoadInt32(4, methodIndex, WasmInt32Subtype.INT32);
WasmIndirectCall call = new WasmIndirectCall(methodIndex); WasmIndirectCall call = new WasmIndirectCall(methodIndex);
@ -788,7 +787,7 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
@Override @Override
public void visit(NewExpr expr) { public void visit(NewExpr expr) {
int tag = classGenerator.getClassPointer(expr.getConstructedClass()); int tag = classGenerator.getClassPointer(ValueType.object(expr.getConstructedClass()));
String allocName = WasmMangling.mangleMethod(new MethodReference(Allocator.class, "allocate", String allocName = WasmMangling.mangleMethod(new MethodReference(Allocator.class, "allocate",
RuntimeClass.class, Address.class)); RuntimeClass.class, Address.class));
WasmCall call = new WasmCall(allocName); WasmCall call = new WasmCall(allocName);
@ -799,21 +798,14 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
@Override @Override
public void visit(NewArrayExpr expr) { public void visit(NewArrayExpr expr) {
ValueType type = expr.getType(); ValueType type = expr.getType();
int depth = 0;
while (type instanceof ValueType.Array) {
++depth;
type = ((ValueType.Array) type).getItemType();
}
ValueType.Object cls = (ValueType.Object) type; int classPointer = classGenerator.getClassPointer(ValueType.arrayOf(type));
int classPointer = classGenerator.getClassPointer(cls.getClassName());
String allocName = WasmMangling.mangleMethod(new MethodReference(Allocator.class, "allocateArray", String allocName = WasmMangling.mangleMethod(new MethodReference(Allocator.class, "allocateArray",
RuntimeClass.class, int.class, byte.class, Address.class)); RuntimeClass.class, int.class, Address.class));
WasmCall call = new WasmCall(allocName); WasmCall call = new WasmCall(allocName);
call.getArguments().add(new WasmInt32Constant(classPointer)); call.getArguments().add(new WasmInt32Constant(classPointer));
expr.getLength().acceptVisitor(this); expr.getLength().acceptVisitor(this);
call.getArguments().add(result); call.getArguments().add(result);
call.getArguments().add(new WasmInt32Constant(depth));
result = call; result = call;
} }

View File

@ -1,55 +0,0 @@
/*
* Copyright 2016 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.wasm.intrinsics;
import org.teavm.ast.InvocationExpr;
import org.teavm.model.MethodReference;
import org.teavm.runtime.RuntimeClass;
import org.teavm.wasm.generate.WasmClassGenerator;
import org.teavm.wasm.model.expression.WasmExpression;
import org.teavm.wasm.model.expression.WasmInt32Constant;
public class WasmRuntimeClassIntrinsic implements WasmIntrinsic {
private WasmClassGenerator classGenerator;
public WasmRuntimeClassIntrinsic(WasmClassGenerator classGenerator) {
this.classGenerator = classGenerator;
}
@Override
public boolean isApplicable(MethodReference methodReference) {
if (!methodReference.getClassName().equals(RuntimeClass.class.getName())) {
return false;
}
switch (methodReference.getName()) {
case "getArrayClass":
return true;
}
return false;
}
@Override
public WasmExpression apply(InvocationExpr invocation, WasmIntrinsicManager manager) {
switch (invocation.getMethod().getName()) {
case "getArrayClass":
return new WasmInt32Constant(classGenerator.getArrayClassPointer());
default:
throw new IllegalArgumentException(invocation.getMethod().toString());
}
}
}

View File

@ -34,7 +34,7 @@ public class WasmStructureIntrinsic implements WasmIntrinsic {
@Override @Override
public boolean isApplicable(MethodReference methodReference) { public boolean isApplicable(MethodReference methodReference) {
return !methodReference.getClassName().equals(Address.class.getName()) return !methodReference.getClassName().equals(Address.class.getName())
&& classGenerator.getClassPointer(methodReference.getClassName()) < 0; && classGenerator.getClassPointer(ValueType.object(methodReference.getClassName())) < 0;
} }
@Override @Override

View File

@ -266,7 +266,8 @@ class AliasFinder {
} }
@Override @Override
public void getElement(VariableReader receiver, VariableReader array, VariableReader index) { public void getElement(VariableReader receiver, VariableReader array, VariableReader index,
ArrayElementType type) {
ArrayElement elem = new ArrayElement(); ArrayElement elem = new ArrayElement();
elem.array = array.getIndex(); elem.array = array.getIndex();
elem.index = index.getIndex(); elem.index = index.getIndex();
@ -274,7 +275,8 @@ class AliasFinder {
} }
@Override @Override
public void putElement(VariableReader array, VariableReader index, VariableReader value) { public void putElement(VariableReader array, VariableReader index, VariableReader value,
ArrayElementType type) {
} }
@Override @Override

View File

@ -768,7 +768,8 @@ public class CompositeMethodGenerator {
} }
@Override @Override
public void getElement(VariableReader receiver, VariableReader array, VariableReader index) { public void getElement(VariableReader receiver, VariableReader array, VariableReader index,
ArrayElementType type) {
int arrayIndex = variableMapping[array.getIndex()]; int arrayIndex = variableMapping[array.getIndex()];
AliasFinder.ArrayElement elem = arrayElements[receiver.getIndex()]; AliasFinder.ArrayElement elem = arrayElements[receiver.getIndex()];
@ -780,7 +781,7 @@ public class CompositeMethodGenerator {
return; return;
} }
GetElementInstruction insn = new GetElementInstruction(); GetElementInstruction insn = new GetElementInstruction(type);
insn.setArray(var(array)); insn.setArray(var(array));
insn.setIndex(var(index)); insn.setIndex(var(index));
insn.setReceiver(var(receiver)); insn.setReceiver(var(receiver));
@ -788,8 +789,9 @@ public class CompositeMethodGenerator {
} }
@Override @Override
public void putElement(VariableReader array, VariableReader index, VariableReader value) { public void putElement(VariableReader array, VariableReader index, VariableReader value,
PutElementInstruction insn = new PutElementInstruction(); ArrayElementType type) {
PutElementInstruction insn = new PutElementInstruction(type);
insn.setArray(var(array)); insn.setArray(var(array));
insn.setIndex(var(index)); insn.setIndex(var(index));
insn.setValue(var(value)); insn.setValue(var(value));
@ -1013,7 +1015,7 @@ public class CompositeMethodGenerator {
return true; return true;
} }
case "getArrayElement": { case "getArrayElement": {
GetElementInstruction insn = new GetElementInstruction(); GetElementInstruction insn = new GetElementInstruction(asArrayType(reflectClass.type));
insn.setArray(unwrapArray(reflectClass.type, var(arguments.get(0)))); insn.setArray(unwrapArray(reflectClass.type, var(arguments.get(0))));
insn.setIndex(var(arguments.get(1))); insn.setIndex(var(arguments.get(1)));
insn.setReceiver(program.createVariable()); insn.setReceiver(program.createVariable());
@ -1047,7 +1049,7 @@ public class CompositeMethodGenerator {
indexInsn.setReceiver(program.createVariable()); indexInsn.setReceiver(program.createVariable());
add(indexInsn); add(indexInsn);
GetElementInstruction extractArgInsn = new GetElementInstruction(); GetElementInstruction extractArgInsn = new GetElementInstruction(ArrayElementType.OBJECT);
extractArgInsn.setArray(argumentsVar); extractArgInsn.setArray(argumentsVar);
extractArgInsn.setIndex(indexInsn.getReceiver()); extractArgInsn.setIndex(indexInsn.getReceiver());
extractArgInsn.setReceiver(program.createVariable()); extractArgInsn.setReceiver(program.createVariable());

View File

@ -162,11 +162,13 @@ class InstructionLocationReader implements InstructionReader {
} }
@Override @Override
public void getElement(VariableReader receiver, VariableReader array, VariableReader index) { public void getElement(VariableReader receiver, VariableReader array, VariableReader index,
ArrayElementType type) {
} }
@Override @Override
public void putElement(VariableReader array, VariableReader index, VariableReader value) { public void putElement(VariableReader array, VariableReader index, VariableReader value,
ArrayElementType type) {
} }
@Override @Override

View File

@ -20,10 +20,6 @@ import java.util.Set;
import org.teavm.model.*; import org.teavm.model.*;
import org.teavm.model.instructions.*; import org.teavm.model.instructions.*;
/**
*
* @author Alexey Andreev
*/
class ProgramSourceAggregator implements InstructionReader { class ProgramSourceAggregator implements InstructionReader {
private Set<String> sourceFiles; private Set<String> sourceFiles;
@ -82,8 +78,10 @@ class ProgramSourceAggregator implements InstructionReader {
@Override public void arrayLength(VariableReader receiver, VariableReader array) { } @Override public void arrayLength(VariableReader receiver, VariableReader array) { }
@Override public void cloneArray(VariableReader receiver, VariableReader array) { } @Override public void cloneArray(VariableReader receiver, VariableReader array) { }
@Override public void unwrapArray(VariableReader receiver, VariableReader array, ArrayElementType elementType) { } @Override public void unwrapArray(VariableReader receiver, VariableReader array, ArrayElementType elementType) { }
@Override public void getElement(VariableReader receiver, VariableReader array, VariableReader index) { } @Override public void getElement(VariableReader receiver, VariableReader array, VariableReader index,
@Override public void putElement(VariableReader array, VariableReader index, VariableReader value) { } ArrayElementType type) { }
@Override public void putElement(VariableReader array, VariableReader index, VariableReader value,
ArrayElementType type) { }
@Override public void invoke(VariableReader receiver, VariableReader instance, MethodReference method, @Override public void invoke(VariableReader receiver, VariableReader instance, MethodReference method,
List<? extends VariableReader> arguments, InvocationType type) { } List<? extends VariableReader> arguments, InvocationType type) { }
@Override public void invokeDynamic(VariableReader receiver, VariableReader instance, MethodDescriptor method, @Override public void invokeDynamic(VariableReader receiver, VariableReader instance, MethodDescriptor method,