@@ -189,6 +189,46 @@ let is_int info x =
189189 | Pc (Int _ ) -> Y
190190 | Pc _ -> N
191191
192+ let the_tag_of info x get =
193+ match x with
194+ | Pv x ->
195+ get_approx
196+ info
197+ (fun x ->
198+ match info.info_defs.(Var. idx x) with
199+ | Expr (Block (j , _ , _ )) ->
200+ if Var.ISet. mem info.info_possibly_mutable x then None else get j
201+ | Expr (Constant (Tuple (j , _ , _ ))) -> get j
202+ | _ -> None )
203+ None
204+ (fun u v ->
205+ match u, v with
206+ | Some i , Some j when Poly. (i = j) -> u
207+ | _ -> None )
208+ x
209+ | Pc (Tuple (j , _ , _ )) -> get j
210+ | _ -> None
211+
212+ let the_cont_of info x (a : cont array ) =
213+ (* The value of [x] might be meaningless when we're inside a dead code.
214+ The proper fix would be to remove the deadcode entirely.
215+ Meanwhile, add guards to prevent Invalid_argument("index out of bounds")
216+ see https://github.com/ocsigen/js_of_ocaml/issues/485 *)
217+ let get i = if i > = 0 && i < Array. length a then Some a.(i) else None in
218+ get_approx
219+ info
220+ (fun x ->
221+ match info.info_defs.(Var. idx x) with
222+ | Expr (Prim (Extern "%direct_obj_tag" , [ b ])) -> the_tag_of info b get
223+ | Expr (Constant (Int j )) -> get (Int32. to_int j)
224+ | _ -> None )
225+ None
226+ (fun u v ->
227+ match u, v with
228+ | Some i , Some j when Poly. (i = j) -> u
229+ | _ -> None )
230+ x
231+
192232let eval_instr info ((x , loc ) as i ) =
193233 match x with
194234 | Let (x , Prim (Extern ("caml_js_equals" | "caml_equal" ), [ y; z ])) -> (
@@ -228,6 +268,13 @@ let eval_instr info ((x, loc) as i) =
228268 let c = Constant (Int b) in
229269 Flow. update_def info x c;
230270 [ Let (x, c), loc ])
271+ | Let (x , Prim (Extern "%direct_obj_tag" , [ y ])) -> (
272+ match the_tag_of info y (fun x -> Some x) with
273+ | Some tag ->
274+ let c = Constant (Int (Int32. of_int tag)) in
275+ Flow. update_def info x c;
276+ [ Let (x, c), loc ]
277+ | None -> [ i ])
231278 | Let (x , Prim (Extern "caml_sys_const_backend_type" , [ _ ])) ->
232279 let jsoo = Code.Var. fresh () in
233280 [ Let (jsoo, Constant (String " js_of_ocaml" )), noloc
@@ -271,34 +318,6 @@ let eval_instr info ((x, loc) as i) =
271318 ])
272319 | _ -> [ i ]
273320
274- type case_of =
275- | CConst of int
276- | CTag of int
277- | Unknown
278-
279- let the_case_of info x =
280- match x with
281- | Pv x ->
282- get_approx
283- info
284- (fun x ->
285- match info.info_defs.(Var. idx x) with
286- | Expr (Constant (Int i )) -> CConst (Int32. to_int i)
287- | Expr (Block (j , _ , _ )) ->
288- if Var.ISet. mem info.info_possibly_mutable x then Unknown else CTag j
289- | Expr (Constant (Tuple (j , _ , _ ))) -> CTag j
290- | _ -> Unknown )
291- Unknown
292- (fun u v ->
293- match u, v with
294- | CTag i , CTag j when i = j -> u
295- | CConst i , CConst j when i = j -> u
296- | _ -> Unknown )
297- x
298- | Pc (Int i ) -> CConst (Int32. to_int i)
299- | Pc (Tuple (j , _ , _ )) -> CTag j
300- | _ -> Unknown
301-
302321type cond_of =
303322 | Zero
304323 | Non_zero
@@ -341,15 +360,10 @@ let eval_branch info (l, loc) =
341360 | Zero -> Branch ffalse
342361 | Non_zero -> Branch ftrue
343362 | Unknown -> b)
344- | Switch (x , const , tags ) as b -> (
345- (* [the_case_of info (Pv x)] might be meaningless when we're inside a dead code.
346- The proper fix would be to remove the deadcode entirely.
347- Meanwhile, add guards to prevent Invalid_argument("index out of bounds")
348- see https://github.com/ocsigen/js_of_ocaml/issues/485 *)
349- match the_case_of info (Pv x) with
350- | CConst j when j > = 0 && j < Array. length const -> Branch const.(j)
351- | CTag j when j > = 0 && j < Array. length tags -> Branch tags.(j)
352- | CConst _ | CTag _ | Unknown -> b)
363+ | Switch (x , a ) as b -> (
364+ match the_cont_of info x a with
365+ | Some cont -> Branch cont
366+ | None -> b)
353367 | _ as b -> b
354368 in
355369 l, loc
@@ -380,15 +394,11 @@ let rec do_not_raise pc visited blocks =
380394 let visited = do_not_raise pc1 visited blocks in
381395 let visited = do_not_raise pc2 visited blocks in
382396 visited
383- | Switch (_ , a1 , a2 ) ->
397+ | Switch (_ , a1 ) ->
384398 let visited =
385399 Array. fold_left a1 ~init: visited ~f: (fun visited (pc , _ ) ->
386400 do_not_raise pc visited blocks)
387401 in
388- let visited =
389- Array. fold_left a2 ~init: visited ~f: (fun visited (pc , _ ) ->
390- do_not_raise pc visited blocks)
391- in
392402 visited
393403 | Pushtrap _ -> raise May_raise
394404
0 commit comments