Skip to content

Commit

Permalink
flambda-backend: Fix mixed block macros so users don't get wrong plat…
Browse files Browse the repository at this point in the history
…form's macros (#2494)
  • Loading branch information
ncik-roberts authored Apr 26, 2024
1 parent ba63be3 commit 2f20f89
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 44 deletions.
4 changes: 2 additions & 2 deletions runtime/alloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ CAMLexport value caml_alloc_mixed_shr_check_gc (mlsize_t wosize, tag_t tag,
mlsize_t scannable_prefix_len)
{
reserved_t reserved =
Reserved_mixed_block_scannable_wosize(scannable_prefix_len);
Reserved_mixed_block_scannable_wosize_native(scannable_prefix_len);
return caml_alloc_shr_reserved_check_gc(wosize, tag, reserved);
}
#endif
Expand Down Expand Up @@ -371,7 +371,7 @@ CAMLprim value caml_alloc_dummy_mixed (value size, value scannable_size)
*/
CAML_STATIC_ASSERT(Double_wosize == 1);
reserved_t reserved =
Reserved_mixed_block_scannable_wosize(scannable_wosize);
Reserved_mixed_block_scannable_wosize_native(scannable_wosize);
#else
/* [scannable_size] can't be used meaningfully in bytecode */
(void)scannable_size;
Expand Down
67 changes: 47 additions & 20 deletions runtime/caml/mlvalues.h
Original file line number Diff line number Diff line change
Expand Up @@ -150,23 +150,14 @@ mixed blocks. In the upstream compiler, R is set with the

#endif

/* Header bits reserved for mixed blocks */

#define Is_mixed_block_reserved(res) (((reserved_t)(res)) > 0)
/* Header bits reserved for mixed blocks */

#ifdef NATIVE_CODE
#define Scannable_wosize_val(val) (Scannable_wosize_hd (Hd_val (val)))
#define Reserved_mixed_block_scannable_wosize(sz) (((mlsize_t)(sz)) + 1)
#define Mixed_block_scannable_wosize_reserved_native(res) (((reserved_t)(res)) - 1)
#define Is_mixed_block_reserved(res) (((reserved_t)(res)) > 0)

Caml_inline mlsize_t Scannable_wosize_reserved(reserved_t res, mlsize_t sz) {
return
Is_mixed_block_reserved(res)
? Mixed_block_scannable_wosize_reserved_native(res)
: sz;
}
/* Native code versions of mixed block macros.
/* The scannable size of a block is how many fields are values as opposed
The scannable size of a block is how many fields are values as opposed
to flat floats/ints/etc. This is different than the (normal) size of a
block for mixed blocks.
Expand All @@ -182,25 +173,61 @@ Caml_inline mlsize_t Scannable_wosize_reserved(reserved_t res, mlsize_t sz) {
Otherwise, the traversal could attempt to recursively descend into
a flat field, which could segfault (or worse).
*/
Caml_inline mlsize_t Scannable_wosize_hd(header_t hd) {

#define Scannable_wosize_val_native(val) (Scannable_wosize_hd (Hd_val (val)))
#define Reserved_mixed_block_scannable_wosize_native(sz) (((mlsize_t)(sz)) + 1)
#define Mixed_block_scannable_wosize_reserved_native(res) \
(((reserved_t)(res)) - 1)

Caml_inline mlsize_t Scannable_wosize_reserved_native(reserved_t res,
mlsize_t sz) {
return
Is_mixed_block_reserved(res)
? Mixed_block_scannable_wosize_reserved_native(res)
: sz;
}

Caml_inline mlsize_t Scannable_wosize_hd_native(header_t hd) {
reserved_t res = Reserved_hd(hd);
return
Is_mixed_block_reserved(res)
? Mixed_block_scannable_wosize_reserved_native(res)
: Wosize_hd(hd);
}

#else
#define Scannable_wosize_hd(val) (Wosize_hd (val))
#define Scannable_wosize_val(val) (Wosize_hd (Hd_val (val)))
#define Faux_mixed_block_sentinel ((reserved_t) 0xff)
/* Bytecode versions of mixed block macros.
// In bytecode always use the size of the block as the scannable size
Caml_inline mlsize_t Scannable_wosize_reserved(reserved_t res, mlsize_t size) {
Bytecode always uses the size of the block as the scannable size. That's
because bytecode doesn't represent mixed records as mixed blocks. They're
"faux mixed blocks", which are regular blocks with a sentinel value set
in the header bits.
*/

#define Scannable_wosize_hd_byte(hd) (Wosize_hd (hd))
#define Scannable_wosize_val_byte(val) (Wosize_hd (Hd_val (val)))
Caml_inline mlsize_t Scannable_wosize_reserved_byte(reserved_t res,
mlsize_t size) {
(void)res;
return size;
}

/* Users should specify whether they want to use the bytecode or native
versions of these macros. Internally to the runtime, the NATIVE_CODE
macro lets us make that determination, so we can define suffixless
versions of the mixed block macros.
*/
#ifdef CAML_INTERNALS
#ifdef NATIVE_CODE
#define Scannable_wosize_reserved(r, s) Scannable_wosize_reserved_native(r, s)
#define Scannable_wosize_hd(hd) Scannable_wosize_hd_native(hd)
#define Scannable_wosize_val(val) Scannable_wosize_val_native(val)
#else
#define Faux_mixed_block_sentinel ((reserved_t) 0xff)
#define Scannable_wosize_reserved(r, s) Scannable_wosize_reserved_byte(r, s)
#define Scannable_wosize_hd(hd) Scannable_wosize_hd_byte(hd)
#define Scannable_wosize_val(val) Scannable_wosize_val_byte(val)
#endif // NATIVE_CODE
#endif // CAML_INTERNALS

/* Color values are pre-shifted */

Expand Down
4 changes: 2 additions & 2 deletions runtime4/alloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ CAMLexport value caml_alloc (mlsize_t wosize, tag_t tag) {
CAMLexport value caml_alloc_mixed (mlsize_t wosize, tag_t tag,
mlsize_t scannable_prefix) {
reserved_t reserved =
Reserved_mixed_block_scannable_wosize(scannable_prefix);
Reserved_mixed_block_scannable_wosize_native(scannable_prefix);
return caml_alloc_with_reserved (wosize, tag, reserved);
}
#endif // NATIVE_CODE
Expand Down Expand Up @@ -263,7 +263,7 @@ CAMLprim value caml_alloc_dummy_mixed (value size, value scannable_size)
*/
CAML_STATIC_ASSERT(Double_wosize == 1);
reserved_t reserved =
Reserved_mixed_block_scannable_wosize(scannable_wosize);
Reserved_mixed_block_scannable_wosize_native(scannable_wosize);
#else
/* [scannable_size] can't be used meaningfully in bytecode */
(void)scannable_size;
Expand Down
66 changes: 46 additions & 20 deletions runtime4/caml/mlvalues.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,21 +145,11 @@ originally built for Spacetime profiling, hence the odd name.
#define Reserved_hd(hd) ((reserved_t)(Profinfo_hd(hd)))
#define Reserved_val(val) ((reserved_t)(Profinfo_val(val)))

#define Is_mixed_block_reserved(res) (((reserved_t)(res)) > 0)
#define Is_mixed_block_reserved(res) (((reserved_t)(res)) > 0)

#ifdef NATIVE_CODE
#define Scannable_wosize_val(val) (Scannable_wosize_hd (Hd_val (val)))
#define Reserved_mixed_block_scannable_wosize(sz) (((mlsize_t)(sz)) + 1)
#define Mixed_block_scannable_wosize_reserved_native(res) (((reserved_t)(res)) - 1)

Caml_inline mlsize_t Scannable_wosize_reserved(reserved_t res, mlsize_t sz) {
return
Is_mixed_block_reserved(res)
? Mixed_block_scannable_wosize_reserved_native(res)
: sz;
}
/* Native code versions of mixed block macros.
/* The scannable size of a block is how many fields are values as opposed
The scannable size of a block is how many fields are values as opposed
to flat floats/ints/etc. This is different than the (normal) size of a
block for mixed blocks.
Expand All @@ -175,25 +165,61 @@ Caml_inline mlsize_t Scannable_wosize_reserved(reserved_t res, mlsize_t sz) {
Otherwise, the traversal could attempt to recursively descend into
a flat field, which could segfault (or worse).
*/
Caml_inline mlsize_t Scannable_wosize_hd(header_t hd) {

#define Scannable_wosize_val_native(val) (Scannable_wosize_hd (Hd_val (val)))
#define Reserved_mixed_block_scannable_wosize_native(sz) (((mlsize_t)(sz)) + 1)
#define Mixed_block_scannable_wosize_reserved_native(res) \
(((reserved_t)(res)) - 1)

Caml_inline mlsize_t Scannable_wosize_reserved_native(reserved_t res,
mlsize_t sz) {
return
Is_mixed_block_reserved(res)
? Mixed_block_scannable_wosize_reserved_native(res)
: sz;
}

Caml_inline mlsize_t Scannable_wosize_hd_native(header_t hd) {
reserved_t res = Reserved_hd(hd);
return
Is_mixed_block_reserved(res)
? Mixed_block_scannable_wosize_reserved_native(res)
: Wosize_hd(hd);
}

#else
#define Scannable_wosize_hd(val) (Wosize_hd (val))
#define Scannable_wosize_val(val) (Wosize_hd (Hd_val (val)))
#define Faux_mixed_block_sentinel ((reserved_t) 0xff)
/* Bytecode versions of mixed block macros.
// In bytecode always use the size of the block as the scannable size
Caml_inline mlsize_t Scannable_wosize_reserved(reserved_t res, mlsize_t size) {
Bytecode always uses the size of the block as the scannable size. That's
because bytecode doesn't represent mixed records as mixed blocks. They're
"faux mixed blocks", which are regular blocks with a sentinel value set
in the header bits.
*/

#define Scannable_wosize_hd_byte(hd) (Wosize_hd (hd))
#define Scannable_wosize_val_byte(val) (Wosize_hd (Hd_val (val)))
Caml_inline mlsize_t Scannable_wosize_reserved_byte(reserved_t res,
mlsize_t size) {
(void)res;
return size;
}

/* Users should specify whether they want to use the bytecode or native
versions of these macros. Internally to the runtime, the NATIVE_CODE
macro lets us make that determination, so we can define suffixless
versions of the mixed block macros.
*/
#ifdef CAML_INTERNALS
#ifdef NATIVE_CODE
#define Scannable_wosize_reserved(r, s) Scannable_wosize_reserved_native(r, s)
#define Scannable_wosize_hd(hd) Scannable_wosize_hd_native(hd)
#define Scannable_wosize_val(val) Scannable_wosize_val_native(val)
#else
#define Faux_mixed_block_sentinel ((reserved_t) 0xff)
#define Scannable_wosize_reserved(r, s) Scannable_wosize_reserved_byte(r, s)
#define Scannable_wosize_hd(hd) Scannable_wosize_hd_byte(hd)
#define Scannable_wosize_val(val) Scannable_wosize_val_byte(val)
#endif // NATIVE_CODE
#endif // CAML_INTERNALS

#define Hd_val(val) (((header_t *) (val)) [-1]) /* Also an l-value. */
#define Hd_op(op) (Hd_val (op)) /* Also an l-value. */
Expand Down

0 comments on commit 2f20f89

Please sign in to comment.