@@ -14,18 +14,20 @@ use std::time::Instant;
1414use crate :: vm:: native:: ExecutableBuffer ;
1515#[ cfg( feature = "cranelift-jit" ) ]
1616use crate :: vm:: native:: {
17- HeapIntrinsicAddrs , HeapIntrinsicRefs , OP_BUILTIN_CALL , OP_CALL , STATUS_CONTINUE , STATUS_ERROR ,
18- alloc_buffer_signature, alloc_byte_buffer_entry_address, alloc_value_buffer_entry_address,
19- aot_call_boundary_interrupt_entry_address, array_push_entry_address, box_heap_value_signature,
20- clear_value_slot_entry_address, clone_value_signature, clone_value_to_slot_entry_address,
21- collection_get_signature, collection_mutation_signature, collection_set_entry_address,
22- copy_bytes_entry_address, copy_bytes_signature, detect_native_stack_layout, entry_signature,
23- free_buffer_signature, helper_entry_offset, helper_signature,
17+ HeapIntrinsicAddrs , HeapIntrinsicRefs , NativeFrameState , OP_BUILTIN_CALL , OP_CALL ,
18+ STATUS_CONTINUE , STATUS_ERROR , alloc_buffer_signature, alloc_byte_buffer_entry_address,
19+ alloc_value_buffer_entry_address, aot_call_boundary_interrupt_entry_address,
20+ array_push_entry_address, box_heap_value_signature, clear_value_slot_entry_address,
21+ clone_value_signature, clone_value_to_slot_entry_address, collection_get_signature,
22+ collection_mutation_signature, collection_set_entry_address, copy_bytes_entry_address,
23+ copy_bytes_signature, detect_native_stack_layout, entry_signature, frame_state_entry_address,
24+ frame_state_signature, free_buffer_signature, helper_entry_offset, helper_signature,
2425 init_null_value_slot_entry_address, jump_with_status, pack_shared_signature, resolve_offsets,
25- restore_exit_signature, restore_exit_state_entry_address,
26- shared_array_from_buffer_entry_address, shared_bytes_from_buffer_entry_address,
27- shared_string_from_buffer_entry_address, value_eq_entry_address, value_eq_signature,
28- value_slot_signature, write_heap_value_to_slot_entry_address, zero_bytes_entry_address,
26+ restore_active_exit_state_entry_address, restore_exit_signature,
27+ restore_exit_state_entry_address, shared_array_from_buffer_entry_address,
28+ shared_bytes_from_buffer_entry_address, shared_string_from_buffer_entry_address,
29+ value_eq_entry_address, value_eq_signature, value_slot_signature,
30+ write_heap_value_to_slot_entry_address, zero_bytes_entry_address,
2931} ;
3032use crate :: vm:: { Program , Value , Vm , VmError , VmResult } ;
3133#[ cfg( feature = "cranelift-jit" ) ]
@@ -219,6 +221,7 @@ struct AotDeoptHelperRefs {
219221 helper_ref : cranelift_codegen:: ir:: SigRef ,
220222 vm_status_ref : cranelift_codegen:: ir:: SigRef ,
221223 interrupt_ref : cranelift_codegen:: ir:: SigRef ,
224+ frame_state_ref : cranelift_codegen:: ir:: SigRef ,
222225 clone_value_ref : cranelift_codegen:: ir:: SigRef ,
223226 value_eq_ref : cranelift_codegen:: ir:: SigRef ,
224227 init_null_slot_ref : cranelift_codegen:: ir:: SigRef ,
@@ -233,6 +236,7 @@ struct AotDeoptHelperRefs {
233236#[ derive( Clone , Copy ) ]
234237struct AotDeoptHelperAddrs {
235238 aot_interrupt : usize ,
239+ frame_state : usize ,
236240 clone_value : usize ,
237241 value_eq : usize ,
238242 init_null_slot : usize ,
@@ -381,6 +385,7 @@ fn compile_ssa(
381385 let sigs_started = Instant :: now ( ) ;
382386 let helper_sig = helper_signature ( pointer_type, call_conv) ;
383387 let alloc_buffer_sig = alloc_buffer_signature ( pointer_type, call_conv) ;
388+ let frame_state_sig = frame_state_signature ( pointer_type, call_conv) ;
384389 let free_buffer_sig = free_buffer_signature ( pointer_type, call_conv) ;
385390 let pack_shared_sig = pack_shared_signature ( pointer_type, call_conv) ;
386391 let copy_bytes_sig = copy_bytes_signature ( pointer_type, call_conv) ;
@@ -408,14 +413,15 @@ fn compile_ssa(
408413 } ;
409414 let helper_addrs = AotDeoptHelperAddrs {
410415 aot_interrupt : aot_call_boundary_interrupt_entry_address ( ) ,
416+ frame_state : frame_state_entry_address ( ) ,
411417 clone_value : clone_value_to_slot_entry_address ( ) ,
412418 value_eq : value_eq_entry_address ( ) ,
413419 init_null_slot : init_null_value_slot_entry_address ( ) ,
414420 clear_value_slot : clear_value_slot_entry_address ( ) ,
415421 box_heap_value : write_heap_value_to_slot_entry_address ( ) ,
416422 array_push : array_push_entry_address ( ) ,
417423 collection_set : collection_set_entry_address ( ) ,
418- restore_exit : restore_exit_state_entry_address ( ) ,
424+ restore_exit : restore_active_exit_state_entry_address ( ) ,
419425 } ;
420426 let addr_setup_elapsed = addr_setup_started. elapsed ( ) ;
421427
@@ -462,6 +468,7 @@ fn compile_ssa(
462468 helper_ref : b. import_signature ( helper_sig) ,
463469 vm_status_ref : b. import_signature ( vm_status_sig) ,
464470 interrupt_ref : b. import_signature ( interrupt_sig) ,
471+ frame_state_ref : b. import_signature ( frame_state_sig) ,
465472 clone_value_ref : b. import_signature ( clone_value_sig) ,
466473 value_eq_ref : b. import_signature ( value_eq_sig) ,
467474 init_null_slot_ref : b. import_signature ( value_slot_sig. clone ( ) ) ,
@@ -558,6 +565,8 @@ fn compile_ssa(
558565 pointer_type,
559566 layout,
560567 offsets,
568+ helper_refs,
569+ helper_addrs,
561570 checkpoint,
562571 ) ?;
563572 b. ins ( )
@@ -685,15 +694,57 @@ fn compile_ssa(
685694}
686695
687696#[ cfg( feature = "cranelift-jit" ) ]
697+ #[ allow( clippy:: too_many_arguments) ]
688698fn load_checkpoint_args (
689699 b : & mut FunctionBuilder ,
690700 vm_ptr : cranelift_codegen:: ir:: Value ,
691701 exit_block : Block ,
692702 pointer_type : cranelift_codegen:: ir:: Type ,
693703 layout : crate :: vm:: native:: NativeStackLayout ,
694704 offsets : crate :: vm:: native:: ResolvedOffsets ,
705+ helper_refs : AotDeoptHelperRefs ,
706+ helper_addrs : AotDeoptHelperAddrs ,
695707 checkpoint : & AotCheckpoint ,
696708) -> Result < Vec < cranelift_codegen:: ir:: Value > , AotCompileError > {
709+ let frame_state_size =
710+ u32:: try_from ( std:: mem:: size_of :: < NativeFrameState > ( ) ) . map_err ( |_| {
711+ AotCompileError :: Codegen ( "native frame state size out of range" . to_string ( ) )
712+ } ) ?;
713+ let frame_state_align = std:: mem:: align_of :: < NativeFrameState > ( ) . trailing_zeros ( ) as u8 ;
714+ let frame_state_slot = b. create_sized_stack_slot ( StackSlotData :: new (
715+ StackSlotKind :: ExplicitSlot ,
716+ frame_state_size,
717+ frame_state_align,
718+ ) ) ;
719+ let frame_state_ptr = b. ins ( ) . stack_addr ( pointer_type, frame_state_slot, 0 ) ;
720+ call_status_helper (
721+ b,
722+ exit_block,
723+ pointer_type,
724+ helper_refs. frame_state_ref ,
725+ helper_addrs. frame_state ,
726+ & [ vm_ptr, frame_state_ptr] ,
727+ ) ?;
728+ let stack_base_offset =
729+ i32:: try_from ( std:: mem:: offset_of!( NativeFrameState , operand_stack_base) ) . map_err (
730+ |_| AotCompileError :: Codegen ( "frame stack-base offset out of range" . to_string ( ) ) ,
731+ ) ?;
732+ let local_base_offset = i32:: try_from ( std:: mem:: offset_of!( NativeFrameState , local_base) )
733+ . map_err ( |_| {
734+ AotCompileError :: Codegen ( "frame local-base offset out of range" . to_string ( ) )
735+ } ) ?;
736+ let stack_base = b. ins ( ) . load (
737+ pointer_type,
738+ MemFlags :: new ( ) ,
739+ frame_state_ptr,
740+ stack_base_offset,
741+ ) ;
742+ let local_base = b. ins ( ) . load (
743+ pointer_type,
744+ MemFlags :: new ( ) ,
745+ frame_state_ptr,
746+ local_base_offset,
747+ ) ;
697748 let stack_len = b
698749 . ins ( )
699750 . load ( pointer_type, MemFlags :: new ( ) , vm_ptr, offsets. stack_len ) ;
@@ -703,7 +754,8 @@ fn load_checkpoint_args(
703754 AotCompileError :: Codegen ( "checkpoint stack length out of range" . to_string ( ) )
704755 } ) ?,
705756 ) ;
706- let stack_ok = b. ins ( ) . icmp ( IntCC :: Equal , stack_len, expected_stack_len) ;
757+ let expected_stack_total = b. ins ( ) . iadd ( stack_base, expected_stack_len) ;
758+ let stack_ok = b. ins ( ) . icmp ( IntCC :: Equal , stack_len, expected_stack_total) ;
707759 let stack_match = b. create_block ( ) ;
708760 let stack_error = b. ins ( ) . iconst ( types:: I32 , STATUS_ERROR as i64 ) ;
709761 b. ins ( ) . brif (
@@ -724,7 +776,10 @@ fn load_checkpoint_args(
724776 AotCompileError :: Codegen ( "checkpoint locals length out of range" . to_string ( ) )
725777 } ) ?,
726778 ) ;
727- let locals_ok = b. ins ( ) . icmp ( IntCC :: Equal , locals_len, expected_locals_len) ;
779+ let expected_locals_total = b. ins ( ) . iadd ( local_base, expected_locals_len) ;
780+ let locals_ok = b
781+ . ins ( )
782+ . icmp ( IntCC :: Equal , locals_len, expected_locals_total) ;
728783 let locals_match = b. create_block ( ) ;
729784 let locals_error = b. ins ( ) . iconst ( types:: I32 , STATUS_ERROR as i64 ) ;
730785 b. ins ( ) . brif (
@@ -742,6 +797,8 @@ fn load_checkpoint_args(
742797 let locals_ptr = b
743798 . ins ( )
744799 . load ( pointer_type, MemFlags :: new ( ) , vm_ptr, offsets. locals_ptr ) ;
800+ let stack_ptr = ssa_value_addr ( b, pointer_type, stack_ptr, stack_base, layout. value . size ) ;
801+ let locals_ptr = ssa_value_addr ( b, pointer_type, locals_ptr, local_base, layout. value . size ) ;
745802
746803 let mut args = Vec :: with_capacity ( checkpoint. stack . len ( ) + checkpoint. locals . len ( ) ) ;
747804 for ( index, repr) in checkpoint. stack . iter ( ) . copied ( ) . enumerate ( ) {
0 commit comments