]> git.llucax.com Git - z.facultad/75.00/informe.git/commitdiff
Mostrar algoritmo de mark() más parecido al real
authorLeandro Lucarella <llucax@gmail.com>
Wed, 29 Sep 2010 02:00:18 +0000 (23:00 -0300)
committerLeandro Lucarella <llucax@gmail.com>
Wed, 29 Sep 2010 02:05:29 +0000 (23:05 -0300)
El algoritmo de mark() en realidad marca un rango de punteros, no sólo
uno, y esta diferencia complica la explicación de los cambios hechos, por
lo tanto se describe el algoritmo de una forma más parecida a la realidad.

source/dgc.rst

index 90192467994cf1e5f9e25bb6142a9d52e5ab8a9c..6918f3334a5cdc8aecffebf6034119f9f712aa2f 100644 (file)
@@ -467,9 +467,9 @@ algoritmo::
       start_the_world()
 
 La variable **global** ``more_to_scan`` indica al algoritmo iterativo cuando
-debe finalizar: la función ``mark()`` (que veremos más adelante) lo pone en
-``true`` cuando una nueva celda debe ser visitada, por lo tanto la iteración
-se interrumpe cuando no hay más celdas por visitar.
+debe finalizar: la función ``mark_range()`` (que veremos más adelante) lo pone
+en ``true`` cuando una nueva celda debe ser visitada, por lo tanto la
+iteración se interrumpe cuando no hay más celdas por visitar.
 
 Las funciones ``stop_the_world()`` y ``start_the_world()`` sencillamente
 pausan y reanudan todos los hilos respectivamente::
@@ -517,9 +517,7 @@ Primero se marca el área de memoria estática de manera :ref:`conservativa
 <gc_conserv>` (es decir, tomando cada *word* como si fuera un puntero)::
 
    function mark_static_data() is
-      foreach word in static_data
-         pointer = cast(void*) word
-         mark(pointer)
+      mark_range(static_data.begin, static_data.end)
 
 Para poder tomar los registros como parte del *root set* primero se apilan
 en el *stack* a través de la función::
@@ -533,9 +531,7 @@ los threads para terminar de marcar el *root set*::
 
    function mark_stacks() is
       foreach thread in threads
-         foreach word in thread.stack
-            pointer = cast(void*) word
-            mark(pointer)
+         mark_range(thread.stack.begin, thread.stack.end)
 
 Dado que D_ soporta manejo de memoria manual al mismo tiempo que memoria
 automática, es posible que existan celdas de memoria que no estén en el *root
@@ -546,20 +542,23 @@ estas nuevas raíces. Es por esto que para concluir el marcado del *root set*
 completo se procede a marcar las raíces definidas por el usuario::
 
    function mark_user_roots() is
-      foreach pointer in user_roots
-         mark(pointer)
+      foreach root_range in user_roots
+         mark_range(root_range.begin, root_range.end)
 
 El algoritmo de marcado no es recursivo sino iterativo por lo tanto al marcar
 una celda (o bloque) no se siguen sus *hijas*, solo se activa el bit de *scan*
 (a menos que la celda no contenga punteros, es decir, tenga el bit *noscan*)::
 
-   function mark(pointer) is
-      [pool, page, block] = find_block(pointer)
-      if block is not null and block.mark is false
-         block.mark = true
-         if block.noscan is false
-            block.scan = true
-            global more_to_scan = true
+   function mark_range(begin, end) is
+      pointer = begin
+      while pointer < end
+         [pool, page, block] = find_block(pointer)
+         if block is not null and block.mark is false
+            block.mark = true
+            if block.noscan is false
+               block.scan = true
+               global more_to_scan = true
+         pointer++
 
 Por lo tanto en este punto, tenemos todas las celdas inmediatamente
 alcanzables desde el *root set* marcadas y con el bit *scan* activado si la
@@ -577,15 +576,11 @@ celdas para visitar (con el bit *scan* activo)::
                      if block.scan is true
                         block.scan = false
                         if page.block_size is PAGE // objeto grande
-                           start = cast(byte*) page
+                           begin = cast(byte*) page
                            end = find_big_object_end(pool, page)
-                           foreach word in start..end
-                                 pointer = cast(void*) word
-                                 mark(pointer)
+                           mark_range(begin, end)
                         else // objeto pequeño
-                           foreach word in block
-                              pointer = cast(void*) word
-                              mark(pointer)
+                           mark_range(block.begin, block.end)
 
 Aquí puede verse, con un poco de esfuerzo, la utilización de la
 :ref:`abstracción tricolor <gc_intro_tricolor>`: todas las celdas alcanzables
@@ -1284,10 +1279,8 @@ Asignación de memoria
 
 Recolección
    *mark(pbot, ptop)*
-      marca un rango de memoria. Este método es análogo al ``mark()``
-      presentado en la sección :ref:`dgc_algo_mark` pero marca un rango
-      completo de memoria, lo que permite que sea considerablemente más
-      eficiente.
+      marca un rango de memoria. Este método es análogo al ``mark_range()``
+      presentado en la sección :ref:`dgc_algo_mark`.
 
    *fullcollectshell()*
       guarda los registros en el *stack* y llama a ``fullcollect()``. El