[Swfdec-commits] 2 commits - swfdec/Makefile.am swfdec/swfdec_actor.c swfdec/swfdec_as_array.c swfdec/swfdec_as_boolean.c swfdec/swfdec_as_context.c swfdec/swfdec_as_context.h swfdec/swfdec_as_date.c swfdec/swfdec_as_frame.c swfdec/swfdec_as_function.c swfdec/swfdec_as_internal.h swfdec/swfdec_as_interpret.c swfdec/swfdec_as_native_function.c swfdec/swfdec_as_number.c swfdec/swfdec_as_object.c swfdec/swfdec_as_object.h swfdec/swfdec_as_script_function.c swfdec/swfdec_as_string.c swfdec/swfdec_as_super.c swfdec/swfdec_as_types.h swfdec/swfdec_bitmap_data.c swfdec/swfdec_button.c swfdec/swfdec_button_movie.c swfdec/swfdec_button_movie.h swfdec/swfdec_color_as.c swfdec/swfdec_color_transform_as.c swfdec/swfdec_gc_object.c swfdec/swfdec_gc_object.h swfdec/swfdec_graphic.c swfdec/swfdec_graphic.h swfdec/swfdec_graphic_movie.c swfdec/swfdec_interval.c swfdec/swfdec_load_object_as.c swfdec/swfdec_load_object.c swfdec/swfdec_load_sound.c swfdec/swfdec_morph_movie.c swfdec/swfdec_morph_movie.h swfdec/swfdec_morphshape.c swfdec/swfdec_movie_as_drawing.c swfdec/swfdec_movie_asprops.c swfdec/swfdec_movie.c swfdec/swfdec_net_connection.c swfdec/swfdec_net_stream.c swfdec/swfdec_player.c swfdec/swfdec_resource.c swfdec/swfdec_sandbox.c swfdec/swfdec_selection.c swfdec/swfdec_sound.c swfdec/swfdec_sound_object.c swfdec/swfdec_sprite.c swfdec/swfdec_sprite_movie_as.c swfdec/swfdec_sprite_movie.c swfdec/swfdec_style_sheet.c swfdec/swfdec_text_field.c swfdec/swfdec_text_field_movie_as.c swfdec/swfdec_text_field_movie.c swfdec/swfdec_text_field_movie_html.c swfdec/swfdec_text_format.c swfdec/swfdec_text_format.h swfdec/swfdec_transform_as.c swfdec/swfdec_video.c swfdec/swfdec_video_movie.c swfdec/swfdec_video_movie.h swfdec/swfdec_xml.c swfdec/swfdec_xml_node.c swfdec/swfdec_xml_socket.c test/swfdec_test_buffer.c test/swfdec_test_image.c test/swfdec_test_socket.c test/swfdec_test_test.c vivified/core

Benjamin Otte company at kemper.freedesktop.org
Thu Jul 24 08:31:04 PDT 2008


 swfdec/Makefile.am                    |    2 
 swfdec/swfdec_actor.c                 |   10 -
 swfdec/swfdec_as_array.c              |   45 ++--
 swfdec/swfdec_as_boolean.c            |    2 
 swfdec/swfdec_as_context.c            |   65 +------
 swfdec/swfdec_as_context.h            |    3 
 swfdec/swfdec_as_date.c               |   13 -
 swfdec/swfdec_as_frame.c              |   48 ++---
 swfdec/swfdec_as_function.c           |    2 
 swfdec/swfdec_as_internal.h           |    4 
 swfdec/swfdec_as_interpret.c          |   19 +-
 swfdec/swfdec_as_native_function.c    |    6 
 swfdec/swfdec_as_number.c             |    2 
 swfdec/swfdec_as_object.c             |  313 +++++++++++++++-------------------
 swfdec/swfdec_as_object.h             |   18 -
 swfdec/swfdec_as_script_function.c    |   18 -
 swfdec/swfdec_as_string.c             |    8 
 swfdec/swfdec_as_super.c              |   14 -
 swfdec/swfdec_as_types.h              |    1 
 swfdec/swfdec_bitmap_data.c           |    2 
 swfdec/swfdec_button.c                |   16 -
 swfdec/swfdec_button_movie.c          |   48 +++--
 swfdec/swfdec_button_movie.h          |    1 
 swfdec/swfdec_color_as.c              |    2 
 swfdec/swfdec_color_transform_as.c    |    6 
 swfdec/swfdec_gc_object.c             |  202 +++++++++++++++++++++
 swfdec/swfdec_gc_object.h             |   60 ++++++
 swfdec/swfdec_graphic.c               |   13 -
 swfdec/swfdec_graphic.h               |    8 
 swfdec/swfdec_graphic_movie.c         |    2 
 swfdec/swfdec_interval.c              |   36 ++-
 swfdec/swfdec_load_object.c           |   14 -
 swfdec/swfdec_load_object_as.c        |    2 
 swfdec/swfdec_load_sound.c            |   12 -
 swfdec/swfdec_morph_movie.c           |    8 
 swfdec/swfdec_morph_movie.h           |    1 
 swfdec/swfdec_morphshape.c            |   16 -
 swfdec/swfdec_movie.c                 |  176 +++++++++++--------
 swfdec/swfdec_movie_as_drawing.c      |    4 
 swfdec/swfdec_movie_asprops.c         |   34 +--
 swfdec/swfdec_net_connection.c        |    2 
 swfdec/swfdec_net_stream.c            |   34 +--
 swfdec/swfdec_player.c                |   10 -
 swfdec/swfdec_resource.c              |   54 ++---
 swfdec/swfdec_sandbox.c               |   37 +---
 swfdec/swfdec_selection.c             |    2 
 swfdec/swfdec_sound.c                 |    4 
 swfdec/swfdec_sound_object.c          |   12 -
 swfdec/swfdec_sprite.c                |   14 -
 swfdec/swfdec_sprite_movie.c          |   52 +++--
 swfdec/swfdec_sprite_movie_as.c       |    7 
 swfdec/swfdec_style_sheet.c           |    4 
 swfdec/swfdec_text_field.c            |   28 ---
 swfdec/swfdec_text_field_movie.c      |   65 ++++---
 swfdec/swfdec_text_field_movie_as.c   |    4 
 swfdec/swfdec_text_field_movie_html.c |    6 
 swfdec/swfdec_text_format.c           |   41 ++--
 swfdec/swfdec_text_format.h           |    2 
 swfdec/swfdec_transform_as.c          |    6 
 swfdec/swfdec_video.c                 |   20 --
 swfdec/swfdec_video_movie.c           |   46 +++-
 swfdec/swfdec_video_movie.h           |    1 
 swfdec/swfdec_xml.c                   |   48 ++---
 swfdec/swfdec_xml_node.c              |   48 ++---
 swfdec/swfdec_xml_socket.c            |   29 +--
 test/swfdec_test_buffer.c             |    5 
 test/swfdec_test_image.c              |    5 
 test/swfdec_test_socket.c             |    6 
 test/swfdec_test_test.c               |    4 
 vivified/core/vivi_breakpoint.c       |   32 +--
 vivified/core/vivi_wrap.c             |    6 
 71 files changed, 1027 insertions(+), 863 deletions(-)

New commits:
commit 7373d1a94be5e6c1a6ac193d27851ccfb2b8c6f7
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Jul 24 17:26:10 2008 +0200

    Significantly change object hierarchy and creation
    
    Highlights:
    - There is a SwfdecGcObject class now. It's to be used for objects that are
      not accessible to the script engine, but are garbage-collected (examples:
      SwfdecInterval, SwfdecResource)
    - object initialization is now done using object properties. This has the
      advantage of being able to easily create objects via g_object_new() and
      not having to use
    - swfdec_as_object_add() is gone. SwfdecGcObject does that automatically.
    - SWFDEC_AS_OBJECT (foo)->context has been replaced by
      swfdec_gc_object_get_context (foo)
    
    I ensured that the testsuite passes.

diff --git a/swfdec/Makefile.am b/swfdec/Makefile.am
index f4c05a7..f8dbc00 100644
--- a/swfdec/Makefile.am
+++ b/swfdec/Makefile.am
@@ -80,6 +80,7 @@ libswfdec_source_files = \
 	swfdec_flv_decoder.c \
 	swfdec_font.c \
 	swfdec_function_list.c \
+	swfdec_gc_object.c \
 	swfdec_glow_filter.c \
 	swfdec_gradient_filter.c \
 	swfdec_gradient_pattern.c \
@@ -201,6 +202,7 @@ public_headers = \
 	swfdec_audio.h \
 	swfdec_buffer.h \
 	swfdec_file_loader.h \
+	swfdec_gc_object.h \
 	swfdec_keys.h \
 	swfdec_loader.h \
 	swfdec_player.h \
diff --git a/swfdec/swfdec_actor.c b/swfdec/swfdec_actor.c
index ce0a921..bf1bd6a 100644
--- a/swfdec/swfdec_actor.c
+++ b/swfdec/swfdec_actor.c
@@ -81,7 +81,7 @@ swfdec_actor_mouse_events (SwfdecActor *actor)
 static void
 swfdec_actor_mouse_in (SwfdecActor *actor)
 {
-  if (swfdec_player_is_mouse_pressed (SWFDEC_PLAYER (SWFDEC_AS_OBJECT (actor)->context)))
+  if (swfdec_player_is_mouse_pressed (SWFDEC_PLAYER (swfdec_gc_object_get_context (actor))))
     swfdec_actor_queue_script (actor, SWFDEC_EVENT_DRAG_OVER);
   else
     swfdec_actor_queue_script (actor, SWFDEC_EVENT_ROLL_OVER);
@@ -90,7 +90,7 @@ swfdec_actor_mouse_in (SwfdecActor *actor)
 static void
 swfdec_actor_mouse_out (SwfdecActor *actor)
 {
-  if (swfdec_player_is_mouse_pressed (SWFDEC_PLAYER (SWFDEC_AS_OBJECT (actor)->context)))
+  if (swfdec_player_is_mouse_pressed (SWFDEC_PLAYER (swfdec_gc_object_get_context (actor))))
     swfdec_actor_queue_script (actor, SWFDEC_EVENT_DRAG_OUT);
   else
     swfdec_actor_queue_script (actor, SWFDEC_EVENT_ROLL_OUT);
@@ -112,7 +112,7 @@ swfdec_actor_mouse_release (SwfdecActor *actor, guint button)
   if (button != 0)
     return;
 
-  player = SWFDEC_PLAYER (SWFDEC_AS_OBJECT (actor)->context);
+  player = SWFDEC_PLAYER (swfdec_gc_object_get_context (actor));
   if (player->priv->mouse_below == actor)
     swfdec_actor_queue_script (actor, SWFDEC_EVENT_RELEASE);
   else
@@ -165,7 +165,7 @@ static void
 swfdec_sprite_movie_set_constructor (SwfdecSpriteMovie *movie)
 {
   SwfdecMovie *mov = SWFDEC_MOVIE (movie);
-  SwfdecAsContext *context = SWFDEC_AS_OBJECT (movie)->context;
+  SwfdecAsContext *context = swfdec_gc_object_get_context (movie);
   SwfdecAsObject *constructor = NULL;
 
   g_assert (mov->resource != NULL);
@@ -309,7 +309,7 @@ swfdec_actor_queue_script_with_key (SwfdecActor *actor,
       g_return_if_reached ();
   }
 
-  player = SWFDEC_PLAYER (SWFDEC_AS_OBJECT (actor)->context);
+  player = SWFDEC_PLAYER (swfdec_gc_object_get_context (actor));
   swfdec_player_add_action (player, actor, condition, key, importance);
 }
 
diff --git a/swfdec/swfdec_as_array.c b/swfdec/swfdec_as_array.c
index 42635fb..2603ae4 100644
--- a/swfdec/swfdec_as_array.c
+++ b/swfdec/swfdec_as_array.c
@@ -84,7 +84,7 @@ swfdec_as_array_length_as_integer (SwfdecAsObject *object)
   g_return_val_if_fail (object != NULL, 0);
 
   swfdec_as_object_get_variable (object, SWFDEC_AS_STR_length, &val);
-  length = swfdec_as_value_to_integer (object->context, &val);
+  length = swfdec_as_value_to_integer (swfdec_gc_object_get_context (object), &val);
 
   return length;
 }
@@ -196,8 +196,8 @@ swfdec_as_array_remove_range (SwfdecAsArray *array, gint32 start_index,
 
   // to avoid foreach loop, use special case when removing just one variable
   if (num == 1) {
-    swfdec_as_object_delete_variable (object,
-	swfdec_as_integer_to_string (object->context, start_index));
+    swfdec_as_object_delete_variable (object, swfdec_as_integer_to_string (
+	  swfdec_gc_object_get_context (object), start_index));
   } else {
     ForeachRemoveRangeData fdata = { start_index, num };
     swfdec_as_object_foreach_remove (object,
@@ -223,7 +223,7 @@ swfdec_as_array_foreach_move_range (SwfdecAsObject *object,
     return variable;
 
   if (idx >= fdata->start_index && idx < fdata->start_index + fdata->num) {
-    return swfdec_as_integer_to_string (object->context,
+    return swfdec_as_integer_to_string (swfdec_gc_object_get_context (object),
 	fdata->to_index + idx - fdata->start_index);
   } else if (idx >= fdata->to_index && idx < fdata->to_index + fdata->num) {
     return NULL;
@@ -268,7 +268,7 @@ swfdec_as_array_set_range_with_flags (SwfdecAsObject *object,
   g_return_if_fail (num == 0 || value != NULL);
 
   for (i = 0; i < num; i++) {
-    var = swfdec_as_integer_to_string (object->context, start_index + i);
+    var = swfdec_as_integer_to_string (swfdec_gc_object_get_context (object), start_index + i);
     swfdec_as_object_set_variable_and_flags (object, var, &value[i], flags);
   }
 }
@@ -424,7 +424,7 @@ swfdec_as_array_get_value (SwfdecAsArray *array, gint32 idx,
   g_assert (idx >= 0);
   g_assert (value != NULL);
 
-  var = swfdec_as_integer_to_string (SWFDEC_AS_OBJECT (array)->context, idx);
+  var = swfdec_as_integer_to_string (swfdec_gc_object_get_context (array), idx);
   swfdec_as_object_get_variable (SWFDEC_AS_OBJECT (array), var, value);
 }
 
@@ -447,7 +447,7 @@ swfdec_as_array_set_value (SwfdecAsArray *array, gint32 idx,
   g_assert (idx >= 0);
   g_assert (SWFDEC_IS_AS_VALUE (value));
 
-  var = swfdec_as_integer_to_string (SWFDEC_AS_OBJECT (array)->context, idx);
+  var = swfdec_as_integer_to_string (swfdec_gc_object_get_context (array), idx);
   swfdec_as_object_set_variable (SWFDEC_AS_OBJECT (array), var, value);
 }
 
@@ -468,7 +468,7 @@ swfdec_as_array_foreach_append_array_range (SwfdecAsObject *object,
 
   idx = swfdec_as_array_to_index (variable);
   if (idx >= fdata->start_index && idx < fdata->start_index + fdata->num) {
-    var = swfdec_as_integer_to_string (fdata->object_to->context,
+    var = swfdec_as_integer_to_string (swfdec_gc_object_get_context (fdata->object_to),
 	fdata->offset + (idx - fdata->start_index));
     swfdec_as_object_set_variable (fdata->object_to, var, value);
   }
@@ -527,11 +527,11 @@ swfdec_as_array_set (SwfdecAsObject *object, const char *variable,
   // if we changed to smaller length, destroy all values that are outside it
   //
   if (SWFDEC_AS_ARRAY (object)->check_length &&
-      !swfdec_strcmp (object->context->version, variable,
+      !swfdec_strcmp (swfdec_gc_object_get_context (object)->version, variable,
 	SWFDEC_AS_STR_length))
   {
     gint32 length_old = swfdec_as_array_length (object);
-    gint32 length_new = swfdec_as_value_to_integer (object->context, val);
+    gint32 length_new = swfdec_as_value_to_integer (swfdec_gc_object_get_context (object), val);
     length_new = MAX (0, length_new);
     if (length_old > length_new) {
       swfdec_as_array_remove_range (SWFDEC_AS_ARRAY (object), length_new,
@@ -581,10 +581,7 @@ swfdec_as_array_new (SwfdecAsContext *context)
 
   g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context), NULL);
 
-  swfdec_as_context_use_mem (context, sizeof (SwfdecAsArray));
-
-  ret = g_object_new (SWFDEC_TYPE_AS_ARRAY, NULL);
-  swfdec_as_object_add (ret, context, sizeof (SwfdecAsArray));
+  ret = g_object_new (SWFDEC_TYPE_AS_ARRAY, "context", context, NULL);
   swfdec_as_object_get_variable (context->global, SWFDEC_AS_STR_Array, &val);
   if (SWFDEC_AS_VALUE_IS_OBJECT (&val))
     swfdec_as_object_set_constructor (ret, SWFDEC_AS_VALUE_GET_OBJECT (&val));
@@ -681,7 +678,7 @@ swfdec_as_array_do_pop (SwfdecAsContext *cx, SwfdecAsObject *object,
   if (length == 0)
     return;
 
-  var = swfdec_as_integer_to_string (object->context, length - 1);
+  var = swfdec_as_integer_to_string (swfdec_gc_object_get_context (object), length - 1);
   swfdec_as_object_get_variable (object, var, ret);
 
   swfdec_as_object_delete_variable (object, var);
@@ -742,12 +739,12 @@ swfdec_as_array_do_shift (SwfdecAsContext *cx, SwfdecAsObject *object,
     // we have to put the last element back, because we used move, not copy
     SwfdecAsValue val;
     if (length > 1) {
-      var = swfdec_as_integer_to_string (object->context, length - 2);
+      var = swfdec_as_integer_to_string (swfdec_gc_object_get_context (object), length - 2);
       swfdec_as_object_get_variable (object, var, &val);
     } else {
       val = *ret;
     }
-    var = swfdec_as_integer_to_string (object->context, length - 1);
+    var = swfdec_as_integer_to_string (swfdec_gc_object_get_context (object), length - 1);
     swfdec_as_object_set_variable (object, var, &val);
   }
 }
@@ -763,7 +760,7 @@ swfdec_as_array_foreach_reverse (SwfdecAsObject *object, const char *variable,
   if (idx == -1 || idx >= *length)
     return variable;
 
-  return swfdec_as_integer_to_string (object->context, *length - 1 - idx);
+  return swfdec_as_integer_to_string (swfdec_gc_object_get_context (object), *length - 1 - idx);
 }
 
 SWFDEC_AS_NATIVE (252, 11, swfdec_as_array_reverse)
@@ -812,7 +809,7 @@ swfdec_as_array_concat (SwfdecAsContext *cx, SwfdecAsObject *object,
     }
     else
     {
-      var = swfdec_as_integer_to_string (object->context,
+      var = swfdec_as_integer_to_string (swfdec_gc_object_get_context (object),
 	  swfdec_as_array_length (object_new));
       swfdec_as_object_set_variable (object_new, var, &argv[j]);
     }
@@ -941,10 +938,10 @@ swfdec_as_array_sort_compare_values (SwfdecAsContext *cx,
   {
     SwfdecAsValue argv[2] = { *a, *b };
     SwfdecAsValue ret;
+    SwfdecAsContext *context = swfdec_gc_object_get_context (custom_function);
     swfdec_as_function_call (custom_function, NULL, 2, argv, &ret);
-    swfdec_as_context_run (SWFDEC_AS_OBJECT (custom_function)->context);
-    retval = swfdec_as_value_to_integer (
-	SWFDEC_AS_OBJECT (custom_function)->context, &ret);
+    swfdec_as_context_run (context);
+    retval = swfdec_as_value_to_integer (context, &ret);
   }
   else if (options & SORT_OPTION_NUMERIC &&
       (SWFDEC_AS_VALUE_IS_NUMBER (a) ||
@@ -1372,9 +1369,7 @@ swfdec_as_array_construct (SwfdecAsContext *cx, SwfdecAsObject *object,
 
   if (!cx->frame->construct) {
     SwfdecAsValue val;
-    swfdec_as_context_use_mem (cx, sizeof (SwfdecAsArray));
-    object = g_object_new (SWFDEC_TYPE_AS_ARRAY, NULL);
-    swfdec_as_object_add (object, cx, sizeof (SwfdecAsArray));
+    object = g_object_new (SWFDEC_TYPE_AS_ARRAY, "context", cx, NULL);
     swfdec_as_object_get_variable (cx->global, SWFDEC_AS_STR_Array, &val);
     if (SWFDEC_AS_VALUE_IS_OBJECT (&val)) {
       swfdec_as_object_set_constructor (object,
diff --git a/swfdec/swfdec_as_boolean.c b/swfdec/swfdec_as_boolean.c
index a33088b..65a1ec7 100644
--- a/swfdec/swfdec_as_boolean.c
+++ b/swfdec/swfdec_as_boolean.c
@@ -52,7 +52,7 @@ swfdec_as_boolean_construct (SwfdecAsContext *cx, SwfdecAsObject *object,
   gboolean b;
 
   if (argc > 0) {
-    b = swfdec_as_value_to_boolean (object->context, &argv[0]);
+    b = swfdec_as_value_to_boolean (swfdec_gc_object_get_context (object), &argv[0]);
   } else {
     if (!swfdec_as_context_is_constructing (cx))
       return;
diff --git a/swfdec/swfdec_as_context.c b/swfdec/swfdec_as_context.c
index f906d9f..f010c60 100644
--- a/swfdec/swfdec_as_context.c
+++ b/swfdec/swfdec_as_context.c
@@ -1,5 +1,5 @@
 /* Swfdec
- * Copyright (C) 2007 Benjamin Otte <otte at gnome.org>
+ * Copyright (C) 2007-2008 Benjamin Otte <otte at gnome.org>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -38,14 +38,12 @@
 #include "swfdec_as_types.h"
 #include "swfdec_constant_pool.h"
 #include "swfdec_debug.h"
+#include "swfdec_gc_object.h"
 #include "swfdec_internal.h" /* for swfdec_player_preinit_global() */
 #include "swfdec_script.h"
 
 /*** GARBAGE COLLECTION DOCS ***/
 
-#define SWFDEC_AS_GC_MARK (1 << 0)		/* only valid during GC */
-#define SWFDEC_AS_GC_ROOT (1 << 1)		/* for objects: rooted, for strings: static */
-
 /**
  * SECTION:Internals
  * @title: Internals and garbage collection
@@ -281,23 +279,18 @@ swfdec_as_context_remove_strings (gpointer key, gpointer value, gpointer data)
 static gboolean
 swfdec_as_context_remove_objects (gpointer key, gpointer value, gpointer debugger)
 {
-  SwfdecAsObject *object;
+  SwfdecGcObject *gc;
 
-  object = key;
+  gc = key;
   /* we only check for mark here, not root, since this works on destroy, too */
-  if (object->flags & SWFDEC_AS_GC_MARK) {
-    object->flags &= ~SWFDEC_AS_GC_MARK;
-    SWFDEC_LOG ("%s: %s %p", (object->flags & SWFDEC_AS_GC_ROOT) ? "rooted" : "marked",
-	G_OBJECT_TYPE_NAME (object), object);
+  if (gc->flags & SWFDEC_AS_GC_MARK) {
+    gc->flags &= ~SWFDEC_AS_GC_MARK;
+    SWFDEC_LOG ("%s: %s %p", (gc->flags & SWFDEC_AS_GC_ROOT) ? "rooted" : "marked",
+	G_OBJECT_TYPE_NAME (gc), gc);
     return FALSE;
   } else {
-    SWFDEC_LOG ("deleted: %s %p", G_OBJECT_TYPE_NAME (object), object);
-    if (debugger) {
-      SwfdecAsDebuggerClass *klass = SWFDEC_AS_DEBUGGER_GET_CLASS (debugger);
-      if (klass->remove)
-	klass->remove (debugger, object->context, object);
-    }
-    swfdec_as_object_collect (object);
+    SWFDEC_LOG ("deleted: %s %p", G_OBJECT_TYPE_NAME (gc), gc);
+    g_object_unref (gc);
     return TRUE;
   }
 }
@@ -315,28 +308,6 @@ swfdec_as_context_collect (SwfdecAsContext *context)
 }
 
 /**
- * swfdec_as_object_mark:
- * @object: a #SwfdecAsObject
- *
- * Mark @object as being in use. Calling this function is only valid during
- * the marking phase of garbage collection.
- **/
-void
-swfdec_as_object_mark (SwfdecAsObject *object)
-{
-  SwfdecAsObjectClass *klass;
-
-  g_return_if_fail (SWFDEC_IS_AS_OBJECT (object));
-
-  if (object->flags & SWFDEC_AS_GC_MARK)
-    return;
-  object->flags |= SWFDEC_AS_GC_MARK;
-  klass = SWFDEC_AS_OBJECT_GET_CLASS (object);
-  g_assert (klass->mark);
-  klass->mark (object);
-}
-
-/**
  * swfdec_as_string_mark:
  * @string: a garbage-collected string
  *
@@ -369,7 +340,7 @@ swfdec_as_value_mark (SwfdecAsValue *value)
   g_return_if_fail (SWFDEC_IS_AS_VALUE (value));
 
   if (SWFDEC_AS_VALUE_IS_OBJECT (value)) {
-    swfdec_as_object_mark (SWFDEC_AS_VALUE_GET_OBJECT (value));
+    swfdec_gc_object_mark (SWFDEC_AS_VALUE_GET_OBJECT (value));
   } else if (SWFDEC_AS_VALUE_IS_STRING (value)) {
     swfdec_as_string_mark (SWFDEC_AS_VALUE_GET_STRING (value));
   }
@@ -378,10 +349,10 @@ swfdec_as_value_mark (SwfdecAsValue *value)
 static void
 swfdec_as_context_mark_roots (gpointer key, gpointer value, gpointer data)
 {
-  SwfdecAsObject *object = key;
+  SwfdecGcObject *object = key;
 
   if ((object->flags & (SWFDEC_AS_GC_MARK | SWFDEC_AS_GC_ROOT)) == SWFDEC_AS_GC_ROOT)
-    swfdec_as_object_mark (object);
+    swfdec_gc_object_mark (object);
 }
 
 /* FIXME: replace this with refcounted strings? */
@@ -401,11 +372,11 @@ swfdec_as_context_do_mark (SwfdecAsContext *context)
 {
   /* This if is needed for SwfdecPlayer */
   if (context->global) {
-    swfdec_as_object_mark (context->global);
-    swfdec_as_object_mark (context->Function);
-    swfdec_as_object_mark (context->Function_prototype);
-    swfdec_as_object_mark (context->Object);
-    swfdec_as_object_mark (context->Object_prototype);
+    swfdec_gc_object_mark (context->global);
+    swfdec_gc_object_mark (context->Function);
+    swfdec_gc_object_mark (context->Function_prototype);
+    swfdec_gc_object_mark (context->Object);
+    swfdec_gc_object_mark (context->Object_prototype);
   }
   if (context->exception)
     swfdec_as_value_mark (&context->exception_value);
diff --git a/swfdec/swfdec_as_context.h b/swfdec/swfdec_as_context.h
index e517992..1e56dc6 100644
--- a/swfdec/swfdec_as_context.h
+++ b/swfdec/swfdec_as_context.h
@@ -1,5 +1,5 @@
 /* Swfdec
- * Copyright (C) 2007 Benjamin Otte <otte at gnome.org>
+ * Copyright (C) 2007-2008 Benjamin Otte <otte at gnome.org>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -125,7 +125,6 @@ void		swfdec_as_context_use_mem	(SwfdecAsContext *	context,
 						 gsize			bytes);
 void		swfdec_as_context_unuse_mem   	(SwfdecAsContext *	context,
 						 gsize			bytes);
-void		swfdec_as_object_mark		(SwfdecAsObject *	object);
 void		swfdec_as_value_mark		(SwfdecAsValue *	value);
 void		swfdec_as_string_mark		(const char *		string);
 void		swfdec_as_context_gc		(SwfdecAsContext *	context);
diff --git a/swfdec/swfdec_as_date.c b/swfdec/swfdec_as_date.c
index eb37f66..1b3c0e6 100644
--- a/swfdec/swfdec_as_date.c
+++ b/swfdec/swfdec_as_date.c
@@ -1016,9 +1016,7 @@ swfdec_as_date_construct (SwfdecAsContext *cx, SwfdecAsObject *object,
 
   if (!cx->frame->construct) {
     SwfdecAsValue val;
-    swfdec_as_context_use_mem (cx, sizeof (SwfdecAsDate));
-    object = g_object_new (SWFDEC_TYPE_AS_DATE, NULL);
-    swfdec_as_object_add (object, cx, sizeof (SwfdecAsDate));
+    object = g_object_new (SWFDEC_TYPE_AS_DATE, "context", cx, NULL);
     swfdec_as_object_get_variable (cx->global, SWFDEC_AS_STR_Date, &val);
     if (SWFDEC_AS_VALUE_IS_OBJECT (&val)) {
       swfdec_as_object_set_constructor (object,
@@ -1031,9 +1029,9 @@ swfdec_as_date_construct (SwfdecAsContext *cx, SwfdecAsObject *object,
   date = SWFDEC_AS_DATE (object);
 
   /* FIXME: find a general solution here */
-  if (SWFDEC_IS_PLAYER (SWFDEC_AS_OBJECT (date)->context)) {
+  if (SWFDEC_IS_PLAYER (swfdec_gc_object_get_context (date))) {
     date->utc_offset =
-      SWFDEC_PLAYER (SWFDEC_AS_OBJECT (date)->context)->priv->system->utc_offset;
+      SWFDEC_PLAYER (swfdec_gc_object_get_context (date))->priv->system->utc_offset;
   }
 
   // don't accept arguments when not constructing
@@ -1170,10 +1168,7 @@ swfdec_as_date_new (SwfdecAsContext *context, double milliseconds,
 
   g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context), NULL);
 
-  swfdec_as_context_use_mem (context, sizeof (SwfdecAsDate));
-
-  ret = g_object_new (SWFDEC_TYPE_AS_DATE, NULL);
-  swfdec_as_object_add (ret, context, sizeof (SwfdecAsDate));
+  ret = g_object_new (SWFDEC_TYPE_AS_DATE, "context", context, NULL);
   swfdec_as_object_get_variable (context->global, SWFDEC_AS_STR_Date, &val);
   if (SWFDEC_AS_VALUE_IS_OBJECT (&val))
     swfdec_as_object_set_constructor (ret, SWFDEC_AS_VALUE_GET_OBJECT (&val));
diff --git a/swfdec/swfdec_as_frame.c b/swfdec/swfdec_as_frame.c
index 0604f04..f85843c 100644
--- a/swfdec/swfdec_as_frame.c
+++ b/swfdec/swfdec_as_frame.c
@@ -87,7 +87,7 @@ swfdec_as_stack_iterator_init_arguments (SwfdecAsStackIterator *iter, SwfdecAsFr
     iter->current = NULL;
     return NULL;
   }
-  context = SWFDEC_AS_OBJECT (frame)->context;
+  context = swfdec_gc_object_get_context (frame);
   if (frame->argv) {
     iter->stack = NULL;
     iter->current = (SwfdecAsValue *) frame->argv;
@@ -134,7 +134,7 @@ swfdec_as_stack_iterator_init (SwfdecAsStackIterator *iter, SwfdecAsFrame *frame
   g_return_val_if_fail (iter != NULL, NULL);
   g_return_val_if_fail (SWFDEC_IS_AS_FRAME (frame), NULL);
 
-  context = SWFDEC_AS_OBJECT (frame)->context;
+  context = swfdec_gc_object_get_context (frame);
   iter->i = 0;
   stack = context->stack;
   if (context->frame == frame) {
@@ -293,27 +293,27 @@ swfdec_as_frame_dispose (GObject *object)
 }
 
 static void
-swfdec_as_frame_mark (SwfdecAsObject *object)
+swfdec_as_frame_mark (SwfdecGcObject *object)
 {
   SwfdecAsFrame *frame = SWFDEC_AS_FRAME (object);
   guint i;
 
   if (frame->next)
-    swfdec_as_object_mark (SWFDEC_AS_OBJECT (frame->next));
-  g_slist_foreach (frame->scope_chain, (GFunc) swfdec_as_object_mark, NULL);
+    swfdec_gc_object_mark (frame->next);
+  g_slist_foreach (frame->scope_chain, (GFunc) swfdec_gc_object_mark, NULL);
   if (frame->thisp)
-    swfdec_as_object_mark (frame->thisp);
+    swfdec_gc_object_mark (frame->thisp);
   if (frame->super)
-    swfdec_as_object_mark (frame->super);
-  swfdec_as_object_mark (frame->target);
-  swfdec_as_object_mark (frame->original_target);
+    swfdec_gc_object_mark (frame->super);
+  swfdec_gc_object_mark (frame->target);
+  swfdec_gc_object_mark (frame->original_target);
   if (frame->function)
-    swfdec_as_object_mark (SWFDEC_AS_OBJECT (frame->function));
+    swfdec_gc_object_mark (frame->function);
   for (i = 0; i < frame->n_registers; i++) {
     swfdec_as_value_mark (&frame->registers[i]);
   }
   /* don't mark argv, it's const, others have to take care of it */
-  SWFDEC_AS_OBJECT_CLASS (swfdec_as_frame_parent_class)->mark (object);
+  SWFDEC_GC_OBJECT_CLASS (swfdec_as_frame_parent_class)->mark (object);
 }
 
 static char *
@@ -356,11 +356,13 @@ static void
 swfdec_as_frame_class_init (SwfdecAsFrameClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  SwfdecGcObjectClass *gc_class = SWFDEC_GC_OBJECT_CLASS (klass);
   SwfdecAsObjectClass *asobject_class = SWFDEC_AS_OBJECT_CLASS (klass);
 
   object_class->dispose = swfdec_as_frame_dispose;
 
-  asobject_class->mark = swfdec_as_frame_mark;
+  gc_class->mark = swfdec_as_frame_mark;
+
   asobject_class->debug = swfdec_as_frame_debug;
 }
 
@@ -375,7 +377,7 @@ swfdec_as_frame_init (SwfdecAsFrame *frame)
 static void
 swfdec_as_frame_load (SwfdecAsFrame *frame)
 {
-  SwfdecAsContext *context = SWFDEC_AS_OBJECT (frame)->context;
+  SwfdecAsContext *context = swfdec_gc_object_get_context (frame);
 
   frame->stack_begin = context->cur;
   context->base = frame->stack_begin;
@@ -394,9 +396,7 @@ swfdec_as_frame_new (SwfdecAsContext *context, SwfdecScript *script)
   g_return_val_if_fail (script != NULL, NULL);
   
   size = sizeof (SwfdecAsFrame) + sizeof (SwfdecAsValue) * script->n_registers;
-  swfdec_as_context_use_mem (context, size);
-  frame = g_object_new (SWFDEC_TYPE_AS_FRAME, NULL);
-  swfdec_as_object_add (SWFDEC_AS_OBJECT (frame), context, size);
+  frame = g_object_new (SWFDEC_TYPE_AS_FRAME, "context", context, NULL);
   frame->script = swfdec_script_ref (script);
   frame->function_name = script->name;
   SWFDEC_DEBUG ("new frame for function %s", frame->function_name);
@@ -424,10 +424,8 @@ swfdec_as_frame_new_native (SwfdecAsContext *context)
   g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context), NULL);
   
   size = sizeof (SwfdecAsFrame);
-  swfdec_as_context_use_mem (context, size);
-  frame = g_object_new (SWFDEC_TYPE_AS_FRAME, NULL);
+  frame = g_object_new (SWFDEC_TYPE_AS_FRAME, "context", context, NULL);
   SWFDEC_DEBUG ("new native frame");
-  swfdec_as_object_add (SWFDEC_AS_OBJECT (frame), context, size);
   swfdec_as_frame_load (frame);
   return frame;
 }
@@ -450,7 +448,7 @@ swfdec_as_frame_return (SwfdecAsFrame *frame, SwfdecAsValue *return_value)
   SwfdecAsFrame *next;
 
   g_return_if_fail (SWFDEC_IS_AS_FRAME (frame));
-  context = SWFDEC_AS_OBJECT (frame)->context;
+  context = swfdec_gc_object_get_context (frame);
   g_return_if_fail (frame == context->frame);
 
   /* save return value in case it was on the stack somewhere */
@@ -561,7 +559,7 @@ swfdec_as_frame_get_variable_and_flags (SwfdecAsFrame *frame, const char *variab
   g_return_val_if_fail (SWFDEC_IS_AS_FRAME (frame), NULL);
   g_return_val_if_fail (variable != NULL, NULL);
 
-  cx = SWFDEC_AS_OBJECT (frame)->context;
+  cx = swfdec_gc_object_get_context (frame);
 
   for (walk = frame->scope_chain; walk; walk = walk->next) {
     if (swfdec_as_object_get_variable_and_flags (walk->data, variable, value, 
@@ -584,7 +582,7 @@ swfdec_as_frame_get_variable_and_flags (SwfdecAsFrame *frame, const char *variab
   /* FIXME: ignored on version 4, but should it never be created instead? */
   if (cx->version > 4 && swfdec_as_object_get_variable_and_flags (cx->global,
 	variable, value, flags, pobject))
-    return SWFDEC_AS_OBJECT (frame)->context->global;
+    return swfdec_gc_object_get_context (frame)->global;
 
   return NULL;
 }
@@ -645,7 +643,7 @@ swfdec_as_frame_delete_variable (SwfdecAsFrame *frame, const char *variable)
   if (ret)
     return ret;
   /* 2) the global object */
-  return swfdec_as_object_delete_variable (SWFDEC_AS_OBJECT (frame)->context->global, variable);
+  return swfdec_as_object_delete_variable (swfdec_gc_object_get_context (frame)->global, variable);
 }
 
 /**
@@ -686,7 +684,7 @@ swfdec_as_frame_preload (SwfdecAsFrame *frame)
 
   /* setup */
   object = SWFDEC_AS_OBJECT (frame);
-  context = object->context;
+  context = swfdec_gc_object_get_context (frame);
   script = frame->script;
   if (frame->script == NULL)
     goto out;
@@ -826,7 +824,7 @@ swfdec_as_frame_handle_exception (SwfdecAsFrame *frame)
   SwfdecAsContext *cx;
 
   g_return_if_fail (SWFDEC_IS_AS_FRAME (frame));
-  cx = SWFDEC_AS_OBJECT (frame)->context;
+  cx = swfdec_gc_object_get_context (frame);
   g_return_if_fail (cx->exception);
 
   /* pop blocks in the hope that we are inside a Try block */
diff --git a/swfdec/swfdec_as_function.c b/swfdec/swfdec_as_function.c
index 4e534c9..3096ad3 100644
--- a/swfdec/swfdec_as_function.c
+++ b/swfdec/swfdec_as_function.c
@@ -84,7 +84,7 @@ swfdec_as_function_set_constructor (SwfdecAsFunction *fun)
   g_return_if_fail (SWFDEC_IS_AS_FUNCTION (fun));
 
   object = SWFDEC_AS_OBJECT (fun);
-  context = object->context;
+  context = swfdec_gc_object_get_context (fun);
   if (context->Function == NULL)
     return;
   
diff --git a/swfdec/swfdec_as_internal.h b/swfdec/swfdec_as_internal.h
index 7b634d7..798f442 100644
--- a/swfdec/swfdec_as_internal.h
+++ b/swfdec/swfdec_as_internal.h
@@ -34,6 +34,9 @@ G_BEGIN_DECLS
 
 #define SWFDEC_AS_OBJECT_PROTOTYPE_RECURSION_LIMIT 256
 
+#define SWFDEC_AS_GC_MARK (1 << 0)		/* only valid during GC */
+#define SWFDEC_AS_GC_ROOT (1 << 1)		/* for objects: rooted, for strings: static */
+
 void		swfdec_as_function_set_constructor	(SwfdecAsFunction *	fun);
 void		swfdec_as_function_init_context		(SwfdecAsContext *	context);
 SwfdecAsFrame *	swfdec_as_function_call_no_preload	(SwfdecAsFunction *	function, 
@@ -56,7 +59,6 @@ typedef const char *(* SwfdecAsVariableForeachRename) (SwfdecAsObject *object,
 
 SwfdecAsValue *	swfdec_as_object_peek_variable	(SwfdecAsObject *       object,
 						 const char *		name);
-void		swfdec_as_object_collect	(SwfdecAsObject *     	object);
 guint		swfdec_as_object_foreach_remove	(SwfdecAsObject *       object,
 						 SwfdecAsVariableForeach func,
 						 gpointer		data);
diff --git a/swfdec/swfdec_as_interpret.c b/swfdec/swfdec_as_interpret.c
index 4f77e79..0031257 100644
--- a/swfdec/swfdec_as_interpret.c
+++ b/swfdec/swfdec_as_interpret.c
@@ -945,7 +945,7 @@ swfdec_action_add2_to_primitive (SwfdecAsValue *value)
   if (SWFDEC_IS_MOVIE (object))
     return;
 
-  if (SWFDEC_IS_AS_DATE (object) && object->context->version > 5)
+  if (SWFDEC_IS_AS_DATE (object) && swfdec_gc_object_get_context (object)->version > 5)
     name = SWFDEC_AS_STR_toString;
   else
     name = SWFDEC_AS_STR_valueOf;
@@ -1152,22 +1152,24 @@ static gboolean
 swfdec_as_interpret_encode_variables_foreach (SwfdecAsObject *object,
     const char *variable, SwfdecAsValue *value, guint flags, gpointer data)
 {
+  SwfdecAsContext *context;
   GString *variables = data;
   char *escaped;
 
+  context = swfdec_gc_object_get_context (object);
   // FIXME: check propflags?
 
   if (variables->len > 0)
     g_string_append_c (variables, '&');
 
-  escaped = swfdec_as_string_escape (object->context, variable);
+  escaped = swfdec_as_string_escape (context, variable);
   g_string_append (variables, escaped);
   g_free (escaped);
 
   g_string_append_c (variables, '=');
 
-  escaped = swfdec_as_string_escape (object->context,
-      swfdec_as_value_to_string (object->context, value));
+  escaped = swfdec_as_string_escape (context,
+      swfdec_as_value_to_string (context, value));
   g_string_append (variables, escaped);
   g_free (escaped);
 
@@ -2409,7 +2411,8 @@ swfdec_action_do_enumerate (SwfdecAsContext *cx, SwfdecAsObject *object)
     object = swfdec_as_object_get_prototype (object);
   }
   if (i == 256) {
-    swfdec_as_context_abort (object->context, "Prototype recursion limit exceeded");
+    swfdec_as_context_abort (swfdec_gc_object_get_context (object),
+	"Prototype recursion limit exceeded");
     g_slist_free (list);
     return;
   }
@@ -2600,7 +2603,7 @@ swfdec_action_try_end_finally (SwfdecAsFrame *frame, gpointer data)
   g_return_if_fail (SWFDEC_IS_AS_FRAME (frame));
   g_return_if_fail (SWFDEC_IS_AS_VALUE (exception_value));
 
-  cx = SWFDEC_AS_OBJECT (frame)->context;
+  cx = swfdec_gc_object_get_context (frame);
 
   // finally has ended and we had exception stored, throw it
   if (!cx->exception)
@@ -2619,7 +2622,7 @@ swfdec_action_try_end_catch (SwfdecAsFrame *frame, gpointer data)
   g_return_if_fail (SWFDEC_IS_AS_FRAME (frame));
   g_return_if_fail (try_data != NULL);
 
-  cx = SWFDEC_AS_OBJECT (frame)->context;
+  cx = swfdec_gc_object_get_context (frame);
 
   if (try_data->scope_object) {
     g_assert (frame->scope_chain->data == try_data->scope_object);
@@ -2664,7 +2667,7 @@ swfdec_action_try_end_try (SwfdecAsFrame *frame, gpointer data)
     return;
   }
 
-  cx = SWFDEC_AS_OBJECT (frame)->context;
+  cx = swfdec_gc_object_get_context (frame);
 
   if (swfdec_as_context_catch (cx, &val))
   {
diff --git a/swfdec/swfdec_as_native_function.c b/swfdec/swfdec_as_native_function.c
index b1f6be4..c6c2b7a 100644
--- a/swfdec/swfdec_as_native_function.c
+++ b/swfdec/swfdec_as_native_function.c
@@ -59,7 +59,7 @@ swfdec_as_native_function_call (SwfdecAsFunction *function)
   SwfdecAsFrame *frame;
   SwfdecAsContext *cx;
 
-  cx = SWFDEC_AS_OBJECT (function)->context;
+  cx = swfdec_gc_object_get_context (function);
   frame = swfdec_as_frame_new_native (cx);
   if (frame == NULL)
     return NULL;
@@ -143,12 +143,10 @@ swfdec_as_native_function_new (SwfdecAsContext *context, const char *name,
   g_return_val_if_fail (native != NULL, NULL);
   g_return_val_if_fail (prototype == NULL || SWFDEC_IS_AS_OBJECT (prototype), NULL);
 
-  swfdec_as_context_use_mem (context, sizeof (SwfdecAsNativeFunction));
-  fun = g_object_new (SWFDEC_TYPE_AS_NATIVE_FUNCTION, NULL);
+  fun = g_object_new (SWFDEC_TYPE_AS_NATIVE_FUNCTION, "context", context, NULL);
   fun->native = native;
   fun->min_args = min_args;
   fun->name = g_strdup (name);
-  swfdec_as_object_add (SWFDEC_AS_OBJECT (fun), context, sizeof (SwfdecAsNativeFunction));
   /* need to set prototype before setting the constructor or Function.constructor 
    * being CONSTANT disallows setting it. */
   if (prototype) {
diff --git a/swfdec/swfdec_as_number.c b/swfdec/swfdec_as_number.c
index ceb94e6..a7e99f6 100644
--- a/swfdec/swfdec_as_number.c
+++ b/swfdec/swfdec_as_number.c
@@ -53,7 +53,7 @@ swfdec_as_number_construct (SwfdecAsContext *cx, SwfdecAsObject *object,
   double d;
 
   if (argc > 0) {
-    d = swfdec_as_value_to_number (object->context, &argv[0]);
+    d = swfdec_as_value_to_number (swfdec_gc_object_get_context (object), &argv[0]);
   } else {
     d = NAN;
   }
diff --git a/swfdec/swfdec_as_object.c b/swfdec/swfdec_as_object.c
index 8d20123..cd543b3 100644
--- a/swfdec/swfdec_as_object.c
+++ b/swfdec/swfdec_as_object.c
@@ -1,5 +1,5 @@
 /* Swfdec
- * Copyright (C) 2007 Benjamin Otte <otte at gnome.org>
+ * Copyright (C) 2007-2008 Benjamin Otte <otte at gnome.org>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -123,14 +123,82 @@ typedef struct {
   guint			refcount;	/* refcount - misused for recursion detection */
 } SwfdecAsWatch;
 
-G_DEFINE_TYPE (SwfdecAsObject, swfdec_as_object, G_TYPE_OBJECT)
+G_DEFINE_TYPE (SwfdecAsObject, swfdec_as_object, SWFDEC_TYPE_GC_OBJECT)
+
+static gboolean
+swfdec_as_watch_can_recurse (SwfdecAsWatch *watch)
+{
+  guint version;
+
+  version = swfdec_gc_object_get_context (watch->watch)->version;
+  if (version <= 6) {
+    return watch->refcount <= 1;
+  } else {
+    return watch->refcount <= 64 + 1;
+  }
+}
+
+static void
+swfdec_as_watch_ref (SwfdecAsWatch *watch)
+{
+  watch->refcount++;
+}
+
+static void
+swfdec_as_watch_unref (SwfdecAsWatch *watch)
+{
+  watch->refcount--;
+  if (watch->refcount == 0) {
+    swfdec_as_context_unuse_mem (swfdec_gc_object_get_context (watch->watch), 
+	sizeof (SwfdecAsWatch));
+    g_slice_free (SwfdecAsWatch, watch);
+  }
+}
+
+/* This is a huge hack design-wise, but we can't use watch->watch, 
+ * it might be gone already */
+static gboolean
+swfdec_as_object_steal_watches (gpointer key, gpointer value, gpointer object)
+{
+  SwfdecAsWatch *watch = value;
+
+  g_assert (watch->refcount == 1);
+  watch->watch = (SwfdecAsFunction *) object;
+  swfdec_as_watch_unref (watch);
+  return TRUE;
+}
+
+static void
+swfdec_as_object_free_property (gpointer key, gpointer value, gpointer data)
+{
+  SwfdecAsObject *object = data;
+
+  swfdec_as_context_unuse_mem (swfdec_gc_object_get_context (object), sizeof (SwfdecAsVariable));
+  g_slice_free (SwfdecAsVariable, value);
+}
 
 static void
 swfdec_as_object_dispose (GObject *gobject)
 {
+  SwfdecAsContext *context = swfdec_gc_object_get_context (gobject);
   SwfdecAsObject *object = SWFDEC_AS_OBJECT (gobject);
 
-  g_assert (object->properties == NULL);
+  if (context->debugger) {
+    SwfdecAsDebuggerClass *klass = SWFDEC_AS_DEBUGGER_GET_CLASS (context->debugger);
+    if (klass->remove)
+      klass->remove (context->debugger, context, object);
+  }
+
+  if (object->properties) {
+    g_hash_table_foreach (object->properties, swfdec_as_object_free_property, object);
+    g_hash_table_destroy (object->properties);
+    object->properties = NULL;
+  }
+  if (object->watches) {
+    g_hash_table_foreach_steal (object->watches, swfdec_as_object_steal_watches, object);
+    g_hash_table_destroy (object->watches);
+    object->watches = NULL;
+  }
   g_slist_free (object->interfaces);
   object->interfaces = NULL;
 
@@ -138,44 +206,41 @@ swfdec_as_object_dispose (GObject *gobject)
 }
 
 static void
-swfdec_as_object_mark_property (gpointer key, gpointer value, gpointer unused)
+swfdec_gc_object_mark_property (gpointer key, gpointer value, gpointer unused)
 {
   SwfdecAsVariable *var = value;
 
   swfdec_as_string_mark (key);
   if (var->get) {
-    swfdec_as_object_mark (SWFDEC_AS_OBJECT (var->get));
+    swfdec_gc_object_mark (var->get);
     if (var->set)
-      swfdec_as_object_mark (SWFDEC_AS_OBJECT (var->set));
+      swfdec_gc_object_mark (var->set);
   } else {
     swfdec_as_value_mark (&var->value);
   }
 }
 
 static void
-swfdec_as_object_mark_watch (gpointer key, gpointer value, gpointer unused)
+swfdec_gc_object_mark_watch (gpointer key, gpointer value, gpointer unused)
 {
   SwfdecAsWatch *watch = value;
 
   swfdec_as_string_mark (key);
-  swfdec_as_object_mark (SWFDEC_AS_OBJECT (watch->watch));
+  swfdec_gc_object_mark (watch->watch);
   swfdec_as_value_mark (&watch->watch_data);
 }
 
 static void
-swfdec_as_object_do_mark (SwfdecAsObject *object)
+swfdec_as_object_mark (SwfdecGcObject *gc)
 {
+  SwfdecAsObject *object = SWFDEC_AS_OBJECT (gc);
+
   if (object->prototype)
-    swfdec_as_object_mark (object->prototype);
-  g_hash_table_foreach (object->properties, swfdec_as_object_mark_property, NULL);
+    swfdec_gc_object_mark (object->prototype);
+  g_hash_table_foreach (object->properties, swfdec_gc_object_mark_property, NULL);
   if (object->watches)
-    g_hash_table_foreach (object->watches, swfdec_as_object_mark_watch, NULL);
-  g_slist_foreach (object->interfaces, (GFunc) swfdec_as_object_mark, NULL); 
-}
-
-static void
-swfdec_as_object_do_add (SwfdecAsObject *object)
-{
+    g_hash_table_foreach (object->watches, swfdec_gc_object_mark_watch, NULL);
+  g_slist_foreach (object->interfaces, (GFunc) swfdec_gc_object_mark, NULL); 
 }
 
 static gboolean
@@ -195,7 +260,7 @@ swfdec_as_object_hash_lookup (SwfdecAsObject *object, const char *variable)
 {
   SwfdecAsVariable *var = g_hash_table_lookup (object->properties, variable);
 
-  if (var || object->context->version >= 7)
+  if (var || swfdec_gc_object_get_context (object)->version >= 7)
     return var;
   var = g_hash_table_find (object->properties, swfdec_as_object_lookup_case_insensitive, (gpointer) variable);
   return var;
@@ -208,7 +273,7 @@ swfdec_as_object_hash_create (SwfdecAsObject *object, const char *variable, guin
 
   if (!swfdec_as_variable_name_is_valid (variable))
     return NULL;
-  swfdec_as_context_use_mem (object->context, sizeof (SwfdecAsVariable));
+  swfdec_as_context_use_mem (swfdec_gc_object_get_context (object), sizeof (SwfdecAsVariable));
   var = g_slice_new0 (SwfdecAsVariable);
   var->flags = flags;
   g_hash_table_insert (object->properties, (gpointer) variable, var);
@@ -245,12 +310,12 @@ swfdec_as_object_do_get (SwfdecAsObject *object, SwfdecAsObject *orig,
 
   /* variable flag checks */
   if (!swfdec_as_object_variable_enabled_in_version (var,
-	object->context->version))
+	swfdec_gc_object_get_context (object)->version))
     return FALSE;
 
   if (var->get) {
     swfdec_as_function_call (var->get, orig, 0, NULL, val);
-    swfdec_as_context_run (object->context);
+    swfdec_as_context_run (swfdec_gc_object_get_context (object));
     *flags = var->flags;
   } else {
     *val = var->value;
@@ -264,7 +329,7 @@ swfdec_as_watch_new (SwfdecAsFunction *function)
 {
   SwfdecAsWatch *watch;
 
-  swfdec_as_context_use_mem (SWFDEC_AS_OBJECT (function)->context, 
+  swfdec_as_context_use_mem (swfdec_gc_object_get_context (function), 
       sizeof (SwfdecAsWatch));
 
   watch = g_slice_new (SwfdecAsWatch);
@@ -274,36 +339,6 @@ swfdec_as_watch_new (SwfdecAsFunction *function)
   return watch;
 }
 
-static gboolean
-swfdec_as_watch_can_recurse (SwfdecAsWatch *watch)
-{
-  guint version;
-
-  version = SWFDEC_AS_OBJECT (watch->watch)->context->version;
-  if (version <= 6) {
-    return watch->refcount <= 1;
-  } else {
-    return watch->refcount <= 64 + 1;
-  }
-}
-
-static void
-swfdec_as_watch_ref (SwfdecAsWatch *watch)
-{
-  watch->refcount++;
-}
-
-static void
-swfdec_as_watch_unref (SwfdecAsWatch *watch)
-{
-  watch->refcount--;
-  if (watch->refcount == 0) {
-    swfdec_as_context_unuse_mem (SWFDEC_AS_OBJECT (watch->watch)->context, 
-	sizeof (SwfdecAsWatch));
-    g_slice_free (SwfdecAsWatch, watch);
-  }
-}
-
 /*
  * Like swfdec_as_object_get_prototype, but doesn't check 8_UP flag when
  * version is 7 and doesn't check if the property has been deleted if version
@@ -316,7 +351,7 @@ swfdec_as_object_get_prototype_internal (SwfdecAsObject *object)
 
   g_return_val_if_fail (SWFDEC_IS_AS_OBJECT (object), NULL);
 
-  version = object->context->version;
+  version = swfdec_gc_object_get_context (object)->version;
 
   if (object->prototype == NULL)
     return NULL;
@@ -349,7 +384,7 @@ swfdec_as_object_get_prototype (SwfdecAsObject *object)
 
   g_return_val_if_fail (SWFDEC_IS_AS_OBJECT (object), NULL);
 
-  version = object->context->version;
+  version = swfdec_gc_object_get_context (object)->version;
 
   prototype = swfdec_as_object_get_prototype_internal (object);
 
@@ -399,7 +434,7 @@ swfdec_as_object_hash_lookup_with_prototype (SwfdecAsObject *object,
     }
 
     if (i == SWFDEC_AS_OBJECT_PROTOTYPE_RECURSION_LIMIT) {
-      swfdec_as_context_abort (object->context, "Prototype recursion limit exceeded");
+      swfdec_as_context_abort (swfdec_gc_object_get_context (object), "Prototype recursion limit exceeded");
       return NULL;
     }
   }
@@ -422,12 +457,12 @@ swfdec_as_object_do_set (SwfdecAsObject *object, const char *variable,
     return;
 
   var = swfdec_as_object_hash_lookup_with_prototype (object, variable, &proto);
-  if (swfdec_as_context_is_aborted (object->context))
+  if (swfdec_as_context_is_aborted (swfdec_gc_object_get_context (object)))
     return;
 
   // if variable is disabled in this version
   if (var != NULL && !swfdec_as_object_variable_enabled_in_version (var,
-	object->context->version)) {
+	swfdec_gc_object_get_context (object)->version)) {
     if (proto == NULL) {
       // it's at the top level, remove getter and setter plus overwrite
       var->get = NULL;
@@ -446,7 +481,7 @@ swfdec_as_object_do_set (SwfdecAsObject *object, const char *variable,
     if (var->flags & SWFDEC_AS_VARIABLE_CONSTANT)
       return;
     // remove the flags that could make this variable hidden
-    if (object->context->version == 6) {
+    if (swfdec_gc_object_get_context (object)->version == 6) {
       // version 6, so let's forget SWFDEC_AS_VARIABLE_VERSION_7_UP flag, oops!
       // we will still set the value though, even if that flag is set
       var->flags &= ~(SWFDEC_AS_VARIABLE_VERSION_6_UP |
@@ -471,11 +506,11 @@ swfdec_as_object_do_set (SwfdecAsObject *object, const char *variable,
       args[3] = watch->watch_data;
       swfdec_as_watch_ref (watch);
       swfdec_as_function_call (watch->watch, object, 4, args, &ret);
-      swfdec_as_context_run (object->context);
+      swfdec_as_context_run (swfdec_gc_object_get_context (object));
       swfdec_as_watch_unref (watch);
       var = swfdec_as_object_hash_lookup_with_prototype (object, variable,
 	  NULL);
-      if (swfdec_as_context_is_aborted (object->context))
+      if (swfdec_as_context_is_aborted (swfdec_gc_object_get_context (object)))
 	return;
       if (var == NULL) {
 	SWFDEC_INFO ("watch removed variable %s", variable);
@@ -491,7 +526,7 @@ swfdec_as_object_do_set (SwfdecAsObject *object, const char *variable,
     if (var->set) {
       SwfdecAsValue tmp;
       swfdec_as_function_call (var->set, object, 1, val, &tmp);
-      swfdec_as_context_run (object->context);
+      swfdec_as_context_run (swfdec_gc_object_get_context (object));
     }
   } else if (watch == NULL) {
     var->value = *val;
@@ -522,15 +557,6 @@ swfdec_as_object_do_set_flags (SwfdecAsObject *object, const char *variable, gui
   }
 }
 
-static void
-swfdec_as_object_free_property (gpointer key, gpointer value, gpointer data)
-{
-  SwfdecAsObject *object = data;
-
-  swfdec_as_context_unuse_mem (object->context, sizeof (SwfdecAsVariable));
-  g_slice_free (SwfdecAsVariable, value);
-}
-
 static SwfdecAsDeleteReturn
 swfdec_as_object_do_delete (SwfdecAsObject *object, const char *variable)
 {
@@ -681,15 +707,37 @@ swfdec_as_object_do_debug (SwfdecAsObject *object)
   return g_strdup ("Object");
 }
 
+static GObject *
+swfdec_as_object_constructor (GType type, guint n_construct_properties,
+    GObjectConstructParam *construct_properties)
+{
+  GObject *gobject;
+  SwfdecAsContext *context;
+
+  gobject = G_OBJECT_CLASS (swfdec_as_object_parent_class)->constructor (type, 
+      n_construct_properties, construct_properties);
+
+  context = swfdec_gc_object_get_context (gobject);
+  if (context->debugger) {
+    SwfdecAsDebuggerClass *dklass = SWFDEC_AS_DEBUGGER_GET_CLASS (context->debugger);
+    if (dklass->add)
+      dklass->add (context->debugger, context, SWFDEC_AS_OBJECT (gobject));
+  }
+
+  return gobject;
+}
+
 static void
 swfdec_as_object_class_init (SwfdecAsObjectClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  SwfdecGcObjectClass *gc_class = SWFDEC_GC_OBJECT_CLASS (klass);
 
+  object_class->constructor = swfdec_as_object_constructor;
   object_class->dispose = swfdec_as_object_dispose;
 
-  klass->mark = swfdec_as_object_do_mark;
-  klass->add = swfdec_as_object_do_add;
+  gc_class->mark = swfdec_as_object_mark;
+
   klass->get = swfdec_as_object_do_get;
   klass->set = swfdec_as_object_do_set;
   klass->set_flags = swfdec_as_object_do_set_flags;
@@ -701,6 +749,7 @@ swfdec_as_object_class_init (SwfdecAsObjectClass *klass)
 static void
 swfdec_as_object_init (SwfdecAsObject *object)
 {
+  object->properties = g_hash_table_new (g_direct_hash, g_direct_equal);
 }
 
 /**
@@ -717,14 +766,9 @@ swfdec_as_object_init (SwfdecAsObject *object)
 SwfdecAsObject *
 swfdec_as_object_new_empty (SwfdecAsContext *context)
 {
-  SwfdecAsObject *object;
-
   g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context), NULL);
   
-  swfdec_as_context_use_mem (context, sizeof (SwfdecAsObject));
-  object = g_object_new (SWFDEC_TYPE_AS_OBJECT, NULL);
-  swfdec_as_object_add (object, context, sizeof (SwfdecAsObject));
-  return object;
+  return g_object_new (SWFDEC_TYPE_AS_OBJECT, "context", context, NULL);
 }
 
 /**
@@ -757,73 +801,6 @@ swfdec_as_object_new (SwfdecAsContext *context)
 }
 
 /**
- * swfdec_as_object_add:
- * @object: #SwfdecAsObject to make garbage-collected
- * @context: #SwfdecAsContext that should manage the object
- * @size: size the object currently uses
- *
- * Takes over the reference to @object for the garbage collector of @context. 
- * The object may not already be part of a different context. The given @size 
- * must have been allocated before with swfdec_as_context_use_mem ().
- * Note that after swfdec_as_object_add() the garbage collector might hold the
- * only reference to @object.
- **/
-void
-swfdec_as_object_add (SwfdecAsObject *object, SwfdecAsContext *context, gsize size)
-{
-  SwfdecAsObjectClass *klass;
-
-  g_return_if_fail (SWFDEC_IS_AS_OBJECT (object));
-  g_return_if_fail (SWFDEC_IS_AS_CONTEXT (context));
-  g_return_if_fail (object->properties == NULL);
-
-  object->context = context;
-  object->size = size;
-  g_hash_table_insert (context->objects, object, object);
-  object->properties = g_hash_table_new (g_direct_hash, g_direct_equal);
-  klass = SWFDEC_AS_OBJECT_GET_CLASS (object);
-  g_return_if_fail (klass->add);
-  klass->add (object);
-  if (context->debugger) {
-    SwfdecAsDebuggerClass *dklass = SWFDEC_AS_DEBUGGER_GET_CLASS (context->debugger);
-    if (dklass->add)
-      dklass->add (context->debugger, context, object);
-  }
-}
-
-/* This is a huge hack design-wise, but we can't use watch->watch, 
- * it might be gone already */
-static gboolean
-swfdec_as_object_steal_watches (gpointer key, gpointer value, gpointer object)
-{
-  SwfdecAsWatch *watch = value;
-
-  g_assert (watch->refcount == 1);
-  watch->watch = (SwfdecAsFunction *) object;
-  swfdec_as_watch_unref (watch);
-  return TRUE;
-}
-
-void
-swfdec_as_object_collect (SwfdecAsObject *object)
-{
-  g_return_if_fail (SWFDEC_IS_AS_OBJECT (object));
-  g_return_if_fail (object->properties != NULL);
-
-  g_hash_table_foreach (object->properties, swfdec_as_object_free_property, object);
-  g_hash_table_destroy (object->properties);
-  object->properties = NULL;
-  if (object->watches) {
-    g_hash_table_foreach_steal (object->watches, swfdec_as_object_steal_watches, object);
-    g_hash_table_destroy (object->watches);
-    object->watches = NULL;
-  }
-  if (object->size)
-    swfdec_as_context_unuse_mem (object->context, object->size);
-  g_object_unref (object);
-}
-
-/**
  * swfdec_as_object_set_variable:
  * @object: a #SwfdecAsObject
  * @variable: garbage-collected name of the variable to set
@@ -856,11 +833,11 @@ swfdec_as_object_set_variable_and_flags (SwfdecAsObject *object,
   g_return_if_fail (variable != NULL);
   g_return_if_fail (SWFDEC_IS_AS_VALUE (value));
 
-  if (object->context->debugger) {
-    SwfdecAsDebugger *debugger = object->context->debugger;
+  if (swfdec_gc_object_get_context (object)->debugger) {
+    SwfdecAsDebugger *debugger = swfdec_gc_object_get_context (object)->debugger;
     SwfdecAsDebuggerClass *dklass = SWFDEC_AS_DEBUGGER_GET_CLASS (debugger);
     if (dklass->set_variable)
-      dklass->set_variable (debugger, object->context, object, variable, value);
+      dklass->set_variable (debugger, swfdec_gc_object_get_context (object), object, variable, value);
   }
   klass = SWFDEC_AS_OBJECT_GET_CLASS (object);
   klass->set (object, variable, value, default_flags);
@@ -954,14 +931,14 @@ swfdec_as_object_get_variable_and_flags (SwfdecAsObject *object,
       SwfdecAsVariable *var =
 	swfdec_as_object_hash_lookup (cur, SWFDEC_AS_STR___resolve);
 
-      if (var != NULL && (object->context->version <= 6 ||
+      if (var != NULL && (swfdec_gc_object_get_context (object)->version <= 6 ||
 	    SWFDEC_AS_VALUE_IS_OBJECT (&var->value)))
 	resolve = cur;
     }
     cur = swfdec_as_object_get_prototype_internal (cur);
   }
   if (i > SWFDEC_AS_OBJECT_PROTOTYPE_RECURSION_LIMIT) {
-    swfdec_as_context_abort (object->context, "Prototype recursion limit exceeded");
+    swfdec_as_context_abort (swfdec_gc_object_get_context (object), "Prototype recursion limit exceeded");
     SWFDEC_AS_VALUE_SET_UNDEFINED (value);
     *flags = 0;
     *pobject = NULL;
@@ -971,10 +948,12 @@ swfdec_as_object_get_variable_and_flags (SwfdecAsObject *object,
     SwfdecAsValue argv;
     SwfdecAsVariable *var;
     SwfdecAsFunction *fun;
+    SwfdecAsContext *context;
 
     *flags = 0;
     *pobject = resolve;
     SWFDEC_AS_VALUE_SET_UNDEFINED (value);
+    context = swfdec_gc_object_get_context (resolve);
 
     var = swfdec_as_object_hash_lookup (resolve, SWFDEC_AS_STR___resolve);
     g_assert (var != NULL);
@@ -985,9 +964,9 @@ swfdec_as_object_get_variable_and_flags (SwfdecAsObject *object,
       return FALSE;
     SWFDEC_AS_VALUE_SET_STRING (&argv, variable);
     swfdec_as_function_call (fun, resolve, 1, &argv, value);
-    if (swfdec_as_context_is_aborted (resolve->context))
+    if (swfdec_as_context_is_aborted (context))
       return TRUE;
-    swfdec_as_context_run (resolve->context);
+    swfdec_as_context_run (context);
 
     return TRUE;
   }
@@ -1202,12 +1181,12 @@ swfdec_as_object_add_constructor (SwfdecAsObject *object, const char *name, GTyp
 
   if (!native)
     native = swfdec_as_object_do_nothing;
-  function = swfdec_as_native_function_new (object->context, name, native, min_args, prototype);
+  function = swfdec_as_native_function_new (swfdec_gc_object_get_context (object), name, native, min_args, prototype);
   if (type != 0)
     swfdec_as_native_function_set_object_type (SWFDEC_AS_NATIVE_FUNCTION (function), type);
   if (construct_type != 0)
     swfdec_as_native_function_set_construct_type (SWFDEC_AS_NATIVE_FUNCTION (function), construct_type);
-  name = swfdec_as_context_get_string (object->context, name);
+  name = swfdec_as_context_get_string (swfdec_gc_object_get_context (object), name);
   SWFDEC_AS_VALUE_SET_OBJECT (&val, SWFDEC_AS_OBJECT (function));
   /* FIXME: I'd like to make sure no such property exists yet */
   swfdec_as_object_set_variable_and_flags (object, name, &val,
@@ -1231,7 +1210,7 @@ swfdec_as_object_run (SwfdecAsObject *object, SwfdecScript *script)
   g_return_if_fail (SWFDEC_IS_AS_OBJECT (object));
   g_return_if_fail (script != NULL);
 
-  context = object->context;
+  context = swfdec_gc_object_get_context (object);
   frame = swfdec_as_frame_new (context, script);
   if (frame == NULL)
     return;
@@ -1268,7 +1247,7 @@ swfdec_as_object_call (SwfdecAsObject *object, const char *name, guint argc,
   g_return_val_if_fail (SWFDEC_IS_AS_OBJECT (object), TRUE);
   g_return_val_if_fail (name != NULL, TRUE);
   g_return_val_if_fail (argc == 0 || argv != NULL, TRUE);
-  g_return_val_if_fail (object->context->global != NULL, TRUE); /* for SwfdecPlayer */
+  g_return_val_if_fail (swfdec_gc_object_get_context (object)->global != NULL, TRUE); /* for SwfdecPlayer */
 
   if (return_value)
     SWFDEC_AS_VALUE_SET_UNDEFINED (return_value);
@@ -1279,9 +1258,9 @@ swfdec_as_object_call (SwfdecAsObject *object, const char *name, guint argc,
   if (!SWFDEC_IS_AS_FUNCTION (fun))
     return FALSE;
   swfdec_as_function_call (fun, object, argc, argv, return_value ? return_value : &tmp);
-  if (swfdec_as_context_is_aborted (object->context))
+  if (swfdec_as_context_is_aborted (swfdec_gc_object_get_context (object)))
     return TRUE;
-  swfdec_as_context_run (object->context);
+  swfdec_as_context_run (swfdec_gc_object_get_context (object));
 
   return TRUE;
 }
@@ -1312,7 +1291,7 @@ swfdec_as_object_create (SwfdecAsFunction *fun, guint n_args,
 
   g_return_if_fail (SWFDEC_IS_AS_FUNCTION (fun));
 
-  context = SWFDEC_AS_OBJECT (fun)->context;
+  context = swfdec_gc_object_get_context (fun);
   cur = fun;
   do {
     if (SWFDEC_IS_AS_NATIVE_FUNCTION (cur)) {
@@ -1340,10 +1319,8 @@ swfdec_as_object_create (SwfdecAsFunction *fun, guint n_args,
     type = SWFDEC_TYPE_AS_OBJECT;
     size = sizeof (SwfdecAsObject);
   }
-  swfdec_as_context_use_mem (context, size);
 
-  new = g_object_new (type, NULL);
-  swfdec_as_object_add (new, context, size);
+  new = g_object_new (type, "context", context, NULL);
   /* set initial variables */
   if (swfdec_as_object_get_variable (SWFDEC_AS_OBJECT (fun), SWFDEC_AS_STR_prototype, &val)) {
       swfdec_as_object_set_variable_and_flags (new, SWFDEC_AS_STR___proto__,
@@ -1443,13 +1420,13 @@ swfdec_as_object_add_native_variable (SwfdecAsObject *object,
   g_return_if_fail (get != NULL);
 
   get_func =
-    swfdec_as_native_function_new (object->context, variable, get, 0, NULL);
+    swfdec_as_native_function_new (swfdec_gc_object_get_context (object), variable, get, 0, NULL);
   if (get_func == NULL)
     return;
 
   if (set != NULL) {
     set_func =
-      swfdec_as_native_function_new (object->context, variable, set, 0, NULL);
+      swfdec_as_native_function_new (swfdec_gc_object_get_context (object), variable, set, 0, NULL);
   } else {
     set_func = NULL;
   }
@@ -1505,7 +1482,7 @@ swfdec_as_object_hasOwnProperty (SwfdecAsContext *cx, SwfdecAsObject *object,
   if (argc < 1)
     return;
 
-  name = swfdec_as_value_to_string (object->context, &argv[0]);
+  name = swfdec_as_value_to_string (swfdec_gc_object_get_context (object), &argv[0]);
 
   if (!(var = swfdec_as_object_hash_lookup (object, name)))
     return;
@@ -1535,7 +1512,7 @@ swfdec_as_object_isPropertyEnumerable (SwfdecAsContext *cx,
   if (argc < 1)
     return;
 
-  name = swfdec_as_value_to_string (object->context, &argv[0]);
+  name = swfdec_as_value_to_string (swfdec_gc_object_get_context (object), &argv[0]);
 
   if (!(var = swfdec_as_object_hash_lookup (object, name)))
     return;
@@ -1687,7 +1664,7 @@ swfdec_as_object_old_constructor (SwfdecAsContext *cx, SwfdecAsObject *object,
 void
 swfdec_as_object_decode (SwfdecAsObject *object, const char *str)
 {
-  SwfdecAsContext *cx = object->context;
+  SwfdecAsContext *cx = swfdec_gc_object_get_context (object);
   SwfdecAsValue val;
   char **varlist, *p, *unescaped;
   guint i;
diff --git a/swfdec/swfdec_as_object.h b/swfdec/swfdec_as_object.h
index 6394270..c91a9d9 100644
--- a/swfdec/swfdec_as_object.h
+++ b/swfdec/swfdec_as_object.h
@@ -1,5 +1,5 @@
 /* Swfdec
- * Copyright (C) 2007 Benjamin Otte <otte at gnome.org>
+ * Copyright (C) 2007-2008 Benjamin Otte <otte at gnome.org>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -22,6 +22,7 @@
 
 #include <glib-object.h>
 #include <swfdec/swfdec_as_types.h>
+#include <swfdec/swfdec_gc_object.h>
 
 G_BEGIN_DECLS
 
@@ -57,25 +58,18 @@ typedef gboolean (* SwfdecAsVariableForeach) (SwfdecAsObject *object,
 
 struct _SwfdecAsObject {
   /*< protected >*/
-  GObject		object;
-  SwfdecAsContext *	context;	/* context the object belongs to */
+  SwfdecGcObject      	object;
   /*< private >*/
   SwfdecAsObject *	prototype;	/* prototype object (referred to as __proto__) */
   guint			prototype_flags; /* propflags for the prototype object */
   GHashTable *		properties;	/* string->SwfdecAsVariable mapping or NULL when not in GC */
   GHashTable *		watches;	/* string->WatchData mapping or NULL when not watching anything */
-  guint8		flags;		/* GC flags */
-  gsize			size;		/* size reserved in GC */
   GSList *		interfaces;	/* list of interfaces this object implements */
 };
 
 struct _SwfdecAsObjectClass {
-  GObjectClass		object_class;
+  SwfdecGcObjectClass	object_class;
 
-  /* mark everything that should survive during GC */
-  void			(* mark)		(SwfdecAsObject *	object);
-  /* object was added to the context */
-  void			(* add)			(SwfdecAsObject *	object);
   /* get the value and flags for a variables */
   gboolean	      	(* get)			(SwfdecAsObject *       object,
 						 SwfdecAsObject *	orig,
@@ -118,10 +112,6 @@ void		swfdec_as_object_set_constructor(SwfdecAsObject *	object,
 SwfdecAsObject *swfdec_as_object_resolve	(SwfdecAsObject *	object);
 char *		swfdec_as_object_get_debug	(SwfdecAsObject *	object);
 
-void		swfdec_as_object_add		(SwfdecAsObject *     	object,
-						 SwfdecAsContext *    	context,
-						 gsize			size);
-
 /* I'd like to name these [gs]et_property, but binding authors will complain
  * about overlap with g_object_[gs]et_property then */
 #define swfdec_as_object_set_variable(object, variable, value) \
diff --git a/swfdec/swfdec_as_script_function.c b/swfdec/swfdec_as_script_function.c
index 5006c95..d61f4f4 100644
--- a/swfdec/swfdec_as_script_function.c
+++ b/swfdec/swfdec_as_script_function.c
@@ -37,7 +37,7 @@ swfdec_as_script_function_call (SwfdecAsFunction *function)
   SwfdecAsScriptFunction *script = SWFDEC_AS_SCRIPT_FUNCTION (function);
   SwfdecAsFrame *frame;
 
-  frame = swfdec_as_frame_new (SWFDEC_AS_OBJECT (function)->context, script->script);
+  frame = swfdec_as_frame_new (swfdec_gc_object_get_context (function), script->script);
   if (frame == NULL)
     return NULL;
   frame->scope_chain = g_slist_concat (frame->scope_chain, g_slist_copy (script->scope_chain));
@@ -63,13 +63,13 @@ swfdec_as_script_function_dispose (GObject *object)
 }
 
 static void
-swfdec_as_script_function_mark (SwfdecAsObject *object)
+swfdec_as_script_function_mark (SwfdecGcObject *object)
 {
   SwfdecAsScriptFunction *script = SWFDEC_AS_SCRIPT_FUNCTION (object);
 
-  g_slist_foreach (script->scope_chain, (GFunc) swfdec_as_object_mark, NULL);
+  g_slist_foreach (script->scope_chain, (GFunc) swfdec_gc_object_mark, NULL);
 
-  SWFDEC_AS_OBJECT_CLASS (swfdec_as_script_function_parent_class)->mark (object);
+  SWFDEC_GC_OBJECT_CLASS (swfdec_as_script_function_parent_class)->mark (object);
 }
 
 static char *
@@ -96,12 +96,14 @@ static void
 swfdec_as_script_function_class_init (SwfdecAsScriptFunctionClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  SwfdecGcObjectClass *gc_class = SWFDEC_GC_OBJECT_CLASS (klass);
   SwfdecAsObjectClass *asobject_class = SWFDEC_AS_OBJECT_CLASS (klass);
   SwfdecAsFunctionClass *function_class = SWFDEC_AS_FUNCTION_CLASS (klass);
 
   object_class->dispose = swfdec_as_script_function_dispose;
 
-  asobject_class->mark = swfdec_as_script_function_mark;
+  gc_class->mark = swfdec_as_script_function_mark;
+
   asobject_class->debug = swfdec_as_script_function_debug;
 
   function_class->call = swfdec_as_script_function_call;
@@ -123,13 +125,11 @@ swfdec_as_script_function_new (SwfdecAsObject *target, const GSList *scope_chain
   g_return_val_if_fail (SWFDEC_IS_AS_OBJECT (target), NULL);
   g_return_val_if_fail (script != NULL, NULL);
 
-  context = target->context;
-  swfdec_as_context_use_mem (context, sizeof (SwfdecAsScriptFunction));
-  fun = g_object_new (SWFDEC_TYPE_AS_SCRIPT_FUNCTION, NULL);
+  context = swfdec_gc_object_get_context (target);
+  fun = g_object_new (SWFDEC_TYPE_AS_SCRIPT_FUNCTION, "context", context, NULL);
   fun->scope_chain = g_slist_copy ((GSList *) scope_chain);
   fun->script = script;
   fun->target = target;
-  swfdec_as_object_add (SWFDEC_AS_OBJECT (fun), context, sizeof (SwfdecAsScriptFunction));
   /* set prototype */
   proto = swfdec_as_object_new_empty (context);
   SWFDEC_AS_VALUE_SET_OBJECT (&val, proto);
diff --git a/swfdec/swfdec_as_string.c b/swfdec/swfdec_as_string.c
index ff48559..8ac4f4e 100644
--- a/swfdec/swfdec_as_string.c
+++ b/swfdec/swfdec_as_string.c
@@ -35,13 +35,13 @@
 G_DEFINE_TYPE (SwfdecAsString, swfdec_as_string, SWFDEC_TYPE_AS_OBJECT)
 
 static void
-swfdec_as_string_do_mark (SwfdecAsObject *object)
+swfdec_as_string_do_mark (SwfdecGcObject *object)
 {
   SwfdecAsString *string = SWFDEC_AS_STRING (object);
 
   swfdec_as_string_mark (string->string);
 
-  SWFDEC_AS_OBJECT_CLASS (swfdec_as_string_parent_class)->mark (object);
+  SWFDEC_GC_OBJECT_CLASS (swfdec_as_string_parent_class)->mark (object);
 }
 
 static char *
@@ -55,9 +55,11 @@ swfdec_as_string_debug (SwfdecAsObject *object)
 static void
 swfdec_as_string_class_init (SwfdecAsStringClass *klass)
 {
+  SwfdecGcObjectClass *gc_class = SWFDEC_GC_OBJECT_CLASS (klass);
   SwfdecAsObjectClass *asobject_class = SWFDEC_AS_OBJECT_CLASS (klass);
 
-  asobject_class->mark = swfdec_as_string_do_mark;
+  gc_class->mark = swfdec_as_string_do_mark;
+
   asobject_class->debug = swfdec_as_string_debug;
 }
 
diff --git a/swfdec/swfdec_as_super.c b/swfdec/swfdec_as_super.c
index 22a74d2..379c4b0 100644
--- a/swfdec/swfdec_as_super.c
+++ b/swfdec/swfdec_as_super.c
@@ -89,8 +89,10 @@ swfdec_as_super_get (SwfdecAsObject *object, SwfdecAsObject *orig,
     /* FIXME: need get_prototype_internal here? */
     cur = swfdec_as_object_get_prototype (cur);
   }
-  if (i > SWFDEC_AS_OBJECT_PROTOTYPE_RECURSION_LIMIT)
-    swfdec_as_context_abort (object->context, "Prototype recursion limit exceeded");
+  if (i > SWFDEC_AS_OBJECT_PROTOTYPE_RECURSION_LIMIT) {
+    swfdec_as_context_abort (swfdec_gc_object_get_context (object),
+	"Prototype recursion limit exceeded");
+  }
   SWFDEC_AS_VALUE_SET_UNDEFINED (val);
   *flags = 0;
   return FALSE;
@@ -155,14 +157,12 @@ swfdec_as_super_new (SwfdecAsFrame *frame, SwfdecAsObject *thisp, SwfdecAsObject
   
   if (frame->super != NULL)
     return;
-  context = SWFDEC_AS_OBJECT (frame)->context;
+  context = swfdec_gc_object_get_context (frame);
   if (context->version <= 5)
     return;
 
-  swfdec_as_context_use_mem (context, sizeof (SwfdecAsSuper));
-  super = g_object_new (SWFDEC_TYPE_AS_SUPER, NULL);
+  super = g_object_new (SWFDEC_TYPE_AS_SUPER, "context", context, NULL);
   frame->super = SWFDEC_AS_OBJECT (super);
-  swfdec_as_object_add (SWFDEC_AS_OBJECT (super), context, sizeof (SwfdecAsSuper));
   super->thisp = thisp;
   if (context->version <= 5) {
     super->object = NULL;
@@ -199,7 +199,7 @@ swfdec_as_super_new_chain (SwfdecAsFrame *frame, SwfdecAsSuper *super,
   ref = super->object->prototype;
   if (ref == NULL)
     return;
-  context = SWFDEC_AS_OBJECT (frame)->context;
+  context = swfdec_gc_object_get_context (frame);
   if (function_name && context->version > 6) {
     /* skip prototypes to find the next one that has this function defined */
     SwfdecAsObject *res;
diff --git a/swfdec/swfdec_as_types.h b/swfdec/swfdec_as_types.h
index ff22c8f..44e0e8a 100644
--- a/swfdec/swfdec_as_types.h
+++ b/swfdec/swfdec_as_types.h
@@ -49,6 +49,7 @@ typedef void (* SwfdecAsNative) (SwfdecAsContext *	context,
 				 guint			argc,
 				 SwfdecAsValue *	argv,
 				 SwfdecAsValue *	retval);
+typedef struct _SwfdecGcObject SwfdecGcObject;
 typedef struct _SwfdecScript SwfdecScript;
 
 
diff --git a/swfdec/swfdec_bitmap_data.c b/swfdec/swfdec_bitmap_data.c
index 8217308..c5f7b3e 100644
--- a/swfdec/swfdec_bitmap_data.c
+++ b/swfdec/swfdec_bitmap_data.c
@@ -38,7 +38,7 @@ swfdec_bitmap_data_clear (SwfdecBitmapData *bitmap)
   if (bitmap->surface == NULL)
     return;
 
-  swfdec_as_context_unuse_mem (SWFDEC_AS_OBJECT (bitmap)->context, 4 * 
+  swfdec_as_context_unuse_mem (swfdec_gc_object_get_context (bitmap), 4 * 
       cairo_image_surface_get_width (bitmap->surface) *
       cairo_image_surface_get_height (bitmap->surface));
   cairo_surface_destroy (bitmap->surface);
diff --git a/swfdec/swfdec_button.c b/swfdec/swfdec_button.c
index 60a93de..aa3a8c1 100644
--- a/swfdec/swfdec_button.c
+++ b/swfdec/swfdec_button.c
@@ -61,20 +61,6 @@ swfdec_button_dispose (GObject *object)
   G_OBJECT_CLASS (swfdec_button_parent_class)->dispose (G_OBJECT (button));
 }
 
-static SwfdecMovie *
-swfdec_button_create_movie (SwfdecGraphic *graphic, gsize *size)
-{
-  SwfdecButton *button = SWFDEC_BUTTON (graphic);
-  SwfdecButtonMovie *movie = g_object_new (SWFDEC_TYPE_BUTTON_MOVIE, NULL);
-
-  movie->button = g_object_ref (button);
-  *size = sizeof (SwfdecButtonMovie);
-  if (button->events)
-    SWFDEC_ACTOR (movie)->events = swfdec_event_list_copy (button->events);
-
-  return SWFDEC_MOVIE (movie);
-}
-
 static void
 swfdec_button_class_init (SwfdecButtonClass * g_class)
 {
@@ -83,7 +69,7 @@ swfdec_button_class_init (SwfdecButtonClass * g_class)
 
   object_class->dispose = swfdec_button_dispose;
 
-  graphic_class->create_movie = swfdec_button_create_movie;
+  graphic_class->movie_type = SWFDEC_TYPE_BUTTON_MOVIE;
 }
 
 static guint
diff --git a/swfdec/swfdec_button_movie.c b/swfdec/swfdec_button_movie.c
index 90364f3..d4d23f9 100644
--- a/swfdec/swfdec_button_movie.c
+++ b/swfdec/swfdec_button_movie.c
@@ -36,8 +36,7 @@ static void
 swfdec_button_movie_update_extents (SwfdecMovie *movie,
     SwfdecRect *extents)
 {
-  swfdec_rect_union (extents, extents, 
-      &SWFDEC_GRAPHIC (SWFDEC_BUTTON_MOVIE (movie)->button)->extents);
+  swfdec_rect_union (extents, extents, &movie->graphic->extents);
 }
 
 static void
@@ -72,7 +71,7 @@ swfdec_button_movie_perform_place (SwfdecButtonMovie *button, SwfdecBits *bits)
     return;
   }
 
-  player = SWFDEC_PLAYER (SWFDEC_AS_OBJECT (movie)->context);
+  player = SWFDEC_PLAYER (swfdec_gc_object_get_context (movie));
   new = swfdec_movie_new (player, depth, movie, movie->resource, graphic, NULL);
   swfdec_bits_get_matrix (bits, &trans, NULL);
   if (swfdec_bits_left (bits)) {
@@ -119,17 +118,19 @@ swfdec_button_movie_set_state (SwfdecButtonMovie *button, SwfdecButtonState stat
   GSList *walk;
   guint old, new, i;
   int depth;
+  SwfdecButton *but;
 
   if (button->state == state) {
     SWFDEC_LOG ("not changing state, it's already in %d", state);
     return;
   }
   SWFDEC_DEBUG ("changing state from %d to %d", button->state, state);
+  but = SWFDEC_BUTTON (movie->graphic);
   /* remove all movies that aren't in the new state */
   new = 1 << state;
   if (button->state >= 0) {
     old = 1 << button->state;
-    for (walk = button->button->records; walk; walk = walk->next) {
+    for (walk = but->records; walk; walk = walk->next) {
       swfdec_bits_init (&bits, walk->data);
       i = swfdec_bits_get_u8 (&bits);
       if ((i & old) && !(i & new)) {
@@ -149,7 +150,7 @@ swfdec_button_movie_set_state (SwfdecButtonMovie *button, SwfdecButtonState stat
   }
   button->state = state;
   /* add all movies that are in the new state */
-  for (walk = button->button->records; walk; walk = walk->next) {
+  for (walk = but->records; walk; walk = walk->next) {
     swfdec_bits_init (&bits, walk->data);
     i = swfdec_bits_peek_u8 (&bits);
     if ((i & old) || !(i & new))
@@ -167,7 +168,7 @@ swfdec_button_movie_mouse_events (SwfdecActor *actor)
 static void
 swfdec_button_movie_mouse_in (SwfdecActor *actor)
 {
-  if (swfdec_player_is_mouse_pressed (SWFDEC_PLAYER (SWFDEC_AS_OBJECT (actor)->context)))
+  if (swfdec_player_is_mouse_pressed (SWFDEC_PLAYER (swfdec_gc_object_get_context (actor))))
     swfdec_button_movie_set_state (SWFDEC_BUTTON_MOVIE (actor), SWFDEC_BUTTON_DOWN);
   else
     swfdec_button_movie_set_state (SWFDEC_BUTTON_MOVIE (actor), SWFDEC_BUTTON_OVER);
@@ -180,8 +181,8 @@ swfdec_button_movie_mouse_out (SwfdecActor *actor)
 {
   SwfdecButtonMovie *button = SWFDEC_BUTTON_MOVIE (actor);
 
-  if (swfdec_player_is_mouse_pressed (SWFDEC_PLAYER (SWFDEC_AS_OBJECT (button)->context))) {
-    if (button->button->menubutton) {
+  if (swfdec_player_is_mouse_pressed (SWFDEC_PLAYER (swfdec_gc_object_get_context (button)))) {
+    if (SWFDEC_BUTTON (SWFDEC_MOVIE (actor)->graphic)->menubutton) {
       swfdec_button_movie_set_state (SWFDEC_BUTTON_MOVIE (actor), SWFDEC_BUTTON_UP);
     } else {
       swfdec_button_movie_set_state (SWFDEC_BUTTON_MOVIE (actor), SWFDEC_BUTTON_OVER);
@@ -210,7 +211,7 @@ swfdec_button_movie_mouse_release (SwfdecActor *actor, guint button)
 
   if (button != 0)
     return;
-  player = SWFDEC_PLAYER (SWFDEC_AS_OBJECT (actor)->context);
+  player = SWFDEC_PLAYER (swfdec_gc_object_get_context (actor));
   if (player->priv->mouse_below == actor) {
     swfdec_button_movie_set_state (SWFDEC_BUTTON_MOVIE (actor), SWFDEC_BUTTON_OVER);
 
@@ -219,7 +220,7 @@ swfdec_button_movie_mouse_release (SwfdecActor *actor, guint button)
     swfdec_button_movie_set_state (SWFDEC_BUTTON_MOVIE (actor), SWFDEC_BUTTON_UP);
 
     /* NB: We don't chain to parent here for menubuttons*/
-    if (!SWFDEC_BUTTON_MOVIE (actor)->button->menubutton) {
+    if (!SWFDEC_BUTTON (SWFDEC_MOVIE (actor)->graphic)->menubutton) {
       SWFDEC_ACTOR_CLASS (swfdec_button_movie_parent_class)->mouse_release (actor, button);
     } else {
       SWFDEC_FIXME ("use mouse_below as recipient for mouse_release events?");
@@ -243,7 +244,7 @@ swfdec_button_movie_hit_test (SwfdecButtonMovie *button, double x, double y)
   double tmpx, tmpy;
 
   dec = SWFDEC_SWF_DECODER (SWFDEC_MOVIE (button)->resource->decoder);
-  for (walk = button->button->records; walk; walk = walk->next) {
+  for (walk = SWFDEC_BUTTON (SWFDEC_MOVIE (button)->graphic)->records; walk; walk = walk->next) {
     SwfdecGraphic *graphic;
     SwfdecBits bits;
     cairo_matrix_t matrix, inverse;
@@ -288,16 +289,24 @@ swfdec_button_movie_contains (SwfdecMovie *movie, double x, double y, gboolean e
   return swfdec_button_movie_hit_test (SWFDEC_BUTTON_MOVIE (movie), x, y) ? movie : NULL;
 }
 
-static void
-swfdec_button_movie_dispose (GObject *object)
+static GObject *
+swfdec_button_movie_constructor (GType type, guint n_construct_properties,
+    GObjectConstructParam *construct_properties)
 {
-  SwfdecButtonMovie *button = SWFDEC_BUTTON_MOVIE (object);
+  SwfdecMovie *movie;
+  GObject *object;
+
+  object = G_OBJECT_CLASS (swfdec_button_movie_parent_class)->constructor (type, 
+      n_construct_properties, construct_properties);
 
-  if (button->button) {
-    g_object_unref (button->button);
-    button->button = NULL;
+  movie = SWFDEC_MOVIE (object);
+  g_assert (movie->graphic);
+  if (SWFDEC_BUTTON (movie->graphic)->events) {
+    SWFDEC_ACTOR (movie)->events = swfdec_event_list_copy (
+	SWFDEC_BUTTON (movie->graphic)->events);
   }
-  G_OBJECT_CLASS (swfdec_button_movie_parent_class)->dispose (object);
+
+  return object;
 }
 
 static void
@@ -307,7 +316,8 @@ swfdec_button_movie_class_init (SwfdecButtonMovieClass * g_class)
   SwfdecMovieClass *movie_class = SWFDEC_MOVIE_CLASS (g_class);
   SwfdecActorClass *actor_class = SWFDEC_ACTOR_CLASS (g_class);
 
-  object_class->dispose = swfdec_button_movie_dispose;
+  object_class->constructor = swfdec_button_movie_constructor;
+
   movie_class->init_movie = swfdec_button_movie_init_movie;
   movie_class->update_extents = swfdec_button_movie_update_extents;
   movie_class->contains = swfdec_button_movie_contains;
diff --git a/swfdec/swfdec_button_movie.h b/swfdec/swfdec_button_movie.h
index 59a3db6..0857496 100644
--- a/swfdec/swfdec_button_movie.h
+++ b/swfdec/swfdec_button_movie.h
@@ -39,7 +39,6 @@ typedef struct _SwfdecButtonMovieClass SwfdecButtonMovieClass;
 struct _SwfdecButtonMovie {
   SwfdecActor		actor;
 
-  SwfdecButton *	button;		/* button we render */
   SwfdecButtonState	state;		/* current state we're in */
 };
 
diff --git a/swfdec/swfdec_color_as.c b/swfdec/swfdec_color_as.c
index 8155b1b..b76de66 100644
--- a/swfdec/swfdec_color_as.c
+++ b/swfdec/swfdec_color_as.c
@@ -140,7 +140,7 @@ parse_property (SwfdecAsObject *obj, const char *name, int *target, gboolean sca
 
   if (!swfdec_as_object_get_variable (obj, name, &val))
     return;
-  d = swfdec_as_value_to_number (obj->context, &val);
+  d = swfdec_as_value_to_number (swfdec_gc_object_get_context (obj), &val);
   if (scale) {
     *target = d * 256.0 / 100.0;
   } else {
diff --git a/swfdec/swfdec_color_transform_as.c b/swfdec/swfdec_color_transform_as.c
index 4c098df..ab6a7d2 100644
--- a/swfdec/swfdec_color_transform_as.c
+++ b/swfdec/swfdec_color_transform_as.c
@@ -365,15 +365,11 @@ swfdec_color_transform_as_new_from_transform (SwfdecAsContext *context,
 {
   SwfdecAsValue val;
   SwfdecColorTransformAs *transform_as;
-  guint size;
 
   g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context), NULL);
   g_return_val_if_fail (transform != NULL, NULL);
 
-  size = sizeof (SwfdecColorTransformAs);
-  swfdec_as_context_use_mem (context, size);
-  transform_as = g_object_new (SWFDEC_TYPE_COLOR_TRANSFORM_AS, NULL);
-  swfdec_as_object_add (SWFDEC_AS_OBJECT (transform_as), context, size);
+  transform_as = g_object_new (SWFDEC_TYPE_COLOR_TRANSFORM_AS, "context", context, NULL);
 
   swfdec_as_object_get_variable (context->global, SWFDEC_AS_STR_flash, &val);
   if (SWFDEC_AS_VALUE_IS_OBJECT (&val)) {
diff --git a/swfdec/swfdec_gc_object.c b/swfdec/swfdec_gc_object.c
new file mode 100644
index 0000000..82c0f11
--- /dev/null
+++ b/swfdec/swfdec_gc_object.c
@@ -0,0 +1,202 @@
+/* Swfdec
+ * Copyright (C) 2008 Benjamin Otte <otte at gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02110-1301  USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+
+#include "swfdec_gc_object.h"
+#include "swfdec_as_context.h"
+#include "swfdec_as_internal.h"
+
+/**
+ * SECTION:SwfdecGcObject
+ * @title: SwfdecGcObject
+ * @short_description: the base object type for garbage-collected objects
+ *
+ * This type is the basic garbage-collected object in Swfdec. It contains the
+ * simple facilities for required by the garbage collector. The initial 
+ * reference of this object will be owned by the context that created it and
+ * will be released automatically when no other object references it anymore
+ * in the garbage collection cycle.
+ *
+ * Note that you cannot know the lifetime of a #SwfdecGcObject, since scripts 
+ * may assign it as a variable to other objects. So you should not assume to 
+ * know when an object gets removed.
+ */
+
+/**
+ * SwfdecGcObject:
+ *
+ * If you want to add custom objects to the garbage collection lifecycle, you
+ * need to subclass this object as this object is abstract. 
+ */
+
+enum {
+  PROP_0,
+  PROP_CONTEXT
+};
+
+G_DEFINE_ABSTRACT_TYPE (SwfdecGcObject, swfdec_gc_object, G_TYPE_OBJECT)
+
+static gsize
+swfdec_gc_object_get_size (SwfdecGcObject *object)
+{
+  GTypeQuery query;
+
+  /* FIXME: This only uses the size of the public instance but doesn't include
+   * private members. http://bugzilla.gnome.org/show_bug.cgi?id=354457 blocks
+   * this. */
+  g_type_query (G_OBJECT_TYPE (object), &query);
+  return query.instance_size;
+}
+
+static void
+swfdec_gc_object_dispose (GObject *gobject)
+{
+  SwfdecGcObject *object = SWFDEC_GC_OBJECT (gobject);
+
+  swfdec_as_context_unuse_mem (object->context, swfdec_gc_object_get_size (object));
+  G_OBJECT_CLASS (swfdec_gc_object_parent_class)->dispose (gobject);
+}
+
+static void
+swfdec_gc_object_do_mark (SwfdecGcObject *object)
+{
+}
+
+static GObject *
+swfdec_gc_object_constructor (GType type, guint n_construct_properties,
+    GObjectConstructParam *construct_properties)
+{
+  GObject *gobject;
+  SwfdecGcObject *object;
+  SwfdecAsContext *context;
+
+  gobject = G_OBJECT_CLASS (swfdec_gc_object_parent_class)->constructor (type, 
+      n_construct_properties, construct_properties);
+  object = SWFDEC_GC_OBJECT (gobject);
+
+  context = object->context;
+  swfdec_as_context_use_mem (context, swfdec_gc_object_get_size (object));
+  g_hash_table_insert (context->objects, object, object);
+
+  return gobject;
+}
+
+static void
+swfdec_gc_object_get_property (GObject *object, guint param_id, GValue *value, 
+    GParamSpec * pspec)
+{
+  SwfdecGcObject *gc = SWFDEC_GC_OBJECT (object);
+
+  switch (param_id) {
+    case PROP_CONTEXT:
+      g_value_set_object (value, gc->context);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+      break;
+  }
+}
+
+static void
+swfdec_gc_object_set_property (GObject *object, guint param_id, const GValue *value, 
+    GParamSpec * pspec)
+{
+  SwfdecGcObject *gc = SWFDEC_GC_OBJECT (object);
+
+  switch (param_id) {
+    case PROP_CONTEXT:
+      gc->context = g_value_get_object (value);
+      g_assert (gc->context != NULL);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+      break;
+  }
+}
+
+static void
+swfdec_gc_object_class_init (SwfdecGcObjectClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->dispose = swfdec_gc_object_dispose;
+  object_class->set_property = swfdec_gc_object_set_property;
+  object_class->get_property = swfdec_gc_object_get_property;
+  object_class->constructor = swfdec_gc_object_constructor;
+
+  g_object_class_install_property (object_class, PROP_CONTEXT,
+      g_param_spec_object ("context", "context", "context managing this object",
+	  SWFDEC_TYPE_AS_CONTEXT, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+  klass->mark = swfdec_gc_object_do_mark;
+}
+
+static void
+swfdec_gc_object_init (SwfdecGcObject *object)
+{
+}
+
+/**
+ * swfdec_gc_object_get_context:
+ * @object: a #SwfdecGcObject. This function takes a gpointer argument only to
+ *          save you from having to cast it manually. For language bindings, 
+ *          please treat this argument as having the #SwfdecGcObject type.
+ *
+ * Gets the cotext that garbage-collects this object.
+ *
+ * Returns: the context this object belongs to
+ **/
+SwfdecAsContext *
+swfdec_gc_object_get_context (gpointer object)
+{
+  g_return_val_if_fail (SWFDEC_IS_GC_OBJECT (object), NULL);
+
+  return SWFDEC_GC_OBJECT (object)->context;
+}
+
+/**
+ * swfdec_gc_object_mark:
+ * @object: a #SwfdecGcObject. This function takes a gpointer argument only to
+ *          save you from having to cast it manually. For language bindings, 
+ *          please treat this argument as having the #SwfdecGcObject type.
+ *
+ * Mark @object as being in use. Calling this function is only valid during
+ * the marking phase of garbage collection.
+ **/
+void
+swfdec_gc_object_mark (gpointer object)
+{
+  SwfdecGcObject *gc = object;
+  SwfdecGcObjectClass *klass;
+
+  g_return_if_fail (SWFDEC_IS_GC_OBJECT (object));
+
+  if (gc->flags & SWFDEC_AS_GC_MARK)
+    return;
+  gc->flags |= SWFDEC_AS_GC_MARK;
+  klass = SWFDEC_GC_OBJECT_GET_CLASS (gc);
+  g_assert (klass->mark);
+  klass->mark (gc);
+}
+
diff --git a/swfdec/swfdec_gc_object.h b/swfdec/swfdec_gc_object.h
new file mode 100644
index 0000000..8bf0138
--- /dev/null
+++ b/swfdec/swfdec_gc_object.h
@@ -0,0 +1,60 @@
+/* Swfdec
+ * Copyright (C) 2008 Benjamin Otte <otte at gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02110-1301  USA
+ */
+
+#ifndef _SWFDEC_GC_OBJECT_H_
+#define _SWFDEC_GC_OBJECT_H_
+
+#include <glib-object.h>
+#include <swfdec/swfdec_as_types.h>
+
+G_BEGIN_DECLS
+
+typedef struct _SwfdecGcObjectClass SwfdecGcObjectClass;
+
+#define SWFDEC_TYPE_GC_OBJECT                    (swfdec_gc_object_get_type())
+#define SWFDEC_IS_GC_OBJECT(obj)                 (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SWFDEC_TYPE_GC_OBJECT))
+#define SWFDEC_IS_GC_OBJECT_CLASS(klass)         (G_TYPE_CHECK_CLASS_TYPE ((klass), SWFDEC_TYPE_GC_OBJECT))
+#define SWFDEC_GC_OBJECT(obj)                    (G_TYPE_CHECK_INSTANCE_CAST ((obj), SWFDEC_TYPE_GC_OBJECT, SwfdecGcObject))
+#define SWFDEC_GC_OBJECT_CLASS(klass)            (G_TYPE_CHECK_CLASS_CAST ((klass), SWFDEC_TYPE_GC_OBJECT, SwfdecGcObjectClass))
+#define SWFDEC_GC_OBJECT_GET_CLASS(obj)          (G_TYPE_INSTANCE_GET_CLASS ((obj), SWFDEC_TYPE_GC_OBJECT, SwfdecGcObjectClass))
+
+struct _SwfdecGcObject {
+  /*< protected >*/
+  GObject		object;
+  SwfdecAsContext *	context;	/* context the object belongs to - NB: object holds no reference */
+  /*< private >*/
+  guint8		flags;		/* GC flags */
+  gsize			size;		/* size reserved in GC */
+};
+
+struct _SwfdecGcObjectClass {
+  GObjectClass		object_class;
+
+  /* mark everything that should survive during GC */
+  void			(* mark)			(SwfdecGcObject *	object);
+};
+
+GType			swfdec_gc_object_get_type	(void);
+
+void			swfdec_gc_object_mark		(gpointer		object);
+SwfdecAsContext *	swfdec_gc_object_get_context	(gpointer		object);
+
+
+G_END_DECLS
+#endif
diff --git a/swfdec/swfdec_graphic.c b/swfdec/swfdec_graphic.c
index 0d3c260..bc40093 100644
--- a/swfdec/swfdec_graphic.c
+++ b/swfdec/swfdec_graphic.c
@@ -1,7 +1,7 @@
 /* Swfdec
  * Copyright (C) 2003-2006 David Schleef <ds at schleef.org>
  *		 2005-2006 Eric Anholt <eric at anholt.net>
- *		      2006 Benjamin Otte <otte at gnome.org>
+ *		 2006-2008 Benjamin Otte <otte at gnome.org>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -29,19 +29,10 @@
 
 G_DEFINE_ABSTRACT_TYPE (SwfdecGraphic, swfdec_graphic, SWFDEC_TYPE_CHARACTER)
 
-static SwfdecMovie *
-swfdec_graphic_create_movie (SwfdecGraphic *graphic, gsize *size)
-{
-  SwfdecGraphicMovie *movie = g_object_new (SWFDEC_TYPE_GRAPHIC_MOVIE, NULL);
-
-  *size = sizeof (SwfdecGraphicMovie);
-  return SWFDEC_MOVIE (movie);
-}
-
 static void
 swfdec_graphic_class_init (SwfdecGraphicClass *klass)
 {
-  klass->create_movie = swfdec_graphic_create_movie;
+  klass->movie_type = SWFDEC_TYPE_GRAPHIC_MOVIE;
 }
 
 static void
diff --git a/swfdec/swfdec_graphic.h b/swfdec/swfdec_graphic.h
index 3c96ba3..99d0892 100644
--- a/swfdec/swfdec_graphic.h
+++ b/swfdec/swfdec_graphic.h
@@ -1,7 +1,7 @@
 /* Swfdec
  * Copyright (C) 2003-2006 David Schleef <ds at schleef.org>
  *		 2005-2006 Eric Anholt <eric at anholt.net>
- *		 2006-2007 Benjamin Otte <otte at gnome.org>
+ *		 2006-2008 Benjamin Otte <otte at gnome.org>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -24,6 +24,7 @@
 
 #include <glib-object.h>
 #include <swfdec/swfdec_character.h>
+#include <swfdec/swfdec_player.h>
 #include <swfdec/swfdec_types.h>
 
 G_BEGIN_DECLS
@@ -49,9 +50,8 @@ struct _SwfdecGraphicClass
 {
   SwfdecCharacterClass	character_class;
 
-  /* when creating a movie for this graphic, calls this function */
-  SwfdecMovie *	      	(*create_movie)	(SwfdecGraphic *		graphic,
-					 gsize *      			size);
+  /* when creating a movie for this graphic, use this type. Must be a SWFDEC_TYPE_MOVIE */
+  GType			movie_type;
   /* optional vfuncs */
   void			(* render)	(SwfdecGraphic *	      	graphic, 
                                          cairo_t *			cr,
diff --git a/swfdec/swfdec_graphic_movie.c b/swfdec/swfdec_graphic_movie.c
index 55dfcdc..7fa7842 100644
--- a/swfdec/swfdec_graphic_movie.c
+++ b/swfdec/swfdec_graphic_movie.c
@@ -56,7 +56,7 @@ swfdec_graphic_movie_invalidate (SwfdecMovie *movie, const cairo_matrix_t *matri
   SwfdecRect rect;
 
   swfdec_rect_transform (&rect, &movie->graphic->extents, matrix);
-  swfdec_player_invalidate (SWFDEC_PLAYER (SWFDEC_AS_OBJECT (movie)->context), &rect);
+  swfdec_player_invalidate (SWFDEC_PLAYER (swfdec_gc_object_get_context (movie)), &rect);
 }
 
 static SwfdecMovie *
diff --git a/swfdec/swfdec_interval.c b/swfdec/swfdec_interval.c
index da80306..1dabd43 100644
--- a/swfdec/swfdec_interval.c
+++ b/swfdec/swfdec_interval.c
@@ -36,20 +36,20 @@
 G_DEFINE_TYPE (SwfdecInterval, swfdec_interval, SWFDEC_TYPE_AS_OBJECT)
 
 static void
-swfdec_interval_mark (SwfdecAsObject *object)
+swfdec_interval_mark (SwfdecGcObject *object)
 {
   guint i;
   SwfdecInterval *interval = SWFDEC_INTERVAL (object);
 
-  swfdec_as_object_mark (interval->object);
-  swfdec_as_object_mark (SWFDEC_AS_OBJECT (interval->sandbox));
+  swfdec_gc_object_mark (interval->object);
+  swfdec_gc_object_mark (interval->sandbox);
   if (interval->fun_name)
     swfdec_as_string_mark (interval->fun_name);
   for (i = 0; i < interval->n_args; i++) {
     swfdec_as_value_mark (&interval->args[i]);
   }
 
-  SWFDEC_AS_OBJECT_CLASS (swfdec_interval_parent_class)->mark (object);
+  SWFDEC_GC_OBJECT_CLASS (swfdec_interval_parent_class)->mark (object);
 }
 
 static void
@@ -57,11 +57,16 @@ swfdec_interval_dispose (GObject *object)
 {
   SwfdecInterval *interval = SWFDEC_INTERVAL (object);
 
-  g_free (interval->args);
-  interval->args = NULL;
+  if (interval->n_args) {
+    swfdec_as_context_unuse_mem (swfdec_gc_object_get_context (interval),
+	interval->n_args * sizeof (SwfdecAsValue));
+    g_free (interval->args);
+    interval->args = NULL;
+    interval->n_args = 0;
+  }
   /* needed here when GC'ed by closing the player */
   if (interval->timeout.callback != NULL) {
-    swfdec_player_remove_timeout (SWFDEC_PLAYER (SWFDEC_AS_OBJECT (object)->context), &interval->timeout);
+    swfdec_player_remove_timeout (SWFDEC_PLAYER (swfdec_gc_object_get_context (object)), &interval->timeout);
     interval->timeout.callback = NULL;
   }
 
@@ -72,11 +77,11 @@ static void
 swfdec_interval_class_init (SwfdecIntervalClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
-  SwfdecAsObjectClass *asobject_class = SWFDEC_AS_OBJECT_CLASS (klass);
+  SwfdecGcObjectClass *gc_class = SWFDEC_GC_OBJECT_CLASS (klass);
 
   object_class->dispose = swfdec_interval_dispose;
 
-  asobject_class->mark = swfdec_interval_mark;
+  gc_class->mark = swfdec_interval_mark;
 }
 
 static void
@@ -90,7 +95,7 @@ swfdec_interval_trigger (SwfdecTimeout *timeout)
   SwfdecAsValue ret;
   SwfdecInterval *interval = SWFDEC_INTERVAL ((void *) (((guchar *) timeout) 
       - G_STRUCT_OFFSET (SwfdecInterval, timeout)));
-  SwfdecAsContext *context = SWFDEC_AS_OBJECT (interval)->context;
+  SwfdecAsContext *context = swfdec_gc_object_get_context (interval);
   SwfdecPlayer *player = SWFDEC_PLAYER (context);
 
   if (interval->repeat) {
@@ -119,13 +124,14 @@ swfdec_interval_new (SwfdecPlayer *player, guint msecs, gboolean repeat,
 {
   SwfdecAsContext *context;
   SwfdecInterval *interval;
-  guint size;
 
   context = SWFDEC_AS_CONTEXT (player);
-  size = sizeof (SwfdecInterval) + n_args * sizeof (SwfdecAsValue);
-  swfdec_as_context_use_mem (context, size);
-  interval = g_object_new (SWFDEC_TYPE_INTERVAL, NULL);
-  swfdec_as_object_add (SWFDEC_AS_OBJECT (interval), context, size);
+  if (n_args && !swfdec_as_context_try_use_mem (context, n_args * sizeof (SwfdecAsValue))) {
+    swfdec_as_context_abort (context,
+	"Too many arguments passed to setInterval/setTimeout");
+    return 0;
+  }
+  interval = g_object_new (SWFDEC_TYPE_INTERVAL, "context", context, NULL);
 
   interval->id = ++player->priv->interval_id;
   interval->sandbox = SWFDEC_SANDBOX (context->global);
diff --git a/swfdec/swfdec_load_object.c b/swfdec/swfdec_load_object.c
index c9e0d3a..cc75a58 100644
--- a/swfdec/swfdec_load_object.c
+++ b/swfdec/swfdec_load_object.c
@@ -38,7 +38,7 @@
 static SwfdecPlayer *
 swfdec_load_object_stream_target_get_player (SwfdecStreamTarget *target)
 {
-  return SWFDEC_PLAYER (SWFDEC_LOAD_OBJECT (target)->target->context);
+  return SWFDEC_PLAYER (swfdec_gc_object_get_context (SWFDEC_LOAD_OBJECT (target)->target));
 }
 
 static gboolean
@@ -76,7 +76,7 @@ swfdec_load_object_stream_target_error (SwfdecStreamTarget *target,
 
   /* unroot */
   swfdec_player_unroot (SWFDEC_PLAYER (
-	SWFDEC_AS_OBJECT (load_object->sandbox)->context), load_object);
+	swfdec_gc_object_get_context (load_object->sandbox)), load_object);
 }
 
 static void
@@ -98,7 +98,7 @@ swfdec_load_object_stream_target_close (SwfdecStreamTarget *target,
   swfdec_sandbox_use (load_object->sandbox);
   if (text != NULL) {
     load_object->finish (load_object->target, 
-	swfdec_as_context_give_string (load_object->target->context, text));
+	swfdec_as_context_give_string (swfdec_gc_object_get_context (load_object->target), text));
   } else {
     load_object->finish (load_object->target, SWFDEC_AS_STR_EMPTY);
   }
@@ -106,7 +106,7 @@ swfdec_load_object_stream_target_close (SwfdecStreamTarget *target,
 
   /* unroot */
   swfdec_player_unroot (SWFDEC_PLAYER (
-	SWFDEC_AS_OBJECT (load_object->sandbox)->context), load_object);
+	swfdec_gc_object_get_context (load_object->sandbox)), load_object);
 }
 
 static void
@@ -206,10 +206,10 @@ swfdec_load_object_mark (gpointer object, gpointer player)
 {
   SwfdecLoadObject *load = object;
 
-  swfdec_as_object_mark (SWFDEC_AS_OBJECT (load->sandbox));
+  swfdec_gc_object_mark (load->sandbox);
   if (load->url)
     swfdec_as_string_mark (load->url);
-  swfdec_as_object_mark (load->target);
+  swfdec_gc_object_mark (load->target);
 }
 
 void
@@ -227,7 +227,7 @@ swfdec_load_object_create (SwfdecAsObject *target, const char *url,
   g_return_if_fail (header_count == 0 || header_values != NULL);
   g_return_if_fail (finish != NULL);
 
-  player = SWFDEC_PLAYER (target->context);
+  player = SWFDEC_PLAYER (swfdec_gc_object_get_context (target));
   load = g_object_new (SWFDEC_TYPE_LOAD_OBJECT, NULL);
   swfdec_player_root_full (player, load, swfdec_load_object_mark, g_object_unref);
 
diff --git a/swfdec/swfdec_load_object_as.c b/swfdec/swfdec_load_object_as.c
index 68dd657..e642093 100644
--- a/swfdec/swfdec_load_object_as.c
+++ b/swfdec/swfdec_load_object_as.c
@@ -112,7 +112,7 @@ swfdec_load_object_as_get_headers (SwfdecAsObject *object, guint *header_count,
   const char *name;
   SwfdecAsContext *cx;
 
-  cx = object->context;
+  cx = swfdec_gc_object_get_context (object);
 
   array_names = g_ptr_array_new ();
   array_values = g_ptr_array_new ();
diff --git a/swfdec/swfdec_load_sound.c b/swfdec/swfdec_load_sound.c
index 702d94f..eec790f 100644
--- a/swfdec/swfdec_load_sound.c
+++ b/swfdec/swfdec_load_sound.c
@@ -52,7 +52,7 @@ swfdec_load_sound_sound_provider_start (SwfdecSoundProvider *provider,
     SWFDEC_FIXME ("implement starting at offset %"G_GSIZE_FORMAT" with %u loops",
 	samples_offset, loops);
   }
-  sound->audio = swfdec_audio_load_new (SWFDEC_PLAYER (SWFDEC_AS_OBJECT (actor)->context), sound);
+  sound->audio = swfdec_audio_load_new (SWFDEC_PLAYER (swfdec_gc_object_get_context (actor)), sound);
   swfdec_audio_set_matrix (sound->audio, &sound->sound_matrix);
 }
 
@@ -91,7 +91,7 @@ swfdec_load_sound_sound_provider_init (SwfdecSoundProviderInterface *iface)
 static SwfdecPlayer *
 swfdec_load_sound_stream_target_get_player (SwfdecStreamTarget *target)
 {
-  return SWFDEC_PLAYER (SWFDEC_LOAD_SOUND (target)->target->context);
+  return SWFDEC_PLAYER (swfdec_gc_object_get_context (SWFDEC_LOAD_SOUND (target)->target));
 }
 
 static gboolean
@@ -401,24 +401,26 @@ SwfdecLoadSound *
 swfdec_load_sound_new (SwfdecAsObject *target, const char *url)
 {
   SwfdecLoadSound *sound;
+  SwfdecAsContext *context;
   char *missing;
 
   g_return_val_if_fail (SWFDEC_IS_AS_OBJECT (target), NULL);
   g_return_val_if_fail (url != NULL, NULL);
 
+  context = swfdec_gc_object_get_context (target);
   sound = g_object_new (SWFDEC_TYPE_LOAD_SOUND, NULL);
   sound->target = target;
-  sound->sandbox = SWFDEC_SANDBOX (target->context->global);
+  sound->sandbox = SWFDEC_SANDBOX (context->global);
   sound->url = g_strdup (url);
   g_assert (sound->sandbox);
-  swfdec_player_allow_by_matrix (SWFDEC_PLAYER (target->context), sound->sandbox,
+  swfdec_player_allow_by_matrix (SWFDEC_PLAYER (context), sound->sandbox,
       url, swfdec_load_sound_matrix, swfdec_load_sound_load, sound);
   /* tell missing plugins stuff we want MP3 */
   missing = NULL;
   swfdec_audio_decoder_prepare (SWFDEC_AUDIO_CODEC_MP3, 
       swfdec_audio_format_new (44100, 2, TRUE), &missing);
   if (missing) {
-    swfdec_player_add_missing_plugin (SWFDEC_PLAYER (target->context),
+    swfdec_player_add_missing_plugin (SWFDEC_PLAYER (context),
 	missing);
     g_free (missing);
   }
diff --git a/swfdec/swfdec_morph_movie.c b/swfdec/swfdec_morph_movie.c
index b060eb0..c057c54 100644
--- a/swfdec/swfdec_morph_movie.c
+++ b/swfdec/swfdec_morph_movie.c
@@ -34,8 +34,7 @@ swfdec_morph_movie_update_extents (SwfdecMovie *movie,
     SwfdecRect *extents)
 {
   guint ratio = movie->original_ratio;
-  SwfdecMorphMovie *mmovie = SWFDEC_MORPH_MOVIE (movie);
-  SwfdecMorphShape *morph = mmovie->morph;
+  SwfdecMorphShape *morph = SWFDEC_MORPH_SHAPE (movie->graphic);
   SwfdecGraphic *graphic = SWFDEC_GRAPHIC (morph);
   extents->x0 = ((65535 - ratio) * graphic->extents.x0 + ratio * morph->end_extents.x0) / 65535;
   extents->x1 = ((65535 - ratio) * graphic->extents.x1 + ratio * morph->end_extents.x1) / 65535;
@@ -58,7 +57,7 @@ swfdec_morph_movie_set_ratio (SwfdecMovie *movie)
 static void
 swfdec_morph_movie_create_morphs (SwfdecMorphMovie *mmovie)
 {
-  SwfdecShape *shape = SWFDEC_SHAPE (mmovie->morph);
+  SwfdecShape *shape = SWFDEC_SHAPE (SWFDEC_MOVIE (mmovie)->graphic);
   guint ratio = SWFDEC_MOVIE (mmovie)->original_ratio;
   GSList *walk;
 
@@ -97,7 +96,7 @@ swfdec_morph_movie_invalidate (SwfdecMovie *movie, const cairo_matrix_t *matrix,
   SwfdecRect rect;
   
   swfdec_rect_transform (&rect, &movie->original_extents, matrix);
-  swfdec_player_invalidate (SWFDEC_PLAYER (SWFDEC_AS_OBJECT (movie)->context), &rect);
+  swfdec_player_invalidate (SWFDEC_PLAYER (swfdec_gc_object_get_context (movie)), &rect);
 }
 
 static void
@@ -108,7 +107,6 @@ swfdec_morph_movie_dispose (GObject *object)
   g_slist_foreach (morph->draws, (GFunc) g_object_unref, NULL);
   g_slist_free (morph->draws);
   morph->draws = NULL;
-  g_object_unref (morph->morph);
 
   G_OBJECT_CLASS (swfdec_morph_movie_parent_class)->dispose (object);
 }
diff --git a/swfdec/swfdec_morph_movie.h b/swfdec/swfdec_morph_movie.h
index db19692..b3446ae 100644
--- a/swfdec/swfdec_morph_movie.h
+++ b/swfdec/swfdec_morph_movie.h
@@ -39,7 +39,6 @@ typedef struct _SwfdecMorphMovieClass SwfdecMorphMovieClass;
 struct _SwfdecMorphMovie {
   SwfdecMovie		movie;
 
-  SwfdecMorphShape *	morph;
   GSList *		draws;		/* drawing operations to use or NULL if not yet created */
 };
 
diff --git a/swfdec/swfdec_morphshape.c b/swfdec/swfdec_morphshape.c
index 5252804..65f0fcf 100644
--- a/swfdec/swfdec_morphshape.c
+++ b/swfdec/swfdec_morphshape.c
@@ -31,26 +31,12 @@
 
 G_DEFINE_TYPE (SwfdecMorphShape, swfdec_morph_shape, SWFDEC_TYPE_SHAPE)
 
-static SwfdecMovie *
-swfdec_graphic_create_movie (SwfdecGraphic *graphic, gsize *size)
-{
-  SwfdecMorphShape *morph = SWFDEC_MORPH_SHAPE (graphic);
-  SwfdecMorphMovie *movie = g_object_new (SWFDEC_TYPE_MORPH_MOVIE, NULL);
-
-  movie->morph = morph;
-  g_object_ref (morph);
-
-  *size = sizeof (SwfdecMorphMovie);
-
-  return SWFDEC_MOVIE (movie);
-}
-
 static void
 swfdec_morph_shape_class_init (SwfdecMorphShapeClass * g_class)
 {
   SwfdecGraphicClass *graphic_class = SWFDEC_GRAPHIC_CLASS (g_class);
   
-  graphic_class->create_movie = swfdec_graphic_create_movie;
+  graphic_class->movie_type = SWFDEC_TYPE_MORPH_MOVIE;
 }
 
 static void
diff --git a/swfdec/swfdec_movie.c b/swfdec/swfdec_movie.c
index 8a252e7..7de4119 100644
--- a/swfdec/swfdec_movie.c
+++ b/swfdec/swfdec_movie.c
@@ -52,7 +52,11 @@
 
 enum {
   PROP_0,
-  PROP_DEPTH
+  PROP_DEPTH,
+  PROP_GRAPHIC,
+  PROP_NAME,
+  PROP_PARENT,
+  PROP_RESOURCE
 };
 
 enum {
@@ -111,7 +115,7 @@ swfdec_movie_invalidate (SwfdecMovie *movie, const cairo_matrix_t *parent_to_glo
     if (movie->invalidate_last)
       return;
     movie->invalidate_last = TRUE;
-    player = SWFDEC_PLAYER (SWFDEC_AS_OBJECT (movie)->context);
+    player = SWFDEC_PLAYER (swfdec_gc_object_get_context (movie));
     player->priv->invalid_pending = g_slist_prepend (player->priv->invalid_pending, movie);
   }
   g_assert (movie->cache_state <= SWFDEC_MOVIE_INVALID_CHILDREN);
@@ -164,7 +168,7 @@ swfdec_movie_invalidate_next (SwfdecMovie *movie)
 
   swfdec_movie_invalidate_last (movie);
   movie->invalidate_next = TRUE;
-  player = SWFDEC_PLAYER (SWFDEC_AS_OBJECT (movie)->context);
+  player = SWFDEC_PLAYER (swfdec_gc_object_get_context (movie));
   if (movie == SWFDEC_MOVIE (player->priv->focus))
     swfdec_player_invalidate_focusrect (player);
 }
@@ -349,7 +353,7 @@ swfdec_movie_do_remove (SwfdecMovie *movie, gboolean destroy)
 
   SWFDEC_LOG ("removing %s %s", G_OBJECT_TYPE_NAME (movie), movie->name);
 
-  player = SWFDEC_PLAYER (SWFDEC_AS_OBJECT (movie)->context);
+  player = SWFDEC_PLAYER (swfdec_gc_object_get_context (movie));
   while (movie->list) {
     GList *walk = movie->list;
     while (walk && SWFDEC_MOVIE (walk->data)->state >= SWFDEC_MOVIE_STATE_REMOVED)
@@ -410,7 +414,7 @@ void
 swfdec_movie_destroy (SwfdecMovie *movie)
 {
   SwfdecMovieClass *klass = SWFDEC_MOVIE_GET_CLASS (movie);
-  SwfdecPlayer *player = SWFDEC_PLAYER (SWFDEC_AS_OBJECT (movie)->context);
+  SwfdecPlayer *player = SWFDEC_PLAYER (swfdec_gc_object_get_context (movie));
 
   g_assert (movie->state < SWFDEC_MOVIE_STATE_DESTROYED);
   SWFDEC_LOG ("destroying movie %s", movie->name);
@@ -590,7 +594,7 @@ swfdec_movie_get_mouse (SwfdecMovie *movie, double *x, double *y)
   g_return_if_fail (x != NULL);
   g_return_if_fail (y != NULL);
 
-  player = SWFDEC_PLAYER (SWFDEC_AS_OBJECT (movie)->context);
+  player = SWFDEC_PLAYER (swfdec_gc_object_get_context (movie));
   *x = player->priv->mouse_x;
   *y = player->priv->mouse_y;
   swfdec_player_stage_to_global (player, x, y);
@@ -861,6 +865,12 @@ swfdec_movie_get_property (GObject *object, guint param_id, GValue *value,
     case PROP_DEPTH:
       g_value_set_int (value, movie->depth);
       break;
+    case PROP_PARENT:
+      g_value_set_object (value, movie->parent);
+      break;
+    case PROP_RESOURCE:
+      g_value_set_object (value, movie->resource);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
       break;
@@ -872,11 +882,60 @@ swfdec_movie_set_property (GObject *object, guint param_id, const GValue *value,
     GParamSpec * pspec)
 {
   SwfdecMovie *movie = SWFDEC_MOVIE (object);
+  SwfdecAsContext *cx = swfdec_gc_object_get_context (movie);
+
+  /* The context must be set before all movie-related properties */
+  g_assert (cx);
 
   switch (param_id) {
     case PROP_DEPTH:
+      /* parent must be set after depth */
+      g_assert (movie->parent == NULL);
       movie->depth = g_value_get_int (value);
       break;
+    case PROP_GRAPHIC:
+      movie->graphic = g_value_get_object (value);
+      if (movie->graphic)
+	g_object_ref (movie->graphic);
+      break;
+    case PROP_NAME:
+      movie->name = g_value_get_string (value);
+      if (movie->name) {
+	movie->name = swfdec_as_context_get_string (cx, movie->name);
+	movie->original_name = movie->name;
+      } else {
+	movie->original_name = SWFDEC_AS_STR_EMPTY;
+	if (SWFDEC_IS_SPRITE_MOVIE (movie) || SWFDEC_IS_BUTTON_MOVIE (movie)) {
+	  movie->name = swfdec_as_context_give_string (cx,
+	      g_strdup_printf ("instance%u", ++SWFDEC_PLAYER (cx)->priv->unnamed_count));
+	} else {
+	  movie->name = SWFDEC_AS_STR_EMPTY;
+	}
+      }
+      break;
+    case PROP_PARENT:
+      movie->parent = g_value_get_object (value);
+      /* parent holds a reference */
+      g_object_ref (movie);
+      if (movie->parent) {
+	movie->parent->list = g_list_insert_sorted (movie->parent->list, movie, swfdec_movie_compare_depths);
+	SWFDEC_DEBUG ("inserting %s %p into %s %p", G_OBJECT_TYPE_NAME (movie), movie,
+	    G_OBJECT_TYPE_NAME (movie->parent), movie->parent);
+	/* invalidate the parent, so it gets visible */
+	swfdec_movie_queue_update (movie->parent, SWFDEC_MOVIE_INVALID_CHILDREN);
+      } else {
+	SwfdecPlayerPrivate *priv = SWFDEC_PLAYER (cx)->priv;
+	priv->roots = g_list_insert_sorted (priv->roots, movie, swfdec_movie_compare_depths);
+      }
+      break;
+    case PROP_RESOURCE:
+      movie->resource = g_value_get_object (value);
+      /* NB: the resource assumes it can access the player via the movie */
+      if (movie->resource->movie == NULL) {
+	g_assert (SWFDEC_IS_SPRITE_MOVIE (movie));
+	movie->resource->movie = SWFDEC_SPRITE_MOVIE (movie);
+      }
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
       break;
@@ -914,27 +973,27 @@ swfdec_movie_dispose (GObject *object)
 }
 
 static void
-swfdec_movie_mark (SwfdecAsObject *object)
+swfdec_movie_mark (SwfdecGcObject *object)
 {
   SwfdecMovie *movie = SWFDEC_MOVIE (object);
   GList *walk;
   GSList *iter;
 
   if (movie->parent)
-    swfdec_as_object_mark (SWFDEC_AS_OBJECT (movie->parent));
+    swfdec_gc_object_mark (movie->parent);
   swfdec_as_string_mark (movie->original_name);
   swfdec_as_string_mark (movie->name);
   for (walk = movie->list; walk; walk = walk->next) {
-    swfdec_as_object_mark (walk->data);
+    swfdec_gc_object_mark (walk->data);
   }
   for (iter = movie->variable_listeners; iter != NULL; iter = iter->next) {
     SwfdecMovieVariableListener *listener = iter->data;
-    swfdec_as_object_mark (listener->object);
+    swfdec_gc_object_mark (listener->object);
     swfdec_as_string_mark (listener->name);
   }
-  swfdec_as_object_mark (SWFDEC_AS_OBJECT (movie->resource));
+  swfdec_gc_object_mark (movie->resource);
 
-  SWFDEC_AS_OBJECT_CLASS (swfdec_movie_parent_class)->mark (object);
+  SWFDEC_GC_OBJECT_CLASS (swfdec_movie_parent_class)->mark (object);
 }
 
 #define swfdec_movie_is_scriptable(mov) \
@@ -947,8 +1006,8 @@ swfdec_movie_get_by_name (SwfdecMovie *movie, const char *name, gboolean unnamed
 {
   GList *walk;
   int i;
-  guint version = SWFDEC_AS_OBJECT (movie)->context->version;
-  SwfdecPlayer *player = SWFDEC_PLAYER (SWFDEC_AS_OBJECT (movie)->context);
+  guint version = swfdec_gc_object_get_context (movie)->version;
+  SwfdecPlayer *player = SWFDEC_PLAYER (swfdec_gc_object_get_context (movie));
 
   i = swfdec_player_get_level (player, name, version);
   if (i >= 0)
@@ -1005,7 +1064,7 @@ swfdec_movie_get_variable (SwfdecAsObject *object, SwfdecAsObject *orig,
     return TRUE;
 
   /* FIXME: check that this is correct */
-  if (object->context->version > 5 && variable == SWFDEC_AS_STR__global) {
+  if (swfdec_gc_object_get_context (object)->version > 5 && variable == SWFDEC_AS_STR__global) {
     SWFDEC_AS_VALUE_SET_OBJECT (val, SWFDEC_AS_OBJECT (movie->resource->sandbox));
     *flags = 0;
     return TRUE;
@@ -1086,7 +1145,7 @@ swfdec_movie_call_variable_listeners (SwfdecMovie *movie, const char *name,
     SwfdecMovieVariableListener *listener = iter->data;
 
     if (listener->name != name &&
-	(SWFDEC_AS_OBJECT (movie)->context->version >= 7 ||
+	(swfdec_gc_object_get_context (movie)->version >= 7 ||
 	 !swfdec_str_case_equal (listener->name, name)))
       continue;
 
@@ -1269,7 +1328,7 @@ swfdec_movie_do_invalidate (SwfdecMovie *movie, const cairo_matrix_t *matrix, gb
   }
   swfdec_rect_union (&rect, &rect, &movie->draw_extents);
   swfdec_rect_transform (&rect, &rect, matrix);
-  swfdec_player_invalidate (SWFDEC_PLAYER (SWFDEC_AS_OBJECT (movie)->context), &rect);
+  swfdec_player_invalidate (SWFDEC_PLAYER (swfdec_gc_object_get_context (movie)), &rect);
 
   for (walk = movie->list; walk; walk = walk->next) {
     swfdec_movie_invalidate (walk->data, matrix, last);
@@ -1280,13 +1339,15 @@ static void
 swfdec_movie_class_init (SwfdecMovieClass * movie_class)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (movie_class);
+  SwfdecGcObjectClass *gc_class = SWFDEC_GC_OBJECT_CLASS (movie_class);
   SwfdecAsObjectClass *asobject_class = SWFDEC_AS_OBJECT_CLASS (movie_class);
 
   object_class->dispose = swfdec_movie_dispose;
   object_class->get_property = swfdec_movie_get_property;
   object_class->set_property = swfdec_movie_set_property;
 
-  asobject_class->mark = swfdec_movie_mark;
+  gc_class->mark = swfdec_movie_mark;
+
   asobject_class->get = swfdec_movie_get_variable;
   asobject_class->set = swfdec_movie_set_variable;
   asobject_class->foreach = swfdec_movie_foreach_variable;
@@ -1299,6 +1360,18 @@ swfdec_movie_class_init (SwfdecMovieClass * movie_class)
   g_object_class_install_property (object_class, PROP_DEPTH,
       g_param_spec_int ("depth", "depth", "z order inside the parent",
 	  G_MININT, G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+  g_object_class_install_property (object_class, PROP_GRAPHIC,
+      g_param_spec_object ("graphic", "graphic", "graphic represented by this movie",
+	  SWFDEC_TYPE_GRAPHIC, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+  g_object_class_install_property (object_class, PROP_NAME,
+      g_param_spec_string ("name", "name", "the name given to this movie (can be empty)",
+	  NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+  g_object_class_install_property (object_class, PROP_PARENT,
+      g_param_spec_object ("parent", "parent", "parent movie containing this movie",
+	  SWFDEC_TYPE_MOVIE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+  g_object_class_install_property (object_class, PROP_RESOURCE,
+      g_param_spec_object ("resource", "resource", "the resource that spawned this movie",
+	  SWFDEC_TYPE_RESOURCE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
 
   movie_class->render = swfdec_movie_do_render;
   movie_class->invalidate = swfdec_movie_do_invalidate;
@@ -1332,7 +1405,7 @@ swfdec_movie_set_depth (SwfdecMovie *movie, int depth)
   if (movie->parent) {
     movie->parent->list = g_list_sort (movie->parent->list, swfdec_movie_compare_depths);
   } else {
-    SwfdecPlayerPrivate *player = SWFDEC_PLAYER (SWFDEC_AS_OBJECT (movie)->context)->priv;
+    SwfdecPlayerPrivate *player = SWFDEC_PLAYER (swfdec_gc_object_get_context (movie))->priv;
     player->roots = g_list_sort (player->roots, swfdec_movie_compare_depths);
   }
   g_object_notify (G_OBJECT (movie), "depth");
@@ -1341,17 +1414,15 @@ swfdec_movie_set_depth (SwfdecMovie *movie, int depth)
 static void
 swfdec_movie_set_version (SwfdecMovie *movie)
 {
-  SwfdecAsObject *o;
   SwfdecAsContext *cx;
   SwfdecAsValue val;
 
   if (movie->parent != NULL)
     return;
 
-  o = SWFDEC_AS_OBJECT (movie);
-  cx = o->context;
+  cx = swfdec_gc_object_get_context (movie);
   SWFDEC_AS_VALUE_SET_STRING (&val, swfdec_as_context_get_string (cx, SWFDEC_PLAYER (cx)->priv->system->version));
-  swfdec_as_object_set_variable (o, SWFDEC_AS_STR__version, &val);
+  swfdec_as_object_set_variable (SWFDEC_AS_OBJECT (movie), SWFDEC_AS_STR__version, &val);
 }
 
 /**
@@ -1379,7 +1450,7 @@ swfdec_movie_new (SwfdecPlayer *player, int depth, SwfdecMovie *parent, SwfdecRe
     SwfdecGraphic *graphic, const char *name)
 {
   SwfdecMovie *movie;
-  gsize size;
+  GType type;
 
   g_return_val_if_fail (SWFDEC_IS_PLAYER (player), NULL);
   g_return_val_if_fail (parent == NULL || SWFDEC_IS_MOVIE (parent), NULL);
@@ -1388,58 +1459,24 @@ swfdec_movie_new (SwfdecPlayer *player, int depth, SwfdecMovie *parent, SwfdecRe
 
   /* create the right movie */
   if (graphic == NULL) {
-    movie = g_object_new (SWFDEC_TYPE_SPRITE_MOVIE, "depth", depth, NULL);
-    size = sizeof (SwfdecSpriteMovie);
+    type = SWFDEC_TYPE_SPRITE_MOVIE;
   } else {
     SwfdecGraphicClass *klass = SWFDEC_GRAPHIC_GET_CLASS (graphic);
-    g_return_val_if_fail (klass->create_movie != NULL, NULL);
-    movie = klass->create_movie (graphic, &size);
-    movie->graphic = g_object_ref (graphic);
-    movie->depth = depth;
-  }
-  /* register it to the VM */
-  swfdec_as_context_use_mem (SWFDEC_AS_CONTEXT (player), size);
-  g_object_ref (movie);
-  /* set essential properties */
-  movie->parent = parent;
-  movie->resource = resource;
-  if (parent) {
-    parent->list = g_list_insert_sorted (parent->list, movie, swfdec_movie_compare_depths);
-    SWFDEC_DEBUG ("inserting %s %s (depth %d) into %s %p", G_OBJECT_TYPE_NAME (movie), movie->name,
-	movie->depth,  G_OBJECT_TYPE_NAME (parent), parent);
-    /* invalidate the parent, so it gets visible */
-    swfdec_movie_queue_update (parent, SWFDEC_MOVIE_INVALID_CHILDREN);
-  } else {
-    player->priv->roots = g_list_insert_sorted (player->priv->roots, movie, swfdec_movie_compare_depths);
-  }
-  /* set its name */
-  if (name) {
-    movie->original_name = name;
-    movie->name = name;
-  } else {
-    movie->original_name = SWFDEC_AS_STR_EMPTY;
-    if (SWFDEC_IS_SPRITE_MOVIE (movie) || SWFDEC_IS_BUTTON_MOVIE (movie)) {
-      movie->name = swfdec_as_context_give_string (SWFDEC_AS_CONTEXT (player), 
-	  g_strdup_printf ("instance%u", ++player->priv->unnamed_count));
-    } else {
-      movie->name = SWFDEC_AS_STR_EMPTY;
-    }
+    g_return_val_if_fail (g_type_is_a (klass->movie_type, SWFDEC_TYPE_MOVIE), NULL);
+    type = klass->movie_type;
   }
+  movie = g_object_new (type, "context", player, "depth", depth, 
+      "parent", parent, "name", name, "resource", resource,
+      "graphic", graphic, NULL);
   /* add the movie to the global movies list */
-  /* NB: adding to the movies list happens before setting the parent.
-   * Setting the parent does a gotoAndPlay(0) for Sprites which can cause
-   * new movies to be created (and added to this list)
+  /* NB: adding to the movies list happens before swfdec_movie_initialize().
+   * swfdec_movie_initialize() does a gotoAndPlay(0) for Sprites which can
+   * cause new movies to be created (and added to this list).
    */
   if (SWFDEC_IS_ACTOR (movie))
     player->priv->actors = g_list_prepend (player->priv->actors, movie);
   /* only add the movie here, because it needs to be setup for the debugger */
-  swfdec_as_object_add (SWFDEC_AS_OBJECT (movie), SWFDEC_AS_CONTEXT (player), size);
   swfdec_movie_set_version (movie);
-  /* only setup here, the resource assumes it can access the player via the movie */
-  if (resource->movie == NULL) {
-    g_assert (SWFDEC_IS_SPRITE_MOVIE (movie));
-    resource->movie = SWFDEC_SPRITE_MOVIE (movie);
-  }
   /* the movie is invalid already */
   player->priv->invalid_pending = g_slist_prepend (player->priv->invalid_pending, movie);
 
@@ -1537,14 +1574,14 @@ swfdec_movie_duplicate (SwfdecMovie *movie, const char *name, int depth)
     SWFDEC_LOG ("depth %d already occupied while duplicating, removing old movie", depth);
     swfdec_movie_remove (copy);
   }
-  copy = swfdec_movie_new (SWFDEC_PLAYER (SWFDEC_AS_OBJECT (movie)->context), depth, 
+  copy = swfdec_movie_new (SWFDEC_PLAYER (swfdec_gc_object_get_context (movie)), depth, 
       parent, movie->resource, movie->graphic, name);
   if (copy == NULL)
     return NULL;
   swfdec_movie_set_static_properties (copy, &movie->original_transform,
       &movie->color_transform, movie->original_ratio, movie->clip_depth, 
       movie->blend_mode, SWFDEC_IS_ACTOR (movie) ? SWFDEC_ACTOR (movie)->events : NULL);
-  sandbox = SWFDEC_SANDBOX (SWFDEC_AS_OBJECT (movie)->context->global);
+  sandbox = SWFDEC_SANDBOX (swfdec_gc_object_get_context (movie)->global);
   swfdec_sandbox_unuse (sandbox);
   if (SWFDEC_IS_SPRITE_MOVIE (copy)) {
     SwfdecActor *actor = SWFDEC_ACTOR (copy);
diff --git a/swfdec/swfdec_movie_as_drawing.c b/swfdec/swfdec_movie_as_drawing.c
index 24d0953..c42ad88 100644
--- a/swfdec/swfdec_movie_as_drawing.c
+++ b/swfdec/swfdec_movie_as_drawing.c
@@ -107,7 +107,7 @@ swfdec_sprite_movie_gradient_fill_get_length (SwfdecAsObject *o)
   SwfdecAsValue val;
 
   swfdec_as_object_get_variable (o, SWFDEC_AS_STR_length, &val);
-  length = swfdec_as_value_to_integer (o->context, &val);
+  length = swfdec_as_value_to_integer (swfdec_gc_object_get_context (o), &val);
   return MAX (length, 0);
 }
 
@@ -127,7 +127,7 @@ swfdec_sprite_movie_gradient_fill_check_length (SwfdecAsObject *colors, SwfdecAs
 static void
 swfdec_sprite_movie_extract_matrix (SwfdecAsObject *o, cairo_matrix_t *mat)
 {
-  SwfdecAsContext *cx = o->context;
+  SwfdecAsContext *cx = swfdec_gc_object_get_context (o);
   SwfdecAsValue val;
 
   /* FIXME: This function does not call valueOf in the right order */
diff --git a/swfdec/swfdec_movie_asprops.c b/swfdec/swfdec_movie_asprops.c
index 1786236..2a885a4 100644
--- a/swfdec/swfdec_movie_asprops.c
+++ b/swfdec/swfdec_movie_asprops.c
@@ -51,7 +51,7 @@ mc_x_set (SwfdecMovie *movie, const SwfdecAsValue *val)
 {
   SwfdecTwips x;
 
-  if (!swfdec_as_value_to_twips (SWFDEC_AS_OBJECT (movie)->context, val, FALSE, &x))
+  if (!swfdec_as_value_to_twips (swfdec_gc_object_get_context (movie), val, FALSE, &x))
     return;
   movie->modified = TRUE;
   if (x != movie->matrix.x0) {
@@ -76,7 +76,7 @@ mc_y_set (SwfdecMovie *movie, const SwfdecAsValue *val)
 {
   SwfdecTwips y;
 
-  if (!swfdec_as_value_to_twips (SWFDEC_AS_OBJECT (movie)->context, val, FALSE, &y))
+  if (!swfdec_as_value_to_twips (swfdec_gc_object_get_context (movie), val, FALSE, &y))
     return;
   movie->modified = TRUE;
   if (y != movie->matrix.y0) {
@@ -97,7 +97,7 @@ mc_xscale_set (SwfdecMovie *movie, const SwfdecAsValue *val)
 {
   double d;
 
-  d = swfdec_as_value_to_number (SWFDEC_AS_OBJECT (movie)->context, val);
+  d = swfdec_as_value_to_number (swfdec_gc_object_get_context (movie), val);
   if (!isfinite (d)) {
     SWFDEC_WARNING ("trying to set xscale to a non-finite value, ignoring");
     return;
@@ -121,7 +121,7 @@ mc_yscale_set (SwfdecMovie *movie, const SwfdecAsValue *val)
 {
   double d;
 
-  d = swfdec_as_value_to_number (SWFDEC_AS_OBJECT (movie)->context, val);
+  d = swfdec_as_value_to_number (swfdec_gc_object_get_context (movie), val);
   if (!isfinite (d)) {
     SWFDEC_WARNING ("trying to set yscale to a non-finite value, ignoring");
     return;
@@ -143,7 +143,7 @@ mc_name_get (SwfdecMovie *movie, SwfdecAsValue *rval)
 static void
 mc_name_set (SwfdecMovie *movie, const SwfdecAsValue *val)
 {
-  movie->name = swfdec_as_value_to_string (SWFDEC_AS_OBJECT (movie)->context, val);
+  movie->name = swfdec_as_value_to_string (swfdec_gc_object_get_context (movie), val);
 }
 
 static void
@@ -159,7 +159,7 @@ mc_alpha_set (SwfdecMovie *movie, const SwfdecAsValue *val)
   double d;
   int alpha;
 
-  d = swfdec_as_value_to_number (SWFDEC_AS_OBJECT (movie)->context, val);
+  d = swfdec_as_value_to_number (swfdec_gc_object_get_context (movie), val);
   if (!isfinite (d)) {
     SWFDEC_WARNING ("trying to set alpha to a non-finite value, ignoring");
     return;
@@ -182,7 +182,7 @@ mc_visible_set (SwfdecMovie *movie, const SwfdecAsValue *val)
 {
   gboolean b;
 
-  b = swfdec_as_value_to_boolean (SWFDEC_AS_OBJECT (movie)->context, val);
+  b = swfdec_as_value_to_boolean (swfdec_gc_object_get_context (movie), val);
   if (b != movie->visible) {
     movie->visible = b;
     swfdec_movie_invalidate_last (movie);
@@ -206,9 +206,9 @@ mc_width_set (SwfdecMovie *movie, const SwfdecAsValue *val)
   double d, cur;
 
   /* property was readonly in Flash 4 and before */
-  if (SWFDEC_AS_OBJECT (movie)->context->version < 5)
+  if (swfdec_gc_object_get_context (movie)->version < 5)
     return;
-  d = swfdec_as_value_to_number (SWFDEC_AS_OBJECT (movie)->context, val);
+  d = swfdec_as_value_to_number (swfdec_gc_object_get_context (movie), val);
   if (!isfinite (d)) {
     SWFDEC_WARNING ("trying to set width to a non-finite value, ignoring");
     return;
@@ -248,9 +248,9 @@ mc_height_set (SwfdecMovie *movie, const SwfdecAsValue *val)
   double d, cur;
 
   /* property was readonly in Flash 4 and before */
-  if (SWFDEC_AS_OBJECT (movie)->context->version < 5)
+  if (swfdec_gc_object_get_context (movie)->version < 5)
     return;
-  d = swfdec_as_value_to_number (SWFDEC_AS_OBJECT (movie)->context, val);
+  d = swfdec_as_value_to_number (swfdec_gc_object_get_context (movie), val);
   if (!isfinite (d)) {
     SWFDEC_WARNING ("trying to set height to a non-finite value, ignoring");
     return;
@@ -285,7 +285,7 @@ mc_rotation_set (SwfdecMovie *movie, const SwfdecAsValue *val)
   double d;
 
   /* FIXME: Flash 4 handles this differently */
-  d = swfdec_as_value_to_number (SWFDEC_AS_OBJECT (movie)->context, val);
+  d = swfdec_as_value_to_number (swfdec_gc_object_get_context (movie), val);
   if (isnan (d)) {
     SWFDEC_WARNING ("setting rotation to NaN - not allowed");
     return;
@@ -295,7 +295,7 @@ mc_rotation_set (SwfdecMovie *movie, const SwfdecAsValue *val)
     d -= 360.0;
   if (d < -180.0)
     d += 360.0;
-  if (SWFDEC_AS_OBJECT (movie)->context->version < 5) {
+  if (swfdec_gc_object_get_context (movie)->version < 5) {
     if (!isfinite (d))
       return;
     SWFDEC_FIXME ("implement correct rounding errors here");
@@ -361,7 +361,7 @@ mc_target_get (SwfdecMovie *movie, SwfdecAsValue *rval)
     g_string_free (s, TRUE);
   } else {
     SWFDEC_AS_VALUE_SET_STRING (rval, swfdec_as_context_give_string (
-	  SWFDEC_AS_OBJECT (movie)->context, g_string_free (s, FALSE)));
+	  swfdec_gc_object_get_context (movie), g_string_free (s, FALSE)));
   }
 }
 
@@ -369,7 +369,7 @@ static void
 mc_url_get (SwfdecMovie *movie, SwfdecAsValue *rval)
 {
   SWFDEC_AS_VALUE_SET_STRING (rval, swfdec_as_context_get_string (
-	SWFDEC_AS_OBJECT (movie)->context,
+	swfdec_gc_object_get_context (movie),
 	swfdec_url_get_url (swfdec_loader_get_url (movie->resource->loader))));
 }
 
@@ -384,7 +384,7 @@ mc_focusrect_get (SwfdecMovie *movie, SwfdecAsValue *rval)
     return;
   }
   actor = SWFDEC_ACTOR (movie);
-  cx = SWFDEC_AS_OBJECT (actor)->context;
+  cx = swfdec_gc_object_get_context (actor);
 
   switch (actor->focusrect) {
     case SWFDEC_FLASH_YES:
@@ -418,7 +418,7 @@ mc_focusrect_set (SwfdecMovie *movie, const SwfdecAsValue *val)
     SWFDEC_FIXME ("should not be possible to get _focusrect on non-actors");
     return;
   }
-  cx = SWFDEC_AS_OBJECT (movie)->context;
+  cx = swfdec_gc_object_get_context (movie);
   actor = SWFDEC_ACTOR (movie);
 
   if (SWFDEC_AS_VALUE_IS_UNDEFINED (val) ||
diff --git a/swfdec/swfdec_net_connection.c b/swfdec/swfdec_net_connection.c
index 6e288e3..234ca5f 100644
--- a/swfdec/swfdec_net_connection.c
+++ b/swfdec/swfdec_net_connection.c
@@ -66,7 +66,7 @@ swfdec_net_connection_onstatus (SwfdecNetConnection *conn, const char *code,
   SwfdecAsValue value;
   SwfdecAsObject *info;
 
-  info = swfdec_as_object_new (SWFDEC_AS_OBJECT (conn)->context);
+  info = swfdec_as_object_new (swfdec_gc_object_get_context (conn));
   SWFDEC_AS_VALUE_SET_STRING (&value, code);
   swfdec_as_object_set_variable (info, SWFDEC_AS_STR_code, &value);
   SWFDEC_AS_VALUE_SET_STRING (&value, level);
diff --git a/swfdec/swfdec_net_stream.c b/swfdec/swfdec_net_stream.c
index 8b9741e..77bbc21 100644
--- a/swfdec/swfdec_net_stream.c
+++ b/swfdec/swfdec_net_stream.c
@@ -46,7 +46,7 @@ swfdec_net_stream_onstatus (SwfdecNetStream *stream, const char *code, const cha
   SwfdecAsObject *object;
 
   swfdec_sandbox_use (stream->sandbox);
-  object = swfdec_as_object_new (SWFDEC_AS_OBJECT (stream)->context);
+  object = swfdec_as_object_new (swfdec_gc_object_get_context (stream));
   SWFDEC_INFO ("emitting onStatus for %s %s", level, code);
   SWFDEC_AS_VALUE_SET_STRING (&val, code);
   swfdec_as_object_set_variable (object, SWFDEC_AS_STR_code, &val);
@@ -61,8 +61,8 @@ swfdec_net_stream_onstatus (SwfdecNetStream *stream, const char *code, const cha
     if (level == SWFDEC_AS_STR_error) {
       SwfdecAsValue system;
 
-      swfdec_as_object_get_variable (SWFDEC_AS_OBJECT
-          (stream)->context->global, SWFDEC_AS_STR_System, &system);
+      swfdec_as_object_get_variable (swfdec_gc_object_get_context (stream)->global,
+          SWFDEC_AS_STR_System, &system);
       if (SWFDEC_AS_VALUE_IS_OBJECT (&system)) {
         swfdec_as_object_call (SWFDEC_AS_VALUE_GET_OBJECT (&system),
               SWFDEC_AS_STR_onStatus, 1, &val, NULL);
@@ -215,7 +215,7 @@ swfdec_net_stream_video_goto (SwfdecNetStream *stream, guint timestamp)
       process_events_from++; /* increase so we get the next event next time */
       swfdec_bits_init (&bits, event);
       swfdec_sandbox_use (stream->sandbox);
-      if (swfdec_amf_parse (SWFDEC_AS_OBJECT (stream)->context, &bits, 2, 
+      if (swfdec_amf_parse (swfdec_gc_object_get_context (stream), &bits, 2, 
 	    SWFDEC_AMF_STRING, &name, SWFDEC_AMF_MIXED_ARRAY, &value) != 2) {
 	SWFDEC_ERROR ("could not parse data tag");
       } else {
@@ -240,14 +240,14 @@ swfdec_net_stream_timeout (SwfdecTimeout *timeout)
       stream->timeout.callback) {
     SWFDEC_LOG ("readding timeout");
     stream->timeout.timestamp += SWFDEC_MSECS_TO_TICKS (stream->next_time - stream->current_time);
-    swfdec_player_add_timeout (SWFDEC_PLAYER (SWFDEC_AS_OBJECT (stream)->context), &stream->timeout);
+    swfdec_player_add_timeout (SWFDEC_PLAYER (swfdec_gc_object_get_context (stream)), &stream->timeout);
   }
 }
 
 static void
 swfdec_net_stream_update_playing (SwfdecNetStream *stream)
 {
-  SwfdecPlayer *player = SWFDEC_PLAYER (SWFDEC_AS_OBJECT (stream)->context);
+  SwfdecPlayer *player = SWFDEC_PLAYER (swfdec_gc_object_get_context (stream));
   gboolean should_play;
     
   should_play = stream->playing; /* checks user-set play/pause */
@@ -287,7 +287,7 @@ swfdec_net_stream_update_playing (SwfdecNetStream *stream)
 static SwfdecPlayer *
 swfdec_net_stream_stream_target_get_player (SwfdecStreamTarget *target)
 {
-  return SWFDEC_PLAYER (SWFDEC_AS_OBJECT (target)->context);
+  return SWFDEC_PLAYER (swfdec_gc_object_get_context (target));
 }
 
 static void
@@ -333,7 +333,7 @@ swfdec_net_stream_stream_target_parse (SwfdecStreamTarget *target,
     /* FIXME: add mp3 support */
     ns->flvdecoder = g_object_new (SWFDEC_TYPE_FLV_DECODER, NULL);
     g_signal_connect_swapped (ns->flvdecoder, "missing-plugin", 
-	G_CALLBACK (swfdec_player_add_missing_plugin), SWFDEC_AS_OBJECT (ns)->context);
+	G_CALLBACK (swfdec_player_add_missing_plugin), swfdec_gc_object_get_context (ns));
     swfdec_net_stream_onstatus (ns, SWFDEC_AS_STR_NetStream_Play_Start,
 	SWFDEC_AS_STR_status);
     swfdec_loader_set_data_type (SWFDEC_LOADER (stream), SWFDEC_LOADER_DATA_FLV);
@@ -535,28 +535,30 @@ swfdec_net_stream_get_variable (SwfdecAsObject *object, SwfdecAsObject *orig,
 }
 
 static void
-swfdec_net_stream_mark (SwfdecAsObject *object)
+swfdec_net_stream_mark (SwfdecGcObject *object)
 {
   SwfdecNetStream *stream = SWFDEC_NET_STREAM (object);
 
   if (stream->conn)
-    swfdec_as_object_mark (SWFDEC_AS_OBJECT (stream->conn));
+    swfdec_gc_object_mark (stream->conn);
   if (stream->sandbox)
-    swfdec_as_object_mark (SWFDEC_AS_OBJECT (stream->sandbox));
+    swfdec_gc_object_mark (stream->sandbox);
 
-  SWFDEC_AS_OBJECT_CLASS (swfdec_net_stream_parent_class)->mark (object);
+  SWFDEC_GC_OBJECT_CLASS (swfdec_net_stream_parent_class)->mark (object);
 }
 
 static void
 swfdec_net_stream_class_init (SwfdecNetStreamClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  SwfdecGcObjectClass *gc_class = SWFDEC_GC_OBJECT_CLASS (klass);
   SwfdecAsObjectClass *asobject_class = SWFDEC_AS_OBJECT_CLASS (klass);
 
   object_class->dispose = swfdec_net_stream_dispose;
 
+  gc_class->mark = swfdec_net_stream_mark;
+
   asobject_class->get = swfdec_net_stream_get_variable;
-  asobject_class->mark = swfdec_net_stream_mark;
 }
 
 static void
@@ -601,7 +603,7 @@ swfdec_net_stream_set_url (SwfdecNetStream *stream, const char *url_string)
   g_return_if_fail (SWFDEC_IS_NET_STREAM (stream));
   g_return_if_fail (url_string != NULL);
 
-  cx = SWFDEC_AS_OBJECT (stream)->context;
+  cx = swfdec_gc_object_get_context (stream);
   player = SWFDEC_PLAYER (cx);
 
   if (stream->requested_url != NULL) {
@@ -631,7 +633,7 @@ swfdec_net_stream_set_loader (SwfdecNetStream *stream, SwfdecLoader *loader)
   }
   if (stream->flvdecoder) {
     g_signal_handlers_disconnect_by_func (stream->flvdecoder,
-	  swfdec_player_add_missing_plugin, SWFDEC_AS_OBJECT (stream)->context);
+	  swfdec_player_add_missing_plugin, swfdec_gc_object_get_context (stream));
     g_object_unref (stream->flvdecoder);
     stream->flvdecoder = NULL;
   }
@@ -718,7 +720,7 @@ swfdec_net_stream_seek (SwfdecNetStream *stream, double secs)
     SWFDEC_WARNING ("FIXME: restarting audio after seek");
     swfdec_audio_remove (stream->audio);
     g_object_unref (stream->audio);
-    stream->audio = swfdec_audio_flv_new (SWFDEC_PLAYER (SWFDEC_AS_OBJECT (stream)->context), 
+    stream->audio = swfdec_audio_flv_new (SWFDEC_PLAYER (swfdec_gc_object_get_context (stream)), 
 	stream->flvdecoder, stream->current_time);
   }
 }
diff --git a/swfdec/swfdec_player.c b/swfdec/swfdec_player.c
index 316a1bd..fbf268f 100644
--- a/swfdec/swfdec_player.c
+++ b/swfdec/swfdec_player.c
@@ -2043,7 +2043,7 @@ static void
 swfdec_player_mark_string_object (gpointer key, gpointer value, gpointer data)
 {
   swfdec_as_string_mark (key);
-  swfdec_as_object_mark (value);
+  swfdec_gc_object_mark (value);
 }
 
 static void
@@ -2054,11 +2054,11 @@ swfdec_player_mark (SwfdecAsContext *context)
 
   g_hash_table_foreach (priv->registered_classes, swfdec_player_mark_string_object, NULL);
   g_hash_table_foreach (priv->scripting_callbacks, swfdec_player_mark_string_object, NULL);
-  g_list_foreach (priv->roots, (GFunc) swfdec_as_object_mark, NULL);
-  g_list_foreach (priv->intervals, (GFunc) swfdec_as_object_mark, NULL);
-  g_slist_foreach (priv->sandboxes, (GFunc) swfdec_as_object_mark, NULL);
+  g_list_foreach (priv->roots, (GFunc) swfdec_gc_object_mark, NULL);
+  g_list_foreach (priv->intervals, (GFunc) swfdec_gc_object_mark, NULL);
+  g_slist_foreach (priv->sandboxes, (GFunc) swfdec_gc_object_mark, NULL);
   swfdec_function_list_execute (&priv->rooted, player);
-  swfdec_as_object_mark (SWFDEC_AS_OBJECT (priv->resource));
+  swfdec_gc_object_mark (priv->resource);
 
   SWFDEC_AS_CONTEXT_CLASS (swfdec_player_parent_class)->mark (context);
 }
diff --git a/swfdec/swfdec_resource.c b/swfdec/swfdec_resource.c
index 0500216..5fb9f01 100644
--- a/swfdec/swfdec_resource.c
+++ b/swfdec/swfdec_resource.c
@@ -57,19 +57,19 @@ swfdec_resource_is_root (SwfdecResource *resource)
   g_return_val_if_fail (SWFDEC_IS_RESOURCE (resource), FALSE);
 
   return
-    resource->movie == SWFDEC_PLAYER (SWFDEC_AS_OBJECT (resource)->context)->priv->roots->data;
+    resource->movie == SWFDEC_PLAYER (swfdec_gc_object_get_context (resource))->priv->roots->data;
 }
 
 static SwfdecPlayer *
 swfdec_resource_stream_target_get_player (SwfdecStreamTarget *target)
 {
-  return SWFDEC_PLAYER (SWFDEC_AS_OBJECT (target)->context);
+  return SWFDEC_PLAYER (swfdec_gc_object_get_context (target));
 }
 
 static void
 swfdec_resource_stream_target_image (SwfdecResource *instance)
 {
-  SwfdecPlayer *player = SWFDEC_PLAYER (SWFDEC_AS_OBJECT (instance)->context);
+  SwfdecPlayer *player = SWFDEC_PLAYER (swfdec_gc_object_get_context (instance));
   SwfdecSpriteMovie *movie = instance->movie;
 
   if (movie->sprite != NULL)
@@ -118,7 +118,7 @@ swfdec_resource_emit_signal (SwfdecResource *resource, const char *name, gboolea
 
   if (resource->clip_loader == NULL)
     return;
-  cx = SWFDEC_AS_OBJECT (resource->clip_loader)->context;
+  cx = swfdec_gc_object_get_context (resource->clip_loader);
 
   SWFDEC_AS_VALUE_SET_STRING (&vals[0], name);
   if (resource->movie) {
@@ -180,7 +180,7 @@ swfdec_resource_replace_movie (SwfdecSpriteMovie *movie, SwfdecResource *resourc
   SwfdecMovie *mov = SWFDEC_MOVIE (movie);
   SwfdecMovie *copy;
   
-  copy = swfdec_movie_new (SWFDEC_PLAYER (SWFDEC_AS_OBJECT (movie)->context), 
+  copy = swfdec_movie_new (SWFDEC_PLAYER (swfdec_gc_object_get_context (movie)), 
       mov->depth, mov->parent, resource, NULL, mov->name);
   if (copy == NULL)
     return FALSE;
@@ -246,7 +246,7 @@ swfdec_resource_stream_target_parse (SwfdecStreamTarget *target, SwfdecStream *s
       glong total;
       resource->decoder = dec;
       g_signal_connect_swapped (dec, "missing-plugin", 
-	  G_CALLBACK (swfdec_player_add_missing_plugin), SWFDEC_AS_OBJECT (resource)->context);
+	  G_CALLBACK (swfdec_player_add_missing_plugin), swfdec_gc_object_get_context (resource));
       total = swfdec_loader_get_size (loader);
       if (total >= 0)
 	dec->bytes_total = total;
@@ -282,7 +282,7 @@ swfdec_resource_stream_target_parse (SwfdecStreamTarget *target, SwfdecStream *s
       if (SWFDEC_IS_SWF_DECODER (dec))
 	resource->version = SWFDEC_SWF_DECODER (dec)->version;
       if (swfdec_resource_is_root (resource)) {
-	swfdec_player_initialize (SWFDEC_PLAYER (SWFDEC_AS_OBJECT (resource)->context),
+	swfdec_player_initialize (SWFDEC_PLAYER (swfdec_gc_object_get_context (resource)),
 	    dec->rate, dec->width, dec->height);
       }
     }
@@ -301,7 +301,7 @@ swfdec_resource_abort_if_not_initialized (SwfdecResource *resource)
   if (resource->sandbox)
     return FALSE;
 
-  swfdec_as_context_abort (SWFDEC_AS_OBJECT (resource)->context,
+  swfdec_as_context_abort (swfdec_gc_object_get_context (resource),
       "This is not a Flash file");
   return TRUE;
 }
@@ -366,20 +366,20 @@ swfdec_resource_stream_target_init (SwfdecStreamTargetInterface *iface)
 }
 
 static void
-swfdec_resource_mark (SwfdecAsObject *object)
+swfdec_resource_mark (SwfdecGcObject *object)
 {
   SwfdecResource *resource = SWFDEC_RESOURCE (object);
 
   if (resource->clip_loader) {
-    swfdec_as_object_mark (SWFDEC_AS_OBJECT (resource->clip_loader));
-    swfdec_as_object_mark (SWFDEC_AS_OBJECT (resource->clip_loader_sandbox));
+    swfdec_gc_object_mark (resource->clip_loader);
+    swfdec_gc_object_mark (resource->clip_loader_sandbox);
   }
   if (resource->sandbox)
-    swfdec_as_object_mark (SWFDEC_AS_OBJECT (resource->sandbox));
+    swfdec_gc_object_mark (resource->sandbox);
   if (resource->target)
-    swfdec_as_object_mark (SWFDEC_AS_OBJECT (resource->target));
+    swfdec_gc_object_mark (resource->target);
 
-  SWFDEC_AS_OBJECT_CLASS (swfdec_resource_parent_class)->mark (object);
+  SWFDEC_GC_OBJECT_CLASS (swfdec_resource_parent_class)->mark (object);
 }
 
 static void
@@ -394,7 +394,7 @@ swfdec_resource_dispose (GObject *object)
   }
   if (resource->decoder) {
     g_signal_handlers_disconnect_by_func (resource->decoder,
-	  swfdec_player_add_missing_plugin, SWFDEC_AS_OBJECT (resource)->context);
+	  swfdec_player_add_missing_plugin, swfdec_gc_object_get_context (resource));
     g_object_unref (resource->decoder);
     resource->decoder = NULL;
   }
@@ -409,11 +409,11 @@ static void
 swfdec_resource_class_init (SwfdecResourceClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
-  SwfdecAsObjectClass *asobject_class = SWFDEC_AS_OBJECT_CLASS (klass);
+  SwfdecGcObjectClass *gc_class = SWFDEC_GC_OBJECT_CLASS (klass);
 
   object_class->dispose = swfdec_resource_dispose;
 
-  asobject_class->mark = swfdec_resource_mark;
+  gc_class->mark = swfdec_resource_mark;
 }
 
 static void
@@ -441,15 +441,11 @@ SwfdecResource *
 swfdec_resource_new (SwfdecPlayer *player, SwfdecLoader *loader, const char *variables)
 {
   SwfdecResource *resource;
-  guint size;
 
   g_return_val_if_fail (SWFDEC_IS_PLAYER (player), NULL);
   g_return_val_if_fail (SWFDEC_IS_LOADER (loader), NULL);
 
-  size = sizeof (SwfdecResource);
-  swfdec_as_context_use_mem (SWFDEC_AS_CONTEXT (player), size);
-  resource = g_object_new (SWFDEC_TYPE_RESOURCE, NULL);
-  swfdec_as_object_add (SWFDEC_AS_OBJECT (resource), SWFDEC_AS_CONTEXT (player), size);
+  resource = g_object_new (SWFDEC_TYPE_RESOURCE, "context", player, NULL);
   resource->version = 8;
   resource->variables = g_strdup (variables);
   swfdec_resource_set_loader (resource, loader);
@@ -515,11 +511,11 @@ swfdec_resource_load_mark (gpointer loadp, gpointer playerp)
 {
   SwfdecResourceLoad *load = loadp;
 
-  swfdec_as_object_mark (SWFDEC_AS_OBJECT (load->sandbox));
+  swfdec_gc_object_mark (load->sandbox);
   if (load->loader)
-    swfdec_as_object_mark (SWFDEC_AS_OBJECT (load->loader));
+    swfdec_gc_object_mark (load->loader);
   if (load->target_movie)
-    swfdec_as_object_mark (SWFDEC_AS_OBJECT (load->target_movie));
+    swfdec_gc_object_mark (load->target_movie);
 }
 
 static gboolean
@@ -530,7 +526,7 @@ swfdec_resource_create_movie (SwfdecResource *resource, SwfdecResourceLoad *load
 
   if (resource->movie)
     return TRUE;
-  player = SWFDEC_PLAYER (SWFDEC_AS_OBJECT (resource)->context);
+  player = SWFDEC_PLAYER (swfdec_gc_object_get_context (resource));
   if (load->target_movie) {
     movie = (SwfdecSpriteMovie *) swfdec_movie_resolve (SWFDEC_MOVIE (load->target_movie));
     if (SWFDEC_IS_SPRITE_MOVIE (movie))
@@ -564,9 +560,7 @@ swfdec_resource_do_load (SwfdecPlayer *player, gboolean allowed, gpointer loadp)
   SwfdecResource *resource;
   SwfdecLoader *loader;
   
-  swfdec_as_context_use_mem (SWFDEC_AS_CONTEXT (player), sizeof (SwfdecResource));
-  resource = g_object_new (SWFDEC_TYPE_RESOURCE, NULL);
-  swfdec_as_object_add (SWFDEC_AS_OBJECT (resource), SWFDEC_AS_CONTEXT (player), sizeof (SwfdecResource));
+  resource = g_object_new (SWFDEC_TYPE_RESOURCE, "context", player, NULL);
   resource->version = 8;
   if (load->loader) {
     resource->clip_loader = load->loader;
@@ -698,7 +692,7 @@ swfdec_resource_load_movie (SwfdecPlayer *player, const SwfdecAsValue *target,
       int i = swfdec_as_double_to_integer (SWFDEC_AS_VALUE_GET_NUMBER (target));
       if (i < 0)
 	return FALSE;
-      s = swfdec_as_context_give_string (SWFDEC_AS_OBJECT (loader)->context,
+      s = swfdec_as_context_give_string (swfdec_gc_object_get_context (loader),
 	  g_strdup_printf ("_level%d", i));
       swfdec_resource_load_internal (player, NULL, s, url, buffer, loader);
       return TRUE;
diff --git a/swfdec/swfdec_sandbox.c b/swfdec/swfdec_sandbox.c
index cdce611..f468a07 100644
--- a/swfdec/swfdec_sandbox.c
+++ b/swfdec/swfdec_sandbox.c
@@ -47,18 +47,18 @@
 G_DEFINE_TYPE (SwfdecSandbox, swfdec_sandbox, SWFDEC_TYPE_AS_OBJECT)
 
 static void
-swfdec_sandbox_mark (SwfdecAsObject *object)
+swfdec_sandbox_mark (SwfdecGcObject *object)
 {
   SwfdecSandbox *sandbox = SWFDEC_SANDBOX (object);
 
-  swfdec_as_object_mark (sandbox->Function);
-  swfdec_as_object_mark (sandbox->Function_prototype);
-  swfdec_as_object_mark (sandbox->Object);
-  swfdec_as_object_mark (sandbox->Object_prototype);
-  swfdec_as_object_mark (sandbox->MovieClip);
-  swfdec_as_object_mark (sandbox->Video);
+  swfdec_gc_object_mark (sandbox->Function);
+  swfdec_gc_object_mark (sandbox->Function_prototype);
+  swfdec_gc_object_mark (sandbox->Object);
+  swfdec_gc_object_mark (sandbox->Object_prototype);
+  swfdec_gc_object_mark (sandbox->MovieClip);
+  swfdec_gc_object_mark (sandbox->Video);
 
-  SWFDEC_AS_OBJECT_CLASS (swfdec_sandbox_parent_class)->mark (object);
+  SWFDEC_GC_OBJECT_CLASS (swfdec_sandbox_parent_class)->mark (object);
 }
 
 static void
@@ -75,11 +75,11 @@ static void
 swfdec_sandbox_class_init (SwfdecSandboxClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
-  SwfdecAsObjectClass *asobject_class = SWFDEC_AS_OBJECT_CLASS (klass);
+  SwfdecGcObjectClass *gc_class = SWFDEC_GC_OBJECT_CLASS (klass);
 
   object_class->dispose = swfdec_sandbox_dispose;
 
-  asobject_class->mark = swfdec_sandbox_mark;
+  gc_class->mark = swfdec_sandbox_mark;
 }
 
 static void
@@ -91,7 +91,7 @@ swfdec_sandbox_init (SwfdecSandbox *sandbox)
 static void
 swfdec_sandbox_initialize (SwfdecSandbox *sandbox, guint version)
 {
-  SwfdecAsContext *context = SWFDEC_AS_OBJECT (sandbox)->context;
+  SwfdecAsContext *context = swfdec_gc_object_get_context (sandbox);
   SwfdecPlayer *player = SWFDEC_PLAYER (context);
 
   swfdec_sandbox_use (sandbox);
@@ -207,11 +207,8 @@ swfdec_sandbox_get_for_url (SwfdecPlayer *player, const SwfdecURL *url,
       return NULL;
   } else {
     SwfdecAsContext *context = SWFDEC_AS_CONTEXT (player);
-    guint size = sizeof (SwfdecSandbox);
-    swfdec_as_context_use_mem (context, size);
 
-    sandbox = g_object_new (SWFDEC_TYPE_SANDBOX, NULL);
-    swfdec_as_object_add (SWFDEC_AS_OBJECT (sandbox), context, size);
+    sandbox = g_object_new (SWFDEC_TYPE_SANDBOX, "context", context, NULL);
     sandbox->url = real;
     sandbox->as_version = as_version;
     priv->sandboxes = g_slist_append (priv->sandboxes, sandbox);
@@ -242,9 +239,9 @@ swfdec_sandbox_use (SwfdecSandbox *sandbox)
 
   g_return_if_fail (SWFDEC_IS_SANDBOX (sandbox));
   g_return_if_fail (sandbox->type != SWFDEC_SANDBOX_NONE);
-  g_return_if_fail (SWFDEC_AS_OBJECT (sandbox)->context->global == NULL);
+  g_return_if_fail (swfdec_gc_object_get_context (sandbox)->global == NULL);
 
-  context = SWFDEC_AS_OBJECT (sandbox)->context;
+  context = swfdec_gc_object_get_context (sandbox);
   priv = SWFDEC_PLAYER (context)->priv;
   context->global = SWFDEC_AS_OBJECT (sandbox);
 
@@ -273,7 +270,7 @@ swfdec_sandbox_try_use (SwfdecSandbox *sandbox)
   g_return_val_if_fail (SWFDEC_IS_SANDBOX (sandbox), FALSE);
   g_return_val_if_fail (sandbox->type != SWFDEC_SANDBOX_NONE, FALSE);
 
-  if (SWFDEC_AS_OBJECT (sandbox)->context->global)
+  if (swfdec_gc_object_get_context (sandbox)->global)
     return FALSE;
 
   swfdec_sandbox_use (sandbox);
@@ -292,9 +289,9 @@ swfdec_sandbox_unuse (SwfdecSandbox *sandbox)
   SwfdecAsContext *context;
 
   g_return_if_fail (SWFDEC_IS_SANDBOX (sandbox));
-  g_return_if_fail (SWFDEC_AS_OBJECT (sandbox)->context->global == SWFDEC_AS_OBJECT (sandbox));
+  g_return_if_fail (swfdec_gc_object_get_context (sandbox)->global == SWFDEC_AS_OBJECT (sandbox));
 
-  context = SWFDEC_AS_OBJECT (sandbox)->context;
+  context = swfdec_gc_object_get_context (sandbox);
   context->global = NULL;
   context->Function = NULL;
   context->Function_prototype = NULL;
diff --git a/swfdec/swfdec_selection.c b/swfdec/swfdec_selection.c
index 4772b1a..853f2b4 100644
--- a/swfdec/swfdec_selection.c
+++ b/swfdec/swfdec_selection.c
@@ -120,7 +120,7 @@ swfdec_actor_can_grab_focus (SwfdecActor *actor)
     if (!swfdec_as_object_get_variable (SWFDEC_AS_OBJECT (actor),
 	SWFDEC_AS_STR_focusEnabled, &val))
       return swfdec_actor_get_mouse_events (actor);
-    return swfdec_as_value_to_boolean (SWFDEC_AS_OBJECT (actor)->context, &val);
+    return swfdec_as_value_to_boolean (swfdec_gc_object_get_context (actor), &val);
   } else if (SWFDEC_IS_TEXT_FIELD_MOVIE (actor)) {
     /* cool that you can select all textfields, eh? */
     return TRUE;
diff --git a/swfdec/swfdec_sound.c b/swfdec/swfdec_sound.c
index 581c0eb..d228e45 100644
--- a/swfdec/swfdec_sound.c
+++ b/swfdec/swfdec_sound.c
@@ -45,7 +45,7 @@ swfdec_sound_sound_provider_start (SwfdecSoundProvider *provider,
   SwfdecSound *sound = SWFDEC_SOUND (provider);
   SwfdecAudio *audio;
 
-  audio = swfdec_audio_event_new (SWFDEC_PLAYER (SWFDEC_AS_OBJECT (actor)->context),
+  audio = swfdec_audio_event_new (SWFDEC_PLAYER (swfdec_gc_object_get_context (actor)),
       sound, samples_offset, loops);
   swfdec_audio_set_actor (audio, actor);
   g_object_unref (audio);
@@ -75,7 +75,7 @@ swfdec_sound_sound_provider_stop (SwfdecSoundProvider *provider, SwfdecActor *ac
 {
   RemoveData data = { actor, SWFDEC_SOUND (provider) };
 
-  swfdec_player_stop_sounds (SWFDEC_PLAYER (SWFDEC_AS_OBJECT (actor)->context), 
+  swfdec_player_stop_sounds (SWFDEC_PLAYER (swfdec_gc_object_get_context (actor)), 
       swfdec_sound_object_should_stop, &data);
 }
 
diff --git a/swfdec/swfdec_sound_object.c b/swfdec/swfdec_sound_object.c
index 8e7993c..8150c78 100644
--- a/swfdec/swfdec_sound_object.c
+++ b/swfdec/swfdec_sound_object.c
@@ -39,14 +39,14 @@
 G_DEFINE_TYPE (SwfdecSoundObject, swfdec_sound_object, SWFDEC_TYPE_AS_OBJECT)
 
 static void
-swfdec_sound_object_mark (SwfdecAsObject *object)
+swfdec_sound_object_mark (SwfdecGcObject *object)
 {
   SwfdecSoundObject *sound = SWFDEC_SOUND_OBJECT (object);
 
   if (sound->target != NULL)
     swfdec_as_string_mark (sound->target);
 
-  SWFDEC_AS_OBJECT_CLASS (swfdec_sound_object_parent_class)->mark (object);
+  SWFDEC_GC_OBJECT_CLASS (swfdec_sound_object_parent_class)->mark (object);
 }
 
 static void
@@ -66,11 +66,11 @@ static void
 swfdec_sound_object_class_init (SwfdecSoundObjectClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
-  SwfdecAsObjectClass *asobject_class = SWFDEC_AS_OBJECT_CLASS (klass);
+  SwfdecGcObjectClass *gc_class = SWFDEC_GC_OBJECT_CLASS (klass);
 
   object_class->dispose = swfdec_sound_object_dispose;
 
-  asobject_class->mark = swfdec_sound_object_mark;
+  gc_class->mark = swfdec_sound_object_mark;
 }
 
 static void
@@ -81,7 +81,7 @@ swfdec_sound_object_init (SwfdecSoundObject *sound)
 static SwfdecActor *
 swfdec_sound_object_get_actor (SwfdecSoundObject *sound)
 {
-  SwfdecPlayer *player = SWFDEC_PLAYER (SWFDEC_AS_OBJECT (sound)->context);
+  SwfdecPlayer *player = SWFDEC_PLAYER (swfdec_gc_object_get_context (sound));
   SwfdecMovie *movie;
 
   movie = swfdec_player_get_movie_from_string (player, 
@@ -114,7 +114,7 @@ swfdec_sound_object_get_matrix (SwfdecSoundObject *sound)
   }
 
   if (sound->target == NULL) {
-    return &SWFDEC_PLAYER (SWFDEC_AS_OBJECT (sound)->context)->priv->sound_matrix;
+    return &SWFDEC_PLAYER (swfdec_gc_object_get_context (sound))->priv->sound_matrix;
   } else {
     SwfdecActor *actor = swfdec_sound_object_get_actor (sound);
     if (actor)
diff --git a/swfdec/swfdec_sprite.c b/swfdec/swfdec_sprite.c
index fe6386d..5a1044f 100644
--- a/swfdec/swfdec_sprite.c
+++ b/swfdec/swfdec_sprite.c
@@ -91,18 +91,6 @@ swfdec_sprite_get_action (SwfdecSprite *sprite, guint n, guint *tag, SwfdecBuffe
   return TRUE;
 }
 
-static SwfdecMovie *
-swfdec_sprite_create_movie (SwfdecGraphic *graphic, gsize *size)
-{
-  SwfdecSpriteMovie *ret = g_object_new (SWFDEC_TYPE_SPRITE_MOVIE, NULL);
-
-  ret->sprite = SWFDEC_SPRITE (graphic);
-  ret->n_frames = ret->sprite->n_frames;
-  *size = sizeof (SwfdecSpriteMovie);
-
-  return SWFDEC_MOVIE (ret);
-}
-
 static void
 swfdec_sprite_class_init (SwfdecSpriteClass * g_class)
 {
@@ -111,7 +99,7 @@ swfdec_sprite_class_init (SwfdecSpriteClass * g_class)
 
   object_class->dispose = swfdec_sprite_dispose;
 
-  graphic_class->create_movie = swfdec_sprite_create_movie;
+  graphic_class->movie_type = SWFDEC_TYPE_SPRITE_MOVIE;
 }
 
 static void
diff --git a/swfdec/swfdec_sprite_movie.c b/swfdec/swfdec_sprite_movie.c
index 47e5668..006767d 100644
--- a/swfdec/swfdec_sprite_movie.c
+++ b/swfdec/swfdec_sprite_movie.c
@@ -67,7 +67,7 @@ static gboolean
 swfdec_sprite_movie_perform_old_place (SwfdecSpriteMovie *movie,
     SwfdecBits *bits, guint tag)
 {
-  SwfdecPlayer *player = SWFDEC_PLAYER (SWFDEC_AS_OBJECT (movie)->context);
+  SwfdecPlayer *player = SWFDEC_PLAYER (swfdec_gc_object_get_context (movie));
   SwfdecMovie *mov = SWFDEC_MOVIE (movie);
   SwfdecMovie *cur;
   SwfdecSwfDecoder *dec;
@@ -137,7 +137,7 @@ swfdec_sprite_movie_perform_old_place (SwfdecSpriteMovie *movie,
 static gboolean
 swfdec_sprite_movie_perform_place (SwfdecSpriteMovie *movie, SwfdecBits *bits, guint tag)
 {
-  SwfdecPlayer *player = SWFDEC_PLAYER (SWFDEC_AS_OBJECT (movie)->context);
+  SwfdecPlayer *player = SWFDEC_PLAYER (swfdec_gc_object_get_context (movie));
   SwfdecMovie *mov = SWFDEC_MOVIE (movie);
   SwfdecMovie *cur;
   SwfdecSwfDecoder *dec;
@@ -359,7 +359,7 @@ swfdec_sprite_movie_start_sound (SwfdecMovie *movie, SwfdecBits *bits)
   chunk = swfdec_sound_parse_chunk (SWFDEC_SWF_DECODER (movie->resource->decoder), bits, id);
   if (chunk) {
     SwfdecAudio *audio = swfdec_audio_event_new_from_chunk (SWFDEC_PLAYER (
-	  SWFDEC_AS_OBJECT (movie)->context), chunk);
+	  swfdec_gc_object_get_context (movie)), chunk);
     if (audio)
       g_object_unref (audio);
   }
@@ -371,7 +371,7 @@ swfdec_sprite_movie_perform_one_action (SwfdecSpriteMovie *movie, guint tag, Swf
 {
   SwfdecMovie *mov = SWFDEC_MOVIE (movie);
   SwfdecActor *actor = SWFDEC_ACTOR (movie);
-  SwfdecPlayer *player = SWFDEC_PLAYER (SWFDEC_AS_OBJECT (mov)->context);
+  SwfdecPlayer *player = SWFDEC_PLAYER (swfdec_gc_object_get_context (mov));
   SwfdecBits bits;
 
   g_assert (mov->resource);
@@ -562,7 +562,7 @@ swfdec_sprite_movie_goto (SwfdecSpriteMovie *movie, guint goto_frame)
     return;
   }
 
-  player = SWFDEC_PLAYER (SWFDEC_AS_OBJECT (movie)->context);
+  player = SWFDEC_PLAYER (swfdec_gc_object_get_context (movie));
   SWFDEC_LOG ("doing goto %u for %p %d", goto_frame, movie, 
       SWFDEC_CHARACTER (movie->sprite)->id);
 
@@ -690,15 +690,29 @@ swfdec_sprite_movie_init_movie (SwfdecMovie *mov)
   swfdec_sprite_movie_goto (movie, 1);
 }
 
-static void
-swfdec_sprite_movie_add (SwfdecAsObject *object)
+static GObject *
+swfdec_sprite_movie_constructor (GType type, guint n_construct_properties,
+    GObjectConstructParam *construct_properties)
 {
-  SwfdecMovie *movie = SWFDEC_MOVIE (object);
+  GObject *object;
+  SwfdecMovie *movie;
+
+  object = G_OBJECT_CLASS (swfdec_sprite_movie_parent_class)->constructor (type, 
+      n_construct_properties, construct_properties);
 
-  if (movie->resource->sandbox)
-    swfdec_as_object_set_constructor (object, movie->resource->sandbox->MovieClip);
+  movie = SWFDEC_MOVIE (object);
+  if (movie->resource->sandbox) {
+    swfdec_as_object_set_constructor (SWFDEC_AS_OBJECT (movie), 
+	movie->resource->sandbox->MovieClip);
+  }
+
+  if (movie->graphic) {
+    SwfdecSpriteMovie *smovie = SWFDEC_SPRITE_MOVIE (object);
+    smovie->sprite = SWFDEC_SPRITE (movie->graphic);
+    smovie->n_frames = smovie->sprite->n_frames;
+  }
 
-  SWFDEC_AS_OBJECT_CLASS (swfdec_sprite_movie_parent_class)->add (object);
+  return object;
 }
 
 static void
@@ -729,7 +743,7 @@ static void
 swfdec_sprite_movie_finish_movie (SwfdecMovie *mov)
 {
   SwfdecSpriteMovie *movie = SWFDEC_SPRITE_MOVIE (mov);
-  SwfdecPlayer *player = SWFDEC_PLAYER (SWFDEC_AS_OBJECT (mov)->context);
+  SwfdecPlayer *player = SWFDEC_PLAYER (swfdec_gc_object_get_context (mov));
 
   swfdec_player_remove_all_actions (player, SWFDEC_ACTOR (mov));
   if (movie->sound_stream) {
@@ -740,17 +754,17 @@ swfdec_sprite_movie_finish_movie (SwfdecMovie *mov)
 }
 
 static void
-swfdec_sprite_movie_mark (SwfdecAsObject *object)
+swfdec_sprite_movie_mark (SwfdecGcObject *object)
 {
   GList *walk;
 
   for (walk = SWFDEC_MOVIE (object)->list; walk; walk = walk->next) {
     SwfdecAsObject *child = walk->data;
     g_assert (child->properties != NULL);
-    swfdec_as_object_mark (child);
+    swfdec_gc_object_mark (child);
   }
 
-  SWFDEC_AS_OBJECT_CLASS (swfdec_sprite_movie_parent_class)->mark (object);
+  SWFDEC_GC_OBJECT_CLASS (swfdec_sprite_movie_parent_class)->mark (object);
 }
 
 static void
@@ -778,14 +792,14 @@ static void
 swfdec_sprite_movie_class_init (SwfdecSpriteMovieClass * g_class)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (g_class);
-  SwfdecAsObjectClass *asobject_class = SWFDEC_AS_OBJECT_CLASS (g_class);
+  SwfdecGcObjectClass *gc_class = SWFDEC_GC_OBJECT_CLASS (g_class);
   SwfdecMovieClass *movie_class = SWFDEC_MOVIE_CLASS (g_class);
   SwfdecActorClass *actor_class = SWFDEC_ACTOR_CLASS (g_class);
 
   object_class->dispose = swfdec_sprite_movie_dispose;
+  object_class->constructor = swfdec_sprite_movie_constructor;
 
-  asobject_class->add = swfdec_sprite_movie_add;
-  asobject_class->mark = swfdec_sprite_movie_mark;
+  gc_class->mark = swfdec_sprite_movie_mark;
 
   movie_class->init_movie = swfdec_sprite_movie_init_movie;
   movie_class->finish_movie = swfdec_sprite_movie_finish_movie;
@@ -821,7 +835,7 @@ swfdec_sprite_movie_unload (SwfdecSpriteMovie *movie)
   g_return_if_fail (SWFDEC_IS_SPRITE_MOVIE (movie));
 
   mov = SWFDEC_MOVIE (movie);
-  swfdec_sprite_movie_clear (SWFDEC_AS_OBJECT (movie)->context, 
+  swfdec_sprite_movie_clear (swfdec_gc_object_get_context (movie), 
       SWFDEC_AS_OBJECT (movie), 0, NULL, &hack);
   /* FIXME: destroy or unload? */
   while (mov->list)
diff --git a/swfdec/swfdec_sprite_movie_as.c b/swfdec/swfdec_sprite_movie_as.c
index 7935692..bfd62b0 100644
--- a/swfdec/swfdec_sprite_movie_as.c
+++ b/swfdec/swfdec_sprite_movie_as.c
@@ -454,7 +454,7 @@ swfdec_sprite_movie_do_goto (SwfdecSpriteMovie *movie, SwfdecAsValue *target)
       return;
     frame++;
   } else {
-    frame = swfdec_as_value_to_integer (SWFDEC_AS_OBJECT (movie)->context, target);
+    frame = swfdec_as_value_to_integer (swfdec_gc_object_get_context (movie), target);
   }
   /* FIXME: how to handle overflow? */
   frame = CLAMP (frame, 1, (int) movie->n_frames);
@@ -711,7 +711,7 @@ swfdec_sprite_movie_init_from_object (SwfdecMovie *movie,
   g_return_if_fail (initObject == NULL || SWFDEC_IS_AS_OBJECT (initObject));
 
   if (initObject != NULL) {
-    SwfdecAsContext *cx = SWFDEC_AS_OBJECT (movie)->context;
+    SwfdecAsContext *cx = swfdec_gc_object_get_context (movie);
     if (cx->version <= 6) {
       swfdec_as_object_foreach (initObject,
 	  swfdec_sprite_movie_foreach_copy_properties, SWFDEC_AS_OBJECT (movie));
@@ -769,7 +769,8 @@ swfdec_sprite_movie_attachMovie (SwfdecAsContext *cx, SwfdecAsObject *object,
   ret = swfdec_movie_find (movie, depth);
   if (ret)
     swfdec_movie_remove (ret);
-  ret = swfdec_movie_new (SWFDEC_PLAYER (object->context), depth, movie, movie->resource, sprite, name);
+  ret = swfdec_movie_new (SWFDEC_PLAYER (swfdec_gc_object_get_context (object)),
+      depth, movie, movie->resource, sprite, name);
   SWFDEC_LOG ("attached %s (%u) as %s to depth %u", export, SWFDEC_CHARACTER (sprite)->id,
       ret->name, ret->depth);
   /* run init and construct */
diff --git a/swfdec/swfdec_style_sheet.c b/swfdec/swfdec_style_sheet.c
index 51dfa1c..2d3a249 100644
--- a/swfdec/swfdec_style_sheet.c
+++ b/swfdec/swfdec_style_sheet.c
@@ -68,7 +68,7 @@ swfdec_style_sheet_get_selector_object (SwfdecAsObject *object,
   g_return_val_if_fail (SWFDEC_IS_AS_OBJECT (object), NULL);
   g_return_val_if_fail (name != NULL, NULL);
 
-  empty = swfdec_as_object_new_empty (object->context);
+  empty = swfdec_as_object_new_empty (swfdec_gc_object_get_context (object));
   SWFDEC_AS_VALUE_SET_OBJECT (&val, empty);
   swfdec_as_object_unset_variable_flags (object, name,
       SWFDEC_AS_VARIABLE_CONSTANT);
@@ -363,5 +363,5 @@ swfdec_style_sheet_get_class_format (SwfdecStyleSheet *style, const char *name)
   memcpy (name_full + 1, name, strlen (name) + 1);
 
   return swfdec_style_sheet_get_format (style, swfdec_as_context_give_string (
-	SWFDEC_AS_OBJECT (style)->context, name_full));
+	swfdec_gc_object_get_context (style), name_full));
 }
diff --git a/swfdec/swfdec_text_field.c b/swfdec/swfdec_text_field.c
index 0711b8b..34257b5 100644
--- a/swfdec/swfdec_text_field.c
+++ b/swfdec/swfdec_text_field.c
@@ -39,31 +39,6 @@ swfdec_text_field_mouse_in (SwfdecGraphic *graphic, double x, double y)
   return swfdec_rect_contains (&graphic->extents, x, y);
 }
 
-static SwfdecMovie *
-swfdec_text_field_create_movie (SwfdecGraphic *graphic, gsize *size)
-{
-  SwfdecTextField *text = SWFDEC_TEXT_FIELD (graphic);
-  SwfdecTextFieldMovie *ret =
-    g_object_new (SWFDEC_TYPE_TEXT_FIELD_MOVIE, NULL);
-
-  ret->extents = graphic->extents;
-
-  ret->html = text->html;
-  ret->editable = text->editable;
-  swfdec_text_layout_set_password (ret->layout, text->password);
-  ret->max_chars = text->max_chars;
-  ret->selectable = text->selectable;
-  ret->embed_fonts = text->embed_fonts;
-  swfdec_text_layout_set_word_wrap (ret->layout, text->word_wrap);
-  ret->multiline = text->multiline;
-  ret->auto_size = text->auto_size;
-  ret->border = text->border;
-
-  *size = sizeof (SwfdecTextFieldMovie);
-
-  return SWFDEC_MOVIE (ret);
-}
-
 static void
 swfdec_text_field_dispose (GObject *object)
 {
@@ -92,7 +67,8 @@ swfdec_text_field_class_init (SwfdecTextFieldClass * g_class)
   SwfdecGraphicClass *graphic_class = SWFDEC_GRAPHIC_CLASS (g_class);
 
   object_class->dispose = swfdec_text_field_dispose;
-  graphic_class->create_movie = swfdec_text_field_create_movie;
+
+  graphic_class->movie_type = SWFDEC_TYPE_TEXT_FIELD_MOVIE;
   graphic_class->mouse_in = swfdec_text_field_mouse_in;
 }
 
diff --git a/swfdec/swfdec_text_field_movie.c b/swfdec/swfdec_text_field_movie.c
index 28712df..bd21c74 100644
--- a/swfdec/swfdec_text_field_movie.c
+++ b/swfdec/swfdec_text_field_movie.c
@@ -75,14 +75,14 @@ swfdec_text_field_movie_update_area (SwfdecTextFieldMovie *text)
   cairo_matrix_t *matrix, translate;
   double x, y;
 
-  if (swfdec_player_is_locked (SWFDEC_PLAYER (SWFDEC_AS_OBJECT (text)->context)))
+  if (swfdec_player_is_locked (SWFDEC_PLAYER (swfdec_gc_object_get_context (text))))
     swfdec_movie_invalidate_next (movie);
 
   /* check if we indeed want to render */
   matrix = &text->to_layout;
   swfdec_movie_local_to_global_matrix (movie, matrix);
   cairo_matrix_multiply (matrix, matrix,
-      &SWFDEC_PLAYER (SWFDEC_AS_OBJECT (movie)->context)->priv->global_to_stage);
+      &SWFDEC_PLAYER (swfdec_gc_object_get_context (movie))->priv->global_to_stage);
   if (matrix->xy != 0.0 || matrix->yx != 0.0 ||
       matrix->xx <= 0.0 || matrix->yy <= 0.0) {
     swfdec_rectangle_init_empty (&text->stage_area);
@@ -205,15 +205,15 @@ swfdec_text_field_movie_invalidate (SwfdecMovie *movie, const cairo_matrix_t *ma
   }
 
   swfdec_rect_transform (&rect, &rect,
-      &SWFDEC_PLAYER (SWFDEC_AS_OBJECT (text)->context)->priv->stage_to_global);
+      &SWFDEC_PLAYER (swfdec_gc_object_get_context (text))->priv->stage_to_global);
   swfdec_player_invalidate (
-      SWFDEC_PLAYER (SWFDEC_AS_OBJECT (movie)->context), &rect);
+      SWFDEC_PLAYER (swfdec_gc_object_get_context (movie)), &rect);
 }
 
 static gboolean
 swfdec_text_field_movie_has_focus (SwfdecTextFieldMovie *text)
 {
-  SwfdecPlayer *player = SWFDEC_PLAYER (SWFDEC_AS_OBJECT (text)->context);
+  SwfdecPlayer *player = SWFDEC_PLAYER (swfdec_gc_object_get_context (text));
 
   return swfdec_player_has_focus (player, SWFDEC_ACTOR (text));
 }
@@ -309,7 +309,7 @@ swfdec_text_field_movie_dispose (GObject *object)
 }
 
 static void
-swfdec_text_field_movie_mark (SwfdecAsObject *object)
+swfdec_text_field_movie_mark (SwfdecGcObject *object)
 {
   SwfdecTextFieldMovie *text;
 
@@ -320,13 +320,13 @@ swfdec_text_field_movie_mark (SwfdecAsObject *object)
 
   swfdec_text_buffer_mark (text->text);
   if (text->style_sheet != NULL)
-    swfdec_as_object_mark (text->style_sheet);
+    swfdec_gc_object_mark (text->style_sheet);
   if (text->style_sheet_input != NULL)
     swfdec_as_string_mark (text->style_sheet_input);
   if (text->restrict_ != NULL)
     swfdec_as_string_mark (text->restrict_);
 
-  SWFDEC_AS_OBJECT_CLASS (swfdec_text_field_movie_parent_class)->mark (object);
+  SWFDEC_GC_OBJECT_CLASS (swfdec_text_field_movie_parent_class)->mark (object);
 }
 
 void
@@ -335,7 +335,7 @@ swfdec_text_field_movie_emit_onScroller (SwfdecTextFieldMovie *text)
   g_return_if_fail (SWFDEC_IS_TEXT_FIELD_MOVIE (text));
 
   if (!text->onScroller_emitted && swfdec_movie_get_version (SWFDEC_MOVIE (text)) > 6) {
-    swfdec_player_add_action (SWFDEC_PLAYER (SWFDEC_AS_OBJECT (text)->context), 
+    swfdec_player_add_action (SWFDEC_PLAYER (swfdec_gc_object_get_context (text)), 
 	SWFDEC_ACTOR (text), SWFDEC_EVENT_SCROLL, 0, SWFDEC_PLAYER_ACTION_QUEUE_NORMAL);
   }
   text->onScroller_emitted = TRUE;
@@ -393,7 +393,7 @@ swfdec_text_field_movie_init_movie (SwfdecMovie *movie)
 
   needs_unuse = swfdec_sandbox_try_use (movie->resource->sandbox);
 
-  cx = SWFDEC_AS_OBJECT (movie)->context;
+  cx = swfdec_gc_object_get_context (movie);
 
   swfdec_text_field_movie_init_properties (cx);
 
@@ -420,6 +420,19 @@ swfdec_text_field_movie_init_movie (SwfdecMovie *movie)
   text->background_color = SWFDEC_COLOR_COMBINE (255, 255, 255, 0);
 
   if (text_field) {
+    text->extents = SWFDEC_GRAPHIC (text_field)->extents;
+
+    text->html = text_field->html;
+    text->editable = text_field->editable;
+    swfdec_text_layout_set_password (text->layout, text_field->password);
+    text->max_chars = text_field->max_chars;
+    text->selectable = text_field->selectable;
+    text->embed_fonts = text_field->embed_fonts;
+    swfdec_text_layout_set_word_wrap (text->layout, text_field->word_wrap);
+    text->multiline = text_field->multiline;
+    text->auto_size = text_field->auto_size;
+    text->border = text_field->border;
+
     text->text->default_attributes.color = text_field->color;
     text->text->default_attributes.align = text_field->align;
     if (text_field->font != NULL)  {
@@ -488,13 +501,13 @@ swfdec_text_field_movie_iterate (SwfdecActor *actor)
   SwfdecTextFieldMovie *text = SWFDEC_TEXT_FIELD_MOVIE (actor);
 
   while (text->changed) {
-    swfdec_player_add_action (SWFDEC_PLAYER (SWFDEC_AS_OBJECT (text)->context), 
+    swfdec_player_add_action (SWFDEC_PLAYER (swfdec_gc_object_get_context (text)), 
 	SWFDEC_ACTOR (text), SWFDEC_EVENT_CHANGED, 0, SWFDEC_PLAYER_ACTION_QUEUE_NORMAL);
     text->changed--;
   }
 
   if (text->onScroller_emitted && swfdec_movie_get_version (SWFDEC_MOVIE (text)) <= 6) {
-    swfdec_player_add_action (SWFDEC_PLAYER (SWFDEC_AS_OBJECT (text)->context), 
+    swfdec_player_add_action (SWFDEC_PLAYER (swfdec_gc_object_get_context (text)), 
 	SWFDEC_ACTOR (text), SWFDEC_EVENT_SCROLL, 0, SWFDEC_PLAYER_ACTION_QUEUE_NORMAL);
   }
   text->onScroller_emitted = FALSE;
@@ -528,7 +541,7 @@ swfdec_text_field_movie_letter_clicked (SwfdecTextFieldMovie *text,
   attr = swfdec_text_buffer_get_attributes (text->text, index_);
 
   if (attr->url != SWFDEC_AS_STR_EMPTY) {
-    swfdec_player_launch (SWFDEC_PLAYER (SWFDEC_AS_OBJECT (text)->context),
+    swfdec_player_launch (SWFDEC_PLAYER (swfdec_gc_object_get_context (text)),
 	attr->url, attr->target, NULL);
   }
 }
@@ -608,7 +621,7 @@ swfdec_text_field_movie_mouse_press (SwfdecActor *actor, guint button)
     text->character_pressed = -1;
   }
 
-  swfdec_player_grab_focus (SWFDEC_PLAYER (SWFDEC_AS_OBJECT (text)->context), actor);
+  swfdec_player_grab_focus (SWFDEC_PLAYER (swfdec_gc_object_get_context (text)), actor);
 
   text->mouse_pressed = TRUE;
   swfdec_text_buffer_set_cursor (text->text, index_, index_);
@@ -789,12 +802,12 @@ swfdec_text_field_movie_property_set (SwfdecMovie *movie, guint prop_id,
     const SwfdecAsValue *val)
 {
   SwfdecTextFieldMovie *text = SWFDEC_TEXT_FIELD_MOVIE (movie);
-  SwfdecAsContext *cx = SWFDEC_AS_OBJECT (movie)->context;
+  SwfdecAsContext *cx = swfdec_gc_object_get_context (movie);
   SwfdecTwips twips;
 
   switch (prop_id) {
     case SWFDEC_MOVIE_PROPERTY_X:
-      if (!swfdec_as_value_to_twips (SWFDEC_AS_OBJECT (movie)->context, val, FALSE, &twips))
+      if (!swfdec_as_value_to_twips (swfdec_gc_object_get_context (movie), val, FALSE, &twips))
 	return;
       movie->modified = TRUE;
       twips -= text->extents.x0;
@@ -805,7 +818,7 @@ swfdec_text_field_movie_property_set (SwfdecMovie *movie, guint prop_id,
       }
       return;
     case SWFDEC_MOVIE_PROPERTY_Y:
-      if (!swfdec_as_value_to_twips (SWFDEC_AS_OBJECT (movie)->context, val, FALSE, &twips))
+      if (!swfdec_as_value_to_twips (swfdec_gc_object_get_context (movie), val, FALSE, &twips))
 	return;
       movie->modified = TRUE;
       twips -= text->extents.y0;
@@ -849,13 +862,13 @@ static void
 swfdec_text_field_movie_class_init (SwfdecTextFieldMovieClass * g_class)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (g_class);
-  SwfdecAsObjectClass *asobject_class = SWFDEC_AS_OBJECT_CLASS (g_class);
+  SwfdecGcObjectClass *gc_class = SWFDEC_GC_OBJECT_CLASS (g_class);
   SwfdecMovieClass *movie_class = SWFDEC_MOVIE_CLASS (g_class);
   SwfdecActorClass *actor_class = SWFDEC_ACTOR_CLASS (g_class);
 
   object_class->dispose = swfdec_text_field_movie_dispose;
 
-  asobject_class->mark = swfdec_text_field_movie_mark;
+  gc_class->mark = swfdec_text_field_movie_mark;
 
   movie_class->init_movie = swfdec_text_field_movie_init_movie;
   movie_class->finish_movie = swfdec_text_field_movie_finish_movie;
@@ -930,7 +943,7 @@ swfdec_text_field_movie_parse_listen_variable (SwfdecTextFieldMovie *text,
     return;
 
   g_assert (SWFDEC_IS_AS_OBJECT (SWFDEC_MOVIE (text)->parent));
-  cx = SWFDEC_AS_OBJECT (text)->context;
+  cx = swfdec_gc_object_get_context (text);
   parent = SWFDEC_AS_OBJECT (SWFDEC_MOVIE (text)->parent);
 
   p1 = strrchr (variable, '.');
@@ -980,7 +993,7 @@ swfdec_text_field_movie_variable_listener_callback (SwfdecAsObject *object,
 
   text = SWFDEC_TEXT_FIELD_MOVIE (object);
   swfdec_text_field_movie_set_text (text,
-      swfdec_as_value_to_string (object->context, val), text->html);
+      swfdec_as_value_to_string (swfdec_gc_object_get_context (text), val), text->html);
 }
 
 void
@@ -1015,12 +1028,12 @@ swfdec_text_field_movie_set_listen_variable (SwfdecTextFieldMovie *text,
 	&name);
     if (object != NULL && swfdec_as_object_get_variable (object, name, &val)) {
       swfdec_text_field_movie_set_text (text,
-	  swfdec_as_value_to_string (SWFDEC_AS_OBJECT (text)->context, &val),
+	  swfdec_as_value_to_string (swfdec_gc_object_get_context (text), &val),
 	  text->html);
     } else if (text_field != NULL && text_field->input != NULL) {
       // Set to the original value from the tag, not current value
       const char *initial = swfdec_as_context_get_string (
-	  SWFDEC_AS_OBJECT (text)->context, text_field->input);
+	  swfdec_gc_object_get_context (text), text_field->input);
       swfdec_text_field_movie_set_listen_variable_text (text, initial);
       // FIXME: html value correct here?
       swfdec_text_field_movie_set_text (text, initial, text_field->html);
@@ -1062,7 +1075,7 @@ swfdec_text_field_movie_get_text (SwfdecTextFieldMovie *text)
     *p = '\r';
   }
 
-  return swfdec_as_context_give_string (SWFDEC_AS_OBJECT (text)->context, ret);
+  return swfdec_as_context_give_string (swfdec_gc_object_get_context (text), ret);
 }
 
 void
@@ -1075,14 +1088,14 @@ swfdec_text_field_movie_set_text (SwfdecTextFieldMovie *text, const char *str,
   g_return_if_fail (str != NULL);
 
   /* Flash 7 resets to default style here */
-  if (html && SWFDEC_AS_OBJECT (text)->context->version < 8)
+  if (html && swfdec_gc_object_get_context (text)->version < 8)
     swfdec_text_buffer_reset_default_attributes (text->text);
 
   length = swfdec_text_buffer_get_length (text->text);
   if (length)
     swfdec_text_buffer_delete_text (text->text, 0, length);
 
-  if (SWFDEC_AS_OBJECT (text)->context->version >= 7 &&
+  if (swfdec_gc_object_get_context (text)->version >= 7 &&
       text->style_sheet != NULL)
   {
     text->style_sheet_input = str;
diff --git a/swfdec/swfdec_text_field_movie_as.c b/swfdec/swfdec_text_field_movie_as.c
index 5b18e66..d09919b 100644
--- a/swfdec/swfdec_text_field_movie_as.c
+++ b/swfdec/swfdec_text_field_movie_as.c
@@ -1550,9 +1550,7 @@ swfdec_text_field_movie_construct (SwfdecAsContext *cx, SwfdecAsObject *object,
 {
   if (!cx->frame->construct) {
     SwfdecAsValue val;
-    swfdec_as_context_use_mem (cx, sizeof (SwfdecAsObject));
-    object = g_object_new (SWFDEC_TYPE_AS_OBJECT, NULL);
-    swfdec_as_object_add (object, cx, sizeof (SwfdecAsObject));
+    object = swfdec_as_object_new_empty (cx);
     swfdec_as_object_get_variable (cx->global, SWFDEC_AS_STR_TextField, &val);
     if (SWFDEC_AS_VALUE_IS_OBJECT (&val)) {
       swfdec_as_object_set_constructor (object,
diff --git a/swfdec/swfdec_text_field_movie_html.c b/swfdec/swfdec_text_field_movie_html.c
index e882493..bcc606d 100644
--- a/swfdec/swfdec_text_field_movie_html.c
+++ b/swfdec/swfdec_text_field_movie_html.c
@@ -129,7 +129,7 @@ swfdec_text_field_movie_html_tag_set_attribute (ParserData *data,
 
   object = SWFDEC_AS_OBJECT (tag->format);
   SWFDEC_AS_VALUE_SET_STRING (&val, swfdec_as_context_give_string (
-	object->context, g_strndup (value, value_length)));
+	swfdec_gc_object_get_context (object), g_strndup (value, value_length)));
 
   if (tag->name_length == 10 && !g_strncasecmp (tag->name, "textformat", 10))
   {
@@ -494,7 +494,7 @@ swfdec_text_field_movie_html_parse (SwfdecTextFieldMovie *text, const char *str)
   g_return_if_fail (SWFDEC_IS_TEXT_FIELD_MOVIE (text));
   g_return_if_fail (str != NULL);
 
-  data.cx = SWFDEC_AS_OBJECT (text)->context;
+  data.cx = swfdec_gc_object_get_context (text);
   data.multiline = (data.cx->version < 7 || text->multiline);
   data.condense_white = text->condense_white;
   if (text->style_sheet != NULL && SWFDEC_IS_STYLESHEET (text->style_sheet)) {
@@ -811,6 +811,6 @@ swfdec_text_field_movie_get_html_text (SwfdecTextFieldMovie *text)
     if (*p != '\0') p++;
   }
 
-  return swfdec_as_context_give_string (SWFDEC_AS_OBJECT (text)->context,
+  return swfdec_as_context_give_string (swfdec_gc_object_get_context (text),
       g_string_free (string, FALSE));
 }
diff --git a/swfdec/swfdec_text_format.c b/swfdec/swfdec_text_format.c
index 9ec4d15..b1ebb00 100644
--- a/swfdec/swfdec_text_format.c
+++ b/swfdec/swfdec_text_format.c
@@ -64,21 +64,21 @@ static int property_offsets[] = {
 };
 
 static void
-swfdec_text_format_do_mark (SwfdecAsObject *object)
+swfdec_text_format_mark (SwfdecGcObject *object)
 {
   SwfdecTextFormat *format = SWFDEC_TEXT_FORMAT (object);
 
   swfdec_text_attributes_mark (&format->attr);
 
-  SWFDEC_AS_OBJECT_CLASS (swfdec_text_format_parent_class)->mark (object);
+  SWFDEC_GC_OBJECT_CLASS (swfdec_text_format_parent_class)->mark (object);
 }
 
 static void
 swfdec_text_format_class_init (SwfdecTextFormatClass *klass)
 {
-  SwfdecAsObjectClass *asobject_class = SWFDEC_AS_OBJECT_CLASS (klass);
+  SwfdecGcObjectClass *gc_class = SWFDEC_GC_OBJECT_CLASS (klass);
 
-  asobject_class->mark = swfdec_text_format_do_mark;
+  gc_class->mark = swfdec_text_format_mark;
 }
 
 static void
@@ -111,6 +111,7 @@ swfdec_text_format_set_string (SwfdecAsObject *object,
     SwfdecTextAttribute property, guint argc, SwfdecAsValue *argv)
 {
   SwfdecTextFormat *format;
+  SwfdecAsContext *context;
   const char *s;
 
   if (!SWFDEC_IS_TEXT_FORMAT (object))
@@ -120,9 +121,10 @@ swfdec_text_format_set_string (SwfdecAsObject *object,
   if (argc < 1)
     return;
 
-  swfdec_as_value_to_integer (object->context, &argv[0]);
-  swfdec_as_value_to_number (object->context, &argv[0]);
-  s = swfdec_as_value_to_string (object->context, &argv[0]);
+  context = swfdec_gc_object_get_context (format);
+  swfdec_as_value_to_integer (context, &argv[0]);
+  swfdec_as_value_to_number (context, &argv[0]);
+  s = swfdec_as_value_to_string (context, &argv[0]);
 
   if (SWFDEC_AS_VALUE_IS_UNDEFINED (&argv[0]) ||
       SWFDEC_AS_VALUE_IS_NULL (&argv[0])) {
@@ -162,6 +164,7 @@ swfdec_text_format_set_boolean (SwfdecAsObject *object,
     SwfdecTextAttribute property, guint argc, SwfdecAsValue *argv)
 {
   SwfdecTextFormat *format;
+  SwfdecAsContext *context;
 
   if (!SWFDEC_IS_TEXT_FORMAT (object))
     return;
@@ -170,16 +173,17 @@ swfdec_text_format_set_boolean (SwfdecAsObject *object,
   if (argc < 1)
     return;
 
-  swfdec_as_value_to_integer (object->context, &argv[0]);
-  swfdec_as_value_to_number (object->context, &argv[0]);
-  swfdec_as_value_to_string (object->context, &argv[0]);
+  context = swfdec_gc_object_get_context (format);
+  swfdec_as_value_to_integer (context, &argv[0]);
+  swfdec_as_value_to_number (context, &argv[0]);
+  swfdec_as_value_to_string (context, &argv[0]);
 
   if (SWFDEC_AS_VALUE_IS_UNDEFINED (&argv[0]) ||
       SWFDEC_AS_VALUE_IS_NULL (&argv[0])) {
     SWFDEC_TEXT_ATTRIBUTE_UNSET (format->values_set, property);
   } else {
     G_STRUCT_MEMBER (gboolean, format, property_offsets[property]) =
-      swfdec_as_value_to_boolean (object->context, &argv[0]);
+      swfdec_as_value_to_boolean (context, &argv[0]);
     SWFDEC_TEXT_ATTRIBUTE_SET (format->values_set, property);
   }
 }
@@ -262,8 +266,8 @@ swfdec_text_format_set_integer (SwfdecAsObject *object,
     SWFDEC_TEXT_ATTRIBUTE_UNSET (format->values_set, property);
   } else {
     G_STRUCT_MEMBER (int, format, property_offsets[property]) =
-      swfdec_text_format_value_to_integer (object->context, &argv[0],
-	  allow_negative);
+      swfdec_text_format_value_to_integer (swfdec_gc_object_get_context (format),
+	  &argv[0], allow_negative);
     SWFDEC_TEXT_ATTRIBUTE_SET (format->values_set, property);
   }
 }
@@ -904,7 +908,7 @@ swfdec_text_format_set_defaults (SwfdecTextFormat *format)
   swfdec_text_attributes_reset (&format->attr);
   format->values_set = SWFDEC_TEXT_ATTRIBUTES_MASK;
 
-  if (SWFDEC_AS_OBJECT (format)->context->version < 8) {
+  if (swfdec_gc_object_get_context (format)->version < 8) {
     SWFDEC_TEXT_ATTRIBUTE_UNSET (format->values_set, SWFDEC_TEXT_ATTRIBUTE_KERNING);
     SWFDEC_TEXT_ATTRIBUTE_UNSET (format->values_set, SWFDEC_TEXT_ATTRIBUTE_LETTER_SPACING);
   }
@@ -1044,7 +1048,7 @@ swfdec_text_format_construct (SwfdecAsContext *cx, SwfdecAsObject *object,
 }
 
 SwfdecTextFormat *
-swfdec_text_format_copy (const SwfdecTextFormat *copy_from)
+swfdec_text_format_copy (SwfdecTextFormat *copy_from)
 {
   SwfdecAsObject *object_to;
   SwfdecTextFormat *copy_to;
@@ -1052,7 +1056,7 @@ swfdec_text_format_copy (const SwfdecTextFormat *copy_from)
   g_return_val_if_fail (SWFDEC_IS_TEXT_FORMAT (copy_from), NULL);
 
   object_to = swfdec_text_format_new_no_properties (
-      SWFDEC_AS_OBJECT (copy_from)->context);
+      swfdec_gc_object_get_context (copy_from));
   if (object_to == NULL)
     return NULL;
   copy_to = SWFDEC_TEXT_FORMAT (object_to);
@@ -1072,10 +1076,7 @@ swfdec_text_format_new_no_properties (SwfdecAsContext *context)
 
   g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context), NULL);
 
-  swfdec_as_context_use_mem (context, sizeof (SwfdecTextFormat));
-
-  ret = g_object_new (SWFDEC_TYPE_TEXT_FORMAT, NULL);
-  swfdec_as_object_add (ret, context, sizeof (SwfdecTextFormat));
+  ret = g_object_new (SWFDEC_TYPE_TEXT_FORMAT, "context", context, NULL);
 
   swfdec_text_format_clear (SWFDEC_TEXT_FORMAT (ret));
 
diff --git a/swfdec/swfdec_text_format.h b/swfdec/swfdec_text_format.h
index ed5ef75..a5f32a4 100644
--- a/swfdec/swfdec_text_format.h
+++ b/swfdec/swfdec_text_format.h
@@ -56,7 +56,7 @@ GType		swfdec_text_format_get_type	(void);
 SwfdecAsObject * swfdec_text_format_new		(SwfdecAsContext *	context);
 SwfdecAsObject * swfdec_text_format_new_no_properties (SwfdecAsContext *	context);
 void		swfdec_text_format_set_defaults	(SwfdecTextFormat *	format);
-SwfdecTextFormat * swfdec_text_format_copy	(const SwfdecTextFormat *copy_from);
+SwfdecTextFormat * swfdec_text_format_copy	(SwfdecTextFormat *	copy_from);
 void		swfdec_text_format_add		(SwfdecTextFormat *	format,
 						 const SwfdecTextFormat *from);
 gboolean	swfdec_text_format_equal	(const SwfdecTextFormat *a,
diff --git a/swfdec/swfdec_transform_as.c b/swfdec/swfdec_transform_as.c
index 9d1b990..2efd3a8 100644
--- a/swfdec/swfdec_transform_as.c
+++ b/swfdec/swfdec_transform_as.c
@@ -202,15 +202,11 @@ swfdec_transform_as_new (SwfdecAsContext *context, SwfdecMovie *target)
 {
   SwfdecAsValue val;
   SwfdecTransformAs *transform;
-  guint size;
 
   g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context), NULL);
   g_return_val_if_fail (SWFDEC_IS_MOVIE (target), NULL);
 
-  size = sizeof (SwfdecTransformAs);
-  swfdec_as_context_use_mem (context, size);
-  transform = g_object_new (SWFDEC_TYPE_TRANSFORM_AS, NULL);
-  swfdec_as_object_add (SWFDEC_AS_OBJECT (transform), context, size);
+  transform = g_object_new (SWFDEC_TYPE_TRANSFORM_AS, "context", context, NULL);
 
   swfdec_as_object_get_variable (context->global, SWFDEC_AS_STR_flash, &val);
   if (SWFDEC_AS_VALUE_IS_OBJECT (&val)) {
diff --git a/swfdec/swfdec_video.c b/swfdec/swfdec_video.c
index a03c758..451164d 100644
--- a/swfdec/swfdec_video.c
+++ b/swfdec/swfdec_video.c
@@ -27,29 +27,11 @@
 #include "swfdec_swf_decoder.h"
 #include "swfdec_video_decoder.h"
 #include "swfdec_video_movie.h"
-#include "swfdec_video_video_provider.h"
 
 /*** SWFDEC_VIDEO ***/
 
 G_DEFINE_TYPE (SwfdecVideo, swfdec_video, SWFDEC_TYPE_GRAPHIC)
 
-static SwfdecMovie *
-swfdec_video_create_movie (SwfdecGraphic *graphic, gsize *size)
-{
-  SwfdecVideo *video = SWFDEC_VIDEO (graphic);
-  SwfdecVideoMovie *movie = g_object_new (SWFDEC_TYPE_VIDEO_MOVIE, NULL);
-
-  movie->video = video;
-  g_object_ref (video);
-  if (video->n_frames > 0) {
-    SwfdecVideoProvider *provider = swfdec_video_video_provider_new (video);
-    swfdec_video_movie_set_provider (movie, provider);
-    g_object_unref (provider);
-  }
-  *size = sizeof (SwfdecVideoMovie);
-  return SWFDEC_MOVIE (movie);
-}
-
 static void
 swfdec_video_dispose (GObject *object)
 {
@@ -71,7 +53,7 @@ swfdec_video_class_init (SwfdecVideoClass * g_class)
 
   object_class->dispose = swfdec_video_dispose;
 
-  graphic_class->create_movie = swfdec_video_create_movie;
+  graphic_class->movie_type = SWFDEC_TYPE_VIDEO_MOVIE;
 }
 
 static void
diff --git a/swfdec/swfdec_video_movie.c b/swfdec/swfdec_video_movie.c
index 897aa8c..86aa47f 100644
--- a/swfdec/swfdec_video_movie.c
+++ b/swfdec/swfdec_video_movie.c
@@ -29,6 +29,7 @@
 #include "swfdec_renderer_internal.h"
 #include "swfdec_utils.h"
 #include "swfdec_video_provider.h"
+#include "swfdec_video_video_provider.h"
 
 G_DEFINE_TYPE (SwfdecVideoMovie, swfdec_video_movie, SWFDEC_TYPE_MOVIE)
 
@@ -36,10 +37,10 @@ static void
 swfdec_video_movie_update_extents (SwfdecMovie *movie,
     SwfdecRect *extents)
 {
-  SwfdecVideoMovie *video = SWFDEC_VIDEO_MOVIE (movie);
+  SwfdecVideo *org = SWFDEC_VIDEO (movie->graphic);
   SwfdecRect rect = { 0, 0, 
-    SWFDEC_TWIPS_SCALE_FACTOR * video->video->width, 
-    SWFDEC_TWIPS_SCALE_FACTOR * video->video->height };
+    SWFDEC_TWIPS_SCALE_FACTOR * org->width, 
+    SWFDEC_TWIPS_SCALE_FACTOR * org->height };
   
   swfdec_rect_union (extents, extents, &rect);
 }
@@ -88,8 +89,6 @@ swfdec_video_movie_dispose (GObject *object)
     movie->provider = NULL;
   }
 
-  g_object_unref (movie->video);
-
   G_OBJECT_CLASS (swfdec_video_movie_parent_class)->dispose (object);
 }
 
@@ -106,7 +105,7 @@ static gboolean
 swfdec_video_movie_get_variable (SwfdecAsObject *object, SwfdecAsObject *orig,
     const char *variable, SwfdecAsValue *val, guint *flags)
 {
-  guint version = object->context->version;
+  guint version = swfdec_gc_object_get_context (object)->version;
   SwfdecVideoMovie *video;
 
   video = SWFDEC_VIDEO_MOVIE (object);
@@ -147,7 +146,7 @@ static void
 swfdec_video_movie_set_variable (SwfdecAsObject *object, const char *variable,
     const SwfdecAsValue *val, guint flags)
 {
-  guint version = object->context->version;
+  guint version = swfdec_gc_object_get_context (object)->version;
 
   if (swfdec_strcmp (version, variable, SWFDEC_AS_STR_deblocking) == 0) {
     SWFDEC_STUB ("Video.deblocking (set)");
@@ -180,19 +179,38 @@ swfdec_video_movie_foreach_variable (SwfdecAsObject *object, SwfdecAsVariableFor
 static void
 swfdec_video_movie_invalidate (SwfdecMovie *movie, const cairo_matrix_t *matrix, gboolean last)
 {
-  SwfdecVideoMovie *video = SWFDEC_VIDEO_MOVIE (movie);
+  SwfdecVideo *org = SWFDEC_VIDEO (movie->graphic);
   SwfdecRect rect = { 0, 0, 
-    SWFDEC_TWIPS_SCALE_FACTOR * video->video->width, 
-    SWFDEC_TWIPS_SCALE_FACTOR * video->video->height };
+    SWFDEC_TWIPS_SCALE_FACTOR * org->width, 
+    SWFDEC_TWIPS_SCALE_FACTOR * org->height };
 
   swfdec_rect_transform (&rect, &rect, matrix);
-  swfdec_player_invalidate (SWFDEC_PLAYER (SWFDEC_AS_OBJECT (movie)->context), &rect);
+  swfdec_player_invalidate (SWFDEC_PLAYER (swfdec_gc_object_get_context (movie)), &rect);
 }
 
-static void
-swfdec_video_movie_init_movie (SwfdecMovie *movie)
+static GObject *
+swfdec_video_movie_constructor (GType type, guint n_construct_properties,
+    GObjectConstructParam *construct_properties)
 {
+  GObject *object;
+  SwfdecMovie *movie;
+  SwfdecVideo *video;
+
+  object = G_OBJECT_CLASS (swfdec_video_movie_parent_class)->constructor (type, 
+      n_construct_properties, construct_properties);
+
+  movie = SWFDEC_MOVIE (object);
   swfdec_as_object_set_constructor (SWFDEC_AS_OBJECT (movie), movie->resource->sandbox->Video);
+
+  video = SWFDEC_VIDEO (movie->graphic);
+
+  if (video->n_frames > 0) {
+    SwfdecVideoProvider *provider = swfdec_video_video_provider_new (video);
+    swfdec_video_movie_set_provider (SWFDEC_VIDEO_MOVIE (movie), provider);
+    g_object_unref (provider);
+  }
+
+  return object;
 }
 
 static void
@@ -202,6 +220,7 @@ swfdec_video_movie_class_init (SwfdecVideoMovieClass * g_class)
   SwfdecAsObjectClass *asobject_class = SWFDEC_AS_OBJECT_CLASS (g_class);
   SwfdecMovieClass *movie_class = SWFDEC_MOVIE_CLASS (g_class);
 
+  object_class->constructor = swfdec_video_movie_constructor;
   object_class->dispose = swfdec_video_movie_dispose;
 
   asobject_class->get = swfdec_video_movie_get_variable;
@@ -211,7 +230,6 @@ swfdec_video_movie_class_init (SwfdecVideoMovieClass * g_class)
   movie_class->update_extents = swfdec_video_movie_update_extents;
   movie_class->render = swfdec_video_movie_render;
   movie_class->invalidate = swfdec_video_movie_invalidate;
-  movie_class->init_movie = swfdec_video_movie_init_movie;
   movie_class->set_ratio = swfdec_video_movie_set_ratio;
 }
 
diff --git a/swfdec/swfdec_video_movie.h b/swfdec/swfdec_video_movie.h
index 09543e0..36ea820 100644
--- a/swfdec/swfdec_video_movie.h
+++ b/swfdec/swfdec_video_movie.h
@@ -41,7 +41,6 @@ typedef struct _SwfdecVideoMovieInput SwfdecVideoMovieInput;
 struct _SwfdecVideoMovie {
   SwfdecMovie		movie;
 
-  SwfdecVideo *		video;		/* video we play back */
   SwfdecVideoProvider *	provider;	/* where we take the video from */
   gboolean		clear;		/* do not display a video image */
 };
diff --git a/swfdec/swfdec_xml.c b/swfdec/swfdec_xml.c
index 57a1bff..efff92a 100644
--- a/swfdec/swfdec_xml.c
+++ b/swfdec/swfdec_xml.c
@@ -39,7 +39,7 @@
 G_DEFINE_TYPE (SwfdecXml, swfdec_xml, SWFDEC_TYPE_XML_NODE)
 
 static void
-swfdec_xml_do_mark (SwfdecAsObject *object)
+swfdec_xml_mark (SwfdecGcObject *object)
 {
   SwfdecXml *xml = SWFDEC_XML (object);
 
@@ -48,15 +48,15 @@ swfdec_xml_do_mark (SwfdecAsObject *object)
   if (xml->doc_type_decl != NULL)
     swfdec_as_string_mark (xml->doc_type_decl);
 
-  SWFDEC_AS_OBJECT_CLASS (swfdec_xml_parent_class)->mark (object);
+  SWFDEC_GC_OBJECT_CLASS (swfdec_xml_parent_class)->mark (object);
 }
 
 static void
 swfdec_xml_class_init (SwfdecXmlClass *klass)
 {
-  SwfdecAsObjectClass *asobject_class = SWFDEC_AS_OBJECT_CLASS (klass);
+  SwfdecGcObjectClass *gc_class = SWFDEC_GC_OBJECT_CLASS (klass);
 
-  asobject_class->mark = swfdec_xml_do_mark;
+  gc_class->mark = swfdec_xml_mark;
 }
 
 static void
@@ -389,11 +389,11 @@ swfdec_xml_parse_xmlDecl (SwfdecXml *xml, SwfdecXmlNode *node, const char *p)
   string = g_string_new ((xml->xml_decl != NULL ? xml->xml_decl : ""));
   string = g_string_append_len (string, p, end - p);
   xml->xml_decl = swfdec_as_context_give_string (
-      SWFDEC_AS_OBJECT (xml)->context, g_string_free (string, FALSE));
+      swfdec_gc_object_get_context (xml), g_string_free (string, FALSE));
 
   // in version 5 parsing xmlDecl or docType always adds undefined element to
   // the childNodes array
-  if (SWFDEC_AS_OBJECT (xml)->context->version < 6)
+  if (swfdec_gc_object_get_context (xml)->version < 6)
     SWFDEC_FIXME ("Need to add undefined element to childNodes array");
 
   g_return_val_if_fail (end > p, strchr (p, '\0'));
@@ -431,11 +431,11 @@ swfdec_xml_parse_docTypeDecl (SwfdecXml *xml, SwfdecXmlNode *node,
     xml->status = XML_PARSE_STATUS_DOCTYPEDECL_NOT_TERMINATED;
   } else {
     xml->doc_type_decl = swfdec_as_context_give_string (
-	SWFDEC_AS_OBJECT (xml)->context, g_strndup (p, end - p));
+	swfdec_gc_object_get_context (xml), g_strndup (p, end - p));
 
     // in version 5 parsing xmlDecl or docType always adds undefined element to
     // the childNodes array
-    if (SWFDEC_AS_OBJECT (xml)->context->version < 6)
+    if (swfdec_gc_object_get_context (xml)->version < 6)
       SWFDEC_FIXME ("Need to add undefined element to childNodes array");
   }
 
@@ -478,7 +478,7 @@ swfdec_xml_add_id_map (SwfdecXml *xml, SwfdecXmlNode *node, const char *id)
   g_return_if_fail (SWFDEC_IS_XML_NODE (xml));
   g_return_if_fail (id != NULL && id != SWFDEC_AS_STR_EMPTY);
 
-  if (SWFDEC_AS_OBJECT (xml)->context->version >= 8) {
+  if (swfdec_gc_object_get_context (xml)->version >= 8) {
     if (swfdec_as_object_get_variable (SWFDEC_AS_OBJECT (xml),
 	  SWFDEC_AS_STR_idMap, &val)) {
       if (SWFDEC_AS_VALUE_IS_OBJECT (&val)) {
@@ -487,7 +487,7 @@ swfdec_xml_add_id_map (SwfdecXml *xml, SwfdecXmlNode *node, const char *id)
 	return;
       }
     } else {
-      object = swfdec_as_object_new_empty (SWFDEC_AS_OBJECT (xml)->context);
+      object = swfdec_as_object_new_empty (swfdec_gc_object_get_context (xml));
       SWFDEC_AS_VALUE_SET_OBJECT (&val, object);
       swfdec_as_object_set_variable (SWFDEC_AS_OBJECT (xml),
 	  SWFDEC_AS_STR_idMap, &val);
@@ -518,8 +518,8 @@ swfdec_xml_parse_attribute (SwfdecXml *xml, SwfdecXmlNode *node, const char *p)
   }
 
   text = g_strndup (p, end - p);
-  name = swfdec_as_context_give_string (SWFDEC_AS_OBJECT (node)->context,
-      swfdec_xml_unescape (SWFDEC_AS_OBJECT (xml)->context, text));
+  name = swfdec_as_context_give_string (swfdec_gc_object_get_context (node),
+      swfdec_xml_unescape (swfdec_gc_object_get_context (xml), text));
   g_free (text);
 
   p = end + strspn (end, " \r\n\t");
@@ -548,9 +548,9 @@ swfdec_xml_parse_attribute (SwfdecXml *xml, SwfdecXmlNode *node, const char *p)
     char *unescaped;
     const char *value;
 
-    unescaped = swfdec_xml_unescape_len (SWFDEC_AS_OBJECT (xml)->context,
+    unescaped = swfdec_xml_unescape_len (swfdec_gc_object_get_context (xml),
 	p + 1, end - (p + 1), TRUE);
-    value = swfdec_as_context_give_string (SWFDEC_AS_OBJECT (node)->context,
+    value = swfdec_as_context_give_string (swfdec_gc_object_get_context (node),
 	unescaped);
     SWFDEC_AS_VALUE_SET_STRING (&val, value);
 
@@ -603,8 +603,8 @@ swfdec_xml_parse_tag (SwfdecXml *xml, SwfdecXmlNode **node, const char *p)
   // create the new element
   if (!close) {
     child = swfdec_xml_node_new_no_properties (
-	SWFDEC_AS_OBJECT (*node)->context, SWFDEC_XML_NODE_ELEMENT,
-	swfdec_as_context_give_string (SWFDEC_AS_OBJECT (*node)->context,
+	swfdec_gc_object_get_context (*node), SWFDEC_XML_NODE_ELEMENT,
+	swfdec_as_context_give_string (swfdec_gc_object_get_context (*node),
 	  name));
     if (child == NULL)
       return strchr (p, '\0');
@@ -694,8 +694,8 @@ swfdec_xml_parse_cdata (SwfdecXml *xml, SwfdecXmlNode *node, const char *p)
   text = g_strndup (p, end - p);
 
   child = swfdec_xml_node_new_no_properties (
-      SWFDEC_AS_OBJECT (node)->context, SWFDEC_XML_NODE_TEXT,
-      swfdec_as_context_give_string (SWFDEC_AS_OBJECT (xml)->context, text));
+      swfdec_gc_object_get_context (node), SWFDEC_XML_NODE_TEXT,
+      swfdec_as_context_give_string (swfdec_gc_object_get_context (xml), text));
   if (child == NULL)
     return strchr (p, '\0');
   swfdec_xml_node_appendChild (node, child);
@@ -726,11 +726,11 @@ swfdec_xml_parse_text (SwfdecXml *xml, SwfdecXmlNode *node,
   if (!ignore_white || strspn (p, " \t\r\n") < (gsize)(end - p))
   {
     text = g_strndup (p, end - p);
-    unescaped = swfdec_xml_unescape (SWFDEC_AS_OBJECT (xml)->context, text);
+    unescaped = swfdec_xml_unescape (swfdec_gc_object_get_context (xml), text);
     g_free (text);
     child = swfdec_xml_node_new_no_properties (
-	SWFDEC_AS_OBJECT (node)->context, SWFDEC_XML_NODE_TEXT,
-	swfdec_as_context_give_string (SWFDEC_AS_OBJECT (xml)->context,
+	swfdec_gc_object_get_context (node), SWFDEC_XML_NODE_TEXT,
+	swfdec_as_context_give_string (swfdec_gc_object_get_context (xml),
 	  unescaped));
     if (child == NULL)
       return strchr (p, '\0');
@@ -942,14 +942,10 @@ swfdec_xml_new_no_properties (SwfdecAsContext *context, const char *str,
 {
   SwfdecAsValue val;
   SwfdecXml *xml;
-  guint size;
 
   g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context), NULL);
 
-  size = sizeof (SwfdecXml);
-  swfdec_as_context_use_mem (context, size);
-  xml = g_object_new (SWFDEC_TYPE_XML, NULL);
-  swfdec_as_object_add (SWFDEC_AS_OBJECT (xml), context, size);
+  xml = g_object_new (SWFDEC_TYPE_XML, "context", context, NULL);
   swfdec_as_object_get_variable (context->global, SWFDEC_AS_STR_XML, &val);
   if (SWFDEC_AS_VALUE_IS_OBJECT (&val)) {
     swfdec_as_object_set_constructor (SWFDEC_AS_OBJECT (xml),
diff --git a/swfdec/swfdec_xml_node.c b/swfdec/swfdec_xml_node.c
index 32e7e63..6d43192 100644
--- a/swfdec/swfdec_xml_node.c
+++ b/swfdec/swfdec_xml_node.c
@@ -39,7 +39,7 @@
 G_DEFINE_TYPE (SwfdecXmlNode, swfdec_xml_node, SWFDEC_TYPE_AS_OBJECT)
 
 static void
-swfdec_xml_node_do_mark (SwfdecAsObject *object)
+swfdec_xml_node_mark (SwfdecGcObject *object)
 {
   SwfdecXmlNode *node = SWFDEC_XML_NODE (object);
 
@@ -48,23 +48,23 @@ swfdec_xml_node_do_mark (SwfdecAsObject *object)
   if (node->value != NULL)
     swfdec_as_string_mark (node->value);
   if (node->parent != NULL)
-    swfdec_as_object_mark (SWFDEC_AS_OBJECT (node->parent));
+    swfdec_gc_object_mark (node->parent);
   if (node->children != NULL)
-    swfdec_as_object_mark (SWFDEC_AS_OBJECT (node->children));
+    swfdec_gc_object_mark (node->children);
   if (node->attributes != NULL)
-    swfdec_as_object_mark (SWFDEC_AS_OBJECT (node->attributes));
+    swfdec_gc_object_mark (node->attributes);
   if (node->child_nodes != NULL)
-    swfdec_as_object_mark (SWFDEC_AS_OBJECT (node->child_nodes));
+    swfdec_gc_object_mark (node->child_nodes);
 
-  SWFDEC_AS_OBJECT_CLASS (swfdec_xml_node_parent_class)->mark (object);
+  SWFDEC_GC_OBJECT_CLASS (swfdec_xml_node_parent_class)->mark (object);
 }
 
 static void
 swfdec_xml_node_class_init (SwfdecXmlNodeClass *klass)
 {
-  SwfdecAsObjectClass *asobject_class = SWFDEC_AS_OBJECT_CLASS (klass);
+  SwfdecGcObjectClass *gc_class = SWFDEC_GC_OBJECT_CLASS (klass);
 
-  asobject_class->mark = swfdec_xml_node_do_mark;
+  gc_class->mark = swfdec_xml_node_mark;
 }
 
 static void
@@ -154,7 +154,7 @@ swfdec_xml_node_get_attribute (SwfdecXmlNode *node, const char *name)
   g_return_val_if_fail (name != NULL, NULL);
 
   if (swfdec_as_object_get_variable (node->attributes, name, &val)) {
-    return swfdec_as_value_to_string (SWFDEC_AS_OBJECT (node)->context, &val);
+    return swfdec_as_value_to_string (swfdec_gc_object_get_context (node), &val);
   } else {
     return NULL;
   }
@@ -169,17 +169,17 @@ swfdec_xml_node_getNamespaceForPrefix (SwfdecXmlNode *node, const char *prefix)
   g_return_val_if_fail (SWFDEC_IS_VALID_XML_NODE (node), NULL);
 
   if (prefix == NULL || strlen (prefix) == 0) {
-    var = swfdec_as_context_get_string (SWFDEC_AS_OBJECT (node)->context,
+    var = swfdec_as_context_get_string (swfdec_gc_object_get_context (node),
 	"xmlns");
   } else {
-    var = swfdec_as_context_give_string (SWFDEC_AS_OBJECT (node)->context,
+    var = swfdec_as_context_give_string (swfdec_gc_object_get_context (node),
 	g_strconcat ("xmlns:", prefix, NULL));
   }
 
   do {
     swfdec_as_object_get_variable (node->attributes, var, &val);
     if (!SWFDEC_AS_VALUE_IS_UNDEFINED (&val)) {
-      return swfdec_as_value_to_string (SWFDEC_AS_OBJECT (node)->context, &val);
+      return swfdec_as_value_to_string (swfdec_gc_object_get_context (node), &val);
     }
     node = node->parent;
   } while (node != NULL);
@@ -210,7 +210,7 @@ swfdec_xml_node_foreach_find_namespace (SwfdecAsObject *object,
     return TRUE;
 
   // ok, now check if the uri is the one we are searching for
-  uri = swfdec_as_value_to_string (object->context, value);
+  uri = swfdec_as_value_to_string (swfdec_gc_object_get_context (object), value);
   if (!g_ascii_strcasecmp (uri, fdata->namespace)) {
     fdata->variable = variable;
     return FALSE;
@@ -244,7 +244,7 @@ swfdec_xml_node_getPrefixForNamespace (SwfdecXmlNode *node,
     if (p == NULL || *(p + 1) == '\0')
       return SWFDEC_AS_STR_EMPTY;
 
-    return swfdec_as_context_get_string (SWFDEC_AS_OBJECT (node)->context,
+    return swfdec_as_context_get_string (swfdec_gc_object_get_context (node),
 	p + 1);
   } else {
     return NULL;
@@ -343,7 +343,7 @@ swfdec_xml_node_get_prefix (SwfdecXmlNode *node)
   if (p == NULL || *(p + 1) == '\0')
     return NULL;
 
-  return swfdec_as_context_give_string (SWFDEC_AS_OBJECT (node)->context,
+  return swfdec_as_context_give_string (swfdec_gc_object_get_context (node),
       g_strndup (node->name, p - node->name));
 }
 
@@ -742,7 +742,7 @@ swfdec_xml_node_insertAt (SwfdecXmlNode *node, SwfdecXmlNode *child, gint32 ind)
   g_assert (SWFDEC_IS_VALID_XML_NODE (child));
   g_assert (ind >= 0);
 
-  if (SWFDEC_AS_OBJECT (node)->context->version >= 8) {
+  if (swfdec_gc_object_get_context (node)->version >= 8) {
     SwfdecXmlNode *parent = node;
     while (parent != NULL) {
       if (parent == child)
@@ -871,7 +871,7 @@ swfdec_xml_node_foreach_string_append_attribute (SwfdecAsObject *object,
   string = g_string_append (string, variable);
   string = g_string_append (string, "=\"");
   escaped =
-    swfdec_xml_escape (swfdec_as_value_to_string (object->context, value));
+    swfdec_xml_escape (swfdec_as_value_to_string (swfdec_gc_object_get_context (object), value));
   string = g_string_append (string, escaped);
   g_free (escaped);
   string = g_string_append (string, "\"");
@@ -952,7 +952,7 @@ swfdec_xml_node_toString (SwfdecXmlNode *node)
       }
   }
 
-  return swfdec_as_context_give_string (object->context,
+  return swfdec_as_context_give_string (swfdec_gc_object_get_context (object),
       g_string_free (string, FALSE));
 }
 
@@ -980,8 +980,8 @@ swfdec_xml_node_init_values (SwfdecXmlNode *node, int type, const char* value)
 
   node->valid = TRUE;
   node->parent = NULL;
-  node->children = SWFDEC_AS_ARRAY (swfdec_as_array_new (object->context));
-  node->attributes = swfdec_as_object_new_empty (object->context);
+  node->children = SWFDEC_AS_ARRAY (swfdec_as_array_new (swfdec_gc_object_get_context (object)));
+  node->attributes = swfdec_as_object_new_empty (swfdec_gc_object_get_context (object));
   node->type = type;
   if (node->type == SWFDEC_XML_NODE_ELEMENT) {
     node->name = value;
@@ -989,7 +989,7 @@ swfdec_xml_node_init_values (SwfdecXmlNode *node, int type, const char* value)
     node->value = value;
   }
 
-  node->child_nodes = SWFDEC_AS_ARRAY (swfdec_as_array_new (object->context));
+  node->child_nodes = SWFDEC_AS_ARRAY (swfdec_as_array_new (swfdec_gc_object_get_context (object)));
 }
 
 static void
@@ -1048,15 +1048,11 @@ swfdec_xml_node_new_no_properties (SwfdecAsContext *context,
 {
   SwfdecAsValue val;
   SwfdecXmlNode *node;
-  guint size;
 
   g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context), NULL);
   g_return_val_if_fail (value != NULL, NULL);
 
-  size = sizeof (SwfdecXmlNode);
-  swfdec_as_context_use_mem (context, size);
-  node = g_object_new (SWFDEC_TYPE_XML_NODE, NULL);
-  swfdec_as_object_add (SWFDEC_AS_OBJECT (node), context, size);
+  node = g_object_new (SWFDEC_TYPE_XML_NODE, "context", context, NULL);
   swfdec_as_object_get_variable (context->global, SWFDEC_AS_STR_XMLNode, &val);
   if (SWFDEC_AS_VALUE_IS_OBJECT (&val)) {
     swfdec_as_object_set_constructor (SWFDEC_AS_OBJECT (node),
diff --git a/swfdec/swfdec_xml_socket.c b/swfdec/swfdec_xml_socket.c
index d7ea1e8..64f7a2e 100644
--- a/swfdec/swfdec_xml_socket.c
+++ b/swfdec/swfdec_xml_socket.c
@@ -44,7 +44,7 @@ swfdec_xml_socket_ensure_closed (SwfdecXmlSocket *xml)
   g_object_unref (xml->socket);
   xml->socket = NULL;
 
-  swfdec_player_unroot (SWFDEC_PLAYER (SWFDEC_AS_OBJECT (xml)->context), xml);
+  swfdec_player_unroot (SWFDEC_PLAYER (swfdec_gc_object_get_context (xml)), xml);
   if (xml->target_owner) {
     g_object_steal_qdata (G_OBJECT (xml->target), xml_socket_quark);
     xml->target_owner = FALSE;
@@ -57,7 +57,7 @@ swfdec_xml_socket_ensure_closed (SwfdecXmlSocket *xml)
 static SwfdecPlayer *
 swfdec_xml_socket_stream_target_get_player (SwfdecStreamTarget *target)
 {
-  return SWFDEC_PLAYER (SWFDEC_AS_OBJECT (target)->context);
+  return SWFDEC_PLAYER (swfdec_gc_object_get_context (target));
 }
 
 static void
@@ -124,7 +124,7 @@ swfdec_xml_socket_stream_target_parse (SwfdecStreamTarget *target,
 	SwfdecAsValue val;
 
 	SWFDEC_AS_VALUE_SET_STRING (&val, swfdec_as_context_get_string (
-	      SWFDEC_AS_OBJECT (xml)->context, (char *) buffer->data));
+	      swfdec_gc_object_get_context (xml), (char *) buffer->data));
 	swfdec_sandbox_use (xml->sandbox);
 	swfdec_as_object_call (xml->target, SWFDEC_AS_STR_onData, 1, &val, NULL);
 	swfdec_sandbox_unuse (xml->sandbox);
@@ -167,12 +167,14 @@ G_DEFINE_TYPE_WITH_CODE (SwfdecXmlSocket, swfdec_xml_socket, SWFDEC_TYPE_AS_OBJE
     G_IMPLEMENT_INTERFACE (SWFDEC_TYPE_STREAM_TARGET, swfdec_xml_socket_stream_target_init))
 
 static void
-swfdec_xml_socket_mark (SwfdecAsObject *object)
+swfdec_xml_socket_mark (SwfdecGcObject *object)
 {
-  swfdec_as_object_mark (SWFDEC_XML_SOCKET (object)->target);
-  swfdec_as_object_mark (SWFDEC_AS_OBJECT (SWFDEC_XML_SOCKET (object)->sandbox));
+  SwfdecXmlSocket *sock = SWFDEC_XML_SOCKET (object);
 
-  SWFDEC_AS_OBJECT_CLASS (swfdec_xml_socket_parent_class)->mark (object);
+  swfdec_gc_object_mark (sock->target);
+  swfdec_gc_object_mark (sock->sandbox);
+
+  SWFDEC_GC_OBJECT_CLASS (swfdec_xml_socket_parent_class)->mark (object);
 }
 
 static void
@@ -193,11 +195,11 @@ static void
 swfdec_xml_socket_class_init (SwfdecXmlSocketClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
-  SwfdecAsObjectClass *as_object_class = SWFDEC_AS_OBJECT_CLASS (klass);
+  SwfdecGcObjectClass *gc_class = SWFDEC_GC_OBJECT_CLASS (klass);
 
   object_class->dispose = swfdec_xml_socket_dispose;
 
-  as_object_class->mark = swfdec_xml_socket_mark;
+  gc_class->mark = swfdec_xml_socket_mark;
 }
 
 static void
@@ -217,20 +219,17 @@ swfdec_xml_socket_target_gone (gpointer xmlp)
 static SwfdecXmlSocket *
 swfdec_xml_socket_create (SwfdecAsObject *target, SwfdecSandbox *sandbox, const char *hostname, guint port)
 {
-  SwfdecAsContext *cx = target->context;
+  SwfdecAsContext *cx = swfdec_gc_object_get_context (target);
   SwfdecXmlSocket *xml;
   SwfdecSocket *sock;
 
-  swfdec_as_context_use_mem (cx, sizeof (SwfdecXmlSocket));
-
   SWFDEC_FIXME ("implement security checks please");
   sock = swfdec_player_create_socket (SWFDEC_PLAYER (cx), hostname, port);
   if (sock == NULL)
     return NULL;
 
-  xml = g_object_new (SWFDEC_TYPE_XML_SOCKET, NULL);
-  swfdec_as_object_add (SWFDEC_AS_OBJECT (xml), cx, sizeof (SwfdecXmlSocket));
-  swfdec_player_root (SWFDEC_PLAYER (cx), xml, (GFunc) swfdec_as_object_mark);
+  xml = g_object_new (SWFDEC_TYPE_XML_SOCKET, "context", cx, NULL);
+  swfdec_player_root (SWFDEC_PLAYER (cx), xml, (GFunc) swfdec_gc_object_mark);
 
   if (xml_socket_quark == 0)
     xml_socket_quark = g_quark_from_static_string ("swfdec-xml-socket");
diff --git a/test/swfdec_test_buffer.c b/test/swfdec_test_buffer.c
index f81ea6a..3d5c74d 100644
--- a/test/swfdec_test_buffer.c
+++ b/test/swfdec_test_buffer.c
@@ -34,10 +34,7 @@ swfdec_test_buffer_new (SwfdecAsContext *context, SwfdecBuffer *buffer)
   SwfdecAsValue val;
   SwfdecAsObject *ret;
 
-  swfdec_as_context_use_mem (context, sizeof (SwfdecTestBuffer));
-
-  ret = g_object_new (SWFDEC_TYPE_TEST_BUFFER, NULL);
-  swfdec_as_object_add (ret, context, sizeof (SwfdecTestBuffer));
+  ret = g_object_new (SWFDEC_TYPE_TEST_BUFFER, "context", context, NULL);
   swfdec_as_object_get_variable (context->global, 
       swfdec_as_context_get_string (context, "Buffer"), &val);
   if (SWFDEC_AS_VALUE_IS_OBJECT (&val))
diff --git a/test/swfdec_test_image.c b/test/swfdec_test_image.c
index b1bc223..388df6b 100644
--- a/test/swfdec_test_image.c
+++ b/test/swfdec_test_image.c
@@ -34,10 +34,7 @@ swfdec_test_image_new (SwfdecAsContext *context, guint width, guint height)
   SwfdecAsValue val;
   SwfdecAsObject *ret;
 
-  swfdec_as_context_use_mem (context, sizeof (SwfdecTestImage));
-
-  ret = g_object_new (SWFDEC_TYPE_TEST_IMAGE, NULL);
-  swfdec_as_object_add (ret, context, sizeof (SwfdecTestImage));
+  ret = g_object_new (SWFDEC_TYPE_TEST_IMAGE, "context", context, NULL);
   swfdec_as_object_get_variable (context->global, 
       swfdec_as_context_get_string (context, "Image"), &val);
   if (SWFDEC_AS_VALUE_IS_OBJECT (&val))
diff --git a/test/swfdec_test_socket.c b/test/swfdec_test_socket.c
index a017f99..c6655c3 100644
--- a/test/swfdec_test_socket.c
+++ b/test/swfdec_test_socket.c
@@ -205,11 +205,9 @@ swfdec_test_socket_new (SwfdecTestTest *test, SwfdecTestPluginSocket *plugin)
   g_return_val_if_fail (SWFDEC_IS_TEST_TEST (test), NULL);
   g_return_val_if_fail (plugin != NULL, NULL);
 
-  cx = SWFDEC_AS_OBJECT (test)->context;
+  cx = swfdec_gc_object_get_context (test);
 
-  swfdec_as_context_use_mem (cx, sizeof (SwfdecTestSocket));
-  new = g_object_new (SWFDEC_TYPE_TEST_SOCKET, NULL);
-  swfdec_as_object_add (new, cx, sizeof (SwfdecTestSocket));
+  new = g_object_new (SWFDEC_TYPE_TEST_SOCKET, "context", cx, NULL);
   swfdec_as_object_get_variable (cx->global, 
       swfdec_as_context_get_string (cx, "Socket"), &val);
   if (SWFDEC_AS_VALUE_IS_OBJECT (&val))
diff --git a/test/swfdec_test_test.c b/test/swfdec_test_test.c
index 2da666f..ae8f502 100644
--- a/test/swfdec_test_test.c
+++ b/test/swfdec_test_test.c
@@ -54,7 +54,7 @@ swfdec_test_test_error (SwfdecTestPlugin *plugin, const char *description)
   if (test->plugin_error)
     return;
   test->plugin_error = TRUE;
-  swfdec_test_throw (SWFDEC_AS_OBJECT (test)->context, description);
+  swfdec_test_throw (swfdec_gc_object_get_context (test), description);
 }
 
 static void
@@ -119,7 +119,7 @@ swfdec_test_test_load_plugin (SwfdecTestTest *test, const char *filename)
     g_free (dir);
     test->module = g_module_open (name, G_MODULE_BIND_LOCAL);
     if (test->module == NULL) {
-      swfdec_test_throw (SWFDEC_AS_OBJECT (test)->context, "could not find player \"%s\"",
+      swfdec_test_throw (swfdec_gc_object_get_context (test), "could not find player \"%s\"",
 	  swfdec_test_plugin_name);
       return;
     }
diff --git a/vivified/core/vivi_breakpoint.c b/vivified/core/vivi_breakpoint.c
index 423bf7f..df47627 100644
--- a/vivified/core/vivi_breakpoint.c
+++ b/vivified/core/vivi_breakpoint.c
@@ -34,8 +34,8 @@ vivi_breakpoint_step (ViviDebugger *debugger, ViviBreakpoint *breakpoint)
   SwfdecAsObject *obj = SWFDEC_AS_OBJECT (breakpoint);
   SwfdecAsValue retval;
 
-  swfdec_as_object_call (obj, swfdec_as_context_get_string (obj->context, "onCommand"), 0, NULL, &retval);
-  return swfdec_as_value_to_boolean (obj->context, &retval);
+  swfdec_as_object_call (obj, swfdec_as_context_get_string (swfdec_gc_object_get_context (obj), "onCommand"), 0, NULL, &retval);
+  return swfdec_as_value_to_boolean (swfdec_gc_object_get_context (obj), &retval);
 }
 
 static gboolean
@@ -45,9 +45,9 @@ vivi_breakpoint_enter_frame (ViviDebugger *debugger, SwfdecAsFrame *frame, ViviB
   SwfdecAsValue val;
   SwfdecAsValue retval;
 
-  SWFDEC_AS_VALUE_SET_OBJECT (&val, vivi_wrap_object (VIVI_APPLICATION (obj->context), SWFDEC_AS_OBJECT (frame)));
-  swfdec_as_object_call (obj, swfdec_as_context_get_string (obj->context, "onEnterFrame"), 1, &val, &retval);
-  return swfdec_as_value_to_boolean (obj->context, &retval);
+  SWFDEC_AS_VALUE_SET_OBJECT (&val, vivi_wrap_object (VIVI_APPLICATION (swfdec_gc_object_get_context (obj)), SWFDEC_AS_OBJECT (frame)));
+  swfdec_as_object_call (obj, swfdec_as_context_get_string (swfdec_gc_object_get_context (obj), "onEnterFrame"), 1, &val, &retval);
+  return swfdec_as_value_to_boolean (swfdec_gc_object_get_context (obj), &retval);
 }
 
 static gboolean
@@ -57,10 +57,10 @@ vivi_breakpoint_leave_frame (ViviDebugger *debugger, SwfdecAsFrame *frame, const
   SwfdecAsValue vals[2];
   SwfdecAsValue retval;
 
-  SWFDEC_AS_VALUE_SET_OBJECT (&vals[0], vivi_wrap_object (VIVI_APPLICATION (obj->context), SWFDEC_AS_OBJECT (frame)));
-  vivi_wrap_value (VIVI_APPLICATION (obj->context), &vals[1], ret);
-  swfdec_as_object_call (obj, swfdec_as_context_get_string (obj->context, "onLeaveFrame"), 2, vals, &retval);
-  return swfdec_as_value_to_boolean (obj->context, &retval);
+  SWFDEC_AS_VALUE_SET_OBJECT (&vals[0], vivi_wrap_object (VIVI_APPLICATION (swfdec_gc_object_get_context (obj)), SWFDEC_AS_OBJECT (frame)));
+  vivi_wrap_value (VIVI_APPLICATION (swfdec_gc_object_get_context (obj)), &vals[1], ret);
+  swfdec_as_object_call (obj, swfdec_as_context_get_string (swfdec_gc_object_get_context (obj), "onLeaveFrame"), 2, vals, &retval);
+  return swfdec_as_value_to_boolean (swfdec_gc_object_get_context (obj), &retval);
 }
 
 static gboolean
@@ -71,11 +71,11 @@ vivi_breakpoint_set_variable (ViviDebugger *debugger, SwfdecAsObject *object,
   SwfdecAsValue vals[3];
   SwfdecAsValue retval;
 
-  SWFDEC_AS_VALUE_SET_OBJECT (&vals[0], vivi_wrap_object (VIVI_APPLICATION (obj->context), object));
-  SWFDEC_AS_VALUE_SET_STRING (&vals[1], swfdec_as_context_get_string (obj->context, variable));
-  vivi_wrap_value (VIVI_APPLICATION (obj->context), &vals[2], value);
-  swfdec_as_object_call (obj, swfdec_as_context_get_string (obj->context, "onSetVariable"), 3, vals, &retval);
-  return swfdec_as_value_to_boolean (obj->context, &retval);
+  SWFDEC_AS_VALUE_SET_OBJECT (&vals[0], vivi_wrap_object (VIVI_APPLICATION (swfdec_gc_object_get_context (obj)), object));
+  SWFDEC_AS_VALUE_SET_STRING (&vals[1], swfdec_as_context_get_string (swfdec_gc_object_get_context (obj), variable));
+  vivi_wrap_value (VIVI_APPLICATION (swfdec_gc_object_get_context (obj)), &vals[2], value);
+  swfdec_as_object_call (obj, swfdec_as_context_get_string (swfdec_gc_object_get_context (obj), "onSetVariable"), 3, vals, &retval);
+  return swfdec_as_value_to_boolean (swfdec_gc_object_get_context (obj), &retval);
 }
 
 static const struct {
@@ -105,7 +105,7 @@ vivi_breakpoint_find_event (const char *name)
 static void
 vivi_breakpoint_add (ViviBreakpoint *breakpoint, guint i)
 {
-  ViviDebugger *debugger = VIVI_APPLICATION (SWFDEC_AS_OBJECT (breakpoint)->context)->debugger;
+  ViviDebugger *debugger = VIVI_APPLICATION (swfdec_gc_object_get_context (breakpoint))->debugger;
 
   g_assert (i != 0);
   if (breakpoint->active) {
@@ -119,7 +119,7 @@ vivi_breakpoint_add (ViviBreakpoint *breakpoint, guint i)
 static void
 vivi_breakpoint_remove (ViviBreakpoint *breakpoint, guint i)
 {
-  ViviDebugger *debugger = VIVI_APPLICATION (SWFDEC_AS_OBJECT (breakpoint)->context)->debugger;
+  ViviDebugger *debugger = VIVI_APPLICATION (swfdec_gc_object_get_context (breakpoint))->debugger;
 
   g_assert (i != 0);
   if (breakpoint->active)
diff --git a/vivified/core/vivi_wrap.c b/vivified/core/vivi_wrap.c
index b018dcd..8f99ddb 100644
--- a/vivified/core/vivi_wrap.c
+++ b/vivified/core/vivi_wrap.c
@@ -32,7 +32,7 @@ vivi_wrap_dispose (GObject *object)
   ViviWrap *wrap = VIVI_WRAP (object);
 
   if (wrap->wrap) {
-    g_hash_table_remove (VIVI_APPLICATION (SWFDEC_AS_OBJECT (wrap)->context)->wraps, wrap->wrap);
+    g_hash_table_remove (VIVI_APPLICATION (swfdec_gc_object_get_context (wrap))->wraps, wrap->wrap);
     wrap->wrap = NULL;
   }
 
@@ -65,9 +65,7 @@ vivi_wrap_object (ViviApplication *app, SwfdecAsObject *object)
     return wrap;
 
   cx = SWFDEC_AS_CONTEXT (app);
-  swfdec_as_context_use_mem (cx, sizeof (ViviWrap));
-  wrap = g_object_new (VIVI_TYPE_WRAP, NULL);
-  swfdec_as_object_add (wrap, cx, sizeof (ViviWrap));
+  wrap = g_object_new (VIVI_TYPE_WRAP, "context", cx, NULL);
   /* frames are special */
   if (SWFDEC_IS_AS_FRAME (object))
     name = "Frame";
commit 74bc11c52826659b2aeac7cab1883573fb5ff93a
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Jul 24 10:41:31 2008 +0200

    remove outdated comment

diff --git a/swfdec/swfdec_movie.c b/swfdec/swfdec_movie.c
index 8392cbd..8a252e7 100644
--- a/swfdec/swfdec_movie.c
+++ b/swfdec/swfdec_movie.c
@@ -1398,7 +1398,6 @@ swfdec_movie_new (SwfdecPlayer *player, int depth, SwfdecMovie *parent, SwfdecRe
     movie->depth = depth;
   }
   /* register it to the VM */
-  /* FIXME: It'd be nice if we'd not overuse memory here when calling this function from a script */
   swfdec_as_context_use_mem (SWFDEC_AS_CONTEXT (player), size);
   g_object_ref (movie);
   /* set essential properties */


More information about the Swfdec-commits mailing list