@@ -382,35 +382,52 @@ impl Table {
382382 // 1. Cross-instance table copy.
383383 // 2. Intra-instance table copy.
384384 // 3. Intra-table copy.
385+ //
386+ // We handle each of them slightly differently.
385387 let src_instance = src_table. instance . instance ( ) ;
386388 let dst_instance = dst_table. instance . instance ( ) ;
387- if src_instance != dst_instance {
388- // SAFETY: accessing two instances requires only accessing defined items
389- // on each instance which is done below with `get_defined_*` methods.
390- let ( gc_store, [ src_instance, dst_instance] ) =
391- unsafe { store. optional_gc_store_and_instances_mut ( [ src_instance, dst_instance] ) } ;
392- src_instance. get_defined_table ( src_table. index ) . copy_to (
393- dst_instance. get_defined_table ( dst_table. index ) ,
394- gc_store,
395- dst_index,
396- src_index,
397- len,
398- )
399- } else if src_table. index != dst_table. index {
400- assert_eq ! ( src_instance, dst_instance) ;
401- let ( gc_store, instance) = store. optional_gc_store_and_instance_mut ( src_instance) ;
402- let [ ( _, src_table) , ( _, dst_table) ] = instance
403- . tables_mut ( )
404- . get_disjoint_mut ( [ src_table. index , dst_table. index ] )
405- . unwrap ( ) ;
406- src_table. copy_to ( dst_table, gc_store, dst_index, src_index, len)
407- } else {
408- assert_eq ! ( src_instance, dst_instance) ;
409- assert_eq ! ( src_table. index, dst_table. index) ;
410- let ( gc_store, instance) = store. optional_gc_store_and_instance_mut ( src_instance) ;
411- instance
412- . get_defined_table ( src_table. index )
413- . copy_within ( gc_store, dst_index, src_index, len)
389+ match (
390+ src_instance == dst_instance,
391+ src_table. index == dst_table. index ,
392+ ) {
393+ // 1. Cross-instance table copy: split the mutable store borrow into
394+ // two mutable instance borrows, get each instance's defined table,
395+ // and do the copy.
396+ ( false , _) => {
397+ // SAFETY: accessing two instances mutably at the same time
398+ // requires only accessing defined entities on each instance
399+ // which is done below with `get_defined_*` methods.
400+ let ( gc_store, [ src_instance, dst_instance] ) = unsafe {
401+ store. optional_gc_store_and_instances_mut ( [ src_instance, dst_instance] )
402+ } ;
403+ src_instance. get_defined_table ( src_table. index ) . copy_to (
404+ dst_instance. get_defined_table ( dst_table. index ) ,
405+ gc_store,
406+ dst_index,
407+ src_index,
408+ len,
409+ )
410+ }
411+
412+ // 2. Intra-instance, distinct-tables copy: split the mutable
413+ // instance borrow into two distinct mutable table borrows and do
414+ // the copy.
415+ ( true , false ) => {
416+ let ( gc_store, instance) = store. optional_gc_store_and_instance_mut ( src_instance) ;
417+ let [ ( _, src_table) , ( _, dst_table) ] = instance
418+ . tables_mut ( )
419+ . get_disjoint_mut ( [ src_table. index , dst_table. index ] )
420+ . unwrap ( ) ;
421+ src_table. copy_to ( dst_table, gc_store, dst_index, src_index, len)
422+ }
423+
424+ // 3. Intra-table copy: get the table and copy within it!
425+ ( true , true ) => {
426+ let ( gc_store, instance) = store. optional_gc_store_and_instance_mut ( src_instance) ;
427+ instance
428+ . get_defined_table ( src_table. index )
429+ . copy_within ( gc_store, dst_index, src_index, len)
430+ }
414431 }
415432 }
416433
0 commit comments