1. Appel's scheme will not work for weakly-typed or polymorphic languages.  For example, let's suppose Appel's algorithm is traversing the type graph and a data structure and finds that a particular field of the data structure is an INTEGER (according to the type graph).  In a weakly typed language such as C, this field could contain anything that would fit in the "INTEGER".  Thus, the garbage collector would not know whether to treat that field as a pointer or as an integer.  Similarly, let's suppose that the above-mentioned field was of type REF T.  In a polymorphic type system, this field could either point to an object of type T or any subtype of T.  So once again, the garbage collector will not know what the field points to.
  2. (i) time spent doing allocation will be less for scheme 1 since it just needs to do check and bump a pointer.  Scheme II needs to search a free list (note: an allocation may trigger a garbage collection but that is a "deallocation" cost and thus will be compared to explicit deallocation).
    (ii) time spent doing deallocation.  Scheme II needs to explicitly free each garbage object, and thus does work proportional in the size and number of dead objects.  Scheme I copies the reachable objects and thus does work proportional in the number of reachable objects per garbage collection.  If most objects are short-lived, Scheme I will do much less work than Scheme II.  If most objects are long-lived, then the balance may shift in favor of Scheme II since Scheme I will need to copy these long lived objects back and forth every garbage collection.
    (iii)paging behavior.  Scheme I compacts the reachable objects and thus will have a smaller memory footprint, probably leading to better paging behavior than Scheme II.  On the other hand, during garbage collection, Scheme I will touch objects all over memory and thus the paging behavior during garbage collection may neutralize the benefits of compaction.  The bottom line is that it depends on whether objects are short lived or long lived, because if they are short lived, Scheme I will not touch many pages during gc.
  3. After the statement "l1 = quicksort(lt)", the variable "lt" is dead--i.e., it will not be accessed again in the future.  If the garbage collector has this information then even though lt contains a pointer, the gc does not need to consider "lt" as a root variable.  In other words, a garbage collector that does not have liveness information will keep the list pointed to by "lt" around for the lifetime of the enclosing instantiation of quicsort (and that lifetime corresponds to the time taken to sort the entire list passed to quicksort).  If on the other hand, the collector has the liveness information, it will be able to reclaim the list pointed to by lt as soon as quicksort(lt) returns.
  4. persistence independence: if this is violated, then the programmer would have to worry about writing separate code for persistent and non-persistent objects.
    data-type orthogonality: if this is violated, the programmer would have to declare two distinct sets of classes, one set for persistent objects and one set for non-persistent objects.  This could also potentially lead to problems if the user creates pointers from persistent to non-persistent objects.  Chances are that if this principle is violated, the principle of persistence independence has also been violated.
    persistence identification: if this is violated, then the programmer can end up creating pointers from persistent to transient objects, which will potentially manifest itself later as dangling pointer bugs.