⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 swfdec_as_context.c

📁 Swfdec is a decoder/renderer for Macromedia Flash animations. The decoding and rendering engine is
💻 C
📖 第 1 页 / 共 3 页
字号:
/* Swfdec * Copyright (C) 2007 Benjamin Otte <otte@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 <math.h>#include <string.h>#include "swfdec_as_context.h"#include "swfdec_as_array.h"#include "swfdec_as_boolean.h"#include "swfdec_as_frame_internal.h"#include "swfdec_as_function.h"#include "swfdec_as_internal.h"#include "swfdec_as_interpret.h"#include "swfdec_as_math.h"#include "swfdec_as_native_function.h"#include "swfdec_as_number.h"#include "swfdec_as_object.h"#include "swfdec_as_stack.h"#include "swfdec_as_string.h"#include "swfdec_as_strings.h"#include "swfdec_as_types.h"#include "swfdec_debug.h"#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 * @short_description: understanding internals such as garbage collection * @see_also: #SwfdecAsContext * * This section deals with the internals of the Swfdec Actionscript engine. You * should probably read this first when trying to write code with it. If you're * just trying to use Swfdec for creating Flash content, you can probably skip * this section. * * First, I'd like to note that the Swfdec script engine has to be modeled very  * closely after the existing Flash players. So if there are some behaviours * that seem stupid at first sight, it might very well be that it was chosen for * a very particular reason. Now on to the features. * * The Swfdec script engine tries to imitate Actionscript as good as possible. * Actionscript is similar to Javascript, but not equal. Depending on the  * version of the script executed it might be more or less similar. An important * example is that Flash in versions up to 6 did case-insensitive variable  * lookups. * * The script engine starts its life when it is initialized via  * swfdec_as_context_startup (). At that point, the basic objects are created. * After this function has been called, you can start executing code. All code * execution happens by creating a new #SwfdecAsFrame and then calling  * swfdec_as_context_run() to execute it. This function is the single entry  * point for code execution. Convenience functions exist that make executing  * code easy, most notably swfdec_as_object_run() and  * swfdec_as_object_call(). * * It is also easily possible to extend the environment by adding new objects. * In fact, without doing so, the environment is pretty bare as it just contains * the basic Math, String, Number, Array, Date and Boolean objects. This is done * by adding #SwfdecAsNative functions to the environment. The easy way * to do this is via swfdec_as_object_add_function(). * * The Swfdec script engine is dynamically typed and knows about different types * of values. See #SwfdecAsValue for the different values. Memory management is * done using a mark and sweep garbage collector. You can initiate a garbage  * collection cycle by calling swfdec_as_context_gc() or  * swfdec_as_context_maybe_gc(). You should do this regularly to avoid excessive * memory use. The #SwfdecAsContext will then collect the objects and strings it * is keeping track of. If you want to use an object or string in the script  * engine, you'll have to add it first via swfdec_as_object_add() or * swfdec_as_context_get_string() and swfdec_as_context_give_string(),  * respectively. * * Garbage-collected strings are special in Swfdec in that they are unique. This * means the same string exists exactly once. Because of this you can do  * equality comparisons using == instead of strcmp. It also means that if you  * forget to add a string to the context before using it, your app will most  * likely not work, since the string will not compare equal to any other string. * * When a garbage collection cycle happens, all reachable objects and strings  * are marked and all unreachable ones are freed. This is done by calling the * context class's mark function which will mark all reachable objects. This is * usually called the "root set". For any reachable object, the object's mark * function is called so that the object in turn can mark all objects it can  * reach itself. Marking is done via functions described below. *//*** GTK-DOC ***//** * SECTION:SwfdecAsContext * @title: SwfdecAsContext * @short_description: the main script engine context * @see_also: SwfdecPlayer * * A #SwfdecAsContext provides the main execution environment for Actionscript * execution. It provides the objects typically available in ECMAScript and * manages script execution, garbage collection etc. #SwfdecPlayer is a * subclass of the context that implements Flash specific objects on top of it. * However, it is possible to use the context for completely different functions * where a sandboxed scripting environment is needed. An example is the Swfdec  * debugger. * <note>The Actionscript engine is similar, but not equal to Javascript. It * is not very different, but it is different.</note> *//** * SwfdecAsContext * * This is the main object ued to hold the state of a script engine. All members  * are private and should not be accessed. * * Subclassing this structure to get scripting support in your own appliation is * encouraged. *//** * SwfdecAsContextState * @SWFDEC_AS_CONTEXT_NEW: the context is not yet initialized,  *                         swfdec_as_context_startup() needs to be called. * @SWFDEC_AS_CONTEXT_RUNNING: the context is running normally * @SWFDEC_AS_CONTEXT_INTERRUPTED: the context has been interrupted by a  *                             debugger * @SWFDEC_AS_CONTEXT_ABORTED: the context has aborted execution due to a  *                         fatal error * * The state of the context describes what operations are possible on the context. * It will be in the state @SWFDEC_AS_CONTEXT_STATE_RUNNING almost all the time. If * it is in the state @SWFDEC_AS_CONTEXT_STATE_ABORTED, it will not work anymore and * every operation on it will instantly fail. *//*** RUNNING STATE ***//** * swfdec_as_context_abort: * @context: a #SwfdecAsContext * @reason: a string describing why execution was aborted * * Aborts script execution in @context. Call this functon if the script engine  * encountered a fatal error and cannot continue. A possible reason for this is * an out-of-memory condition. **/voidswfdec_as_context_abort (SwfdecAsContext *context, const char *reason){  g_return_if_fail (context);  SWFDEC_ERROR ("%s", reason);  context->state = SWFDEC_AS_CONTEXT_ABORTED;}/*** MEMORY MANAGEMENT ***//** * swfdec_as_context_use_mem: * @context: a #SwfdecAsContext * @bytes: number of bytes to use * * Registers @bytes additional bytes as in use by the @context. This function * keeps track of the memory that script code consumes. If too many memory is  * in use, this function may decide to stop the script engine with an out of  * memory error. * * Returns: %TRUE if the memory could be allocated. %FALSE on OOM. **/gbooleanswfdec_as_context_use_mem (SwfdecAsContext *context, gsize bytes){  g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context), FALSE);  g_return_val_if_fail (bytes > 0, FALSE);  if (context->state == SWFDEC_AS_CONTEXT_ABORTED)    return FALSE;    context->memory += bytes;  context->memory_since_gc += bytes;  /* FIXME: Don't foget to abort on OOM */  return TRUE;}/** * swfdec_as_context_unuse_mem: * @context: a #SwfdecAsContext * @bytes: number of bytes to release * * Releases a number of bytes previously allocated using  * swfdec_as_context_use_mem(). See that function for details. **/voidswfdec_as_context_unuse_mem (SwfdecAsContext *context, gsize bytes){  g_return_if_fail (SWFDEC_IS_AS_CONTEXT (context));  g_return_if_fail (bytes > 0);  g_return_if_fail (context->memory >= bytes);  context->memory -= bytes;}/*** GC ***/static gbooleanswfdec_as_context_remove_strings (gpointer key, gpointer value, gpointer data){  SwfdecAsContext *context = data;  char *string;  string = (char *) value;  /* it doesn't matter that rooted strings aren't destroyed, they're constant */  if (string[0] & SWFDEC_AS_GC_ROOT) {    SWFDEC_LOG ("rooted: %s", (char *) key);    return FALSE;  } else if (string[0] & SWFDEC_AS_GC_MARK) {    SWFDEC_LOG ("marked: %s", (char *) key);    string[0] &= ~SWFDEC_AS_GC_MARK;    return FALSE;  } else {    gsize len;    SWFDEC_LOG ("deleted: %s", (char *) key);    len = (strlen ((char *) key) + 2);    swfdec_as_context_unuse_mem (context, len);    g_slice_free1 (len, value);    return TRUE;  }}static gbooleanswfdec_as_context_remove_objects (gpointer key, gpointer value, gpointer debugger){  SwfdecAsObject *object;  object = 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);    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);    return TRUE;  }}static voidswfdec_as_context_collect (SwfdecAsContext *context){  SWFDEC_INFO (">> collecting garbage");  /* NB: This functions is called without GC from swfdec_as_context_dispose */  g_hash_table_foreach_remove (context->strings,     swfdec_as_context_remove_strings, context);  g_hash_table_foreach_remove (context->objects,     swfdec_as_context_remove_objects, context->debugger);  SWFDEC_INFO (">> done collecting garbage");}/** * 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. **/voidswfdec_as_object_mark (SwfdecAsObject *object){  SwfdecAsObjectClass *klass;  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 * * Mark @string as being in use. Calling this function is only valid during * the marking phase of garbage collection. **/voidswfdec_as_string_mark (const char *string){  char *str = (char *) string - 1;  if (*str == 0)    *str = SWFDEC_AS_GC_MARK;}/** * swfdec_as_value_mark: * @value: a #SwfdecAsValue * * Mark @value as being in use. This is just a convenience function that calls * the right marking function depending on the value's type. Calling this  * function is only valid during the marking phase of garbage collection. **/voidswfdec_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));  } else if (SWFDEC_AS_VALUE_IS_STRING (value)) {    swfdec_as_string_mark (SWFDEC_AS_VALUE_GET_STRING (value));  }}static voidswfdec_as_context_mark_roots (gpointer key, gpointer value, gpointer data){  SwfdecAsObject *object = key;  if ((object->flags & (SWFDEC_AS_GC_MARK | SWFDEC_AS_GC_ROOT)) == SWFDEC_AS_GC_ROOT)    swfdec_as_object_mark (object);}static voidswfdec_as_context_do_mark (SwfdecAsContext *context){  swfdec_as_object_mark (context->global);  swfdec_as_object_mark (context->Function);  if (context->Function_prototype)    swfdec_as_object_mark (context->Function_prototype);  swfdec_as_object_mark (context->Object);  swfdec_as_object_mark (context->Object_prototype);  swfdec_as_object_mark (context->Array);  g_hash_table_foreach (context->objects, swfdec_as_context_mark_roots, NULL);}/** * swfdec_as_context_gc: * @context: a #SwfdecAsContext * * Calls the Swfdec Gargbage collector and reclaims any unused memory. You  * should call this function or swfdec_as_context_maybe_gc() regularly. * <warning>Calling the GC during execution of code or initialization is not *          allowed.</warning> **/voidswfdec_as_context_gc (SwfdecAsContext *context){  SwfdecAsContextClass *klass;  g_return_if_fail (SWFDEC_IS_AS_CONTEXT (context));  g_return_if_fail (context->frame == NULL);  g_return_if_fail (context->state != SWFDEC_AS_CONTEXT_NEW);  if (context->state == SWFDEC_AS_CONTEXT_ABORTED)    return;  SWFDEC_INFO ("invoking the garbage collector");  klass = SWFDEC_AS_CONTEXT_GET_CLASS (context);  g_assert (klass->mark);  klass->mark (context);  swfdec_as_context_collect (context);  context->memory_since_gc = 0;}static gbooleanswfdec_as_context_needs_gc (SwfdecAsContext *context){  return context->memory_since_gc >= context->memory_until_gc;}/** * swfdec_as_context_maybe_gc: * @context: a #SwfdecAsContext * * Calls the garbage collector if necessary. It's a good idea to call this * function regularly instead of swfdec_as_context_gc() as it only does collect * garage as needed. For example, #SwfdecPlayer calls this function after every * frame advancement. **/voidswfdec_as_context_maybe_gc (SwfdecAsContext *context){

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -