ソースを参照

First pass at experimental optimization, -D js_flatten.

It generates the class hierarchy as "flat" as possible without using
nested objects. This allows JS minifiers to compress classes down to one
letter, and seems to run quite a bit faster too:
http://jsperf.com/class-declaration
Bruno Garcia 12 年 前
コミット
35fad93378
2 ファイル変更22 行追加7 行削除
  1. 2 0
      common.ml
  2. 20 7
      genjs.ml

+ 2 - 0
common.ml

@@ -172,6 +172,7 @@ module Define = struct
 		| Interp
 		| JavaVer
 		| JsClassic
+		| JsFlatten
 		| Macro
 		| MacroTimes
 		| NekoSource
@@ -233,6 +234,7 @@ module Define = struct
 		| Interp -> ("interp","The code is compiled to be run with --interp")
 		| JavaVer -> ("java_ver", "<version:5-7> Sets the Java version to be targeted")
 		| JsClassic -> ("js_classic","Don't use a function wrapper and strict mode in JS output")
+		| JsFlatten -> ("js_flatten","Generate classes to use fewer object property lookups")
 		| Macro -> ("macro","Defined when we compile code in the macro context")
 		| MacroTimes -> ("macro_times","Display per-macro timing when used with --times")
 		| NekoSource -> ("neko_source","Output neko source instead of bytecode")

+ 20 - 7
genjs.ml

@@ -45,6 +45,7 @@ type ctx = {
 	packages : (string list,unit) Hashtbl.t;
 	smap : sourcemap;
 	js_modern : bool;
+	js_flatten : bool;
 	mutable current : tclass;
 	mutable statics : (tclass * string * texpr) list;
 	mutable inits : texpr list;
@@ -58,7 +59,9 @@ type ctx = {
 	mutable found_expose : bool;
 }
 
-let s_path ctx = Ast.s_type_path
+let dot_path = Ast.s_type_path
+let flat_path (p,s) = match p with [] -> s | _ -> String.concat "_" p ^ "_" ^ s
+let s_path ctx = if ctx.js_flatten then flat_path else dot_path
 
 let kwds =
 	let h = Hashtbl.create 0 in
@@ -898,18 +901,21 @@ let generate_class ctx c =
 	| [],"Function" -> error "This class redefine a native one" c.cl_pos
 	| _ -> ());
 	let p = s_path ctx c.cl_path in
-	generate_package_create ctx c.cl_path;
 	let hxClasses = has_feature ctx "Type.resolveClass" in
+	if ctx.js_flatten then
+		print ctx "var "
+	else
+		generate_package_create ctx c.cl_path;
 	if ctx.js_modern || not hxClasses then
 		print ctx "%s = " p
 	else
-		print ctx "%s = $hxClasses[\"%s\"] = " p p;
+		print ctx "%s = $hxClasses[\"%s\"] = " p (dot_path c.cl_path);
 	(match c.cl_constructor with
 	| Some { cf_expr = Some e } -> gen_expr ctx e
 	| _ -> print ctx "function() { }");
 	newline ctx;
 	if ctx.js_modern && hxClasses then begin
-		print ctx "$hxClasses[\"%s\"] = %s" p p;
+		print ctx "$hxClasses[\"%s\"] = %s" (dot_path c.cl_path) p;
 		newline ctx;
 	end;
 	handle_expose ctx p c.cl_meta;
@@ -983,10 +989,13 @@ let generate_class ctx c =
 
 let generate_enum ctx e =
 	let p = s_path ctx e.e_path in
-	generate_package_create ctx e.e_path;
 	let ename = List.map (fun s -> Printf.sprintf "\"%s\"" (Ast.s_escape s)) (fst e.e_path @ [snd e.e_path]) in
+	if ctx.js_flatten then
+		print ctx "var "
+	else
+		generate_package_create ctx e.e_path;
 	print ctx "%s = " p;
-	if has_feature ctx "Type.resolveEnum" then print ctx "$hxClasses[\"%s\"] = " p;
+	if has_feature ctx "Type.resolveEnum" then print ctx "$hxClasses[\"%s\"] = " (dot_path e.e_path);
 	print ctx "{";
 	if has_feature ctx "js.Boot.isEnum" then print ctx " __ename__ : %s," (if has_feature ctx "Type.getEnumName" then "[" ^ String.concat "," ename ^ "]" else "true");
 	print ctx " __constructs__ : [%s] }" (String.concat "," (List.map (fun s -> Printf.sprintf "\"%s\"" s) e.e_names));
@@ -1025,7 +1034,10 @@ let generate_type ctx = function
 		| None -> ()
 		| Some e ->
 			ctx.inits <- e :: ctx.inits);
-		if not c.cl_extern then generate_class ctx c else if Meta.has Meta.InitPackage c.cl_meta then generate_package_create ctx c.cl_path
+		if not c.cl_extern then
+			generate_class ctx c
+		else if not ctx.js_flatten && Meta.has Meta.InitPackage c.cl_meta then
+			generate_package_create ctx c.cl_path
 	| TEnumDecl e when e.e_extern ->
 		()
 	| TEnumDecl e -> generate_enum ctx e
@@ -1051,6 +1063,7 @@ let alloc_ctx com =
 			mappings = Buffer.create 16;
 		};
 		js_modern = not (Common.defined com Define.JsClassic);
+		js_flatten = Common.defined com Define.JsFlatten;
 		statics = [];
 		inits = [];
 		current = null_class;