123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241# 2 "obj.ml"(**************************************************************************)(* *)(* OCaml *)(* *)(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *)(* *)(* Copyright 1996 Institut National de Recherche en Informatique et *)(* en Automatique. *)(* *)(* All rights reserved. This file is distributed under the terms of *)(* the GNU Lesser General Public License version 2.1, with the *)(* special exception on linking described in the file LICENSE. *)(* *)(**************************************************************************)open!Stdlib[@@@ocaml.flambda_o3](* Operations on internal representations of values *)typettyperaw_data=nativeintexternalrepr:'a->t@@portable="%obj_magic"externalrepr_contended:'a@contended->t@contended@@portable="%obj_magic"externalobj:t->'a@@portable="%obj_magic"externalobj_contended:t@contended->'a@contended@@portable="%obj_magic"externalmagic:'a->'b@@portable="%obj_magic"externalmagic_portable:('a[@local_opt])->('a[@local_opt])@portable@@portable="%identity"externalmagic_uncontended:('a[@local_opt])@contended->('a[@local_opt])@@portable="%identity"externalmagic_unique:('a[@local_opt])->('a[@local_opt])@unique@@portable="%identity"externalmagic_many:('a[@local_opt])@once->('a[@local_opt])@@portable="%identity"externalmagic_at_unique:('a[@local_opt])@unique->('b[@local_opt])@unique@@portable="%identity"externalis_int:t@contended->bool@@portable="%obj_is_int"let[@inlinealways]is_blocka=not(is_inta)externaltag:t@contended->int@@portable="caml_obj_tag"[@@noalloc](* For Flambda 2 there is a strict distinction between arrays and other
blocks. %obj_size and %obj_field may only be used on blocks. As such
they are protected here using [Sys.opaque_identity], since this
restriction is likely not respected by callees of this module. *)externalsize:t@contended->int@@portable="%obj_size"externalopaque_identity_contended:'a@contended->'a@contended@@portable="%opaque"let[@inlinealways]sizet=size(opaque_identity_contendedt)externalreachable_words:t->int@@portable="caml_obj_reachable_words"externaluniquely_reachable_words:tarray->intarray*int@@portable="caml_obj_uniquely_reachable_words"externalfield:t->int->t@@portable="%obj_field"let[@inlinealways]fieldtindex=field(Sys.opaque_identityt)indexexternalfield_contended:t@contended->int->t@contended@@portable="%obj_field"let[@inlinealways]field_contendedtindex=field_contended(opaque_identity_contendedt)indexexternalset_field:t->int->t->unit@@portable="%obj_set_field"let[@inlinealways]set_fieldtindexnew_value=set_field(Sys.opaque_identityt)indexnew_valueexternalfloatarray_get:floatarray->int->float@@portable="caml_floatarray_get"externalfloatarray_set:floatarray->int->float->unit@@portable="caml_floatarray_set"let[@inlinealways]double_fieldxi=floatarray_get(objx:floatarray)ilet[@inlinealways]set_double_fieldxiv=floatarray_set(objx:floatarray)ivexternalbox_int64:int64#->int64@@portable="%box_int64"externalunbox_int64:int64->int64#@@portable="%unbox_int64"externalunsafe_get_int64_field:t->int64#->int64#@@portable="%get_idx"externalunsafe_set_int64_field:t->int64#->int64#->unit@@portable="%set_idx"externalraw_field_bytecode:t->int->raw_data@@portable="caml_obj_raw_field"externalset_raw_field_bytecode:t->int->raw_data->unit@@portable="caml_obj_set_raw_field"let[@inlinealways]raw_fieldti=(matchSys.backend_typewith|Native->letbyte_offset=Int64.mul(Int64.of_inti)8LinInt64.to_nativeint(box_int64(unsafe_get_int64_fieldt(unbox_int64byte_offset)))|Bytecode|Other_->raw_field_bytecodeti)let[@inlinealways]set_raw_fieldtiv=(matchSys.backend_typewith|Native->letbyte_offset=Int64.mul(Int64.of_inti)8Linunsafe_set_int64_fieldt(unbox_int64byte_offset)(unbox_int64(Int64.of_nativeintv))|Bytecode|Other_->set_raw_field_bytecodetiv)externalnew_block:int->int->t@@portable="caml_obj_block"externaldup:t->t@@portable="%obj_dup"externaladd_offset:t->Int32.t->t@@portable="caml_obj_add_offset"externalwith_tag:int->t->t@@portable="caml_obj_with_tag"letfirst_non_constant_constructor_tag=0letlast_non_constant_constructor_tag=243letforcing_tag=244(* Note that cmmgen.ml contains a copy of [cont_tag] of its own *)letcont_tag=245letlazy_tag=246letclosure_tag=247letobject_tag=248letinfix_tag=249letforward_tag=250letno_scan_tag=251letabstract_tag=251letstring_tag=252letdouble_tag=253letdouble_array_tag=254letcustom_tag=255letint_tag=1000letout_of_heap_tag=1001letunaligned_tag=1002(* [null_tag] is not exposed in the interface of [Stdlib.Obj]
since [Stdlib.Obj.tag] accepts only non-null values. *)let[@warning"-32"]null_tag=1010moduleExtension_constructor=structtypet=extension_constructorletof_valx=letx=repr_contendedxinletslot=if(is_blockx)&&(tagx)<>object_tag&&(sizex)>=1thenfield_contendedx0elsexinletname=if(is_blockslot)&&(tagslot)=object_tagthenfield_contendedslot0elseinvalid_arg"Obj.extension_constructor"inif(tagname)=string_tagthen(obj_contendedslot:t)elseinvalid_arg"Obj.extension_constructor"let[@inlinealways]name(slot:t)=(obj(field(reprslot)0):string)let[@inlinealways]id(slot:t)=(obj(field(reprslot)1):int)endmoduleEphemeron=structtypeobj_t=ttypet(** ephemeron *)(** To change in sync with weak.h *)letadditional_values=2letmax_ephe_length=Sys.max_array_length-additional_valuesexternalcreate:int->t@@portable="caml_ephe_create"letcreatel=ifnot(0<=l&&l<=max_ephe_length)theninvalid_arg"Obj.Ephemeron.create";createlletlengthx=size(reprx)-additional_valuesletraise_if_invalid_offseteomsg=ifnot(0<=o&&o<lengthe)theninvalid_argmsgexternalget_key:t->int->obj_toption@@portable="caml_ephe_get_key"letget_keyeo=raise_if_invalid_offseteo"Obj.Ephemeron.get_key";get_keyeoexternalget_key_copy:t->int->obj_toption@@portable="caml_ephe_get_key_copy"letget_key_copyeo=raise_if_invalid_offseteo"Obj.Ephemeron.get_key_copy";get_key_copyeoexternalset_key:t->int->obj_t->unit@@portable="caml_ephe_set_key"letset_keyeox=raise_if_invalid_offseteo"Obj.Ephemeron.set_key";set_keyeoxexternalunset_key:t->int->unit@@portable="caml_ephe_unset_key"letunset_keyeo=raise_if_invalid_offseteo"Obj.Ephemeron.unset_key";unset_keyeoexternalcheck_key:t->int->bool@@portable="caml_ephe_check_key"letcheck_keyeo=raise_if_invalid_offseteo"Obj.Ephemeron.check_key";check_keyeoexternalblit_key:t->int->t->int->int->unit@@portable="caml_ephe_blit_key"letblit_keye1o1e2o2l=ifl<0||o1<0||o1>lengthe1-l||o2<0||o2>lengthe2-ltheninvalid_arg"Obj.Ephemeron.blit_key"elseifl<>0thenblit_keye1o1e2o2lexternalget_data:t->obj_toption@@portable="caml_ephe_get_data"externalget_data_copy:t->obj_toption@@portable="caml_ephe_get_data_copy"externalset_data:t->obj_t->unit@@portable="caml_ephe_set_data"externalunset_data:t->unit@@portable="caml_ephe_unset_data"externalcheck_data:t->bool@@portable="caml_ephe_check_data"externalblit_data:t->t->unit@@portable="caml_ephe_blit_data"endmoduleUniform_or_mixed=structtypeobj_t=t(* In native code, the raw reserved header bits, which is either 0 if the
block is uniform or n+1 if the block has a scannable prefix of length n.
In bytecode, this will be size+1 for "faux mixed blocks" representing
mixed records, and otherwise 0.
*)typet=intexternalof_block:obj_t->t@@portable="caml_succ_scannable_prefix_len"[@@noalloc]typerepr=|Uniform|Mixedof{scannable_prefix_len:int}letrepr=function|0->Uniform|n->Mixed{scannable_prefix_len=n-1}letis_uniformt=t=0letis_mixedt=not(is_uniformt)letmixed_scannable_prefix_len_exnt=ifis_uniformttheninvalid_arg"Uniform_or_mixed.mixed_scannable_prefix_len_exn";t-1end