Add type Obj.raw_data and functions Obj.raw_field, Obj.set_raw_field
Some OCaml objects contain data that cannot be safely represented as an OCaml value (type Obj.t). For example, in no-naked-pointers mode, this is the case for code pointers inside closures, and for the "custom operations" pointers inside custom blocks. This PR introduces a type Obj.raw_data (an alias for nativeint) to encapsulate this data, and functions Obj.raw_field / Obj.set_raw_field to read and write the "raw" contents of fields of blocks. Note: just like it is wrong to access code pointers and custom operations using Obj.field / Obj.set_field, it is wrong to access regular fields possibly containing pointers into the OCaml heap using Obj.raw_field / Obj.set_raw_field. The OCaml heap block can be reclaimed or moved after its address was captured by Obj.raw_field. Symmetrically, Obj.set_raw_field on a regular field bypasses the write barrier of the GC.master
parent
d8f3273292
commit
ec33006c0a
|
@ -73,6 +73,18 @@ CAMLprim value caml_obj_set_tag (value arg, value new_tag)
|
|||
return Val_unit;
|
||||
}
|
||||
|
||||
CAMLprim value caml_obj_raw_field(value arg, value pos)
|
||||
{
|
||||
/* Represent field contents as a native integer */
|
||||
return caml_copy_nativeint((intnat) Field(arg, Long_val(pos)));
|
||||
}
|
||||
|
||||
CAMLprim value caml_obj_set_raw_field(value arg, value pos, value bits)
|
||||
{
|
||||
Field(arg, Long_val(pos)) = (value) Nativeint_val(bits);
|
||||
return Val_unit;
|
||||
}
|
||||
|
||||
CAMLprim value caml_obj_make_forward (value blk, value fwd)
|
||||
{
|
||||
caml_modify(&Field(blk, 0), fwd);
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
|
||||
type t
|
||||
|
||||
type raw_data = nativeint
|
||||
|
||||
external repr : 'a -> t = "%identity"
|
||||
external obj : t -> 'a = "%identity"
|
||||
external magic : 'a -> 'b = "%identity"
|
||||
|
@ -34,6 +36,10 @@ external floatarray_set :
|
|||
let [@inline always] double_field x i = floatarray_get (obj x : floatarray) i
|
||||
let [@inline always] set_double_field x i v =
|
||||
floatarray_set (obj x : floatarray) i v
|
||||
external raw_field : t -> int -> raw_data = "caml_obj_raw_field"
|
||||
external set_raw_field : t -> int -> raw_data -> unit
|
||||
= "caml_obj_set_raw_field"
|
||||
|
||||
external new_block : int -> int -> t = "caml_obj_block"
|
||||
external dup : t -> t = "caml_obj_dup"
|
||||
external truncate : t -> int -> unit = "caml_obj_truncate"
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
|
||||
type t
|
||||
|
||||
type raw_data = nativeint (* @since 4.12 *)
|
||||
|
||||
external repr : 'a -> t = "%identity"
|
||||
external obj : t -> 'a = "%identity"
|
||||
external magic : 'a -> 'b = "%identity"
|
||||
|
@ -60,6 +62,13 @@ external set_tag : t -> int -> unit = "caml_obj_set_tag"
|
|||
val [@inline always] double_field : t -> int -> float (* @since 3.11.2 *)
|
||||
val [@inline always] set_double_field : t -> int -> float -> unit
|
||||
(* @since 3.11.2 *)
|
||||
|
||||
external raw_field : t -> int -> raw_data = "caml_obj_raw_field"
|
||||
(* @since 4.12 *)
|
||||
external set_raw_field : t -> int -> raw_data -> unit
|
||||
= "caml_obj_set_raw_field"
|
||||
(* @since 4.12 *)
|
||||
|
||||
external new_block : int -> int -> t = "caml_obj_block"
|
||||
external dup : t -> t = "caml_obj_dup"
|
||||
external truncate : t -> int -> unit = "caml_obj_truncate"
|
||||
|
|
Loading…
Reference in New Issue