Skip to content

refine let_kind in js ir, simplify [string_of_int] and other micro-optimizations #63

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 1, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion jscomp/j.ml
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ and expression_desc =
since GC does not rely on it
*)
| Array_copy of expression (* shallow copy, like [x.slice] *)
| Array_append of expression * expression list (* For [caml_array_append]*)
| Array_append of expression * expression (* For [caml_array_append]*)
| Tag_ml_obj of expression
| String_append of expression * expression
| Int_of_boolean of expression
Expand Down
2 changes: 1 addition & 1 deletion jscomp/js_dump.ml
Original file line number Diff line number Diff line change
Expand Up @@ -432,7 +432,7 @@ and
P.group f 1 (fun _ ->
let cxt = expression 15 cxt f e in
P.string f ".concat";
P.paren_group f 1 (fun _ -> arguments cxt f el))
P.paren_group f 1 (fun _ -> arguments cxt f [el]))

| Array_copy e ->
P.group f 1 (fun _ ->
Expand Down
3 changes: 1 addition & 2 deletions jscomp/js_fold.ml
Original file line number Diff line number Diff line change
Expand Up @@ -339,8 +339,7 @@ class virtual fold =
| Array_of_size _x -> let o = o#expression _x in o
| Array_copy _x -> let o = o#expression _x in o
| Array_append (_x, _x_i1) ->
let o = o#expression _x in
let o = o#list (fun o -> o#expression) _x_i1 in o
let o = o#expression _x in let o = o#expression _x_i1 in o
| Tag_ml_obj _x -> let o = o#expression _x in o
| String_append (_x, _x_i1) ->
let o = o#expression _x in let o = o#expression _x_i1 in o
Expand Down
39 changes: 21 additions & 18 deletions jscomp/js_helper.ml
Original file line number Diff line number Diff line change
Expand Up @@ -142,15 +142,26 @@ module Exp = struct

let str ?(pure=true) ?comment s : t = {expression_desc = Str (pure,s); comment}

let any_to_string ?comment (e : t) : t =
let anything_to_string ?comment (e : t) : t =
match e.expression_desc with
| Str _ -> e
| _ -> {expression_desc = Anything_to_string e ; comment}


(* we can do constant folding here, but need to make sure the result is consistent
{[
let f x = string_of_int x
;; f 3
]}
{[
string_of_int 3
]}
*)
let int_to_string ?comment (e : t) : t =
anything_to_string ?comment e
(* Shared mutable state is evil
[Js_fun_env.empty] is a mutable state ..
*)
let efun ?comment ?immutable_mask
let fun_ ?comment ?immutable_mask
params block : t =
let len = List.length params in
{
Expand Down Expand Up @@ -308,6 +319,8 @@ module Exp = struct
String_append ({expression_desc = Str(_,c)} ,d) ->
string_append ?comment (string_append a (str (b ^ c))) d
| Str (_,a), Str (_,b) -> str ?comment (a ^ b)
| _, Anything_to_string b -> string_append ?comment e b
| Anything_to_string b, _ -> string_append ?comment b el
| _, _ -> {comment ; expression_desc = String_append(e,el)}


Expand Down Expand Up @@ -911,12 +924,7 @@ module Stmt = struct
{ statement_desc = Exp e; comment}

let declare_variable ?comment ?ident_info ~kind (v:Ident.t) : t=
let property : J.property =
match (kind : Lambda.let_kind ) with
| (Alias | Strict | StrictOpt )
-> Immutable
| Variable -> Mutable
in
let property : J.property = kind in
let ident_info : J.ident_info =
match ident_info with
| None -> {used_stats = NA}
Expand All @@ -927,12 +935,7 @@ module Stmt = struct
comment}

let define ?comment ?ident_info ~kind (v:Ident.t) exp : t=
let property : J.property =
match (kind : Lambda.let_kind ) with
| (Alias | Strict | StrictOpt )
-> Immutable
| Variable -> Mutable
in
let property : J.property = kind in
let ident_info : J.ident_info =
match ident_info with
| None -> {used_stats = NA}
Expand Down Expand Up @@ -1130,10 +1133,10 @@ module Stmt = struct



let const_variable ?comment ?exp (v:Ident.t) : t=
let alias_variable ?comment ?exp (v:Ident.t) : t=
{statement_desc =
Variable {
ident = v; value = exp; property = Immutable;
ident = v; value = exp; property = Alias;
ident_info = {used_stats = NA } };
comment}

Expand All @@ -1152,7 +1155,7 @@ module Stmt = struct
statement_desc =
J.Variable { ident = id;
value = Some (Exp.unit ()) ;
property = Mutable;
property = Variable;
ident_info = {used_stats = NA}
};
comment
Expand Down
9 changes: 5 additions & 4 deletions jscomp/js_helper.mli
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ module Exp : sig

val str : ?pure:bool -> ?comment:string -> string -> t

val efun : ?comment:string ->
val fun_ : ?comment:string ->
?immutable_mask:bool array -> J.ident list -> J.block -> t

val econd : ?comment:string -> t -> t -> t -> t
Expand Down Expand Up @@ -126,7 +126,7 @@ module Exp : sig

val char_to_int : unary_op

val array_append : ?comment:string -> t -> t list -> t
val array_append : binary_op

val array_copy : unary_op
val string_append : binary_op
Expand Down Expand Up @@ -189,7 +189,8 @@ module Exp : sig

val dump : ?comment:string -> Js_op.level -> t list -> t

val any_to_string : unary_op
val anything_to_string : unary_op
val int_to_string : unary_op
val to_json_string : unary_op

val new_ : ?comment:string -> J.expression -> J.expression list -> t
Expand Down Expand Up @@ -285,7 +286,7 @@ module Stmt : sig
?ident_info:J.ident_info ->
kind:Lambda.let_kind -> Ident.t -> J.expression -> t

val const_variable :
val alias_variable :
?comment:string -> ?exp:J.expression -> Ident.t -> t
val assign : ?comment:string -> J.ident -> J.expression -> t

Expand Down
2 changes: 1 addition & 1 deletion jscomp/js_inline_and_eliminate.ml
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ let subst name export_set stats =
-> self#statement st :: self#block rest

| { value = Some {expression_desc = Fun (params, block, _env) ; comment = _};
property = Immutable;
property = (Alias | StrictOpt | Strict);
ident_info = {used_stats = Once_pure };
ident = _
} as v
Expand Down
3 changes: 1 addition & 2 deletions jscomp/js_map.ml
Original file line number Diff line number Diff line change
Expand Up @@ -371,8 +371,7 @@ class virtual map =
| Array_copy _x -> let _x = o#expression _x in Array_copy _x
| Array_append (_x, _x_i1) ->
let _x = o#expression _x in
let _x_i1 = o#list (fun o -> o#expression) _x_i1
in Array_append (_x, _x_i1)
let _x_i1 = o#expression _x_i1 in Array_append (_x, _x_i1)
| Tag_ml_obj _x -> let _x = o#expression _x in Tag_ml_obj _x
| String_append (_x, _x_i1) ->
let _x = o#expression _x in
Expand Down
8 changes: 5 additions & 3 deletions jscomp/js_op.ml
Original file line number Diff line number Diff line change
Expand Up @@ -127,9 +127,11 @@ type kind =
| Runtime
| External of string

type property =
| Mutable
| Immutable
type property = Lambda.let_kind =
| Strict
| Alias
| StrictOpt
| Variable

type int_or_char =
{ i : int;
Expand Down
2 changes: 1 addition & 1 deletion jscomp/js_pass_flatten_and_mark_dead.ml
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ let subst_map name = object (self)
{v with statement_desc = (Exp x)}

| Variable ({ ident ;
property = Immutable;
property = (Strict | StrictOpt | Alias);
value = Some ({expression_desc = (Array ( _:: _ :: _ as ls, Immutable))} as array)
} as variable) ->
(** If we do this, we should prevent incorrect inlning to inline it into an array :)
Expand Down
8 changes: 4 additions & 4 deletions jscomp/js_pass_scope.ml
Original file line number Diff line number Diff line change
Expand Up @@ -196,10 +196,10 @@ let scope_pass =
| { ident ; value; property } ->
let obj =
(match self#get_in_loop, property with
| true, Mutable
| true, Variable
->
self#add_loop_mutable_variable ident
| true, Immutable
| true, (Strict | StrictOpt | Alias)
(* Not real true immutable in javascript
since it's in the loop

Expand Down Expand Up @@ -235,10 +235,10 @@ let scope_pass =
(* else *)
self#add_loop_mutable_variable ident
end
| false, Mutable
| false, Variable
->
self#add_mutable_variable ident
| false, Immutable
| false, (Strict | StrictOpt | Alias)
-> self
)#add_defined_ident ident
in
Expand Down
10 changes: 5 additions & 5 deletions jscomp/lam_compile.ml
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ and compile_recursive_let (cxt : Lam_compile_defs.cxt) (id : Ident.t) (arg : Lam
jmp_table = Lam_compile_defs.empty_handler_map} body in
if ret.triggered then
let body_block = Js_output.to_block output in
E.efun (* TODO: save computation of length several times *)
E.fun_ (* TODO: save computation of length several times *)
~immutable_mask:ret.immutable_mask
(List.map (fun x ->
try Ident_map.find x ret.new_params with Not_found -> x)
Expand All @@ -107,7 +107,7 @@ and compile_recursive_let (cxt : Lam_compile_defs.cxt) (id : Ident.t) (arg : Lam
]

else (* TODO: save computation of length several times *)
E.efun params (Js_output.to_block output )
E.fun_ params (Js_output.to_block output )
), []
| (Lprim(Pmakeblock _ , _) ) ->
(* Lconst should not appear here if we do [scc]
Expand Down Expand Up @@ -261,7 +261,7 @@ and
match lam with
| Lfunction(kind, params, body) ->
Js_output.handle_name_tail st should_return lam
(E.efun
(E.fun_
params
(* Invariant: jmp_table can not across function boundary,
here we share env
Expand Down Expand Up @@ -918,11 +918,11 @@ and
(* | String_length e *)
(* -> *)
(* let len = Ext_ident.create "_length" in *)
(* b2 @ [ S.const_variable len ~exp:e2 ], J.Finish (Id len ) *)
(* b2 @ [ S.alias_variable len ~exp:e2 ], J.Finish (Id len ) *)
(* | _ -> *)
(* (\* TODO: guess a better name when possible*\) *)
(* let len = Ext_ident.create "_finish" in *)
(* b2 @ [S.const_variable len ~exp:e2], J.Finish (Id len) *)
(* b2 @ [S.alias_variable len ~exp:e2], J.Finish (Id len) *)
(* in *)

b1 @ (S.define ~kind:Variable id e1 :: b2 ) @ ([
Expand Down
3 changes: 3 additions & 0 deletions jscomp/lam_compile_global.ml
Original file line number Diff line number Diff line change
Expand Up @@ -115,10 +115,13 @@ let get_exp_with_args (id : Ident.t) (pos : int) env (args : J.expression list)
id.flags
pos
))

~found:(fun {id; name;arity; _} ->
match id, name, args with
| {name = "Pervasives"; _}, "^", [ e0 ; e1] ->
E.string_append e0 e1
| {name = "Pervasives"; _}, "string_of_int", [e]
-> E.int_to_string e
| {name = "Pervasives"; _}, "print_endline", ([ _ ] as args) ->
E.seq (E.dump Log args) (E.unit ())
| {name = "Pervasives"; _}, "prerr_endline", ([ _ ] as args) ->
Expand Down
47 changes: 28 additions & 19 deletions jscomp/lam_compile_group.ml
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,11 @@ let compile_group ({filename = file_name; env;} as meta : Lam_stats.meta)
2. [E.builtin_dot] for javascript builtin
3. [E.mldot]
*)
(* ATTENTION: check {!Lam_compile_global} for consistency *)
(** Special handling for values in [Pervasives] *)
| Single(_, ({name="stdout"|"stderr"|"stdin";_} as id),_ ),
"pervasives.ml" ->
Js_output.of_stmt @@ S.const_variable id
Js_output.of_stmt @@ S.alias_variable id
~exp:(E.runtime_ref Js_helper.io id.name)
(*
we delegate [stdout, stderr, and stdin] into [caml_io] module,
Expand All @@ -49,11 +50,11 @@ let compile_group ({filename = file_name; env;} as meta : Lam_stats.meta)
*)
| Single(_, ({name="infinity";_} as id),_ ), "pervasives.ml"
-> (* TODO: check relative path to compiler*)
Js_output.of_stmt @@ S.const_variable id ~exp:(E.js_global "Infinity")
Js_output.of_stmt @@ S.alias_variable id ~exp:(E.js_global "Infinity")
| Single(_, ({name="neg_infinity";_} as id),_ ), "pervasives.ml" ->
Js_output.of_stmt @@ S.const_variable id ~exp:(E.js_global "-Infinity")
Js_output.of_stmt @@ S.alias_variable id ~exp:(E.js_global "-Infinity")
| Single(_, ({name="nan";_} as id),_ ), "pervasives.ml" ->
Js_output.of_stmt @@ S.const_variable id ~exp:(E.js_global "NaN")
Js_output.of_stmt @@ S.alias_variable id ~exp:(E.js_global "NaN")

(* TODO:
Make it more safe, we should rewrite the last one...
Expand All @@ -62,55 +63,63 @@ let compile_group ({filename = file_name; env;} as meta : Lam_stats.meta)
[Lam_dispatch_primitive], here it makes an exception since this function is not a primitive
*)
| Single(_, ({name="^";_} as id),_ ), "pervasives.ml" ->
Js_output.of_stmt @@ S.const_variable id
~exp:(E.runtime_ref Js_helper.string "add")
Js_output.of_stmt @@ S.alias_variable id
~exp:(let a = Ext_ident.create "a" in
let b = Ext_ident.create "b" in
E.fun_ [a;b] [S.return (E.string_append (E.var a) (E.var b))]
)

(* QUICK hack to make hello world example nicer,
Note the arity of [print_endline] is already analyzed before,
so it should be safe
*)
| Single(_, ({name="print_endline";_} as id),_ ), "pervasives.ml" ->
Js_output.of_stmt @@ S.const_variable id
Js_output.of_stmt @@ S.alias_variable id
~exp:(E.js_global "console.log")
| Single(_, ({name="prerr_endline";_} as id),_ ), "pervasives.ml" ->
Js_output.of_stmt @@ S.const_variable id
Js_output.of_stmt @@ S.alias_variable id
~exp:(E.js_global "console.error")


| Single(_, ({name="string_of_int";_} as id),_ ), "pervasives.ml" ->
Js_output.of_stmt @@ S.const_variable id ~exp:(E.runtime_ref
Js_helper.prim "string_of_int")
Js_output.of_stmt @@ S.alias_variable id
~exp:(
let arg = Ext_ident.create "param" in
E.fun_ [arg] [S.return (E.anything_to_string (E.var arg))]
)

| Single(_, ({name="max_float";_} as id),_ ), "pervasives.ml" ->

Js_output.of_stmt @@ S.const_variable id
Js_output.of_stmt @@ S.alias_variable id
~exp:(E.js_global_dot "Number" "MAX_VALUE")
| Single(_, ({name="min_float";_} as id) ,_ ), "pervasives.ml" ->
Js_output.of_stmt @@ S.const_variable id
Js_output.of_stmt @@ S.alias_variable id
~exp:(E.js_global_dot "Number" "MIN_VALUE")
| Single(_, ({name="epsilon_float";_} as id) ,_ ), "pervasives.ml" ->
Js_output.of_stmt @@ S.const_variable id
Js_output.of_stmt @@ S.alias_variable id
~exp:(E.js_global_dot "Number" "EPSILON")
| Single(_, ({name="cat";_} as id) ,_ ), "bytes.ml" ->
Js_output.of_stmt @@ S.const_variable id
~exp:(E.runtime_ref
Js_helper.string "bytes_cat")
Js_output.of_stmt @@ S.alias_variable id
~exp:(let a = Ext_ident.create "a" in
let b = Ext_ident.create "b" in
E.fun_ [a;b] [S.return (E.array_append (E.var a) (E.var b))]
)

(** Special handling for values in [Sys] *)
| Single(_, ({name="max_array_length" | "max_string_length";_} as id) ,_ ), "sys.ml" ->
(* See [js_knowledge] Array size section, can not be expressed by OCaml int,
note that casual handling of {!Sys.max_string_length} could result into
negative value which could cause wrong behavior of {!Buffer.create}
*)
Js_output.of_stmt @@ S.const_variable id ~exp:(E.float "4_294_967_295.")
Js_output.of_stmt @@ S.alias_variable id ~exp:(E.float "4_294_967_295.")

| Single(_, ({name="max_int";_} as id) ,_ ), ("sys.ml" | "nativeint.ml") ->
(* See [js_knowledge] Max int section, (2. ** 53. -. 1.;;) can not be expressed by OCaml int *)
Js_output.of_stmt @@ S.const_variable id ~exp:(E.float "9007199254740991.")
Js_output.of_stmt @@ S.alias_variable id ~exp:(E.float "9007199254740991.")

| Single(_, ({name="min_int";_} as id) ,_ ), ("sys.ml" | "nativeint.ml") ->
(* See [js_knowledge] Max int section, -. (2. ** 53. -. 1.);; can not be expressed by OCaml int *)
Js_output.of_stmt @@ S.const_variable id ~exp:(E.float ("-9007199254740991."))
Js_output.of_stmt @@ S.alias_variable id ~exp:(E.float ("-9007199254740991."))

| Single (kind, id, lam), _ ->
(* let lam = Optimizer.simplify_lets [] lam in *)
Expand Down
Loading