Repository navigation
Expand file tree
/
Copy pathCompileModuleTest.java
More file actions
110 lines (93 loc) · 4.29 KB
/
Copy pathCompileModuleTest.java
File metadata and controls
110 lines (93 loc) · 4.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
package run.endive.testing;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static run.endive.corpus.WatGenerator.methodTooLarge;
import java.util.List;
import java.util.Set;
import org.junit.jupiter.api.Test;
import run.endive.compiler.InterpreterFallback;
import run.endive.compiler.MachineFactoryCompiler;
import run.endive.corpus.CorpusResources;
import run.endive.runtime.CompiledModule;
import run.endive.runtime.HostFunction;
import run.endive.runtime.ImportValues;
import run.endive.runtime.Instance;
import run.endive.wabt.Wat2Wasm;
import run.endive.wasm.Parser;
import run.endive.wasm.WasmModule;
import run.endive.wasm.types.CodeSection;
import run.endive.wasm.types.FunctionType;
import run.endive.wasm.types.ValType;
public class CompileModuleTest {
// func_1 (function index 2, code index 1) is too large to compile and is interpreted.
private static final WasmModule METHOD_TOO_LARGE =
Parser.parse(Wat2Wasm.parse(methodTooLarge(20_000)));
private static final HostFunction HOST_FUNC =
new HostFunction(
"funcs",
"host_func",
FunctionType.of(List.of(ValType.I32), List.of(ValType.I32)),
(inst, args) -> new long[] {35});
private static CompiledModule compileModule(WasmModule module) {
return MachineFactoryCompiler.builder(module)
.withInterpreterFallback(InterpreterFallback.SILENT)
.compileModule();
}
private static Instance instantiate(CompiledModule compiled) {
return Instance.builder(compiled)
.withImportValues(ImportValues.builder().addFunction(HOST_FUNC).build())
.withStart(false)
.build();
}
private static void assertRetained(CodeSection code, Set<Integer> retained) {
var bodies = code.functionBodies();
for (int i = 0; i < bodies.length; i++) {
assertEquals(retained.contains(i), bodies[i] != null, "function body " + i);
}
}
@Test
public void keepsOnlyInterpretedFunctionBodies() {
var compiled = compileModule(METHOD_TOO_LARGE);
var code = compiled.wasmModule().codeSection();
assertEquals(3, code.functionBodyCount());
assertRetained(code, Set.of(1));
assertThrows(IllegalStateException.class, () -> code.getFunctionBody(0));
// The module passed to the compiler is left unchanged.
assertRetained(METHOD_TOO_LARGE.codeSection(), Set.of(0, 1, 2));
var instance = instantiate(compiled);
// Through the interpreted func_1, calling back into compiled code directly...
assertEquals(35, instance.export("func_2").apply(0)[0]);
// ...and through call_indirect.
assertEquals(35, instance.export("func_2").apply(1)[0]);
}
@Test
public void keepsFunctionsReachableThroughTailCalls() {
// interpreted tail calls tail_called, which calls compiled
var module =
Parser.parse(
CorpusResources.getResource("compiled/tail_call_drop_bodies.wat.wasm"));
var compiled =
MachineFactoryCompiler.builder(module)
.withInterpreterFallback(InterpreterFallback.FAIL)
.withInterpretedFunctions(Set.of(0))
.compileModule();
assertRetained(compiled.wasmModule().codeSection(), Set.of(0, 1));
assertEquals(42, Instance.builder(compiled).build().export("interpreted").apply(41)[0]);
}
@Test
public void compileKeepsTheModule() {
var factory =
MachineFactoryCompiler.builder(METHOD_TOO_LARGE)
.withInterpreterFallback(InterpreterFallback.SILENT)
.compile();
assertSame(METHOD_TOO_LARGE, ((CompiledModule) factory).wasmModule());
}
@Test
public void instanceRejectsDroppedBody() {
var instance = instantiate(compileModule(METHOD_TOO_LARGE));
var exception = assertThrows(IllegalStateException.class, () -> instance.function(1));
assertTrue(exception.getMessage().contains("dropped"));
}
}