mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
Refactoring RTTI, add type annotation to array subscription instructions
This commit is contained in:
parent
73d4a389b7
commit
164ebeb629
27
core/src/main/java/org/teavm/ast/ArrayType.java
Normal file
27
core/src/main/java/org/teavm/ast/ArrayType.java
Normal 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
|
||||||
|
}
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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];
|
||||||
|
|
|
@ -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: {
|
||||||
|
|
|
@ -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()));
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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()) {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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()]);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Reference in New Issue
Block a user