On 09/03/2012 01:13, Johan Tibell wrote:
Hi,

I just ran across some code that calls unsafeThawArray#, writeArray#,
and unsafeFreezeArray#, in that order. How unsafe is that?

  * Is it unsafe in the sense that if someone has a reference to the
original Array# they will see the value of that pure array change?

Yes.

  * Is it unsafe in the sense things will crash and burn?

No. (at least, we would consider it a bug if a crash was the result)

I looked at the implementation of unsafeFreezeArray#, which is

     emitPrimOp [res] UnsafeFreezeArrayOp [arg] _
        = stmtsC [ setInfo arg (CmmLit (CmmLabel mkMAP_FROZEN_infoLabel)),
            CmmAssign (CmmLocal res) arg ]

but I couldn't find any implementation of unsafeThawArray#. Is it a
no-op? It seems to me that if unsafeFreezeArray# changes the head of
the array heap object so should unsafeThawArray#.

You'll find the implementation of unsafeThawArray# in rts/PrimOps.cmm, reproduced here for your enjoyment:

stg_unsafeThawArrayzh
{
  // SUBTLETY TO DO WITH THE OLD GEN MUTABLE LIST
  //
  // A MUT_ARR_PTRS lives on the mutable list, but a MUT_ARR_PTRS_FROZEN
  // normally doesn't.  However, when we freeze a MUT_ARR_PTRS, we leave
  // it on the mutable list for the GC to remove (removing something from
  // the mutable list is not easy).
  //
// So that we can tell whether a MUT_ARR_PTRS_FROZEN is on the mutable list,
  // when we freeze it we set the info ptr to be MUT_ARR_PTRS_FROZEN0
  // to indicate that it is still on the mutable list.
  //
  // So, when we thaw a MUT_ARR_PTRS_FROZEN, we must cope with two cases:
  // either it is on a mut_list, or it isn't.  We adopt the convention that
  // the closure type is MUT_ARR_PTRS_FROZEN0 if it is on the mutable list,
  // and MUT_ARR_PTRS_FROZEN otherwise.  In fact it wouldn't matter if
// we put it on the mutable list more than once, but it would get scavenged
  // multiple times during GC, which would be unnecessarily slow.
  //
  if (StgHeader_info(R1) != stg_MUT_ARR_PTRS_FROZEN0_info) {
        SET_INFO(R1,stg_MUT_ARR_PTRS_DIRTY_info);
        recordMutable(R1, R1);
        // must be done after SET_INFO, because it ASSERTs closure_MUTABLE()
        RET_P(R1);
  } else {
        SET_INFO(R1,stg_MUT_ARR_PTRS_DIRTY_info);
        RET_P(R1);
  }
}


Cheers,
        Simon

_______________________________________________
Glasgow-haskell-users mailing list
Glasgow-haskell-users@haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users

Reply via email to