@@ -377,7 +377,29 @@ module Constants : sig
377377
378378 val inlined : Code .constant -> bool
379379end = struct
380- let same_custom x y = Obj. field x 0 == Obj. field (Obj. repr y) 0
380+ (* In order to check that two custom objects share the same kind, we
381+ compare their identifier. The identifier is currently extracted
382+ from the marshaled value. *)
383+ let ident_of_custom x =
384+ (* Make sure tags are equal to custom_tag.
385+ Note that in javascript [0l] and [0n] are not encoded as custom blocks. *)
386+ if Obj. tag x <> Obj. custom_tag
387+ then None
388+ else
389+ try
390+ let bin = Marshal. to_string x [] in
391+ match Char. code bin.[20 ] with
392+ | 0x12 | 0x18 | 0x19 ->
393+ let last = String. index_from bin 21 '\000' in
394+ let name = String. sub bin ~pos: 21 ~len: (last - 21 ) in
395+ Some name
396+ | _ -> assert false
397+ with _ -> assert false
398+
399+ let same_ident x y =
400+ match y with
401+ | Some y -> String. equal x y
402+ | None -> false
381403
382404 let warn_overflow i i32 =
383405 warn
@@ -387,6 +409,12 @@ end = struct
387409 i32
388410 i32
389411
412+ let ident_32 = ident_of_custom (Obj. repr 0l )
413+
414+ let ident_64 = ident_of_custom (Obj. repr 0L )
415+
416+ let ident_native = ident_of_custom (Obj. repr 0n )
417+
390418 let rec parse x =
391419 if Obj. is_block x
392420 then
@@ -397,17 +425,23 @@ end = struct
397425 then Float (Obj. magic x : float )
398426 else if tag = Obj. double_array_tag
399427 then Float_array (Obj. magic x : float array )
400- else if tag = Obj. custom_tag && same_custom x 0l
401- then Int (Obj. magic x : int32 )
402- else if tag = Obj. custom_tag && same_custom x 0n
403- then (
404- let i : nativeint = Obj. magic x in
405- let i32 = Nativeint. to_int32 i in
406- let i' = Nativeint. of_int32 i32 in
407- if Poly. (i' <> i) then warn_overflow (Printf. sprintf " 0x%nx (%nd)" i i) i32;
408- Int i32)
409- else if tag = Obj. custom_tag && same_custom x 0L
410- then Int64 (Obj. magic x : int64 )
428+ else if tag = Obj. custom_tag
429+ then
430+ match ident_of_custom x with
431+ | Some name when same_ident name ident_32 -> Int (Obj. magic x : int32 )
432+ | Some name when same_ident name ident_native ->
433+ let i : nativeint = Obj. magic x in
434+ let i32 = Nativeint. to_int32 i in
435+ let i' = Nativeint. of_int32 i32 in
436+ if Poly. (i' <> i) then warn_overflow (Printf. sprintf " 0x%nx (%nd)" i i) i32;
437+ Int i32
438+ | Some name when same_ident name ident_64 -> Int64 (Obj. magic x : int64 )
439+ | Some name ->
440+ failwith
441+ (Printf. sprintf
442+ " parse_bytecode: Don't know what to do with custom block (%s)"
443+ name)
444+ | None -> assert false
411445 else if tag < Obj. no_scan_tag
412446 then
413447 Tuple (tag, Array. init (Obj. size x) ~f: (fun i -> parse (Obj. field x i)), Unknown )
0 commit comments