Skip to content

Commit

Permalink
[js] optimize Std.is for common types
Browse files Browse the repository at this point in the history
  • Loading branch information
nadako committed Jan 18, 2014
1 parent 532fbbf commit dd8c8be
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 0 deletions.
18 changes: 18 additions & 0 deletions genjs.ml
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,24 @@ let rec gen_call ctx e el in_value =
print ctx " instanceof ";
gen_value ctx t;
spr ctx ")";
| TLocal { v_name = "__typeof__" }, [o] ->
spr ctx "typeof(";
gen_value ctx o;
spr ctx ")";
| TLocal { v_name = "__strict_eq__" } , [x;y] ->
(* add extra parenthesis here because of operator precedence *)
spr ctx "((";
gen_value ctx x;
spr ctx ") === ";
gen_value ctx y;
spr ctx ")";
| TLocal { v_name = "__strict_neq__" } , [x;y] ->
(* add extra parenthesis here because of operator precedence *)
spr ctx "((";
gen_value ctx x;
spr ctx ") !== ";
gen_value ctx y;
spr ctx ")";
| TLocal ({v_name = "__define_feature__"}), [_;e] ->
gen_expr ctx e
| TLocal { v_name = "__feature__" }, { eexpr = TConst (TString f) } :: eif :: eelse ->
Expand Down
39 changes: 39 additions & 0 deletions optimizer.ml
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,45 @@ let api_inline ctx c field params p =
Some stringv
| _ ->
None)
| ([],"Std"),"is",[o;t] | (["js"],"Boot"),"__instanceof",[o;t] when ctx.com.platform = Js ->
let mk_local ctx n t pos = mk (TLocal (try PMap.find n ctx.locals with _ -> add_local ctx n t)) t pos in

let tstring = ctx.com.basic.tstring in
let tbool = ctx.com.basic.tbool in
let tint = ctx.com.basic.tint in

let is_trivial e =
match e.eexpr with
| TConst _ | TLocal _ -> true
| _ -> false
in

let typeof t =
let tof = mk_local ctx "__typeof__" (tfun [o.etype] tstring) p in
let tof = mk (TCall (tof, [o])) tstring p in
mk (TBinop (Ast.OpEq, tof, (mk (TConst (TString t)) tstring p))) tbool p
in

(match t.eexpr with
(* generate simple typeof checks for basic types *)
| TTypeExpr (TClassDecl ({ cl_path = [],"String" })) -> Some (typeof "string")
| TTypeExpr (TAbstractDecl ({ a_path = [],"Bool" })) -> Some (typeof "boolean")
| TTypeExpr (TAbstractDecl ({ a_path = [],"Float" })) -> Some (typeof "number")
| TTypeExpr (TAbstractDecl ({ a_path = [],"Int" })) when is_trivial o ->
(* generate (o|0) === o check *)
let teq = mk_local ctx "__strict_eq__" (tfun [tint; tint] tbool) p in
let lhs = mk (TBinop (Ast.OpOr, o, mk (TConst (TInt Int32.zero)) tint p)) tint p in
Some (mk (TCall (teq, [lhs; o])) tbool p)
| TTypeExpr (TClassDecl ({ cl_path = [],"Array" })) ->
(* generate (o instanceof Array) && o.__enum__ == null check *)
let iof = mk_local ctx "__instanceof__" (tfun [o.etype;t.etype] tbool) p in
let iof = mk (TCall (iof, [o; t])) tbool p in
let enum = mk (TField (o, FDynamic "__enum__")) (mk_mono()) p in
let null = mk (TConst TNull) (mk_mono()) p in
let not_enum = mk (TBinop (Ast.OpEq, enum, null)) tbool p in
Some (mk (TBinop (Ast.OpBoolAnd, iof, not_enum)) tbool p)
| _ ->
None)
| ([],"Std"),"int",[{ eexpr = TConst (TFloat f) }] ->
let f = float_of_string f in
(match classify_float f with
Expand Down
8 changes: 8 additions & 0 deletions tests/unit/unitstd/Std.unit.hx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ Std.is(unknown, String) == false;
Std.is(null, String) == false;
Std.is("foo", null) == false;

Std.is("", String) == true;
Std.is(false, Bool) == true;
Std.is(1, Int) == true;
Std.is(1.5, Int) == false;
Std.is(1.5, Float) == true;
Std.is([], Array) == true;
Std.is(unit.MyEnum.A, Array) == false;

// instance
#if !js
Std.instance("", String) == "";
Expand Down

0 comments on commit dd8c8be

Please sign in to comment.