gnash-commit
[Top][All Lists]
Advanced

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

[Gnash-commit] gnash ChangeLog server/array.cpp server/array.h...


From: Sandro Santilli
Subject: [Gnash-commit] gnash ChangeLog server/array.cpp server/array.h...
Date: Wed, 19 Mar 2008 11:40:18 +0000

CVSROOT:        /sources/gnash
Module name:    gnash
Changes by:     Sandro Santilli <strk>  08/03/19 11:40:16

Modified files:
        .              : ChangeLog 
        server         : array.cpp array.h 
        testsuite/actionscript.all: array.as 

Log message:
                * server/array.{cpp,h}: use boost's mapped_vector for a sparse
                  array implementation. Saves space at some cpu cycles till all
                  gaps are filled (which happens by most modifiers, as an 
expected
                  behaviour :/).
                * testsuite/actionscript.all/array.as: successes in gaps 
filling.

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/gnash/ChangeLog?cvsroot=gnash&r1=1.5974&r2=1.5975
http://cvs.savannah.gnu.org/viewcvs/gnash/server/array.cpp?cvsroot=gnash&r1=1.96&r2=1.97
http://cvs.savannah.gnu.org/viewcvs/gnash/server/array.h?cvsroot=gnash&r1=1.44&r2=1.45
http://cvs.savannah.gnu.org/viewcvs/gnash/testsuite/actionscript.all/array.as?cvsroot=gnash&r1=1.57&r2=1.58

Patches:
Index: ChangeLog
===================================================================
RCS file: /sources/gnash/gnash/ChangeLog,v
retrieving revision 1.5974
retrieving revision 1.5975
diff -u -b -r1.5974 -r1.5975
--- ChangeLog   19 Mar 2008 10:13:38 -0000      1.5974
+++ ChangeLog   19 Mar 2008 11:40:12 -0000      1.5975
@@ -1,5 +1,13 @@
 2008-03-18 Sandro Santilli <address@hidden>
 
+       * server/array.{cpp,h}: use boost's mapped_vector for a sparse
+         array implementation. Saves space at some cpu cycles till all
+         gaps are filled (which happens by most modifiers, as an expected
+         behaviour :/).
+       * testsuite/actionscript.all/array.as: successes in gaps filling.
+
+2008-03-18 Sandro Santilli <address@hidden>
+
        * testsuite/actionscript.all/array.as:
          test splice() and members access on a sparse array.
 

Index: server/array.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/array.cpp,v
retrieving revision 1.96
retrieving revision 1.97
diff -u -b -r1.96 -r1.97
--- server/array.cpp    18 Mar 2008 11:26:54 -0000      1.96
+++ server/array.cpp    19 Mar 2008 11:40:15 -0000      1.97
@@ -511,26 +511,18 @@
        // extract fUniqueSort and fReturnIndexedArray from first flag
        if (it != itEnd)
        {
-               as_array_object::ValOrNone v = *it++;
-               if ( v.which() == as_array_object::itemValue )
-               {
-                       boost::uint8_t flag = 
static_cast<boost::uint8_t>(boost::get<as_value>(v).to_number());
+               boost::uint8_t flag = 
static_cast<boost::uint8_t>((*it++).to_number());
                        flag = flag_preprocess(flag, uniq, index);
                        flgs.push_back(flag);
                }
-       }
 
        while (it != itEnd)
        {
-               as_array_object::ValOrNone v = *it++;
-               if ( v.which() == as_array_object::itemValue )
-               {
-                       boost::uint8_t flag = 
static_cast<boost::uint8_t>(boost::get<as_value>(v).to_number());
+               boost::uint8_t flag = 
static_cast<boost::uint8_t>((*it++).to_number());
                        flag &= ~(as_array_object::fReturnIndexedArray);
                        flag &= ~(as_array_object::fUniqueSort);
                        flgs.push_back(flag);
                }
-       }
        return flgs;
 }
 
@@ -568,10 +560,7 @@
        for (const_iterator it = elements.begin();
                it != elements.end(); ++it)
        {
-               if ( it->which() == itemValue )
-               {
-                       
indexed_elements.push_back(indexed_as_value(boost::get<as_value>(*it), i++));
-               }
+               indexed_elements.push_back(indexed_as_value(*it, i++));
        }
        return indexed_elements;
 }
@@ -606,20 +595,25 @@
 void
 as_array_object::push(const as_value& val)
 {
-       elements.push_back(val);
+        size_t s=elements.size();
+        elements.resize(s+1);
+        elements[s] = val;
 }
 
 void
 as_array_object::unshift(const as_value& val)
 {
-       elements.push_front(val);
+        shiftElementsRight(1);
+        elements[0] = val;
 }
 
 as_value
 as_array_object::pop()
 {
        // If the array is empty, report an error and return undefined!
-       if ( elements.empty() ) 
+       size_t sz = elements.size();
+
+       if ( ! sz )
        {
                IF_VERBOSE_ASCODING_ERRORS(
                log_aserror(_("tried to pop element from back of empty array, 
returning undef"));
@@ -627,11 +621,9 @@
                return as_value(); // undefined
        }
 
-       ValOrNone last = elements.back();
-       as_value ret;
-       if ( last.which() == itemValue ) ret = boost::get<as_value>(last);
-       else log_error("Last element of Array (on pop) is not a value");
-       elements.pop_back();
+       --sz;
+       as_value ret = elements[sz];
+       elements.resize(sz);
 
        return ret;
 }
@@ -639,8 +631,10 @@
 as_value
 as_array_object::shift()
 {
+       size_t sz = elements.size();
+
        // If the array is empty, report an error and return undefined!
-       if ( elements.empty() ) 
+       if ( ! sz )
        {
                IF_VERBOSE_ASCODING_ERRORS(
                log_aserror(_("tried to shift element from front of empty 
array, returning undef"));
@@ -648,10 +642,8 @@
                return as_value(); // undefined
        }
 
-       ValOrNone first = elements.front();
-       as_value ret;
-       if ( first.which() == itemValue ) ret = boost::get<as_value>(first);
-       elements.pop_front();
+       as_value ret = elements[0];
+       shiftElementsLeft(1);
 
        return ret;
 }
@@ -659,8 +651,20 @@
 void
 as_array_object::reverse()
 {
-       // Reverse the deque elements
-       std::reverse(elements.begin(), elements.end());
+       size_t sz = elements.size();
+       if ( sz < 2 ) return; // nothing to do (CHECKME: might be a single 
hole!)
+
+       // We create another container, as we want to fill the gaps
+       // There could likely be an in-place version for this, but
+       // filling the gaps would need more care
+       container newelements(sz);
+
+       for (size_t i=0, n=sz-1; i<sz; ++i, --n)
+       {
+               newelements[i] = elements[n];
+       }
+
+       elements = newelements;
 }
 
 std::string
@@ -674,25 +678,19 @@
        // We should change output based on SWF version --strk 2006-04-28
 
        std::string temp;
+
        //std::string temp = "("; // SWF > 7
 
-       int swfversion = _vm.getSWFVersion();
+       size_t sz = elements.size();
 
-       if ( ! elements.empty() ) 
+       if ( sz ) 
        {
-               bool printed=false;
-
-               const_iterator it=elements.begin(), itEnd=elements.end();
+               int swfversion = _vm.getSWFVersion();
                
-               while ( it != itEnd )
+               for (size_t i=0; i<sz; ++i)
                {
-                       ValOrNone v = *it++;
-                       if ( printed ) temp += separator;
-                       if ( v.which() == itemValue )
-                               temp += 
boost::get<as_value>(v).to_string_versioned(swfversion);
-                       else
-                               temp += 
as_value().to_string_versioned(swfversion);
-                       printed=true;
+                       if ( i ) temp += separator;
+                       temp += elements[i].to_string_versioned(swfversion);
                }
        }
 
@@ -705,8 +703,8 @@
 void
 as_array_object::concat(const as_array_object& other)
 {
-       elements.insert(elements.end(), other.elements.begin(),
-               other.elements.end());
+       for (size_t i=0, e=other.size(); i<e; i++)
+               push(other.at(i));
 }
 
 std::string
@@ -722,18 +720,10 @@
 }
 
 as_value
-as_array_object::at(unsigned int index)
+as_array_object::at(unsigned int index) const
 {
-       if ( index > elements.size()-1 )
-       {
-               return as_value();
-       }
-       else
-       {
-               ValOrNone v = elements[index];
-               if ( v.which() != itemValue ) return as_value();
-               return boost::get<as_value>(v);
-       }
+       if ( index > elements.size()-1 ) return as_value();
+       else return elements[index];
 }
 
 std::auto_ptr<as_array_object>
@@ -762,59 +752,14 @@
 
 }
 
-std::auto_ptr<as_array_object>
-as_array_object::splice(unsigned start, unsigned len,
-               const std::vector<as_value>& replace)
-{
-       assert(len <= size()-start);
-       assert(start <= size());
-
-#ifdef GNASH_DEBUG
-       std::stringstream ss;
-       ss << "Array.splice(" << start << ", " << len << ", ";
-       std::ostream_iterator<as_value> ostrIter(ss, "," ) ;
-       std::copy(replace.begin(), replace.end(), ostrIter);
-        ss << ") called";
-       log_debug("%s", ss.str().c_str());
-       log_debug(_("Current array is %s"), toString().c_str());
-#endif
-
-       container::iterator itStart = elements.begin()+start;
-       container::iterator itEnd = itStart+len;
-
-       // This will be returned...
-       std::auto_ptr<as_array_object> ret(new as_array_object);
-       
-       // If something has to be removed do it and assign
-       // to the returned object
-       if ( itStart != itEnd )
-       {
-               ret->elements.assign(itStart, itEnd);
-
-               elements.erase(itStart, itEnd);
-       }
-
-       // Now insert the new stuff, if needed
-       if ( ! replace.empty() )
-       {
-               container::iterator itStart = elements.begin()+start;
-               elements.insert(itStart, replace.begin(), replace.end());
-       }
-
-       return ret;
-}
-
 bool
 as_array_object::removeFirst(const as_value& v)
 {
        for (iterator it = elements.begin(); it != elements.end(); ++it)
        {
-               ValOrNone x = *it;
-               if ( x.which() != itemValue ) continue;
-               
-               if ( v.equals(boost::get<as_value>(x)) )
+               if ( v.equals(*it) )
                {
-                       elements.erase(it);
+                       splice(it.index(), 1);
                        return true;
                }
        }
@@ -828,12 +773,14 @@
 {
        // an index has been requested
        int index = index_requested(name);
-       if ( index >= 0 && (unsigned int)index < elements.size() )
+
+       if ( index >= 0 ) // a valid index was requested
        {
-               ValOrNone x = elements[index];
-               if ( x.which() == itemValue )
+               size_t i = index;
+               const_iterator it = elements.find(i);
+               if ( it != elements.end() && it.index() == i )
                {
-                       *val = boost::get<as_value>(x); 
+                       *val = *it;
                        return true;
                }
        }
@@ -871,7 +818,7 @@
        // if we were sent a valid array index and not a normal member
        if (index >= 0)
        {
-               if (index >= int(elements.size()))
+               if ( size_t(index) >= elements.size() )
                {
                        // if we're setting index (x), the vector
                        // must be size (x+1)
@@ -883,6 +830,7 @@
                return;
        }
 
+
        as_object::set_member_default(name,val, nsname);
 }
 
@@ -959,9 +907,8 @@
                replace.push_back(fn.arg(i));
        }
 
-       std::auto_ptr<as_array_object> spliced ( array->splice(startoffset, 
len, replace) );
-
-       boost::intrusive_ptr<as_object> ret = spliced.release();
+       as_array_object* ret = new as_array_object();
+       array->splice(startoffset, len, &replace, ret);
 
        return as_value(ret);
 }
@@ -1084,13 +1031,9 @@
                for (as_array_object::const_iterator it = props->begin();
                        it != props->end(); ++it)
                {
-                       as_array_object::ValOrNone v = *it;
-                       if ( v.which() == as_array_object::itemValue )
-                       {
-                               string_table::key s = 
st.find(PROPNAME(boost::get<as_value>(v).to_string_versioned(sv)));
+                       string_table::key s = 
st.find(PROPNAME((*it).to_string_versioned(sv)));
                                prp.push_back(s);
                        }
-               }
                
                // case: sortOn(["prop1", "prop2"])
                if (fn.nargs == 1)
@@ -1306,7 +1249,10 @@
        boost::intrusive_ptr<as_array_object> array = 
ensureType<as_array_object>(fn.this_ptr);
 
        // use copy ctor
-       as_array_object* newarray = new as_array_object(*array);
+       as_array_object* newarray = new as_array_object();
+
+       for (size_t i=0, e=array->size(); i<e; i++)
+               newarray->push(array->at(i));
 
        for (unsigned int i=0; i<fn.nargs; i++)
        {
@@ -1571,13 +1517,87 @@
        // TODO: only actually defined elements should be pushed on the env
        //       but we currently have no way to distinguish between defined
        //       and non-defined elements
-       for (unsigned int i=0; i<size(); ++i)
+       for (const_iterator it = elements.begin(),
+               itEnd = elements.end(); it != itEnd; ++it)
        {
-               if ( elements[i].which() == itemValue )
+                       env.push(as_value(it.index()));
+       }
+}
+
+void
+as_array_object::shiftElementsLeft(unsigned int count)
+{
+       container& v = elements;
+
+       if ( count >= v.size() )
                {
-                       env.push(as_value(i));
+               v.clear();
+               return;
                }
+
+       for (unsigned int i=0; i<count; ++i) v.erase_element(i);
+
+       for (container::iterator i=v.begin(), e=v.end(); i!=e; ++i)
+       {
+               int currentIndex = i.index();
+               int newIndex = currentIndex-count;
+               v[newIndex] = *i;
        }
+       v.resize(v.size()-count);
+}
+
+void
+as_array_object::shiftElementsRight(unsigned int count)
+{
+       container& v = elements;
+
+       v.resize(v.size()+count);
+       for (container::reverse_iterator i=v.rbegin(), e=v.rend(); i!=e; ++i)
+       {
+               int currentIndex = i.index();
+               int newIndex = currentIndex+count;
+               v[newIndex] = *i;
+       }
+       while (count--) v.erase_element(count);
+}
+
+void
+as_array_object::splice(unsigned int start, unsigned int count, const 
std::vector<as_value>* replace, as_array_object* receive)
+{
+       size_t sz = elements.size();
+
+       assert ( start <= sz );
+       assert ( start+count <= sz );
+
+       size_t newsize = sz-count;
+       if ( replace ) newsize += replace->size();
+       container newelements(newsize);
+
+       size_t ni=0;
+
+       // add initial portion
+       for (size_t i=0; i<start; ++i )
+               newelements[ni++] = elements[i];
+
+       // add replacement, if any
+       if ( replace )
+       {
+               for (size_t i=0, e=replace->size(); i<e; ++i) 
+                       newelements[ni++] = replace->at(i);
+       }       
+
+       // add final portion
+       for (size_t i=start+count; i<sz; ++i )
+               newelements[ni++] = elements[i];
+
+       // push trimmed data to the copy array, if any
+       if ( receive )
+       {
+               for (size_t i=start; i<start+count; ++i )
+                       receive->push(elements[i]);
+       }
+
+       elements = newelements;
 }
 
 #ifdef GNASH_USE_GC
@@ -1586,11 +1606,7 @@
 {
        for (const_iterator i=elements.begin(), e=elements.end(); i!=e; ++i)
        {
-               ValOrNone v = *i;
-               if ( v.which() == itemValue )
-               {
-                       boost::get<as_value>(v).setReachable();
-               }
+               (*i).setReachable();
        }
        markAsObjectReachable();
 }

Index: server/array.h
===================================================================
RCS file: /sources/gnash/gnash/server/array.h,v
retrieving revision 1.44
retrieving revision 1.45
diff -u -b -r1.44 -r1.45
--- server/array.h      18 Mar 2008 11:26:54 -0000      1.44
+++ server/array.h      19 Mar 2008 11:40:15 -0000      1.45
@@ -23,6 +23,7 @@
 #include <deque>
 #include <vector>
 #include <memory> // for auto_ptr
+#include <boost/numeric/ublas/vector_sparse.hpp>
 
 #include <string>
 
@@ -62,9 +63,10 @@
 
        enum { itemBlank, itemValue };
 
-       typedef boost::variant<blank, as_value> ValOrNone;
+       //typedef boost::variant<blank, as_value> ValOrNone;
+       //typedef std::deque<ValOrNone> container;
 
-       typedef std::deque<ValOrNone> container;
+       typedef boost::numeric::ublas::mapped_vector<as_value> container;
 
        typedef container::const_iterator const_iterator;
        typedef container::iterator iterator;
@@ -78,10 +80,10 @@
                // NOTE: we copy the elements as the visitor might call 
arbitrary code
                //       possibly modifying the container itself.
                container copy = elements;
+
+               // iterating this way will skip holes
                for (iterator i=copy.begin(), ie=copy.end(); i!=ie; ++i)
-               {
-                       if ( i->which() == itemValue ) 
v.visit(boost::get<as_value>(*i));
-               }
+                       v.visit(*i);
        }
 
        /// Sort flags
@@ -133,7 +135,7 @@
 
        as_value pop();
 
-       as_value at(unsigned int index);
+       as_value at(unsigned int index) const;
 
        as_array_object* get_indices(std::deque<indexed_as_value> origElems);
 
@@ -191,6 +193,9 @@
        //
        /// Return true if any element was removed, false otherwise
        ///
+       /// NOTE: if an element is removed, holes in the array will be
+       ///       filled.
+       ///
        /// @param v
        ///     The value to compare elements against
        ///
@@ -200,27 +205,24 @@
        bool removeFirst(const as_value& v);
 
        /// \brief
-       /// Substitute 'len' elements from 'start' with elements from
-       /// the given array.
+       /// Replace count elements from start with given values, optionally
+       /// returning the erased ones.
        //
-       /// NOTE: assertions are:
-       ///
-       ///     assert(len <= size()-start);
-       ///     assert(start <= size());
-       ///
        /// @param start
-       ///     0-index based offset of first element to replace.
+       ///     First element to remove. Will abort if invalid.
        ///
-       /// @param len
-       ///     Number of elements to replace.
+       /// @param count
+       ///     Number of elements to remove. Will abort if > then available.
        ///
-       /// @param replacement
-       ///     The element to use as replacement
+       /// @param replace
+       ///     If not null, use as a replacement for the cutted values
        ///
-       /// TODO: should we return by intrusive_ptr instead ?
+       /// @param copy
+       ///     If not null, an array to push cutted values to.
        ///
-       std::auto_ptr<as_array_object> splice(unsigned start, unsigned len,
-                       const std::vector<as_value>& replacement);
+       void splice(unsigned int start, unsigned int count, 
+                       const std::vector<as_value>* replace=NULL,
+                       as_array_object* copy=NULL);
 
        /// \brief
        /// Sort the array, using given values comparator
@@ -255,8 +257,12 @@
 
                size_t oldSize = elements.size(); // custom comparator might 
change input size
                nelem.sort(avc);
-               elements.assign(nelem.begin(), nelem.end());
-               resize(oldSize);
+               elements.resize(oldSize, false);
+               size_t idx=0;
+               for (ValueList::iterator i=nelem.begin(), e=nelem.end(); i!=e; 
++i)
+               {
+                       elements[idx++] = *i;
+               };
        }
 
        /// \brief
@@ -305,8 +311,12 @@
                if (std::adjacent_find(nelem.begin(), nelem.end(), ave) != 
nelem.end() )
                        return as_value(0);
 
-               elements.assign(nelem.begin(), nelem.end());
-               resize(oldSize);
+               elements.resize(oldSize, false);
+               size_t idx=0;
+               for (ValueList::iterator i=nelem.begin(), e=nelem.end(); i!=e; 
++i)
+               {
+                       elements[idx++] = *i;
+               };
 
                return as_value(this);
        }
@@ -388,6 +398,19 @@
        // if the string does not refer to an index, or an appropriate int if 
the string does refer to an index
        int index_requested(string_table::key name);
 
+       /// Shift all elements to the left by count positions
+       //
+       /// Pre-condition: size of the array must be >= count
+       /// Post-condition: size of the array will reduce by 'count'
+       ///
+       void shiftElementsLeft(unsigned int count);
+
+       /// Shift all elements to the right by count positions
+       //
+       /// Pre-condition: none
+       /// Post-condition: size of the array will incremented by 'count'
+       ///
+       void shiftElementsRight(unsigned int count);
 };
 
 

Index: testsuite/actionscript.all/array.as
===================================================================
RCS file: /sources/gnash/gnash/testsuite/actionscript.all/array.as,v
retrieving revision 1.57
retrieving revision 1.58
diff -u -b -r1.57 -r1.58
--- testsuite/actionscript.all/array.as 19 Mar 2008 10:13:38 -0000      1.57
+++ testsuite/actionscript.all/array.as 19 Mar 2008 11:40:16 -0000      1.58
@@ -19,7 +19,7 @@
 // Initial test written by Mike Carlson
 
 
-rcsid="$Id: array.as,v 1.57 2008/03/19 10:13:38 strk Exp $";
+rcsid="$Id: array.as,v 1.58 2008/03/19 11:40:16 strk Exp $";
 #include "check.as"
 
 check_equals(typeof(Array), 'function');
@@ -464,7 +464,7 @@
 #endif
 sparse.reverse();
 count=0; for (var i in sparse) count++;
-xcheck_equals(count, 6); // no more holes
+check_equals(count, 6); // no more holes
 #if OUTPUT_VERSION > 5
  xcheck(sparse.hasOwnProperty(0));
  xcheck(sparse.hasOwnProperty(5));
@@ -552,11 +552,11 @@
 check_equals(count, 1);
 
 count=0; for (var i in csp) count++;
-xcheck_equals(count, 7); // concat filled any holes
+check_equals(count, 7); // concat filled any holes
 
 csp = sparse1.concat('onemore');
 count=0; for (var i in csp) count++;
-xcheck_equals(count, 5); // concat filled any holes
+check_equals(count, 5); // concat filled any holes
 
 //-------------------------------
 // Test Array.splice
@@ -665,22 +665,22 @@
 spliced = ary.splice(3, 0); // no op ?
 check_equals(ary.length, 8); // no change in length
 count=0; for (var i in ary) count++;
-xcheck_equals(count, 8); // but fills the gaps !
+check_equals(count, 8); // but fills the gaps !
 
 ary = new Array(); ary[2] = 2; ary[7] = 7;
 spliced = ary.splice(3, 0, 3); // add 3 at index 3
 check_equals(ary.length, 9); 
 count=0; for (var i in ary) count++;
-xcheck_equals(count, 9); // fills the gaps !
+check_equals(count, 9); // fills the gaps !
 check_equals(ary[3], 3);
 check_equals(ary[2], 2);
 
 ary = new Array(); ary[2] = 2; ary[7] = 7;
 spliced = ary.splice(3, 1, 3); // replace index 3 (an hole) with a 3 value
 count=0; for (var i in ary) count++;
-xcheck_equals(count, 8); // fills the gaps 
+check_equals(count, 8); // fills the gaps 
 count=0; for (var i in spliced) count++;
-xcheck_equals(count, 1); // the returned array contains an actual value, not 
an hole
+check_equals(count, 1); // the returned array contains an actual value, not an 
hole
 
 //-------------------------------
 // Test single parameter constructor, and implicitly expanding array




reply via email to

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