From 869d3714190bbd53b65eee4e3e352f7035277a3e Mon Sep 17 00:00:00 2001 From: Leandro Lucarella Date: Tue, 28 Sep 2010 23:00:18 -0300 Subject: [PATCH] =?utf8?q?Mostrar=20algoritmo=20de=20mark()=20m=C3=A1s=20p?= =?utf8?q?arecido=20al=20real?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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 | 51 ++++++++++++++++++++++---------------------------- 1 file changed, 22 insertions(+), 29 deletions(-) diff --git a/source/dgc.rst b/source/dgc.rst index 9019246..6918f33 100644 --- a/source/dgc.rst +++ b/source/dgc.rst @@ -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 ` (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 `: 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 -- 2.43.0