WASM: fix bugs

This commit is contained in:
Alexey Andreev 2017-01-29 19:01:18 +03:00
parent 055f39c1c8
commit 2610fe5428
5 changed files with 94 additions and 68 deletions

View File

@ -670,9 +670,10 @@ public class WasmTarget implements TeaVMTarget {
gcIntrinsic.setRegionsAddress(address);
gcIntrinsic.setRegionMaxCount(regionCount);
gcMemory -= regionCount * 2;
address += regionCount * 2;
address = (address + 4) >> 2 << 2;
gcMemory = module.getMemorySize() * 65536 - address;
gcIntrinsic.setHeapAddress(address);
gcIntrinsic.setAvailableBytes(gcMemory);
}

View File

@ -22,11 +22,6 @@ import org.teavm.backend.wasm.binary.BinaryWriter;
import org.teavm.backend.wasm.model.WasmFunction;
import org.teavm.backend.wasm.model.WasmLocal;
import org.teavm.backend.wasm.model.WasmType;
import org.teavm.backend.wasm.model.expression.WasmExpression;
import org.teavm.backend.wasm.model.expression.WasmFloat32Constant;
import org.teavm.backend.wasm.model.expression.WasmFloat64Constant;
import org.teavm.backend.wasm.model.expression.WasmInt32Constant;
import org.teavm.backend.wasm.model.expression.WasmInt64Constant;
import org.teavm.interop.Export;
import org.teavm.model.AnnotationReader;
import org.teavm.model.ClassHolder;
@ -90,27 +85,6 @@ public class WasmGenerator {
methodAst.getBody().acceptVisitor(visitor);
function.getBody().add(visitor.result);
if (function.getResult() != null) {
WasmExpression finalExpr;
switch (function.getResult()) {
case INT32:
finalExpr = new WasmInt32Constant(0);
break;
case INT64:
finalExpr = new WasmInt64Constant(0);
break;
case FLOAT32:
finalExpr = new WasmFloat32Constant(0);
break;
case FLOAT64:
finalExpr = new WasmFloat64Constant(0);
break;
default:
throw new AssertionError();
}
function.getBody().add(finalExpr);
}
AnnotationReader exportAnnot = method.getAnnotations().get(Export.class.getName());
if (exportAnnot != null) {
function.setExportName(exportAnnot.getValue("name").getString());

View File

@ -55,28 +55,24 @@ public class WasmRenderer {
public void render(WasmModule module) {
visitor.open().append("module");
renderMemory(module);
renderTypes(module);
for (WasmFunction function : module.getFunctions().values()) {
if (function.getImportName() == null) {
continue;
}
lf().renderImport(function);
}
for (WasmFunction function : module.getFunctions().values()) {
if (function.getImportName() != null) {
continue;
lf().render(function);
}
lf().render(function);
}
for (WasmFunction function : module.getFunctions().values()) {
if (function.getExportName() == null) {
continue;
if (function.getImportName() == null) {
lf().render(function);
}
lf().renderExport(function);
}
renderTable(module);
renderMemory(module);
renderElement(module);
renderData(module);
if (module.getStartFunction() != null) {
visitor.lf().open().append("start $" + module.getStartFunction().getName()).close().lf();
}
@ -85,9 +81,12 @@ public class WasmRenderer {
public void renderMemory(WasmModule module) {
visitor.lf();
visitor.open().append("memory " + module.getMemorySize());
visitor.open().append("memory " + module.getMemorySize()).close().lf();
}
public void renderData(WasmModule module) {
for (WasmMemorySegment segment : module.getSegments()) {
visitor.lf().open().append("segment " + segment.getOffset());
visitor.lf().open().append("data (i32.const " + segment.getOffset() + ")");
visitor.indent();
for (int i = 0; i < segment.getLength(); i += 256) {
visitor.lf().append("\"");
@ -110,26 +109,21 @@ public class WasmRenderer {
visitor.outdent();
visitor.close();
}
visitor.close().lf();
}
public void renderImport(WasmFunction function) {
String importModule = function.getImportModule();
if (importModule == null) {
importModule = "";
}
visitor.open().append("import $" + function.getName() + " \"" + importModule + "\" "
+ "\"" + function.getImportName() + "\"");
renderSignature(function);
visitor.close();
}
public void renderExport(WasmFunction function) {
visitor.open().append("export \"" + function.getExportName() + "\" $" + function.getName()).close();
}
public void render(WasmFunction function) {
visitor.open().append("func $" + function.getName());
if (function.getImportName() != null) {
String importModule = function.getImportModule();
if (importModule == null) {
importModule = "";
}
visitor.append(" (import \"" + importModule + "\" \"" + function.getImportName() + "\")");
} else if (function.getExportName() != null) {
visitor.append(" (export \"" + function.getExportName() + "\")");
}
renderSignature(function);
int firstLocalVariable = function.getParameters().size();
@ -142,6 +136,9 @@ public class WasmRenderer {
}
visitor.close();
}
for (WasmExpression part : function.getBody()) {
visitor.preprocess(part);
}
for (WasmExpression part : function.getBody()) {
visitor.line(part);
}
@ -195,7 +192,15 @@ public class WasmRenderer {
return;
}
visitor.lf().open().append("table");
visitor.lf().open().append("table " + module.getFunctionTable().size() + " anyfunc").close().lf();
}
private void renderElement(WasmModule module) {
if (module.getFunctionTable().isEmpty()) {
return;
}
visitor.lf().open().append("elem (i32.const 0)");
for (WasmFunction function : module.getFunctionTable()) {
visitor.lf().append("$" + function.getName());
}

View File

@ -29,6 +29,7 @@ import org.teavm.backend.wasm.model.expression.WasmBreak;
import org.teavm.backend.wasm.model.expression.WasmCall;
import org.teavm.backend.wasm.model.expression.WasmConditional;
import org.teavm.backend.wasm.model.expression.WasmConversion;
import org.teavm.backend.wasm.model.expression.WasmDefaultExpressionVisitor;
import org.teavm.backend.wasm.model.expression.WasmDrop;
import org.teavm.backend.wasm.model.expression.WasmExpression;
import org.teavm.backend.wasm.model.expression.WasmExpressionVisitor;
@ -71,6 +72,35 @@ class WasmRenderingVisitor implements WasmExpressionVisitor {
List<WasmSignature> signatureList = new ArrayList<>();
Map<WasmSignature, Integer> signatureMap = new HashMap<>();
void preprocess(WasmExpression expression) {
expression.acceptVisitor(new WasmDefaultExpressionVisitor() {
@Override
public void visit(WasmBranch expression) {
super.visit(expression);
register(expression.getTarget());
}
@Override
public void visit(WasmBreak expression) {
super.visit(expression);
register(expression.getTarget());
}
@Override
public void visit(WasmSwitch expression) {
super.visit(expression);
for (WasmBlock target : expression.getTargets()) {
register(target);
}
register(expression.getDefaultTarget());
}
private void register(WasmBlock block) {
blockIdentifiers.computeIfAbsent(block, key -> "block_" + blockIdentifiers.size());
}
});
}
void clear() {
blockIdentifiers.clear();
usedIdentifiers.clear();
@ -135,13 +165,18 @@ class WasmRenderingVisitor implements WasmExpressionVisitor {
@Override
public void visit(WasmBlock expression) {
renderBlock(expression, expression.isLoop() ? "loop" : "block");
renderBlock(expression, expression.isLoop() ? "loop" : "block", true);
}
private void renderBlock(WasmBlock block, String name) {
String id = getIdentifier("@block");
blockIdentifiers.put(block, id);
open().append(name + " $" + id);
private void renderBlock(WasmBlock block, String name, boolean signature) {
open().append(name);
String id = blockIdentifiers.get(block);
if (id != null) {
append(" $" + id);
}
if (signature && block.getType() != null) {
append(" " + type(block.getType()));
}
for (WasmExpression part : block.getBody()) {
line(part);
}
@ -183,14 +218,19 @@ class WasmRenderingVisitor implements WasmExpressionVisitor {
@Override
public void visit(WasmConditional expression) {
open().append("if");
if (expression.getType() != null) {
append(" " + type(expression.getType()));
}
line(expression.getCondition());
lf();
renderBlock(expression.getThenBlock(), "then");
renderBlock(expression.getThenBlock(), "then", false);
if (!expression.getElseBlock().getBody().isEmpty()) {
lf();
renderBlock(expression.getElseBlock(), "else");
renderBlock(expression.getElseBlock(), "else", false);
}
close();
@ -343,7 +383,7 @@ class WasmRenderingVisitor implements WasmExpressionVisitor {
@Override
public void visit(WasmCall expression) {
open().append(expression.isImported() ? "call_import" : "call").append(" $" + expression.getFunctionName());
open().append("call").append(" $" + expression.getFunctionName());
for (WasmExpression argument : expression.getArguments()) {
line(argument);
}

View File

@ -70,12 +70,15 @@ public final class GC {
next = currentChunk.toAddress().add(size);
}
int freeSize = current.size;
currentChunk = next.toStructure();
freeSize -= size;
if (freeSize > 0) {
currentChunk.classReference = 0;
currentChunk = next.toStructure();
currentChunk.size = freeSize;
} else {
freeMemory -= size;
getAvailableChunkIfPossible(currentChunk.size + 1);
}
currentChunk.classReference = 0;
freeMemory -= size;
return current;
}
@ -89,6 +92,9 @@ public final class GC {
}
private static boolean getAvailableChunkIfPossible(int size) {
if (freeChunks == 0) {
return false;
}
while (true) {
if (currentChunk.toAddress().add(size) == currentChunkLimit) {
break;