Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions jscomp/compiler.mllib
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ ext_pp_scope
ext_array
ext_bytes
ext_map
ext_hashtbl

lam_mk
lam_compile_env
lam_dispatch_primitive
lam_stats
Expand Down Expand Up @@ -56,6 +58,7 @@ lam_fold
lam_register
lam_analysis
lam_group
lam_current_unit

j
js_program_loader
Expand Down
33 changes: 33 additions & 0 deletions jscomp/ext_hashtbl.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
(* OCamlScript compiler
* Copyright (C) 2015-2016 Bloomberg Finance L.P.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, with linking exception;
* either version 2.1 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*)

(* Author: Hongbo Zhang *)

let of_list kvs =
let map = Hashtbl.create 51 in
List.iter (fun (k, v) -> Hashtbl.add map k v) kvs ;
map


let of_list2 ks vs =
let map = Hashtbl.create 51 in
List.iter2 (fun k v -> Hashtbl.add map k v) ks vs ;
map

let add_list map kvs =
List.iter (fun (k, v) -> Hashtbl.add map k v) kvs
26 changes: 26 additions & 0 deletions jscomp/ext_hashtbl.mli
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
(* OCamlScript compiler
* Copyright (C) 2015-2016 Bloomberg Finance L.P.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, with linking exception;
* either version 2.1 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*)

(* Author: Hongbo Zhang *)


val of_list : ('a * 'b) list -> ('a, 'b) Hashtbl.t

val of_list2 : 'a list -> 'b list -> ('a, 'b) Hashtbl.t

val add_list : ('a, 'b) Hashtbl.t -> ('a * 'b) list -> unit
1 change: 1 addition & 0 deletions jscomp/ext_ident.ml
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ let convert (name : string) =
| '@' -> Buffer.add_string buffer "$at"
| '^' -> Buffer.add_string buffer "$caret"
| '/' -> Buffer.add_string buffer "$slash"
| '|' -> Buffer.add_string buffer "$pipe"
| '.' -> Buffer.add_string buffer "$dot"
| 'a'..'z' | 'A'..'Z'| '_'|'$' |'0'..'9'-> Buffer.add_char buffer c
| _ -> Buffer.add_string buffer "$unknown"
Expand Down
8 changes: 8 additions & 0 deletions jscomp/ext_log.ml
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,20 @@ let ierr b str f v =
let warn str f v =
Format.fprintf Format.err_formatter ("WARN: %s " ^^ f) str v



let iwarn b str f v =
if b then
Format.fprintf Format.err_formatter ("WARN: %s " ^^ f) str v
else
Format.ifprintf Format.err_formatter ("WARN: %s " ^^ f) str v

let dwarn str f v =
if Lam_current_unit.is_same_file () then
Format.fprintf Format.err_formatter ("WARN: %s " ^^ f) str v
else
Format.ifprintf Format.err_formatter ("WARN: %s " ^^ f) str v

let info str f v =
Format.fprintf Format.err_formatter ("INFO: %s " ^^ f) str v

Expand Down
1 change: 1 addition & 0 deletions jscomp/ext_log.mli
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,6 @@ val err : string -> ('a,'b) logging
val ierr : bool -> string -> ('a,'b) logging
val warn : string -> ('a,'b) logging
val iwarn : bool -> string -> ('a,'b) logging
val dwarn : string -> ('a,'b) logging
val info : string -> ('a,'b) logging
val iinfo : bool -> string -> ('a,'b) logging
9 changes: 9 additions & 0 deletions jscomp/j.ml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,15 @@ and vident =
just print `A.length` - it's guarateed to be unique

when the third one is None, it means the whole module

TODO:
invariant, when [kind] is [Runtime], then we can ignore [ident],
since all [runtime] functions are unique, when do the
pattern match we can ignore the first one for simplicity
for example
{[
Qualified (_, Runtime, Some "caml_int_compare")
]}
*)

and exception_ident = ident
Expand Down
9 changes: 9 additions & 0 deletions jscomp/js_fold.ml
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,15 @@ class virtual fold =
just print `A.length` - it's guarateed to be unique

when the third one is None, it means the whole module

TODO:
invariant, when [kind] is [Runtime], then we can ignore [ident],
since all [runtime] functions are unique, when do the
pattern match we can ignore the first one for simplicity
for example
{[
Qualified (_, Runtime, Some "caml_int_compare")
]}
*)
(* used in [js_create_array] primitive, note having
uninitilized array is not as bad as in ocaml,
Expand Down
63 changes: 47 additions & 16 deletions jscomp/js_helper.ml
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,7 @@ module Exp = struct
true_
| _ ->
to_ocaml_boolean {expression_desc = Bin(EqEqEq, e0,e1); comment}
let int_equal = float_equal
let rec string_equal ?comment (e0 : t) (e1 : t) : t =
match e0.expression_desc, e1.expression_desc with
| Str (_, a0), Str(_, b0)
Expand Down Expand Up @@ -514,27 +515,44 @@ module Exp = struct
bit different from Javascript, so that we can change it in the future
*)
let rec and_ ?comment (e1 : t) (e2 : t) =
match e1, e2 with
| {expression_desc = Int_of_boolean e1;_} ,
{expression_desc = Int_of_boolean e2;_} ->
match e1.expression_desc, e2.expression_desc with
| Int_of_boolean e1 , Int_of_boolean e2 ->
and_ ?comment e1 e2
| {expression_desc = Int_of_boolean e1; _} ,
e2 -> and_ ?comment e1 e2
| e1, {expression_desc = Int_of_boolean e2;_}
| Int_of_boolean e1 , _ -> and_ ?comment e1 e2
| _, Int_of_boolean e2
-> and_ ?comment e1 e2
| e1, e2 ->
(* optimization if [e1 = e2], then and_ e1 e2 -> e2
be careful for side effect
*)
| Var i, Var j when Js_op_util.same_vident i j
->
to_ocaml_boolean e1
| Var i,
(Bin (And, {expression_desc = Var j ; _}, _)
| Bin (And , _, {expression_desc = Var j ; _}))
when Js_op_util.same_vident i j
->
to_ocaml_boolean e2
| _, _ ->
to_ocaml_boolean @@ bin ?comment And e1 e2

let rec or_ ?comment (e1 : t) (e2 : t) =
match e1, e2 with
| {expression_desc = Int_of_boolean e1;_} ,
{expression_desc = Int_of_boolean e2;_} ->
match e1.expression_desc, e2.expression_desc with
| Int_of_boolean e1 , Int_of_boolean e2
->
or_ ?comment e1 e2
| {expression_desc = Int_of_boolean e1;_} ,
e2 -> or_ ?comment e1 e2
| e1, {expression_desc = Int_of_boolean e2;_}
| Int_of_boolean e1 , _ -> or_ ?comment e1 e2
| _, Int_of_boolean e2
-> or_ ?comment e1 e2
| e1, e2 ->
| Var i, Var j when Js_op_util.same_vident i j
->
to_ocaml_boolean e1
| Var i,
(Bin (Or, {expression_desc = Var j ; _}, _)
| Bin (Or , _, {expression_desc = Var j ; _}))
when Js_op_util.same_vident i j
-> to_ocaml_boolean e2
| _, _ ->
to_ocaml_boolean @@ bin ?comment Or e1 e2

let string_of_small_int_array ?comment xs : t =
Expand Down Expand Up @@ -594,8 +612,21 @@ module Exp = struct

let string_comp cmp ?comment e0 e1 =
to_ocaml_boolean @@ bin ?comment cmp e0 e1
let int_comp cmp ?comment e0 e1 =
to_ocaml_boolean @@ bin ?comment (Lam_compile_util.jsop_of_comp cmp) e0 e1


let rec int_comp (cmp : Lambda.comparison) ?comment (e0 : t) (e1 : t) =
match cmp, e0.expression_desc, e1.expression_desc with
| _, Call ({
expression_desc =
Var (Qualified
(_, Runtime,
Some ("caml_int_compare" | "caml_int32_compare"))); _},
[l;r], _),
Number (Int {i = 0})
-> int_comp cmp l r (* = 0 > 0 < 0 *)
| _ ->
to_ocaml_boolean @@ bin ?comment (Lam_compile_util.jsop_of_comp cmp) e0 e1

let float_comp cmp ?comment e0 e1 =
to_ocaml_boolean @@ bin ?comment (Lam_compile_util.jsop_of_comp cmp) e0 e1

Expand Down
3 changes: 3 additions & 0 deletions jscomp/js_helper.mli
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,10 @@ module Exp : sig
val assign : binary_op

val triple_equal : binary_op
(* TODO: reduce [triple_equal] use *)

val float_equal : binary_op
val int_equal : binary_op
val string_equal : binary_op
val is_type_number : unary_op
val typeof : unary_op
Expand Down
9 changes: 9 additions & 0 deletions jscomp/js_map.ml
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,15 @@ class virtual map =
just print `A.length` - it's guarateed to be unique

when the third one is None, it means the whole module

TODO:
invariant, when [kind] is [Runtime], then we can ignore [ident],
since all [runtime] functions are unique, when do the
pattern match we can ignore the first one for simplicity
for example
{[
Qualified (_, Runtime, Some "caml_int_compare")
]}
*)
(* used in [js_create_array] primitive, note having
uninitilized array is not as bad as in ocaml,
Expand Down
30 changes: 27 additions & 3 deletions jscomp/lam_analysis.ml
Original file line number Diff line number Diff line change
Expand Up @@ -215,9 +215,13 @@ let rec size (lam : Lambda.lambda) =
try
match lam with
| Lvar _ -> 1
| Lconst _ -> 1 (* Modify *)
| Lconst c -> size_constant c
| Llet(_, _, l1, l2) -> 1 + size l1 + size l2
| Lletrec _ -> really_big ()
| Lprim(Pfield _, [Lprim(Pgetglobal _, [ ])])
-> 1
| Lprim (Praise _, [l ])
-> size l
| Lprim(_, ll) -> size_lams 1 ll

(** complicated
Expand All @@ -230,7 +234,8 @@ let rec size (lam : Lambda.lambda) =
*)
| Lapply(f,
args, _) -> size_lams (size f) args
| Lfunction(_, params, l) -> really_big ()
(* | Lfunction(_, params, l) -> really_big () *)
| Lfunction(_,_params,body) -> size body
| Lswitch(_, _) -> really_big ()
| Lstringswitch(_,_,_) -> really_big ()
| Lstaticraise (i,ls) ->
Expand All @@ -246,11 +251,21 @@ let rec size (lam : Lambda.lambda) =
| Levent(l, _) -> size l
| Lifused(v, l) -> size l
with Too_big_to_inline -> 1000
and size_constant x =
match x with
| Const_base _
| Const_immstring _
| Const_pointer _
-> 1
| Const_block (_, _, str)
-> List.fold_left (fun acc x -> acc + size_constant x ) 0 str
| Const_float_array xs -> List.length xs

and size_lams acc (lams : Lambda.lambda list) =
List.fold_left (fun acc l -> acc + size l ) acc lams


let exit_inline_size = 7
let small_inline_size = 5
(* compared two lambdas in case analysis, note that we only compare some small lambdas
Actually this patten is quite common in GADT, people have to write duplicated code
due to the type system restriction
Expand Down Expand Up @@ -289,3 +304,12 @@ and eq_primitive (p : Lambda.primitive) (p1 : Lambda.primitive) =
| _ , _ ->
(* FIXME: relies on structure equality *)
try p = p1 with _ -> false


let is_closed_by map lam =
Lambda.IdentSet.for_all Ident.global
(Lambda.IdentSet.diff (Lambda.free_variables lam) map )


let is_closed lam =
Lambda.IdentSet.for_all Ident.global (Lambda.free_variables lam)
10 changes: 10 additions & 0 deletions jscomp/lam_analysis.mli
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,13 @@ val eq_lambda : Lambda.lambda -> Lambda.lambda -> bool
for looking for similar cases in switch
*)

(** [is_closed_by map lam]
return [true] if all unbound variables
belongs to the given [map] *)
val is_closed_by : Lambda.IdentSet.t -> Lambda.lambda -> bool

val is_closed : Lambda.lambda -> bool


val small_inline_size : int
val exit_inline_size : int
Loading