Browse Source

optimized Type.enumIndex(E) and Type.enumIndex(E(a,b,c)) when no side effects

Nicolas Cannasse 13 years ago
parent
commit
dd0a7778b1
1 changed files with 42 additions and 0 deletions
  1. 42 0
      optimizer.ml

+ 42 - 0
optimizer.ml

@@ -21,6 +21,33 @@ open Type
 open Common
 open Typecore
 
+(* ---------------------------------------------------------------------- *)
+(* API OPTIMIZATIONS *)
+
+let has_side_effect e =
+	let rec loop e =
+		match e.eexpr with
+		| TConst _ | TLocal _ | TEnumField _ | TTypeExpr _ | TFunction _ -> ()
+		| TMatch _ | TNew _ | TCall _ | TClosure _ | TField _ | TArray _ | TBinop ((OpAssignOp _ | OpAssign),_,_) | TUnop ((Increment|Decrement),_,_) -> raise Exit
+		| TReturn _ | TBreak | TContinue | TThrow _ | TCast (_,Some _) -> raise Exit
+		| TCast (_,None) | TBinop _ | TUnop _ | TParenthesis _ | TWhile _ | TFor _ | TIf _ | TTry _ | TSwitch _ | TArrayDecl _ | TVars _ | TBlock _ | TObjectDecl _ -> Type.iter loop e
+	in
+	try
+		loop e; false
+	with Exit ->
+		true
+
+let api_inline ctx c field params p =
+	match c.cl_path, field, params with
+	| ([],"Type"),"enumIndex",[{ eexpr = TEnumField (en,f) }] ->
+		let c = (try PMap.find f en.e_constrs with Not_found -> assert false) in
+		Some (mk (TConst (TInt (Int32.of_int c.ef_index))) ctx.t.tint p)
+	| ([],"Type"),"enumIndex",[{ eexpr = TCall({ eexpr = TEnumField (en,f) },pl) }] when List.for_all (fun e -> not (has_side_effect e)) pl ->
+		let c = (try PMap.find f en.e_constrs with Not_found -> assert false) in
+		Some (mk (TConst (TInt (Int32.of_int c.ef_index))) ctx.t.tint p)
+	| _ ->
+		None
+
 (* ---------------------------------------------------------------------- *)
 (* INLINING *)
 
@@ -32,6 +59,17 @@ type in_local = {
 }
 
 let rec type_inline ctx cf f ethis params tret p force =
+	(* perform some specific optimization before we inline the call since it's not possible to detect at final optimization time *)
+	try
+		let cl = (match follow ethis.etype with
+			| TInst (c,_) -> c
+			| TAnon a -> (match !(a.a_status) with Statics c -> c | _ -> raise Exit)
+			| _ -> raise Exit
+		) in
+		(match api_inline ctx cl cf.cf_name params p with
+		| None -> raise Exit
+		| Some e -> Some e)
+	with Exit ->
 	(* type substitution on both class and function type parameters *)
 	let has_params, map_type =
 		let rec get_params c pl =
@@ -698,6 +736,10 @@ let rec reduce_loop ctx e =
 				e
 		| _ -> e
 		)
+	| TCall ({ eexpr = TField ({ eexpr = TTypeExpr (TClassDecl c) },field) },params) ->
+		(match api_inline ctx c field params e.epos with
+		| None -> reduce_expr ctx e
+		| Some e -> reduce_loop ctx e)
 	| TCall ({ eexpr = TFunction func } as ef,el) ->
 		let cf = mk_field "" ef.etype e.epos in
 		let ethis = mk (TConst TThis) t_dynamic e.epos in