Ремонт принтеров, сканнеров, факсов и остальной офисной техники


назад Оглавление вперед




[160]

Непосредственно перед сборкой мусора

the-cars the-cdrs

new-cars

new-cdrs

смесь полезных данных и мусора

рабочая память

свободная

свободная память

свободная память

new-cars new-cdrs

сразу после сборки мусора

освобожденная память

новая

свободная

память

the-cars the-cdrs

полезные данные

свободная область

новая

рабочая

память

Рис. 5.15: Перестройка памяти в процессе сборки мусора.


мещены и просканированы. В этот момент указатель scan догонит указатель free, и процесс завершится.

Алгоритм остановки с копированием можно описать как последовательность команд регистровой машины. Базовый шаг, состоящий в перемещении объекта, проделывается подпрограммой relocate-old-result-in-new. Эта подпрограмма принимает свой аргумент, указатель на объект, подлежащий перемещению, в регистре old. Она перемещает данный объект (по пути обновляя free), помещает указатель на перемещенный объект в регистр new, и возвращается, переходя на точку входа, хранимую в регистре relocate-continue. В начале процесса сборки мы с помощью этой подпрограммы перемещаем указатель root, после инициализации free и scan. Когда root перемещен, мы записываем новый указатель в регистр root и входим в основной цикл сборщика мусора.

begin-garbage-collection (assign free (const 0)) (assign scan (const 0)) (assign old (reg root))

(assign relocate-continue (label reassign-root)) (goto (label relocate-old-result-in-new)) reassign-root

(assign root (reg new)) (goto (label gc-loop))

В основном цикле сборщика мусора нам нужно определить, есть ли еще подлежащие сканированию объекты. Для этого мы проверяем, совпадает ли указатель scan с указателем free. Если указатели равны, значит, все доступные объекты перемещены, и мы переходим на gc-flip. По этому адресу расположены восстановительные действия, после которых можно продолжить прерванные вычисления. Если же еще есть пары, которые требуется просканировать, мы зовем подпрограмму перемещения для car следующей пары (при вызове мы помещаем указатель car в регистр old). Регистр relocate-continue устанавливается таким образом, чтобы при возврате мы могли обновить указатель car.

gc-loop

(test (op =) (reg scan) (reg free)) (branch (label gc-flip))

(assign old (op vector-ref) (reg new-cars) (reg scan)) (assign relocate-continue (label update-car)) (goto (label relocate-old-result-in-new))

На метке update-car мы изменяем указатель car сканируемой пары. После этого мы перемещаем ее cdr, а затем возвращаемся на метку update-cdr. Наконец, когда cdr перемещен и обновлен, сканирование пары закончено, и мы продолжаем главный цикл.

update-car (perform

(op vector-set!) (reg new-cars) (reg scan) (reg new)) (assign old (op vector-ref) (reg new-cdrs) (reg scan)) (assign relocate-continue (label update-cdr)) (goto (label relocate-old-result-in-new))


update-cdr (perform

(op vector-set!) (reg new-cdrs) (reg scan) (reg new)) (assign scan (op +) (reg scan) (const 1)) (goto (label gc-loop))

Подпрограмма relocate-old-result-in-new перемещает объекты следующим образом: если перемещаемый объект (на него указывает old) не является парой, мы возвращаем указатель на него неизменным (в регистре new). (К примеру, мы можем сканировать пару, в car которой находится число 4. Если значение в car представляется как n4, как описано в разделе 5.3.1, то нам нужно, чтобы «перемещенный» car по-прежнему равнялся n4.) В противном случае требуется произвести перемещение. Если позиция car перемещаемой пары содержит метку разбитого сердца, значит, сама пара уже перенесена, и нам остается только взять перенаправляющий адрес (из позиции cdr разбитого сердца) и вернуть его в регистре new. Если же регистр old указывает на еще пе перенесенную пару, то мы ее переносим в первую пустую ячейку новой памяти (на нее указывает free), а затем строим разбитое сердце, записывая в старой ячейке метку разбитого сердца и перенаправляющий адрес. Процедура relocate-old-result-in-new хранит car или cdr объекта, на который указывает old, в регистре oldcr.18

relocate-old-result-in-new

(test (op pointer-to-pair?) (reg old))

(branch (label pair))

(assign new (reg old))

(goto (reg relocate-continue)) pair

(assign oldcr (op vector-ref) (reg the-cars) (reg old)) (test (op broken-heart?) (reg oldcr)) (branch (label already-moved))

(assign new (reg free)) ; новов мвсто для пары

;; Обновить указатвль free. (assign free (op +) (reg free) (const 1))

;; Скопировать car и cdr в новую память. (perform (op vector-set!)

(reg new-cars) (reg new) (reg oldcr)) (assign oldcr (op vector-ref) (reg the-cdrs) (reg old)) (perform (op vector-set!)

(reg new-cdrs) (reg new) (reg oldcr)) ;; Построить разбитов сврдцв. (perform (op vector-set!)

(reg the-cars) (reg old) (const broken-heart))

(perform

(op vector-set!) (reg the-cdrs) (reg old) (reg new)) (goto (reg relocate-continue))

18Сборщик мусора использует низкоуровневый предикат pointer-to-pair? вместо обыкновенного pair?, поскольку в настоящей системе могут иметься различные объекты, которые с точки зрения сборщика будут являться парами. Например, в системе, которая соответствует стандарту Scheme IEEE, объект-процедура может реализовываться особого рода «парой», которая не удовлетворяет предикату pair?. В нашем имитаторе можно реализовать pointer-to-pair? как pair?.



[стр.Начало] [стр.1] [стр.2] [стр.3] [стр.4] [стр.5] [стр.6] [стр.7] [стр.8] [стр.9] [стр.10] [стр.11] [стр.12] [стр.13] [стр.14] [стр.15] [стр.16] [стр.17] [стр.18] [стр.19] [стр.20] [стр.21] [стр.22] [стр.23] [стр.24] [стр.25] [стр.26] [стр.27] [стр.28] [стр.29] [стр.30] [стр.31] [стр.32] [стр.33] [стр.34] [стр.35] [стр.36] [стр.37] [стр.38] [стр.39] [стр.40] [стр.41] [стр.42] [стр.43] [стр.44] [стр.45] [стр.46] [стр.47] [стр.48] [стр.49] [стр.50] [стр.51] [стр.52] [стр.53] [стр.54] [стр.55] [стр.56] [стр.57] [стр.58] [стр.59] [стр.60] [стр.61] [стр.62] [стр.63] [стр.64] [стр.65] [стр.66] [стр.67] [стр.68] [стр.69] [стр.70] [стр.71] [стр.72] [стр.73] [стр.74] [стр.75] [стр.76] [стр.77] [стр.78] [стр.79] [стр.80] [стр.81] [стр.82] [стр.83] [стр.84] [стр.85] [стр.86] [стр.87] [стр.88] [стр.89] [стр.90] [стр.91] [стр.92] [стр.93] [стр.94] [стр.95] [стр.96] [стр.97] [стр.98] [стр.99] [стр.100] [стр.101] [стр.102] [стр.103] [стр.104] [стр.105] [стр.106] [стр.107] [стр.108] [стр.109] [стр.110] [стр.111] [стр.112] [стр.113] [стр.114] [стр.115] [стр.116] [стр.117] [стр.118] [стр.119] [стр.120] [стр.121] [стр.122] [стр.123] [стр.124] [стр.125] [стр.126] [стр.127] [стр.128] [стр.129] [стр.130] [стр.131] [стр.132] [стр.133] [стр.134] [стр.135] [стр.136] [стр.137] [стр.138] [стр.139] [стр.140] [стр.141] [стр.142] [стр.143] [стр.144] [стр.145] [стр.146] [стр.147] [стр.148] [стр.149] [стр.150] [стр.151] [стр.152] [стр.153] [стр.154] [стр.155] [стр.156] [стр.157] [стр.158] [стр.159] [стр.160] [стр.161] [стр.162] [стр.163] [стр.164] [стр.165] [стр.166] [стр.167] [стр.168] [стр.169] [стр.170] [стр.171] [стр.172] [стр.173] [стр.174] [стр.175] [стр.176] [стр.177] [стр.178] [стр.179] [стр.180] [стр.181] [стр.182] [стр.183] [стр.184] [стр.185] [стр.186] [стр.187] [стр.188] [стр.189] [стр.190] [стр.191] [стр.192] [стр.193] [стр.194] [стр.195] [стр.196]