Skip to content

Commit 3e3877d

Browse files
authored
[c#] Align lists, free alloc'ed memory before return (bytecodealliance#1055)
* align lists, free alloc'ed memory before return * revert ws change
1 parent dea39d0 commit 3e3877d

File tree

1 file changed

+22
-13
lines changed

1 file changed

+22
-13
lines changed

crates/csharp/src/lib.rs

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1956,6 +1956,7 @@ struct FunctionBindgen<'a, 'b> {
19561956
blocks: Vec<Block>,
19571957
payloads: Vec<String>,
19581958
needs_cleanup_list: bool,
1959+
needs_native_alloc_list: bool,
19591960
cleanup: Vec<Cleanup>,
19601961
import_return_pointer_area_size: usize,
19611962
import_return_pointer_area_align: usize,
@@ -1989,6 +1990,7 @@ impl<'a, 'b> FunctionBindgen<'a, 'b> {
19891990
blocks: Vec::new(),
19901991
payloads: Vec::new(),
19911992
needs_cleanup_list: false,
1993+
needs_native_alloc_list: false,
19921994
cleanup: Vec::new(),
19931995
import_return_pointer_area_size: 0,
19941996
import_return_pointer_area_align: 0,
@@ -2185,7 +2187,7 @@ impl Bindgen for FunctionBindgen<'_, '_> {
21852187
Instruction::F64Load { offset } => results.push(format!("BitConverter.ToDouble(new Span<byte>((void*)({} + {offset}), 8))",operands[0])),
21862188
Instruction::I32Store { offset }
21872189
| Instruction::PointerStore { offset }
2188-
| Instruction::LengthStore { offset } => uwriteln!(self.src, "BitConverter.TryWriteBytes(new Span<byte>((void*)({} + {offset}), 4), unchecked((int){}));", operands[1], operands[0]),
2190+
| Instruction::LengthStore { offset } => uwriteln!(self.src, "BitConverter.TryWriteBytes(new Span<byte>((void*)({} + {offset}), 4), {});", operands[1], operands[0]),
21892191
Instruction::I32Store8 { offset } => uwriteln!(self.src, "*(byte*)({} + {offset}) = (byte){};", operands[1], operands[0]),
21902192
Instruction::I32Store16 { offset } => uwriteln!(self.src, "BitConverter.TryWriteBytes(new Span<byte>((void*)({} + {offset}), 2), (short){});", operands[1], operands[0]),
21912193
Instruction::I64Store { offset } => uwriteln!(self.src, "BitConverter.TryWriteBytes(new Span<byte>((void*)({} + {offset}), 8), unchecked((long){}));", operands[1], operands[0]),
@@ -2601,16 +2603,18 @@ impl Bindgen for FunctionBindgen<'_, '_> {
26012603
let ty = self.gen.type_name_with_qualifier(element, true);
26022604
let index = self.locals.tmp("index");
26032605

2604-
let buffer: String = self.locals.tmp("buffer");
2605-
let gc_handle = self.locals.tmp("gcHandle");
26062606
let address = self.locals.tmp("address");
2607+
let buffer_size = self.locals.tmp("bufferSize");
2608+
//TODO: wasm64
2609+
let align = self.gen.gen.sizes.align(element).align_wasm32();
2610+
self.needs_native_alloc_list = true;
26072611

26082612
uwrite!(
26092613
self.src,
26102614
"
2611-
byte[] {buffer} = new byte[{size} * {list}.Count];
2612-
var {gc_handle} = GCHandle.Alloc({buffer}, GCHandleType.Pinned);
2613-
var {address} = {gc_handle}.AddrOfPinnedObject();
2615+
var {buffer_size} = {size} * (nuint){list}.Count;
2616+
var {address} = NativeMemory.AlignedAlloc({buffer_size}, {align});
2617+
nativeAllocs.Add((IntPtr){address});
26142618
26152619
for (int {index} = 0; {index} < {list}.Count; ++{index}) {{
26162620
{ty} {block_element} = {list}[{index}];
@@ -2620,12 +2624,6 @@ impl Bindgen for FunctionBindgen<'_, '_> {
26202624
"
26212625
);
26222626

2623-
if realloc.is_none() {
2624-
self.cleanup.push(Cleanup {
2625-
address: gc_handle.clone(),
2626-
});
2627-
}
2628-
26292627
results.push(format!("(int){address}"));
26302628
results.push(format!("{list}.Count"));
26312629
}
@@ -2829,6 +2827,17 @@ impl Bindgen for FunctionBindgen<'_, '_> {
28292827
uwriteln!(self.src, "{address}.Free();");
28302828
}
28312829

2830+
if self.needs_native_alloc_list {
2831+
self.src.insert_str(0, "var nativeAllocs = new List<IntPtr>();
2832+
");
2833+
2834+
uwriteln!(self.src, "\
2835+
foreach (var nativeAlloc in nativeAllocs)
2836+
{{
2837+
NativeMemory.AlignedFree((void*)nativeAlloc);
2838+
}}");
2839+
}
2840+
28322841
if !matches!((self.gen.direction, self.kind), (Direction::Import, FunctionKind::Constructor(_))) {
28332842
match func.results.len() {
28342843
0 => (),
@@ -2920,7 +2929,7 @@ impl Bindgen for FunctionBindgen<'_, '_> {
29202929
Direction::Export => {
29212930
self.gen.gen.needs_rep_table = true;
29222931
let local_rep = self.locals.tmp("localRep");
2923-
let export_name = self.gen.gen.all_resources[&id].export_impl_name();
2932+
let export_name = self.gen.gen.all_resources[&id].export_impl_name();
29242933
if is_own {
29252934
// Note that we set `{op}.Handle` to zero below to ensure that application code doesn't
29262935
// try to use the instance while the host has ownership. We'll set it back to non-zero

0 commit comments

Comments
 (0)