0
# Memory Management
1
2
Linear memory allocation, access, and manipulation supporting both regular and shared memory models. Provides comprehensive memory operations including growth, data transfer, multi-threading coordination, and direct memory access for high-performance WebAssembly applications.
3
4
## Capabilities
5
6
### Linear Memory
7
8
WebAssembly linear memory providing byte-addressable storage with dynamic growth capabilities, bounds checking, and direct data access for efficient communication between Python and WebAssembly code.
9
10
```python { .api }
11
class Memory:
12
def __init__(self, store: Store, ty: MemoryType):
13
"""
14
Create a new linear memory with specified type.
15
16
Parameters:
17
- store: Store for memory allocation context
18
- ty: Memory type specifying size limits
19
20
Raises:
21
WasmtimeError: If memory allocation fails
22
"""
23
24
def type(self, store: Store) -> MemoryType:
25
"""
26
Get the memory type specification.
27
28
Parameters:
29
- store: Store context
30
31
Returns:
32
Memory type with current size limits
33
"""
34
35
def grow(self, store: Store, delta: int) -> int:
36
"""
37
Grow memory by specified number of pages.
38
39
Parameters:
40
- store: Store context
41
- delta: Number of 64KB pages to add (must be non-negative)
42
43
Returns:
44
Previous memory size in pages
45
46
Raises:
47
WasmtimeError: If growth fails or exceeds maximum size
48
"""
49
50
def size(self, store: Store) -> int:
51
"""
52
Get current memory size in pages.
53
54
Parameters:
55
- store: Store context
56
57
Returns:
58
Memory size in 64KB pages
59
"""
60
61
def data_len(self, store: Store) -> int:
62
"""
63
Get current memory size in bytes.
64
65
Parameters:
66
- store: Store context
67
68
Returns:
69
Memory size in bytes
70
"""
71
72
def data_ptr(self, store: Store) -> int:
73
"""
74
Get pointer to raw memory data.
75
76
Parameters:
77
- store: Store context
78
79
Returns:
80
Pointer to memory data (for advanced use with ctypes)
81
82
Warning:
83
Direct pointer access bypasses bounds checking
84
"""
85
86
def read(self, store: Store, start: int, stop: int) -> bytes:
87
"""
88
Read bytes from memory range.
89
90
Parameters:
91
- store: Store context
92
- start: Starting byte offset
93
- stop: Ending byte offset (exclusive)
94
95
Returns:
96
Bytes read from memory
97
98
Raises:
99
WasmtimeError: If range is out of bounds
100
"""
101
102
def write(self, store: Store, data: bytes, start: int = 0) -> None:
103
"""
104
Write bytes to memory starting at offset.
105
106
Parameters:
107
- store: Store context
108
- data: Bytes to write
109
- start: Starting byte offset (default: 0)
110
111
Raises:
112
WasmtimeError: If write would exceed memory bounds
113
"""
114
```
115
116
### Shared Memory
117
118
Multi-threaded shared memory supporting concurrent access from multiple WebAssembly instances, with proper synchronization primitives and cross-thread memory coordination.
119
120
```python { .api }
121
class SharedMemory:
122
def __init__(self, engine: Engine, ty: MemoryType):
123
"""
124
Create a new shared memory with specified type.
125
126
Parameters:
127
- engine: Engine for shared memory allocation
128
- ty: Memory type specifying size limits (must be shared-compatible)
129
130
Raises:
131
WasmtimeError: If shared memory creation fails or type incompatible
132
"""
133
134
def type(self) -> MemoryType:
135
"""
136
Get the shared memory type specification.
137
138
Returns:
139
Memory type with size limits and shared flag
140
"""
141
142
def as_memory(self, store: Store) -> Memory:
143
"""
144
Get a Memory view for use within a specific store.
145
146
Parameters:
147
- store: Store context for memory access
148
149
Returns:
150
Memory object providing access to shared memory
151
152
Note:
153
Multiple stores can have Memory views of the same SharedMemory
154
"""
155
```
156
157
## Usage Examples
158
159
### Basic Memory Operations
160
161
```python
162
import wasmtime
163
164
# Create memory type: 1-10 pages (64KB - 640KB)
165
limits = wasmtime.Limits(1, 10)
166
memory_type = wasmtime.MemoryType(limits)
167
168
# Create engine, store, and memory
169
engine = wasmtime.Engine()
170
store = wasmtime.Store(engine)
171
memory = wasmtime.Memory(store, memory_type)
172
173
# Check initial memory size
174
pages = memory.size(store)
175
bytes_size = memory.data_len(store)
176
print(f"Initial memory: {pages} pages ({bytes_size} bytes)")
177
178
# Write data to memory
179
message = b"Hello from Python!"
180
memory.write(store, message, 0)
181
182
# Read data back
183
read_data = memory.read(store, 0, len(message))
184
print(f"Read from memory: {read_data.decode('utf-8')}")
185
186
# Grow memory
187
old_size = memory.grow(store, 2) # Add 2 pages (128KB)
188
new_size = memory.size(store)
189
print(f"Memory grown from {old_size} to {new_size} pages")
190
```
191
192
### Memory with WebAssembly Module
193
194
```python
195
import wasmtime
196
197
# WebAssembly module that uses memory
198
wasm_bytes = wasmtime.wat2wasm('''
199
(module
200
(memory (export "memory") 1 10)
201
(func (export "write_hello") (param i32)
202
;; Write "Hello" starting at given offset
203
local.get 0
204
i32.const 72 ;; 'H'
205
i32.store8
206
local.get 0
207
i32.const 1
208
i32.add
209
i32.const 101 ;; 'e'
210
i32.store8
211
local.get 0
212
i32.const 2
213
i32.add
214
i32.const 108 ;; 'l'
215
i32.store8
216
local.get 0
217
i32.const 3
218
i32.add
219
i32.const 108 ;; 'l'
220
i32.store8
221
local.get 0
222
i32.const 4
223
i32.add
224
i32.const 111 ;; 'o'
225
i32.store8)
226
(func (export "read_byte") (param i32) (result i32)
227
local.get 0
228
i32.load8_u)
229
)
230
''')
231
232
engine = wasmtime.Engine()
233
store = wasmtime.Store(engine)
234
module = wasmtime.Module(engine, wasm_bytes)
235
instance = wasmtime.Instance(store, module, [])
236
237
# Get exported memory and functions
238
exports = instance.exports(store)
239
memory = exports["memory"]
240
write_hello = exports["write_hello"]
241
read_byte = exports["read_byte"]
242
243
# Call WebAssembly function to write to memory
244
write_hello(store, 10) # Write "Hello" starting at offset 10
245
246
# Read from memory using Python
247
hello_bytes = memory.read(store, 10, 15)
248
print(f"WebAssembly wrote: {hello_bytes.decode('utf-8')}")
249
250
# Read individual bytes using WebAssembly function
251
for i in range(5):
252
byte_val = read_byte(store, 10 + i)
253
print(f"Byte at {10 + i}: {byte_val} ('{chr(byte_val)}')")
254
```
255
256
### Shared Memory for Multi-threading
257
258
```python
259
import wasmtime
260
import threading
261
import time
262
263
# Create shared memory configuration
264
config = wasmtime.Config()
265
config.wasm_threads(True) # Enable threads support
266
engine = wasmtime.Engine(config)
267
268
# Create shared memory: 1-5 pages, shared
269
limits = wasmtime.Limits(1, 5)
270
memory_type = wasmtime.MemoryType(limits)
271
shared_memory = wasmtime.SharedMemory(engine, memory_type)
272
273
def worker_thread(thread_id: int):
274
"""Worker thread that accesses shared memory"""
275
# Each thread needs its own store
276
store = wasmtime.Store(engine)
277
278
# Get memory view for this store
279
memory = shared_memory.as_memory(store)
280
281
# Write thread-specific data
282
message = f"Thread {thread_id} was here!".encode('utf-8')
283
offset = thread_id * 32 # Each thread writes to different offset
284
memory.write(store, message, offset)
285
286
print(f"Thread {thread_id} wrote to offset {offset}")
287
288
# Start multiple threads
289
threads = []
290
for i in range(3):
291
thread = threading.Thread(target=worker_thread, args=(i,))
292
threads.append(thread)
293
thread.start()
294
295
# Wait for all threads to complete
296
for thread in threads:
297
thread.join()
298
299
# Read all data from main thread
300
main_store = wasmtime.Store(engine)
301
main_memory = shared_memory.as_memory(main_store)
302
303
print("Reading results from shared memory:")
304
for i in range(3):
305
offset = i * 32
306
# Read up to 32 bytes or until null terminator
307
data = main_memory.read(main_store, offset, offset + 32)
308
# Find null terminator if present
309
null_pos = data.find(b'\x00')
310
if null_pos != -1:
311
data = data[:null_pos]
312
print(f"Thread {i} data: {data.decode('utf-8')}")
313
```
314
315
### Memory Growth and Bounds Checking
316
317
```python
318
import wasmtime
319
320
# Create memory with tight limits for demonstration
321
limits = wasmtime.Limits(1, 3) # 1-3 pages (64KB - 192KB)
322
memory_type = wasmtime.MemoryType(limits)
323
324
engine = wasmtime.Engine()
325
store = wasmtime.Store(engine)
326
memory = wasmtime.Memory(store, memory_type)
327
328
# Fill initial page with data
329
page_size = 64 * 1024 # 64KB
330
test_data = b'A' * (page_size - 100) # Fill most of first page
331
memory.write(store, test_data, 0)
332
333
print(f"Initial memory: {memory.size(store)} pages")
334
335
# Try to write beyond current memory - should fail
336
try:
337
memory.write(store, b"This will fail", page_size + 1000)
338
except wasmtime.WasmtimeError as e:
339
print(f"Expected error: {e}")
340
341
# Grow memory and try again
342
old_size = memory.grow(store, 1) # Add 1 page
343
print(f"Memory grown from {old_size} to {memory.size(store)} pages")
344
345
# Now write to second page - should succeed
346
memory.write(store, b"Second page data", page_size + 100)
347
second_page_data = memory.read(store, page_size + 100, page_size + 116)
348
print(f"Second page contains: {second_page_data.decode('utf-8')}")
349
350
# Try to grow beyond maximum - should fail
351
try:
352
memory.grow(store, 5) # Would exceed 3-page maximum
353
except wasmtime.WasmtimeError as e:
354
print(f"Growth limit reached: {e}")
355
```
356
357
### Direct Memory Access with ctypes
358
359
```python
360
import wasmtime
361
import ctypes
362
363
# Create memory
364
engine = wasmtime.Engine()
365
store = wasmtime.Store(engine)
366
limits = wasmtime.Limits(1)
367
memory_type = wasmtime.MemoryType(limits)
368
memory = wasmtime.Memory(store, memory_type)
369
370
# Get direct pointer to memory (advanced usage)
371
ptr = memory.data_ptr(store)
372
size = memory.data_len(store)
373
374
# Create ctypes array from memory pointer
375
# WARNING: This bypasses WebAssembly bounds checking!
376
memory_array = (ctypes.c_ubyte * size).from_address(ptr)
377
378
# Write using ctypes (very fast, but unsafe)
379
test_string = b"Direct memory access"
380
for i, byte in enumerate(test_string):
381
memory_array[i] = byte
382
383
# Read back using normal memory API
384
read_data = memory.read(store, 0, len(test_string))
385
print(f"Direct write result: {read_data.decode('utf-8')}")
386
387
# Structure overlay example
388
class DataStruct(ctypes.Structure):
389
_fields_ = [
390
("magic", ctypes.c_uint32),
391
("version", ctypes.c_uint16),
392
("flags", ctypes.c_uint16),
393
("data_size", ctypes.c_uint32)
394
]
395
396
# Overlay structure on memory (at offset 100)
397
struct_ptr = ptr + 100
398
data_struct = DataStruct.from_address(struct_ptr)
399
400
# Write structured data
401
data_struct.magic = 0x12345678
402
data_struct.version = 1
403
data_struct.flags = 0b1010
404
data_struct.data_size = 1024
405
406
# Read back using memory API
407
struct_bytes = memory.read(store, 100, 100 + ctypes.sizeof(DataStruct))
408
magic_bytes = struct_bytes[:4]
409
magic_value = int.from_bytes(magic_bytes, 'little')
410
print(f"Magic value: 0x{magic_value:08x}")
411
```
412
413
### Memory Debugging and Inspection
414
415
```python
416
import wasmtime
417
418
def dump_memory(memory: wasmtime.Memory, store: wasmtime.Store,
419
start: int = 0, length: int = 256, width: int = 16):
420
"""Debug utility to dump memory contents in hex format"""
421
data = memory.read(store, start, start + length)
422
423
print(f"Memory dump from 0x{start:04x} to 0x{start + length:04x}:")
424
for i in range(0, len(data), width):
425
# Address
426
addr = start + i
427
print(f"{addr:04x}: ", end="")
428
429
# Hex bytes
430
line_data = data[i:i + width]
431
for j, byte in enumerate(line_data):
432
print(f"{byte:02x} ", end="")
433
434
# Padding for incomplete lines
435
for j in range(len(line_data), width):
436
print(" ", end="")
437
438
# ASCII representation
439
print(" |", end="")
440
for byte in line_data:
441
if 32 <= byte <= 126: # Printable ASCII
442
print(chr(byte), end="")
443
else:
444
print(".", end="")
445
print("|")
446
447
# Example usage
448
engine = wasmtime.Engine()
449
store = wasmtime.Store(engine)
450
limits = wasmtime.Limits(1)
451
memory = wasmtime.Memory(store, wasmtime.MemoryType(limits))
452
453
# Write some test data
454
test_data = b"Hello, WebAssembly World!\x00\x01\x02\x03\xff\xfe\xfd"
455
memory.write(store, test_data, 0)
456
457
# Dump memory contents
458
dump_memory(memory, store, 0, 64)
459
```