|
@@ -107,6 +107,15 @@ and inline_object_field =
|
|
|
| IOFInlineVar of inline_var
|
|
|
| IOFNone
|
|
|
|
|
|
+(*
|
|
|
+ inline_expression_handled
|
|
|
+ Defines what will happen to the expression being analized by analyze_aliases
|
|
|
+*)
|
|
|
+and inline_expression_handled =
|
|
|
+ | IEHCaptured (* The expression will be assigned to a variable *)
|
|
|
+ | IEHIgnored (* The result of the expression will not be used *)
|
|
|
+ | IEHNotHandled (* Cases that are not handled (usually leads to cancelling inlining *)
|
|
|
+
|
|
|
let inline_constructors ctx original_e =
|
|
|
let inline_objs = ref IntMap.empty in
|
|
|
let vars = ref IntMap.empty in
|
|
@@ -259,7 +268,7 @@ let inline_constructors ctx original_e =
|
|
|
|
|
|
e: The expression to analyze
|
|
|
*)
|
|
|
- let rec analyze_aliases (seen_ctors:tclass_field list) (captured:bool) (is_lvalue:bool) (e:texpr) : inline_var option =
|
|
|
+ let rec analyze_aliases (seen_ctors:tclass_field list) (captured:inline_expression_handled) (is_lvalue:bool) (e:texpr) : inline_var option =
|
|
|
let mk_io ?(has_untyped=false) (iok : inline_object_kind) (id:int) (expr:texpr) : inline_object =
|
|
|
let io = {
|
|
|
io_kind = iok;
|
|
@@ -297,8 +306,8 @@ let inline_constructors ctx original_e =
|
|
|
| _ -> None
|
|
|
end
|
|
|
in
|
|
|
- let handle_field_case ?(captured=false) ?(is_lvalue=false) efield ethis fname validate_io : inline_object_field =
|
|
|
- begin match analyze_aliases true ethis with
|
|
|
+ let handle_field_case ?(captured=IEHNotHandled) ?(is_lvalue=false) efield ethis fname validate_io : inline_object_field =
|
|
|
+ begin match analyze_aliases IEHCaptured ethis with
|
|
|
| Some({iv_state = IVSAliasing io} as iv) when validate_io io ->
|
|
|
begin match get_io_inline_method io fname with
|
|
|
| Some(c, tl, cf, tf)->
|
|
@@ -321,7 +330,7 @@ let inline_constructors ctx original_e =
|
|
|
warning ctx WConstructorInliningCancelled ("Constructor inlining cancelled because of use of uninitialized member field " ^ fname) ethis.epos;
|
|
|
raise Not_found
|
|
|
);
|
|
|
- if not captured then cancel_iv fiv efield.epos;
|
|
|
+ if captured == IEHNotHandled then cancel_iv fiv efield.epos;
|
|
|
IOFInlineVar(fiv)
|
|
|
with Not_found ->
|
|
|
cancel_iv iv efield.epos;
|
|
@@ -343,7 +352,7 @@ let inline_constructors ctx original_e =
|
|
|
let handle_default_case e =
|
|
|
let old = !scoped_ivs in
|
|
|
scoped_ivs := [];
|
|
|
- let f e = ignore(analyze_aliases false e) in
|
|
|
+ let f e = ignore(analyze_aliases IEHNotHandled e) in
|
|
|
Type.iter f e;
|
|
|
List.iter (fun iv -> iv.iv_closed <- true) !scoped_ivs;
|
|
|
scoped_ivs := old;
|
|
@@ -357,7 +366,7 @@ let inline_constructors ctx original_e =
|
|
|
| _ ->
|
|
|
let v = alloc_var VGenerated "arg" e.etype e.epos in
|
|
|
let decle = mk (TVar(v, Some e)) ctx.t.tvoid e.epos in
|
|
|
- ignore(analyze_aliases true decle);
|
|
|
+ ignore(analyze_aliases IEHIgnored decle);
|
|
|
let mde = (Meta.InlineConstructorArgument (v.v_id, 0)), [], e.epos in
|
|
|
let e = mk (TMeta(mde, e)) e.etype e.epos in
|
|
|
loop (v::vs, e::es) el
|
|
@@ -369,7 +378,7 @@ let inline_constructors ctx original_e =
|
|
|
let handle_inline_object_case (io_id:int) (force_inline:bool) (e:texpr) =
|
|
|
match e.eexpr, e.etype with
|
|
|
| TNew({ cl_constructor = Some ({cf_expr = Some ({eexpr = TFunction tf})} as cf)} as c,tl,pl),_
|
|
|
- when captured && not (List.memq cf seen_ctors) ->
|
|
|
+ when captured!=IEHNotHandled && not (List.memq cf seen_ctors) ->
|
|
|
begin
|
|
|
let argvs, pl = analyze_call_args pl in
|
|
|
let _, cname = c.cl_path in
|
|
@@ -395,12 +404,12 @@ let inline_constructors ctx original_e =
|
|
|
in loop c tl;
|
|
|
let iv = add v IVKLocal in
|
|
|
set_iv_alias iv io;
|
|
|
- ignore(analyze_aliases_in_ctor cf true io.io_expr);
|
|
|
+ ignore(analyze_aliases_in_ctor cf IEHIgnored io.io_expr);
|
|
|
Some iv
|
|
|
end
|
|
|
| TNew({ cl_constructor = Some ({cf_kind = Method MethInline; cf_expr = Some _} as cf)} as c,_,pl),_ when is_extern_ctor c cf ->
|
|
|
raise_typing_error "Extern constructor could not be inlined" e.epos;
|
|
|
- | TObjectDecl fl, _ when captured && fl <> [] && List.for_all (fun((s,_,_),_) -> Lexer.is_valid_identifier s) fl ->
|
|
|
+ | TObjectDecl fl, _ when captured!=IEHNotHandled && fl <> [] && List.for_all (fun((s,_,_),_) -> Lexer.is_valid_identifier s) fl ->
|
|
|
let v = alloc_var VGenerated "inlobj" e.etype e.epos in
|
|
|
let ev = mk (TLocal v) v.v_type e.epos in
|
|
|
let el = List.map (fun ((s,_,_),e) ->
|
|
@@ -413,9 +422,9 @@ let inline_constructors ctx original_e =
|
|
|
List.iter (fun ((s,_,_),e) -> ignore(alloc_io_field io s e.etype v.v_pos)) fl;
|
|
|
let iv = add v IVKLocal in
|
|
|
set_iv_alias iv io;
|
|
|
- List.iter (fun e -> ignore(analyze_aliases true e)) el;
|
|
|
+ List.iter (fun e -> ignore(analyze_aliases IEHIgnored e)) el;
|
|
|
Some iv
|
|
|
- | TArrayDecl el, TInst(_, [elemtype]) when captured ->
|
|
|
+ | TArrayDecl el, TInst(_, [elemtype]) when captured!=IEHNotHandled ->
|
|
|
let len = List.length el in
|
|
|
let v = alloc_var VGenerated "inlarr" e.etype e.epos in
|
|
|
let ev = mk (TLocal v) v.v_type e.epos in
|
|
@@ -429,7 +438,7 @@ let inline_constructors ctx original_e =
|
|
|
for i = 0 to len-1 do ignore(alloc_io_field io (int_field_name i) elemtype v.v_pos) done;
|
|
|
let iv = add v IVKLocal in
|
|
|
set_iv_alias iv io;
|
|
|
- List.iter (fun e -> ignore(analyze_aliases true e)) el;
|
|
|
+ List.iter (fun e -> ignore(analyze_aliases IEHIgnored e)) el;
|
|
|
Some iv
|
|
|
| _ ->
|
|
|
handle_default_case e
|
|
@@ -443,7 +452,7 @@ let inline_constructors ctx original_e =
|
|
|
handle_inline_object_case io_id false e
|
|
|
| TVar(v,None) -> ignore(add v IVKLocal); None
|
|
|
| TVar(v,Some rve) ->
|
|
|
- begin match analyze_aliases true rve with
|
|
|
+ begin match analyze_aliases IEHCaptured rve with
|
|
|
| Some({iv_state = IVSAliasing(io)}) ->
|
|
|
let iv = add v IVKLocal in
|
|
|
set_iv_alias iv io;
|
|
@@ -453,15 +462,15 @@ let inline_constructors ctx original_e =
|
|
|
| TBinop(OpAssign, lve, rve) ->
|
|
|
begin match analyze_aliases_in_lvalue lve with
|
|
|
| Some({iv_state = IVSUnassigned} as iv) ->
|
|
|
- begin match analyze_aliases true rve with
|
|
|
+ begin match analyze_aliases IEHCaptured rve with
|
|
|
| Some({iv_state = IVSAliasing(io)}) ->
|
|
|
scoped_ivs := iv :: !scoped_ivs;
|
|
|
set_iv_alias iv io
|
|
|
| _ -> cancel_iv iv lve.epos
|
|
|
end;
|
|
|
Some iv
|
|
|
- | Some(iv) -> cancel_iv iv e.epos; ignore(analyze_aliases false rve); None
|
|
|
- | _ -> ignore(analyze_aliases false rve); None
|
|
|
+ | Some(iv) -> cancel_iv iv e.epos; ignore(analyze_aliases IEHNotHandled rve); None
|
|
|
+ | _ -> ignore(analyze_aliases IEHNotHandled rve); None
|
|
|
end
|
|
|
| TField(ethis, fa) ->
|
|
|
handle_field_case_no_methods e ethis (field_name fa) (fun _ -> true)
|
|
@@ -471,19 +480,19 @@ let inline_constructors ctx original_e =
|
|
|
handle_field_case_no_methods e ethis (int_field_name i) validate_io
|
|
|
| TLocal(v) when v.v_id < 0 ->
|
|
|
let iv = get_iv v.v_id in
|
|
|
- if iv.iv_closed || not captured then cancel_iv iv e.epos;
|
|
|
+ if iv.iv_closed || captured==IEHNotHandled then cancel_iv iv e.epos;
|
|
|
Some iv
|
|
|
| TBlock(el) ->
|
|
|
let rec loop = function
|
|
|
| [e] -> analyze_aliases captured e
|
|
|
- | e::el -> ignore(analyze_aliases true e); loop (el)
|
|
|
+ | e::el -> ignore(analyze_aliases IEHIgnored e); loop (el)
|
|
|
| [] -> None
|
|
|
in loop el
|
|
|
| TMeta((Meta.InlineConstructorArgument (vid,_),_,_),_) ->
|
|
|
(* The contents have already been analyzed, so we must skip the wrapped expression *)
|
|
|
(try
|
|
|
let iv = get_iv vid in
|
|
|
- if iv.iv_closed || not captured then cancel_iv iv e.epos;
|
|
|
+ if iv.iv_closed || captured==IEHNotHandled then cancel_iv iv e.epos;
|
|
|
Some(get_iv vid)
|
|
|
with Not_found -> None)
|
|
|
| TParenthesis e | TMeta(_,e) | TCast(e,None) ->
|
|
@@ -517,14 +526,32 @@ let inline_constructors ctx original_e =
|
|
|
end
|
|
|
| IOFInlineVar(iv) ->
|
|
|
cancel_iv iv e.epos;
|
|
|
- List.iter (fun ca -> ignore(analyze_aliases false ca)) call_args;
|
|
|
+ List.iter (fun ca -> ignore(analyze_aliases IEHNotHandled ca)) call_args;
|
|
|
None
|
|
|
| IOFNone ->
|
|
|
- List.iter (fun ca -> ignore(analyze_aliases false ca)) call_args;
|
|
|
+ List.iter (fun ca -> ignore(analyze_aliases IEHNotHandled ca)) call_args;
|
|
|
None
|
|
|
end
|
|
|
| TFunction tf ->
|
|
|
- analyze_aliases true tf.tf_expr
|
|
|
+ let old = !scoped_ivs in
|
|
|
+ scoped_ivs := [];
|
|
|
+ ignore(analyze_aliases IEHIgnored tf.tf_expr);
|
|
|
+ List.iter (fun iv -> iv.iv_closed <- true) !scoped_ivs;
|
|
|
+ scoped_ivs := old;
|
|
|
+ None
|
|
|
+ | TWhile(condition, body, _) ->
|
|
|
+ ignore(analyze_aliases IEHNotHandled condition);
|
|
|
+ ignore(analyze_aliases IEHIgnored body);
|
|
|
+ None
|
|
|
+ | TIf (e,e1,e2) when captured=IEHIgnored ->
|
|
|
+ ignore(analyze_aliases IEHNotHandled e);
|
|
|
+ ignore(analyze_aliases IEHIgnored e1);
|
|
|
+ (match e2 with None -> () | Some e -> ignore(analyze_aliases IEHIgnored e));
|
|
|
+ None
|
|
|
+ | TTry (e,catches) when captured==IEHIgnored ->
|
|
|
+ ignore(analyze_aliases IEHIgnored e);
|
|
|
+ List.iter (fun (_,e) -> ignore(analyze_aliases IEHIgnored e)) catches;
|
|
|
+ None
|
|
|
| _ ->
|
|
|
handle_default_case e
|
|
|
in
|
|
@@ -690,7 +717,7 @@ let inline_constructors ctx original_e =
|
|
|
in
|
|
|
if not (check_for_ctors original_e) then original_e else
|
|
|
let e = mark_ctors original_e in
|
|
|
- ignore(analyze_aliases [] false false e);
|
|
|
+ ignore(analyze_aliases [] IEHNotHandled false e);
|
|
|
if IntMap.for_all (fun _ io -> io.io_cancelled) !inline_objs then begin
|
|
|
IntMap.iter (fun _ iv -> let v = iv.iv_var in if v.v_id < 0 then v.v_id <- -v.v_id ) !vars;
|
|
|
original_e
|