Skip to content

Commit 434c20d

Browse files
committed
[GR-33296] Added Callback system for memory.grow.
PullRequest: graal/9622
2 parents 3778148 + 98f5caf commit 434c20d

File tree

4 files changed

+50
-1
lines changed

4 files changed

+50
-1
lines changed

wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/api/WebAssembly.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ public WebAssembly(WasmContext currentContext) {
101101

102102
addMember("mem_alloc", new Executable(args -> memAlloc(args)));
103103
addMember("mem_grow", new Executable(args -> memGrow(args)));
104+
addMember("mem_set_grow_callback", new Executable(args -> memSetGrowCallback(args)));
104105

105106
addMember("global_alloc", new Executable(args -> globalAlloc(args)));
106107
addMember("global_read", new Executable(args -> globalRead(args)));
@@ -586,6 +587,35 @@ public static long memGrow(WasmMemory memory, int delta) {
586587
return pageSize;
587588
}
588589

590+
private static Object memSetGrowCallback(Object[] args) {
591+
InteropLibrary lib = InteropLibrary.getUncached();
592+
if (!(args[0] instanceof WasmMemory)) {
593+
throw new WasmJsApiException(WasmJsApiException.Kind.TypeError, "First argument must be wasm memory");
594+
}
595+
if (!lib.isExecutable(args[1])) {
596+
throw new WasmJsApiException(WasmJsApiException.Kind.TypeError, "Second argument must be executable");
597+
}
598+
WasmMemory memory = (WasmMemory) args[0];
599+
return memSetGrowCallback(memory, args[1]);
600+
}
601+
602+
private static Object memSetGrowCallback(WasmMemory memory, Object callback) {
603+
memory.setGrowCallback(callback);
604+
return WasmVoidResult.getInstance();
605+
}
606+
607+
public static void invokeMemGrowCallback(WasmMemory memory) {
608+
Object callback = memory.getGrowCallback();
609+
if (callback != null) {
610+
InteropLibrary lib = InteropLibrary.getUncached();
611+
try {
612+
lib.execute(callback, memory);
613+
} catch (InteropException e) {
614+
throw new WasmJsApiException(WasmJsApiException.Kind.TypeError, "Unable to call memory grow callback", e);
615+
}
616+
}
617+
}
618+
589619
private static Object globalAlloc(Object[] args) {
590620
checkArgumentCount(args, 3);
591621

wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/memory/ByteArrayWasmMemory.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -146,6 +146,7 @@ public int declaredMaxSize() {
146146
@TruffleBoundary
147147
public synchronized boolean grow(int extraPageSize) {
148148
if (extraPageSize == 0) {
149+
invokeGrowCallback();
149150
return true;
150151
} else if (compareUnsigned(extraPageSize, maxAllowedSize) <= 0 && compareUnsigned(size() + extraPageSize, maxAllowedSize) <= 0) {
151152
try {
@@ -155,6 +156,7 @@ public synchronized boolean grow(int extraPageSize) {
155156
final byte[] newBuffer = new byte[targetByteSize];
156157
System.arraycopy(buffer, 0, newBuffer, 0, buffer.length);
157158
buffer = newBuffer;
159+
invokeGrowCallback();
158160
return true;
159161
} catch (OutOfMemoryError error) {
160162
throw WasmException.create(Failure.MEMORY_ALLOCATION_FAILED);

wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/memory/UnsafeWasmMemory.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ public int declaredMaxSize() {
159159
@TruffleBoundary
160160
public boolean grow(int extraPageSize) {
161161
if (extraPageSize == 0) {
162+
invokeGrowCallback();
162163
return true;
163164
} else if (compareUnsigned(extraPageSize, maxAllowedSize) <= 0 && compareUnsigned(size() + extraPageSize, maxAllowedSize) <= 0) {
164165
// Condition above and limit on maxPageSize (see ModuleLimits#MAX_MEMORY_SIZE) ensure
@@ -171,6 +172,7 @@ public boolean grow(int extraPageSize) {
171172
unsafe.freeMemory(startAddress);
172173
startAddress = updatedStartAddress;
173174
size += extraPageSize;
175+
invokeGrowCallback();
174176
return true;
175177
} catch (OutOfMemoryError error) {
176178
throw WasmException.create(Failure.MEMORY_ALLOCATION_FAILED);

wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/memory/WasmMemory.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,13 @@
6464
import com.oracle.truffle.api.library.ExportMessage;
6565
import com.oracle.truffle.api.nodes.Node;
6666
import com.oracle.truffle.api.profiles.BranchProfile;
67+
import org.graalvm.wasm.api.WebAssembly;
6768

6869
@ExportLibrary(InteropLibrary.class)
6970
public abstract class WasmMemory implements TruffleObject {
7071

72+
private Object growCallback = null;
73+
7174
public abstract void copy(Node node, int src, int dst, int n);
7275

7376
/**
@@ -489,4 +492,16 @@ public void writeArrayElement(long address, Object value,
489492
}
490493
store_i32_8(null, (int) address, rawValue);
491494
}
495+
496+
public void setGrowCallback(Object growCallback) {
497+
this.growCallback = growCallback;
498+
}
499+
500+
public Object getGrowCallback() {
501+
return growCallback;
502+
}
503+
504+
protected void invokeGrowCallback() {
505+
WebAssembly.invokeMemGrowCallback(this);
506+
}
492507
}

0 commit comments

Comments
 (0)