tidepool_codegen/
alloc.rs1use cranelift_codegen::ir::{self, types, BlockArg, InstBuilder, MemFlags, Value};
2use cranelift_frontend::FunctionBuilder;
3
4use crate::layout::*;
5
6pub fn emit_alloc_fast_path(
21 builder: &mut FunctionBuilder,
22 vmctx_val: Value,
23 size: u64,
24 gc_trigger_sig: ir::SigRef,
25 oom_func: ir::FuncRef,
26) -> Value {
27 let aligned_size = (size + 7) & !7;
28 let flags = MemFlags::trusted();
38
39 let alloc_ptr = builder
41 .ins()
42 .load(types::I64, flags, vmctx_val, VMCTX_ALLOC_PTR_OFFSET);
43
44 let size_val = builder.ins().iconst(types::I64, aligned_size as i64);
46 let new_ptr = builder.ins().iadd(alloc_ptr, size_val);
47
48 let alloc_limit = builder
50 .ins()
51 .load(types::I64, flags, vmctx_val, VMCTX_ALLOC_LIMIT_OFFSET);
52
53 let overflow = builder.ins().icmp(
55 ir::condcodes::IntCC::UnsignedGreaterThan,
56 new_ptr,
57 alloc_limit,
58 );
59
60 let slow_block = builder.create_block();
61 let fast_store_block = builder.create_block();
62 let continue_block = builder.create_block();
63 builder.append_block_param(continue_block, types::I64); builder
66 .ins()
67 .brif(overflow, slow_block, &[], fast_store_block, &[]);
68
69 builder.switch_to_block(fast_store_block);
71 builder.seal_block(fast_store_block);
72 builder
73 .ins()
74 .store(flags, new_ptr, vmctx_val, VMCTX_ALLOC_PTR_OFFSET);
75 builder
76 .ins()
77 .jump(continue_block, &[BlockArg::Value(alloc_ptr)]);
78
79 builder.switch_to_block(slow_block);
81 builder.seal_block(slow_block);
82
83 let gc_trigger_ptr = builder
84 .ins()
85 .load(types::I64, flags, vmctx_val, VMCTX_GC_TRIGGER_OFFSET);
86 builder
87 .ins()
88 .call_indirect(gc_trigger_sig, gc_trigger_ptr, &[vmctx_val]);
89
90 let post_gc_ptr = builder
92 .ins()
93 .load(types::I64, flags, vmctx_val, VMCTX_ALLOC_PTR_OFFSET);
94 let post_gc_limit = builder
95 .ins()
96 .load(types::I64, flags, vmctx_val, VMCTX_ALLOC_LIMIT_OFFSET);
97 let post_gc_new = builder.ins().iadd(post_gc_ptr, size_val);
98 let post_gc_overflow = builder.ins().icmp(
99 ir::condcodes::IntCC::UnsignedGreaterThan,
100 post_gc_new,
101 post_gc_limit,
102 );
103
104 let slow_fail_block = builder.create_block();
105 let slow_store_block = builder.create_block();
106
107 builder.ins().brif(
108 post_gc_overflow,
109 slow_fail_block,
110 &[],
111 slow_store_block,
112 &[],
113 );
114
115 builder.switch_to_block(slow_store_block);
117 builder.seal_block(slow_store_block);
118 builder
119 .ins()
120 .store(flags, post_gc_new, vmctx_val, VMCTX_ALLOC_PTR_OFFSET);
121 builder
122 .ins()
123 .jump(continue_block, &[BlockArg::Value(post_gc_ptr)]);
124
125 builder.switch_to_block(slow_fail_block);
127 builder.seal_block(slow_fail_block);
128 let oom_result = builder.ins().call(oom_func, &[]);
129 let poison_ptr = builder.inst_results(oom_result)[0];
130 builder
131 .ins()
132 .jump(continue_block, &[BlockArg::Value(poison_ptr)]);
133
134 builder.switch_to_block(continue_block);
136 builder.seal_block(continue_block);
137
138 builder.block_params(continue_block)[0]
139}