[Top][All Lists]
[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
- [Gnash-commit] gnash ChangeLog server/as_environment.cpp serve...,
Sandro Santilli <=