[vala] Add support for [Profile] method attribute



commit 8b5d74dceffec42c90ba74a457e2d1cb2e1c7fcd
Author: JÃrg Billeter <j bitron ch>
Date:   Fri Apr 20 14:05:15 2012 +0200

    Add support for [Profile] method attribute
    
    This allows simple method-level profiling. Requires GCC.

 codegen/valaccodebasemodule.vala   |   10 +++++
 codegen/valaccodemethodmodule.vala |   78 ++++++++++++++++++++++++++++++++++++
 2 files changed, 88 insertions(+), 0 deletions(-)
---
diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala
index 866e8b9..6a1b890 100644
--- a/codegen/valaccodebasemodule.vala
+++ b/codegen/valaccodebasemodule.vala
@@ -3488,6 +3488,16 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
 			}
 		}
 
+		if (current_method != null && current_method.get_attribute ("Profile") != null) {
+			string prefix = "_vala_prof_%s".printf (get_ccode_real_name (current_method));
+
+			var timer = new CCodeIdentifier (prefix + "_timer");
+
+			var stop_call = new CCodeFunctionCall (new CCodeIdentifier ("g_timer_stop"));
+			stop_call.add_argument (timer);
+			ccode.add_expression (stop_call);
+		}
+
 		if (is_in_constructor ()) {
 			ccode.add_return (new CCodeIdentifier ("obj"));
 		} else if (is_in_destructor ()) {
diff --git a/codegen/valaccodemethodmodule.vala b/codegen/valaccodemethodmodule.vala
index be69a1c..b03f889 100644
--- a/codegen/valaccodemethodmodule.vala
+++ b/codegen/valaccodemethodmodule.vala
@@ -258,6 +258,8 @@ public abstract class Vala.CCodeMethodModule : CCodeStructModule {
 
 		check_type (m.return_type);
 
+		bool profile = m.get_attribute ("Profile") != null;
+
 		if (m.get_attribute ("NoArrayLength") != null) {
 			Report.deprecated (m.source_reference, "NoArrayLength attribute is deprecated, use [CCode (array_length = false)] instead.");
 		}
@@ -300,6 +302,60 @@ public abstract class Vala.CCodeMethodModule : CCodeStructModule {
 			}
 		}
 
+		if (profile) {
+			string prefix = "_vala_prof_%s".printf (get_ccode_real_name (m));
+
+			cfile.add_include ("stdio.h");
+
+			var counter = new CCodeIdentifier (prefix + "_counter");
+			var counter_decl = new CCodeDeclaration ("gint");
+			counter_decl.add_declarator (new CCodeVariableDeclarator (counter.name));
+			counter_decl.modifiers = CCodeModifiers.STATIC;
+			cfile.add_type_member_declaration (counter_decl);
+
+			var timer = new CCodeIdentifier (prefix + "_timer");
+			var timer_decl = new CCodeDeclaration ("GTimer *");
+			timer_decl.add_declarator (new CCodeVariableDeclarator (timer.name));
+			timer_decl.modifiers = CCodeModifiers.STATIC;
+			cfile.add_type_member_declaration (timer_decl);
+
+			var constructor = new CCodeFunction (prefix + "_init");
+			constructor.modifiers = CCodeModifiers.STATIC;
+			constructor.attributes = "__attribute__((constructor))";
+			cfile.add_function_declaration (constructor);
+			push_function (constructor);
+
+			ccode.add_assignment (timer, new CCodeFunctionCall (new CCodeIdentifier ("g_timer_new")));
+
+			var stop_call = new CCodeFunctionCall (new CCodeIdentifier ("g_timer_stop"));
+			stop_call.add_argument (timer);
+			ccode.add_expression (stop_call);
+
+			pop_function ();
+			cfile.add_function (constructor);
+
+
+			var destructor = new CCodeFunction (prefix + "_exit");
+			destructor.modifiers = CCodeModifiers.STATIC;
+			destructor.attributes = "__attribute__((destructor))";
+			cfile.add_function_declaration (destructor);
+			push_function (destructor);
+
+			var elapsed_call = new CCodeFunctionCall (new CCodeIdentifier ("g_timer_elapsed"));
+			elapsed_call.add_argument (timer);
+			elapsed_call.add_argument (new CCodeConstant ("NULL"));
+
+			var print_call = new CCodeFunctionCall (new CCodeIdentifier ("fprintf"));
+			print_call.add_argument (new CCodeIdentifier ("stderr"));
+			print_call.add_argument (new CCodeConstant ("\"%s: %%gs (%%d calls)\\n\"".printf (m.get_full_name ())));
+			print_call.add_argument (elapsed_call);
+			print_call.add_argument (counter);
+			ccode.add_expression (print_call);
+
+			pop_function ();
+			cfile.add_function (destructor);
+		}
+
 		CCodeFunction function;
 		function = new CCodeFunction (get_ccode_real_name (m));
 
@@ -560,10 +616,32 @@ public abstract class Vala.CCodeMethodModule : CCodeStructModule {
 			}
 		}
 
+		if (profile) {
+			string prefix = "_vala_prof_%s".printf (get_ccode_real_name (m));
+
+			var counter = new CCodeIdentifier (prefix + "_counter");
+			ccode.add_expression (new CCodeUnaryExpression (CCodeUnaryOperator.POSTFIX_INCREMENT, counter));
+
+			var timer = new CCodeIdentifier (prefix + "_timer");
+			var cont_call = new CCodeFunctionCall (new CCodeIdentifier ("g_timer_continue"));
+			cont_call.add_argument (timer);
+			ccode.add_expression (cont_call);
+		}
+
 		if (m.body != null) {
 			m.body.emit (this);
 		}
 
+		if (profile) {
+			string prefix = "_vala_prof_%s".printf (get_ccode_real_name (m));
+
+			var timer = new CCodeIdentifier (prefix + "_timer");
+
+			var stop_call = new CCodeFunctionCall (new CCodeIdentifier ("g_timer_stop"));
+			stop_call.add_argument (timer);
+			ccode.add_expression (stop_call);
+		}
+
 		// generate *_real_* functions for virtual methods
 		// also generate them for abstract methods of classes to prevent faulty subclassing
 		if (!m.is_abstract || (m.is_abstract && current_type_symbol is Class)) {



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]