Skip to content

Commit fa494b6

Browse files
committed
Compiler: improve parsing of constant in parse_bytecode so that it works in javascript
1 parent 37549f5 commit fa494b6

File tree

1 file changed

+46
-12
lines changed

1 file changed

+46
-12
lines changed

compiler/lib/parse_bytecode.ml

Lines changed: 46 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,29 @@ module Constants : sig
377377

378378
val inlined : Code.constant -> bool
379379
end = 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

Comments
 (0)