Skip to content

Commit 1b3a9f0

Browse files
feat(runtime): Simplify copy and fill polyfills in Memory module (#2148)
Co-authored-by: Oscar Spencer <oscar.spen@gmail.com>
1 parent 18b9cd2 commit 1b3a9f0

File tree

2 files changed

+46
-22
lines changed

2 files changed

+46
-22
lines changed

stdlib/runtime/unsafe/memory.gr

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,38 +4,42 @@ module Memory
44
from "runtime/gc" include GC
55
use GC.{ malloc, free, incRef, decRef }
66
from "runtime/unsafe/wasmi32" include WasmI32
7-
use WasmI32.{ (+), (-), (<<), (==), (!=), ltU as (<) }
7+
use WasmI32.{ (+), (-), (!=), ltU as (<), gtU as (>) }
88

99
provide { malloc, free, incRef, decRef }
1010

11-
provide let copy = (dest, src, n) => {
12-
let mut dest = dest
13-
let mut src = src
14-
let mut n = n
11+
/**
12+
* Copies the source memory region to the destination memory region. Regions may overlap.
13+
*
14+
* @param dest: The destination memory region
15+
* @param src: The source memory region
16+
* @param length: The length of the memory region to copy
17+
*/
18+
provide let copy = (dest, src, length) => {
1519
if (dest != src) {
1620
if (dest < src) {
17-
while (n != 0n) {
18-
WasmI32.store8(dest, WasmI32.load8U(src, 0n), 0n)
19-
dest += 1n
20-
src += 1n
21-
n -= 1n
21+
for (let mut i = 0n; i < length; i += 1n) {
22+
WasmI32.store8(dest, WasmI32.load8U(src, i), i)
2223
}
2324
} else {
24-
while (n != 0n) {
25-
n -= 1n
26-
WasmI32.store8(dest + n, WasmI32.load8U(src + n, 0n), 0n)
25+
// Copy backwards to ensure we do not overwrite on overlapping regions
26+
for (let mut n = length; n > 0n; n -= 1n) {
27+
WasmI32.store8(dest + n - 1n, WasmI32.load8U(src + n - 1n, 0n), 0n)
2728
}
2829
}
2930
}
3031
}
3132

32-
provide let fill = (dest, c, n) => {
33-
let mut dest = dest
34-
let mut n = n
35-
while (n != 0n) {
36-
WasmI32.store8(dest, c, 0n)
37-
dest += 1n
38-
n -= 1n
33+
/**
34+
* Fills the given memory region with the given 1-byte value. Values larger than 1 byte will be truncated.
35+
*
36+
* @param dest: The destination memory region
37+
* @param value: The value to fill the memory region with
38+
* @param length: The length of the memory region to fill
39+
*/
40+
provide let fill = (dest, value, length) => {
41+
for (let mut i = 0n; i < length; i += 1n) {
42+
WasmI32.store8(dest, value, i)
3943
}
4044
}
4145

stdlib/runtime/unsafe/memory.md

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,15 +33,35 @@ decRef : (userPtr: WasmI32) => WasmI32
3333
### Memory.**copy**
3434

3535
```grain
36-
copy : (dest: WasmI32, src: WasmI32, n: WasmI32) => Void
36+
copy : (dest: WasmI32, src: WasmI32, length: WasmI32) => Void
3737
```
3838

39+
Copies the source memory region to the destination memory region. Regions may overlap.
40+
41+
Parameters:
42+
43+
|param|type|description|
44+
|-----|----|-----------|
45+
|`dest`|`WasmI32`|The destination memory region|
46+
|`src`|`WasmI32`|The source memory region|
47+
|`length`|`WasmI32`|The length of the memory region to copy|
48+
3949
### Memory.**fill**
4050

4151
```grain
42-
fill : (dest: WasmI32, c: WasmI32, n: WasmI32) => Void
52+
fill : (dest: WasmI32, value: WasmI32, length: WasmI32) => Void
4353
```
4454

55+
Fills the given memory region with the given 1-byte value. Values larger than 1 byte will be truncated.
56+
57+
Parameters:
58+
59+
|param|type|description|
60+
|-----|----|-----------|
61+
|`dest`|`WasmI32`|The destination memory region|
62+
|`value`|`WasmI32`|The value to fill the memory region with|
63+
|`length`|`WasmI32`|The length of the memory region to fill|
64+
4565
### Memory.**compare**
4666

4767
```grain

0 commit comments

Comments
 (0)