diff options
Diffstat (limited to 'byterun/weak.c')
-rw-r--r-- | byterun/weak.c | 34 |
1 files changed, 31 insertions, 3 deletions
diff --git a/byterun/weak.c b/byterun/weak.c index a9d67b56c..c9657fb33 100644 --- a/byterun/weak.c +++ b/byterun/weak.c @@ -27,7 +27,7 @@ value weak_create (value len) /* ML */ value res; size = Long_val (len) + 1; - if (size > Max_wosize) invalid_argument ("Weak.create"); + if (size <= 0 || size > Max_wosize) invalid_argument ("Weak.create"); res = alloc_shr (size, Abstract_tag); for (i = 1; i < size; i++) Field (res, i) = 0; Field (res, 0) = weak_list_head; @@ -44,7 +44,7 @@ value weak_set (value ar, value n, value el) /* ML */ Assert (Is_in_heap (ar)); if (offset < 1 || offset >= Wosize_val (ar)) invalid_argument ("Weak.set"); Field (ar, offset) = 0; - if (el != None_val){ Assert (Wosize_val (el) == 1); + if (el != None_val){ Assert (Wosize_val (el) == 1); Modify (&Field (ar, offset), Field (el, 0)); } return Val_unit; @@ -74,10 +74,38 @@ value weak_get (value ar, value n) /* ML */ #undef Setup_for_gc #undef Restore_after_gc +value weak_get_copy (value ar, value n) /* ML */ +{ + CAMLparam2 (ar, n); + mlsize_t offset = Long_val (n) + 1; + CAMLlocal2 (res, elt); + value v; /* Caution: this is NOT a local root. */ + Assert (Is_in_heap (ar)); + if (offset < 1 || offset >= Wosize_val (ar)) invalid_argument ("Weak.get"); + + v = Field (ar, offset); + if (v == 0) CAMLreturn (None_val); + elt = alloc (Wosize_val (v), Tag_val (v)); /* The GC may erase or move v. */ + v = Field (ar, offset); + if (v == 0) CAMLreturn (None_val); + if (Tag_val (v) < No_scan_tag){ + mlsize_t i; + for (i = 0; i < Wosize_val (v); i++){ + Store_field (elt, i, Field (v, i)); + } + }else{ + memmove (Bp_val (elt), Bp_val (v), Bosize_val (v)); + } + res = alloc_small (1, Some_tag); + Field (res, 0) = elt; + + CAMLreturn (res); +} + value weak_check (value ar, value n) /* ML */ { mlsize_t offset = Long_val (n) + 1; - Assert (Is_in_heap (ar)); + Assert (Is_in_heap (ar)); if (offset < 1 || offset >= Wosize_val (ar)) invalid_argument ("Weak.get"); return Val_bool (Field (ar, offset) != 0); } |