Theory Noninterference
theory Noninterference
imports
  Global_Invariants_Lemmas
  Local_Invariants_Lemmas
  Tactics
begin
section‹ Noninterference ›
lemma mut_del_barrier1_subseteq_mut_mo_valid_ref_locs[locset_cache]: 
  "mut_m.del_barrier1_locs ⊆ mut_m.mo_valid_ref_locs"
unfolding mut_m.del_barrier1_locs_def mut_m.mo_valid_ref_locs_def by (auto intro: append_prefixD)
lemma mut_del_barrier2_subseteq_mut_mo_valid_ref[locset_cache]: 
  "mut_m.ins_barrier_locs ⊆ mut_m.mo_valid_ref_locs"
unfolding mut_m.ins_barrier_locs_def mut_m.mo_valid_ref_locs_def by (auto intro: append_prefixD)
context gc
begin
lemma obj_fields_marked_locs_subseteq_hp_IdleMarkSweep_locs:
  "obj_fields_marked_locs ⊆ hp_IdleMarkSweep_locs"
unfolding gc.obj_fields_marked_locs_def gc.hp_IdleMarkSweep_locs_def gc.mark_loop_locs_def gc.mark_loop_mo_locs_def
apply (clarsimp simp: locset_cache loc_defs)
apply (drule mp)
apply (auto intro: append_prefixD)
done
lemma obj_fields_marked_locs_subseteq_hs_in_sync_locs:
  "obj_fields_marked_locs ⊆ hs_in_sync_locs"
unfolding obj_fields_marked_locs_def hs_in_sync_locs_def hs_done_locs_def mark_loop_mo_locs_def
by (auto simp: loc_defs dest: prefix_same_cases)
lemma obj_fields_marked_good_ref_subseteq_hp_IdleMarkSweep_locs:
  "obj_fields_marked_good_ref_locs ⊆ hp_IdleMarkSweep_locs"
unfolding obj_fields_marked_good_ref_locs_def mark_loop_locs_def hp_IdleMarkSweep_locs_def mark_loop_mo_locs_def
apply (clarsimp simp: loc_defs)
apply (drule mp)
apply (auto intro: append_prefixD)
done
lemma mark_loop_mo_mark_loop_field_done_subseteq_hs_in_sync_locs:
  "obj_fields_marked_good_ref_locs ⊆ hs_in_sync_locs"
unfolding obj_fields_marked_good_ref_locs_def hs_in_sync_locs_def mark_loop_mo_locs_def hs_done_locs_def
by (auto simp: loc_defs dest: prefix_same_cases)
lemma no_grey_refs_locs_subseteq_hs_in_sync_locs:
  "no_grey_refs_locs ⊆ hs_in_sync_locs"
by (auto simp: no_grey_refs_locs_def black_heap_locs_def hs_in_sync_locs_def hs_done_locs_def sweep_locs_def loc_defs
         dest: prefix_same_cases)
lemma get_roots_UN_get_work_locs_subseteq_gc_W_empty_locs:
  "get_roots_UN_get_work_locs ⊆ gc_W_empty_locs"
unfolding get_roots_UN_get_work_locs_def
by (auto simp: hs_get_roots_locs_def hs_get_work_locs_def gc_W_empty_locs_def)
end
declare
  gc.obj_fields_marked_locs_subseteq_hp_IdleMarkSweep_locs[locset_cache]
  gc.obj_fields_marked_locs_subseteq_hs_in_sync_locs[locset_cache]
  gc.obj_fields_marked_good_ref_subseteq_hp_IdleMarkSweep_locs[locset_cache]
  gc.mark_loop_mo_mark_loop_field_done_subseteq_hs_in_sync_locs[locset_cache]
  gc.no_grey_refs_locs_subseteq_hs_in_sync_locs[locset_cache]
  gc.get_roots_UN_get_work_locs_subseteq_gc_W_empty_locs[locset_cache]
lemma handshake_obj_fields_markedD:
  "⟦ atS gc gc.obj_fields_marked_locs s; gc.handshake_invL s ⟧ ⟹ sys_ghost_hs_phase s↓ = hp_IdleMarkSweep ∧ All (ghost_hs_in_sync (s↓ sys))"
unfolding gc.handshake_invL_def
by (metis (no_types, lifting) atS_mono gc.obj_fields_marked_locs_subseteq_hp_IdleMarkSweep_locs gc.obj_fields_marked_locs_subseteq_hs_in_sync_locs)
lemma obj_fields_marked_good_ref_locs_hp_phaseD:
  "⟦ atS gc gc.obj_fields_marked_good_ref_locs s; gc.handshake_invL s ⟧
     ⟹ sys_ghost_hs_phase s↓ = hp_IdleMarkSweep ∧ All (ghost_hs_in_sync (s↓ sys))"
unfolding gc.handshake_invL_def
by (metis (no_types, lifting) atS_mono gc.mark_loop_mo_mark_loop_field_done_subseteq_hs_in_sync_locs gc.obj_fields_marked_good_ref_subseteq_hp_IdleMarkSweep_locs)
lemma gc_marking_reaches_Mutate:
  assumes xys: "∀y. (x reaches y) s ⟶ valid_ref y s"
  assumes xy: "(x reaches y) (s(sys := s sys⦇heap := (sys_heap s)(r := map_option (λobj. obj⦇obj_fields := (obj_fields obj)(f := opt_r')⦈) (sys_heap s r)),
                                             mem_store_buffers := (mem_store_buffers (s sys))(p := ws)⦈))"
  assumes sb: "sys_mem_store_buffers (mutator m) s = mw_Mutate r f opt_r' # ws"
  assumes vri: "valid_refs_inv s"
  shows "valid_ref y s"
proof -
  from xy xys
  have "∃z. z ∈ {x} ∪ mut_m.tso_store_refs m s ∧ (z reaches y) s ∧ valid_ref y s"
  proof induct
    case (refl x) then show ?case by auto
  next
    case (step x y z) with sb vri show ?case
      apply (clarsimp simp: points_to_Mutate)
      apply (elim disjE)
         apply (metis (no_types, lifting) obj_at_cong reaches_def rtranclp.rtrancl_into_rtrancl)
        apply (metis (no_types, lifting) obj_at_def option.case(2) reaches_def rtranclp.rtrancl_into_rtrancl valid_refs_invD(4))
       apply clarsimp
       apply (elim disjE)
        apply (rule exI[where x=z])
        apply (clarsimp simp: mut_m.tso_store_refs_def)
        apply (rule valid_refs_invD(3)[where m=m and x=z], auto simp: mut_m.tso_store_refs_def; fail)[1]
       apply (metis (no_types, lifting) obj_at_cong reaches_def rtranclp.rtrancl_into_rtrancl)
      apply clarsimp
      apply (elim disjE)
       apply (rule exI[where x=z])
       apply (clarsimp simp: mut_m.tso_store_refs_def)
       apply (rule valid_refs_invD(3)[where m=m and x=z], auto simp: mut_m.tso_store_refs_def)[1]
      apply (metis (no_types, lifting) obj_at_def option.case(2) reaches_def rtranclp.rtrancl_into_rtrancl valid_refs_invD(4))
      done
  qed
  then show ?thesis by blast
qed
lemma (in sys) gc_obj_fields_marked_invL[intro]:
  notes filter_empty_conv[simp]
  notes fun_upd_apply[simp]
  shows
  "⦃ gc.fM_fA_invL ❙∧ gc.handshake_invL ❙∧ gc.obj_fields_marked_invL
       ❙∧ LSTP (fM_rel_inv ❙∧ handshake_phase_inv ❙∧ mutators_phase_inv ❙∧ tso_store_inv ❙∧ valid_refs_inv ❙∧ valid_W_inv) ⦄
     sys
   ⦃ gc.obj_fields_marked_invL ⦄"
proof(vcg_jackhammer (keep_locs) (no_thin_post_inv), vcg_name_cases)
  case (tso_dequeue_store_buffer s s' p w ws) show ?case
  proof(cases w)
       case (mw_Mark ref mark) with tso_dequeue_store_buffer show ?thesis
apply -
apply (clarsimp simp: p_not_sys gc.obj_fields_marked_invL_def)
apply (intro conjI impI; clarsimp)
apply (frule (1) handshake_obj_fields_markedD)
apply (clarsimp simp: gc.obj_fields_marked_def)
apply (frule (1) valid_W_invD)
apply (drule_tac x=x in spec)
apply clarsimp
apply (erule obj_at_field_on_heapE)
 apply (force split: obj_at_splits)
apply (force split: obj_at_splits)
apply (erule obj_at_field_on_heapE)
 apply (clarsimp split: obj_at_splits; fail)
apply (clarsimp split: obj_at_splits)
 apply (metis valid_W_invD(1))
apply (metis valid_W_invD(1))
apply (force simp: valid_W_invD(1) split: obj_at_splits)
done
  next case (mw_Mutate r f opt_r') with tso_dequeue_store_buffer show ?thesis
apply -
apply (clarsimp simp: p_not_sys gc.obj_fields_marked_invL_def)
apply (erule disjE; clarsimp)
apply (rename_tac m)
apply (drule_tac m=m in mut_m.handshake_phase_invD; clarsimp simp: hp_step_rel_def)
apply (drule_tac x=m in spec)
apply (intro conjI impI; clarsimp simp: obj_at_field_on_heap_imp_valid_ref gc_marking_reaches_Mutate split: option.splits)
subgoal for m
apply (frule (1) handshake_obj_fields_markedD)
apply (elim disjE; auto simp: gc.obj_fields_marked_def split: option.splits)
done
subgoal for m r'
apply (frule (1) obj_fields_marked_good_ref_locs_hp_phaseD)
apply (elim disjE; clarsimp simp: marked_insertionD)
done
done
  next case (mw_Mutate_Payload r f pl) with tso_dequeue_store_buffer show ?thesis by - (erule gc_obj_fields_marked_invL_niE; clarsimp)
  next case (mw_fA mark) with tso_dequeue_store_buffer show ?thesis by - (erule gc_obj_fields_marked_invL_niE; clarsimp)
  next case (mw_fM mark) with tso_dequeue_store_buffer show ?thesis
        apply -
        apply (clarsimp simp: p_not_sys fM_rel_inv_def fM_rel_def gc.obj_fields_marked_invL_def)
        apply (erule disjE; clarsimp)
        apply (intro conjI impI; clarsimp)
          apply (metis (no_types, lifting) handshake_obj_fields_markedD hs_phase.distinct(7))
         apply (metis (no_types, lifting) hs_phase.distinct(7) obj_fields_marked_good_ref_locs_hp_phaseD)
        apply (metis (no_types, lifting) UnCI elem_set hs_phase.distinct(7) gc.obj_fields_marked_good_ref_locs_def obj_fields_marked_good_ref_locs_hp_phaseD option.simps(15) thin_locs_pre_keep_atSE)
        done
  next case (mw_Phase ph) with tso_dequeue_store_buffer show ?thesis
        by - (erule gc_obj_fields_marked_invL_niE; clarsimp)
  qed
qed
subsection‹The infamous termination argument›
lemma (in mut_m) gc_W_empty_mut_inv_eq_imp:
  "eq_imp (λm'. sys_W ❙⊗ WL (mutator m') ❙⊗ sys_ghost_hs_in_sync m')
          gc_W_empty_mut_inv"
by (simp add: eq_imp_def gc_W_empty_mut_inv_def)
lemmas gc_W_empty_mut_inv_fun_upd[simp] = eq_imp_fun_upd[OF mut_m.gc_W_empty_mut_inv_eq_imp, simplified eq_imp_simps, rule_format]
lemma (in gc) gc_W_empty_invL_eq_imp:
  "eq_imp (λ(m', p) s. (AT s gc, s↓ gc, sys_W s↓, WL p s↓, sys_ghost_hs_in_sync m' s↓))
          gc_W_empty_invL"
by (simp add: eq_imp_def gc_W_empty_invL_def mut_m.gc_W_empty_mut_inv_def no_grey_refs_def grey_def)
lemmas gc_W_empty_invL_niE[nie] =
  iffD1[OF gc.gc_W_empty_invL_eq_imp[simplified eq_imp_simps, rule_format, unfolded conj_explode, rule_format], rotated -1]
lemma gc_W_empty_mut_inv_load_W:
  "⟦ ∀m. mut_m.gc_W_empty_mut_inv m s; ∀m. sys_ghost_hs_in_sync m s; WL gc s = {}; WL sys s = {} ⟧
     ⟹ no_grey_refs s"
apply (clarsimp simp: mut_m.gc_W_empty_mut_inv_def no_grey_refs_def grey_def)
apply (rename_tac x xa)
apply (case_tac xa)
apply (simp_all add: WL_def)
done
context gc
begin
lemma gc_W_empty_mut_inv_hs_init[iff]:
  "mut_m.gc_W_empty_mut_inv m (s(sys := s sys⦇hs_type := ht, ghost_hs_in_sync := ⟨False⟩⦈))"
  "mut_m.gc_W_empty_mut_inv m (s(sys := s sys⦇hs_type := ht, ghost_hs_in_sync := ⟨False⟩, ghost_hs_phase := hp' ⦈))"
by (simp_all add: mut_m.gc_W_empty_mut_inv_def)
lemma gc_W_empty_invL[intro]:
  notes fun_upd_apply[simp]
  shows
  "⦃ handshake_invL ❙∧ obj_fields_marked_invL ❙∧ gc_W_empty_invL ❙∧ LSTP valid_W_inv ⦄
     gc
   ⦃ gc_W_empty_invL ⦄"
apply (vcg_jackhammer; (clarsimp elim: gc_W_empty_mut_inv_load_W simp: WL_def)?)
proof vcg_name_cases
     case (mark_loop_get_work_done_loop s s') then show ?case
       by (simp add: WL_def gc_W_empty_mut_inv_load_W valid_W_inv_sys_ghg_empty_iff)
next case (mark_loop_get_roots_done_loop s s') then show ?case
       by (simp add: WL_def gc_W_empty_mut_inv_load_W valid_W_inv_sys_ghg_empty_iff)
qed
end
lemma (in sys) gc_gc_W_empty_invL[intro]:
  notes fun_upd_apply[simp]
  shows
  "⦃ gc.gc_W_empty_invL ⦄ sys"
by vcg_chainsaw
lemma empty_WL_GC:
  "⟦ atS gc gc.get_roots_UN_get_work_locs s; gc.obj_fields_marked_invL s ⟧ ⟹ gc_ghost_honorary_grey s↓ = {}"
unfolding gc.obj_fields_marked_invL_def
using atS_mono[OF _ gc.get_roots_UN_get_work_locs_subseteq_ghost_honorary_grey_empty_locs]
apply metis
done
lemma gc_hs_get_roots_get_workD:
  "⟦ atS gc gc.get_roots_UN_get_work_locs s; gc.handshake_invL s ⟧
     ⟹ sys_ghost_hs_phase s↓ = hp_IdleMarkSweep ∧ sys_hs_type s↓ ∈ {ht_GetWork, ht_GetRoots}"
unfolding gc.handshake_invL_def
apply clarsimp
apply (metis (no_types, lifting) atS_mono atS_un gc.get_roots_UN_get_work_locs_def gc.hs_get_roots_locs_subseteq_hp_IdleMarkSweep_locs gc.hs_get_work_locs_subseteq_hp_IdleMarkSweep_locs)
done
context gc
begin
lemma handshake_sweep_mark_endD:
  "⟦ atS gc no_grey_refs_locs s; handshake_invL s; handshake_phase_inv s↓ ⟧
     ⟹ mut_m.mut_ghost_hs_phase m s↓ = hp_IdleMarkSweep ∧ All (ghost_hs_in_sync (s↓ sys))"
apply (simp add: gc.handshake_invL_def)
apply (elim conjE)
apply (drule mp, erule atS_mono[OF _ gc.no_grey_refs_locs_subseteq_hs_in_sync_locs])
apply (drule mut_m.handshake_phase_invD)
apply (simp only: gc.no_grey_refs_locs_def cong del: atS_state_weak_cong)
apply (clarsimp simp: atS_un)
apply (elim disjE)
  apply (drule mp, erule atS_mono[where ls'="gc.hp_IdleMarkSweep_locs"])
   apply (clarsimp simp: gc.black_heap_locs_def locset_cache)
  apply (clarsimp simp: hp_step_rel_def)
  apply blast
 apply (drule mp, erule atS_mono[where ls'="gc.hp_IdleMarkSweep_locs"])
  apply (clarsimp simp: hp_IdleMarkSweep_locs_def hp_step_rel_def)
 apply (clarsimp simp: hp_step_rel_def)
 apply blast
apply (clarsimp simp: atS_simps locset_cache hp_step_rel_def)
apply blast
done
lemma gc_W_empty_mut_mo_co_mark:
  "⟦ ∀x. mut_m.gc_W_empty_mut_inv x s↓; mutators_phase_inv s↓;
     mut_m.mut_ghost_honorary_grey m s↓ = {};
     r ∈ mut_m.mut_roots m s↓ ∪ mut_m.mut_ghost_honorary_root m s↓; white r s↓;
     atS gc get_roots_UN_get_work_locs s; gc.handshake_invL s; gc.obj_fields_marked_invL s;
     atS gc gc_W_empty_locs s ⟶ gc_W s↓ = {};
     handshake_phase_inv s↓; valid_W_inv s↓ ⟧
    ⟹ mut_m.gc_W_empty_mut_inv m' (s↓(mutator m := s↓ (mutator m)⦇ghost_honorary_grey := {r}⦈))"
apply (frule (1) gc_hs_get_roots_get_workD)
apply (frule_tac m=m in mut_m.handshake_phase_invD)
apply (clarsimp simp: hp_step_rel_def simp del: Un_iff)
apply (elim disjE, simp_all)
proof(goal_cases before_get_work past_get_work before_get_roots after_get_roots)
     case before_get_work then show ?thesis
      apply (clarsimp simp: mut_m.gc_W_empty_mut_inv_def)
      apply blast
      done
next case past_get_work then show ?thesis
      apply (clarsimp simp: mut_m.gc_W_empty_mut_inv_def)
      apply (frule spec[where x=m], clarsimp)
      apply (frule (2) mut_m.reachable_snapshot_inv_white_root)
      apply clarsimp
      apply (drule grey_protects_whiteD)
      apply (clarsimp simp: grey_def)
      apply (rename_tac g p)
      apply (case_tac p; clarsimp)
        
        apply blast
       
       apply (frule (1) empty_WL_GC)
       apply (drule mp, erule atS_mono[OF _ get_roots_UN_get_work_locs_subseteq_gc_W_empty_locs])
       apply (clarsimp simp: WL_def; fail)
      
      apply (clarsimp simp: WL_def valid_W_inv_sys_ghg_empty_iff; fail)
      done
next case before_get_roots then show ?case
      apply (clarsimp simp: mut_m.gc_W_empty_mut_inv_def)
      apply blast
      done
next case after_get_roots then show ?case
      apply (clarsimp simp: mut_m.gc_W_empty_mut_inv_def)
      apply (frule spec[where x=m], clarsimp)
      apply (frule (2) mut_m.reachable_snapshot_inv_white_root)
      apply clarsimp
      apply (drule grey_protects_whiteD)
      apply (clarsimp simp: grey_def)
      apply (rename_tac g p)
      apply (case_tac p; clarsimp)
        
        apply blast
       
       apply (frule (1) empty_WL_GC)
       apply (drule mp, erule atS_mono[OF _ get_roots_UN_get_work_locs_subseteq_gc_W_empty_locs])
       apply (clarsimp simp: WL_def; fail)
      
      apply (clarsimp simp: WL_def valid_W_inv_sys_ghg_empty_iff; fail)
      done
qed
lemma no_grey_refs_mo_co_mark:
  "⟦ mutators_phase_inv s↓;
     no_grey_refs s↓;
     gc.handshake_invL s;
     at gc mark_loop s ∨ at gc mark_loop_get_roots_load_W s ∨ at gc mark_loop_get_work_load_W s ∨ atS gc no_grey_refs_locs s;
     r ∈ mut_m.mut_roots m s↓ ∪ mut_m.mut_ghost_honorary_root m s↓; white r s↓;
     handshake_phase_inv s↓ ⟧
    ⟹ no_grey_refs (s↓(mutator m := s↓ (mutator m)⦇ghost_honorary_grey := {r}⦈))"
apply (elim disjE)
   apply (clarsimp simp: atS_simps gc.handshake_invL_def locset_cache)
   apply (frule mut_m.handshake_phase_invD)
   apply (clarsimp simp: hp_step_rel_def)
   apply (drule spec[where x=m])
   apply (clarsimp simp: conj_disj_distribR[symmetric])
   apply (simp add: handshake_in_syncD mut_m.no_grey_refs_not_rootD; fail)
  apply (clarsimp simp: atS_simps gc.handshake_invL_def locset_cache)
  apply (frule mut_m.handshake_phase_invD)
  apply (clarsimp simp: hp_step_rel_def)
  apply (drule spec[where x=m])
  apply (simp add: handshake_in_syncD mut_m.no_grey_refs_not_rootD; fail)
 apply (clarsimp simp: atS_simps gc.handshake_invL_def locset_cache)
 apply (frule mut_m.handshake_phase_invD)
 apply (clarsimp simp: hp_step_rel_def)
 apply (drule spec[where x=m])
 apply (simp add: handshake_in_syncD mut_m.no_grey_refs_not_rootD; fail)
apply (frule (2) handshake_sweep_mark_endD)
apply (drule spec[where x=m])
apply clarsimp
apply (simp add: handshake_in_syncD mut_m.no_grey_refs_not_rootD; fail)
done
end
context mut_m
begin
lemma gc_W_empty_invL[intro]:
  notes gc.gc_W_empty_mut_mo_co_mark[simp]
  notes gc.no_grey_refs_mo_co_mark[simp]
  notes fun_upd_apply[simp]
  shows
  "⦃ handshake_invL ❙∧ mark_object_invL ❙∧ tso_lock_invL
             ❙∧ mut_get_roots.mark_object_invL m
             ❙∧ mut_store_del.mark_object_invL m
             ❙∧ mut_store_ins.mark_object_invL m
           ❙∧ gc.handshake_invL ❙∧ gc.obj_fields_marked_invL
           ❙∧ gc.gc_W_empty_invL
             ❙∧ LSTP (handshake_phase_inv ❙∧ mutators_phase_inv ❙∧ valid_W_inv) ⦄
     mutator m
   ⦃ gc.gc_W_empty_invL ⦄"
proof(vcg_chainsaw gc.gc_W_empty_invL_def, vcg_name_cases)
     case (hs_noop_done s s' x)       then show ?case
      unfolding gc.handshake_invL_def
      by (metis atS_un gc.get_roots_UN_get_work_locs_def hs_type.distinct(1) hs_type.distinct(3))
next case (hs_get_roots_done0 s s' x) then show ?case
      apply (clarsimp simp: mut_m.gc_W_empty_mut_inv_def WL_def)
      apply (metis (no_types, lifting))
      done
next case (hs_get_work_done0 s s' x)  then show ?case
      apply (clarsimp simp: mut_m.gc_W_empty_mut_inv_def WL_def)
      apply (metis (no_types, lifting))
      done
qed (simp_all add: no_grey_refs_def)
end
context gc
begin
lemma mut_store_old_mark_object_invL[intro]:
  notes fun_upd_apply[simp]
  shows
  "⦃ fM_fA_invL ❙∧ handshake_invL ❙∧ sweep_loop_invL ❙∧ gc_W_empty_invL
      ❙∧ mut_m.mark_object_invL m
      ❙∧ mut_store_del.mark_object_invL m
      ❙∧ LSTP (handshake_phase_inv ❙∧ mut_m.mutator_phase_inv m) ⦄
     gc
   ⦃ mut_store_del.mark_object_invL m ⦄"
apply (vcg_chainsaw mut_m.mark_object_invL_def mut_m.mut_store_del_mark_object_invL_def2) 
  apply (metis (no_types, lifting) handshake_in_syncD mut_m.mutator_phase_inv_aux.simps(5) mut_m.no_grey_refs_not_rootD obj_at_cong white_def)+
done
lemma mut_store_ins_mark_object_invL[intro]:
  "⦃ fM_fA_invL ❙∧ handshake_invL ❙∧ sweep_loop_invL ❙∧ gc_W_empty_invL
      ❙∧ mut_m.mark_object_invL m
      ❙∧ mut_store_ins.mark_object_invL m
      ❙∧ LSTP (handshake_phase_inv ❙∧ mut_m.mutator_phase_inv m) ⦄
     gc
   ⦃ mut_store_ins.mark_object_invL m ⦄"
apply (vcg_chainsaw mut_m.mark_object_invL_def mut_m.mut_store_ins_mark_object_invL_def2) 
  apply (metis (no_types, lifting) handshake_in_syncD mut_m.mutator_phase_inv_aux.simps(5) mut_m.no_grey_refs_not_rootD obj_at_cong white_def)+
done
lemma mut_mark_object_invL[intro]:
  "⦃ fM_fA_invL ❙∧ gc_W_empty_invL ❙∧ handshake_invL ❙∧ sweep_loop_invL
       ❙∧ mut_m.handshake_invL m ❙∧ mut_m.mark_object_invL m
       ❙∧ LSTP (fM_rel_inv ❙∧ handshake_phase_inv ❙∧ mutators_phase_inv ❙∧ sys_phase_inv) ⦄
     gc
   ⦃ mut_m.mark_object_invL m ⦄"
proof(vcg_chainsaw mut_m.handshake_invL_def mut_m.mark_object_invL_def, vcg_name_cases "mutator m") 
    case (ins_barrier_locs s s') then show ?case
      apply -
      apply (drule_tac x=m in spec)
      apply (clarsimp simp: fun_upd_apply dest!: handshake_in_syncD split: obj_at_field_on_heap_splits)
       apply (metis (no_types, lifting) mut_m.no_grey_refs_not_rootD obj_at_cong white_def)
      apply (metis (no_types) marked_not_white mut_m.no_grey_refs_not_rootD whiteI)
      done
next case (del_barrier1_locs s s') then show ?case
      apply -
      apply (drule_tac x=m in spec)
      apply (clarsimp simp: fun_upd_apply dest!: handshake_in_syncD split: obj_at_field_on_heap_splits)
       apply (metis (no_types, lifting) mut_m.no_grey_refs_not_rootD obj_at_cong white_def)
      apply (metis (no_types, lifting) marked_not_white mut_m.no_grey_refs_not_rootD obj_at_cong white_def)
      done
qed blast+
end
lemma mut_m_get_roots_no_fM_write:
  "⟦ mut_m.handshake_invL m s; handshake_phase_inv s↓; fM_rel_inv s↓; tso_store_inv s↓ ⟧
     ⟹ atS (mutator m) mut_m.hs_get_roots_locs s ∧ p ≠ sys ⟶ ¬sys_mem_store_buffers p s↓ = mw_fM fl # ws"
unfolding mut_m.handshake_invL_def
apply (elim conjE)
apply (drule mut_m.handshake_phase_invD[where m=m])
apply (drule fM_rel_invD)
apply (clarsimp simp: hp_step_rel_def fM_rel_def filter_empty_conv p_not_sys)
apply (metis (full_types) hs_phase.distinct(7) list.set_intros(1) tso_store_invD(4))
done
lemma (in sys) mut_mark_object_invL[intro]:
  notes filter_empty_conv[simp]
  notes fun_upd_apply[simp]
  shows
  "⦃ mut_m.handshake_invL m ❙∧ mut_m.mark_object_invL m
     ❙∧ LSTP (fA_rel_inv ❙∧ fM_rel_inv ❙∧ handshake_phase_inv ❙∧ mutators_phase_inv ❙∧ phase_rel_inv ❙∧ valid_refs_inv ❙∧ valid_W_inv ❙∧ tso_store_inv) ⦄
     sys
   ⦃ mut_m.mark_object_invL m ⦄"
proof(vcg_chainsaw mut_m.mark_object_invL_def, vcg_name_cases "mutator m")
  case (hs_get_roots_loop_locs s s' p w ws x) then show ?case
      apply -
      apply (cases w; clarsimp split: obj_at_splits)
       apply (meson valid_W_invD(1))
      apply (simp add: atS_mono mut_m.hs_get_roots_loop_locs_subseteq_hs_get_roots_locs mut_m_get_roots_no_fM_write)
      done
next case (hs_get_roots_loop_done s s' p w ws y) then show ?case
      apply -
      apply (cases w; clarsimp simp: p_not_sys valid_W_invD split: obj_at_splits)
      apply (rename_tac fl obj)
      apply (drule_tac fl=fl and p=p and ws=ws in mut_m_get_roots_no_fM_write; clarsimp)
      apply (drule mp, erule atS_simps, loc_mem)
      apply blast
      done
next case (hs_get_roots_done s s' p w ws x) then show ?case
      apply -
      apply (cases w; clarsimp simp: p_not_sys valid_W_invD split: obj_at_splits)
       apply blast
      apply (rename_tac fl)
      apply (drule_tac fl=fl and p=p and ws=ws in mut_m_get_roots_no_fM_write; clarsimp)
      apply (drule mp, erule atS_simps, loc_mem)
      apply blast
      done
next case (mo_ptest_locs s s' p ws ph') then show ?case by (clarsimp simp: p_not_sys; elim disjE; clarsimp simp: phase_rel_def handshake_in_syncD dest!: phase_rel_invD)
next case (store_ins s s' p w ws y) then show ?case
      apply -
      apply (cases w; clarsimp simp: p_not_sys valid_W_invD split: obj_at_splits)
        apply (metis (no_types, lifting) hs_phase.distinct(3, 5) mut_m.mut_ghost_handshake_phase_idle mut_m_not_idle_no_fM_writeD store_ins(9))
       using valid_refs_invD(9) apply fastforce
      apply (elim disjE; clarsimp simp: phase_rel_def handshake_in_syncD dest!: phase_rel_invD)
      done
next case (del_barrier1_locs s s' p w ws) then show ?case
      proof(cases w)
       case (mw_Mutate r f opt_r') with del_barrier1_locs show ?thesis
apply (clarsimp simp: p_not_sys; elim disjE; clarsimp)
apply (intro conjI impI; clarsimp simp: obj_at_field_on_heap_imp_valid_ref split: option.splits)
 apply (intro conjI impI; clarsimp)
  apply (smt (z3) reachableI(1) valid_refs_invD(8))
 apply (metis (no_types, lifting) marked_insertionD mut_m.mutator_phase_inv_aux.simps(4) mut_m.mutator_phase_inv_aux.simps(5) obj_at_cong reachableI(1) valid_refs_invD(8))
apply (rename_tac ma x2)
apply (frule_tac m=m in mut_m.handshake_phase_invD)
apply (frule_tac m=ma in mut_m.handshake_phase_invD)
apply (frule spec[where x=m])
apply (drule_tac x=ma in spec)
apply (clarsimp simp: hp_step_rel_def)
apply (elim disjE; clarsimp simp: marked_insertionD mut_m.mut_ghost_handshake_phase_idle)
done
      next case (mw_fM fl) with del_barrier1_locs mut_m_not_idle_no_fM_writeD show ?thesis by fastforce
      next case (mw_Phase ph) with del_barrier1_locs show ?thesis by (clarsimp simp: p_not_sys; elim disjE; clarsimp simp: phase_rel_def handshake_in_syncD dest!: phase_rel_invD)
      qed (fastforce simp: valid_W_invD split: obj_at_field_on_heap_splits obj_at_splits)+
next case (ins_barrier_locs s s' p w ws) then show ?case
      proof(cases w)
       case (mw_Mutate r f opt_r') with ins_barrier_locs show ?thesis
apply (clarsimp simp: p_not_sys; elim disjE; clarsimp)
apply (intro conjI impI; clarsimp simp: obj_at_field_on_heap_imp_valid_ref split: option.splits)
 apply (intro conjI impI; clarsimp)
  apply (smt (z3) reachableI(1) valid_refs_invD(8))
 apply (metis (no_types, lifting) marked_insertionD mut_m.mutator_phase_inv_aux.simps(4) mut_m.mutator_phase_inv_aux.simps(5) obj_at_cong reachableI(1) valid_refs_invD(8))
apply (rename_tac ma x2)
apply (frule_tac m=m in mut_m.handshake_phase_invD)
apply (frule_tac m=ma in mut_m.handshake_phase_invD)
apply (frule spec[where x=m])
apply (drule_tac x=ma in spec)
apply (clarsimp simp: hp_step_rel_def)
apply (elim disjE; clarsimp simp: marked_insertionD mut_m.mut_ghost_handshake_phase_idle)
done
      next case (mw_fM fl) with ins_barrier_locs mut_m_not_idle_no_fM_writeD show ?thesis by fastforce
      next case (mw_Phase ph) with ins_barrier_locs show ?thesis by (clarsimp simp: p_not_sys; elim disjE; clarsimp simp: phase_rel_def handshake_in_syncD dest!: phase_rel_invD)
      qed (fastforce simp: valid_W_invD split: obj_at_field_on_heap_splits obj_at_splits)+
next case (lop_store_ins s s' p w ws y) then show ?case
      apply -
      apply (cases w; clarsimp simp: valid_W_invD(1) split: obj_at_splits)
        apply (metis (no_types, opaque_lifting) hs_phase.distinct(5,7) mut_m_not_idle_no_fM_write)
       apply (clarsimp simp: p_not_sys; elim disjE; clarsimp simp: phase_rel_def handshake_in_syncD dest!: phase_rel_invD; fail)+
      done
qed
end