Skip to content

Commit e852440

Browse files
committed
refactor(jit): parameterize tail wrapper lowering
1 parent 2b8b744 commit e852440

1 file changed

Lines changed: 118 additions & 104 deletions

File tree

src/vm/jit/native/lower.rs

Lines changed: 118 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -189,20 +189,30 @@ pub(crate) fn compile_tail_status_body(status: i32) -> VmResult<CompiledTailFunc
189189
)
190190
}
191191

192-
pub(crate) fn compile_tail_side_link_body(
192+
fn compile_tail_side_link_body_with_abi(
193+
prefix: &str,
193194
slot_address: usize,
194195
deopt_status: i32,
196+
abi: TailCallAbi,
195197
) -> VmResult<CompiledTailFunction> {
198+
debug_assert!(matches!(abi, TailCallAbi::Plain | TailCallAbi::Owned));
196199
compile_standalone_native_function(
197-
"pd_vm_tail_side_link",
198-
|pointer_type, _| tail_entry_signature(pointer_type),
200+
prefix,
201+
move |pointer_type, _| abi.tail_signature(pointer_type),
199202
move |builder, pointer_type, _| {
200203
let entry = builder.create_block();
201204
let deopt = builder.create_block();
202205
let linked = builder.create_block();
203206
builder.append_block_params_for_function_params(entry);
204207
builder.switch_to_block(entry);
205208
let vm_ptr = builder.block_params(entry)[0];
209+
let args = match abi {
210+
TailCallAbi::Plain => vec![vm_ptr],
211+
TailCallAbi::Owned => vec![vm_ptr, builder.block_params(entry)[1]],
212+
TailCallAbi::Inherited => {
213+
unreachable!("inherited packets use the trace dispatcher")
214+
}
215+
};
206216
let slot_address = iconst_ptr_from_addr(builder, pointer_type, slot_address)?;
207217
let target = builder
208218
.ins()
@@ -215,83 +225,130 @@ pub(crate) fn compile_tail_side_link_body(
215225
builder.ins().return_(&[status]);
216226

217227
builder.switch_to_block(linked);
218-
let signature = builder.import_signature(tail_entry_signature(pointer_type));
219-
builder
220-
.ins()
221-
.return_call_indirect(signature, target, &[vm_ptr]);
228+
let signature = builder.import_signature(abi.tail_signature(pointer_type));
229+
builder.ins().return_call_indirect(signature, target, &args);
222230
Ok(())
223231
},
224232
)
225233
}
226234

227-
pub(crate) fn compile_system_tail_wrapper(root_entry: *const u8) -> VmResult<CompiledTailFunction> {
235+
pub(crate) fn compile_tail_side_link_body(
236+
slot_address: usize,
237+
deopt_status: i32,
238+
) -> VmResult<CompiledTailFunction> {
239+
compile_tail_side_link_body_with_abi(
240+
"pd_vm_tail_side_link",
241+
slot_address,
242+
deopt_status,
243+
TailCallAbi::Plain,
244+
)
245+
}
246+
247+
#[derive(Clone, Copy)]
248+
enum TailCallAbi {
249+
Plain,
250+
Inherited,
251+
Owned,
252+
}
253+
254+
impl TailCallAbi {
255+
fn system_signature(
256+
self,
257+
pointer_type: cranelift_codegen::ir::Type,
258+
call_conv: CallConv,
259+
) -> Signature {
260+
match self {
261+
Self::Plain | Self::Inherited => entry_signature(pointer_type, call_conv),
262+
Self::Owned => system_owned_entry_signature(pointer_type, call_conv),
263+
}
264+
}
265+
266+
fn tail_signature(self, pointer_type: cranelift_codegen::ir::Type) -> Signature {
267+
match self {
268+
Self::Plain => tail_entry_signature(pointer_type),
269+
Self::Inherited => inherited_tail_entry_signature(pointer_type),
270+
Self::Owned => tail_owned_entry_signature(pointer_type),
271+
}
272+
}
273+
}
274+
275+
fn create_inherited_state_packet(
276+
builder: &mut FunctionBuilder<'_>,
277+
pointer_type: cranelift_codegen::ir::Type,
278+
) -> VmResult<cranelift_codegen::ir::Value> {
279+
let pointer_bytes = pointer_type.bits() / 8;
280+
let packet_bytes = pointer_bytes
281+
.checked_mul((MAX_INHERITED_ENTRY_VALUES + 7) as u32)
282+
.ok_or_else(|| {
283+
VmError::JitNative("native inherited-state packet is too large".to_string())
284+
})?;
285+
let packet = builder.create_sized_stack_slot(StackSlotData::new(
286+
StackSlotKind::ExplicitSlot,
287+
packet_bytes,
288+
pointer_bytes.trailing_zeros() as u8,
289+
));
290+
let packet_ptr = builder.ins().stack_addr(pointer_type, packet, 0);
291+
let inactive = builder.ins().iconst(pointer_type, 0);
292+
builder.ins().store(
293+
MemFlags::new(),
294+
inactive,
295+
packet_ptr,
296+
INHERITED_STATE_ACTIVE_OFFSET,
297+
);
298+
builder.ins().store(
299+
MemFlags::new(),
300+
inactive,
301+
packet_ptr,
302+
INHERITED_STATE_DYNAMIC_TARGET_OFFSET,
303+
);
304+
Ok(packet_ptr)
305+
}
306+
307+
fn compile_system_tail_wrapper_with_abi(
308+
prefix: &str,
309+
root_entry: *const u8,
310+
abi: TailCallAbi,
311+
) -> VmResult<CompiledTailFunction> {
228312
let root_entry = root_entry as usize;
229313
compile_standalone_native_function(
230-
"pd_vm_tail_wrapper",
231-
entry_signature,
314+
prefix,
315+
move |pointer_type, call_conv| abi.system_signature(pointer_type, call_conv),
232316
move |builder, pointer_type, _| {
233317
let entry = builder.create_block();
234318
builder.append_block_params_for_function_params(entry);
235319
builder.switch_to_block(entry);
236320
let vm_ptr = builder.block_params(entry)[0];
321+
let args = match abi {
322+
TailCallAbi::Plain => vec![vm_ptr],
323+
TailCallAbi::Inherited => {
324+
vec![
325+
vm_ptr,
326+
create_inherited_state_packet(builder, pointer_type)?,
327+
]
328+
}
329+
TailCallAbi::Owned => vec![vm_ptr, builder.block_params(entry)[1]],
330+
};
237331
let root_entry = iconst_ptr_from_addr(builder, pointer_type, root_entry)?;
238-
let signature = builder.import_signature(tail_entry_signature(pointer_type));
239-
let call = builder
240-
.ins()
241-
.call_indirect(signature, root_entry, &[vm_ptr]);
332+
let signature = builder.import_signature(abi.tail_signature(pointer_type));
333+
let call = builder.ins().call_indirect(signature, root_entry, &args);
242334
let status = builder.inst_results(call)[0];
243335
builder.ins().return_(&[status]);
244336
Ok(())
245337
},
246338
)
247339
}
248340

341+
pub(crate) fn compile_system_tail_wrapper(root_entry: *const u8) -> VmResult<CompiledTailFunction> {
342+
compile_system_tail_wrapper_with_abi("pd_vm_tail_wrapper", root_entry, TailCallAbi::Plain)
343+
}
344+
249345
pub(crate) fn compile_system_inherited_tail_wrapper(
250346
root_entry: *const u8,
251347
) -> VmResult<CompiledTailFunction> {
252-
let root_entry = root_entry as usize;
253-
compile_standalone_native_function(
348+
compile_system_tail_wrapper_with_abi(
254349
"pd_vm_inherited_tail_wrapper",
255-
entry_signature,
256-
move |builder, pointer_type, _| {
257-
let entry = builder.create_block();
258-
builder.append_block_params_for_function_params(entry);
259-
builder.switch_to_block(entry);
260-
let vm_ptr = builder.block_params(entry)[0];
261-
let pointer_bytes = pointer_type.bits() / 8;
262-
let packet_bytes = pointer_bytes
263-
.checked_mul((MAX_INHERITED_ENTRY_VALUES + 7) as u32)
264-
.ok_or_else(|| {
265-
VmError::JitNative("native inherited-state packet is too large".to_string())
266-
})?;
267-
let packet = builder.create_sized_stack_slot(StackSlotData::new(
268-
StackSlotKind::ExplicitSlot,
269-
packet_bytes,
270-
pointer_bytes.trailing_zeros() as u8,
271-
));
272-
let packet_ptr = builder.ins().stack_addr(pointer_type, packet, 0);
273-
let inactive = builder.ins().iconst(pointer_type, 0);
274-
builder.ins().store(
275-
MemFlags::new(),
276-
inactive,
277-
packet_ptr,
278-
INHERITED_STATE_ACTIVE_OFFSET,
279-
);
280-
builder.ins().store(
281-
MemFlags::new(),
282-
inactive,
283-
packet_ptr,
284-
INHERITED_STATE_DYNAMIC_TARGET_OFFSET,
285-
);
286-
let root_entry = iconst_ptr_from_addr(builder, pointer_type, root_entry)?;
287-
let signature = builder.import_signature(inherited_tail_entry_signature(pointer_type));
288-
let call = builder
289-
.ins()
290-
.call_indirect(signature, root_entry, &[vm_ptr, packet_ptr]);
291-
let status = builder.inst_results(call)[0];
292-
builder.ins().return_(&[status]);
293-
Ok(())
294-
},
350+
root_entry,
351+
TailCallAbi::Inherited,
295352
)
296353
}
297354

@@ -455,35 +512,11 @@ pub(crate) fn compile_tail_owned_side_link_body(
455512
slot_address: usize,
456513
deopt_status: i32,
457514
) -> VmResult<CompiledTailFunction> {
458-
compile_standalone_native_function(
515+
compile_tail_side_link_body_with_abi(
459516
"pd_vm_tail_owned_side_link",
460-
|pointer_type, _| tail_owned_entry_signature(pointer_type),
461-
move |builder, pointer_type, _| {
462-
let entry = builder.create_block();
463-
let deopt = builder.create_block();
464-
let linked = builder.create_block();
465-
builder.append_block_params_for_function_params(entry);
466-
builder.switch_to_block(entry);
467-
let vm_ptr = builder.block_params(entry)[0];
468-
let owned_slot = builder.block_params(entry)[1];
469-
let slot_address = iconst_ptr_from_addr(builder, pointer_type, slot_address)?;
470-
let target = builder
471-
.ins()
472-
.atomic_load(pointer_type, MemFlags::new(), slot_address);
473-
let is_null = builder.ins().icmp_imm(IntCC::Equal, target, 0);
474-
builder.ins().brif(is_null, deopt, &[], linked, &[]);
475-
476-
builder.switch_to_block(deopt);
477-
let status = builder.ins().iconst(types::I32, i64::from(deopt_status));
478-
builder.ins().return_(&[status]);
479-
480-
builder.switch_to_block(linked);
481-
let signature = builder.import_signature(tail_owned_entry_signature(pointer_type));
482-
builder
483-
.ins()
484-
.return_call_indirect(signature, target, &[vm_ptr, owned_slot]);
485-
Ok(())
486-
},
517+
slot_address,
518+
deopt_status,
519+
TailCallAbi::Owned,
487520
)
488521
}
489522

@@ -530,26 +563,7 @@ pub(crate) fn compile_tail_owned_clear_body(success_status: i32) -> VmResult<Com
530563
pub(crate) fn compile_system_owned_tail_wrapper(
531564
root_entry: *const u8,
532565
) -> VmResult<CompiledTailFunction> {
533-
let root_entry = root_entry as usize;
534-
compile_standalone_native_function(
535-
"pd_vm_tail_owned_wrapper",
536-
system_owned_entry_signature,
537-
move |builder, pointer_type, _| {
538-
let entry = builder.create_block();
539-
builder.append_block_params_for_function_params(entry);
540-
builder.switch_to_block(entry);
541-
let vm_ptr = builder.block_params(entry)[0];
542-
let owned_slot = builder.block_params(entry)[1];
543-
let root_entry = iconst_ptr_from_addr(builder, pointer_type, root_entry)?;
544-
let signature = builder.import_signature(tail_owned_entry_signature(pointer_type));
545-
let call = builder
546-
.ins()
547-
.call_indirect(signature, root_entry, &[vm_ptr, owned_slot]);
548-
let status = builder.inst_results(call)[0];
549-
builder.ins().return_(&[status]);
550-
Ok(())
551-
},
552-
)
566+
compile_system_tail_wrapper_with_abi("pd_vm_tail_owned_wrapper", root_entry, TailCallAbi::Owned)
553567
}
554568

555569
fn try_compile_ssa_trace(

0 commit comments

Comments
 (0)