(* GC Stop & Copy *) open Format open Array let ram = 100 let memory = make ram 0 let space_size = ram / 2 let max_roots = 10 let roots = make max_roots (-1) let is_pointer start p = start <= p && p < start + space_size let stop_and_copy from_space to_space = (* printf "collection from_space=%d to_space=%d@." from_space to_space; *) let next = ref to_space in let forward p = if is_pointer from_space p then if is_pointer to_space memory.(p + 1) then memory.(p + 1) else begin let size = memory.(p) in let p' = !next in (* printf " deslocação size=%d de %d para %d@." size p p'; *) memory.(p') <- size; for i = 1 to size do memory.(p' + i) <- memory.(p + i) done; memory.(p + 1) <- p'; next := !next + size + 1; p' end else p in let scan = ref to_space in for r = 0 to length roots - 1 do roots.(r) <- forward roots.(r) done; while !scan < !next do let size = memory.(!scan) in for i = 1 to size do memory.(!scan + i) <- forward memory.(!scan + i) done; scan := !scan + size + 1 done; printf "memória ocupada após recolha = %d palavras@\n" (!next - to_space); !next let first_space = ref true (* true = alocamos no primeiro meio-espaço i.e. from_space = 0 / to_space = space_size false = alocamos no segundo meio-espaço i.e. from_space = space_size / to_space = 0 *) let next = ref 0 (* primeiro espaço livre *) (* alocamos um bloco de tamanho size i.e. com size campos *) let rec alloc size = let from_space = if !first_space then 0 else space_size in let limit = from_space + space_size in if !next + size + 1 <= limit then begin (* há espaço suficiente *) let p = !next in memory.(p) <- size; next := !next + size + 1; p end else begin (* não há espaço suficiente *) let to_space = if !first_space then space_size else 0 in next := stop_and_copy from_space to_space; if !next + size + 1 >= to_space + limit then failwith "out of memory"; first_space := not !first_space; alloc size end let reset () = fill memory 0 ram (-42); fill roots 0 max_roots (-1); first_space := true; next := 0;; (**** (* teste com o exemplo da aula *) let _ = fill memory 0 ram (-42); fill roots 0 max_roots (-1); roots.(0) <- 9; roots.(1) <- 3; blit [| 2; -1; 3; 2; -2; 6; 2; -3; -1; 2; -2; -1; 2; 9; 3 |] 0 memory 0 15; stop_and_copy 0 space_size ****) (* resposta à adivinha : As funções insert e sort são recursivas e parte dos dados encontra-se assim as vezes arquivadas temporariamente na pilha, que é aqui a pilha de OCaml, logo não está materializada na memória. No caso extremo em que ram=100 e n=16 a integralidade da lista ocupa 48 palavras, para um meio-espaço de 50 palavras. Quando invocamos "sort", esta percorre a lista recursivamente, mantendo os elementos nas variáveis locais "y" que estão na pilha. Chegando ao fim, esta invoca "insert" e, visto que roots.(0)=-1, a primeira coisa que faz "insert" é alocar um bloco de tamanho 3 com "cons0 x". Visto não haver espaço, chamamos o GC, que recupera então toda a memória visto que roots.(0)=-1. Mas a lista sera reconstruída em memória, a partir dos valores arquivados em pilha. *)
This document was generated using caml2html