gnash-commit
[Top][All Lists]
Advanced

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

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


From: Sandro Santilli
Subject: [Gnash-commit] gnash ChangeLog server/as_environment.cpp serve...
Date: Fri, 02 Mar 2007 19:38:56 +0000

CVSROOT:        /sources/gnash
Module name:    gnash
Changes by:     Sandro Santilli <strk>  07/03/02 19:38:56

Modified files:
        .              : ChangeLog 
        server         : as_environment.cpp as_environment.h 
                         swf_function.cpp 

Log message:
                * server/as_environment.{cpp,h}, server/swf_function.cpp:
                  Registers must also be stacked between function calls,
                  like local vars.
                  With this commit I put local registers, local variables
                  and a function pointer into a CallFrame struct
                  and stack that directly. pushCallFrame() and popCallFrame()
                  now replace the add_frame_barrier/set_local_frame_top things.
                  This commit fixes the testcase under misc-mtasc.all !

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/gnash/ChangeLog?cvsroot=gnash&r1=1.2516&r2=1.2517
http://cvs.savannah.gnu.org/viewcvs/gnash/server/as_environment.cpp?cvsroot=gnash&r1=1.55&r2=1.56
http://cvs.savannah.gnu.org/viewcvs/gnash/server/as_environment.h?cvsroot=gnash&r1=1.40&r2=1.41
http://cvs.savannah.gnu.org/viewcvs/gnash/server/swf_function.cpp?cvsroot=gnash&r1=1.20&r2=1.21

Patches:
Index: ChangeLog
===================================================================
RCS file: /sources/gnash/gnash/ChangeLog,v
retrieving revision 1.2516
retrieving revision 1.2517
diff -u -b -r1.2516 -r1.2517
--- ChangeLog   2 Mar 2007 17:35:28 -0000       1.2516
+++ ChangeLog   2 Mar 2007 19:38:56 -0000       1.2517
@@ -1,5 +1,13 @@
 2007-03-02 Sandro Santilli <address@hidden>
 
+       * server/as_environment.{cpp,h}, server/swf_function.cpp:
+         Registers must also be stacked between function calls,
+         like local vars.
+         With this commit I put local registers, local variables
+         and a function pointer into a CallFrame struct
+         and stack that directly. pushCallFrame() and popCallFrame()
+         now replace the add_frame_barrier/set_local_frame_top things.
+         This commit fixes the testcase under misc-mtasc.all !
        * server/vm/ASHandlers.cpp (ActionVar):
          Ignore local variable declarations in non-function
          context, and make it an aserror.

Index: server/as_environment.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/as_environment.cpp,v
retrieving revision 1.55
retrieving revision 1.56
diff -u -b -r1.55 -r1.56
--- server/as_environment.cpp   6 Feb 2007 11:00:36 -0000       1.55
+++ server/as_environment.cpp   2 Mar 2007 19:38:56 -0000       1.56
@@ -16,7 +16,7 @@
 
 //
 
-/* $Id: as_environment.cpp,v 1.55 2007/02/06 11:00:36 strk Exp $ */
+/* $Id: as_environment.cpp,v 1.56 2007/03/02 19:38:56 strk Exp $ */
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
@@ -100,19 +100,16 @@
     // varname must be a plain variable name; no path parsing.
 {
     assert(strchr(varname.c_str(), ':') == NULL);
-    //let's allow slashes in variable names, if SWF has them..
-    //assert(strchr(varname.c_str(), '/') == NULL);
-    ////assert(strchr(varname.c_str(), '.') == NULL);
-
-    as_value   val;
 
     // Check locals for getting them
-    LocalFrames::const_iterator it = findLocal(varname, true);
-    if (it != endLocal()) {
-       // Get local var.
-       return it->m_value;
+    as_environment::frame_slot slot;
+    if ( findLocal(varname, slot, true) ) // do we really want to descend here 
??
+    {
+       return slot.m_value;
     }
 
+    as_value   val;
+
     // Check the with-stack.
     for (size_t i = with_stack.size(); i > 0; --i) {
         // const_cast needed due to non-const as_object::get_member 
@@ -190,13 +187,8 @@
        }
 
        // Check locals for deletion.
-       LocalFrames::iterator it = findLocal(varname, true);
-       if (it != endLocal())
+       if ( delLocal(varname) )
        {
-               // delete local var.
-               // This sucks, we need m_local_frames to be a list
-               // or map, NOT A VECTOR !
-               m_local_frames.erase(it);
                return true;
        }
 
@@ -275,14 +267,12 @@
 {
 
        // Check locals for setting them
-       LocalFrames::iterator it = findLocal(varname, true);
-       if (it != endLocal()) {
-               // Set local var.
-               it->m_value = val;
+       as_environment::frame_slot slot;
+       if ( setLocal(varname, val, true) )
+       {
                return;
        }
     
-
        // Check the with-stack.
        for (size_t i = with_stack.size(); i > 0; --i)
        {
@@ -313,45 +303,42 @@
 void
 as_environment::set_local(const std::string& varname, const as_value& val)
 {
+       // why would you want to set a local if there's no call frame on the
+       // stack ?
+       assert(_localFrames.size());
+
     // Is it in the current frame already?
     // TODO: should we descend to upper frames ?
     //       (probably not as we want to update it)
-    LocalFrames::iterator it = findLocal(varname), itEnd=endLocal();
-    if (it == itEnd) {
+       as_environment::frame_slot slot;
+       if ( setLocal(varname, val, false) )
+       {
+               return;
+       }
+       else
+       {
        // Not in frame; create a new local var.
+               assert(_localFrames.size());
        assert(varname.length() > 0);   // null varnames are invalid!
-       m_local_frames.push_back(frame_slot(varname, val));
-    } else {
-       // In frame already; modify existing var.
-       it->m_value = val;
+               LocalVars& locals = _localFrames.back().locals;
+               locals.push_back(as_environment::frame_slot(varname, val));
     }
 }
        
-// Add a local var with the given name and value to our
-// current local frame.  Use this when you know the var
-// doesn't exist yet, since it's faster than set_local();
-// e.g. when setting up args for a function.
-void
-as_environment::add_local(const std::string& varname, const as_value& val)
-{
-    assert(varname.length() > 0);
-    m_local_frames.push_back(frame_slot(varname, val));
-}
-
 // Create the specified local var if it doesn't exist already.
 void
 as_environment::declare_local(const std::string& varname)
 {
-    // Is it in the current frame already?
     // TODO: should we descend to upper frames ?
     //       (probably not as we want to declare it)
-    LocalFrames::const_iterator it = findLocal(varname), itEnd=endLocal();
-    if (it == itEnd) {
+       as_environment::frame_slot slot;
+       if ( ! findLocal(varname, slot, false) )
+       {
        // Not in frame; create a new local var.
+               assert(_localFrames.size());
        assert(varname.length() > 0);   // null varnames are invalid!
-       m_local_frames.push_back(frame_slot(varname, as_value()));
-    } else {
-       // In frame already; don't mess with it.
+               LocalVars& locals = _localFrames.back().locals;
+               locals.push_back(as_environment::frame_slot(varname, 
as_value()));
     }
 }
        
@@ -372,26 +359,6 @@
     _variables[varname] = val;
 }
 
-as_value&
-as_environment::local_register(uint8_t n)
-{
-       assert( n < m_local_register.size() );
-       return m_local_register[n];
-}
-
-void
-as_environment::drop_local_registers(unsigned int register_count)
-{
-       assert(register_count <= m_local_register.size());
-       m_local_register.resize(m_local_register.size() - register_count);
-}
-
-void
-as_environment::add_local_registers(unsigned int register_count)
-{
-       m_local_register.resize(m_local_register.size() + register_count);
-}
-
 /* public static */
 bool
 as_environment::parse_path(const std::string& var_path,
@@ -850,16 +817,40 @@
        return VM::get().getSWFVersion();
 }
 
+static void
+dump(const as_environment::Registers& r, std::ostream& out) 
+{
+       for (size_t i=0; i<r.size(); ++i)
+       {
+               if (i) out << ", ";
+               out << '"' << r[i].to_string() << '"';
+       }
+}
+
 void
 as_environment::dump_local_registers(std::ostream& out) const
 {
-       size_t n=m_local_register.size();
-       if ( ! n ) return;
+       if ( _localFrames.empty() ) return;
        out << "Local registers: ";
-       for (unsigned int i=0; i<n; i++)
+       for (CallStack::const_iterator it=_localFrames.begin(),
+                       itEnd=_localFrames.end();
+                       it != itEnd; ++it)
        {
-               if (i) out << " | ";
-               out << '"' << m_local_register[i].to_string() << '"';
+               if ( it != _localFrames.begin() ) out << " | ";
+               dump(it->registers, out);
+       }
+       out << std::endl;
+}
+
+static void
+dump(const as_environment::LocalVars& locals, std::ostream& out)
+{
+       for (size_t i=0; i<locals.size(); ++i)
+       {
+               const as_environment::frame_slot& slot = locals[i];
+               if (i) out << ", ";
+               // TODO: define output operator for as_value !
+               out << slot.m_name << "==" << slot.m_value;
        }
        out << std::endl;
 }
@@ -867,19 +858,14 @@
 void
 as_environment::dump_local_variables(std::ostream& out) const
 {
-       out << "Local variables:";
-       size_t cnt=0;
-       for (size_t i = 0, n=m_local_frames.size(); i < n; ++i)
-       {
-               const frame_slot& slot = m_local_frames[i];
-               if ( slot.m_name.empty() ) {
-                       out << " |";
-                       cnt=0;
-               } else {
-                       if (cnt) out << "," << slot.m_name;
-                       else out << " " << slot.m_name;
-                       ++cnt;
-               }
+       if ( _localFrames.empty() ) return;
+       out << "Local variables: ";
+       for (CallStack::const_iterator it=_localFrames.begin(),
+                       itEnd=_localFrames.end();
+                       it != itEnd; ++it)
+       {
+               if ( it != _localFrames.begin() ) out << " | ";
+               dump(it->locals, out);
        }
        out << std::endl;
 }
@@ -901,26 +887,118 @@
 }
 
 /*private*/
-as_environment::LocalFrames::iterator
-as_environment::findLocal(const std::string& varname, bool descend)
+bool
+as_environment::findLocal(const std::string& varname, 
as_environment::frame_slot& ret, bool descend)
+{
+       if ( _localFrames.empty() ) return false;
+       if ( ! descend ) return findLocal(_localFrames.back().locals, varname, 
ret);
+
+       for (CallStack::reverse_iterator it=_localFrames.rbegin(),
+                       itEnd=_localFrames.rend();
+                       it != itEnd;
+                       ++it)
+       {
+               LocalVars& locals = it->locals;
+               if ( findLocal(locals, varname, ret) )
+               {
+                       return true;
+               }
+       }
+       return false;
+}
+
+/* static private */
+bool
+as_environment::findLocal(LocalVars& locals, const std::string& name, 
as_environment::frame_slot& ret)
 {
-       for (int i = m_local_frames.size() - 1; i >= 0; i--)
+       for (size_t i=0; i<locals.size(); ++i)
        {
-               const frame_slot&       slot = m_local_frames[i];
-               if (!descend && slot.m_name.length() == 0)
+               const as_environment::frame_slot& slot = locals[i];
+               if (slot.m_name == name)
                {
-                       // End of local frame; stop looking.
-                       return endLocal();
+                       ret = slot;
+                       return true;
+               }
                }
-               else if (slot.m_name == varname)
+       return false;
+}
+
+/* static private */
+bool
+as_environment::delLocal(LocalVars& locals, const std::string& varname)
+{
+       for (size_t i=0; i<locals.size(); ++i)
                {
-                       // Found it.
-                       return beginLocal()+i;
+               const as_environment::frame_slot& slot = locals[i];
+               if (slot.m_name == varname)
+               {
+                       locals.erase(locals.begin()+i);
+                       return true;
                }
        }
-       return endLocal();
+       return false;
 }
 
+/* private */
+bool
+as_environment::delLocal(const std::string& varname, bool descend)
+{
+       if ( _localFrames.empty() ) return false;
+       if ( ! descend ) return delLocal(_localFrames.back().locals, varname);
+
+       for (CallStack::reverse_iterator it=_localFrames.rbegin(),
+                       itEnd=_localFrames.rend();
+                       it != itEnd;
+                       ++it)
+       {
+               LocalVars& locals = it->locals;
+               if ( delLocal(locals, varname) )
+               {
+                       return true;
+               }
+       }
+       return false;
+}
+
+/* private */
+bool
+as_environment::setLocal(const std::string& varname, const as_value& val, bool 
descend)
+{
+       if ( _localFrames.empty() ) return false;
+       if ( ! descend ) return setLocal(_localFrames.back().locals, varname, 
val);
+
+       for (CallStack::reverse_iterator it=_localFrames.rbegin(),
+                       itEnd=_localFrames.rend();
+                       it != itEnd;
+                       ++it)
+       {
+               LocalVars& locals = it->locals;
+               if ( setLocal(locals, varname, val) )
+               {
+                       return true;
+               }
+       }
+       return false;
+}
+
+/* static private */
+bool
+as_environment::setLocal(LocalVars& locals,
+               const std::string& varname, const as_value& val)
+{
+       for (size_t i=0; i<locals.size(); ++i)
+       {
+               as_environment::frame_slot& slot = locals[i];
+               if (slot.m_name == varname)
+               {
+                       slot.m_value = val;
+                       return true;
+               }
+       }
+       return false;
+}
+
+
 void
 as_environment::padStack(size_t offset, size_t count)
 {

Index: server/as_environment.h
===================================================================
RCS file: /sources/gnash/gnash/server/as_environment.h,v
retrieving revision 1.40
retrieving revision 1.41
diff -u -b -r1.40 -r1.41
--- server/as_environment.h     6 Feb 2007 17:46:25 -0000       1.40
+++ server/as_environment.h     2 Mar 2007 19:38:56 -0000       1.41
@@ -14,7 +14,7 @@
 // along with this program; if not, write to the Free Software
 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
-/* $Id: as_environment.h,v 1.40 2007/02/06 17:46:25 rsavoye Exp $ */
+/* $Id: as_environment.h,v 1.41 2007/03/02 19:38:56 strk Exp $ */
 
 #ifndef GNASH_AS_ENVIRONMENT_H
 #define GNASH_AS_ENVIRONMENT_H
@@ -254,7 +254,14 @@
        /// Use this when you know the var
        /// doesn't exist yet, since it's faster than set_local();
        /// e.g. when setting up args for a function.
-       void    add_local(const std::string& varname, const as_value& val);
+       ///
+       void add_local(const std::string& varname, const as_value& val)
+       {
+               assert(varname.length() > 0);   // null varnames are invalid!
+               assert(_localFrames.size());
+               LocalVars& locals = _localFrames.back().locals;
+               locals.push_back(frame_slot(varname, val));
+       }
 
        /// Create the specified local var if it doesn't exist already.
        void    declare_local(const std::string& varname);
@@ -274,52 +281,46 @@
        ///
        void    set_member(const std::string& varname, const as_value& val);
 
-       // Parameter/local stack frame management.
-       int     get_local_frame_top() const { return m_local_frames.size(); }
-       void    set_local_frame_top(unsigned int t) {
-               assert(t <= m_local_frames.size());
-               m_local_frames.resize(t);
-       }
-       void    add_frame_barrier() { m_local_frames.push_back(frame_slot()); }
-
        /// Add 'count' local registers (add space to end)
        //
        /// Local registers are only meaningful within a function2 context.
        ///
-       void    add_local_registers(unsigned int register_count);
-
-       /// Drop 'count' local registers (drop space from end)
-       //
-       /// Local registers are only meaningful within a function2 context.
-       ///
-       void    drop_local_registers(unsigned int register_count);
-
-       /// Return the number of local registers currently available
-       //
-       /// Local registers are only meaningful within a function2 context.
-       ///
-       size_t num_local_registers() const {
-               return m_local_register.size();
+       void add_local_registers(unsigned int register_count)
+       {
+               assert(_localFrames.size());
+               return _localFrames.back().registers.resize(register_count);
        }
 
-       /// Set number of local registers.
+       /// Return the number of local registers currently available
        //
        /// Local registers are only meaningful within a function2 context.
        ///
-       void resize_local_registers(unsigned int register_count) {
-               m_local_register.resize(register_count);
+       size_t num_local_registers() const
+       {
+               assert(_localFrames.size());
+               return _localFrames.back().registers.size();
        }
 
        /// Return a reference to the Nth local register.
        //
        /// Local registers are only meaningful within a function2 context.
        ///
-       as_value& local_register(uint8_t n);
+       as_value& local_register(uint8_t n)
+       {
+               assert(_localFrames.size());
+               return _localFrames.back().registers[n];
+       }
 
         /// Set the Nth local register to something
-        void set_local_register(uint8_t n, as_value &val) {
-           if (n <= m_local_register.size()) {
-               m_local_register[n] = val;
+        void set_local_register(uint8_t n, as_value &val)
+       {
+               if (_localFrames.size() )
+               {
+                       Registers& registers = _localFrames.back().registers;
+                       if ( n < registers.size() )
+                       {
+                               registers[n] = val;
+                       }
            }
        }
 
@@ -415,25 +416,64 @@
        /// The variables container (case-insensitive)
        typedef std::map<std::string, as_value, StringNoCaseLessThen> Variables;
 
-       /// The locals container (TODO: use a std::map here !)
-       typedef std::vector<frame_slot> LocalFrames;
+       /// The locals container 
+       typedef std::vector<frame_slot> LocalVars;
+
+       typedef std::vector<as_value> Registers;
+
+       struct CallFrame
+       {
+               CallFrame(as_function* funcPtr)
+                       :
+                       func(funcPtr)
+               {}
+
+               /// function use this 
+               LocalVars locals;
 
-       /// Local variables.
+               /// function2 also use this
+               Registers registers;
+
+               as_function* func;
+       };
+
+       /// Push a frame on the calls stack.
        //
-       /// TODO: make private. currently an hack in timers.cpp prevents this.
+       /// This should happen right before calling an ActionScript
+       /// function. Function local registers and variables
+       /// must be set *after* pushCallFrame has been invoked
+       ///
+       /// Call popCallFrame() at ActionScript function return.
+       ///
+       /// @param func
+       ///     The function being called
        ///
-       LocalFrames m_local_frames;
+       void pushCallFrame(as_function* func)
+       {
+               _localFrames.push_back(CallFrame(func));
+       }
+
+       /// Remove current call frame from the stack
+       //
+       /// This should happen when an ActionScript function returns.
+       ///
+       void popCallFrame()
+       {
+               assert(_localFrames.size());
+               _localFrames.pop_back();
+       }
 
 private:
 
+       typedef std::vector<CallFrame> CallStack;
+               
+       CallStack _localFrames;
+
        /// Variables available in this environment
        Variables _variables;
 
        as_value m_global_register[4];
 
-       /// function2 uses this (could move to swf_function2 class)
-       std::vector<as_value>   m_local_register;
-
        /// Movie target. 
        character* m_target;
 
@@ -447,38 +487,90 @@
 
 
        /// \brief
-       /// Return an iterator to the local variable with given name,
-       /// or an iterator to it's end() iterator if none found
+       /// Get a local variable given its name,
        //
        /// @param varname
        ///     Name of the local variable
        ///
+       /// @param ret
+       ///     If a variable is found it's assigned to this parameter.
+       ///     Untouched if the variable is not found.
+       ///
        /// @param descend
-       ///     If true the seek don't stop at local frame top, but
+       ///     If true the seek don't stop at current call frame, but
        ///     descends in upper frames. By default it is false.
        ///
-       LocalFrames::iterator findLocal(const std::string& varname, bool 
descend=false);
+       /// @return true if the variable was found, false otherwise
+       ///
+       bool findLocal(const std::string& varname, frame_slot& ret, bool 
descend=false);
 
-       LocalFrames::const_iterator findLocal(const std::string& varname, bool 
descend=false) const
+       bool findLocal(const std::string& varname, frame_slot& ret, bool 
descend=false) const
        {
-               return const_cast<as_environment*>(this)->findLocal(varname, 
descend);
+               return const_cast<as_environment*>(this)->findLocal(varname, 
ret, descend);
        }
 
-       LocalFrames::iterator endLocal() {
-               return m_local_frames.end();
-       }
+       /// Find a variable in the given LocalVars
+       //
+       /// @param varname
+       ///     Name of the local variable
+       ///
+       /// @param ret
+       ///     If a variable is found it's assigned to this parameter.
+       ///     Untouched if the variable is not found.
+       ///
+       /// @return true if the variable was found, false otherwise
+       ///
+       static bool findLocal(LocalVars& locals, const std::string& name, 
frame_slot& ret);
 
-       LocalFrames::const_iterator endLocal() const {
-               return m_local_frames.end();
-       }
+       /// Delete a local variable
+       //
+       /// @param varname
+       ///     Name of the local variable
+       ///
+       /// @param descend
+       ///     If true the seek don't stop at current call frame, but
+       ///     descends in upper frames. By default it is false.
+       ///
+       /// @return true if the variable was found, false otherwise
+       ///
+       bool delLocal(const std::string& varname, bool descend=false);
 
-       LocalFrames::iterator beginLocal() {
-               return m_local_frames.begin();
-       }
+       /// Delete a variable from the given LocalVars
+       //
+       /// @param varname
+       ///     Name of the local variable
+       ///
+       /// @return true if the variable was found, false otherwise
+       ///
+       static bool delLocal(LocalVars& locals, const std::string& varname);
 
-       LocalFrames::const_iterator beginLocal() const {
-               return m_local_frames.begin();
-       }
+       /// Set a local variable, if it exists.
+       //
+       /// @param varname
+       ///     Name of the local variable
+       ///
+       /// @param val
+       ///     Value to assign to the variable
+       ///
+       /// @param descend
+       ///     If true the seek don't stop at current call frame, but
+       ///     descends in upper frames. By default it is false.
+       ///
+       /// @return true if the variable was found, false otherwise
+       ///
+       bool setLocal(const std::string& varname, const as_value& val, bool 
descend=false);
+
+       /// Set a variable from the given LocalVars, if it exists.
+       //
+       /// @param varname
+       ///     Name of the local variable
+       ///
+       /// @param val
+       ///     Value to assign to the variable
+       ///
+       /// @return true if the variable was found, false otherwise
+       ///
+       static bool setLocal(LocalVars& locals, const std::string& varname, 
const as_value& val);
 
        /// Find an object referenced by the given path (slash syntax).
        //

Index: server/swf_function.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/swf_function.cpp,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -b -r1.20 -r1.21
--- server/swf_function.cpp     28 Feb 2007 07:46:23 -0000      1.20
+++ server/swf_function.cpp     2 Mar 2007 19:38:56 -0000       1.21
@@ -178,8 +178,7 @@
 #endif
 
        // Set up local stack frame, for parameters and locals.
-       int     local_stack_top = our_env->get_local_frame_top();
-       our_env->add_frame_barrier();
+       our_env->pushCallFrame(this);
 
        if (m_is_function2 == false)
        {
@@ -320,14 +319,7 @@
        ActionExec exec(*this, *our_env, fn.result);
        exec();
 
-       // Clean up stack frame.
-       our_env->set_local_frame_top(local_stack_top);
-
-       if (m_is_function2)
-       {
-               // Clean up the local registers.
-               our_env->drop_local_registers(m_local_register_count);
-       }
+       our_env->popCallFrame();
 }
 
 void




reply via email to

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