]> git.llucax.com Git - z.facultad/75.00/informe.git/commitdiff
Terminar descripción de la fase de barrido
authorLeandro Lucarella <llucax@gmail.com>
Wed, 10 Jun 2009 20:54:07 +0000 (17:54 -0300)
committerLeandro Lucarella <llucax@gmail.com>
Tue, 16 Jun 2009 00:40:05 +0000 (21:40 -0300)
source/dgc.rst

index dc322238ccac4922bd3c1ecef1f057b3e37f364a..f7e42eaccb03837c0427a4ac832d16b11c1c8d79 100644 (file)
@@ -494,7 +494,79 @@ dividirse en dos pasos básicos::
       sweep()
       rebuild_free_lists()
 
       sweep()
       rebuild_free_lists()
 
-El barrido se realiza con una pasada por sobre todo el heap
+El barrido se realiza con una pasada por sobre todo el *heap* de la siguiente
+manera::
+
+   function sweep() is
+      foreach pool in heap
+         foreach page in pool
+            if page.block_size <= PAGE // saltea FREE y CONTINUATION
+               foreach block in page
+                  if block.mark is false
+                     if block.final is true
+                        finalize(block)
+                     block.free = true
+                     block.final = false
+                     block.noscan = false
+                     if page.block_size is PAGE // objeto grande
+                        free_big_object(pool, page)
+
+Como se observa, se recorre todo el *heap* en busca de bloques y páginas
+libres. Los bloques libres son marcados con el atributo ``free`` y las páginas
+libres son marcadas con el tamaño de bloque simbólico ``FREE``. Para los
+objetos grandes se marcan todas las páginas que utilizaban como ``FREE``::
+
+   function free_big_object(pool, page) is
+      pool_end = cast(byte*) pool.pages + (PAGE_SIZE * pool.number_of_pages)
+      do
+         page = cast(byte*) page + PAGE_SIZE
+         page.block_size = FREE
+      while page.block_size is CONTINUATION and page < pool_end
+
+Además, los bloques que tienen en atributo ``final`` son finalizados llamando
+a la función ``finalize()``. Esta función es un servicio que provee la
+biblioteca *runtime* y en última instancia llama al destructor del objeto
+almacenado en el bloque a liberar.
+
+Una vez marcados todos los bloques y páginas como libre, se procede
+a reconstruir las listas de libres. En el proceso buscan las páginas que
+tengan todos los bloques libres para marcar la página completa como libre (de
+manera que pueda utilizarse para albergar otro tamaño de bloque u objetos
+grandes de ser necesario)::
+
+   function rebuild_free_lists() is
+      foreach free_list in heap
+         free_list.clear()
+      foreach pool in heap
+         foreach page in pool
+            if page.block_size < PAGE // objetos pequeños
+               if is_page_free(page)
+                  page.block_size = FREE
+               else
+                  foreach block in page
+                     if block.free is true
+                        free_lists[page.block_size].link(block)
+
+Esta reorganización de listas libres además mejoran la localidad de
+referencia y previenen la fragmentación. La localidad de referencia se ve
+mojorada debido a que asignaciones de memoria proximas en el tiempo serán
+también próximas en espacio porque pertenecerán a la misma página (al menos si
+las asignaciones son todas del mismo tamaño). La fragmentación se minimiza por
+el mismo efecto, primero se asignarán todos los bloques de la misma página.
+
+A continuación se presenta la implementación de una de las funciones
+suplementarias de la fase de barrido::
+
+   function is_page_free(page) is
+      foreach block in page
+         if block.free is false
+            return false
+      return true
+
+Las demás funciones suplementarias pertenecen a la manipulación de listas
+libres que no son más que operaciones sobre una lista simplemente enlazada. En
+la sección :ref:`dgc_impl` se verá con más detalles como las implementa el
+recolector actual.