-Como se ha visto, D_ es un lenguaje de programación muy completo, pero aún
-tiene algunos aspectos inconclusos. Su recolector de basura está en un estado
-de evolución muy temprana. Se trata de un marcado y barrido (*mark and sweep*)
-conservativo que, en ciertas circunstancias, no se comporta como es debido, ya
-que revisa toda la memoria del programa en busca de referencias a objetos en
-el *heap* (en vez de revisar sólo las partes que almacenan punteros). Esto
-produce que, en ciertos casos, por ejemplo al almacenar arreglos de número
-o *strings* en la pila, el recolector de basura se encuentre con *falsos
-positivos*, pensando que un área del *heap* está siendo utilizada cuando en
-realidad el puntero que hacía referencia a ésta no era tal. Este efecto puede
-llevar a la pérdida de memoria masiva, llegando al límite de que eventualmente
-el sistema operativo tenga que matar al programa por falta de memoria
-[DNG46407]_. Aún cuando el programa no tenga estos problemas de por sí, por
-usar datos que no pueden ser confundidos con direcciones de memoria, este
-problema podría ser explotado por ataques de seguridad, inyectando valores que
-sí sean punteros válidos y provocando el efecto antes mencionado que deriva en
-la terminación abrupta del programa [DNG35364]_. Finalmente, a estos problemas
-se suman los problemas de *performance* [DNG43991]_.
+A continuación se resumen las funciones principales, separadas en categorías
+para facilitar la comprensión. Los siguientes son métodos de la estructura
+``Gcx``:
+
+**Inicialización y terminación**
+
+ *initialize()*:
+ inicializa las estructuras internas del recolector para que pueda ser
+ utilizado. Esta función la llama la biblioteca *runtime* antes de que el
+ programa comience a correr.
+
+ *Dtor()*:
+ libera todas las estructuras que utiliza el recolector.
+
+**Manipulación de raíces definidas por el usuario**
+
+ *addRoot(p)*, *removeRoot(p)*, *rootIter(dg)*:
+ agrega, remueve e itera sobre las raíces simples definidas por el
+ usuario.
+
+ *addRange(pbot, ptop)*, *remove range(pbot)*, *rangeIter(dg)*:
+ agrega, remueve e itera sobre los rangos de raíces definidas por el
+ usuario.
+
+**Manipulación de indicadores**
+
+ Cada bloque (*bin* en la terminología de la implementación del recolector)
+ tiene ciertos indicadores asociados. Algunos de ellos pueden ser
+ manipulados (indirectamente) por el usuario utilizando estas funciones:
+
+ *getBits(pool, biti)*:
+ obtiene los indicadores especificados para el bloque de índice ``biti``
+ en el *pool* ``pool``.
+
+ *setBits(pool, biti, mask)*:
+ establece los indicadores especificados en ``mask`` para el bloque de
+ índice ``biti`` en el *pool* ``pool``.
+
+ *clrBits(pool, biti, mask)*:
+ limpia los indicadores especificados en ``mask`` para el bloque de
+ índice ``biti`` en el *pool* ``pool``.
+
+ El parámetro ``mask`` debe ser una máscara de bits que puede estar
+ compuesta por la conjunción de los siguientes valores:
+
+ *FINALIZE*:
+ el objeto almacenado en el bloque tiene un destructor (indicador
+ *finals*).
+
+ *NO_SCAN*:
+ el objeto almacenado en el bloque no contiene punteros (indicador
+ *noscan*).
+
+ *NO_MOVE*:
+ el objeto almacenado en el bloque no debe ser movido [#dgcmove]_.
+
+.. [#dgcmove] Si bien el recolector actual no tiene la capacidad de mover
+ objetos, la interfaz del recolector hacer que sea posible una
+ implementación que lo haga, ya que a través de este indicador se pueden
+ fijar objetos apuntados desde algún segmento no conservativo (objeto
+ *pinned*).
+
+**Búsquedas**
+
+ *findPool(p)*:
+ busca el *pool* al que pertenece el objeto apuntado por ``p``.
+
+ *findBase(p)*:
+ busca la dirección base (el inicio) del bloque apuntado por ``p``
+ (``find_block()`` según la sección :ref:`dgc_algo_mark`).
+
+ *findSize(p)*:
+ busca el tamaño del bloque apuntado por ``p``.
+
+ *getInfo(p)*:
+ obtiene información sobre el bloque apuntado por ``p``. Dicha
+ información se retorna en una estructura ``BlkInfo`` que contiene los
+ siguientes atributos: ``base`` (dirección del inicio del bloque),
+ ``size`` (tamaño del bloque) y ``attr`` (atributos o indicadores del
+ bloque, los que se pueden obtener con ``getBits()``).
+
+ *findBin(size)*:
+ calcula el tamaño de bloque más pequeño que pueda contener un objeto de
+ tamaño ``size`` (``find_block_size()`` según lo visto en
+ :ref:`dgc_algo_alloc`).
+
+**Asignación de memoria**
+
+ Recordar que la ``pooltable`` siempre se mantiene ordenada según la
+ dirección de la primera página.
+
+ *reserve(size)*:
+ reserva un nuevo *pool* de al menos ``size`` bytes. El algoritmo nunca
+ crea un *pool* con menos de 256 páginas (es decir, 1 MiB).
+
+ *minimize()*:
+ minimiza el uso de la memoria retornando *pools* sin páginas usadas al
+ sistema operativo.
+
+ *newPool(n)*:
+ reserva un nuevo *pool* con al menos ``n`` páginas. Junto con
+ ``Pool.initialize()`` es análoga a ``new_pool()``, solo que esta función
+ siempre incrementa el número de páginas a, al menos, 256 páginas (es
+ decir, los *pools* son siempre mayores a 1 MiB). Si la cantidad de
+ páginas pedidas supera 256, se incrementa el número de páginas en un 50%
+ como para que sirva para futuras asignaciones también. Además a medida
+ que la cantidad de *pools* crece, también trata de obtener cada vez más
+ memoria. Si ya había un *pool*, el 2do tendrá como mínimo 2 MiB, el 3ro
+ 3 MiB y así sucesivamente hasta 8 MiB. A partir de ahí siempre crea
+ *pools* de 8 MiB o la cantidad pedida, si ésta es mayor.
+
+ *Pool.initialize(n_pages)*:
+ inicializa un nuevo *pool* de memoria. Junto con ``newPool()`` es
+ análoga a ``new_pool()``. Mientras ``newPool()`` es la encargada de
+ calcular la cantidad de páginas y crear el objeto *pool*, esta función
+ es la que pide la memoria al sistema operativo. Además inicializa los
+ conjuntos de bits: ``mark``, ``scan``, ``freebits``, ``noscan``.
+ ``finals`` se inicializa de forma perezosa, cuando se intenta asignar el
+ atributo ``FINALIZE`` a un bloque, se inicializa el conjunto de bits
+ ``finals`` de todo el *pool*.
+
+ *allocPage(bin)*:
+ asigna a una página libre el tamaño de bloque ``bin`` y enlaza los
+ nuevos bloques libres a la lista de libres correspondiente (análogo
+ a ``assign_page()``).
+
+ *allocPages(n)*:
+ Busca ``n`` cantidad de páginas consecutivas libres (análoga
+ a ``find_pages(n)``).
+
+ *malloc(size, bits)*:
+ asigna memoria para un objeto de tamaño ``size`` bytes. Análoga al
+ algoritmo ``new(size, attr)`` presentado, excepto que introduce además
+ un caché para no recalcular el tamaño de bloque necesario si se realizan
+ múltiples asignaciones consecutivas de objetos del mismo tamaño y que la
+ asignación de objetos pequeños no está separada en una función aparte.
+
+ *bigAlloc(size)*:
+ asigna un objeto grande (análogo a ``new_big()``). La implementación es
+ mucho más compleja que la presentada en ``new_big()``, pero la semántica
+ es la misma. La única diferencia es que esta función aprovecha que
+ ``fullcollectshell()`` / ``fullcollect()`` retornan la cantidad de
+ páginas liberadas en la recolección por lo que puede optimizar levemente
+ el caso en que no se liberaron suficientes páginas para asignar el
+ objeto grande y pasar directamente a crear un nuevo *pool*.
+
+ *free(p)*:
+ libera la memoria apuntada por ``p`` (análoga a ``delete()`` de la
+ sección anterior).
+
+**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.
+
+ *fullcollectshell()*:
+ guarda los registros en el *stack* y llama a ``fullcollect()``. El
+ algoritmo presentado en :ref:`dgc_algo_mark` es simbólico, ya que si los
+ registros se apilaran en el *stack* dentro de otra función, al salir de
+ esta se volverían a desapilar, por lo tanto debe ser hecho en la misma
+ función ``collect()`` o en una función que luego la llame (como en este
+ caso).
+
+ *fullcollect(stackTop)*:
+ realiza la recolección de basura. Es análoga a ``collect()`` pero
+ considerablemente menos modularizada, todos los pasos se hacen
+ directamente en esta función: marcado del *root set*, marcado iterativo
+ del *heap*, barrido y reconstrucción de la lista de libres. Además
+ devuelve la cantidad de páginas que se liberaron en la recolección, lo
+ que permite optimizar levemente la función ``bigAlloc()``.