Skip to content

Commit

Permalink
bigarray: fix ocaml#12491 (memory accounting of shared bigarray data)
Browse files Browse the repository at this point in the history
  • Loading branch information
gasche committed Aug 24, 2023
1 parent 7a507ce commit ecf2613
Showing 1 changed file with 28 additions and 15 deletions.
43 changes: 28 additions & 15 deletions runtime/bigarray.c
Expand Up @@ -229,48 +229,60 @@ static int ba_compute_size(int flags, int num_dims, intnat * dim, uintnat *num_e
size));
}

static caml_ba_alloc_gen(int flags, int num_dims, void * data, intnat * dim, int owns_data)
{

}
/* [caml_ba_alloc_gen] will allocate a new bigarray object in the heap.
If [data] is NULL, the memory for the contents is also allocated.
(with [malloc]) by [caml_ba_alloc_gen].
If [data] is NULL or [owns_data] is non-zero, we consider that [data] is now
owned by the OCaml heap, and adjust GC pacing accordingly --
the external memory considered is the size of the bigarray.
/* [caml_ba_alloc] will allocate a new bigarray object in the heap.
If [data] is NULL, the memory for the contents is also allocated
(with [malloc]) by [caml_ba_alloc].
[data] cannot point into the OCaml heap.
[dim] may point into an object in the OCaml heap.
*/
CAMLexport value
caml_ba_alloc(int flags, int num_dims, void * data, intnat * dim)
static value caml_ba_alloc_gen(int flags, int num_dims, void * data, intnat * dim, int owns_data)
{
uintnat asize, num_elts, size;
int i, is_managed;
value res;
struct caml_ba_array * b;
intnat dimcopy[CAML_BA_MAX_NUM_DIMS];

CAMLassert(num_dims >= 0 && num_dims <= CAML_BA_MAX_NUM_DIMS);
CAMLassert((flags & CAML_BA_KIND_MASK) < CAML_BA_FIRST_UNIMPLEMENTED_KIND);
for (i = 0; i < num_dims; i++) dimcopy[i] = dim[i];
for (int i = 0; i < num_dims; i++) dimcopy[i] = dim[i];
if (!ba_compute_size(flags, num_dims, dimcopy, &num_elts, &size))
caml_raise_out_of_memory();
if (data == NULL) {
data = malloc(size);
if (data == NULL && size != 0) caml_raise_out_of_memory();
owns_data = 1;
flags |= CAML_BA_MANAGED;
}
asize = SIZEOF_BA_ARRAY + num_dims * sizeof(intnat);
is_managed = ((flags & CAML_BA_MANAGED_MASK) == CAML_BA_MANAGED);
res = caml_alloc_custom_mem(&caml_ba_ops, asize, is_managed ? size : 0);
res = caml_alloc_custom_mem(&caml_ba_ops, asize, owns_data ? size : 0);
b = Caml_ba_array_val(res);
b->data = data;
b->num_dims = num_dims;
b->flags = flags;
b->proxy = NULL;
for (i = 0; i < num_dims; i++) b->dim[i] = dimcopy[i];
for (int i = 0; i < num_dims; i++) b->dim[i] = dimcopy[i];
return res;
}

/* [caml_ba_alloc] will allocate a new bigarray object in the heap.
If [data] is NULL, the memory for the contents is also allocated.
(with [malloc]) by [caml_ba_alloc].
[data] cannot point into the OCaml heap.
[dim] may point into an object in the OCaml heap.
*/
CAMLexport value
caml_ba_alloc(int flags, int num_dims, void * data, intnat * dim)
{
int is_managed = ((flags & CAML_BA_MANAGED_MASK) == CAML_BA_MANAGED);
return caml_ba_alloc_gen(flags, num_dims, data, dim, is_managed);
}

/* Same as caml_ba_alloc, but dimensions are passed as a list of
arguments */

Expand Down Expand Up @@ -1106,7 +1118,8 @@ static value caml_ba_inherit(value vb, int num_dims, intnat * dim)
CAMLparam1 (vb);
CAMLlocal1 (res);
#define b (Caml_ba_array_val(vb))
res = caml_ba_alloc(b->flags, num_dims, b->data, dim);
int owns_data = 0;
res = caml_ba_alloc_gen(b->flags, num_dims, b->data, dim, owns_data);
/* Copy the finalization function from the original array (PR#8568) */
Custom_ops_val(res) = Custom_ops_val(vb);
/* Create or update proxy in case of managed bigarray */
Expand Down

0 comments on commit ecf2613

Please sign in to comment.