Fine-grained address translation schemes typically require that the persistence mechanism directly manage physical memory because persistent data are usually loaded into memory on a per-object basis.12 Therefore, it is usually necessary to implement a custom object replacement policy as part of the persistence mechanism. This affects not only the overall cost but also the implementation complexity.
A read barrier is typically implemented for every object that resides in memory. The usual action for a read barrier is to set one bit per object for maintaining recency information about object references to aid the object replacement policy. The read barrier may be implemented in software by preceding each object read with a call to the routine that sets the special bit for that object. Compiled code then contains extra instructions--usually inserted by the compiler--to implement the read barrier. The read barrier is typically expensive on stock hardware because, in the usual case, all read requests must be intercepted and recorded. It is known that one in about ten instructions is a pointer store (i.e., a write into a pointer) in Lisp systems that support compilation. Since read actions are more common than write actions, we estimate that between 5 and 20 percent of total instructions in an application usually correspond to a read from a pointer. The exact number obviously varies by application, and more importantly, by the source language; for example, it is likely to be higher in heap-oriented languages such as Java. It may be possible to use data flow analysis during compilation such that the read barrier can be optimized away for some object references; such analysis is, however, hard to implement.
The object replacement policy also interferes with general swizzling, especially if an edge-marking technique is being used. In such cases, the object cannot be evicted from memory without first invalidating all edges that reference it. This obviously requires knowledge about references to the object being evicted. Kemper and Kossman [10] solve this by using a per-object data structure known as a Reverse Reference List (RRL) to maintain a set of back-pointers to all objects that reference a given object. McAuliffe and Solomon [12] use a different data structure, called the swizzle table, a fixed-size hash table that maintains a list of all swizzled pointers in the system. Both these approaches are generally unfavorable because they increase the storage requirements (essentially doubling the number of pointers at the minimum) and the implementation complexity.