Skip to content

Commit ab0924a

Browse files
committed
Compiler: implement a fast js free variable analysis
1 parent b141741 commit ab0924a

File tree

5 files changed

+305
-188
lines changed

5 files changed

+305
-188
lines changed

compiler/bin-wasm_of_ocaml/gen/gen.ml

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,18 @@
11
open Js_of_ocaml_compiler
22
open Js_of_ocaml_compiler.Stdlib
33

4-
let to_stringset utf8_string_set =
5-
Javascript.IdentSet.fold
6-
(fun x acc ->
7-
match x with
8-
| S { name = Utf8 x; _ } -> StringSet.add x acc
9-
| V _ -> acc)
10-
utf8_string_set
11-
StringSet.empty
12-
134
let check_js_file fname =
145
let c = Fs.read_file fname in
156
let p =
167
try Parse_js.parse (Parse_js.Lexer.of_string ~filename:fname c)
178
with Parse_js.Parsing_error pi ->
189
failwith (Printf.sprintf "cannot parse file %S (l:%d, c:%d)@." fname pi.line pi.col)
1910
in
20-
let traverse = new Js_traverse.free in
21-
let _js = traverse#program p in
22-
let freenames = to_stringset traverse#get_free in
11+
12+
let free = ref StringSet.empty in
13+
let o = new Js_traverse.fast_freevar (fun s -> free := StringSet.add s !free) in
14+
o#program p;
15+
let freenames = !free in
2316
let freenames = StringSet.diff freenames Reserved.keyword in
2417
let freenames = StringSet.diff freenames Reserved.provided in
2518
if not (StringSet.is_empty freenames)

compiler/lib/driver.ml

Lines changed: 16 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -291,8 +291,6 @@ let link' ~export_runtime ~standalone ~link (js : Javascript.statement_list) :
291291
let check_missing = standalone in
292292
let t = Timer.make () in
293293
if times () then Format.eprintf "Start Linking...@.";
294-
let traverse = new Js_traverse.free in
295-
let js = traverse#program js in
296294
let js =
297295
if mark_start_of_generated_code ()
298296
then
@@ -311,20 +309,10 @@ let link' ~export_runtime ~standalone ~link (js : Javascript.statement_list) :
311309
| `All_from from -> Linker.list_all ~from ()
312310
| `No -> StringSet.empty
313311
| `Needed ->
314-
let free = traverse#get_free in
315-
let free : StringSet.t =
316-
Javascript.IdentSet.fold
317-
(fun x acc ->
318-
match x with
319-
| V _ ->
320-
(* This is an error. We don't complain here as we want
321-
to be able to name other variable to make it
322-
easier to spot the problematic ones *)
323-
acc
324-
| S { name = Utf8 x; _ } -> StringSet.add x acc)
325-
free
326-
StringSet.empty
327-
in
312+
let free = ref StringSet.empty in
313+
let o = new Js_traverse.fast_freevar (fun s -> free := StringSet.add s !free) in
314+
o#program js;
315+
let free = !free in
328316
let prim = Primitive.get_external () in
329317
let all_external = StringSet.union prim all_provided in
330318
StringSet.inter free all_external
@@ -423,18 +411,10 @@ let link' ~export_runtime ~standalone ~link (js : Javascript.statement_list) :
423411
let check_js js =
424412
let t = Timer.make () in
425413
if times () then Format.eprintf "Start Checks...@.";
426-
let traverse = new Js_traverse.free in
427-
let js = traverse#program js in
428-
let free = traverse#get_free in
429-
let free : StringSet.t =
430-
Javascript.IdentSet.fold
431-
(fun x acc ->
432-
match x with
433-
| V _ -> assert false
434-
| S { name = Utf8 x; _ } -> StringSet.add x acc)
435-
free
436-
StringSet.empty
437-
in
414+
let free = ref StringSet.empty in
415+
let o = new Js_traverse.fast_freevar (fun s -> free := StringSet.add s !free) in
416+
o#program js;
417+
let free = !free in
438418
let prim = Primitive.get_external () in
439419
let prov = Linker.list_all () in
440420
let all_external = StringSet.union prim prov in
@@ -469,19 +449,8 @@ let name_variables js =
469449
js)
470450
else js
471451
in
472-
let traverse = new Js_traverse.free in
473-
let js = traverse#program js in
474-
let free = traverse#get_free in
475-
Javascript.IdentSet.iter
476-
(fun x ->
477-
match x with
478-
| V _ ->
479-
(* This is an error. We don't complain here as we want
480-
to be able to name other variable to make it
481-
easier to spot the problematic ones *)
482-
()
483-
| S { name = Utf8 x; _ } -> Var_printer.add_reserved x)
484-
free;
452+
let o = new Js_traverse.fast_freevar (fun s -> Var_printer.add_reserved s) in
453+
o#program js;
485454
let js = Js_assign.program js in
486455
if times () then Format.eprintf " coloring: %a@." Timer.print t;
487456
js
@@ -520,13 +489,12 @@ let pack ~wrap_with_fun ~standalone { Linker.runtime_code = js; always_required_
520489
let wrap_in_iife ~use_strict js =
521490
let var ident e = J.variable_declaration [ J.ident ident, (e, J.N) ], J.N in
522491
let expr e = J.Expression_statement e, J.N in
523-
let freenames =
524-
let o = new Js_traverse.free in
525-
let (_ : J.program) = o#program js in
526-
o#get_free
527-
in
492+
let free = ref StringSet.empty in
493+
let o = new Js_traverse.fast_freevar (fun s -> free := StringSet.add s !free) in
494+
o#program js;
495+
let freenames = !free in
528496
let export_shim js =
529-
if J.IdentSet.mem (J.ident Global_constant.exports_) freenames
497+
if StringSet.mem Global_constant.exports freenames
530498
then
531499
if should_export wrap_with_fun
532500
then var Global_constant.exports_ (J.EObj []) :: js
@@ -544,7 +512,7 @@ let pack ~wrap_with_fun ~standalone { Linker.runtime_code = js; always_required_
544512
else js
545513
in
546514
let old_global_object_shim js =
547-
if J.IdentSet.mem (J.ident Global_constant.old_global_object_) freenames
515+
if StringSet.mem Global_constant.old_global_object freenames
548516
then
549517
var
550518
Global_constant.old_global_object_

0 commit comments

Comments
 (0)