Skip to content

Commit 1cbe798

Browse files
committed
Support AOT and interp WASM
Primarily for testing purposes.
1 parent 098305d commit 1cbe798

5 files changed

Lines changed: 175 additions & 140 deletions

File tree

Lines changed: 12 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,89 +1,37 @@
11
package org.prism;
22

33
import com.dylibso.chicory.annotations.WasmModuleInterface;
4-
import com.dylibso.chicory.runtime.ByteArrayMemory;
5-
import com.dylibso.chicory.runtime.ImportValues;
6-
import com.dylibso.chicory.runtime.Instance;
74
import com.dylibso.chicory.wasi.WasiOptions;
85
import com.dylibso.chicory.wasi.WasiPreview1;
9-
import com.dylibso.chicory.wasm.WasmModule;
10-
import com.dylibso.chicory.wasm.types.MemoryLimits;
116

127
import java.nio.charset.StandardCharsets;
138

149
@WasmModuleInterface(WasmResource.absoluteFile)
15-
public class Prism implements AutoCloseable {
16-
private final WasiPreview1 wasi;
17-
private final Instance instance;
18-
private final Prism_ModuleExports exports;
10+
public abstract class Prism implements AutoCloseable {
11+
protected final WasiPreview1 wasi;
1912

20-
public Prism() {
13+
Prism() {
2114
this(WasiOptions.builder().build());
2215
}
23-
public Prism(WasiOptions wasiOpts) {
24-
wasi = WasiPreview1.builder().withOptions(wasiOpts).build();
25-
WasmModule module = PrismParser.load();
26-
PrismParser parser = new PrismParser();
27-
instance = Instance.builder(module)
28-
.withMemoryFactory(limits -> new ByteArrayMemory(new MemoryLimits(10, MemoryLimits.MAX_PAGES)))
29-
.withMachineFactory(parser.machineFactory())
30-
.withImportValues(ImportValues.builder().addFunction(wasi.toHostFunctions()).build())
31-
.build();
32-
exports = new Prism_ModuleExports(instance);
33-
}
3416

35-
public Prism_ModuleExports exports() {
36-
return exports;
17+
Prism(WasiOptions wasiOpts) {
18+
wasi = WasiPreview1.builder().withOptions(wasiOpts).build();
3719
}
3820

39-
public byte[] serialize(byte[] packedOptions, byte[] source, int sourceLength) {
40-
int sourcePointer = 0;
41-
int optionsPointer = 0;
42-
int bufferPointer = 0;
43-
byte[] result;
44-
try {
45-
sourcePointer = exports.calloc(sourceLength, 1);
46-
exports.memory().write(sourcePointer, source);
47-
48-
optionsPointer = exports.calloc(1, packedOptions.length);
49-
exports.memory().write(optionsPointer, packedOptions);
50-
51-
bufferPointer = exports.calloc(exports.pmBufferSizeof(), 1);
52-
exports.pmBufferInit(bufferPointer);
53-
54-
exports.pmSerializeParse(bufferPointer, sourcePointer, sourceLength, optionsPointer);
21+
public static Prism newInstance(boolean aot) {
22+
if (aot) return new PrismAOT();
5523

56-
result = instance.memory().readBytes(
57-
exports.pmBufferValue(bufferPointer),
58-
exports.pmBufferLength(bufferPointer));
59-
} finally {
60-
if (sourcePointer != 0) {
61-
exports.free(sourcePointer);
62-
}
63-
if (optionsPointer != 0) {
64-
exports.free(optionsPointer);
65-
}
66-
if (bufferPointer != 0) {
67-
exports.pmBufferFree(bufferPointer);
68-
exports.free(bufferPointer);
69-
}
70-
}
71-
72-
return result;
24+
return new PrismWASM();
7325
}
7426

75-
public ParseResult serializeParse(byte[] packedOptions, String source) {
76-
var sourceBytes = source.getBytes(StandardCharsets.US_ASCII);
27+
public abstract byte[] serialize(byte[] packedOptions, byte[] source, int sourceLength);
7728

29+
public ParseResult serializeParse(byte[] packedOptions, String source) {
30+
var sourceBytes = source.getBytes(StandardCharsets.ISO_8859_1);
7831
byte[] result = serialize(packedOptions, sourceBytes, sourceBytes.length);
79-
8032
return Loader.load(result, sourceBytes);
8133
}
8234

8335
@Override
84-
public void close() {
85-
if (wasi != null) {
86-
wasi.close();
87-
}
88-
}
36+
public abstract void close();
8937
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
package org.prism;
2+
3+
import com.dylibso.chicory.annotations.WasmModuleInterface;
4+
import com.dylibso.chicory.runtime.ByteArrayMemory;
5+
import com.dylibso.chicory.runtime.ImportValues;
6+
import com.dylibso.chicory.runtime.Instance;
7+
import com.dylibso.chicory.wasm.WasmModule;
8+
import com.dylibso.chicory.wasm.types.MemoryLimits;
9+
10+
import java.nio.charset.StandardCharsets;
11+
12+
@WasmModuleInterface(WasmResource.absoluteFile)
13+
public class PrismAOT extends Prism {
14+
private final Instance instance;
15+
private final Prism_ModuleExports exports;
16+
17+
public PrismAOT() {
18+
super();
19+
WasmModule module = PrismParser.load();
20+
PrismParser parser = new PrismParser();
21+
instance = Instance.builder(module)
22+
.withMemoryFactory(limits -> new ByteArrayMemory(new MemoryLimits(10, MemoryLimits.MAX_PAGES)))
23+
.withMachineFactory(parser.machineFactory())
24+
.withImportValues(ImportValues.builder().addFunction(wasi.toHostFunctions()).build())
25+
.build();
26+
exports = new Prism_ModuleExports(instance);
27+
}
28+
29+
public byte[] serialize(byte[] packedOptions, byte[] source, int sourceLength) {
30+
int sourcePointer = 0;
31+
int optionsPointer = 0;
32+
int bufferPointer = 0;
33+
byte[] result;
34+
try {
35+
sourcePointer = exports.calloc(sourceLength, 1);
36+
exports.memory().write(sourcePointer, source);
37+
38+
optionsPointer = exports.calloc(1, packedOptions.length);
39+
exports.memory().write(optionsPointer, packedOptions);
40+
41+
bufferPointer = exports.calloc(exports.pmBufferSizeof(), 1);
42+
exports.pmBufferInit(bufferPointer);
43+
44+
exports.pmSerializeParse(bufferPointer, sourcePointer, sourceLength, optionsPointer);
45+
46+
result = instance.memory().readBytes(
47+
exports.pmBufferValue(bufferPointer),
48+
exports.pmBufferLength(bufferPointer));
49+
} finally {
50+
if (sourcePointer != 0) {
51+
exports.free(sourcePointer);
52+
}
53+
if (optionsPointer != 0) {
54+
exports.free(optionsPointer);
55+
}
56+
if (bufferPointer != 0) {
57+
exports.pmBufferFree(bufferPointer);
58+
exports.free(bufferPointer);
59+
}
60+
}
61+
62+
return result;
63+
}
64+
65+
public ParseResult serializeParse(byte[] packedOptions, String source) {
66+
var sourceBytes = source.getBytes(StandardCharsets.US_ASCII);
67+
68+
byte[] result = serialize(packedOptions, sourceBytes, sourceBytes.length);
69+
70+
return Loader.load(result, sourceBytes);
71+
}
72+
73+
@Override
74+
public void close() {
75+
if (wasi != null) {
76+
wasi.close();
77+
}
78+
}
79+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package org.prism;
2+
3+
import com.dylibso.chicory.annotations.WasmModuleInterface;
4+
import com.dylibso.chicory.runtime.ByteArrayMemory;
5+
import com.dylibso.chicory.runtime.ExportFunction;
6+
import com.dylibso.chicory.runtime.ImportValues;
7+
import com.dylibso.chicory.runtime.Instance;
8+
import com.dylibso.chicory.runtime.WasmRuntimeException;
9+
import com.dylibso.chicory.wasi.WasiOptions;
10+
import com.dylibso.chicory.wasi.WasiPreview1;
11+
import com.dylibso.chicory.wasm.WasmModule;
12+
import com.dylibso.chicory.wasm.types.MemoryLimits;
13+
14+
import java.nio.charset.StandardCharsets;
15+
16+
@WasmModuleInterface(WasmResource.absoluteFile)
17+
public class PrismWASM extends Prism {
18+
private final ExportFunction calloc;
19+
private final ExportFunction pmSerializeParse;
20+
private final ExportFunction pmBufferInit;
21+
private final ExportFunction pmBufferSizeof;
22+
private final ExportFunction pmBufferValue;
23+
private final ExportFunction pmBufferLength;
24+
25+
private final Instance instance;
26+
27+
public PrismWASM() {
28+
super();
29+
instance = Instance.builder(PrismParser.load())
30+
.withMemoryFactory(ByteArrayMemory::new)
31+
.withMachineFactory(PrismParser::create)
32+
.withImportValues(ImportValues.builder().addFunction(wasi.toHostFunctions()).build())
33+
.build();
34+
35+
calloc = instance.exports().function("calloc");
36+
pmSerializeParse = instance.exports().function("pm_serialize_parse");
37+
pmBufferInit = instance.exports().function("pm_buffer_init");
38+
pmBufferSizeof = instance.exports().function("pm_buffer_sizeof");
39+
pmBufferValue = instance.exports().function("pm_buffer_value");
40+
pmBufferLength = instance.exports().function("pm_buffer_length");
41+
}
42+
43+
@Override
44+
public byte[] serialize(byte[] packedOptions, byte[] sourceBytes, int sourceLength) {
45+
var sourcePointer = calloc.apply(1, sourceLength);
46+
instance.memory().write((int) sourcePointer[0], sourceBytes, 0, sourceLength);
47+
48+
var optionsPointer = calloc.apply(1, packedOptions.length);
49+
instance.memory().write((int) optionsPointer[0], packedOptions);
50+
51+
var bufferPointer = calloc.apply(pmBufferSizeof.apply()[0], 1);
52+
pmBufferInit.apply(bufferPointer);
53+
54+
pmSerializeParse.apply(
55+
bufferPointer[0], sourcePointer[0], sourceLength, optionsPointer[0]);
56+
57+
var result = instance.memory().readBytes(
58+
(int) pmBufferValue.apply(bufferPointer[0])[0],
59+
(int) pmBufferLength.apply(bufferPointer[0])[0]);
60+
61+
return result;
62+
}
63+
64+
@Override
65+
public void close() {
66+
if (wasi != null) {
67+
wasi.close();
68+
}
69+
}
70+
}

java-wasm/src/test/java/org/prism/DummyTest.java

Lines changed: 10 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,7 @@
11
package org.prism;
22

3-
import com.dylibso.chicory.runtime.ImportValues;
4-
import com.dylibso.chicory.runtime.Instance;
5-
import com.dylibso.chicory.wasi.WasiOptions;
6-
import com.dylibso.chicory.wasi.WasiPreview1;
7-
import com.dylibso.chicory.wasm.Parser;
8-
import com.dylibso.chicory.wasm.types.Value;
93
import org.junit.jupiter.api.Test;
104

11-
import java.nio.charset.StandardCharsets;
125
import java.util.EnumSet;
136

147
import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -31,42 +24,13 @@ public class DummyTest {
3124

3225
@Test
3326
public void test1() {
34-
WasiOptions wasiOpts = WasiOptions.builder().build();
35-
WasiPreview1 wasi = WasiPreview1.builder().withOptions(wasiOpts).build();
36-
var wasmPrism = Instance.builder(Parser.parse(DummyTest.class.getResourceAsStream("/prism.wasm")))
37-
.withImportValues(ImportValues.builder().addFunction(wasi.toHostFunctions()).build())
38-
.build();
39-
var memory = wasmPrism.memory();
40-
var calloc = wasmPrism.export("calloc");
41-
var pmSerializeParse = wasmPrism.export("pm_serialize_parse");
42-
var pmBufferInit = wasmPrism.export("pm_buffer_init");
43-
var pmBufferSizeof = wasmPrism.export("pm_buffer_sizeof");
44-
var pmBufferValue = wasmPrism.export("pm_buffer_value");
45-
var pmBufferLength = wasmPrism.export("pm_buffer_length");
46-
4727
// The Ruby source code to be processed
4828
var source = "1 + 1";
49-
var sourceBytes = source.getBytes(StandardCharsets.US_ASCII);
50-
51-
var sourcePointer = calloc.apply(1, source.length());
52-
memory.writeString((int) sourcePointer[0], source);
53-
54-
var optionsPointer = calloc.apply(1, packedOptions.length);
55-
memory.write((int) optionsPointer[0], packedOptions);
56-
57-
var bufferPointer = calloc.apply(pmBufferSizeof.apply()[0], 1);
58-
pmBufferInit.apply(bufferPointer);
59-
60-
pmSerializeParse.apply(
61-
bufferPointer[0], sourcePointer[0], source.length(), optionsPointer[0]);
62-
63-
var result = memory.readBytes(
64-
(int) pmBufferValue.apply(bufferPointer[0])[0],
65-
(int) pmBufferLength.apply(bufferPointer[0])[0]);
6629

67-
System.out.println("RESULT: " + new String(result));
68-
69-
ParseResult pr = Loader.load(result, sourceBytes);
30+
ParseResult pr = null;
31+
try (Prism prism = new PrismWASM()) {
32+
pr = prism.serializeParse(packedOptions, source);
33+
}
7034

7135
assertEquals(1, pr.value.childNodes().length);
7236
System.out.println("Nodes:");
@@ -80,7 +44,7 @@ public void test1Aot() {
8044
var source = "1 + 1";
8145

8246
ParseResult pr = null;
83-
try (Prism prism = new Prism()) {
47+
try (Prism prism = new PrismAOT()) {
8448
pr = prism.serializeParse(packedOptions, source);
8549
}
8650

@@ -92,45 +56,15 @@ public void test1Aot() {
9256

9357
@Test
9458
public void test2() {
95-
WasiOptions wasiOpts = WasiOptions.builder().build();
96-
WasiPreview1 wasi = WasiPreview1.builder().withOptions(wasiOpts).build();
97-
var wasmPrism = Instance.builder(Parser.parse(DummyTest.class.getResourceAsStream("/prism.wasm")))
98-
.withImportValues(ImportValues.builder().addFunction(wasi.toHostFunctions()).build())
99-
.build();
100-
var memory = wasmPrism.memory();
101-
var calloc = wasmPrism.export("calloc");
102-
var pmSerializeParse = wasmPrism.export("pm_serialize_parse");
103-
var pmBufferInit = wasmPrism.export("pm_buffer_init");
104-
var pmBufferSizeof = wasmPrism.export("pm_buffer_sizeof");
105-
var pmBufferValue = wasmPrism.export("pm_buffer_value");
106-
var pmBufferLength = wasmPrism.export("pm_buffer_length");
107-
10859
// The Ruby source code to be processed
10960
var source = "puts \"h\ne\nl\nl\no\n\"";
110-
var sourceBytes = source.getBytes(StandardCharsets.US_ASCII);
11161

112-
var sourcePointer = calloc.apply(1, source.length());
113-
memory.writeString((int) sourcePointer[0], source);
114-
115-
var optionsPointer = calloc.apply(1, packedOptions.length);
116-
memory.write((int) optionsPointer[0], packedOptions);
117-
118-
var bufferPointer = calloc.apply(pmBufferSizeof.apply()[0], 1);
119-
pmBufferInit.apply(bufferPointer);
120-
121-
pmSerializeParse.apply(
122-
bufferPointer[0], sourcePointer[0], source.length(), optionsPointer[0]);
123-
124-
var result = memory.readBytes(
125-
(int) pmBufferValue.apply(bufferPointer[0])[0],
126-
(int) pmBufferLength.apply(bufferPointer[0])[0]);
127-
128-
System.out.println("RESULT: " + new String(result));
129-
130-
ParseResult pr = Loader.load(result, sourceBytes);
62+
ParseResult pr = null;
63+
try (Prism prism = new PrismWASM()) {
64+
pr = prism.serializeParse(packedOptions, source);
65+
}
13166

13267
assertEquals(1, pr.value.childNodes().length);
133-
13468
System.out.println("Nodes:");
13569
System.out.println(pr.value.childNodes()[0]);
13670
assertTrue(pr.value.childNodes()[0].toString().contains("CallNode"));
@@ -142,7 +76,7 @@ public void test2Aot() {
14276
var source = "puts \"h\ne\nl\nl\no\n\"";
14377

14478
ParseResult pr = null;
145-
try (Prism prism = new Prism()) {
79+
try (Prism prism = new PrismAOT()) {
14680
pr = prism.serializeParse(packedOptions, source);
14781
}
14882

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package org.prism;
2+
3+
public class JRubyTest {
4+
}

0 commit comments

Comments
 (0)