Skip to content

Commit

Permalink
Merge pull request #9 from lijunsong/redo-const
Browse files Browse the repository at this point in the history
Redo const
  • Loading branch information
lijunsong committed Feb 19, 2015
2 parents f2266e0 + e238baa commit df11c09
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 369 deletions.
182 changes: 13 additions & 169 deletions src/optimization/ljs_fold_const.ml
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,6 @@ open Ljs_syntax
open Ljs_opt
module EU = Exp_util

(* Optimization phase
*
* constant folding will fold two constant into one, in place.
*)

(* TODO: should the opt phase check type error? e.g.
to check the op1 args has the right type for op1.
*)
Expand All @@ -22,111 +17,6 @@ let fold_const_op1 (p : Pos.t) (op : string) (e : exp) : exp option =
let fold_const_op2 (p : Pos.t) (op : string) (e1 : exp) (e2 : exp) : exp option =
EU.apply_op2 p op e1 e2

(* function for extracting property of one field *)
let rec get_obj_field (obj : exp) (name : string) (look_proto: bool) : prop option =
let rec get_field_rec (name : string) (obj_fields : (string * prop) list) : prop option =
match obj_fields with
| (fld_name, p) :: rest ->
if (fld_name = name)
then Some p
else get_field_rec name rest
| [] -> None
in
match obj with
| Object (_, attrs, strprop) ->
let cur_result = get_field_rec name strprop in
let { primval=_;proto=proto;code=_;extensible = _;klass=_ } = attrs in
begin
match cur_result, look_proto with
| Some (_), _ -> cur_result
| None, true ->
begin
match proto with
| Some (proto_obj) -> get_obj_field proto_obj name look_proto
| None -> None
end
| None, false -> None
end
| Null _ -> None
| _ -> EU.print_ljs obj; failwith "get_obj_field can only be applied on constant object"

(* if
1. obj is a const object (no side effect)
2. field name is a const,
try to get the field and then its attr. to make sure the
partially evaluate exp GetAttr. This optimization can shink the code
only if the `obj` is an Object appearing only once in the code. substitute_const
will do that.
*)
let fold_const_getattr pos pattr obj field : exp =
let exp_bool (b : bool) : exp = match b with
| true -> True pos
| false -> False pos in

match obj, field with
| Object (_, _, strprop), String (_, name) ->
(* get field and its property *)
begin match get_obj_field obj name false with
| Some prop ->
begin
match pattr, prop with
| Value, Data ({value = v; writable=_}, _, _) -> v
| Writable, Data({value=_; writable=w}, _, _) -> exp_bool w
| Enum, Data(_, enum, _) -> exp_bool enum
| Config, Data (_, _, config) -> exp_bool config
| _ -> GetAttr(pos, pattr, obj, field) (* no optimization in other situations *)
end
| None -> Undefined pos (* if field is not in the object. don't optimize. *)
end
| _ -> GetAttr(pos, pattr, obj, field)

(* partially evaluate exp GetObjAttr only if
1. o is Object and
2. TODO: o does not have side effect
*)
let fold_const_getobjattr pos (oattr : oattr) o : exp =
match oattr, o with
| Klass, Object (_, {klass=klass}, _) -> String (pos, klass)
| Code, Object (_, {code=None}, _) -> Null pos
| Code, Object (_, {code=Some code}, _) -> code
| Extensible, Object (_, {extensible=true},_) -> True pos
| Extensible, Object (_, {extensible=false},_) -> False pos
| Proto, Object (_, {proto=Some proto}, _) -> proto
| Proto, Object (_, {proto=None}, _) -> Undefined pos
(* primval should not be None, if it is None, leave it as it is and let
interp issues an error on that. REF get_obj_attr in ljs_eval.ml *)
| Primval, Object (_, {primval=Some primval},_) -> primval
| _ -> GetObjAttr(pos, oattr, o)


let rec fold_const_getfield pos o f a =
match o, f with
| Object (_, attr, strprop), String (_, fld) ->
begin
let p = get_obj_field o fld true in
match p with
| None ->
begin
match attr with
| {proto=Some proto} ->
begin
match proto with
| Object (_,_,_) -> fold_const_getfield pos proto f a
| _ -> Undefined pos
end
| _ -> Undefined pos
end
| Some (Data ({value=v; writable=_},_,_)) -> v
| Some (Accessor ({getter=gt; setter=_},_,_)) -> App (pos, gt, [a])
end
| _ -> GetField (pos, o, f, a)


type env = exp IdMap.t

let rec fold_const_app pos lambda args =
Null pos

Expand All @@ -139,51 +29,18 @@ let rec fold_const (e : exp) : exp =
| True _
| False _
| Id (_, _) -> e

| GetAttr (p, pattr, obj, field) ->
let o = fold_const obj in
let f = fold_const field in
if EU.valid_for_folding o && EU.valid_for_folding f then
fold_const_getattr p pattr o f
else
GetAttr (p, pattr, o, f)

| GetObjAttr (p, oattr, obj) ->
let o = fold_const obj in
if EU.valid_for_folding o then
fold_const_getobjattr p oattr o
else
GetObjAttr (p, oattr, o)

| GetField (pos, obj, fld, args) ->
let o = fold_const obj in
let f = fold_const fld in
let a = fold_const args in
if EU.valid_for_folding o && EU.valid_for_folding f then
fold_const_getfield pos o f a
else
GetField (pos, o, f, a)

| Op1 (p, op, e) ->
let newe = fold_const e in
let v = fold_const_op1 p op newe in
begin
try
match v with
| Some (folded) -> folded
| None -> Op1 (p, op, newe)
with _ -> Op1 (p, op, newe)
end
begin match fold_const_op1 p op newe with
| Some (folded) -> folded
| None -> Op1 (p, op, newe)
end
| Op2 (p, op, e1, e2) ->
let newe1 = fold_const e1 in
let newe2 = fold_const e2 in
let v = fold_const_op2 p op newe1 newe2 in
begin
try
match v with
| Some (folded) -> folded
| None -> Op2 (p, op, newe1, newe2)
with _ -> Op2 (p, op, newe1, newe2)
begin match fold_const_op2 p op newe1 newe2 with
| Some (folded) -> folded
| None -> Op2 (p, op, newe1, newe2)
end
| If (p, cond, thn, els) ->
let c_val = fold_const cond in
Expand All @@ -204,25 +61,9 @@ let rec fold_const (e : exp) : exp =
If (p, c_val, t, e)
end
end
| App (p, func, args) ->
let f = fold_const func in
let args = List.map fold_const args in
if EU.valid_for_folding f && (List.for_all EU.valid_for_folding args) then
fold_const_app p f args
else
App (p, f, args)
| Label (p,l,lbody) ->
begin match lbody with
| Break (_, l', brk) ->
if l = l' then fold_const brk
else Label (p, l, fold_const lbody)
| _ -> Label (p, l, fold_const lbody)
end
| TryCatch (p,t,c) ->
if EU.valid_for_folding t then
fold_const t
else
TryCatch (p, fold_const t, fold_const c)
| GetAttr (_, _, _, _)
| GetObjAttr (_, _, _)
| GetField (_, _, _, _)
| Object (_,_,_)
| SetAttr (_,_,_,_,_)
| SetObjAttr (_,_,_,_)
Expand All @@ -234,6 +75,9 @@ let rec fold_const (e : exp) : exp =
| Seq (_,_,_)
| Let (_,_,_,_)
| Rec (_,_,_,_)
| App (_, _, _)
| Label (_, _, _)
| TryCatch (_, _, _)
| Break (_,_,_)
| TryFinally (_,_,_)
| Throw (_,_)
Expand Down
Loading

0 comments on commit df11c09

Please sign in to comment.