[Swfdec-commits] Branch 'abc' - 3 commits - configure.ac swfdec/Makefile.am swfdec/swfdec_abc_class.c swfdec/swfdec_abc_file.c swfdec/swfdec_abc_file.h swfdec/swfdec_abc_function.c swfdec/swfdec_abc_function.h swfdec/swfdec_abc_global.c swfdec/swfdec_abc_internal.h swfdec/swfdec_abc_native.h swfdec/swfdec_abc_traits.h swfdec/swfdec_player_abc.c tools/abcextract.c

Benjamin Otte company at kemper.freedesktop.org
Sat Aug 23 04:59:26 PDT 2008


 configure.ac                 |   10 -
 swfdec/Makefile.am           |    7 
 swfdec/swfdec_abc_class.c    |   11 -
 swfdec/swfdec_abc_file.c     |  121 +--------------
 swfdec/swfdec_abc_file.h     |    2 
 swfdec/swfdec_abc_function.c |  333 ++++++++++++++++++++++++++++++++++++++++++-
 swfdec/swfdec_abc_function.h |    7 
 swfdec/swfdec_abc_global.c   |    8 +
 swfdec/swfdec_abc_internal.h |    7 
 swfdec/swfdec_abc_native.h   |    4 
 swfdec/swfdec_abc_traits.h   |   10 +
 swfdec/swfdec_player_abc.c   |   15 -
 tools/abcextract.c           |    2 
 13 files changed, 391 insertions(+), 146 deletions(-)

New commits:
commit 825c53d6795706716389de43317afb53f780361a
Merge: 1d39724... 70d2769...
Author: Benjamin Otte <otte at gnome.org>
Date:   Sat Aug 23 13:57:25 2008 +0200

    Merge branch 'abc' of ssh://company@git.freedesktop.org/git/swfdec/swfdec into abc
    
    Conflicts:
    
    	tools/abcextract.c

commit 1d397245d1475579cef5a0b670f2287c13f4081c
Author: Benjamin Otte <otte at gnome.org>
Date:   Sat Aug 23 13:51:56 2008 +0200

    make native abc functions really be native
    
    They go through libffi now

diff --git a/configure.ac b/configure.ac
index 644bcfb..67cc453 100644
--- a/configure.ac
+++ b/configure.ac
@@ -187,16 +187,12 @@ AC_SUBST(AUDIO_TYPE)
 
 LIBOIL_VER=0.3.1
 PKG_CHECK_MODULES(LIBOIL, liboil-0.3 >= $LIBOIL_VER, HAVE_LIBOIL=yes, HAVE_LIBOIL=no)
-AC_SUBST(LIBOIL_LIBS)
-AC_SUBST(LIBOIL_CFLAGS)
 if test "$HAVE_LIBOIL" = "no"; then
   AC_MSG_ERROR([liboil-0.3 >= $LIBOIL_VER is required to build swfdec])
 fi
 
 CAIRO_VER=1.6.0
 PKG_CHECK_MODULES(CAIRO, cairo >= $CAIRO_VER cairo-png >= $CAIRO_VER, HAVE_CAIRO=yes, HAVE_CAIRO=no)
-AC_SUBST(CAIRO_LIBS)
-AC_SUBST(CAIRO_CFLAGS)
 if test "$HAVE_CAIRO" = "no"; then
   AC_MSG_ERROR([cairo and cairo-png = $CAIRO_VER is required to build swfdec])
 fi
@@ -243,12 +239,14 @@ else
 fi
 AM_CONDITIONAL(HAVE_VIVI, [test "x$HAVE_VIVI" = xyes])
 
+FFI_VER=3.0.5
+PKG_CHECK_MODULES(FFI, libffi >= $FFI_VER)
 
 AC_SUBST(GLOBAL_CFLAGS)
 AC_SUBST(GLOBAL_CFLAGS)
 
-SWFDEC_CFLAGS="-I\$(top_srcdir) $GLIB_CFLAGS $CAIRO_CFLAGS"
-SWFDEC_LIBS="\$(top_builddir)/swfdec/libswfdec-$SWFDEC_MAJORMINOR.la $GLIB_LIBS $CAIRO_LIBS -lz -lm"
+SWFDEC_CFLAGS="-I\$(top_srcdir) $GLIB_CFLAGS $CAIRO_CFLAGS $FFI_CFLAGS"
+SWFDEC_LIBS="\$(top_builddir)/swfdec/libswfdec-$SWFDEC_MAJORMINOR.la $GLIB_LIBS $CAIRO_LIBS $FFI_LIBS -lz -lm"
 AC_SUBST(SWFDEC_LIBS)
 AC_SUBST(SWFDEC_CFLAGS)
 
diff --git a/swfdec/Makefile.am b/swfdec/Makefile.am
index 0ae9df4..8a737f1 100644
--- a/swfdec/Makefile.am
+++ b/swfdec/Makefile.am
@@ -395,17 +395,16 @@ swfdec_abc_native.c: $(libswfdec_source_files)
 	  && echo "#include \"swfdec_abc_internal.h\"" \
 	  && echo "#undef SWFDEC_ABC_NATIVE" \
 	  && echo "#undef SWFDEC_ABC_FLASH" \
-	  && echo "#define SWFDEC_ABC_NATIVE(id,func) void func (SwfdecAsContext *cx, \\" \
-	  && echo "    guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret);" \
+	  && echo "#define SWFDEC_ABC_NATIVE(id,func) void func (void);" \
 	  && echo "#define SWFDEC_ABC_FLASH SWFDEC_ABC_NATIVE" \
 	  && grep -he "^SWFDEC_ABC_NATIVE" $(libswfdec_source_files) \
 	  && grep -he "^SWFDEC_ABC_FLASH" $(libswfdec_source_files) \
 	  && echo "#undef SWFDEC_ABC_NATIVE" \
 	  && echo "#define SWFDEC_ABC_NATIVE(id,func) [id] = func," \
-	  && echo "const SwfdecAbcNative swfdec_abc_natives[585] = {" \
+	  && echo "const GCallback swfdec_abc_natives[585] = {" \
 	  && grep -he "^SWFDEC_ABC_NATIVE" $(libswfdec_source_files) \
 	  && echo "};" \
-	  && echo "const SwfdecAbcNative swfdec_abc_natives_flash[1944] = {" \
+	  && echo "const GCallback swfdec_abc_natives_flash[1944] = {" \
 	  && grep -he "^SWFDEC_ABC_FLASH" $(libswfdec_source_files) \
 	  && echo "};" \
 	  && echo "#undef SWFDEC_ABC_NATIVE" \
diff --git a/swfdec/swfdec_abc_class.c b/swfdec/swfdec_abc_class.c
index a7e5a65..31d99a6 100644
--- a/swfdec/swfdec_abc_class.c
+++ b/swfdec/swfdec_abc_class.c
@@ -136,17 +136,14 @@ swfdec_abc_class_init (SwfdecAbcClass *class)
 
 /*** ABC CODE ***/
 
+void swfdec_abc_class_get_prototype (SwfdecAbcClass *classp, SwfdecAsValue *ret);
 SWFDEC_ABC_NATIVE (29, swfdec_abc_class_get_prototype)
 void
-swfdec_abc_class_get_prototype (SwfdecAsContext *cx,
-    guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
+swfdec_abc_class_get_prototype (SwfdecAbcClass *classp, SwfdecAsValue *ret)
 {
-  SwfdecAbcClass *classp = SWFDEC_ABC_CLASS (SWFDEC_AS_VALUE_GET_OBJECT (&argv[0]));
-
-  if (classp->prototype) {
+  if (classp->prototype)
     SWFDEC_AS_VALUE_SET_OBJECT (ret, SWFDEC_AS_OBJECT (classp->prototype));
-  } else {
+  else
     SWFDEC_AS_VALUE_SET_NULL (ret);
-  }
 }
 
diff --git a/swfdec/swfdec_abc_file.c b/swfdec/swfdec_abc_file.c
index bddbaeb..b6d08d2 100644
--- a/swfdec/swfdec_abc_file.c
+++ b/swfdec/swfdec_abc_file.c
@@ -647,107 +647,9 @@ swfdec_abc_file_parse_traits (SwfdecAbcFile *file, SwfdecAbcTraits *traits, Swfd
   return TRUE;
 }
 
-static char *
-swfdec_abc_describe_function (SwfdecAbcFunction *function)
-{
-  SwfdecAbcTraits *traits;
-  GString *name;
-  guint i, id;
-
-  g_assert (function->resolved);
-
-  /* find id of our function in pool */
-  for (id = 0; id < function->pool->n_functions; id++) {
-    if (function->pool->functions[id] == function)
-      break;
-  }
-
-  traits = function->bound_traits;
-  name = g_string_new ("");
-  if (traits == NULL) {
-    /* we're likely a lambda function */
-    g_string_append_printf (name, "function %u: %s [lambda]", id, 
-	function->return_traits ? function->return_traits->name : "SwfdecAsValue *");
-  } else if (traits->construct == function) {
-    /* we're the constructor */
-    g_string_append_printf (name, "function %u: %s %s", id, 
-	function->return_traits ? function->return_traits->name : "SwfdecAsValue *",
-	traits->name);
-  } else {
-    /* we're method, getter or setter, find out what */
-    do {
-      for (i = 0; i < traits->n_traits; i++) {
-	SwfdecAbcTrait *trait = &traits->traits[i];
-	guint slot = SWFDEC_ABC_BINDING_GET_ID (trait->type);
-	switch (SWFDEC_ABC_BINDING_GET_TYPE (trait->type)) {
-	  case SWFDEC_ABC_TRAIT_METHOD:
-	    if (traits->methods[slot] == function) {
-	      g_string_append_printf (name, "method %u %s %s.%s", id,
-		  function->return_traits ? function->return_traits->name : "SwfdecAsValue *",
-		  traits->name, trait->name);
-	      goto out;
-	    }
-	    break;
-	  case SWFDEC_ABC_TRAIT_GET:
-	  case SWFDEC_ABC_TRAIT_SET:
-	  case SWFDEC_ABC_TRAIT_GETSET:
-	    if (traits->methods[slot] == function) {
-	      g_string_append_printf (name, "getter %u %s %s.%s", id,
-		  function->return_traits ? function->return_traits->name : "SwfdecAsValue *",
-		  traits->name, trait->name);
-	      goto out;
-	    } else if (traits->methods[slot + 1] == function) {
-	      g_string_append_printf (name, "setter %u %s %s.%s", id,
-		  function->return_traits ? function->return_traits->name : "SwfdecAsValue *",
-		  traits->name, trait->name);
-	      goto out;
-	    }
-	    break;
-	  case SWFDEC_ABC_TRAIT_NONE:
-	  case SWFDEC_ABC_TRAIT_SLOT:
-	  case SWFDEC_ABC_TRAIT_CONST:
-	  case SWFDEC_ABC_TRAIT_ITRAMP:
-	  default:
-	  break;
-	}
-      }
-      traits = traits->base;
-    } while (traits);
-    /* huh? */
-    g_string_append_printf (name, "function %u %s %s", id,
-	function->return_traits->name, function->bound_traits->name);
-  }
-out:
-  /* append arguments */
-  g_string_append (name, " (");
-  for (i = 0; i < function->n_args; i++) {
-    if (i > 0)
-      g_string_append (name, ", ");
-    if (function->args[i].traits)
-      g_string_append (name, function->args[i].traits->name);
-    else 
-      g_string_append (name, "SwfdecAsValue *");
-  }
-  g_string_append (name, ")");
-
-  return g_string_free (name, FALSE);
-}
-
-static void
-swfdec_abc_default_stub (SwfdecAsContext *cx, SwfdecAsObject *obj, guint argc,
-    SwfdecAsValue *argv, SwfdecAsValue *ret)
-{
-  SwfdecAsFrame *frame = swfdec_as_context_get_frame (cx);
-  SwfdecAbcFunction *function = SWFDEC_ABC_FUNCTION (swfdec_as_frame_get_function (frame));
-  char *name = swfdec_abc_describe_function (function);
-
-  SWFDEC_STUB (name);
-  g_free (name);
-}
-
 static gboolean
 swfdec_abc_file_parse_methods (SwfdecAbcFile *file, SwfdecBits *bits,
-    const SwfdecAsNative *natives, guint n_natives)
+    const GCallback *natives, guint n_natives)
 {
   SwfdecAsContext *context = swfdec_gc_object_get_context (file);
   guint i;
@@ -816,7 +718,6 @@ swfdec_abc_file_parse_methods (SwfdecAbcFile *file, SwfdecBits *bits,
 	}
 	if (fun->native == NULL) {
 	  SWFDEC_INFO ("no native for index %u, using default stub", i);
-	  fun->native = swfdec_abc_default_stub;
 	}
       }
       if (optional) {
@@ -1120,7 +1021,7 @@ swfdec_abc_file_parse_bodies (SwfdecAbcFile *file, SwfdecBits *bits)
 
 static gboolean
 swfdec_abc_file_parse (SwfdecAbcFile *file, SwfdecBits *bits,
-    const SwfdecAsNative *natives, guint n_natives)
+    const GCallback *natives, guint n_natives)
 {
   return swfdec_abc_file_parse_constants (file, bits) &&
       swfdec_abc_file_parse_methods (file, bits, natives, n_natives) &&
@@ -1139,7 +1040,7 @@ swfdec_abc_file_new (SwfdecAsContext *context, SwfdecBits *bits)
 
 SwfdecAbcFile *
 swfdec_abc_file_new_trusted (SwfdecAsContext *context, SwfdecBits *bits,
-    const SwfdecAsNative *natives, guint n_natives)
+    const GCallback *natives, guint n_natives)
 {
   SwfdecAbcFile *file;
   guint major, minor;
@@ -1167,18 +1068,26 @@ swfdec_abc_file_new_trusted (SwfdecAsContext *context, SwfdecBits *bits,
     return NULL;
   }
   
-//#define SWFDEC_PRINT_STUBS
+#define SWFDEC_PRINT_STUBS
 #ifdef SWFDEC_PRINT_STUBS
   {
     guint i;
 
     if (SWFDEC_ABC_GLOBAL (context->global)->file == NULL)
       SWFDEC_ABC_GLOBAL (context->global)->file = file;
+    
+    /* update machine types */
+    SWFDEC_ABC_BOOLEAN_TRAITS (context)->machine_type = SWFDEC_ABC_INT;
+    SWFDEC_ABC_INT_TRAITS (context)->machine_type = SWFDEC_ABC_INT;
+    SWFDEC_ABC_UINT_TRAITS (context)->machine_type = SWFDEC_ABC_UINT;
+    SWFDEC_ABC_NUMBER_TRAITS (context)->machine_type = SWFDEC_ABC_DOUBLE;
+    SWFDEC_ABC_STRING_TRAITS (context)->machine_type = SWFDEC_ABC_STRING;
+
     g_print ("missing implementations:\n");
     for (i = 0; i < file->n_functions; i++) {
       SwfdecAbcFunction *fun = file->functions[i];
       char *name;
-      if (fun->native == NULL)
+      if (fun->code != NULL)
 	continue;
       /* This is why we can't print this stuff by default: We need to resolve
        * the function, which could throw */
@@ -1186,8 +1095,8 @@ swfdec_abc_file_new_trusted (SwfdecAsContext *context, SwfdecBits *bits,
 	  (fun->bound_traits != NULL && !swfdec_abc_traits_resolve (fun->bound_traits))) {
 	g_assert_not_reached ();
       }
-      name = swfdec_abc_describe_function (fun);
-      g_print ("%s %s\n", fun->native == swfdec_abc_default_stub ? "XXX" : "   ", name);
+      name = swfdec_abc_function_describe (fun);
+      g_print ("%s %s\n", fun->native == NULL ? "XXX" : "   ", name);
       g_free (name);
       }
   }
diff --git a/swfdec/swfdec_abc_file.h b/swfdec/swfdec_abc_file.h
index 675cf3e..776bc38 100644
--- a/swfdec/swfdec_abc_file.h
+++ b/swfdec/swfdec_abc_file.h
@@ -95,7 +95,7 @@ SwfdecAbcFile *	swfdec_abc_file_new		(SwfdecAsContext *	context,
 						 SwfdecBits *		bits);
 SwfdecAbcFile *	swfdec_abc_file_new_trusted	(SwfdecAsContext *	context,
 						 SwfdecBits *		bits,
-						 const SwfdecAsNative *	natives,
+						 const GCallback *	natives,
 						 guint			n_natives);
 
 gboolean	swfdec_abc_file_get_constant	(SwfdecAbcFile *	pool,
diff --git a/swfdec/swfdec_abc_function.c b/swfdec/swfdec_abc_function.c
index 9fe597d..9c4a2c6 100644
--- a/swfdec/swfdec_abc_function.c
+++ b/swfdec/swfdec_abc_function.c
@@ -30,8 +30,186 @@
 #include "swfdec_abc_traits.h"
 #include "swfdec_as_context.h"
 #include "swfdec_as_frame_internal.h"
+#include "swfdec_as_strings.h" /* swfdec_abc_function_describe */
 #include "swfdec_debug.h"
 
+/*** LIBFFI ***/
+
+static ffi_type *machine_types_ffi[] = {
+  [SWFDEC_ABC_POINTER] = &ffi_type_pointer,
+  [SWFDEC_ABC_INT] = &ffi_type_sint,
+  [SWFDEC_ABC_UINT] = &ffi_type_uint,
+  [SWFDEC_ABC_DOUBLE] = &ffi_type_double,
+  [SWFDEC_ABC_STRING] = &ffi_type_pointer,
+  [SWFDEC_ABC_VOID] = &ffi_type_void
+};
+
+static ffi_type *
+swfdec_abc_ffi_traits_to_type (SwfdecAbcTraits *traits)
+{
+  if (traits == NULL)
+    return &ffi_type_pointer;
+
+  return machine_types_ffi[traits->machine_type];
+}
+
+static guint
+swfdec_abc_function_native_n_arguments (SwfdecAbcFunction *fun)
+{
+  /* this pointer */
+  guint n_args = 1;
+  /* arguments */
+  n_args += fun->n_args;
+  /* add context as first arg if we're not passing an object */
+  if (fun->args[0].traits->machine_type != SWFDEC_ABC_POINTER)
+    n_args++;
+  /* append arguments: guint argc, SwfdecAsValue **argv */
+  if (fun->need_rest || fun->need_arguments)
+    n_args += 2;
+  /* append argument: SwfdecAsValue *retval */
+  if (fun->return_traits == NULL)
+    n_args++;
+  return n_args;
+}
+
+static gboolean
+swfdec_abc_function_ffi_verify (SwfdecAbcFunction *fun)
+{
+  guint i, n_args;
+  ffi_type **args;
+  ffi_type *ret;
+  ffi_status status;
+  
+  /* prepare variables */
+  n_args = swfdec_abc_function_native_n_arguments (fun);
+  args = g_new (ffi_type *, n_args);
+
+  /* set argument types */
+  if (fun->args[0].traits->machine_type != SWFDEC_ABC_POINTER)
+    args[0] = &ffi_type_pointer;
+  for (i = 0; i <= fun->n_args; i++) {
+    args[i] = swfdec_abc_ffi_traits_to_type (fun->args[i].traits);
+  }
+  if (fun->args[0].traits->machine_type != SWFDEC_ABC_POINTER) {
+    args--;
+    i++;
+  }
+  if (fun->need_rest || fun->need_arguments) {
+    args[i++] = &ffi_type_uint;
+    args[i++] = &ffi_type_pointer;
+  }
+  if (fun->return_traits == NULL) {
+    ret = &ffi_type_void;
+    args[i++] = &ffi_type_pointer;
+  } else {
+    ret = swfdec_abc_ffi_traits_to_type (fun->return_traits);
+  }
+  g_assert (i == n_args);
+
+  /* prepare the cif */
+  status = ffi_prep_cif (&fun->cif, FFI_DEFAULT_ABI, n_args, ret, args);
+  //g_free (args);
+  if (status != FFI_OK) {
+    /* We don't have typedefs and we use the default abi, so this must not happen */
+    g_assert_not_reached ();
+  }
+
+  return TRUE;
+}
+
+/* NB: @val must have been coerced to @traits */
+static gpointer
+swfdec_abc_ffi_get_address (SwfdecAbcTraits *traits, SwfdecAsValue *val)
+{
+  g_assert (traits != NULL);
+
+  /* make sure the value is NULL; */
+  if (SWFDEC_AS_VALUE_IS_NULL (val))
+    val->value.object = NULL;
+  /* FIXME: Is this correct, or do we need to do stuff like:
+   * if (SWFDEC_AS_VALUE_IS_BOOLEAN (val)) return &val.values.boolean
+   */
+  return &val->value;
+}
+
+static gboolean
+swfdec_abc_function_ffi_call (SwfdecAbcFunction *fun)
+{
+  SwfdecAsContext *context = swfdec_gc_object_get_context (fun);
+  SwfdecAsFrame *frame = context->frame;
+  SwfdecAsValue rval = { 0, };
+  const SwfdecAsValue *restp;
+  guint i, rest, n_args;
+  gpointer *args;
+  gpointer ret, rvalp;
+
+  /* compute number of arguments */
+  n_args = swfdec_abc_function_native_n_arguments (fun);
+  /* FIXME: I don't want a malloc here */
+  args = g_new (gpointer, n_args);
+
+  if (fun->args[0].traits->machine_type != SWFDEC_ABC_POINTER) {
+    args[0] = &context;
+    args++;
+  }
+  for (i = 0; i <= MIN (frame->argc, fun->n_args); i++) {
+    if (fun->args[i].traits == NULL) {
+      gconstpointer *tmp = g_newa (gconstpointer, 1);
+      *tmp = &frame->argv[i];
+      args[i] = &tmp;
+    } else {
+      args[i] = swfdec_abc_ffi_get_address (fun->args[i].traits, (gpointer) &frame->argv[i]);
+    }
+  }
+  for (; i <= fun->n_args; i++) {
+    if (fun->args[i].traits == NULL) {
+      gpointer *tmp = g_newa (gpointer, 1);
+      *tmp = &fun->args[i].default_value;
+      args[i] = &tmp;
+    } else {
+      args[i] = swfdec_abc_ffi_get_address (fun->args[i].traits, 
+	  &fun->args[i].default_value);
+    }
+  }
+  if (fun->args[0].traits->machine_type != SWFDEC_ABC_POINTER) {
+    args--;
+    i++;
+  }
+  if (fun->need_rest) {
+    if (frame->argc <= fun->n_args) {
+      rest = 0;
+      args[i++] = &rest;
+      args[i++] = &rval.value.object; /* should be a NULL value */
+    } else {
+      rest = frame->argc - fun->n_args;
+      restp = &frame->argv[fun->n_args];
+      args[i++] = &rest;
+      args[i++] = &restp;
+    }
+  } else if (fun->need_arguments) {
+    args[i++] = &frame->argc;
+    args[i++] = &frame->argv;
+  }
+  if (fun->return_traits == NULL) {
+    rvalp = &rval;
+    args[i++] = &rvalp;
+    ret = NULL;
+  } else {
+    ret = swfdec_abc_ffi_get_address (fun->return_traits, &rval);
+  }
+  g_assert (i == n_args);
+
+  ffi_call (&fun->cif, FFI_FN (fun->native), ret, args);
+  g_free (args);
+  if ((SWFDEC_AS_VALUE_IS_OBJECT (&rval) && rval.value.object == NULL) ||
+      (SWFDEC_AS_VALUE_IS_STRING (&rval) && rval.value.string == NULL) ||
+      (SWFDEC_AS_VALUE_IS_NAMESPACE (&rval) && rval.value.ns == NULL)) {
+    SWFDEC_AS_VALUE_SET_NULL (&rval);
+  }
+  swfdec_as_frame_return (frame, &rval);
+  return context->exception ? FALSE : TRUE;
+}
+
 G_DEFINE_TYPE (SwfdecAbcFunction, swfdec_abc_function, SWFDEC_TYPE_GC_OBJECT)
 
 static void
@@ -174,6 +352,9 @@ swfdec_abc_function_verify (SwfdecAbcFunction *fun)
   if (!swfdec_abc_function_resolve (fun))
     return FALSE;
 
+  if (fun->native)
+    return swfdec_abc_function_ffi_verify (fun);
+
   if (!shut_up) {
     SWFDEC_FIXME ("i can has verify?");
     shut_up = TRUE;
@@ -271,11 +452,155 @@ swfdec_abc_function_call (SwfdecAbcFunction *fun, SwfdecAbcScopeChain *scope,
   frame.original_target = frame.target;
   /* FIXME: coerce arguments */
   if (fun->native) {
-    SwfdecAsValue rval;
-    ((SwfdecAbcNative) fun->native) (context, argc, argv, &rval);
+    return swfdec_abc_function_ffi_call (fun);
+  } else if (fun->code) {
+    return swfdec_abc_interpret (fun, scope);
+  } else {
+    /* no code and no native function, probably a missing stub */
+    SwfdecAsValue rval = { 0, };
+    char *desc = swfdec_abc_function_describe (fun);
+    SWFDEC_STUB (desc);
+    g_free (desc);
+    if (fun->return_traits && !swfdec_abc_traits_coerce (fun->return_traits, &rval))
+      return FALSE;
     swfdec_as_frame_return (&frame, &rval);
-    return context->exception ? FALSE : TRUE;
+    return TRUE;
+  }
+}
+
+static void
+swfdec_abc_function_append_name_for_traits (GString *string, SwfdecAbcTraits *traits)
+{
+  if (traits == NULL) {
+    g_string_append (string, "const SwfdecAsValue *");
+    return;
+  }
+
+  switch (traits->machine_type) {
+    case SWFDEC_ABC_POINTER:
+      g_string_append (string, "SwfdecAbc");
+      g_string_append (string, traits->name);
+      g_string_append (string, "*");
+      break;
+    case SWFDEC_ABC_INT:
+      if (traits->name == SWFDEC_AS_STR_Boolean)
+	g_string_append (string, "gboolean");
+      else
+	g_string_append (string, "int");
+      break;
+    case SWFDEC_ABC_UINT:
+      g_string_append (string, "guint");
+      break;
+    case SWFDEC_ABC_DOUBLE:
+      g_string_append (string, "double");
+      break;
+    case SWFDEC_ABC_STRING:
+      g_string_append (string, "const char*");
+      break;
+    case SWFDEC_ABC_VOID:
+      g_string_append (string, "void");
+      break;
+    default:
+      g_assert_not_reached ();
+  }
+}
+
+char *
+swfdec_abc_function_describe (SwfdecAbcFunction *fun)
+{
+  SwfdecAbcTraits *traits;
+  GString *name, *retname;
+  guint i, id;
+
+  g_assert (fun->resolved);
+
+  /* find id of our function in pool */
+  for (id = 0; id < fun->pool->n_functions; id++) {
+    if (fun->pool->functions[id] == fun)
+      break;
+  }
+
+  traits = fun->bound_traits;
+  name = g_string_new ("");
+  if (fun->return_traits == NULL) {
+    retname = g_string_new ("void");
   } else {
-    return swfdec_abc_interpret (fun, scope);
+    retname = g_string_new ("");
+    swfdec_abc_function_append_name_for_traits (retname, fun->return_traits);
   }
+  if (traits == NULL) {
+    /* we're likely a lambda function */
+    g_string_append_printf (name, "function %u: %s [lambda]", id, retname->str);
+  } else if (traits->construct == fun) {
+    /* we're the constructor */
+    g_string_append_printf (name, "function %u: %s %s", id, 
+	retname->str, traits->name);
+  } else {
+    /* we're method, getter or setter, find out what */
+    do {
+      for (i = 0; i < traits->n_traits; i++) {
+	SwfdecAbcTrait *trait = &traits->traits[i];
+	guint slot = SWFDEC_ABC_BINDING_GET_ID (trait->type);
+	switch (SWFDEC_ABC_BINDING_GET_TYPE (trait->type)) {
+	  case SWFDEC_ABC_TRAIT_METHOD:
+	    if (traits->methods[slot] == fun) {
+	      g_string_append_printf (name, "method %u %s %s.%s", id,
+		  retname->str, traits->name, trait->name);
+	      goto out;
+	    }
+	    break;
+	  case SWFDEC_ABC_TRAIT_GET:
+	  case SWFDEC_ABC_TRAIT_SET:
+	  case SWFDEC_ABC_TRAIT_GETSET:
+	    if (traits->methods[slot] == fun) {
+	      g_string_append_printf (name, "getter %u %s %s.%s", id,
+		  retname->str, traits->name, trait->name);
+	      goto out;
+	    } else if (traits->methods[slot + 1] == fun) {
+	      g_string_append_printf (name, "setter %u %s %s.%s", id,
+		  retname->str, traits->name, trait->name);
+	      goto out;
+	    }
+	    break;
+	  case SWFDEC_ABC_TRAIT_NONE:
+	  case SWFDEC_ABC_TRAIT_SLOT:
+	  case SWFDEC_ABC_TRAIT_CONST:
+	  case SWFDEC_ABC_TRAIT_ITRAMP:
+	  default:
+	  break;
+	}
+      }
+      traits = traits->base;
+    } while (traits);
+    /* huh? */
+    g_string_append_printf (name, "function %u %s %s", id, retname->str,
+	fun->bound_traits->name);
+  }
+out:
+  /* append arguments */
+  g_string_append (name, " (");
+  if (fun->args[0].traits->machine_type != SWFDEC_ABC_POINTER)
+    g_string_append (name, "SwfdecAsContext *cx, ");
+  for (i = 0; i <= fun->n_args; i++) {
+    if (i > 0)
+      g_string_append (name, ", ");
+    swfdec_abc_function_append_name_for_traits (name, fun->args[i].traits);
+    if (i > 0)
+      g_string_append_printf (name, " arg%u", i);
+    else
+      g_string_append (name, " thisp");
+  }
+  if (fun->need_rest) {
+    g_string_append (name, ", guint argc, SwfdecAsValue *rest");
+  } else if (fun->need_arguments) {
+    g_string_append (name, ", guint argc, SwfdecAsValue *argv");
+  }
+  if (fun->return_type == NULL) {
+    g_string_append (name, ", SwfdecAsValue *ret");
+  }
+  g_string_append (name, ")");
+
+  g_string_free (retname, TRUE);
+  return g_string_free (name, FALSE);
 }
+
diff --git a/swfdec/swfdec_abc_function.h b/swfdec/swfdec_abc_function.h
index c5ee816..696b71d 100644
--- a/swfdec/swfdec_abc_function.h
+++ b/swfdec/swfdec_abc_function.h
@@ -20,6 +20,8 @@
 #ifndef _SWFDEC_ABC_FUNCTION_H_
 #define _SWFDEC_ABC_FUNCTION_H_
 
+#include <ffi.h>
+
 #include <swfdec/swfdec_abc_types.h>
 #include <swfdec/swfdec_as_function.h>
 #include <swfdec/swfdec_buffer.h>
@@ -84,7 +86,8 @@ struct _SwfdecAbcFunction {
   SwfdecAbcTraits *	bound_traits;		/* traits of objects we construct or NULL */
   
   /* native functions only */
-  SwfdecAsNative	native;			/* SwfdecAsNative for now - will become native when we can marhsal */
+  GCallback		native;			/* SwfdecAsNative for now - will become native when we can marhsal */
+  ffi_cif		cif;			/* native call marshaller - prepared during verification */
   /* functions with body only */
   SwfdecBuffer *	code;			/* the code to be executed */
   guint			n_stack;		/* max number of values on stack */
@@ -115,6 +118,8 @@ gboolean		swfdec_abc_function_call	(SwfdecAbcFunction *	fun,
 							 SwfdecAsValue *	argv,
 							 SwfdecAsValue *	ret);
 
+char *			swfdec_abc_function_describe	(SwfdecAbcFunction *	fun);
+
 
 G_END_DECLS
 #endif
diff --git a/swfdec/swfdec_abc_global.c b/swfdec/swfdec_abc_global.c
index 0e6aae6..1dd8c29 100644
--- a/swfdec/swfdec_abc_global.c
+++ b/swfdec/swfdec_abc_global.c
@@ -77,6 +77,7 @@ swfdec_abc_global_constructor (GType type, guint n_construct_properties,
   global->void_traits->pool = NULL;
   global->void_traits->ns = context->public_ns;
   global->void_traits->name = SWFDEC_AS_STR_void;
+  global->void_traits->machine_type = SWFDEC_ABC_VOID;
   global->void_traits->final = TRUE;
   global->void_traits->resolved = TRUE;
   global->null_traits = g_object_new (SWFDEC_TYPE_ABC_TRAITS, "context", context, NULL);
@@ -107,6 +108,13 @@ swfdec_abc_global_constructor (GType type, guint n_construct_properties,
     SWFDEC_ABC_OBJECT (global)->slots = swfdec_as_context_new (context,
        SwfdecAsValue, traits->n_slots);
 
+  /* update machine types */
+  SWFDEC_ABC_BOOLEAN_TRAITS (context)->machine_type = SWFDEC_ABC_INT;
+  SWFDEC_ABC_INT_TRAITS (context)->machine_type = SWFDEC_ABC_INT;
+  SWFDEC_ABC_UINT_TRAITS (context)->machine_type = SWFDEC_ABC_UINT;
+  SWFDEC_ABC_NUMBER_TRAITS (context)->machine_type = SWFDEC_ABC_DOUBLE;
+  SWFDEC_ABC_STRING_TRAITS (context)->machine_type = SWFDEC_ABC_STRING;
+
   /* run main script */
   global->file->main->global = SWFDEC_ABC_OBJECT (global);
   SWFDEC_AS_VALUE_SET_OBJECT (&val, SWFDEC_AS_OBJECT (global));
diff --git a/swfdec/swfdec_abc_internal.h b/swfdec/swfdec_abc_internal.h
index 9e0157a..62bbb5f 100644
--- a/swfdec/swfdec_abc_internal.h
+++ b/swfdec/swfdec_abc_internal.h
@@ -26,11 +26,8 @@
 
 G_BEGIN_DECLS
 
-#define SWFDEC_ABC_NATIVE(id, func) void func (SwfdecAsContext *cx, \
-    guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret);
-#define SWFDEC_ABC_FLASH(id, func) void func (SwfdecAsContext *cx, \
-    guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret);
-typedef void (* SwfdecAbcNative) (SwfdecAsContext *cx, guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret);
+#define SWFDEC_ABC_NATIVE(id, func)
+#define SWFDEC_ABC_FLASH(id, func)
 
 /* This header contains all private symbols of Abc handling that should not be 
  * exported in the API */
diff --git a/swfdec/swfdec_abc_native.h b/swfdec/swfdec_abc_native.h
index 47a5514..3b9a06c 100644
--- a/swfdec/swfdec_abc_native.h
+++ b/swfdec/swfdec_abc_native.h
@@ -25,9 +25,9 @@
 G_BEGIN_DECLS
 
 
-extern const SwfdecAsNative swfdec_abc_natives[585];
+extern const GCallback swfdec_abc_natives[585];
 
-extern const SwfdecAsNative swfdec_abc_natives_flash[1944];
+extern const GCallback swfdec_abc_natives_flash[1944];
 
 
 G_END_DECLS
diff --git a/swfdec/swfdec_abc_traits.h b/swfdec/swfdec_abc_traits.h
index a5ecf4b..f8af61d 100644
--- a/swfdec/swfdec_abc_traits.h
+++ b/swfdec/swfdec_abc_traits.h
@@ -26,6 +26,15 @@
 
 G_BEGIN_DECLS
 
+typedef enum {
+  SWFDEC_ABC_POINTER = 0,
+  SWFDEC_ABC_INT,
+  SWFDEC_ABC_UINT,
+  SWFDEC_ABC_DOUBLE,
+  SWFDEC_ABC_STRING,
+  SWFDEC_ABC_VOID
+} SwfdecAbcMachineType;
+
 /* NB: The indexes for the binding types have a lot of magic associated with 
  * them, so be sure to update this magic. Examples:
  * (type & 6) == 2 => slot or const
@@ -92,6 +101,7 @@ struct _SwfdecAbcTraits {
   SwfdecAbcFunction *		construct;	/* constructor for objects of these traits or NULL */
   SwfdecAbcNamespace *		protected_ns;	/* protected namespace */
   GType				(* type_func)	(void);	/* get_type function for the object type we create */
+  SwfdecAbcMachineType		machine_type;	/* how this type is represented */
 
   SwfdecAbcTrait *		traits;		/* the traits we have */
   guint				n_traits;	/* number of traits */
diff --git a/swfdec/swfdec_player_abc.c b/swfdec/swfdec_player_abc.c
index 5b49d5e..75a22d0 100644
--- a/swfdec/swfdec_player_abc.c
+++ b/swfdec/swfdec_player_abc.c
@@ -26,11 +26,12 @@
 #include "swfdec_abc_internal.h"
 #include "swfdec_resource.h"
 
+void swfdec_player_abc_trace (SwfdecAsObject *global, guint argc, SwfdecAsValue *argv);
 SWFDEC_ABC_FLASH (0, swfdec_player_abc_trace)
 void
-swfdec_player_abc_trace (SwfdecAsContext *cx,
-    guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
+swfdec_player_abc_trace (SwfdecAsObject *global, guint argc, SwfdecAsValue *argv)
 {
+  SwfdecAsContext *cx = swfdec_gc_object_get_context (global);
   GString *string = g_string_new ("");
   guint i;
 
@@ -44,16 +45,12 @@ swfdec_player_abc_trace (SwfdecAsContext *cx,
   g_string_free (string, TRUE);
 }
 
+void swfdec_player_abc_fscommand (SwfdecAsObject *system, const char *command, const char *target);
 SWFDEC_ABC_FLASH (203, swfdec_player_abc_fscommand)
 void
-swfdec_player_abc_fscommand (SwfdecAsContext *cx,
-    guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
+swfdec_player_abc_fscommand (SwfdecAsObject *system, const char *command, const char *target)
 {
-  const char *command, *target;
-  
-  command = swfdec_as_value_to_string (cx, &argv[1]);
-  target = swfdec_as_value_to_string (cx, &argv[2]);
-
+  SwfdecAsContext *cx = swfdec_gc_object_get_context (system);
   /* FIXME: emit here or (as in older Flash) later? */
   g_signal_emit_by_name (cx, "fscommand", command, target);
 }
commit 39efcd6a8d691107f43f9822c9db08cf891600d5
Author: Benjamin Otte <otte at gnome.org>
Date:   Fri Aug 22 14:32:06 2008 +0100

    make it compile again
    
    Small little problem: The new code initializes the Tamarin ABC stuff, so we
    can't parse those without errors anymore

diff --git a/tools/abcextract.c b/tools/abcextract.c
index 12028c1..3f31c23 100644
--- a/tools/abcextract.c
+++ b/tools/abcextract.c
@@ -116,7 +116,7 @@ main (int argc, char **argv)
   }
 
   cx = g_object_new (SWFDEC_TYPE_AS_CONTEXT, NULL);
-  swfdec_abc_global_new (cx);
+  swfdec_as_context_startup (cx, TRUE);
   offsets = g_ptr_array_new ();
   for (i = 0; i < buffer->length - 3; i++) {
     if (buffer->data[i] != 0x10 ||


More information about the Swfdec-commits mailing list