@@ -209,17 +209,25 @@ impl CodeBlock {
209209 self . page_size
210210 }
211211
212- /// Return the number of code pages that have been allocated by the VirtualMemory.
213- pub fn num_pages ( & self ) -> usize {
212+ /// Return the number of code pages that have been mapped by the VirtualMemory.
213+ pub fn num_mapped_pages ( & self ) -> usize {
214214 let mapped_region_size = self . mem_block . borrow ( ) . mapped_region_size ( ) ;
215215 // CodeBlock's page size != VirtualMem's page size on Linux,
216216 // so mapped_region_size % self.page_size may not be 0
217217 ( ( mapped_region_size - 1 ) / self . page_size ) + 1
218218 }
219219
220+ /// Return the number of code pages that have been reserved by the VirtualMemory.
221+ pub fn num_virtual_pages ( & self ) -> usize {
222+ let virtual_region_size = self . mem_block . borrow ( ) . virtual_region_size ( ) ;
223+ // CodeBlock's page size != VirtualMem's page size on Linux,
224+ // so mapped_region_size % self.page_size may not be 0
225+ ( ( virtual_region_size - 1 ) / self . page_size ) + 1
226+ }
227+
220228 /// Return the number of code pages that have been freed and not used yet.
221229 pub fn num_freed_pages ( & self ) -> usize {
222- ( 0 ..self . num_pages ( ) ) . filter ( |& page_idx| self . has_freed_page ( page_idx) ) . count ( )
230+ ( 0 ..self . num_mapped_pages ( ) ) . filter ( |& page_idx| self . has_freed_page ( page_idx) ) . count ( )
223231 }
224232
225233 pub fn has_freed_page ( & self , page_idx : usize ) -> bool {
@@ -303,7 +311,7 @@ impl CodeBlock {
303311 pub fn code_size ( & self ) -> usize {
304312 let mut size = 0 ;
305313 let current_page_idx = self . write_pos / self . page_size ;
306- for page_idx in 0 ..self . num_pages ( ) {
314+ for page_idx in 0 ..self . num_mapped_pages ( ) {
307315 if page_idx == current_page_idx {
308316 // Count only actually used bytes for the current page.
309317 size += ( self . write_pos % self . page_size ) . saturating_sub ( self . page_start ( ) ) ;
@@ -546,7 +554,7 @@ impl CodeBlock {
546554 }
547555
548556 // Check which pages are still in use
549- let mut pages_in_use = vec ! [ false ; self . num_pages ( ) ] ;
557+ let mut pages_in_use = vec ! [ false ; self . num_mapped_pages ( ) ] ;
550558 // For each ISEQ, we currently assume that only code pages used by inline code
551559 // are used by outlined code, so we mark only code pages used by inlined code.
552560 for_each_on_stack_iseq_payload ( |iseq_payload| {
@@ -560,10 +568,14 @@ impl CodeBlock {
560568 }
561569
562570 // Let VirtuamMem free the pages
563- let freed_pages: Vec < usize > = pages_in_use. iter ( ) . enumerate ( )
571+ let mut freed_pages: Vec < usize > = pages_in_use. iter ( ) . enumerate ( )
564572 . filter ( |& ( _, & in_use) | !in_use) . map ( |( page, _) | page) . collect ( ) ;
565573 self . free_pages ( & freed_pages) ;
566574
575+ // Append virtual pages in case RubyVM::YJIT.code_gc is manually triggered.
576+ let mut virtual_pages: Vec < usize > = ( self . num_mapped_pages ( ) ..self . num_virtual_pages ( ) ) . collect ( ) ;
577+ freed_pages. append ( & mut virtual_pages) ;
578+
567579 // Invalidate everything to have more compact code after code GC.
568580 // This currently patches every ISEQ, which works, but in the future,
569581 // we could limit that to patch only on-stack ISEQs for optimizing code GC.
0 commit comments