@@ -36,8 +36,9 @@ use wasmtime_environ::{
3636 Abi , AddressMapSection , BuiltinFunctionIndex , CacheStore , CompileError , CompiledFunctionBody ,
3737 DefinedFuncIndex , FlagValue , FrameInstPos , FrameStackShape , FrameStateSlotBuilder ,
3838 FrameTableBuilder , FuncKey , FunctionBodyData , FunctionLoc , HostCall , InliningCompiler ,
39- ModuleTranslation , ModuleTypesBuilder , PtrSize , StackMapSection , StaticModuleIndex ,
40- TrapEncodingBuilder , TrapSentinel , TripleExt , Tunables , VMOffsets , WasmFuncType , WasmValType ,
39+ ModuleInternedTypeIndex , ModuleTranslation , ModuleTypesBuilder , PtrSize , StackMapSection ,
40+ StaticModuleIndex , TrapEncodingBuilder , TrapSentinel , TripleExt , Tunables , WasmFuncType ,
41+ WasmValType ,
4142} ;
4243use wasmtime_unwinder:: ExceptionTableBuilder ;
4344
@@ -354,140 +355,20 @@ impl wasmtime_environ::Compiler for Compiler {
354355 key : FuncKey ,
355356 symbol : & str ,
356357 ) -> Result < CompiledFunctionBody , CompileError > {
357- log:: trace!( "compiling array-to-wasm trampoline: {key:?} = {symbol:?}" ) ;
358-
359358 let ( module_index, def_func_index) = key. unwrap_array_to_wasm_trampoline ( ) ;
360- debug_assert_eq ! ( translation. module_index( ) , module_index) ;
361-
362359 let func_index = translation. module . func_index ( def_func_index) ;
363360 let sig = translation. module . functions [ func_index]
364361 . signature
365362 . unwrap_module_type_index ( ) ;
366- let wasm_func_ty = types[ sig] . unwrap_func ( ) ;
367-
368- let isa = & * self . isa ;
369- let pointer_type = isa. pointer_type ( ) ;
370- let wasm_call_sig = wasm_call_signature ( isa, wasm_func_ty, & self . tunables ) ;
371- let array_call_sig = array_call_signature ( isa) ;
372-
373- let mut compiler = self . function_compiler ( ) ;
374- let func = ir:: Function :: with_name_signature ( key_to_name ( key) , array_call_sig) ;
375- let ( mut builder, block0) = compiler. builder ( func) ;
376-
377- let try_call_block = builder. create_block ( ) ;
378- builder. ins ( ) . jump ( try_call_block, [ ] ) ;
379- builder. switch_to_block ( try_call_block) ;
380-
381- let ( vmctx, caller_vmctx, values_vec_ptr, values_vec_len) = {
382- let params = builder. func . dfg . block_params ( block0) ;
383- ( params[ 0 ] , params[ 1 ] , params[ 2 ] , params[ 3 ] )
384- } ;
385-
386- // First load the actual arguments out of the array.
387- let mut args = self . load_values_from_array (
388- wasm_func_ty. params ( ) ,
389- & mut builder,
390- values_vec_ptr,
391- values_vec_len,
392- ) ;
393- args. insert ( 0 , caller_vmctx) ;
394- args. insert ( 0 , vmctx) ;
395-
396- // Just before we enter Wasm, save our context information.
397- //
398- // Assert that we were really given a core Wasm vmctx, since that's
399- // what we are assuming with our offsets below.
400- self . debug_assert_vmctx_kind ( & mut builder, vmctx, wasmtime_environ:: VMCONTEXT_MAGIC ) ;
401- let offsets = VMOffsets :: new ( isa. pointer_bytes ( ) , & translation. module ) ;
402- let vm_store_context_offset = offsets. ptr . vmctx_store_context ( ) ;
403- save_last_wasm_entry_context (
404- & mut builder,
405- pointer_type,
406- & offsets. ptr ,
407- vm_store_context_offset. into ( ) ,
408- vmctx,
409- try_call_block,
410- ) ;
411-
412- // Create the invocation of wasm, which is notably done with a
413- // `try_call` with an exception handler that's used to handle traps.
414- let normal_return = builder. create_block ( ) ;
415- let exceptional_return = builder. create_block ( ) ;
416- let normal_return_values = wasm_call_sig
417- . returns
418- . iter ( )
419- . map ( |ty| {
420- builder
421- . func
422- . dfg
423- . append_block_param ( normal_return, ty. value_type )
424- } )
425- . collect :: < Vec < _ > > ( ) ;
426-
427- // Then call the Wasm function with those arguments.
428- let callee_key = FuncKey :: DefinedWasmFunction ( module_index, def_func_index) ;
429- let signature = builder. func . import_signature ( wasm_call_sig. clone ( ) ) ;
430- let callee = {
431- let ( namespace, index) = callee_key. into_raw_parts ( ) ;
432- let name = ir:: ExternalName :: User (
433- builder
434- . func
435- . declare_imported_user_function ( ir:: UserExternalName { namespace, index } ) ,
436- ) ;
437- builder. func . dfg . ext_funcs . push ( ir:: ExtFuncData {
438- name,
439- signature,
440- colocated : true ,
441- } )
442- } ;
443-
444- let dfg = & mut builder. func . dfg ;
445- let exception_table = dfg. exception_tables . push ( ir:: ExceptionTableData :: new (
446- signature,
447- ir:: BlockCall :: new (
448- normal_return,
449- ( 0 ..wasm_call_sig. returns . len ( ) )
450- . map ( |i| ir:: BlockArg :: TryCallRet ( i. try_into ( ) . unwrap ( ) ) ) ,
451- & mut dfg. value_lists ,
452- ) ,
453- [ ir:: ExceptionTableItem :: Default ( ir:: BlockCall :: new (
454- exceptional_return,
455- None ,
456- & mut dfg. value_lists ,
457- ) ) ] ,
458- ) ) ;
459- builder. ins ( ) . try_call ( callee, & args, exception_table) ;
460-
461- builder. seal_block ( try_call_block) ;
462- builder. seal_block ( normal_return) ;
463- builder. seal_block ( exceptional_return) ;
464-
465- // On the normal return path store all the results in the array we were
466- // provided and return "true" for "returned successfully".
467- builder. switch_to_block ( normal_return) ;
468- self . store_values_to_array (
469- & mut builder,
470- wasm_func_ty. returns ( ) ,
471- & normal_return_values,
472- values_vec_ptr,
473- values_vec_len,
474- ) ;
475- let true_return = builder. ins ( ) . iconst ( ir:: types:: I8 , 1 ) ;
476- builder. ins ( ) . return_ ( & [ true_return] ) ;
477-
478- // On the exceptional return path just return "false" for "did not
479- // succeed". Note that register restoration is part of the `try_call`
480- // and handler implementation.
481- builder. switch_to_block ( exceptional_return) ;
482- let false_return = builder. ins ( ) . iconst ( ir:: types:: I8 , 0 ) ;
483- builder. ins ( ) . return_ ( & [ false_return] ) ;
484-
485- builder. finalize ( ) ;
486-
487- Ok ( CompiledFunctionBody {
488- code : box_dyn_any_compiler_context ( Some ( compiler. cx ) ) ,
489- needs_gc_heap : false ,
490- } )
363+ self . array_to_wasm_trampoline (
364+ key,
365+ FuncKey :: DefinedWasmFunction ( module_index, def_func_index) ,
366+ types,
367+ sig,
368+ symbol,
369+ self . isa . pointer_bytes ( ) . vmctx_store_context ( ) . into ( ) ,
370+ wasmtime_environ:: VMCONTEXT_MAGIC ,
371+ )
491372 }
492373
493374 fn compile_wasm_to_array_trampoline (
@@ -1345,6 +1226,142 @@ impl Compiler {
13451226 ) ;
13461227 builder. ins ( ) . trapz ( is_expected_vmctx, TRAP_INTERNAL_ASSERT ) ;
13471228 }
1229+
1230+ fn array_to_wasm_trampoline (
1231+ & self ,
1232+ trampoline_key : FuncKey ,
1233+ callee_key : FuncKey ,
1234+ types : & ModuleTypesBuilder ,
1235+ callee_sig : ModuleInternedTypeIndex ,
1236+ symbol : & str ,
1237+ vm_store_context_offset : u32 ,
1238+ expected_vmctx_magic : u32 ,
1239+ ) -> Result < CompiledFunctionBody , CompileError > {
1240+ log:: trace!( "compiling array-to-wasm trampoline: {trampoline_key:?} = {symbol:?}" ) ;
1241+
1242+ let wasm_func_ty = types[ callee_sig] . unwrap_func ( ) ;
1243+
1244+ let isa = & * self . isa ;
1245+ let pointer_type = isa. pointer_type ( ) ;
1246+ let wasm_call_sig = wasm_call_signature ( isa, wasm_func_ty, & self . tunables ) ;
1247+ let array_call_sig = array_call_signature ( isa) ;
1248+
1249+ let mut compiler = self . function_compiler ( ) ;
1250+ let func = ir:: Function :: with_name_signature ( key_to_name ( trampoline_key) , array_call_sig) ;
1251+ let ( mut builder, block0) = compiler. builder ( func) ;
1252+
1253+ let try_call_block = builder. create_block ( ) ;
1254+ builder. ins ( ) . jump ( try_call_block, [ ] ) ;
1255+ builder. switch_to_block ( try_call_block) ;
1256+
1257+ let ( vmctx, caller_vmctx, values_vec_ptr, values_vec_len) = {
1258+ let params = builder. func . dfg . block_params ( block0) ;
1259+ ( params[ 0 ] , params[ 1 ] , params[ 2 ] , params[ 3 ] )
1260+ } ;
1261+
1262+ // First load the actual arguments out of the array.
1263+ let mut args = self . load_values_from_array (
1264+ wasm_func_ty. params ( ) ,
1265+ & mut builder,
1266+ values_vec_ptr,
1267+ values_vec_len,
1268+ ) ;
1269+ args. insert ( 0 , caller_vmctx) ;
1270+ args. insert ( 0 , vmctx) ;
1271+
1272+ // Just before we enter Wasm, save our context information.
1273+ //
1274+ // Assert that we were really given a core Wasm vmctx, since that's
1275+ // what we are assuming with our offsets below.
1276+ self . debug_assert_vmctx_kind ( & mut builder, vmctx, expected_vmctx_magic) ;
1277+ save_last_wasm_entry_context (
1278+ & mut builder,
1279+ pointer_type,
1280+ & self . isa . pointer_bytes ( ) ,
1281+ vm_store_context_offset,
1282+ vmctx,
1283+ try_call_block,
1284+ ) ;
1285+
1286+ // Create the invocation of wasm, which is notably done with a
1287+ // `try_call` with an exception handler that's used to handle traps.
1288+ let normal_return = builder. create_block ( ) ;
1289+ let exceptional_return = builder. create_block ( ) ;
1290+ let normal_return_values = wasm_call_sig
1291+ . returns
1292+ . iter ( )
1293+ . map ( |ty| {
1294+ builder
1295+ . func
1296+ . dfg
1297+ . append_block_param ( normal_return, ty. value_type )
1298+ } )
1299+ . collect :: < Vec < _ > > ( ) ;
1300+
1301+ // Then call the Wasm function with those arguments.
1302+ let signature = builder. func . import_signature ( wasm_call_sig. clone ( ) ) ;
1303+ let callee = {
1304+ let ( namespace, index) = callee_key. into_raw_parts ( ) ;
1305+ let name = ir:: ExternalName :: User (
1306+ builder
1307+ . func
1308+ . declare_imported_user_function ( ir:: UserExternalName { namespace, index } ) ,
1309+ ) ;
1310+ builder. func . dfg . ext_funcs . push ( ir:: ExtFuncData {
1311+ name,
1312+ signature,
1313+ colocated : true ,
1314+ } )
1315+ } ;
1316+
1317+ let dfg = & mut builder. func . dfg ;
1318+ let exception_table = dfg. exception_tables . push ( ir:: ExceptionTableData :: new (
1319+ signature,
1320+ ir:: BlockCall :: new (
1321+ normal_return,
1322+ ( 0 ..wasm_call_sig. returns . len ( ) )
1323+ . map ( |i| ir:: BlockArg :: TryCallRet ( i. try_into ( ) . unwrap ( ) ) ) ,
1324+ & mut dfg. value_lists ,
1325+ ) ,
1326+ [ ir:: ExceptionTableItem :: Default ( ir:: BlockCall :: new (
1327+ exceptional_return,
1328+ None ,
1329+ & mut dfg. value_lists ,
1330+ ) ) ] ,
1331+ ) ) ;
1332+ builder. ins ( ) . try_call ( callee, & args, exception_table) ;
1333+
1334+ builder. seal_block ( try_call_block) ;
1335+ builder. seal_block ( normal_return) ;
1336+ builder. seal_block ( exceptional_return) ;
1337+
1338+ // On the normal return path store all the results in the array we were
1339+ // provided and return "true" for "returned successfully".
1340+ builder. switch_to_block ( normal_return) ;
1341+ self . store_values_to_array (
1342+ & mut builder,
1343+ wasm_func_ty. returns ( ) ,
1344+ & normal_return_values,
1345+ values_vec_ptr,
1346+ values_vec_len,
1347+ ) ;
1348+ let true_return = builder. ins ( ) . iconst ( ir:: types:: I8 , 1 ) ;
1349+ builder. ins ( ) . return_ ( & [ true_return] ) ;
1350+
1351+ // On the exceptional return path just return "false" for "did not
1352+ // succeed". Note that register restoration is part of the `try_call`
1353+ // and handler implementation.
1354+ builder. switch_to_block ( exceptional_return) ;
1355+ let false_return = builder. ins ( ) . iconst ( ir:: types:: I8 , 0 ) ;
1356+ builder. ins ( ) . return_ ( & [ false_return] ) ;
1357+
1358+ builder. finalize ( ) ;
1359+
1360+ Ok ( CompiledFunctionBody {
1361+ code : box_dyn_any_compiler_context ( Some ( compiler. cx ) ) ,
1362+ needs_gc_heap : false ,
1363+ } )
1364+ }
13481365}
13491366
13501367struct FunctionCompiler < ' a > {
@@ -1572,7 +1589,7 @@ fn clif_to_env_frame_tables<'a>(
15721589fn save_last_wasm_entry_context (
15731590 builder : & mut FunctionBuilder ,
15741591 pointer_type : ir:: Type ,
1575- ptr_size : & impl PtrSize ,
1592+ ptr_size : & dyn PtrSize ,
15761593 vm_store_context_offset : u32 ,
15771594 vmctx : Value ,
15781595 block : ir:: Block ,
0 commit comments