Просмотр исходного кода

Improve optimisations of Std.is and also Std.string now too.

Luca Deltodesco 12 лет назад
Родитель
Сommit
361a2b95fd
5 измененных файлов с 57 добавлено и 35 удалено
  1. 38 22
      genjs.ml
  2. 1 1
      libs
  3. 11 5
      main.ml
  4. 4 4
      std/js/Boot.hx
  5. 3 3
      std/js/_std/Std.hx

+ 38 - 22
genjs.ml

@@ -1140,45 +1140,61 @@ let gen_single_expr ctx e expr =
 let mk_local tctx n t pos =
 	mk (TLocal (try PMap.find n tctx.locals with _ -> add_local tctx n t)) t pos
 
-let optimize_stdis tctx truth equal triple o t recurse =
+let optimize_stdis tctx equal triple o t recurse =
 	let pos = o.epos in
 	let stringt = tctx.Typecore.com.basic.tstring in
 	let boolt = tctx.Typecore.com.basic.tbool in
 	let intt = tctx.Typecore.com.basic.tint in
-	let ctypeof = mk (TConst (TString "typeof")) stringt pos in
-	let js = mk_local tctx "__js__" (tfun [stringt] (tfun [o.etype] stringt)) pos in
-	let typeof = mk (TCall (js, [ctypeof])) (tfun [o.etype] stringt) pos in
-	let gettof = mk (TCall (typeof, [o])) stringt pos in
-	match t.eexpr with
-		| TTypeExpr (TAbstractDecl ({ a_path = [],"Dynamic" })) ->
-			mk (TConst (TBool truth)) boolt pos
-		| TTypeExpr (TAbstractDecl ({ a_path = [],"Bool" })) ->
-			mk (TBinop (equal, gettof, (mk (TConst (TString "boolean")) stringt pos))) boolt pos
-		| TTypeExpr (TAbstractDecl ({ a_path = [],"Float" })) ->
-			mk (TBinop (equal, gettof, (mk (TConst (TString "number")) stringt pos))) boolt pos
-		| TTypeExpr (TClassDecl ({ cl_path = [],"String" })) ->
-			mk (TBinop (equal, gettof, (mk (TConst (TString "string")) stringt pos))) boolt pos
+	let tostring t = let pstring = mk_local tctx "$ObjectPrototypeToString" t_dynamic pos in
+					let pstring = mk (TField (pstring, FDynamic ("call"))) (tfun [o.etype] stringt) pos in
+					let psof = mk (TCall (pstring, [o])) stringt pos in
+					mk (TBinop (equal, psof, (mk (TConst (TString t)) stringt pos))) boolt pos
+	in match t.eexpr with
+		| TTypeExpr (TAbstractDecl ({ a_path = [],"Bool" })) -> tostring "[object Boolean]"
+		| TTypeExpr (TAbstractDecl ({ a_path = [],"Float" })) -> tostring "[object Number]"
+		| TTypeExpr (TClassDecl ({ cl_path = [],"String" })) -> tostring "[object String]"
 		| TTypeExpr (TAbstractDecl ({ a_path = [],"Int" })) ->
 			(* need to use ===/!==, not ==/!= so tast is a bit more annoying, we leave this to the generator *)
 			let teq = mk_local tctx triple (tfun [intt; intt] boolt) pos in
 			let lhs = mk (TBinop (Ast.OpOr, o, mk (TConst (TInt Int32.zero)) intt pos)) intt pos in
 			mk (TCall (teq, [lhs; o])) boolt pos
-		| TTypeExpr (TClassDecl ({ cl_path = [],"Array" })) ->
-			let pstring = mk_local tctx "$ObjectPrototypeToString" t_dynamic pos in
-			let pstring = mk (TField (pstring, FDynamic ("call"))) (tfun [o.etype] stringt) pos in
-			let psof = mk (TCall (pstring, [o])) stringt pos in
-			mk (TBinop (equal, psof, (mk (TConst (TString "[object Array]")) stringt pos))) boolt pos
+		| TTypeExpr (TClassDecl ({ cl_path = [],"Array" })) -> tostring "[object Array]"
+		| _ -> recurse
+
+let optimize_stdstring tctx v recurse =
+	let pos = v.epos in
+	let stringt = tctx.Typecore.com.basic.tstring in
+	let stringv = mk (TBinop (Ast.OpAdd, mk (TConst (TString "")) stringt pos, v)) stringt pos in
+	match (follow v.etype) with
+		| TInst ({ cl_path = [],"String" }, []) -> v
+		| TAbstract ({ a_path = [],"Float" }, []) -> stringv
+		| TAbstract ({ a_path = [],"Int" }, []) -> stringv
+		| TAbstract ({ a_path = [],"Bool" }, []) -> stringv
 		| _ -> recurse
 
 let rec optimize_call tctx e = let recurse = optimize tctx e in
 	match e.eexpr with
 	| TUnop (Ast.Not, _, { eexpr = TCall (ce, el) }) -> (match ce.eexpr, el with
-		| TField ({ eexpr = TTypeExpr (TClassDecl ({ cl_path = ["js"], "Boot" })) }, FStatic (_, ({ cf_name = "__instanceof" }))), [o;t] -> optimize_stdis tctx false Ast.OpNotEq "__js__tne" o t recurse
+		(* Catch Std.is call, even if it was inlined *)
+		| TField ({ eexpr = TTypeExpr (TClassDecl ({ cl_path = ["js"], "Boot" })) }, FStatic (_, ({ cf_name = "__instanceof" }))), [o;t] ->
+			optimize_stdis tctx Ast.OpNotEq "__js__tne" o t recurse
+		| TField ({ eexpr = TTypeExpr (TClassDecl ({ cl_path = [],"Std" })) }, FStatic (_, ({ cf_name = "is" }))), [o;t] ->
+			optimize_stdis tctx Ast.OpNotEq "__js__tne" o t recurse
 		| _ -> recurse)
 	| TCall (ce, el) -> (match ce.eexpr, el with
-		| TField ({ eexpr = TTypeExpr (TClassDecl ({ cl_path = ["js"], "Boot" })) }, FStatic (_, ({ cf_name = "__instanceof" }))), [o;t] -> optimize_stdis tctx true Ast.OpEq "__js__teq" o t recurse
+		(* Catch Std.is call, even if it was inlined *)
+		| TField ({ eexpr = TTypeExpr (TClassDecl ({ cl_path = ["js"], "Boot" })) }, FStatic (_, ({ cf_name = "__instanceof" }))), [o;t] ->
+			optimize_stdis tctx Ast.OpEq "__js__teq" o t recurse
+		| TField ({ eexpr = TTypeExpr (TClassDecl ({ cl_path = [],"Std" })) }, FStatic (_, ({ cf_name = "is" }))), [o;t] ->
+			optimize_stdis tctx Ast.OpEq "__js__teq" o t recurse
+		(* Catch Std.int when not inlined, if it was inlined there's no optimisation to be made *)
 		| TField ({ eexpr = TTypeExpr (TClassDecl ({ cl_path = [], "Std" })) }, FStatic (_, ({ cf_name = "int" }))), [v] ->
 			mk (TBinop (Ast.OpOr, v, mk (TConst (TInt Int32.zero)) tctx.Typecore.com.basic.tint v.epos)) tctx.Typecore.com.basic.tbool v.epos
+		(* Catch Std.string, even if it was inlined *)
+		| TField ({ eexpr = TTypeExpr (TClassDecl ({ cl_path = [], "Std" })) }, FStatic (_, ({ cf_name = "string" }))), [v] ->
+			optimize_stdstring tctx v recurse
+		| TField ({ eexpr = TTypeExpr (TClassDecl ({ cl_path = ["js"], "Boot" })) }, FStatic (_, ({ cf_name = "__string_rec" }))), [v; { eexpr = TConst (TString "") }] ->
+			optimize_stdstring tctx v recurse
 		| _ -> recurse)
 	| _ -> recurse
 
@@ -1206,7 +1222,7 @@ let generate com =
 				List.concat (class_shallows :: static_shallows)
 			| _ -> []
 		) com.types) in
-	let anyShallowExposed = shalows <> [] in
+	let anyShallowExposed = shallows <> [] in
 	let smap = ref (PMap.create String.compare) in
 	let shallowObject = { os_name = ""; os_fields = [] } in
 	List.iter (fun path -> (

+ 1 - 1
libs

@@ -1 +1 @@
-Subproject commit 97ddb4d99884042469e34d1be94b3605d51fbf43
+Subproject commit ff2e0f209eb9fcec663437e66b5f76b8e730130b

+ 11 - 5
main.ml

@@ -1214,14 +1214,20 @@ try
 		com.main <- main;
 		com.types <- types;
 		com.modules <- modules;
-		let platform_optimize = (match com.platform with
-			| Js -> Genjs.optimize
-			| _ -> fun ctx e -> e
-		) in
+		let foldMap = List.fold_left (fun f g x -> g (f x)) (fun x -> x) in
 		let filters = [
 			Codegen.Abstract.handle_abstract_casts tctx;
 			Codegen.promote_complex_rhs com;
-			if com.foptimize then (fun e -> Optimizer.reduce_expression tctx (platform_optimize tctx (Optimizer.inline_constructors tctx e))) else Optimizer.sanitize tctx;
+			if com.foptimize then foldMap (
+				let reduce_expression = Optimizer.reduce_expression tctx in
+				let inline_constructors = Optimizer.inline_constructors tctx in
+				match com.platform with
+					| Js -> [inline_constructors;
+							 Genjs.optimize tctx;
+							 reduce_expression]
+					| _ -> [inline_constructors;
+							reduce_expression]
+			) else Optimizer.sanitize tctx;
 			Codegen.check_local_vars_init;
 			Codegen.captured_vars com;
 			Codegen.rename_local_vars com;

+ 4 - 4
std/js/Boot.hx

@@ -166,11 +166,11 @@ class Boot {
 		case Int:
 			return (untyped __js__("(o|0) === o"));
 		case Float:
-			return (untyped __js__("typeof"))(o) == "number";
+			return (untyped __js__("$ObjectPrototypeToString")).call(o) == "[object Number]";
 		case Bool:
-			return (untyped __js__("typeof"))(o) == "boolean";
+			return (untyped __js__("$ObjectPrototypeToString")).call(o) == "[object Boolean]";
 		case String:
-			return (untyped __js__("typeof"))(o) == "string";
+			return (untyped __js__("$ObjectPrototypeToString")).call(o) == "[object String]";
 		case Dynamic:
 			return true;
 		default:
@@ -178,7 +178,7 @@ class Boot {
 				// Check if o is an instance of a Haxe class
 				if( (untyped __js__("typeof"))(cl) == "function" ) {
 					if( untyped __js__("o instanceof cl") ) {
-						if( cl == Array )
+						if( (untyped __js__("$ObjectPrototypeToString")).call(o) == "[object Array]" )
 							return (o.__enum__ == null);
 						return true;
 					}

+ 3 - 3
std/js/_std/Std.hx

@@ -24,7 +24,7 @@ import js.Boot;
 @:keepInit
 @:coreApi class Std {
 
-	public static inline function is( v : Dynamic, t : Dynamic ) : Bool {
+	public inline static function is( v : Dynamic, t : Dynamic ) : Bool {
 		return untyped js.Boot.__instanceof(v,t);
 	}
 
@@ -32,11 +32,11 @@ import js.Boot;
 		return untyped __instanceof__(v, c) ? cast v : null;
 	}
 
-	public static function string( s : Dynamic ) : String {
+	public inline static function string( s : Dynamic ) : String {
 		return untyped js.Boot.__string_rec(s,"");
 	}
 
-	public static inline function int( x : Float ) : Int {
+	public inline static function int( x : Float ) : Int {
 		return cast(x) | 0;
 	}