[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Gnash-commit] /srv/bzr/gnash/trunk r11169: Make AVM2 scope stack and st
From: |
Benjamin Wolsey |
Subject: |
[Gnash-commit] /srv/bzr/gnash/trunk r11169: Make AVM2 scope stack and stack usage stricter and more correct by dropping |
Date: |
Fri, 26 Jun 2009 15:39:36 +0200 |
User-agent: |
Bazaar (1.13.1) |
------------------------------------------------------------
revno: 11169
committer: Benjamin Wolsey <address@hidden>
branch nick: trunk
timestamp: Fri 2009-06-26 15:39:36 +0200
message:
Make AVM2 scope stack and stack usage stricter and more correct by dropping
left-over items on return from functions, not dropping items before
entering functions, and using the whole scope stack for lookup. SafeStack
was ideal for this, but wasn't being used correctly.
This also fixes crashes when the VM accessed deleted items that were left in
the stack after function returns. It also removes the need for some ugly hacks
in the AVM2 code. It should be possible to clean it up further with
more testing.
Add limited regression test for stack usage so it doesn't break again.
Add the rest of the infrastructure for trace testing in misc-swfmill.all
(may be better in its own directory). Fix various errors in the Makefile
so that all the tests are built, run, and cleaned.
added:
testsuite/misc-swfmill.all/PASSING
testsuite/misc-swfmill.all/gen-swfmill-trace-runner.sh
testsuite/misc-swfmill.all/scope2.trace
testsuite/misc-swfmill.all/scope2.xml
modified:
libcore/asNamespace.h
libcore/parser/abc_block.cpp
libcore/parser/abc_block.h
libcore/vm/Machine.cpp
libcore/vm/Machine.h
libcore/vm/SafeStack.h
testsuite/misc-swfmill.all/Makefile.am
testsuite/misc-swfmill.all/scope1.xml
------------------------------------------------------------
revno: 11163.1.11
committer: Benjamin Wolsey <address@hidden>
branch nick: work
timestamp: Fri 2009-06-26 07:52:12 +0200
message:
Add more kind constants.
modified:
libcore/parser/abc_block.h
------------------------------------------------------------
revno: 11163.1.12
committer: Benjamin Wolsey <address@hidden>
branch nick: work
timestamp: Fri 2009-06-26 07:53:09 +0200
message:
Minor cleanups.
modified:
libcore/parser/abc_block.cpp
------------------------------------------------------------
revno: 11163.1.13
committer: Benjamin Wolsey <address@hidden>
branch nick: work
timestamp: Fri 2009-06-26 07:54:45 +0200
message:
Track whether it's a package namespace.
modified:
libcore/asNamespace.h
------------------------------------------------------------
revno: 11167.1.1
committer: Benjamin Wolsey <address@hidden>
branch nick: temp
timestamp: Fri 2009-06-26 09:36:09 +0200
message:
Add more info to namespaces.
modified:
libcore/asNamespace.h
libcore/parser/abc_block.cpp
libcore/parser/abc_block.h
------------------------------------------------------------
revno: 11167.1.2
committer: Benjamin Wolsey <address@hidden>
branch nick: temp
timestamp: Fri 2009-06-26 09:38:02 +0200
message:
Don't push things to the scope stack ourselves in find_prop_strict; the
bytecode must take care of that.
modified:
libcore/vm/Machine.cpp
------------------------------------------------------------
revno: 11167.1.3
committer: Benjamin Wolsey <address@hidden>
branch nick: temp
timestamp: Fri 2009-06-26 10:39:23 +0200
message:
Add functions to SafeStack to make 'inaccessible' elements readable. This
is necessary to implement AVM2 stack behaviour.
modified:
libcore/vm/SafeStack.h
------------------------------------------------------------
revno: 11167.1.4
committer: Benjamin Wolsey <address@hidden>
branch nick: temp
timestamp: Fri 2009-06-26 10:40:15 +0200
message:
Use the scope stack properly: do not push objects to it for function
calls,
but rather make sure inaccessible elements are usable for lookups, even
though these elements are invisible to the function scope.
modified:
libcore/vm/Machine.cpp
libcore/vm/Machine.h
------------------------------------------------------------
revno: 11167.1.5
committer: Benjamin Wolsey <address@hidden>
branch nick: temp
timestamp: Fri 2009-06-26 11:03:38 +0200
message:
OpPopStack doesn't exist; it's OpPop and it does cause an error after all.
modified:
testsuite/misc-swfmill.all/scope1.xml
------------------------------------------------------------
revno: 11167.1.6
committer: Benjamin Wolsey <address@hidden>
branch nick: temp
timestamp: Fri 2009-06-26 11:20:12 +0200
message:
Drop load_function function and do it in executeFunction instead for
clarity.
Check the stack size in completeName() first so as not to cause
StackExceptions.
Store and restore stack sizes after executeFunction (not yet using
saveState()).
modified:
libcore/vm/Machine.cpp
------------------------------------------------------------
revno: 11167.1.7
committer: Benjamin Wolsey <address@hidden>
branch nick: temp
timestamp: Fri 2009-06-26 13:30:47 +0200
message:
Set the stack size correctly, that is dropping left-over items on return
and restoring the pre-function-call stack.
Push the object to the stack on CONSTRUCTPROP.
This makes the non-automated misc-swfmill.all scope1.swf test work
(except for tracing an incorrect string for objects and classes) and
introduces no regressions in the as3compile tests.
modified:
libcore/vm/Machine.cpp
------------------------------------------------------------
revno: 11167.1.8
committer: Benjamin Wolsey <address@hidden>
branch nick: temp
timestamp: Fri 2009-06-26 13:49:07 +0200
message:
Add a reduced testcase version so that one passes at all for regression
testing.
added:
testsuite/misc-swfmill.all/scope2.trace
testsuite/misc-swfmill.all/scope2.xml
modified:
testsuite/misc-swfmill.all/Makefile.am
------------------------------------------------------------
revno: 11167.1.9
committer: Benjamin Wolsey <address@hidden>
branch nick: temp
timestamp: Fri 2009-06-26 14:34:04 +0200
message:
Passing trace tests.
added:
testsuite/misc-swfmill.all/PASSING
------------------------------------------------------------
revno: 11167.1.10
committer: Benjamin Wolsey <address@hidden>
branch nick: temp
timestamp: Fri 2009-06-26 14:34:14 +0200
message:
Create and run the test runner.
modified:
testsuite/misc-swfmill.all/Makefile.am
------------------------------------------------------------
revno: 11167.1.11
committer: Benjamin Wolsey <address@hidden>
branch nick: temp
timestamp: Fri 2009-06-26 14:45:04 +0200
message:
Add the test-runner generator, minor corrections to Makefile so that
the tests run.
added:
testsuite/misc-swfmill.all/gen-swfmill-trace-runner.sh
modified:
testsuite/misc-swfmill.all/Makefile.am
------------------------------------------------------------
revno: 11167.1.12
committer: Benjamin Wolsey <address@hidden>
branch nick: temp
timestamp: Fri 2009-06-26 14:47:09 +0200
message:
Do seek on both types of return instead of in different places or twice.
modified:
libcore/vm/Machine.cpp
=== modified file 'libcore/asNamespace.h'
--- a/libcore/asNamespace.h 2009-05-14 15:58:59 +0000
+++ b/libcore/asNamespace.h 2009-06-26 05:54:45 +0000
@@ -43,7 +43,8 @@
mClasses(),
mRecursePrevent(false),
_private(false),
- _protected(false)
+ _protected(false),
+ _package(false)
{}
void markReachableResources() const { /* TODO */ }
@@ -100,6 +101,10 @@
void unsetProtected() { _protected = false; }
bool isProtected() { return _protected; }
+ void setPackage() { _package = true; }
+ void unsetPackage() { _package = false; }
+ bool isPackage() { return _package; }
+
private:
asNamespace* _parent;
@@ -114,6 +119,7 @@
bool _private;
bool _protected;
+ bool _package;
asClass* getClassInternal(string_table::key name) const
{
=== modified file 'libcore/parser/abc_block.cpp'
--- a/libcore/parser/abc_block.cpp 2009-06-23 11:16:38 +0000
+++ b/libcore/parser/abc_block.cpp 2009-06-26 05:53:09 +0000
@@ -325,9 +325,9 @@
// fail as often, but doesn't really seem quite correct.
#if 1
as_object* global = mach->global();
+ assert(global);
for (std::vector<asNamespace*>::iterator i = _namespacePool.begin(),
e = _namespacePool.end(); i != e; ++i) {
- assert(global);
global->reserveSlot((*i)->getURI(), 0, i - _namespacePool.begin());
}
#endif
@@ -548,14 +548,10 @@
else
{
asNamespace *n = mCH->findNamespace(nameIndex);
- if (n == NULL)
- n = mCH->addNamespace(nameIndex);
+ if (!n) n = mCH->addNamespace(nameIndex);
_namespacePool[i] = n;
}
- if (kind == PROTECTED_NS)
- {
- _namespacePool[i]->setProtected();
- }
+ if (kind == PROTECTED_NS) _namespacePool[i]->setProtected();
setNamespaceURI(_namespacePool[i], nameIndex);
}
return true;
=== modified file 'libcore/parser/abc_block.h'
--- a/libcore/parser/abc_block.h 2009-06-23 07:24:01 +0000
+++ b/libcore/parser/abc_block.h 2009-06-26 05:52:12 +0000
@@ -236,6 +236,8 @@
enum Constants
{
PRIVATE_NS = 0x05,
+ PACKAGE_NS = 0x16,
+ PACKAGE_INTERNAL_NS = 0x17,
PROTECTED_NS = 0x18,
METHOD_ARGS = 0x01,
METHOD_ACTIVATION = 0x02,
=== modified file 'libcore/vm/Machine.cpp'
--- a/libcore/vm/Machine.cpp 2009-06-23 13:45:54 +0000
+++ b/libcore/vm/Machine.cpp 2009-06-26 12:47:09 +0000
@@ -1189,13 +1189,7 @@
log_abc("Creating new abc_function: method
index=%u",method_index);
asMethod *m = pool_method(method_index, mPoolObject);
abc_function* new_function = m->getPrototype();
- // TODO: SafeStack contains all the scope objects
- // in for all functions in the call stack.
- // We should only copy the relevent scope objects
- // to the function's scope stacks.
- // Note: this doesn't copy any values, but rather assigns
a pointer
- // value.
- new_function->setScopeStack(getScopeStack());
+
push_stack(as_value(new_function));
break;
}
@@ -1381,11 +1375,9 @@
as_object *object = object_val.to_object().get();
if (!object) {
- IF_VERBOSE_ASCODING_ERRORS(
- log_aserror(_("Can't call a method of a value "
+ log_abc(_("CALLPROP: Can't call a method of a value "
"that doesn't cast to an object (%s)."),
object_val);
- )
}
else {
@@ -1400,12 +1392,10 @@
}
else {
- IF_VERBOSE_ASCODING_ERRORS(
- log_aserror(_("Property '%s' of object '%s' "
+ log_abc(_("CALLPROP: Property '%s' of object '%s' "
"is '%s', cannot call as method"),
mPoolObject->stringPoolAt(a.getABCName()),
object_val, property);
- )
}
}
@@ -1469,6 +1459,8 @@
/// .
/// Do: Return value up the callstack.
case SWF::ABC_ACTION_RETURNVALUE:
+ mStream->seekTo(0);
+
// Slot the return.
mGlobalReturn = pop_stack();
// And restore the previous state.
@@ -1581,6 +1573,9 @@
call_method(val, env,
constructor_val.to_object().get(), args);
+
+ // Push the constructed property?
+ push_stack(constructor_val);
}
}
@@ -2923,6 +2918,11 @@
int
Machine::completeName(asName& name, int offset)
{
+
+ // TODO: implement this properly.
+ // Should this really be called when there's nothing on the stack?
+ if (mStack.empty()) return 0;
+
int size = 0;
if (name.isRuntime())
@@ -2933,8 +2933,9 @@
++size;
}
- if (name.isRtns())
+ if (name.isRtns()) {
++size; // Ignore the Namespace.
+ }
}
else if (name.isRtns())
{
@@ -2969,6 +2970,8 @@
Machine::immediateFunction(const as_function* func, as_object* thisptr,
as_value& storage, unsigned char stack_in, short stack_out)
{
+
+ GNASH_REPORT_FUNCTION;
assert(func);
// TODO: Set up the fn to use the stack
@@ -2980,11 +2983,11 @@
}
fn_call fn(thisptr, as_environment(_vm), args);
- mStack.drop(stack_in - stack_out);
+ mStack.drop(stack_in - stack_out);
saveState();
+ mStack.grow(stack_in - stack_out);
+ mStack.setDownstop(stack_in);
mThis = thisptr;
- mStack.grow(stack_in - stack_out);
- mStack.setDownstop(stack_in);
storage = const_cast<as_function*>(func)->call(fn);
restoreState();
}
@@ -3114,7 +3117,18 @@
mCurrentFunction = method->getPrototype();
bool prev_ext = mExitWithReturn;
CodeStream *stream = method->getBody();
- load_function(stream, method->getMaxRegisters());
+
+ // Protect the current stack from alteration
+ // TODO: use saveState only, but not before checking other effects.
+ size_t stackdepth = mStack.fixDownstop();
+ size_t stacksize = mStack.totalSize();
+ size_t scopedepth = mScopeStack.fixDownstop();
+ size_t scopesize = mScopeStack.totalSize();
+
+ saveState();
+ mStream = stream;
+ clearRegisters(method->getMaxRegisters());
+
log_abc("Executing function: max registers %s, scope depth %s, "
"max scope %s, max stack: %s", method->getMaxRegisters(),
method->scopeDepth(), method->maxScope(), method->maxStack());
@@ -3123,18 +3137,12 @@
for (unsigned int i=0;i<fn.nargs;i++) {
setRegister(i + 1, fn.arg(i));
}
- //TODO: There is probably a better way to do this.
- //
- const as_environment::ScopeStack* const ss =
mCurrentFunction->scopeStack();
-
- if (ss) {
- for (unsigned int i=0; i < ss->size(); ++i) {
- push_scope_stack(as_value(ss->at(i)));
- }
- }
- execute();
+
+ execute();
mExitWithReturn = prev_ext;
- stream->seekTo(0);
+
+ mStack.setAllSizes(stacksize, stackdepth);
+ mScopeStack.setAllSizes(scopesize, scopedepth);
return mGlobalReturn;
}
@@ -3170,8 +3178,13 @@
clearRegisters(ctor->getMaxRegisters());
mCurrentFunction = ctor->getPrototype();
- mStack.clear();
- mScopeStack.clear();
+
+ // Protect the current stack from alteration
+ // TODO: use saveState
+ size_t stackdepth = mStack.fixDownstop();
+ size_t stacksize = mStack.totalSize();
+ size_t scopedepth = mScopeStack.fixDownstop();
+ size_t scopesize = mScopeStack.totalSize();
// The value at _registers[0] is generally pushed to the stack for
// CONSTRUCTSUPER, which apparently expects the object whose super
@@ -3179,6 +3192,10 @@
setRegister(0, cl->getPrototype());
executeCodeblock(ctor->getBody());
log_debug("Finished instantiating class %s", className);
+
+ mStack.setAllSizes(stacksize, stackdepth);
+ mScopeStack.setAllSizes(scopesize, scopedepth);
+
}
as_value
@@ -3189,11 +3206,17 @@
mST.value(multiname.getNamespace()->getURI()),
mST.value(multiname.getGlobalName()));
+ // We should not push anything onto the scope stack here; whatever is
+ // needed should already be pushed. The pp will not call FINDPROP*
+ // when the scope stack is empty.
+ //
+ // However, the complete scope stack, including elements that are
+ // 'invisible' to this scope, is available
as_value val;
- mScopeStack.push(mGlobalObject);
- for (size_t i = 0; i < mScopeStack.size(); ++i)
+ print_scope_stack();
+ for (size_t i = 0; i < mScopeStack.totalSize(); ++i)
{
- as_object* scope_object = mScopeStack.top(i).get();
+ as_object* scope_object = mScopeStack.at(i).get();
if (!scope_object) {
log_abc("Scope object is NULL.");
continue;
@@ -3202,8 +3225,7 @@
multiname.getNamespace()->getURI());
if (!val.is_undefined()) {
- push_stack(mScopeStack.top(i));
- mScopeStack.pop();
+ push_stack(mScopeStack.at(i));
return val;
}
}
@@ -3222,7 +3244,6 @@
val = env.get_variable(path, *envStack, &target);
push_stack(target);
- mScopeStack.pop();
return val;
}
@@ -3268,9 +3289,9 @@
std::stringstream ss;
ss << "Stack: ";
- for (unsigned int i = 0; i < mStack.size(); ++i) {
+ for (unsigned int i = 0; i < mStack.totalSize(); ++i) {
if (i!=0) ss << " | ";
- ss << mStack.value(i).toDebugString();
+ ss << mStack.at(i);
}
log_abc("%s", ss.str());
}
@@ -3281,8 +3302,11 @@
std::stringstream ss;
ss << "ScopeStack: ";
- for (unsigned int i=0;i<mScopeStack.size();++i) {
- ss << as_value(mScopeStack.top(i).get()).toDebugString();
+
+ size_t totalSize = mScopeStack.totalSize();
+
+ for (unsigned int i = 0; i < totalSize; ++i) {
+ ss << as_value(mScopeStack.at(i).get()).toDebugString();
}
log_abc("%s", ss.str());
}
@@ -3299,17 +3323,6 @@
return args;
}
-void
-Machine::load_function(CodeStream* stream, boost::uint32_t maxRegisters)
-{
- saveState();
- //TODO: Maybe this call should be part of saveState(), it
- //returns the old downstop.
- mScopeStack.fixDownstop();
- mStream = stream;
- clearRegisters(maxRegisters);
-}
-
as_environment::ScopeStack*
Machine::getScopeStack()
{
=== modified file 'libcore/vm/Machine.h'
--- a/libcore/vm/Machine.h 2009-06-16 12:28:07 +0000
+++ b/libcore/vm/Machine.h 2009-06-26 08:40:15 +0000
@@ -332,8 +332,18 @@
SafeStack<as_value> mStack;
SafeStack<State> mStateStack;
std::vector<as_value> _registers;
+
+ /// The scope stack is used to look for objects as properties
+ //
+ /// This stack is not cleared before a function call, class instantiation
+ /// etc, but anything on the stack cannot be altered by the function call.
+ /// On return from the function, the stack should be the same as it was
+ /// before.
+ /// Most importantly, the complete stack is used for lookups, including
+ /// the section that is not changeable.
SafeStack<boost::intrusive_ptr<as_object> > mScopeStack;
- CodeStream *mStream;
+
+ CodeStream *mStream;
string_table& mST;
=== modified file 'libcore/vm/SafeStack.h'
--- a/libcore/vm/SafeStack.h 2009-06-19 09:06:53 +0000
+++ b/libcore/vm/SafeStack.h 2009-06-26 08:39:23 +0000
@@ -70,6 +70,30 @@
const StackSize offset = _end - i;
return _data[offset >> _chunkShift][offset & _chunkMod];
}
+
+ /// From the top of the stack, get the i'th value down.
+ //
+ /// 0 is the topmost value value.
+ const T& at(StackSize i) const
+ {
+
+ if (i >= totalSize()) throw StackException();
+ const StackSize offset = _end - i;
+ return _data[offset >> _chunkShift][offset & _chunkMod];
+ }
+
+
+ /// From the top of the stack, get the i'th value down.
+ //
+ /// This is a non-const version of at().
+ /// 0 is the topmost value value.
+ T& at(StackSize i)
+ {
+
+ if (i >= totalSize()) throw StackException();
+ const StackSize offset = _end - i;
+ return _data[offset >> _chunkShift][offset & _chunkMod];
+ }
/// From the bottom of the stack, get the i'th value up. 0 is the
/// bottommost value.
@@ -175,12 +199,10 @@
_downstop = i;
}
- /// The total size of the stack. This is not what can be read. That
- /// value is given by size()
- ///
- /// This function is probably not what you need for anything except for
- /// setting downstops that weren't returned by either fixDownstop() or
- /// getDownstop()
+ /// Return the complete stack size, including non-accessible elements
+ //
+ /// This is required because AVM2 scope stacks are usable even when they
+ /// appear inaccessible
StackSize totalSize() const { return _end - 1; }
/// Set the total size and local size of the stack, for restoring a
=== modified file 'testsuite/misc-swfmill.all/Makefile.am'
--- a/testsuite/misc-swfmill.all/Makefile.am 2009-06-25 07:58:45 +0000
+++ b/testsuite/misc-swfmill.all/Makefile.am 2009-06-26 13:39:36 +0000
@@ -35,21 +35,27 @@
Try-without-jump.xml \
$(NULL)
-SC_AS3_XMLTEXTS = \
+SC_AS3_XMLTESTS = \
mixed-bytecode-as3.xml \
$(NULL)
# XML tests that rely on comparing trace output.
-TRACE_AS_TESTS = \
+TRACE_AS3_TESTS = \
scope1.xml \
+ scope2.xml \
$(NULL)
TRACE_AS3_TRACES = \
scope1.trace \
+ scope2.trace \
$(NULL)
-EXTRA_DIST = $(SC_AS2_XMLTESTS) $(SC_AS3_XMLTESTS) $(TRACE_AS_TESTS) \
- $(TRACE_AS3_TRACES)
+EXTRA_DIST = $(SC_AS2_XMLTESTS) \
+ $(SC_AS3_XMLTESTS) \
+ $(TRACE_AS3_TESTS) \
+ $(TRACE_AS3_TRACES) \
+ gen-swfmill-trace-runner.sh \
+ $(NULL)
AM_CPPFLAGS = \
-I$(top_srcdir)/libbase \
@@ -65,10 +71,11 @@
$(NULL)
SC_XMLTESTS_OUT = $(SC_AS2_XMLTESTS:.xml=.swf)
+TRACE_XMLTESTS_OUT =
if ENABLE_AVM2
SC_XMLTESTS_OUT += $(SC_AS3_XMLTESTS:.xml=.swf)
-SC_XMLTESTS_OUT += $(TRACE_AS3_TESTS:.xml=.swf)
+TRACE_XMLTESTS_OUT += $(TRACE_AS3_TESTS:.xml=.swf)
endif
# Dependencies for all self-contained SWF tests
@@ -88,11 +95,17 @@
if ENABLE_AVM2
check_SCRIPTS += \
mixed-bytecode-as3-runner \
+ trace-test-runner \
$(NULL)
endif
check_PROGRAMS = \
- backgroundTestRunner
+ backgroundTestRunner \
+ $(NULL)
+
+trace-test-runner: $(srcdir)/gen-swfmill-trace-runner.sh $(TRACE_AS3_TESTS)
$(TRACE_XMLTESTS_OUT)
+ sh $< $(srcdir) $(builddir) > $@
+ chmod 755 $@
mixed-bytecode-as3-runner: $(srcdir)/../generic-testrunner.sh
mixed-bytecode-as3.swf Makefile
sh $< -r 50 -c "AS3" $(top_builddir) mixed-bytecode-as3.swf > $@
@@ -150,8 +163,8 @@
$(SWFMILL) -v xml2swf $(@:%.swf=$(srcdir)/%.xml) $@
clean-local:
- rm -f $(check_SCRIPTS) $(SC_XMLTESTS_OUT) \
- *.log *.trace-gnash \
+ rm -f $(check_SCRIPTS) $(SC_XMLTESTS_OUT) $(TRACE_XMLTESTS_OUT) \
+ *.log *.trace-gnash *.out \
site.bak site.exp site.exp.bak testrun.sum \
gnash.sum
=== added file 'testsuite/misc-swfmill.all/PASSING'
--- a/testsuite/misc-swfmill.all/PASSING 1970-01-01 00:00:00 +0000
+++ b/testsuite/misc-swfmill.all/PASSING 2009-06-26 12:34:04 +0000
@@ -0,0 +1,1 @@
+scope2
=== added file 'testsuite/misc-swfmill.all/gen-swfmill-trace-runner.sh'
--- a/testsuite/misc-swfmill.all/gen-swfmill-trace-runner.sh 1970-01-01
00:00:00 +0000
+++ b/testsuite/misc-swfmill.all/gen-swfmill-trace-runner.sh 2009-06-26
12:45:04 +0000
@@ -0,0 +1,56 @@
+#!/bin/sh
+
+if [ -z "$2" ]; then
+ echo "Usage: `basename $0` <gnash_srcdir> <gnash_builddir>" >&2
+ exit 1
+fi
+
+TESTDIR=$1
+BUILDDIR=$2
+PASSFILE="${TESTDIR}/PASSING"
+
+TESTER="${BUILDDIR}/../../utilities/gprocessor -v -r0 -f 10 "
+
+cat<<EOF
+#!/bin/sh
+
+# Generated by gen-swfmill-trace-runner
+EOF
+
+echo -n TESTS=\"
+
+for tracetest in `ls ${TESTDIR}/*.trace`; do
+ testname=`basename ${tracetest} | sed -e s/\\\.trace//g`
+ echo -n "${testname} "
+done
+echo \"
+
+cat<<EOF
+
+for testcase in \$TESTS; do
+
+ expectpass=no
+ if grep -q "^\${testcase}\$" ${PASSFILE}; then
+ expectpass=yes
+ fi
+
+ out=\${testcase}.out
+ $TESTER ${BUILDDIR}/\${testcase}.swf | grep TRACE -A1 | sed '/^--$/d;
s/.*TRACE: //; /\n*[0-9]:[0-9]*\].*/d; s/^$//;' > \$out
+ diff -q ${TESTDIR}/\${testcase}.trace \$out >/dev/null
+ if [ \$? -ne 0 ]; then
+ if [ x"\${expectpass}" = "xyes" ]; then
+ echo FAILED: \${testcase}
+ else
+ echo XFAILED: \${testcase}
+ fi
+ else
+ if [ x"\${expectpass}" = "xyes" ]; then
+ echo PASSED: \${testcase}
+ else
+ echo XPASSED: \${testcase}
+ fi
+ fi
+done
+
+
+EOF
=== modified file 'testsuite/misc-swfmill.all/scope1.xml'
--- a/testsuite/misc-swfmill.all/scope1.xml 2009-06-25 07:29:28 +0000
+++ b/testsuite/misc-swfmill.all/scope1.xml 2009-06-26 09:03:38 +0000
@@ -126,19 +126,7 @@
<MethodBody methodInfo="1" maxStack="8" maxRegs="1"
scopeDepth="5" maxScope="14" exceptionCount="0">
<code>
- <!-- This seems accepted by the player, but has no effect -->
- <OpPopStack/>
- <OpPopStack/>
- <OpPopStack/>
- <OpPopStack/>
- <OpPopStack/>
- <OpPopStack/>
- <OpPopStack/>
- <OpPopStack/>
- <OpPopStack/>
- <OpPopStack/>
-
- <!-- OpPopScope, on the other hand, causes a scope stack
+ <!-- OpPop and OpPopScope cause a scope stack
underflow error, so we don't do it. -->
<OpFindPropStrict name="10"/>
=== added file 'testsuite/misc-swfmill.all/scope2.trace'
--- a/testsuite/misc-swfmill.all/scope2.trace 1970-01-01 00:00:00 +0000
+++ b/testsuite/misc-swfmill.all/scope2.trace 2009-06-26 11:49:07 +0000
@@ -0,0 +1,4 @@
+3
+A.f()
+2
+1
=== added file 'testsuite/misc-swfmill.all/scope2.xml'
--- a/testsuite/misc-swfmill.all/scope2.xml 1970-01-01 00:00:00 +0000
+++ b/testsuite/misc-swfmill.all/scope2.xml 2009-06-26 11:49:07 +0000
@@ -0,0 +1,207 @@
+<?xml version="1.0"?>
+<swf version="9" compressed="1">
+<!-- This is a simpler version of scope1.xml. It only traces simple stack
+values, because tracing things from the scope stack means getting object
+and class names right. That's the reason why scope1.swf fails, so this serves
+as a regression test for stack values only. -->
+ <Header framerate="25" frames="1">
+ <size>
+ <Rectangle left="0" right="8000" top="0" bottom="6000"/>
+ </size>
+ <tags>
+ <FileAttributes hasMetaData="0" allowABC="1"
suppressCrossDomainCaching="0" swfRelativeURLs="0" useNetwork="0"/>
+ <DoABCDefine flags="0" name="">
+ <actions>
+ <Action3 minorVersion="16" majorVersion="46">
+ <constants>
+ <Constants>
+ <ints/>
+ <uints/>
+ <doubles/>
+ <strings>
+ <String2 value="A.f()"/>
+ <String2 value="A"/>
+ <String2 value="MovieClip"/>
+ <String2 value="f"/>
+ <String2 value="Object"/>
+ <String2 value="EventDispatcher"/>
+ <String2 value="DisplayObject"/>
+ <String2 value="InteractiveObject"/>
+ <String2 value="DisplayObjectContainer"/>
+ <String2 value="Sprite"/>
+ <String2 value="trace"/>
+ <String2 value="a"/>
+ <String2 value="flash.display"/>
+ <String2 value=""/>
+ <String2 value="flash.events"/>
+ </strings>
+ <namespaces>
+ <ProtectedNamespace index="2"/>
+ <PackageNamespace index="12"/>
+ <PackageNamespace index="13"/>
+ <PackageNamespace index="14"/>
+ <PackageNamespace index="15"/>
+ </namespaces>
+ <namespaceSets/>
+ <multinames>
+ <QName namespaceIndex="2" nameIndex="2"/>
+ <QName namespaceIndex="3" nameIndex="3"/>
+ <QName namespaceIndex="4" nameIndex="4"/>
+ <QName namespaceIndex="4" nameIndex="5"/>
+ <QName namespaceIndex="5" nameIndex="6"/>
+ <QName namespaceIndex="3" nameIndex="7"/>
+ <QName namespaceIndex="3" nameIndex="8"/>
+ <QName namespaceIndex="3" nameIndex="9"/>
+ <QName namespaceIndex="3" nameIndex="10"/>
+ <QName namespaceIndex="4" nameIndex="11"/>
+ </multinames>
+ </Constants>
+ </constants>
+ <methods>
+ <MethodInfo retType="0" nameIndex="0" hasParamNames="0"
setSDXNs="0" isExplicit="0" ignoreRest="0" hasOptional="0" needRest="0"
needActivation="0" needArguments="0">
+ <paramTypes/>
+ </MethodInfo>
+ <MethodInfo retType="0" nameIndex="0" hasParamNames="0"
setSDXNs="0" isExplicit="0" ignoreRest="0" hasOptional="0" needRest="0"
needActivation="0" needArguments="0">
+ <paramTypes/>
+ </MethodInfo>
+ <MethodInfo retType="0" nameIndex="0" hasParamNames="0"
setSDXNs="0" isExplicit="0" ignoreRest="0" hasOptional="0" needRest="0"
needActivation="0" needArguments="0">
+ <paramTypes/>
+ </MethodInfo>
+ <MethodInfo retType="0" nameIndex="0" hasParamNames="0"
setSDXNs="0" isExplicit="0" ignoreRest="0" hasOptional="0" needRest="0"
needActivation="0" needArguments="0">
+ <paramTypes/>
+ </MethodInfo>
+ </methods>
+ <metadata/>
+ <instances>
+ <InstanceInfo nameIndex="1" superIndex="2" hasProtectedNS="1"
interface="0" final="0" sealed="1" protectedNS="1" iInitIndex="2">
+ <interfaces/>
+ <traits>
+ <TraitInfo nameIndex="3" override="0" final="0">
+ <trait>
+ <Method dispID="1" methodInfo="1"/>
+ </trait>
+ </TraitInfo>
+ </traits>
+ </InstanceInfo>
+ </instances>
+ <classes>
+ <ClassInfo cInitIndex="3">
+ <traits/>
+ </ClassInfo>
+ </classes>
+ <scripts>
+ <ScriptInfo initIndex="0">
+ <traits>
+ <TraitInfo nameIndex="1" override="0" final="0">
+ <trait>
+ <Class slotID="1" classInfo="0"/>
+ </trait>
+ </TraitInfo>
+ </traits>
+ </ScriptInfo>
+ </scripts>
+ <methodBodies>
+ <MethodBody methodInfo="0" maxStack="3" maxRegs="1"
scopeDepth="0" maxScope="8" exceptionCount="0">
+ <code>
+ <OpGetLocal0/>
+ <OpPushScope/>
+ <OpGetGlobalScope/>
+ <OpGetLex name="2"/>
+ <OpDup/>
+ <OpPushScope/>
+ <OpNewClass classIndex="0"/>
+ <OpPopScope/>
+ <OpSetSlot slotID="1"/>
+ <OpReturnVoid/>
+ </code>
+ <exceptions/>
+ <traits/>
+ </MethodBody>
+
+ <!-- This is function A.f() -->
+ <!--
+ Its purpose is to push things onto the stack and the scope
+ stack and leave them there to see whether they are still
+ available after return.
+ Ideally we would also verify that the stack and the scope stack
+ from before this function call are not available, but this causes
+ VerifyErrors that interrupt execution.
+ -->
+ <MethodBody methodInfo="1" maxStack="8" maxRegs="1"
scopeDepth="5" maxScope="14" exceptionCount="0">
+ <code>
+
+ <!-- OpPop and OpPopScope cause a scope stack
+ underflow error, so we don't do it. -->
+
+ <OpFindPropStrict name="10"/>
+ <OpPushString index="1"/>
+ <OpCallPropVoid name="10" argc="1"/>
+
+ <!-- Push junk to the stack -->
+ <OpPushByte value="9"/>
+ <OpPushByte value="9"/>
+ <OpPushByte value="9"/>
+ <OpPushByte value="9"/>
+ <OpPushByte value="9"/>
+
+ <OpReturnVoid/>
+ </code>
+ <exceptions/>
+ <traits/>
+ </MethodBody>
+ <MethodBody methodInfo="2" maxStack="10" maxRegs="1"
scopeDepth="8" maxScope="12" exceptionCount="0">
+ <code>
+ <OpGetLocal0/>
+ <OpConstructSuper argc="0"/>
+
+ <!-- Push 3 values, 3 trace function lookups to the stack -->
+ <OpFindPropStrict name="10"/>
+ <OpPushByte value="1"/>
+ <OpFindPropStrict name="10"/>
+ <OpPushByte value="2"/>
+ <OpFindPropStrict name="10"/>
+ <OpPushByte value="3"/>
+
+ <!-- This is one call to trace() -->
+ <OpCallPropVoid name="10" argc="1"/>
+
+ <!-- This is the call to f() -->
+ <!-- f() pushes things to the stack and leaves them there.
+ They should not be available after
+ the function call has finished, but what was on the stack
+ before the call should still be there. -->
+ <OpGetLocal0/>
+ <OpCallPropVoid name="3" argc="0"/>
+
+ <!-- These are the remaining calls to trace() -->
+ <OpCallPropVoid name="10" argc="1"/>
+ <OpCallPropVoid name="10" argc="1"/>
+
+ <OpReturnVoid/>
+ </code>
+ <exceptions/>
+ <traits/>
+ </MethodBody>
+ <MethodBody methodInfo="3" maxStack="1" maxRegs="1"
scopeDepth="8" maxScope="9" exceptionCount="0">
+ <code>
+ <OpGetLocal0/>
+ <OpPushScope/>
+ <OpReturnVoid/>
+ </code>
+ <exceptions/>
+ <traits/>
+ </MethodBody>
+ </methodBodies>
+ </Action3>
+ </actions>
+ </DoABCDefine>
+ <SymbolClass>
+ <symbols>
+ <Symbol objectID="0" name="a.A"/>
+ </symbols>
+ </SymbolClass>
+ <ShowFrame/>
+ <End/>
+ </tags>
+ </Header>
+</swf>
- [Gnash-commit] /srv/bzr/gnash/trunk r11169: Make AVM2 scope stack and stack usage stricter and more correct by dropping,
Benjamin Wolsey <=