Skip to content

Commit da0cf24

Browse files
committed
Take alignment into consideration during malloc
1 parent 3d78163 commit da0cf24

File tree

8 files changed

+36
-30
lines changed

8 files changed

+36
-30
lines changed

crates/cli-support/src/js/binding.rs

+10-4
Original file line numberDiff line numberDiff line change
@@ -550,11 +550,13 @@ fn instruction(js: &mut JsBuilder, instr: &Instruction, log_error: &mut bool) ->
550550
| Instruction::CallTableElement(_)
551551
| Instruction::DeferCallCore(_) => {
552552
let invoc = Invocation::from(instr, js.cx.module)?;
553-
let (params, results) = invoc.params_results(js.cx);
553+
let (mut params, results) = invoc.params_results(js.cx);
554554

555555
let mut args = Vec::new();
556556
let tmp = js.tmp();
557557
if invoc.defer() {
558+
// substract alignment
559+
params -= 1;
558560
// If the call is deferred, the arguments to the function still need to be
559561
// accessible in the `finally` block, so we declare variables to hold the args
560562
// outside of the try-finally block and then set those to the args.
@@ -564,6 +566,8 @@ fn instruction(js: &mut JsBuilder, instr: &Instruction, log_error: &mut bool) ->
564566
writeln!(js.prelude, "{name} = {arg};").unwrap();
565567
args.push(name);
566568
}
569+
// add alignment
570+
args.push(String::from("4"));
567571
} else {
568572
// Otherwise, pop off the number of parameters for the function we're calling.
569573
for _ in 0..params {
@@ -813,12 +817,14 @@ fn instruction(js: &mut JsBuilder, instr: &Instruction, log_error: &mut bool) ->
813817
let func = js.cx.pass_to_wasm_function(kind.clone(), *mem)?;
814818
let malloc = js.cx.export_name_of(*malloc);
815819
let i = js.tmp();
820+
let align = std::cmp::max(kind.size(), 4);
816821
js.prelude(&format!(
817-
"const ptr{i} = {f}({0}, wasm.{malloc});",
822+
"const ptr{i} = {f}({0}, wasm.{malloc}, {align});",
818823
val,
819824
i = i,
820825
f = func,
821826
malloc = malloc,
827+
align = align,
822828
));
823829
js.prelude(&format!("const len{} = WASM_VECTOR_LEN;", i));
824830
js.push(format!("ptr{}", i));
@@ -922,7 +928,7 @@ fn instruction(js: &mut JsBuilder, instr: &Instruction, log_error: &mut bool) ->
922928
let malloc = js.cx.export_name_of(*malloc);
923929
let val = js.pop();
924930
js.prelude(&format!(
925-
"var ptr{i} = isLikeNone({0}) ? 0 : {f}({0}, wasm.{malloc});",
931+
"var ptr{i} = isLikeNone({0}) ? 0 : {f}({0}, wasm.{malloc}, 4);",
926932
val,
927933
i = i,
928934
f = func,
@@ -940,7 +946,7 @@ fn instruction(js: &mut JsBuilder, instr: &Instruction, log_error: &mut bool) ->
940946
let malloc = js.cx.export_name_of(*malloc);
941947
let i = js.tmp();
942948
js.prelude(&format!(
943-
"var ptr{i} = {f}({val}, wasm.{malloc});",
949+
"var ptr{i} = {f}({val}, wasm.{malloc}, 4);",
944950
val = val,
945951
i = i,
946952
f = func,

crates/cli-support/src/js/mod.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -1259,14 +1259,14 @@ impl<'a> Context<'a> {
12591259
"\
12601260
if (realloc === undefined) {{
12611261
const buf = cachedTextEncoder.encode(arg);
1262-
const ptr = malloc(buf.length) >>> 0;
1262+
const ptr = malloc(buf.length, 4) >>> 0;
12631263
{mem}().subarray(ptr, ptr + buf.length).set(buf);
12641264
WASM_VECTOR_LEN = buf.length;
12651265
return ptr;
12661266
}}
12671267
12681268
let len = arg.length;
1269-
let ptr = malloc(len) >>> 0;
1269+
let ptr = malloc(len, 4) >>> 0;
12701270
12711271
const mem = {mem}();
12721272
@@ -1294,7 +1294,7 @@ impl<'a> Context<'a> {
12941294
if (offset !== 0) {{
12951295
arg = arg.slice(offset);
12961296
}}
1297-
ptr = realloc(ptr, len, len = offset + arg.length * 3) >>> 0;
1297+
ptr = realloc(ptr, len, len = offset + arg.length * 3, 4) >>> 0;
12981298
const view = {mem}().subarray(ptr + offset, ptr + len);
12991299
const ret = encodeString(arg, view);
13001300
{debug_end}
@@ -1366,7 +1366,7 @@ impl<'a> Context<'a> {
13661366
self.global(&format!(
13671367
"
13681368
function {}(array, malloc) {{
1369-
const ptr = malloc(array.length * 4) >>> 0;
1369+
const ptr = malloc(array.length * 4, 4) >>> 0;
13701370
const mem = {}();
13711371
for (let i = 0; i < array.length; i++) {{
13721372
mem[ptr / 4 + i] = {}(array[i]);
@@ -1383,7 +1383,7 @@ impl<'a> Context<'a> {
13831383
self.global(&format!(
13841384
"
13851385
function {}(array, malloc) {{
1386-
const ptr = malloc(array.length * 4) >>> 0;
1386+
const ptr = malloc(array.length * 4, 4) >>> 0;
13871387
const mem = {}();
13881388
for (let i = 0; i < array.length; i++) {{
13891389
mem[ptr / 4 + i] = addHeapObject(array[i]);
@@ -1415,8 +1415,8 @@ impl<'a> Context<'a> {
14151415
self.expose_wasm_vector_len();
14161416
self.global(&format!(
14171417
"
1418-
function {}(arg, malloc) {{
1419-
const ptr = malloc(arg.length * {size}) >>> 0;
1418+
function {}(arg, malloc, align) {{
1419+
const ptr = malloc(arg.length * {size}, align) >>> 0;
14201420
{}().set(arg, ptr / {size});
14211421
WASM_VECTOR_LEN = arg.length;
14221422
return ptr;

crates/cli/tests/reference/result-string.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ export function exported() {
8585
return getStringFromWasm0(ptr1, len1);
8686
} finally {
8787
wasm.__wbindgen_add_to_stack_pointer(16);
88-
wasm.__wbindgen_free(deferred2_0, deferred2_1);
88+
wasm.__wbindgen_free(deferred2_0, deferred2_1, 4);
8989
}
9090
}
9191

crates/cli/tests/reference/string-arg.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -47,14 +47,14 @@ function passStringToWasm0(arg, malloc, realloc) {
4747

4848
if (realloc === undefined) {
4949
const buf = cachedTextEncoder.encode(arg);
50-
const ptr = malloc(buf.length) >>> 0;
50+
const ptr = malloc(buf.length, 4) >>> 0;
5151
getUint8Memory0().subarray(ptr, ptr + buf.length).set(buf);
5252
WASM_VECTOR_LEN = buf.length;
5353
return ptr;
5454
}
5555

5656
let len = arg.length;
57-
let ptr = malloc(len) >>> 0;
57+
let ptr = malloc(len, 4) >>> 0;
5858

5959
const mem = getUint8Memory0();
6060

@@ -70,7 +70,7 @@ function passStringToWasm0(arg, malloc, realloc) {
7070
if (offset !== 0) {
7171
arg = arg.slice(offset);
7272
}
73-
ptr = realloc(ptr, len, len = offset + arg.length * 3) >>> 0;
73+
ptr = realloc(ptr, len, len = offset + arg.length * 3, 4) >>> 0;
7474
const view = getUint8Memory0().subarray(ptr + offset, ptr + len);
7575
const ret = encodeString(arg, view);
7676

crates/cli/tests/reference/string-arg.wat

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
(module
2-
(type (;0;) (func (param i32) (result i32)))
3-
(type (;1;) (func (param i32 i32)))
2+
(type (;0;) (func (param i32 i32)))
3+
(type (;1;) (func (param i32 i32) (result i32)))
44
(type (;2;) (func (param i32 i32 i32) (result i32)))
55
(func $__wbindgen_realloc (;0;) (type 2) (param i32 i32 i32) (result i32))
6-
(func $__wbindgen_malloc (;1;) (type 0) (param i32) (result i32))
7-
(func $foo (;2;) (type 1) (param i32 i32))
6+
(func $__wbindgen_malloc (;1;) (type 1) (param i32 i32) (result i32))
7+
(func $foo (;2;) (type 0) (param i32 i32))
88
(memory (;0;) 17)
99
(export "memory" (memory 0))
1010
(export "foo" (func $foo))

crates/threads-xform/src/lib.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -344,9 +344,10 @@ fn inject_start(
344344
// we give ourselves a stack and we update our stack
345345
// pointer as the default stack pointer is surely wrong for us.
346346
|body| {
347-
// local = malloc(stack.size) [aka base]
347+
// local = malloc(stack.size, align) [aka base]
348348
with_temp_stack(body, memory, stack, |body| {
349349
body.i32_const(stack.size as i32)
350+
.i32_const(4)
350351
.call(malloc)
351352
.local_tee(local);
352353
});
@@ -368,7 +369,6 @@ fn inject_start(
368369
// Afterwards we need to initialize our thread-local state.
369370
body.i32_const(tls.size as i32)
370371
.i32_const(tls.align as i32)
371-
.drop() // TODO: need to actually respect alignment
372372
.call(malloc)
373373
.global_set(tls.base)
374374
.global_get(tls.base)
@@ -406,11 +406,13 @@ fn inject_destroy(
406406
|body| {
407407
body.local_get(tls_base)
408408
.i32_const(tls.size as i32)
409+
.i32_const(tls.align as i32)
409410
.call(free);
410411
},
411412
|body| {
412413
body.global_get(tls.base)
413414
.i32_const(tls.size as i32)
415+
.i32_const(tls.align as i32)
414416
.call(free);
415417

416418
// set tls.base = i32::MIN to trigger invalid memory
@@ -425,12 +427,14 @@ fn inject_destroy(
425427
// we're destroying somebody else's stack, so we can use our own
426428
body.local_get(stack_alloc)
427429
.i32_const(stack.size as i32)
430+
.i32_const(4)
428431
.call(free);
429432
},
430433
|body| {
431434
with_temp_stack(body, memory, stack, |body| {
432435
body.global_get(stack.alloc)
433436
.i32_const(stack.size as i32)
437+
.i32_const(4)
434438
.call(free);
435439
});
436440

guide/src/contributing/design/exporting-rust.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ import * as wasm from './foo_bg';
3333
function passStringToWasm(arg) {
3434
const buf = new TextEncoder('utf-8').encode(arg);
3535
const len = buf.length;
36-
const ptr = wasm.__wbindgen_malloc(len);
36+
const ptr = wasm.__wbindgen_malloc(len, 4);
3737
let array = new Uint8Array(wasm.memory.buffer);
3838
array.set(buf, ptr);
3939
return [ptr, len];
@@ -56,7 +56,7 @@ export function greet(arg0) {
5656
wasm.__wbindgen_boxed_str_free(ret);
5757
return realRet;
5858
} finally {
59-
wasm.__wbindgen_free(ptr0, len0);
59+
wasm.__wbindgen_free(ptr0, len0, 4);
6060
}
6161
}
6262
```

src/lib.rs

+3-7
Original file line numberDiff line numberDiff line change
@@ -1566,11 +1566,9 @@ pub mod __rt {
15661566

15671567
if_std! {
15681568
use std::alloc::{alloc, dealloc, realloc, Layout};
1569-
use std::mem;
15701569

15711570
#[no_mangle]
1572-
pub extern "C" fn __wbindgen_malloc(size: usize) -> *mut u8 {
1573-
let align = mem::align_of::<usize>();
1571+
pub extern "C" fn __wbindgen_malloc(size: usize, align: usize) -> *mut u8 {
15741572
if let Ok(layout) = Layout::from_size_align(size, align) {
15751573
unsafe {
15761574
if layout.size() > 0 {
@@ -1588,8 +1586,7 @@ pub mod __rt {
15881586
}
15891587

15901588
#[no_mangle]
1591-
pub unsafe extern "C" fn __wbindgen_realloc(ptr: *mut u8, old_size: usize, new_size: usize) -> *mut u8 {
1592-
let align = mem::align_of::<usize>();
1589+
pub unsafe extern "C" fn __wbindgen_realloc(ptr: *mut u8, old_size: usize, new_size: usize, align: usize) -> *mut u8 {
15931590
debug_assert!(old_size > 0);
15941591
debug_assert!(new_size > 0);
15951592
if let Ok(layout) = Layout::from_size_align(old_size, align) {
@@ -1611,13 +1608,12 @@ pub mod __rt {
16111608
}
16121609

16131610
#[no_mangle]
1614-
pub unsafe extern "C" fn __wbindgen_free(ptr: *mut u8, size: usize) {
1611+
pub unsafe extern "C" fn __wbindgen_free(ptr: *mut u8, size: usize, align: usize) {
16151612
// This happens for zero-length slices, and in that case `ptr` is
16161613
// likely bogus so don't actually send this to the system allocator
16171614
if size == 0 {
16181615
return
16191616
}
1620-
let align = mem::align_of::<usize>();
16211617
let layout = Layout::from_size_align_unchecked(size, align);
16221618
dealloc(ptr, layout);
16231619
}

0 commit comments

Comments
 (0)