Changes between Version 19 and Version 20 of Commentary/Compiler/RecompilationAvoidance

Dec 2, 2010 12:21:53 PM (4 years ago)

change description of instances following fix for #4469


  • Commentary/Compiler/RecompilationAvoidance

    v19 v20  
    434434depends on, and hence will trigger recompilation. 
    436 This is perfectly safe, but implementing it exactly as described above 
    437 would lead to unnecessary recompilation.  For example 
     436In fact, we don't need to include the instance itself when fingerprinting C or T, it is enough to include the DFun (dictionary function) Id, since the type of this Id includes the form of the instance.  Furthermore, we ''must'' include the DFun anway, because we must have a dependency on the dictionary and its methods, just in case they are inlined in a client module.  A DFun looks something like this: 
     440  $fEqBool :: GHC.Base.Eq GHC.Bool.Bool 
     441    {- HasNoCafRefs Strictness: m 
     442       Unfolding: (GHC.Base.:DEq @ GHC.Bool.Bool GHC.Base.==2 
     443       GHC.Base.$s$dm/=1) 
     446Making a type or class depend on its instances can cause a lot of recompilation when an instance changes.  For example: 
    446 now the instance `C T` will be attached to `T`.  But we really don't 
    447 want to include `C`'s fingerprint in `T`'s fingerprint, because that would 
    448 register an unnecessary dependency of `T` on `C`: every time `C` 
    449 changed, we'd recompile anything that depended on `T`.  The dependency 
    450 is unnecessary, because we know anything that needs the instance will 
    451 already depend on both `C` and `T`. 
    453 So instead of creating a fingerprint that depends on the instance 
    454 declaration and everything it mentions, we fingerprint ''just the 
    455 declaration itself''.  This works by fingerprinting each name in the 
    456 declaration as its literal string, rather than the fingerprint of the 
    457 name. 
    459 But what about the ''contents'' of the instance declaration?  With 
    460 optimisation on, the compiler may inline instances and their methods, 
    461 so if an instance changes we need to trigger recompilation for any 
    462 module that actually used the previous version of the instance.  This 
    463 works as follows.  An instance declaration looks like this 
    465 {{{ 
    466 instance GHC.Base.Eq [GHC.Bool.Bool] = GHC.Base.$f10 
    467 }}} 
    469 Here `GHC.Base.$f10` is the "dictionary function", i.e. the value 
    470 representing this dictionary.  `GHC.Base.$f10` has a declaration of 
    471 its own, in the same interface, complete with a fingerprint. 
    473 {{{ 
    474 c3e94597bf9a532e094067b08c216493 
    475   $f10 :: GHC.Base.Eq GHC.Bool.Bool 
    476     {- HasNoCafRefs Strictness: m 
    477        Unfolding: (GHC.Base.:DEq @ GHC.Bool.Bool GHC.Base.==2 
    478        GHC.Base.$s$dm/=1) 
    479 }}} 
    481 So we ensure that any module that used this instance registers the 
    482 fingerprint of `GHC.Base.$f10` in its usages (this is the single 
    483 exception to the rule that the usages only contains names that are 
    484 explicitly mentioned in the source file). 
     455now the DFun for the instance `C T` will be attached to `T`, and so `T`'s fingerprint will change when anything about the instance changes, including `C` itself.  So there is now have a dependency of `T` on `C`, which can cause a lot of recompilation whenever `C` changes.  Modules using `T` who do not care about `C` will still be recompiled. 
     457This seems like it would cause a lot of unnecessary recompilation.  Indeed, in GHC 7.0.1 and earlier we tried to optimise this case, by breaking the dependency of `T` on `C` and tracking usages of DFuns directly - whenever a DFun was used, the typechecker would record the fact, and a usage on the DFun would be recorded in the interface file.  Unfortunately, there's a bug in this plan (see #4469).  When we're using `make`, we only recompile a module when any of the interfaces that it directly imports have changed; but a DFun dependency can refer to any module, not just the directly imported ones.  Instead, we have to ensure that if an instance related to a particular type or class has changed, then the fingerprint on either the type or class changes, which is what the current plan does.  It would be nice to optimise this in a safe way, and maybe in the future we will be able to do that. 
    486459=== Orphans ===