Source file obj.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
# 2 "obj.ml"
open! Stdlib
[@@@ocaml.flambda_o3]
type t
type raw_data = nativeint
external repr : 'a -> t @@ portable = "%obj_magic"
external repr_contended : 'a @ contended -> t @ contended @@ portable = "%obj_magic"
external obj : t -> 'a @@ portable = "%obj_magic"
external obj_contended : t @ contended -> 'a @ contended @@ portable = "%obj_magic"
external magic : 'a -> 'b @@ portable = "%obj_magic"
external magic_portable : ('a[@local_opt]) -> ('a[@local_opt]) @ portable @@ portable = "%identity"
external magic_uncontended : ('a[@local_opt]) @ contended -> ('a[@local_opt]) @@ portable = "%identity"
external magic_unique : ('a[@local_opt]) -> ('a[@local_opt]) @ unique @@ portable = "%identity"
external magic_many : ('a[@local_opt]) @ once -> ('a[@local_opt]) @@ portable = "%identity"
external magic_at_unique : ('a[@local_opt]) @ unique -> ('b[@local_opt]) @ unique @@ portable= "%identity"
external is_int : t @ contended -> bool @@ portable = "%obj_is_int"
let [@inline always] is_block a = not (is_int a)
external tag : t @ contended -> int @@ portable = "caml_obj_tag" [@@noalloc]
external size : t @ contended -> int @@ portable = "%obj_size"
external opaque_identity_contended : 'a @ contended -> 'a @ contended @@ portable = "%opaque"
let [@inline always] size t = size (opaque_identity_contended t)
external reachable_words : t -> int @@ portable = "caml_obj_reachable_words"
external uniquely_reachable_words : t array -> int array * int @@ portable = "caml_obj_uniquely_reachable_words"
external field : t -> int -> t @@ portable = "%obj_field"
let [@inline always] field t index = field (Sys.opaque_identity t) index
external field_contended : t @ contended -> int -> t @ contended @@ portable = "%obj_field"
let [@inline always] field_contended t index = field_contended (opaque_identity_contended t) index
external set_field : t -> int -> t -> unit @@ portable = "%obj_set_field"
let [@inline always] set_field t index new_value =
set_field (Sys.opaque_identity t) index new_value
external floatarray_get : floatarray -> int -> float @@ portable = "caml_floatarray_get"
external floatarray_set :
floatarray -> int -> float -> unit @@ portable = "caml_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 @@ portable = "caml_obj_raw_field"
external set_raw_field : t -> int -> raw_data -> unit @@ portable
= "caml_obj_set_raw_field"
external new_block : int -> int -> t @@ portable = "caml_obj_block"
external dup : t -> t @@ portable = "%obj_dup"
external add_offset : t -> Int32.t -> t @@ portable = "caml_obj_add_offset"
external with_tag : int -> t -> t @@ portable = "caml_obj_with_tag"
let first_non_constant_constructor_tag = 0
let last_non_constant_constructor_tag = 243
let forcing_tag = 244
let cont_tag = 245
let lazy_tag = 246
let closure_tag = 247
let object_tag = 248
let infix_tag = 249
let forward_tag = 250
let no_scan_tag = 251
let abstract_tag = 251
let string_tag = 252
let double_tag = 253
let double_array_tag = 254
let custom_tag = 255
let int_tag = 1000
let out_of_heap_tag = 1001
let unaligned_tag = 1002
let[@warning "-32"] null_tag = 1010
module Extension_constructor =
struct
type t = extension_constructor
let of_val x =
let x = repr_contended x in
let slot =
if (is_block x) && (tag x) <> object_tag && (size x) >= 1 then field_contended x 0
else x
in
let name =
if (is_block slot) && (tag slot) = object_tag then field_contended slot 0
else invalid_arg "Obj.extension_constructor"
in
if (tag name) = string_tag then (obj_contended slot : t)
else invalid_arg "Obj.extension_constructor"
let [@inline always] name (slot : t) =
(obj (field (repr slot) 0) : string)
let [@inline always] id (slot : t) =
(obj (field (repr slot) 1) : int)
end
module Ephemeron = struct
type obj_t = t
type t (** ephemeron *)
(** To change in sync with weak.h *)
let additional_values = 2
let max_ephe_length = Sys.max_array_length - additional_values
external create : int -> t @@ portable = "caml_ephe_create"
let create l =
if not (0 <= l && l <= max_ephe_length) then
invalid_arg "Obj.Ephemeron.create";
create l
let length x = size(repr x) - additional_values
let raise_if_invalid_offset e o msg =
if not (0 <= o && o < length e) then
invalid_arg msg
external get_key: t -> int -> obj_t option @@ portable = "caml_ephe_get_key"
let get_key e o =
raise_if_invalid_offset e o "Obj.Ephemeron.get_key";
get_key e o
external get_key_copy: t -> int -> obj_t option @@ portable = "caml_ephe_get_key_copy"
let get_key_copy e o =
raise_if_invalid_offset e o "Obj.Ephemeron.get_key_copy";
get_key_copy e o
external set_key: t -> int -> obj_t -> unit @@ portable = "caml_ephe_set_key"
let set_key e o x =
raise_if_invalid_offset e o "Obj.Ephemeron.set_key";
set_key e o x
external unset_key: t -> int -> unit @@ portable = "caml_ephe_unset_key"
let unset_key e o =
raise_if_invalid_offset e o "Obj.Ephemeron.unset_key";
unset_key e o
external check_key: t -> int -> bool @@ portable = "caml_ephe_check_key"
let check_key e o =
raise_if_invalid_offset e o "Obj.Ephemeron.check_key";
check_key e o
external blit_key : t -> int -> t -> int -> int -> unit @@ portable
= "caml_ephe_blit_key"
let blit_key e1 o1 e2 o2 l =
if l < 0 || o1 < 0 || o1 > length e1 - l
|| o2 < 0 || o2 > length e2 - l
then invalid_arg "Obj.Ephemeron.blit_key"
else if l <> 0 then blit_key e1 o1 e2 o2 l
external get_data: t -> obj_t option @@ portable = "caml_ephe_get_data"
external get_data_copy: t -> obj_t option @@ portable = "caml_ephe_get_data_copy"
external set_data: t -> obj_t -> unit @@ portable = "caml_ephe_set_data"
external unset_data: t -> unit @@ portable = "caml_ephe_unset_data"
external check_data: t -> bool @@ portable = "caml_ephe_check_data"
external blit_data : t -> t -> unit @@ portable = "caml_ephe_blit_data"
end
module Uniform_or_mixed = struct
type obj_t = t
type t = int
external of_block : obj_t -> t @@ portable = "caml_succ_scannable_prefix_len" [@@noalloc]
type repr =
| Uniform
| Mixed of { scannable_prefix_len : int }
let repr = function
| 0 -> Uniform
| n -> Mixed { scannable_prefix_len = n - 1 }
let is_uniform t = t = 0
let is_mixed t = not (is_uniform t)
let mixed_scannable_prefix_len_exn t =
if is_uniform t
then invalid_arg "Uniform_or_mixed.mixed_scannable_prefix_len_exn";
t - 1
end