gnash-commit
[Top][All Lists]
Advanced

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

[Gnash-commit] gnash ChangeLog server/vm/AbcHandlers.cpp serve...


From: Chad Musick
Subject: [Gnash-commit] gnash ChangeLog server/vm/AbcHandlers.cpp serve...
Date: Mon, 08 Oct 2007 06:55:11 +0000

CVSROOT:        /sources/gnash
Module name:    gnash
Changes by:     Chad Musick <cmusick>   07/10/08 06:55:11

Modified files:
        .              : ChangeLog 
        server/vm      : AbcHandlers.cpp Machine.h CodeStream.h 
                         SafeStack.h 

Log message:
        More work on the AS3 interpreter and supporting classes.

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/gnash/ChangeLog?cvsroot=gnash&r1=1.4565&r2=1.4566
http://cvs.savannah.gnu.org/viewcvs/gnash/server/vm/AbcHandlers.cpp?cvsroot=gnash&r1=1.4&r2=1.5
http://cvs.savannah.gnu.org/viewcvs/gnash/server/vm/Machine.h?cvsroot=gnash&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/gnash/server/vm/CodeStream.h?cvsroot=gnash&r1=1.1&r2=1.2
http://cvs.savannah.gnu.org/viewcvs/gnash/server/vm/SafeStack.h?cvsroot=gnash&r1=1.1&r2=1.2

Patches:
Index: ChangeLog
===================================================================
RCS file: /sources/gnash/gnash/ChangeLog,v
retrieving revision 1.4565
retrieving revision 1.4566
diff -u -b -r1.4565 -r1.4566
--- ChangeLog   8 Oct 2007 06:33:53 -0000       1.4565
+++ ChangeLog   8 Oct 2007 06:55:11 -0000       1.4566
@@ -1,3 +1,14 @@
+2007-10-08 Chad Musick <address@hidden>
+
+       * server/vm/AbcHandlers.cpp: More work on the AS3 interpreter --
+         function calls and such.
+       * server/vm/Machine.h: Remove Stack (moved to SafeStack.h), remove
+         CodeStream (moved to CodeStream.h), remove FunctionEntry (becomes
+         State internal class).
+       * server/vm/CodeStream.h: Add reInitialize method to allow empty
+         construction.
+       * server/vm/SafeStack.h: Add method to reset stack to a certains state.
+
 2007-10-08 Sandro Santilli <address@hidden>
 
        * testsuite/misc-ming.all/ming_utils.c: have totals() and friend also

Index: server/vm/AbcHandlers.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/vm/AbcHandlers.cpp,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -b -r1.4 -r1.5
--- server/vm/AbcHandlers.cpp   5 Oct 2007 17:48:16 -0000       1.4
+++ server/vm/AbcHandlers.cpp   8 Oct 2007 06:55:11 -0000       1.5
@@ -16,13 +16,134 @@
 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 //
 
+#include <boost/logic/tribool.hpp>
+
+#define ENSURE_NUMBER(vte)                                                     
                        \
+{                                                                              
                                                                \
+       as_value &a = vte; /* Don't call vte multiple times */                  
        \
+       if (vte.is_object())                                                    
                                        \
+       {                                                                       
                                                                \
+               asBinding *b = a.to_object()->getBinding(NSV::PROP_VALUE_OF);   
\
+               if (b)                                                          
                                                        \
+               {                                                               
                                                                \
+                       mStream->seekTo(mOpStart);                              
                                        \
+                       mStack.push(vte);                                       
                                                \
+                       pushCall(1, &vte, b);                                   
                                        \
+                       break;                                                  
                                                        \
+               }                                                               
                                                                \
+       }                                                                       
                                                                \
+}                                                                              
           /* end of ENSURE_NUMBER */
+
+#define ENSURE_OBJECT(vte, backup)                                             
                                \
+{                                                                              
                                                                \
+       if (!vte.is_object())                                                   
                                        \
+               throw ASMalformedError();                                       
                                        \
+}                                                                              
           /* end of ENSURE_OBJECT */
+
+#define ENSURE_STRING(vte, backup)                                             
                                \
+{                                                                              
                                                                \
+       as_value &a = vte; /* Don't call vte multiple times */                  
        \
+       if (a.is_object())                                                      
                                                \
+       {                                                                       
                                                                \
+               asBinding *b = a.to_object()->getBinding(NSV::PROP_TO_STRING);  
\
+               if (b)                                                          
                                                        \
+               {                                                               
                                                                \
+                       mStream->seekTo(mOpStart);                              
                                        \
+                       mStack.push(vte);                                       
                                                \
+                       pushCall(1, &vte, b);                                   
                                        \
+                       break;                                                  
                                                        \
+               }                                                               
                                                                \
+       }                                                                       
                                                                \
+}                                                                              
           /* end of ENSURE_STRING */
+
+#define ABSTRACT_COMPARE(store, rv1, rv2, truth_of_undefined)                  
\
+{                                                                              
                                                                \
+       as_value &a = rv1; /* Don't call rv1 multiple times */                  
        \
+       as_value &b = rv2; /* Don't call rv2 multiple times */                  
        \
+       if (a.ptype() == PTYPE_STRING && b.ptype() == PTYPE_STRING)             
\
+       {                                                                       
                                                                \
+               ENSURE_STRING(a);                                               
                                                \
+               ENSURE_STRING(b);                                               
                                                \
+               std::string &str_a = a.to_string();                             
                        \
+               std::string &str_b = b.to_string();                             
                        \
+               store = a < b;                                                  
                                                \
+       }                                                                       
                                                                \
+       else                                                                    
                                                        \
+       {                                                                       
                                                                \
+               ENSURE_NUMBER(a);                                               
                                                \
+               ENSURE_NUMBER(b);                                               
                                                \
+               if (a.is_nan() || b.is_nan())                                   
                                \
+                       store = truth_of_undefined;                             
                                \
+               else if (a.is_positive_infinity())                              
                                \
+                       store = false;                                          
                                                \
+               else if (b.is_positive_infinity())                              
                                \
+                       store = true;                                           
                                                \
+               else if (b.is_negative_infinity())                              
                                \
+                       store = false;                                          
                                                \
+               else if (a.is_negative_infinity())                              
                                \
+                       store = true;                                           
                                                \
+               else                                                            
                                                        \
+                       store = a.to_number() < b.to_number();                  
                        \
+       }                                                                       
                                                                \
+}                                                                              
        /* end of ABSTRACT_COMPARE */
+
+#define ABSTRACT_EQUALITY(store, ev1, ev2, strictness_on)                      
        \
+{                                                                              
                                                                \
+       as_value &a = ev1; /* Don't call ev1 multiple times */                  
        \
+       as_value &b = ev2; /* Don't call ev2 multiple times */                  
        \
+       if (a.is_object() && b.is_object())                                     
                                \
+               store = a.to_object() == b.to_object();                         
                        \
+       else if (a.is_object() || b.is_object())                                
                        \
+               store = false;                                                  
                                                \
+       else if (a.ptype() != b.ptype())                                        
                                \
+       {                                                                       
                                                                \
+               if (!strictness_on && (a.is_undefined() || b.is_undefined()) && 
\
+                       (a.is_null() || b.is_null())                            
                                \
+                       store = true;                                           
                                                \
+               else                                                            
                                                        \
+                       store = false;                                          
                                                \
+       }                                                                       
                                                                \
+       else if (a.is_number())                                                 
                                        \
+       {                                                                       
                                                                \
+               if (a.is_nan() || b.is_nan())                                   
                                \
+                       store = false;                                          
                                                \
+               else if (a.is_positive_infinity() && b.is_positive_infinity())  
\
+                       store = true;                                           
                                                \
+               else if (a.is_negative_infinity() && b.is_negative_infinity())  
\
+                       store = true;                                           
                                                \
+               else                                                            
                                                        \
+                       store = a.to_number() == b.to_number();                 
                        \
+       }                                                                       
                                                                \
+       else if (a.is_bool() && b.is_bool())                                    
                        \
+               store = a.to_bool() == b.to_bool();                             
                                \
+}                                                                              
   /* end of ABSTRACT_EQUALITY */
+
+#define JUMPIF(jtruth)                                                         
                                        \
+{                                                                              
                                                                \
+       int32t jumpOffset = mStream->read_S24();                                
                        \
+       if (jtruth)                                                             
                                                        \
+               mStream->seekBy(jumpOffset);                                    
                                \
+       break;                                                                  
                                                        \
+}                                                                              
                          /* end of JUMPIF */
+
 void
-ActionMachine::execute_as3()
+ActionMachine::execute()
 {
        for ( ; ; )
        {
-       switch ((opcode = mStream.read_as3op())) // Assignment intentional
+
+       if (mStream->isAS3())
        {
+       switch ((opcode = mStream->read_as3op())) // Assignment intentional
+       {
+       default:
+               throw ASException();
+       case 0:
+       {
+// This is not actually an opcode -- it occurs when the stream is
+// empty. We may need to return from a function, or we may be done.
+               break;
+       }
 /// 0x01 ABC_ACTION_BKPT
 /// Do: Enter the debugger if one has been invoked.
 /// This is a no-op. Enable it if desired.
@@ -59,7 +180,7 @@
        case SWF::ABC_ACTION_GETSUPER:
        {
                // Get the name.
-               asName a = mStream.read_V32();
+               asName a = mStream->read_V32();
                // Finish it, if necessary.
                mStack.drop(completeName(a));
                // Get the target object.
@@ -84,7 +205,7 @@
        case SWF::ABC_ACTION_SETSUPER:
        {
                // Get and finish the name.
-               asName a = mStream.read_V32();
+               asName a = mStream->read_V32();
                as_value vobj = mStack.pop(); // The value
 
                mStack.drop(completeName(a));
@@ -104,7 +225,7 @@
 ///  default XML namespace. 
        case SWF::ABC_ACTION_DXNS:
        {
-               uint32_t soffset = mStream.read_V32();
+               uint32_t soffset = mStream->read_V32();
                std::string& uri = pool_string(soffset);
                mDefaultXMLNamespace = mCH->anonNamespace(mST.find(uri));
                break;
@@ -117,6 +238,7 @@
 /// Do: Same as ABC_ACTION_DXNS, but the uri is in the stack, not the stream.
        case SWF::ABC_ACTION_DXNSLATE:
        {
+               ENSURE_STRING(mStack.top(0));
                const std::string& uri = mStack.top(0).to_string();
                mDefaultXMLNamespace = mCH->anonNamespace(mST.find(uri));
                mStack.drop(1);
@@ -129,7 +251,7 @@
 /// Equivalent: ACTION_DELETE
        case SWF::ABC_ACTION_KILL:
        {
-               uint32_t regNum = mStream.read_V32();
+               uint32_t regNum = mStream->read_V32();
                mFrame.value(regnum).set_undefined();
                break;
        }
@@ -149,9 +271,10 @@
 /// Do: If !(a < b) move by jump in stream, as ABC_ACTION_JUMP does.
        case SWF::ABC_ACTION_IFNLT:
        {
-               bool truth = mStack.top(1).less_than(mStack.top(0));
+               bool truth;
+               ABSTRACT_COMPARE(truth, mStack.top(1), mStack.top(0), false);
                mStack.drop(2);
-               jumpIf(!truth);
+               JUMPIF(!truth); // truth is: a < b
                break;
        }
 /// 0x0D ABC_ACTION_IFNLE
@@ -164,9 +287,10 @@
 /// Do: If !(a <= b) move by jump in stream, as ABC_ACTION_JUMP does.
        case SWF::ABC_ACTION_IFNLE:
        {
-               bool truth = mStack.top(1).less_equal(mStack.top(0));
+               bool truth;
+               ABSTRACT_COMPARE(truth, mStack.top(0), mStack.top(1), true);
                mStack.drop(2);
-               jumpIf(!truth);
+               JUMPIF(truth); // truth is: b < a
                break;
        }
 /// 0x0E ABC_ACTION_IFNGT
@@ -179,9 +303,10 @@
 /// Do: If !(a > b) move by jump in stream, as ABC_ACTION_JUMP does.
        case SWF::ABC_ACTION_IFNGT:
        {
-               bool truth = mStack.top(1).greater_than(mStack.top(0));
+               bool truth;
+               ABSTRACT_COMPARE(truth, mStack.top(0), mStack.top(1), false);
                mStack.drop(2);
-               jumpIf(!truth);
+               JUMPIF(!truth); // truth is: b < a
                break;
        }
 /// 0x0F ABC_ACTION_IFNGE
@@ -194,9 +319,10 @@
 /// Do: If !(a >= b) move by jump in stream, as ABC_ACTION_JUMP does.
        case SWF::ABC_ACTION_IFNGE:
        {
-               bool truth = mStack.top(1).greater_equal(mStack.top(0));
+               bool truth;
+               ABSTRACT_COMPARE(truth, mStack.top(1), mStack.top(0), true);
                mStack.drop(2);
-               jumpIf(!truth);
+               JUMPIF(truth); // truth is: a < b
                break;
        }
 /// 0x10 ABC_ACTION_JUMP
@@ -205,7 +331,7 @@
 /// Equivalent: ACTION_BRANCHALWAYS
        case SWF::ABC_ACTION_JUMP:
        {
-               jumpIf(true);
+               JUMPIF(true);
                break;
        }
 /// 0x11 ABC_ACTION_IFTRUE
@@ -220,7 +346,7 @@
        {
                bool truth = mStack.top(0).to_bool();
                mStack.drop(1);
-               jumpIf(truth);
+               JUMPIF(truth);
                break;
        }
 /// 0x12 ABC_ACTION_IFFALSE
@@ -234,7 +360,7 @@
        {
                bool truth = mStack.top(0).to_bool();
                mStack.drop(1);
-               jumpIf(!truth);
+               JUMPIF(!truth);
                break;
        }
 /// 0x13 ABC_ACTION_IFEQ
@@ -247,9 +373,10 @@
 /// Do: If a == b (weakly), move by jump in stream, as ABC_ACTION_JUMP does.
        case SWF::ABC_ACTION_IFEQ:
        {
-               bool truth = mStack.top(1).weak_equals(mStack.top(0));
+               bool truth;
+               ABSTRACT_EQUALITY(truth, mStack.top(1), mStack.top(0), false);
                mStack.drop(2);
-               jumpIf(truth);
+               JUMPIF(truth);
                break;
        }
 /// 0x14 ABC_ACTION_IFNE
@@ -262,9 +389,10 @@
 /// Do: If a != b (weakly), move by jump in stream, as ABC_ACTION_JUMP does.
        case SWF::ABC_ACTION_IFNE:
        {
-               bool truth = mStack.top(1).weak_nequals(mStack.top(0));
+               bool truth;
+               ABSTRACT_EQUALITY(truth, mStack.top(1), mStack.top(0), false);
                mStack.drop(2);
-               jumpIf(truth);
+               JUMPIF(!truth);
                break;
        }
 /// 0x15 ABC_ACTION_IFLT
@@ -277,9 +405,10 @@
 /// Do: If a < b move by jump in stream, as ABC_ACTION_JUMP does.
        case SWF::ABC_ACTION_IFLT:
        {
-               bool truth = mStack.top(1).less_than(mStack.top(0));
+               bool truth;
+               ABSTRACT_COMPARE(truth, mStack.top(1), mStack.top(0), false);
                mStack.drop(2);
-               jumpIf(truth);
+               JUMPIF(truth); // truth is: a < b
                break;
        }
 /// 0x16 ABC_ACTION_IFLE
@@ -292,9 +421,10 @@
 /// Do: If a <= b move by jump in stream, as ABC_ACTION_JUMP does.
        case SWF::ABC_ACTION_IFLE:
        {
-               bool truth = mStack.top(1).less_equal(mStack.top(0));
+               bool truth;
+               ABSTRACT_COMPARE(truth, mStack.top(0), mStack.top(1), true);
                mStack.drop(2);
-               jumpIf(truth);
+               JUMPIF(!truth); // truth is: b < a
                break;
        }
 /// 0x17 ABC_ACTION_IFGT
@@ -307,9 +437,11 @@
 /// Do: If a > b move by jump in stream, as ABC_ACTION_JUMP does.
        case SWF::ABC_ACTION_IFGT:
        {
-               bool truth = mStack.top(1).greater_than(mStack.top(0));
+               bool truth;
+               // If b < a, then a > b, with undefined as false
+               ABSTRACT_COMPARE(truth, mStack.top(0), mStack.top(1), false);
                mStack.drop(2);
-               jumpIf(truth);
+               JUMPIF(truth); // truth is: b < a
                break;
        }
 /// 0x18 ABC_ACTION_IFGE
@@ -322,9 +454,10 @@
 /// Do: If a >= b move by jump in stream, as ABC_ACTION_JUMP does.
        case SWF::ABC_ACTION_IFGE:
        {
-               bool truth = mStack.top(1).greater_equal(mStack.top(0));
+               bool truth;
+               ABSTRACT_COMPARE(truth, mStack.top(0), mStack.top(1), true);
                mStack.drop(2);
-               jumpIf(truth);
+               JUMPIF(!truth); // truth is: a < b
                break;
        }
 /// 0x19 ABC_ACTION_IFSTRICTEQ
@@ -337,9 +470,10 @@
 /// Do: If a == b (strictly), move by jump in stream, as ABC_ACTION_JUMP
        case SWF::ABC_ACTION_IFSTRICTEQ:
        {
-               bool truth = mStack.top(1).strict_equals(mStack.top(0));
+               bool truth;
+               ABSTRACT_EQUALITY(truth, mStack.top(1), mStack.top(0), true);
                mStack.drop(2);
-               jumpIf(truth);
+               JUMPIF(truth);
                break;
        }
 /// 0x1A ABC_ACTION_IFSTRICTNE
@@ -352,9 +486,10 @@
 /// Do: If a != b (strongly), move by jump in stream, as ABC_ACTION_JUMP
        case SWF::ABC_ACTION_IFSTRICTNE:
        {
-               bool truth = mStack.top(1).strict_nequals(mStack.top(0));
+               bool truth;
+               ABSTRACT_EQUALITY(truth, mStack.top(1), mStack.top(0), true);
                mStack.drop(2);
-               jumpIf(truth);
+               JUMPIF(!truth);
                break;
        }
 /// 0x18 ABC_ACTION_LOOKUPSWITCH
@@ -368,24 +503,27 @@
 ///  Otherwise, move by cases[index] - 1 from stream position on op entry.
        case SWF::ABC_ACTION_LOOKUPSWITCH:
        {
-               AbcHandlers::stream_position npos = mStream.tell();
-               uint32_t index = mStack.top(0).to_number<uint32_t>();
+               AbcHandlers::stream_position npos = mStream->tell();
+               if (!mStack.top(0).is_number())
+                       throw ASMalformedError();
+
+               uint32_t index = mStack.top(0).to_int();
                mStack.drop(1);
 
-               mStream.seekBy(3); // Skip the intial offset.
-               uint32_t cases = mStream.read_V32();
+               mStream->seekBy(3); // Skip the intial offset.
+               uint32_t cases = mStream->read_V32();
                // Read from our original position and use it to skip if the 
case
                // is out of range.
                if (index > cases)
                {
-                       mStream.seekTo(npos);
-                       mStream.seekTo(npos + mStream.read_S24());
+                       mStream->seekTo(npos);
+                       mStream->seekTo(npos + mStream->read_S24());
                }
                else
                {
-                       mStream.seekTo(npos + 3 * (index + 1));
-                       uint_32t newpos = mStream.read_S24();
-                       mStream.seekTo(npos - 1 + newpos);
+                       mStream->seekTo(npos + 3 * (index + 1));
+                       uint_32t newpos = mStream->read_S24();
+                       mStream->seekTo(npos - 1 + newpos);
                }
                break;
        }
@@ -398,9 +536,9 @@
 ///  a base, in which case leave that alone.
        case SWF::ABC_ACTION_PUSHWITH:
        {
-               asScope = mStack.top(0).to_scope();
+               asScope a = mStack.top(0).to_scope();
                mStack.drop(1);
-               pushScope(asScope);
+               mScopeStack.push(a);
                // If there wasn't a base scope, then this becomes it.
                if (!mBaseScope)
                        mBaseScope = mCurrentScope;
@@ -413,7 +551,7 @@
        {
                if (mCurrentScope == mBaseScope)
                        mBaseScope = NULL;
-               popScope();
+               mScopeStack.pop();
                break;
        }
 /// 0x1E ABC_ACTION_NEXTNAME
@@ -424,8 +562,10 @@
 ///  name -- the key name of the property at index in obj
        case SWF::ABC_ACTION_NEXTNAME:
        {
+               ENSURE_NUMBER(mStack.top(0));
+               ENSURE_OBJECT(mStack.top(1));
                as_object *obj = mStack.top(1).to_object();
-               uint32_t index = mStack.top(0).to_number<uint32_t>();
+               uint32_t index = mStack.top(0).to_uint();
                mStack.drop(1);
                asBinding *b = obj->binding_at_index(index);
                if (next)
@@ -444,8 +584,10 @@
 ///  Otherwise, make next_index 0.
        case SWF::ABC_ACTION_HASNEXT:
        {
+               ENSURE_NUMBER(mStack.top(0));
+               ENSURE_OBJECT(mStack.top(1));
                as_object *obj = mStack.top(1).to_object();
-               uint32_t index = mStack.top(0).to_number<uint32_t>();
+               uint32_t index = mStack.top(0).to_uint();
                mStack.drop(1);
                asBinding *next = obj->binding_after_index(index);
                if (next)
@@ -480,14 +622,16 @@
 ///  value -- the value of the key value pair in obj at index.
        case SWF::ABC_ACTION_NEXTVALUE:
        {
+               ENSURE_NUMBER(mStack.top(0));
+               ENSURE_OBJECT(mStack.top(1));
                as_object *obj = mStack.top(1).to_object();
-               uint32_t index = mStack.top(0).to_number<uint32_t>();
-               mStack.drop(1);
+               uint32_t index = mStack.top(0).to_uint();
                asBinding *b = obj->binding_at_index(index);
-               if (next)
-                       mStack.top(0) = b->getValue();
-               else
+               mStack.drop(1);
+               if (!next)
                        mStack.top(0).set_undefined();
+               else // The top of the stack is obj, as it should be.
+                       pushCall(1, &mStack.top(0), b);
                break;
        }
 /// 0x24 ABC_ACTION_PUSHBYTE
@@ -496,7 +640,7 @@
 ///  byte -- as a raw byte
        case SWF::ABC_ACTION_PUSHBYTE:
        {
-               int8_t *b = mStream.read_s8();
+               int8_t *b = mStream->read_s8();
                mStack.grow(1);
                mStack.top(0) = b;
                break;
@@ -507,7 +651,7 @@
 ///  value -- as a raw integer
        case SWF::ABC_ACTION_PUSHSHORT:
        {
-               signed short s = static_cast<signed short>(mStream.read_V32());
+               signed short s = static_cast<signed short>(mStream->read_V32());
                mStack.grow(1);
                mStack.top(0) = s;
                break;
@@ -582,7 +726,7 @@
        case SWF::ABC_ACTION_PUSHSTRING:
        {
                mStack.grow(1);
-               mStack.top(0) = pool_string(mStream.read_V32());
+               mStack.top(0) = pool_string(mStream->read_V32());
                break;
        }
 /// 0x2D ABC_ACTION_PUSHINT
@@ -592,7 +736,7 @@
        case SWF::ABC_ACTION_PUSHINT:
        {
                mStack.grow(1);
-               mStack.top(0) = pool_int(mStream.read_V32());
+               mStack.top(0) = pool_int(mStream->read_V32());
                break;
        }
 /// 0x2E ABC_ACTION_PUSHUINT
@@ -602,7 +746,7 @@
        case SWF::ABC_ACTION_PUSHUINT:
        {
                mStack.grow(1);
-               mStack.top(0) = pool_uint(mStream.read_V32());
+               mStack.top(0) = pool_uint(mStream->read_V32());
                break;
        }
 /// 0x2F ABC_ACTION_PUSHDOUBLE
@@ -612,7 +756,7 @@
        case SWF::ABC_ACTION_PUSHDOUBLE:
        {
                mStack.grow(1);
-               mStack.top(0) = pool_double(mStream.read_V32());
+               mStack.top(0) = pool_double(mStream->read_V32());
                break;
        }
 /// 0x30 ABC_ACTION_PUSHSCOPE
@@ -634,7 +778,7 @@
 ///  ns -- Namespace object from namespace_pool[index]
        case SWF::ABC_ACTION_PUSHNAMESPACE:
        {
-               asNamespace *ns = pool_namespace(mStream.read_V32());
+               asNamespace *ns = pool_namespace(mStream->read_V32());
                mStack.grow(1);
                mStack.top(0) = *ns;
                break;
@@ -649,21 +793,25 @@
 ///  Change at indexloc to index (as object) of the next value.
        case ABC_ACTION_HASNEXT2:
        {
-               int32_t oindex = mStream.read_V32();
-               int32_t iindex = mStream.read_V32();
-               as_object *obj = mFrame.value(oindex).to_object();
-               int32_t index = mFrame.value(iindex).to_number<int32_t>();
+               int32_t oindex = mStream->read_V32();
+               int32_t iindex = mStream->read_V32();
+               as_value &objv = mFrame.value(oindex);
+               as_value &indexv = mFrame.value(iindex);
+               ENSURE_OBJECT(objv);
+               ENSURE_NUMBER(indexv);
+               as_object *obj = objv.to_object();
+               int32_t index = indexv.to_int();
                asBinding *next = obj->next_after_index(index);
                mStack.grow(1);
                if (next)
                {
-                       mStack.top(0) = true;
+                       mStack.top(0).set_bool(true);
                        mFrame.value(oindex) = next->getOwner();
                        mFrame.value(iindex) = next->getName();
                }
                else
                {
-                       mStack.top(0) = false;
+                       mStack.top(0).set_bool(false);
                        mFrame.value(oindex).set_null();
                        mFrame.value(iindex) = 0;
                }
@@ -674,12 +822,12 @@
 /// Stack Out:
 ///  func -- the function object
 /// Do: Information about function is in the pool at index. Construct the
-///  function from this information, current scope, and base of the scope.
+///  function from this information and bind the current scope.
        case SWF::ABC_ACTION_NEWFUNCTION:
        {
                mStack.grow(1);
-               asMethod *m = pool_method(mStream.read_V32());
-               mStack.top(0) = m->construct(mCurrentScope, mBaseScope);
+               asMethod *m = pool_method(mStream->read_V32());
+               mStack.top(0) = m->construct(mCurrentScope);
                break;
        }
 /// 0x41 ABC_ACTION_CALL
@@ -692,11 +840,12 @@
 ///  value -- the value returned by obj->func(arg1, ...., argN)
        case SWF::ABC_ACTION_CALL:
        {
-               uint32_t argc = mStream.read_V32();
+               uint32_t argc = mStream->read_V32();
                as_function *f = mStack.top(argc + 1).to_function();
-               as_object *obj = mStack.top(argc).to_object();
-               mStack.top(argc + 1) = f.call(obj, mStack);
-               mStack.drop(argc + 1);
+               // argc + 1 will be dropped, and mStack.top(argc + 1)
+               // will be the top of the stack, so that is where the
+               // return value should go. (Currently it is the func)
+               pushCall(argc + 1, &mStack.top(argc + 1), asBinding(f));
                break;
        }
 /// 0x42 ABC_ACTION_CONSTRUCT
@@ -708,10 +857,9 @@
 ///  value -- obj after it has been constructed as obj(arg1, ..., argN)
        case SWF::ABC_ACTION_CONSTRUCT:
        {
-               uint32_t argc = mStream.read_V32();
+               uint32_t argc = mStream->read_V32();
                as_function *f = mStack.top(argc).to_function();
-               mStack.top(argc) = f.construct(mStack);
-               mStack.drop(argc);
+               pushCall(argc, &mStack.top(argc), asBinding(f));
                break;
        }
 /// 0x43 ABC_ACTION_CALLMETHOD
@@ -723,11 +871,18 @@
 ///  value -- the value returned by obj::'method_id'(arg1, ..., argN)
        case SWF::ABC_ACTION_CALLMETHOD:
        {
-               uint32_t dispatch_id = mStream.read_V32() - 1;
-               uint32_t argc = mStream.read_V32();
+               uint32_t dispatch_id = mStream->read_V32() - 1;
+               uint32_t argc = mStream->read_V32();
+               ENSURE_OBJECT(mStack.top(argc));
                as_object *obj = mStack.top(argc).to_object();
-               mStack.top(argc) = obj.call_dispatch(dispatch_id);
+               asBinding *b = obj.find_at_index(dispatch_id);
+               if (!b)
+               {
                mStack.drop(argc);
+                       mStack.top(0).set_undefined();
+                       break;
+               }
+               pushCall(argc + 1, &mStack.top(argc), b);
                break;
        }
 /// 0x44 ABC_ACTION_CALLSTATIC
@@ -739,10 +894,9 @@
 ///  value -- the value returned by obj->ABC::'method_id'(arg1, ..., argN)
        case SWF::ABC_ACTION_CALLSTATIC:
        {
-               asMethod *m = pool_method(mStream.read_V32());
-               uint32_t argc = mStream.read_V32();
-               mStack.top(argc) = m->call_static(mStack.top(argc), 
mStack.top(argc - 1));
-               mStack.drop(argc);
+               asMethod *m = pool_method(mStream->read_V32());
+               uint32_t argc = mStream->read_V32();
+               pushCall(argc + 1, &mStack.top(argc), asBinding(m));
                break;
        }
 /// 0x45 ABC_ACTION_CALLSUPER
@@ -759,12 +913,16 @@
        case SWF::ABC_ACTION_CALLSUPER:
        case SWF::ABC_ACTION_CALLSUPERVOID:
        {
-               asName a = mStream.read_V32();
-               mStack.drop(completeName(a));
-       
-               mStack.top(argc) = mStack.top(argc).get_named_super(a)
-                       .call_function(mStack.top(argc - 1));
-               mStack.drop(opcode == SWF::ABC_ACTION_CALL_SUPER ? argc : argc 
+ 1);
+               asName a = mStream->read_V32();
+               uint32_t argc = mStream->read_V32();
+               int dropsize = completeName(a);
+               ENSURE_OBJECT(mStack.top(argc + dropsize));
+               mStack.drop(dropsize);
+               asBinding *b = mStack.top(argc).to_object().get_named_super(a);
+               if (opcode == SWF::ABC_ACTION_CALLSUPER)
+                       pushCall(argc + 1, &mStack.top(argc), b);
+               else
+                       pushCall(argc + 1, &mIgnoreReturn, b);
                break;
        }
 /// 0x46 ABC_ACTION_CALLPROPERTY
@@ -785,23 +943,34 @@
        case SWF::ABC_ACTION_CALLPROPVOID:
        {
                bool lex_only = (opcode == SWF::ABC_ACTION_CALLPROPLEX);
-               asName a = mStream.read_V32();
-               uint32_t argc = mStream.read_V32();
+               asName a = mStream->read_V32();
+               uint32_t argc = mStream->read_V32();
                int shift = completeName(a, argc);
+               ENSURE_OBJECT(mStack.top(shift + argc));
                // Ugly setup. Any name stuff is between the args and the 
object.
-               as_object *obj = mStack.top(argc + shift).to_object();
-               mStack.top(shift + argc) = obj->call_property(a, 
mStack.top(argc));
-               mStack.drop(shift + argc);
+               if (shift)
+               {
+                       uint32_t i = argc;
+                       while (i--)
+                               mStack.top(i + shift) = mStack.top(i);
+                       mStack.drop(shift);
+               }
+               asBinding *b = 
mStack.top(argc).to_object()->getPropertyBinding(a);
+               b->setLexOnly(lex_only);
                if (opcode == SWF::ABC_ACTION_CALLPROPVOID)
-                       mStack.drop(1);
+                       pushCall(argc + 1, &mIgnoreReturn, b);
+               else
+               pushCall(argc + 1, &mStack.top(argc), b);
                break;
        }
 /// 0x47 ABC_ACTION_RETURNVOID
 /// Do: Return an undefined object up the callstack.
        case SWF::ABC_ACTION_RETURNVOID:
        {
-               mReturnStack.grow(1);
-               mReturnStack.top(0).set_undefined();
+               // Slot the return.
+               *mGlobalReturn = as_value();
+               // And restore the previous state.
+               restoreState();
                break;
        }
 /// 0x48 ABC_ACTION_RETURNVALUE
@@ -812,7 +981,10 @@
 /// Do: Return value up the callstack.
        case SWF::ABC_ACTION_RETURNVALUE:
        {
-               mReturnStack.push(mStack.pop());
+               // Slot the return.
+               *mGlobalReturn = mStack.top(0);
+               // And restore the previous state.
+               restoreState();
                break;
        }
 /// 0x49 ABC_ACTION_CONSTRUCTSUPER
@@ -822,13 +994,13 @@
 ///  arg1 ... argN -- the arg_count arguments
 /// Stack Out:
 ///  .
-///
        case SWF::ABC_ACTION_CONSTRUCTSUPER:
        {
-               uint32_t argc = mStream.read_V32();
+               uint32_t argc = mStream->read_V32();
+               ENSURE_OBJECT(mStack.top(argc));
                as_object *obj = mStack.top(argc).to_object();
-               obj->super_construct(mStack.top(argc - 1));
-               mStack.drop(argc + 1);
+               asBinding *b = obj->getSuperConstructor();
+               pushCall(argc + 1, &mIgnoreReturn, b);
                break;
        }
 /// 0x4A ABC_ACTION_CONSTRUCTPROP
@@ -842,12 +1014,21 @@
 ///   'name_offset'(arg1, ..., argN)
        case SWF::ABC_ACTION_CONSTRUCTPROP:
        {
-               asName a = mStream.read_V32();
-               uint32_t argc = mStream.read_V32();
+               asName a = mStream->read_V32();
+               uint32_t argc = mStream->read_V32();
                int shift = completeName(a, argc);
-               as_object *obj = mStack.top(argc + shift).to_object();
-               mStack.top(argc + shift) = obj->construct_property(a, 
mStack.top(argc));
-               mStack.drop(argc + shift);
+               ENSURE_OBJECT(mStack.top(argc + shift));
+               // We have to move the stack if there was a shift.
+               if (shift)
+               {
+                       uint32_t i = argc;
+                       while (i--)
+                               mStack.top(i + shift) = mStack.top(i);
+                       mStack.drop(shift);
+               }
+               as_object *obj = mStack.top(argc).to_object();
+               asBinding *b = obj->getPropertyConstructor(a);
+               pushCall(argc + 1, &mStack.top(0), b);
                break;
        }
 /// 0x55 ABC_ACTION_NEWOBJECT
@@ -866,7 +1047,7 @@
        case SWF::ABC_ACTION_NEWOBJECT:
        {
                as_object *obj = mCH->newOfType(NSV::CLASS_OBJECT);
-               uint32_t argc = mStream.read_V32();
+               uint32_t argc = mStream->read_V32();
                int i = argc;
                while (i--)
                {
@@ -888,10 +1069,13 @@
 ///  array -- an array { value_1, value_2, ..., value_n }
        case SWF::ABC_ACTION_NEWARRAY:
        {
-               uint32_t asize = mStream.read_V32();
+               uint32_t asize = mStream->read_V32();
                as_object *obj = mCH->newOfType(NSV::CLASS_ARRAY);
                as_array *array = dynamic_cast<as_array*> (obj);
-               array->load(mStack.top(asize - 1));
+               array->resize(asize);
+               uint32_t i = asize;
+               while (i--)
+                       array->set_indexed(i, mStack.value(i));
                mStack.drop(asize - 1);
                mStack.top(0) = array;
                break;
@@ -914,7 +1098,7 @@
 /// NB: This depends on scope and scope base (to determine lifetime(?))
        case SWF::ABC_ACTION_NEWCLASS:
        {
-               uint32_t cid = mStream.read_V32();
+               uint32_t cid = mStream->read_V32();
                mStack.top(0) = mCH->newOfId(cid, mStack.top(0));
                break;
        }
@@ -955,7 +1139,7 @@
        case SWF::ABC_ACTION_FINDPROPSTRICT:
        case SWF::ABC_ACTION_FINDPROPERTY:
        {
-               asName a = mStream.read_V32();
+               asName a = mStream->read_V32();
                mStack.drop(completeName(a));
                as_value v = findProperty(a);
                if ((opcode == SWF::ABC_ACTION_FINDPROPSTRICT) && 
v.is_undefined())
@@ -968,7 +1152,7 @@
 ///  def -- The definition of the name at name_id.
        case SWF::ABC_ACTION_FINDDEF:
        {
-               asName a = mStream.read_V32();
+               asName a = mStream->read_V32();
                // TODO
                break;
        }
@@ -979,7 +1163,7 @@
 ///   + 0x66 (ABC_ACTION_GETPROPERTY)
        case SWF::ABC_ACTION_GETLEX
        {
-               asName a = mStream.read_V32();
+               asName a = mStream->read_V32();
                as_value v = findProperty(a);
                if (v.is_undefined())
                        throw ASReferenceException();
@@ -1004,7 +1188,7 @@
 /// key/value is set in the dictionary obj instead.
        case SWF::ABC_ACTION_SETPROPERTY:
        {
-               asName a = mStream.read_V32();
+               asName a = mStream->read_V32();
                as_value &v = mStack.pop();
                if (!a.isRuntime())
                {
@@ -1036,7 +1220,7 @@
        case SWF::ABC_ACTION_GETLOCAL:
        {
                mStack.grow(1);
-               mStack.top(0) = mFrame.value(mStream.read_V32());
+               mStack.top(0) = mFrame.value(mStream->read_V32());
                break;
        }
 /// 0x63 ABC_ACTION_SETLOCAL
@@ -1048,7 +1232,7 @@
 ///  .
        case SWF::ABC_ACTION_SETLOCAL:
        {
-               mFrame.value(mStream.read_V32()) = mStack.top(0);
+               mFrame.value(mStream->read_V32()) = mStack.top(0);
                mStack.drop(1);
                break;
        }
@@ -1067,7 +1251,7 @@
 ///  scope -- The scope object at depth
        case SWF::ABC_ACTION_GETSCOPEOBJECT
        {
-               uint8_t depth = mStream.read_u8();
+               uint8_t depth = mStream->read_u8();
                mStack.grow(1);
                mStack.top(0) = mScopeStack(depth);
                break;
@@ -1084,7 +1268,7 @@
 /// NB: See 0x61 (ABC_ACTION_SETPROPETY) for the decision of ns/key.
        case SWF::ABC_ACTION_GETPROPERTY:
        {
-               asName a = mStream.read_V32();
+               asName a = mStream->read_V32();
                if (!a.isRuntime())
                {
                        mStack.top(0) = mStack.top(0).getProperty(a, v);
@@ -1117,7 +1301,7 @@
 ///  Set obj::(resolve)'name_id' to value, set bindings from the context.
        case SWF::ABC_ACTION_INITPROPERTY:
        {
-               asName a = mStream.read_V32();
+               asName a = mStream->read_V32();
                as_value& v = mStack.pop();
                mStack.drop(completeName(a));
                mStack.pop().to_object().setProperty(a, v, true); // true for 
init
@@ -1132,7 +1316,7 @@
 ///  truth -- True if property was deleted or did not exist, else False.
        case SWF::ABC_ACTION_DELETEPROPERTY:
        {
-               asName a = mStream.read_V32();
+               asName a = mStream->read_V32();
                mStack.drop(completeName(a));
                mStack.top(0) = mStack.top(0).deleteProperty(a);
                break;
@@ -1145,7 +1329,7 @@
 ///  slot -- obj.slots[slot_index]
        case SWF::ABC_ACTION_GETSLOT
        {
-               uint32_t sindex = mStream.read_V32();
+               uint32_t sindex = mStream->read_V32();
                if (!sindex)
                        throw ASException();
                --sindex;
@@ -1162,7 +1346,7 @@
 /// Do: obj.slots[slot_index] = value
        case SWF::ABC_ACTION_SETSLOT:
        {
-               uint32_t sindex = mStream.read_V32();
+               uint32_t sindex = mStream->read_V32();
                if (!sindex)
                        throw ASException();
                --sindex;
@@ -1179,7 +1363,7 @@
 /// NB: Deprecated
        case SWF::ABC_ACTION_GETGLOBALSLOT:
        {
-               uint32_t sindex = mStream.read_V32();
+               uint32_t sindex = mStream->read_V32();
                if (!sindex)
                        throw ASException();
                --sindex;
@@ -1197,7 +1381,7 @@
 /// NB: Deprecated
        case SWF::ABC_ACTION_SETGLOBALSLOT:
        {
-               uint32_t sindex = mStream.read_V32();
+               uint32_t sindex = mStream->read_V32();
                if (!sindex)
                        throw ASException();
                --sindex;
@@ -1316,7 +1500,7 @@
 ///  coerced_obj -- The object as the desired (resolve)'name_index' type.
        case SWF::ABC_ACTION_COERCE:
        {
-               asName a = mStream.read_V32();
+               asName a = mStream->read_V32();
                mStack.drop(completeName(a));
                mStack.top(0) = mStack.top(0).coerce(a);
                break;
@@ -1353,7 +1537,7 @@
 ///  cobj -- obj if obj is of type (resolve)'name_index', otherwise Null
        case SWF::ABC_ACTION_ASTYPE:
        {
-               asName a = mStream.read_V32();
+               asName a = mStream->read_V32();
                mStack.drop(completeName(a));
                if (!mStack.top(0).conforms_to(a)
                        mStack.top(0).set_null();
@@ -1410,7 +1594,7 @@
 /// Frame: Load i from frame_addr and increment it.
        case SWF::ABC_ACTION_INCLOCAL:
        {
-               uint32_t foff = mStream.read_V32();
+               uint32_t foff = mStream->read_V32();
                mFrame.value(foff) = mFrame.value(foff).to_number() + 1;
                break;
        }
@@ -1429,7 +1613,7 @@
 /// Frame: Load i from frame_addr and decrement it.
        case SWF::ABC_ACTION_DECLOCAL:
        {
-               uint32_t foff = mStream.read_V32();
+               uint32_t foff = mStream->read_V32();
                mFrame.value(foff) = mFrame.value(foff).to_number() - 1;
                break;
        }
@@ -1695,7 +1879,7 @@
 ///  truth -- Truth of "obj is of the type given in (resolve)'name_id'"
        case SWF::ABC_ACTION_ISTYPE:
        {
-               asName a = mStream.read_V32();
+               asName a = mStream->read_V32();
                mStack.drop(completeName(a));
                mStack.top(0).set_bool(mStack.top(0).conforms_to(a));
        }
@@ -1744,7 +1928,7 @@
 /// See: 0x92 (ABC_ACTION_INCLOCAL), but forces types to int, not double
        case SWF::ABC_ACTION_INCLOCAL_I:
        {
-               uint32_t foff = mStream.read_V32();
+               uint32_t foff = mStream->read_V32();
                mFrame.value(foff) = mFrame.value(foff).to_number<int>() + 1;
                break;
        }
@@ -1752,7 +1936,7 @@
 /// See: 0x94 (ABC_ACTION_DECLOCAL), but forces types to int, not double
        case SWF::ABC_ACTION_DECLOCAL_I:
        {
-               uint32_t foff = mStream.read_V32();
+               uint32_t foff = mStream->read_V32();
                mFrame.value(foff) = mFrame.value(foff).to_number<int>() - 1;
                break;
        }
@@ -1827,7 +2011,7 @@
 /// Do: skip ahead 7 bytes in stream
        case SWF::ABC_ACTION_DEBUG:
        {
-               seekBy(7);
+               mStream->seekBy(7);
                break;
        }
 /// 0xF0 ABC_ACTION_DEBUGLINE
@@ -1835,7 +2019,7 @@
 /// Do: Nothing, but line_number is for the debugger if wanted.
        case SWF::ABC_ACTION_DEBUGLINE:
        {
-               mStream.skip_V32();
+               mStream->skip_V32();
                break;
        }
 /// 0xF1 ABC_ACTION_DEBUGFILE
@@ -1843,7 +2027,7 @@
 /// Do: Nothing. 'name_offset' into string pool is the file name if wanted.
        case SWF::ABC_ACTION_DEBUGFILE:
        {
-               mStream.skip_V32();
+               mStream->skip_V32();
                break;
        }
 /// 0xF2 ABC_ACTION_BKPTLINE
@@ -1851,11 +2035,17 @@
 /// Do: Enter debugger if present, line_number is the line number in source.
        case SWF::ABC_ACTION_BKPTLINE:
        {
-               mStream.skip_V32();
+               mStream->skip_V32();
                break;
        }
        } // end of switch statement
-       
+       } // end of AS3 conditional
+       else // beginning of !AS3 (this code is AS2)
+       {
+       switch (opcode)
+       {
+       } // end of switch statement
+       } // end of AS2 conditional (!AS3)
        } // end of main loop
 } // end of execute function
 
@@ -1866,7 +2056,7 @@
        if (!instance.is_object())
                throw ASTypeError();
 
-       asBinding *pBinding = pDefinition->findMember(name);
+       asBinding *pBinding = pDefinition->findMember(name, instance);
        if (pBinding->isWriteOnly())
                throw ASReferenceError();
 
@@ -1878,9 +2068,9 @@
 
        // This is a getter, so we need to execute it. Even those
        // written in C++ get called like this, with pushCall handling.
-       // 1 parameter (the source), 1 value expected back.
+       // And push the instance ('this')
        mStack.push(instance);
-       pushCall(1, 1, pBinding->getGetter());
+       pushCall(1, &mStack.top(0), pBinding->getGetter());
 }
 
 void
@@ -1890,7 +2080,8 @@
        if (!instance.is_object())
                throw ReferenceError();
 
-       asBinding *pBinding = pDefinition->findMember(name);
+       asBinding *pBinding = pDefinition->findMember(name, instance);
+
        if (pBinding->isReadOnly())
                throw ASReferenceError();
 
@@ -1903,7 +2094,7 @@
        // Two parameters -- the target object, the value to set.
        mStack.push(instance);
        mStack.push(newvalue);
-       pushCall(2, 0, pBinding->getSetter());
+       pushCall(2, &mStack.top(1), pBinding->getSetter());
 }
 
 int
@@ -1952,3 +2143,90 @@
        return NULL;
 }
 
+void
+ActionMachine::pushCall(unsigned int stack_in, as_value *return_slot,
+       asBinding *pBind)
+{
+       switch (pBind->mType)
+       {
+       default:
+       case asBinding::T_ACCESS:
+       case asBinding::T_CLASS:
+               throw ASException();
+               return;
+       case asBinding::T_VALUE:
+               return_slot = pBind->getValue()->getCurrentValue();
+               return;
+       case asBinding::T_METHOD:
+               break;
+       }
+
+       asMethod *m = pBind->getMethod();
+
+       if (!(m->isNative() || m->hasBody())
+               throw ASException();
+
+       // Here is where the SafeStack shines:
+       // We set the stack the way it should be on return.
+       // If the return slot is the deepest parameter, leave room for it.
+       if (stack_in && (return_slot == &mStack.top(stack_in - 1)))
+               mStack.drop(stack_in - 1);
+       else // The return slot is somewhere else.
+               mStack.drop(stack_in);
+       // We save that state.
+       saveState();
+       // We make the stack appear empty.
+       mStack.fixDownstop();
+       // We grow to reclaim the parameters. Since this is a SafeStack, they
+       // were not lost.
+       mStack.grow(stack_in);
+
+       // Native functions have to be called now.
+       if (m->isNative())
+       {
+               return_slot = m->CallNative(mStack, mGlobalScope);
+               restoreState();
+               return;
+       }
+
+       // The scope stack should be fixed for non-native calls.
+       mScopeStack.fixDownstop();
+       mScopeStack.push(m->getActivation());
+       mCurrentScope = mScopeStack.top(0);
+
+       // We set the stream and return as given in the method and call.
+       mStream = m->getCode();
+       mGlobalReturn = return_slot;
+
+       // When control goes to the main loop of the interpreter, it will
+       // automatically start executing the method.
+}
+
+void
+ActionMachine::restoreState()
+{
+       State &s = mStateStack.top(0);
+       mStack.setAllSizes(s.mStackTotalSize, s.mStackDepth);
+       mScopeStack.setAllSizes(s.mScopeTotalSize, s.mScopeStackDepth);
+       mStream = s.mStream;
+       mDefaultXMLNamespace = s.mDefaultXMLNamespace;
+       mCurrentScope = s.mCurrentScope;
+       mGlobalReturn = s.mGlobalReturn;
+       mStateStack.drop(1);
+}
+
+void
+ActionMachine::saveState()
+{
+       mStateStack.grow(1);
+       State &s = mStateStack.top(0);
+       s.mStackDepth = mStack.getDownstop();
+       s.mStackTotalSize = mStack.getTotalSize();
+       s.mScopeStackDepth = mScopeStack.getDownstop();
+       s.mScopeTotalSize = mScopeStack.getTotalSize();
+       s.mStream = mStream;
+       s.mDefaultXMLNamespace = mDefaultXMLNamespace;
+       s.mCurrentScope = mCurrentScope;
+       s.mGlobalReturn = mGlobalReturn;
+}
+

Index: server/vm/Machine.h
===================================================================
RCS file: /sources/gnash/gnash/server/vm/Machine.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- server/vm/Machine.h 5 Oct 2007 17:48:16 -0000       1.2
+++ server/vm/Machine.h 8 Oct 2007 06:55:11 -0000       1.3
@@ -19,118 +19,11 @@
 
 #include <vector>
 
+#include "SafeStack.h"
 #include "as_value.h"
 
 namespace gnash {
 
-class ASException
-{
-};
-
-class StackException : public ASException
-{
-};
-
-template <class T>
-class Stack
-{
-public:
-       T& top(unsigned int i)
-       {
-               if (i >= mDownstop) 
-                       throw StackException();
-               unsigned int offset = mEnd - i;
-               return mData[offset >> mChunkShift][offset & mChunkMod];
-       }
-
-       T& value(unsigned int i)
-       {
-               if (i >= mDownstop)
-                       throw StackException();
-               unsigned int offset = mEnd - mDownstop + i;
-               return mData[offset >> mChunkShift][offset & mChunkMod];
-       }
-
-       void drop(unsigned int i)
-       { if (i >= mDownstop) throw StackException(); mDownstop -= i; mEnd -= 
i; }
-
-       void push(const T& t)
-       { grow(1); top(0) = t; }
-
-       void grow(unsigned int i)
-       {
-               if (((mEnd + i) >> mChunkShift) > mData.size()) 
-               {
-                       if (i > (1 << mChunkShift))
-                               throw StackException();
-                       mData.push_back(new data_vector(1 << mChunkShift));
-                       mData.back()->resize(1 << mChunkShift);
-               }
-               mDownstop += i;
-               mEnd += i;
-       }
-
-       unsigned int getDownstop() const 
-       { return mDownstop; }
-
-       unsigned int fixDownstop() 
-       { unsigned int ret = mDownstop; mDownstop = 0; return ret; }
-
-       void setDownstop(unsigned int i)
-       { if (mDownstop > mEnd) throw StackException(); mDownstop = i; }
-
-       Stack() : mData(), mDownstop(1), mEnd(1)
-       { /**/ }
-
-       ~Stack()
-       {
-               stack_type::iterator i = mData.begin();
-               for ( ; i != mData.end(); ++i)
-               {
-                       delete (*i);
-               }
-       }
-
-private:
-       typedef std::vector<T> data_vector;
-       typedef std::vector<data_vector *> stack_type;
-       stack_type mData;
-       unsigned int mDownstop;
-       unsigned int mEnd;
-
-       // If mChunkMod is not a power of 2 less 1, it will not work properly.
-       static const unsigned int mChunkShift = 6;
-       static const unsigned int mChunkMod = (1 << mChunkShift) - 1;
-};
-
-class CodeStream
-{
-public:
-       uint32_t read_V32();
-       uint8_t read_as3op();
-       std::size_t tell();
-       void seekBy(int change);
-       void seekTo(std::size_t set);
-       int32_t read_S24();
-       int8_t read_s8();
-       uint8_t read_u8();
-       void skip_V32();
-};
-
-class FunctionEntry
-{
-public:
-       FunctionEntry(Stack<as_value> *s) : mStack(s)
-       { mStackReset = s->fixDownstop(); }
-
-       ~FunctionEntry()
-       { if (mStack) mStack->setDownstop(mStackReset); }
-
-private:
-       unsigned int mStackReset;
-       Stack<as_value> *mStack;
-};
-
 /// This machine is intended to work without relying on the C++ call stack,
 /// by resetting its Stream and Stack members (actually, by limiting the stack)
 /// to make function calls, rather than calling them directly in C++.
@@ -238,21 +131,63 @@
 
        void execute_as2();
 
-       void pushCall(int param_count, int return_count, asMethod *pMethod);
+       /// push a function call to be executed next.
+       ///
+       /// Any asBinding can be pushed, and it will appropriate value
+       /// into return_slot.  This ensures that getter/setter properties
+       /// can be accessed in the same way as other properties, and hides
+       /// the difference between ActionScript methods and native C++ methods.
+       ///
+       /// @param stack_in
+       /// The initial stack size when the function is entered. This can be 
used
+       /// to pass 'this' and other parameters to the call.
+       ///
+       /// @param stack_out
+       /// The maximum number of values to leave on the stack when the function
+       /// returns.
+       ///
+       /// @param return_slot
+       /// A space for the return value. An assignment will always be made 
here,
+       /// but mVoidSlot can be used for values that will be discarded.
+       ///
+       /// @param pBind
+       /// The non-null binding.  If this is only a partial binding, then
+       /// the 'this' value will be used to complete it, when possible.
+       void pushCall(unsigned int stack_in, unsigned int stack_out,
+               as_value &return_slot, asBinding *pBind);
 
 private:
+       /// The state of the machine.
+       class State
+       {
+       public:
+               unsigned int mStackDepth;
+               unsigned int mStackTotalSize;
+               unsigned int mScopeStackDepth;
+               unsigned int mScopeTotalSize;
+               CodeStream *mStream;
+               asNamespace *mDefaultXMLNamespace;
+               asScope *mCurrentScope;
+               asValue *mGlobalReturn;
+       };
+
+       void saveState();
+       void restoreState();
+
        Stack<as_value> mStack;
-       Stack<FunctionEntry> mCallStack;
-       Stack<as_value> mFrame;
-       Stack<asScope*> mScopeStack;
-       CodeStream mStream;
+       Stack<State> mStateStack;
+       Stack<asScope> mScopeStack;
+       CodeStream *mStream;
 
        ClassHierarchy *mCH;
+       string_table& mST;
 
        asNamespace* mDefaultXMLNamespace;
        asScope *mGlobalScope;
        asScope *mCurrentScope;
-       asScope *mBaseScope;
+
+       asValue *mGlobalReturn;
+       asValue mIgnoreReturn; // Throw away returns go here.
 };
 
 } // namespace gnash

Index: server/vm/CodeStream.h
===================================================================
RCS file: /sources/gnash/gnash/server/vm/CodeStream.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- server/vm/CodeStream.h      7 Oct 2007 03:19:48 -0000       1.1
+++ server/vm/CodeStream.h      8 Oct 2007 06:55:11 -0000       1.2
@@ -60,12 +60,48 @@
                }
        }
 
+       /// Construct an empty CodeStream. Call reInitialize to fill it.
+       CodeStream() : mRaw(NULL), mRawEnd(NULL), mEnd(NULL), mOwn(false)
+       {/**/}
+
        /// Destruct a CodeStream
        ///
        /// If the stream owns the memory, it will destroy it.
        ~CodeStream()
        { if (mOwn) delete [] mRaw; }
 
+       /// Pseudo-construct a CodeStream
+       ///
+       /// This has the same parameters as the non-default constructor,
+       /// but it can be used to re-initialize the CodeStream object.
+       void reInitialize(const char *pStart, std::size_t length,
+               bool own = false)
+       {
+               if (own)
+               {
+                       // Delete mRaw if it's not large enough and it's ours.
+                       if (mOwn && length > static_cast<unsigned int> (mRawEnd 
- mRaw))
+                       {
+                               mOwn = false;
+                               delete [] mRaw;
+                       }
+                       if (!mOwn)
+                               mRaw = new char [length];
+                       memcpy(const_cast<char *>(mRaw), pStart, length);
+                       mEnd = mRawEnd = pStart + length;
+                       mCurrent = mRaw;
+                       return;
+               }
+
+               if (mOwn)
+               {
+                       // We own now, but don't want to.
+                       delete [] mRaw;
+               }
+               mCurrent = mRaw = pStart;
+               mEnd = mRawEnd = pStart + length;
+       }
+
        /// Read a variable length encoded 32 bit unsigned integer
        uint32_t read_V32()
        {
@@ -173,6 +209,11 @@
        void unset_end()
        { mEnd = mRawEnd; }
 
+       /// Take ownership of mRaw.  mRaw should be a block which can be
+       /// de-allocated by calling delete [] mRaw
+       void takeMemoryOwnership()
+       { mOwn = true; }
+
        /// Same as read_V32(), but doesn't bother with the arithmetic for
        /// calculating the value.
        void skip_V32()

Index: server/vm/SafeStack.h
===================================================================
RCS file: /sources/gnash/gnash/server/vm/SafeStack.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- server/vm/SafeStack.h       7 Oct 2007 05:09:19 -0000       1.1
+++ server/vm/SafeStack.h       8 Oct 2007 06:55:11 -0000       1.2
@@ -105,6 +105,11 @@
        /// getDownstop()
        unsigned int totalSize() const { return mEnd - 1; }
 
+       /// Set the total size and local size of the stack, for restoring a
+       /// stack through unknown changes.
+       void setAllSizes(unsigned int total, unsigned int downstop)
+       { mEnd = total + 1; mDownstop = downstop; }
+
        /// Default constructor.
        SafeStack() : mData(), mDownstop(1), mEnd(1)
        { /**/ }




reply via email to

[Prev in Thread] Current Thread [Next in Thread]