[cairo-commit] 3 commits - perf/README util/cairo-trace

Chris Wilson ickle at kemper.freedesktop.org
Mon Jun 8 11:02:55 PDT 2009


 perf/README                     |    2 
 util/cairo-trace/cairo-trace.in |    5 ++
 util/cairo-trace/trace.c        |   89 ++++++++++++++++++++++++++++------------
 3 files changed, 69 insertions(+), 27 deletions(-)

New commits:
commit 015df191ba947e714285145c3a4ead198ba0d07e
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Jun 8 17:40:16 2009 +0100

    [trace] Prevent overflowing the operand stack when recreating objects
    
    Objects like cairo_scaled_font_t may return a reference to a previously
    defined scaled-font instead of creating a new token each time. This caused
    cairo-trace to overflow its operand stack by pushing a new instance of the
    old token every time. Modify the tracer such that a font token can only
    appear once on the stack -- for font-faces we remove the old operand and
    for scaled-fonts we simply pop, chosen to reflect expected usage.

diff --git a/util/cairo-trace/trace.c b/util/cairo-trace/trace.c
index 4826e99..db7a251 100644
--- a/util/cairo-trace/trace.c
+++ b/util/cairo-trace/trace.c
@@ -885,38 +885,61 @@ static void
 _push_operand (enum operand_type t, const void *ptr)
 {
     Object *obj = _get_object (t, ptr);
+
+    if (current_stack_depth ==
+	sizeof (current_object) / sizeof (current_object[0]))
+    {
+	int n;
+
+	fprintf (stderr, "Operand stack overflow!\n");
+	for (n = 0; n < current_stack_depth; n++) {
+	    obj = current_object[n];
+
+	    fprintf (stderr, "  [%3d] = %s%ld\n",
+		     n, obj->type->op_code, obj->token);
+	}
+
+	abort ();
+    }
+
     obj->operand = current_stack_depth;
     current_object[current_stack_depth++] = obj;
 }
 
 static void
-_object_undef (void *ptr)
+_object_remove (Object *obj)
 {
-    Object *obj = ptr;
-
-    if (_write_lock ()) {
-	if (obj->operand != -1) {
-	    if (obj->operand == current_stack_depth - 1) {
-		_trace_printf ("pop %% %s%ld destroyed\n",
-			       obj->type->op_code, obj->token);
-	    } else if (obj->operand == current_stack_depth - 2) {
-		_exch_operands ();
-		_trace_printf ("exch pop %% %s%ld destroyed\n",
-			       obj->type->op_code, obj->token);
-	    } else {
-		int n;
+    if (obj->operand != -1) {
+	if (obj->operand == current_stack_depth - 1) {
+	    _trace_printf ("pop %% %s%ld destroyed\n",
+			   obj->type->op_code, obj->token);
+	} else if (obj->operand == current_stack_depth - 2) {
+	    _exch_operands ();
+	    _trace_printf ("exch pop %% %s%ld destroyed\n",
+			   obj->type->op_code, obj->token);
+	} else {
+	    int n;
 
-		_trace_printf ("%d -1 roll pop %% %s%ld destroyed\n",
-			       current_stack_depth - obj->operand,
-			       obj->type->op_code, obj->token);
+	    _trace_printf ("%d -1 roll pop %% %s%ld destroyed\n",
+			   current_stack_depth - obj->operand,
+			   obj->type->op_code, obj->token);
 
-		for (n = obj->operand; n < current_stack_depth - 1; n++) {
-		    current_object[n] = current_object[n+1];
-		    current_object[n]->operand = n;
-		}
+	    for (n = obj->operand; n < current_stack_depth - 1; n++) {
+		current_object[n] = current_object[n+1];
+		current_object[n]->operand = n;
 	    }
-	    current_stack_depth--;
 	}
+	current_stack_depth--;
+    }
+}
+
+static void
+_object_undef (void *ptr)
+{
+    Object *obj = ptr;
+
+    if (_write_lock ()) {
+	_object_remove (obj);
 
 	if (obj->defined) {
 	    _trace_printf ("/%s%ld undef\n",
@@ -2722,11 +2745,16 @@ cairo_scaled_font_create (cairo_font_face_t *font_face,
 
 	_emit_font_options (options);
 
-	_trace_printf ("  scaled-font dup /sf%ld exch def\n",
-		       scaled_font_id);
+	if (_get_object (SCALED_FONT, ret)->defined) {
+	    _trace_printf ("  scaled-font pop %% sf%ld\n",
+			   scaled_font_id);
+	} else {
+	    _trace_printf ("  scaled-font dup /sf%ld exch def\n",
+			   scaled_font_id);
+	    _push_operand (SCALED_FONT, ret);
 
-	_get_object (SCALED_FONT, ret)->defined = true;
-	_push_operand (SCALED_FONT, ret);
+	    _get_object (SCALED_FONT, ret)->defined = true;
+	}
 
 	_write_unlock ();
     }
@@ -3470,8 +3498,13 @@ cairo_ft_font_face_create_for_pattern (FcPattern *pattern)
 
     _emit_line_info ();
     if (pattern != NULL && _write_lock ()) {
+	Object *obj;
 	FcChar8 *parsed;
 
+	obj = _get_object (FONT_FACE, ret);
+	if (obj->operand != -1)
+	    _object_remove (obj);
+
 	parsed = DLCALL (FcNameUnparse, pattern);
 	_trace_printf ("dict\n"
 		       "  /type 42 set\n"
@@ -3523,6 +3556,10 @@ cairo_ft_font_face_create_for_ft_face (FT_Face face, int load_flags)
 
     _emit_line_info ();
     if (_write_lock ()) {
+	obj = _get_object (FONT_FACE, ret);
+	if (obj->operand != -1)
+	    _object_remove (obj);
+
 	_trace_printf ("dict\n"
 		       "  /type 42 set\n"
 		       "  /source ");
commit 09492288b33c36093e50d39e4e7e632ab659a0e2
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Jun 8 17:38:14 2009 +0100

    [trace] Option to re-enable mark-dirty
    
    Applications such as swfdec have a strictly correct use of mark-dirty and
    so we need an option to re-enable mark-dirty tracing in conjunction with
    --profile.

diff --git a/util/cairo-trace/cairo-trace.in b/util/cairo-trace/cairo-trace.in
index 8a1e1b8..16cdad6 100644
--- a/util/cairo-trace/cairo-trace.in
+++ b/util/cairo-trace/cairo-trace.in
@@ -20,6 +20,7 @@ Whatever else happens is driven by its argument:
   --no-file       - Disable the creation of an output file. Outputs to the
                     terminal instead.
   --no-callers    - Do not lookup the caller address/symbol/line whilst tracing.
+  --mark-dirty    - Record image data for cairo_mark_dirty() [default]
   --no-mark-dirty - Do not record image data for cairo_mark_dirty()
   --compress      - Compress the output with LZMA
   --profile       - Combine --no-callers and --no-mark-dirty and --compress
@@ -47,6 +48,10 @@ while test $skip -eq 1; do
 	skip=1
 	nocallers=1
 	;;
+    --mark-dirty)
+	skip=1
+	nomarkdirty=
+	;;
     --no-mark-dirty)
 	skip=1
 	nomarkdirty=1
commit 39bac6edddb8913d07fb25f14f088967ca846a78
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Jun 8 11:52:56 2009 +0100

    [perf] Mention cairo-perf-trace early on in the README

diff --git a/perf/README b/perf/README
index efd9e40..abf0687 100644
--- a/perf/README
+++ b/perf/README
@@ -184,7 +184,7 @@ How to benchmark traces
 -----------------------
 Using cairo-trace you can record the exact sequence of graphic operations
 made by an application and replay them later. These traces can then be
-used to benchmark the various backends and patches.
+used by cairo-perf-trace to benchmark the various backends and patches.
 
 To record a trace:
 $ cairo-trace --no-mark-dirty --no-callers $APPLICATION [$ARGV]


More information about the cairo-commit mailing list