Skip to content

Commit

Permalink
[api] Make Module and Sections immutable with Builders (#460)
Browse files Browse the repository at this point in the history
This is part of the effort toward #441

---------

Co-authored-by: David Phillips <[email protected]>
  • Loading branch information
andreaTP and electrum authored Aug 14, 2024
1 parent bef1801 commit bd17cf3
Show file tree
Hide file tree
Showing 44 changed files with 737 additions and 775 deletions.
7 changes: 7 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,13 @@ jobs:
script: aot/README.md
env:
JBANG_REPO: "${{ github.workspace }}/repository"
# Test WASM Readme
- name: jbang
uses: jbangdev/jbang-action@9f8c55e0a2b6b297711162b20c209c5e07076e59 # tag=v0.117.1
with:
script: wasm/README.md
env:
JBANG_REPO: "${{ github.workspace }}/repository"

test-results:
name: Test Results
Expand Down
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,11 +114,12 @@ Now let's load this module and instantiate it:
import com.dylibso.chicory.runtime.ExportFunction;
import com.dylibso.chicory.wasm.types.Value;
import com.dylibso.chicory.wasm.Module;
import com.dylibso.chicory.wasm.Parser;
import com.dylibso.chicory.runtime.Instance;
import java.io.File;

// point this to your path on disk
Module module = Module.builder(new File("./factorial.wasm")).build();
Module module = Parser.parse(new File("./factorial.wasm"));
Instance instance = Instance.builder(module).build();
```

Expand Down Expand Up @@ -171,7 +172,7 @@ copyFileFromWasmCorpus("count_vowels.rs.wasm", "count_vowels.wasm");
Build and instantiate this module:

```java
Instance instance = Instance.builder(Module.builder(new File("./count_vowels.wasm")).build()).build();
Instance instance = Instance.builder(Parser.parse(new File("./count_vowels.wasm"))).build();
ExportFunction countVowels = instance.export("count_vowels");
```

Expand Down Expand Up @@ -278,7 +279,7 @@ Now we just need to pass this host function in during our instantiation phase:
```java
import com.dylibso.chicory.runtime.HostImports;
var imports = new HostImports(new HostFunction[] {func});
var instance = Instance.builder(Module.builder(new File("./logger.wasm")).build()).withHostImports(imports).build();
var instance = Instance.builder(Parser.parse(new File("./logger.wasm"))).withHostImports(imports).build();
var logIt = instance.export("logIt");
logIt.apply();
// should print "Hello, World!" 10 times
Expand Down
4 changes: 2 additions & 2 deletions aot/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ To enable use the AotMachine factory when building the module:
```java
// ...

import com.dylibso.chicory.wasm.Module;
import com.dylibso.chicory.wasm.Parser;
import com.dylibso.chicory.runtime.Instance;
import com.dylibso.chicory.aot.AotMachine;
// ...
var is = ClassLoader.getSystemClassLoader().getResourceAsStream("compiled/basic.c.wasm");
Instance.builder(Module.builder(is).build()).withMachineFactory(AotMachine::new).build();
Instance.builder(Parser.parse(is)).withMachineFactory(AotMachine::new).build();
```
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import com.dylibso.chicory.aot.AotMachine;
import com.dylibso.chicory.runtime.Instance;
import com.dylibso.chicory.wasm.Module;
import com.dylibso.chicory.wasm.Parser;
import java.io.ByteArrayOutputStream;
import java.io.PrintWriter;
import org.approvaltests.Approvals;
Expand Down Expand Up @@ -65,10 +65,9 @@ public void verifyTrap() {
private static void verifyGeneratedBytecode(String name) {
var instance =
Instance.builder(
Module.builder(
ClassLoader.getSystemClassLoader()
.getResourceAsStream("compiled/" + name))
.build())
Parser.parse(
ClassLoader.getSystemClassLoader()
.getResourceAsStream("compiled/" + name)))
.withImportValidation(false)
.withMachineFactory(AotMachine::new)
.withStart(false)
Expand Down
14 changes: 5 additions & 9 deletions aot/src/test/java/com/dylibso/chicory/testing/TestModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import com.dylibso.chicory.runtime.Instance;
import com.dylibso.chicory.wabt.Wat2Wasm;
import com.dylibso.chicory.wasm.Module;
import com.dylibso.chicory.wasm.ModuleType;
import com.dylibso.chicory.wasm.Parser;
import com.dylibso.chicory.wasm.exceptions.MalformedException;
import java.io.File;

Expand All @@ -21,10 +21,6 @@ public TestModule(Module module) {
this.module = module;
}

public static TestModule of(File file) {
return of(file, ModuleType.BINARY);
}

public static TestModule of(Module module) {
return new TestModule(module);
}
Expand Down Expand Up @@ -54,18 +50,18 @@ public static TestModule of(Module module) {
+ "alignment "
+ "multiple start sections";

public static TestModule of(File file, ModuleType moduleType) {
if (moduleType == ModuleType.TEXT) {
public static TestModule of(File file) {
if (file.getName().endsWith(".wat")) {
byte[] parsed;
try {
parsed = Wat2Wasm.parse(file);
} catch (Exception e) {
throw new MalformedException(
e.getMessage() + HACK_MATCH_ALL_MALFORMED_EXCEPTION_TEXT);
}
return of(Module.builder(parsed).build());
return of(Parser.parse(parsed));
}
return of(Module.builder(file).build());
return of(Parser.parse(file));
}

public Instance build() {
Expand Down
4 changes: 2 additions & 2 deletions cli/src/main/java/com/dylibso/chicory/cli/Cli.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import com.dylibso.chicory.runtime.Instance;
import com.dylibso.chicory.wasi.WasiOptions;
import com.dylibso.chicory.wasi.WasiPreview1;
import com.dylibso.chicory.wasm.Module;
import com.dylibso.chicory.wasm.Parser;
import com.dylibso.chicory.wasm.types.Value;
import java.io.ByteArrayInputStream;
import java.io.File;
Expand Down Expand Up @@ -57,7 +57,7 @@ public void run() {
throw new RuntimeException(e);
}
var logger = new SystemLogger();
var module = Module.builder(file).build();
var module = Parser.parse(file);
var imports =
wasi
? new HostImports(
Expand Down
8 changes: 4 additions & 4 deletions fuzz/src/test/java/com/dylibso/chicory/fuzz/FuzzTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import com.dylibso.chicory.log.Logger;
import com.dylibso.chicory.log.SystemLogger;
import com.dylibso.chicory.runtime.Instance;
import com.dylibso.chicory.wasm.Module;
import com.dylibso.chicory.wasm.Parser;
import com.dylibso.chicory.wasm.types.ExternalType;
import java.io.File;
import org.junit.jupiter.api.BeforeEach;
Expand All @@ -29,7 +29,7 @@ File generateTestData(String prefix, int num, InstructionType... instructionType
targetWasm =
smith.run(prefix + num, "test.wasm", new InstructionTypes(instructionTypes));

var exportSection = Module.builder(targetWasm).build().exportSection();
var exportSection = Parser.parse(targetWasm).exportSection();
atLeastOneExportedFunction = false;
for (int i = 0; i < exportSection.exportCount(); i++) {
if (exportSection.getExport(i).exportType() == ExternalType.FUNCTION) {
Expand Down Expand Up @@ -59,7 +59,7 @@ public void numericOnlyFuzz(RepetitionInfo repetitionInfo) throws Exception {
var targetWasm =
generateTestData(
"numeric-", repetitionInfo.getCurrentRepetition(), InstructionType.NUMERIC);
var module = Module.builder(targetWasm).build();
var module = Parser.parse(targetWasm);
var instance = Instance.builder(module).withInitialize(true).withStart(false).build();

var results = testModule(targetWasm, module, instance);
Expand All @@ -76,7 +76,7 @@ public void tableOnlyFuzz(RepetitionInfo repetitionInfo) throws Exception {
var targetWasm =
generateTestData(
"table-", repetitionInfo.getCurrentRepetition(), InstructionType.TABLE);
var module = Module.builder(targetWasm).build();
var module = Parser.parse(targetWasm);
var instance = Instance.builder(module).withInitialize(true).withStart(false).build();

var results = testModule(targetWasm, module, instance);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import static org.junit.jupiter.api.Assertions.assertEquals;

import com.dylibso.chicory.runtime.Instance;
import com.dylibso.chicory.wasm.Module;
import com.dylibso.chicory.wasm.Parser;
import java.io.File;
import java.util.Arrays;
import java.util.stream.Stream;
Expand All @@ -24,7 +24,7 @@ private static Stream<Arguments> crashFolders() {
@MethodSource("crashFolders")
void regressionTests(File folder) throws Exception {
var targetWasm = new File(folder.getAbsolutePath() + "/test.wasm");
var module = Module.builder(targetWasm).build();
var module = Parser.parse(targetWasm);
var instance = Instance.builder(module).withInitialize(true).withStart(false).build();

var results = testModule(targetWasm, module, instance, false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;

import com.dylibso.chicory.runtime.Instance;
import com.dylibso.chicory.wasm.Module;
import com.dylibso.chicory.wasm.Parser;
import java.nio.file.Files;
import java.nio.file.Paths;
import org.junit.jupiter.api.Test;
Expand All @@ -28,7 +28,7 @@ void singleReproducer() throws Exception {
var targetWasm =
smith.run(seed.substring(0, Math.min(seed.length(), 32)), "test.wasm", types);

var module = Module.builder(targetWasm).build();
var module = Parser.parse(targetWasm);
var instance = Instance.builder(module).withInitialize(true).withStart(false).build();

testModule(targetWasm, module, instance);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import com.dylibso.chicory.aot.AotMachine;
import com.dylibso.chicory.runtime.ExportFunction;
import com.dylibso.chicory.runtime.Instance;
import com.dylibso.chicory.wasm.Module;
import com.dylibso.chicory.wasm.Parser;
import com.dylibso.chicory.wasm.types.Value;
import java.io.File;
import java.util.concurrent.TimeUnit;
Expand Down Expand Up @@ -38,11 +38,11 @@ public class BenchmarkFactorialExecution {

@Setup
public void setup() {
var factorialInt = Instance.builder(Module.builder(ITERFACT).build()).build();
var factorialInt = Instance.builder(Parser.parse(ITERFACT)).build();
iterFactInt = factorialInt.export("iterFact");

var factorialAot =
Instance.builder(Module.builder(ITERFACT).build())
Instance.builder(Parser.parse(ITERFACT))
.withMachineFactory(AotMachine::new)
.build();
iterFactAot = factorialAot.export("iterFact");
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.dylibso.chicory.bench;

import com.dylibso.chicory.wasm.Module;
import com.dylibso.chicory.wasm.Parser;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
Expand Down Expand Up @@ -41,6 +41,6 @@ public void setup() throws IOException {
@Benchmark
@BenchmarkMode(Mode.Throughput)
public void benchmark(Blackhole bh) {
bh.consume(Module.builder(memoryMappedFile).build());
bh.consume(Parser.parse(memoryMappedFile));
}
}
1 change: 1 addition & 0 deletions readmes/wasm/expected/parser-base.result
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
target_features
8 changes: 8 additions & 0 deletions readmes/wasm/expected/parser-listener.result
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.debug_abbrev
.debug_info
.debug_ranges
.debug_str
.debug_line
name
producers
target_features
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import com.dylibso.chicory.runtime.Instance;
import com.dylibso.chicory.wabt.Wat2Wasm;
import com.dylibso.chicory.wasm.Module;
import com.dylibso.chicory.wasm.ModuleType;
import com.dylibso.chicory.wasm.Parser;
import com.dylibso.chicory.wasm.exceptions.MalformedException;
import java.io.File;

Expand All @@ -15,10 +15,6 @@ public class TestModule {

private HostImports imports;

public static TestModule of(File file) {
return of(file, ModuleType.BINARY);
}

public static TestModule of(Module module) {
return new TestModule(module);
}
Expand Down Expand Up @@ -48,18 +44,18 @@ public static TestModule of(Module module) {
+ "alignment "
+ "multiple start sections";

public static TestModule of(File file, ModuleType moduleType) {
if (moduleType == ModuleType.TEXT) {
public static TestModule of(File file) {
if (file.getName().endsWith(".wat")) {
byte[] parsed;
try {
parsed = Wat2Wasm.parse(file);
} catch (Exception e) {
throw new MalformedException(
e.getMessage() + HACK_MATCH_ALL_MALFORMED_EXCEPTION_TEXT);
}
return of(Module.builder(parsed).build());
return of(Parser.parse(parsed));
}
return of(Module.builder(file).build());
return of(Parser.parse(file));
}

public TestModule(Module module) {
Expand Down
21 changes: 9 additions & 12 deletions runtime/src/main/java/com/dylibso/chicory/runtime/Instance.java
Original file line number Diff line number Diff line change
Expand Up @@ -627,8 +627,9 @@ private static void validateModule(Module module) {
if (functionSectionSize != codeSectionSize) {
throw new MalformedException("function and code section have inconsistent lengths");
}
if (module.dataCountSection() != null
&& dataSectionSize != module.dataCountSection().dataCount()) {
if (module.dataCountSection()
.map(dcs -> dcs.dataCount() != dataSectionSize)
.orElse(false)) {
throw new MalformedException(
"data count and data section have inconsistent lengths");
}
Expand Down Expand Up @@ -813,15 +814,13 @@ public Instance build() {
mapHostImports(
imports,
(hostImports == null) ? new HostImports() : hostImports,
(module.memorySection() != null)
? module.memorySection().memoryCount()
: 0);
module.memorySection().map(m -> m.memoryCount()).orElse(0));

if (module.startSection() != null) {
if (module.startSection().isPresent()) {
var export =
new Export(
START_FUNCTION_NAME,
(int) module.startSection().startIndex(),
(int) module.startSection().get().startIndex(),
ExternalType.FUNCTION);
exports.put(START_FUNCTION_NAME, export);
}
Expand All @@ -839,8 +838,8 @@ public Instance build() {
Element[] elements = module.elementSection().elements();

Memory memory = null;
if (module.memorySection() != null) {
var memories = module.memorySection();
if (module.memorySection().isPresent()) {
var memories = module.memorySection().get();
if (memories.memoryCount() > 0) {
memory = new Memory(memories.getMemory(0).memoryLimits());
}
Expand Down Expand Up @@ -912,9 +911,7 @@ public Instance build() {
case MEMORY:
{
var memoryCount =
(module.memorySection() == null)
? 0
: module.memorySection().memoryCount();
module.memorySection().map(m -> m.memoryCount()).orElse(0);
if (e.index() >= memoryCount + memoryImportsOffset) {
throw new InvalidException("unknown memory " + e);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -958,9 +958,8 @@ public void validate(

// to satisfy the check mentioned in the NOTE
// https://webassembly.github.io/spec/core/binary/modules.html#data-count-section
if (instance.module().codeSection() != null
&& instance.module().codeSection().isRequiresDataCount()
&& instance.module().dataCountSection() == null) {
if (instance.module().codeSection().isRequiresDataCount()
&& instance.module().dataCountSection().isEmpty()) {
throw new MalformedException("data count section required");
}
}
Expand Down
Loading

0 comments on commit bd17cf3

Please sign in to comment.