11//! Implements a registry of modules for a store.
22
3+ #[ cfg( feature = "component-model" ) ]
4+ use crate :: component:: Component ;
35use crate :: { Engine , Module } ;
46use std:: {
57 collections:: BTreeMap ,
@@ -24,12 +26,21 @@ lazy_static::lazy_static! {
2426#[ derive( Default ) ]
2527pub struct ModuleRegistry {
2628 // Keyed by the end address of the module's code in memory.
27- modules_with_code : BTreeMap < usize , Module > ,
29+ //
30+ // The value here is the start address and the module/component it
31+ // corresponds to.
32+ modules_with_code : BTreeMap < usize , ( usize , ModuleOrComponent ) > ,
2833
2934 // Preserved for keeping data segments alive or similar
3035 modules_without_code : Vec < Module > ,
3136}
3237
38+ enum ModuleOrComponent {
39+ Module ( Module ) ,
40+ #[ cfg( feature = "component-model" ) ]
41+ Component ( Component ) ,
42+ }
43+
3344fn start ( module : & Module ) -> usize {
3445 assert ! ( !module. compiled_module( ) . code( ) . is_empty( ) ) ;
3546 module. compiled_module ( ) . code ( ) . as_ptr ( ) as usize
@@ -42,15 +53,23 @@ impl ModuleRegistry {
4253 }
4354
4455 fn module ( & self , pc : usize ) -> Option < & Module > {
45- let ( end, module) = self . modules_with_code . range ( pc..) . next ( ) ?;
46- if pc < start ( module) || * end < pc {
56+ match self . module_or_component ( pc) ? {
57+ ModuleOrComponent :: Module ( m) => Some ( m) ,
58+ #[ cfg( feature = "component-model" ) ]
59+ ModuleOrComponent :: Component ( _) => None ,
60+ }
61+ }
62+
63+ fn module_or_component ( & self , pc : usize ) -> Option < & ModuleOrComponent > {
64+ let ( end, ( start, module) ) = self . modules_with_code . range ( pc..) . next ( ) ?;
65+ if pc < * start || * end < pc {
4766 return None ;
4867 }
4968 Some ( module)
5069 }
5170
5271 /// Registers a new module with the registry.
53- pub fn register ( & mut self , module : & Module ) {
72+ pub fn register_module ( & mut self , module : & Module ) {
5473 let compiled_module = module. compiled_module ( ) ;
5574
5675 // If there's not actually any functions in this module then we may
@@ -61,39 +80,70 @@ impl ModuleRegistry {
6180 // modules and retain them.
6281 if compiled_module. finished_functions ( ) . len ( ) == 0 {
6382 self . modules_without_code . push ( module. clone ( ) ) ;
64- return ;
83+ } else {
84+ // The module code range is exclusive for end, so make it inclusive as it
85+ // may be a valid PC value
86+ let start_addr = start ( module) ;
87+ let end_addr = start_addr + compiled_module. code ( ) . len ( ) - 1 ;
88+ self . register (
89+ start_addr,
90+ end_addr,
91+ ModuleOrComponent :: Module ( module. clone ( ) ) ,
92+ ) ;
6593 }
94+ }
6695
67- // The module code range is exclusive for end, so make it inclusive as it
68- // may be a valid PC value
69- let start_addr = start ( module) ;
70- let end_addr = start_addr + compiled_module. code ( ) . len ( ) - 1 ;
96+ #[ cfg( feature = "component-model" ) ]
97+ pub fn register_component ( & mut self , component : & Component ) {
98+ // If there's no text section associated with this component (e.g. no
99+ // lowered functions) then there's nothing to register, otherwise it's
100+ // registered along the same lines as modules above.
101+ //
102+ // Note that empty components don't need retaining here since it doesn't
103+ // have data segments like empty modules.
104+ let text = component. text ( ) ;
105+ if text. is_empty ( ) {
106+ return ;
107+ }
108+ let start = text. as_ptr ( ) as usize ;
109+ self . register (
110+ start,
111+ start + text. len ( ) - 1 ,
112+ ModuleOrComponent :: Component ( component. clone ( ) ) ,
113+ ) ;
114+ }
71115
116+ /// Registers a new module with the registry.
117+ fn register ( & mut self , start_addr : usize , end_addr : usize , item : ModuleOrComponent ) {
72118 // Ensure the module isn't already present in the registry
73119 // This is expected when a module is instantiated multiple times in the
74120 // same store
75- if let Some ( m ) = self . modules_with_code . get ( & end_addr) {
76- assert_eq ! ( start ( m ) , start_addr) ;
121+ if let Some ( ( other_start , _ ) ) = self . modules_with_code . get ( & end_addr) {
122+ assert_eq ! ( * other_start , start_addr) ;
77123 return ;
78124 }
79125
80126 // Assert that this module's code doesn't collide with any other
81127 // registered modules
82- if let Some ( ( _, prev ) ) = self . modules_with_code . range ( end_addr ..) . next ( ) {
83- assert ! ( start ( prev ) > end_addr) ;
128+ if let Some ( ( _, ( prev_start , _ ) ) ) = self . modules_with_code . range ( start_addr ..) . next ( ) {
129+ assert ! ( * prev_start > end_addr) ;
84130 }
85131 if let Some ( ( prev_end, _) ) = self . modules_with_code . range ( ..=start_addr) . next_back ( ) {
86132 assert ! ( * prev_end < start_addr) ;
87133 }
88134
89- let prev = self . modules_with_code . insert ( end_addr, module . clone ( ) ) ;
135+ let prev = self . modules_with_code . insert ( end_addr, ( start_addr , item ) ) ;
90136 assert ! ( prev. is_none( ) ) ;
91137 }
92138
93139 /// Looks up a trampoline from an anyfunc.
94140 pub fn lookup_trampoline ( & self , anyfunc : & VMCallerCheckedAnyfunc ) -> Option < VMTrampoline > {
95- let module = self . module ( anyfunc. func_ptr . as_ptr ( ) as usize ) ?;
96- module. signatures ( ) . trampoline ( anyfunc. type_index )
141+ let signatures = match self . module_or_component ( anyfunc. func_ptr . as_ptr ( ) as usize ) ? {
142+ ModuleOrComponent :: Module ( m) => m. signatures ( ) ,
143+ #[ cfg( feature = "component-model" ) ]
144+ ModuleOrComponent :: Component ( c) => c. signatures ( ) ,
145+ } ;
146+ signatures. trampoline ( anyfunc. type_index )
97147 }
98148}
99149
0 commit comments