@@ -32,6 +32,17 @@ impl<Module> Default for ModuleCache<Module> {
3232 }
3333}
3434
35+ impl < Module > ModuleCache < Module > {
36+ #[ cfg( test) ]
37+ fn with_max_size ( max_size : u64 ) -> Self {
38+ ModuleCache {
39+ modules : LruCache :: unbounded ( ) ,
40+ total_size : 0 ,
41+ max_size,
42+ }
43+ }
44+ }
45+
3546impl < Module : Clone > ModuleCache < Module > {
3647 /// Returns a `Module` for the requested `bytecode`, creating it with `module_builder` and
3748 /// adding it to the cache if it doesn't already exist in the cache.
@@ -58,11 +69,18 @@ impl<Module: Clone> ModuleCache<Module> {
5869 pub fn insert ( & mut self , bytecode : Bytecode , module : Module ) {
5970 let bytecode_size = bytecode. as_ref ( ) . len ( ) as u64 ;
6071
72+ if bytecode_size > self . max_size {
73+ return ;
74+ }
75+
6176 if self . total_size + bytecode_size > self . max_size {
6277 self . reduce_size_to ( self . max_size - bytecode_size) ;
6378 }
6479
65- self . modules . put ( bytecode, module) ;
80+ let already_present = self . modules . put ( bytecode, module) . is_some ( ) ;
81+ if !already_present {
82+ self . total_size += bytecode_size;
83+ }
6684 }
6785
6886 /// Evicts entries from the cache so that the total size of cached bytecode files is less than
@@ -79,3 +97,59 @@ impl<Module: Clone> ModuleCache<Module> {
7997 }
8098 }
8199}
100+
101+ #[ cfg( test) ]
102+ mod tests {
103+ use super :: * ;
104+
105+ fn bytecode ( size : usize ) -> Bytecode {
106+ Bytecode :: new ( vec ! [ 0u8 ; size] )
107+ }
108+
109+ fn distinct_bytecode ( size : usize , discriminant : u8 ) -> Bytecode {
110+ let mut bytes = vec ! [ 0u8 ; size] ;
111+ bytes[ 0 ] = discriminant;
112+ Bytecode :: new ( bytes)
113+ }
114+
115+ #[ test]
116+ fn total_size_tracks_insertions ( ) {
117+ let mut cache = ModuleCache :: < u32 > :: with_max_size ( 1000 ) ;
118+ cache. insert ( bytecode ( 100 ) , 1 ) ;
119+ assert_eq ! ( cache. total_size, 100 ) ;
120+ cache. insert ( distinct_bytecode ( 200 , 1 ) , 2 ) ;
121+ assert_eq ! ( cache. total_size, 300 ) ;
122+ }
123+
124+ #[ test]
125+ fn eviction_triggers_when_full ( ) {
126+ let mut cache = ModuleCache :: < u32 > :: with_max_size ( 250 ) ;
127+ cache. insert ( bytecode ( 100 ) , 1 ) ;
128+ cache. insert ( distinct_bytecode ( 100 , 1 ) , 2 ) ;
129+ assert_eq ! ( cache. total_size, 200 ) ;
130+ assert_eq ! ( cache. modules. len( ) , 2 ) ;
131+
132+ cache. insert ( distinct_bytecode ( 100 , 2 ) , 3 ) ;
133+ assert_eq ! ( cache. modules. len( ) , 2 ) ;
134+ assert ! ( cache. total_size <= 250 ) ;
135+ }
136+
137+ #[ test]
138+ fn oversized_bytecode_is_rejected ( ) {
139+ let mut cache = ModuleCache :: < u32 > :: with_max_size ( 50 ) ;
140+ cache. insert ( bytecode ( 100 ) , 1 ) ;
141+ assert_eq ! ( cache. total_size, 0 ) ;
142+ assert_eq ! ( cache. modules. len( ) , 0 ) ;
143+ }
144+
145+ #[ test]
146+ fn reinserting_same_key_does_not_double_count ( ) {
147+ let mut cache = ModuleCache :: < u32 > :: with_max_size ( 1000 ) ;
148+ let bc = bytecode ( 100 ) ;
149+ cache. insert ( bc. clone ( ) , 1 ) ;
150+ assert_eq ! ( cache. total_size, 100 ) ;
151+ cache. insert ( bc, 2 ) ;
152+ assert_eq ! ( cache. total_size, 100 ) ;
153+ assert_eq ! ( cache. modules. len( ) , 1 ) ;
154+ }
155+ }
0 commit comments