#616: compacting/copying gc
---------------------+------------------------------------------------------
 Reporter:  allison  |       Owner:     
     Type:  roadmap  |      Status:  new
 Priority:  normal   |   Milestone:  3.0
Component:  none     |     Version:     
 Severity:  medium   |    Keywords:     
     Lang:           |       Patch:     
 Platform:           |  
---------------------+------------------------------------------------------

Comment(by mikehh):

 Copying Garbage Collector

 The basic concept of a Copying Collector is that the heap is divided into
 two
 equal semi-spaces, one of which contains the current data and the other
 obsolete data.  The Garbage Collection phase starts by flipping the roles
 of
 the two semi-spaces.  The collector then scans the active data in the old
 semi-space, Fromspace, copying each live cell into the new semi-space,
 Tospace.
 On completion of the collection phase, Tospace contains all the active
 data and
 Fromspace is effectively abandoned.

 One major advantage of this is that the active data is compacted at the
 bottom
 of Tospace.  Compacting collectors can allocate space much more
 efficiently
 than collectors in which fragmentation is a problem.

 Allocation costs are extremely low.  The out-of-space check is a simple
 pointer
 comparison.  New memory is acquired by simply incrementing the free-space
 pointer. Fragmentation is eliminated by simply copying the active data
 into the
 bottom of Tospace.

 The chief drawback of copying collectors is the need to divide the
 available
 memory into two semi-spaces.  As the residency of a program increases the
 performance of the collector degrades, as less free space is recovered and
 collections become more frequent.

 The basic algorithm:
 {{{
 init() =
     Tospace = Heap_bottom
     space_size - Heap_size / 2
     top_of_space = Tospace + space_size
     Fromspace = top_of_space + 1
     free = Tospace

 New(n) =
     if free + n > top_of_spece
         flip()
     if free + n > top_of_space
         abort "Memory exhausted"
     newcell = free
     free = free + n
     return newcell

 flip() =
     Fromspace, Tospace = Tospace, Fromspace
     top_of_space = Tospace + space_size
     free = Tospace
     for R in roots
         R = copy(R)


 -- P points to a word not a cell
 copy(P) =
     if atomic(P) or P == nil        -- P is not a pointer
         return P

     if not forwarded(P)
         n = size(P)
         P' = free                   -- reserve space in Topace
         free = free + n
         temp = P[0]                 -- field 0 will hold the forwarding
 address
         forwardingaddress[P] = P'
         P'[0] = copy(temp)
         for i = 1 to n-1            -- copy each field of P into P'
             P'[i] = copy(P[i])

     return forwarding_address(P)

 }}}

 First, the roles of Tospace and Fromspace ar swapped by a flip, which
 resets
 the variables Tospace, Fromspace and top_of_space.  Each cell reachable
 from
 a root is then copied from Fromspace to Tospace.  For clarity, a simple
 recursive algorithm is used, (more elegant iterative algorithms are
 available).
 Copy(P) scavenges the fields of the cell pointed to by P.  Care has to be
 taken
 when copying data structures to ensure that the topology of the shared
 data
 structures is preserved.  Failure to do this would lead to multiple copies
 of
 shared objects, which at best would increase heap residency of the program
 but
 may also break the user program (for example, if it updated one copy of a
 cell,
 but then read the value from another).  Copying cyclic data structures
 without
 preserving sharing would also require a lot of room!

 Copying collectors preserve sharing by leaving a forwarding address in the
 Fromspace object when it is copied.  The forwarding address is the address
 of
 the copy in Tospace.  When a cell in Fromspace is visited, copy checks to
 see
 if it has already been copied, if it has the forwarding address is
 returned,
 otherwise memory is reserved for the copy in Tospace.  In this recursive
 copying algorithm, the forwarding address is set to point to this reserved
 memory before the constituent fields of the object are copied -- this
 ensures
 termination and that sharing is preserved.

 The forwarding address might be held in its own field in the cell.  More
 generally it can be written over the first word in the cell provided that
 the
 original value of the cell is saved beforehand.  In the above it is
 assumed
 that the forwarding address field in cell P is P[0], and forwarding
 address(P)
 and P[0] are used interchangeably.

 extracted from: Garbage Collection: Algotithms for Automatic Dynamic
 Memory Management by Richard Jones and Rafael Sims
 [http://www.cs.kent.ac.uk/people/staff/rej/gc.html]

-- 
Ticket URL: <https://trac.parrot.org/parrot/ticket/616#comment:1>
Parrot <https://trac.parrot.org/parrot/>
Parrot Development
_______________________________________________
parrot-tickets mailing list
[email protected]
http://lists.parrot.org/mailman/listinfo/parrot-tickets

Reply via email to