[pypy-svn] r20490 - in pypy/dist/pypy/translator/js: . src test
ericvrp at codespeak.net
ericvrp at codespeak.net
Thu Dec 1 13:11:34 CET 2005
Author: ericvrp
Date: Thu Dec 1 13:11:32 2005
New Revision: 20490
Modified:
pypy/dist/pypy/translator/js/codewriter.py
pypy/dist/pypy/translator/js/opwriter.py
pypy/dist/pypy/translator/js/src/ll_stackless.js
pypy/dist/pypy/translator/js/test/test_stackless.py
Log:
more passing stackless tests in genjs
Modified: pypy/dist/pypy/translator/js/codewriter.py
==============================================================================
--- pypy/dist/pypy/translator/js/codewriter.py (original)
+++ pypy/dist/pypy/translator/js/codewriter.py Thu Dec 1 13:11:32 2005
@@ -41,8 +41,11 @@
else:
eol = ';\n'
- do_log = self.js.logging and line and not line.endswith('}')
- for x in ['var', '//', 'for (;;) {', 'switch (block) {', 'slp_new_frame', 'case ', 'if ', 'elif ', 'else ', '} else ']:
+ do_log = self.js.logging and line and not line.endswith('}') and \
+ not ' = slp_frame_stack_top.' in line
+ for x in ['var' , '//' , 'for (;;) {', 'switch (block) {',
+ 'slp_new_frame', 'case ', 'if ' , 'elif ' ,
+ 'else ' , '} else ', 'slp_stack_depth' ]:
if line.startswith(x):
do_log = False
break
@@ -190,20 +193,26 @@
def neg(self, targetvar, source):
self.append('%(targetvar)s = -%(source)s' % locals())
- def call(self, targetvar, functionref, argrefs, no_exception=None, exceptions=[]):
+ def call(self, targetvar, functionref, argrefs=[], no_exception=None, exceptions=[], specialreturnvalue=None):
args = ", ".join(argrefs)
if not exceptions:
assert no_exception is None
+ if self.js.stackless:
+ self.append("slp_stack_depth++")
self.append('%s = %s(%s)' % (targetvar, functionref, args))
if self.js.stackless:
+ self.append("slp_stack_depth--")
selfdecl = self.decl.split('(')[0]
usedvars = ', '.join(self._usedvars.keys())
self.append('if (slp_frame_stack_bottom) {')
self.indent_more()
self.append('slp_new_frame("%s", %s, %d, new Array(%s))' %
(targetvar, selfdecl, self._resume_blocknum, usedvars))
- self.append('return')
+ if specialreturnvalue:
+ self.append("return " + specialreturnvalue)
+ else:
+ self.append('return')
self.indent_less()
self.append('}')
self.indent_less()
@@ -217,7 +226,10 @@
self.indent_more()
if self.js.stackless:
self.comment('TODO: XXX stackless in combination with exceptions handling')
+ self.append("slp_stack_depth++")
self.append('%s = %s(%s)' % (targetvar, functionref, args))
+ if self.js.stackless:
+ self.append("slp_stack_depth--") #XXX we don't actually get here when an exception occurs!
self._phi(no_exception_exit)
self._goto_block(no_exception_label)
self.indent_less()
@@ -252,6 +264,7 @@
self.indent_less()
self.append('}')
+
def cast(self, targetvar, fromtype, fromvar, targettype):
if fromtype == 'void' and targettype == 'void':
return
Modified: pypy/dist/pypy/translator/js/opwriter.py
==============================================================================
--- pypy/dist/pypy/translator/js/opwriter.py (original)
+++ pypy/dist/pypy/translator/js/opwriter.py Thu Dec 1 13:11:32 2005
@@ -124,7 +124,7 @@
self.codewriter.cast(targetvar, mult_type, res_val, mult_type)
def _skipped(self, op):
- #self.codewriter.comment('Skipping operation %s()' % op.opname)
+ self.codewriter.comment('Skipping operation %s()' % op.opname)
pass
keepalive = _skipped
@@ -389,4 +389,8 @@
#Stackless
def yield_current_frame_to_caller(self, op):
- self._skipped(op)
+ '''special handling of this operation: call stack_unwind() to force the
+ current frame to be saved into the heap, but don't propagate the
+ unwind -- instead, capture it and return it normally'''
+ targetvar = self.db.repr_arg(op.result)
+ self.codewriter.call(targetvar, "ll_stack_unwind", specialreturnvalue="slp_return_current_frame_to_caller()")
Modified: pypy/dist/pypy/translator/js/src/ll_stackless.js
==============================================================================
--- pypy/dist/pypy/translator/js/src/ll_stackless.js (original)
+++ pypy/dist/pypy/translator/js/src/ll_stackless.js Thu Dec 1 13:11:32 2005
@@ -3,6 +3,7 @@
var slp_frame_stack_top = null;
var slp_frame_stack_bottom = null;
var slp_return_value = undefined;
+var slp_stack_depth = 0;
// This gets called with --log
@@ -10,7 +11,7 @@
try {
alert(s); // in browser
} catch (e) {
- print('log:' + s); // commandline
+ print('log: ' + s); // commandline
}
}
@@ -22,152 +23,120 @@
return s
}
-//
+// example function for testing
+
+function ll_stackless_stack_frames_depth() {
+ if (!slp_frame_stack_top) {
+ LOG("ll_stackless_stack_frames_depth init");
+ slp_frame_stack_top = slp_frame_stack_bottom = slp_new_frame_simple(ll_stackless_stack_frames_depth);
+ return;
+ }
-function ll_stack_too_big_helper(depth) {
- if (depth > 0) {
- ll_stack_too_big_helper(depth-1)
+ LOG("ll_stackless_stack_frames_depth resume");
+ var f = slp_frame_stack_top;
+ slp_frame_stack_top = null;
+ for (var result = 0;f;result++) {
+ f = f.f_back;
}
-}
+ return result;
+}
+
+//
function ll_stack_too_big() {
- try {
- ll_stack_too_big_helper(5); // some magic number that seems to work
- } catch (e) { //stack overflow when recursing some more
- LOG("stack is too big")
- return true;
- }
- LOG("stack is not too big yet")
- return false;
-}
+ var result = slp_stack_depth > 500; // Firefox has a recursion limit of 1000 (others allow more)
+ LOG("ll_stack_to_big result=" + result);
+ return result;
+}
function slp_new_frame(targetvar, func, resume_blocknum, vars) {
- LOG("starting slp_new_frame("+targetvar+","+function_name(func)+","+resume_blocknum+","+vars.toSource()+")");
+ //LOG("slp_new_frame("+targetvar+","+function_name(func)+","+resume_blocknum+","+vars.toSource()+")");
+ LOG("slp_new_frame("+function_name(func)+")");
var f = new Object();
f.func = func;
f.targetvar = targetvar;
f.resume_blocknum = resume_blocknum;
f.vars = vars;
f.f_back = null;
- // push below current bottom so after unwinding the current stack
- // the slp_frame_stack will be correctly sorted
- slp_frame_stack_bottom.f_back = f;
- slp_frame_stack_bottom = f;
- LOG("finished slp_new_frame");
+ slp_frame_stack_bottom.f_back = f; // push below bottom, to keep stack
+ slp_frame_stack_bottom = f; // correctly sorted after unwind
}
function slp_new_frame_simple(func) {
- LOG("starting slp_new_frame_simple("+function_name(func)+")");
+ LOG("slp_new_frame_simple("+function_name(func)+")");
var f = new Object();
f.func = func;
f.targetvar = undefined;
f.resume_blocknum = undefined;
f.vars = undefined;
f.f_back = null;
- LOG("finished slp_new_frame_simple");
return f; // note: the non-simple version returns nothing
}
-// <UNTESTED>
-
function ll_stack_unwind() {
- LOG("starting ll_stackless_stack_unwind");
+ LOG("ll_stack_unwind");
if (slp_frame_stack_top) {
- slp_frame_stack_top = null; // no need to resume
+ slp_frame_stack_top = null;
} else {
slp_frame_stack_top = slp_frame_stack_bottom = slp_new_frame_simple(ll_stack_unwind);
}
- LOG("finished ll_stackless_stack_unwind");
+ LOG('slp_frame_stack_top='+slp_frame_stack_top + ', slp_frame_stack_bottom='+slp_frame_stack_bottom)
+ return null;
}
-// // ll_stack_unwind = ll_stackless_stack_unwind; // alias (XXX really need both?)
-// ll_stackless_stack_unwind = ll_stack_unwind; // alias (XXX really need both?)
function slp_return_current_frame_to_caller() {
- LOG("starting slp_return_current_frame_to_caller");
- if (!slp_frame_stack_top) alert('!slp_frame_stack_top');
- if (!slp_frame_stack_bottom) alert('!slp_frame_stack_bottom');
+ LOG("slp_return_current_frame_to_caller");
+ if (!slp_frame_stack_top) log('!slp_frame_stack_top');
+ if (!slp_frame_stack_bottom) log('!slp_frame_stack_bottom');
var result = slp_frame_stack_top;
- slp_frame_stack_bottom.f_back = slp_new_frame_simple(slp_return_current_frame_to_caller);
+ slp_frame_stack_bottom.f_back = slp_new_frame_simple(slp_end_of_yielding_function); //special case!
slp_frame_stack_top = slp_frame_stack_bottom = null; // stop unwinding
- LOG("finished slp_return_current_frame_to_caller");
return result;
}
function slp_end_of_yielding_function() {
- LOG("starting slp_end_of_yielding_function");
- if (!slp_frame_stack_top) alert('!slp_frame_stack_top'); // can only resume from slp_return_current_frame_to_caller()
- if (!slp_return_value) alert('!slp_return_value');
+ LOG("slp_end_of_yielding_function");
+ if (!slp_frame_stack_top) log('slp_end_of_yielding_function !slp_frame_stack_top'); // can only resume from slp_return_current_frame_to_caller()
+ if (!slp_return_value) log('slp_end_of_yielding_function !slp_return_value');
slp_frame_stack_top = slp_return_value;
- LOG("finished slp_end_of_yielding_function");
- return null; // XXX or just return?
+ return null;
}
-function ll_stackless_switch(c) {
- LOG("starting ll_stackless_switch");
+function ll_stackless_switch__frame_stack_topPtr(c) {
+ LOG("ll_stackless_switch__frame_stack_topPtr");
var f;
var result;
if (slp_frame_stack_top) { //resume
- LOG("slp_frame_stack_top != null");
- // ready to do the switch. The current (old) frame_stack_top is
- // f.f_back, which we store where it will be found immediately
- // after the switch
+ LOG("slp_frame_stack_top != null, SWITCH");
+ // ready to do the switch. The current (old) frame_stack_top is f.f_back,
+ // which we store where it will be found immediately after the switch
f = slp_frame_stack_top;
result = f.f_back;
// grab the saved value of 'c' and do the switch
slp_frame_stack_top = f.p0;
- LOG("finished ll_stackless_switch");
return result;
}
LOG("slp_frame_stack_top == null");
// first, unwind the current stack
- f = slp_new_frame_simple(ll_stackless_switch);
+ f = slp_new_frame_simple(ll_stackless_switch__frame_stack_topPtr);
f.p0 = c;
slp_frame_stack_top = slp_frame_stack_bottom = f;
- LOG("finished ll_stackless_switch");
- return null;
-}
-ll_stackless_switch__frame_stack_topPtr = ll_stackless_switch; // alias (XXX really need both?)
-
-// </UNTESTED>
-
-// example function for testing
-
-function ll_stackless_stack_frames_depth() {
- if (!slp_frame_stack_top) {
- LOG("starting ll_stackless_stack_frames_depth init");
- slp_frame_stack_top = slp_frame_stack_bottom = slp_new_frame_simple(ll_stackless_stack_frames_depth);
- LOG("finished ll_stackless_stack_frames_depth init");
- return;
- }
-
- LOG("starting ll_stackless_stack_frames_depth resume");
- var f = slp_frame_stack_top;
- slp_frame_stack_top = null;
- for (var result = 0;f;result++) {
- f = f.f_back;
- }
- LOG("stack_frames_depth = " + result);
- LOG("finished ll_stackless_stack_frames_depth resume");
- return result;
}
// main dispatcher loop
function slp_main_loop() {
var f_back;
- LOG("starting slp_main_loop");
while (true) {
- LOG("slp_main_loop (outer loop)");
-
slp_frame_stack_bottom = null;
pending = slp_frame_stack_top;
while (true) {
- LOG("slp_main_loop (inner loop)");
f_back = pending.f_back;
LOG('calling: ' + function_name(pending.func));
+ slp_stack_depth = 0; // we are restarting to recurse
slp_return_value = pending.func(); // params get initialized in the function because it's a resume!
if (slp_frame_stack_top) {
break;
@@ -180,26 +149,19 @@
}
if (slp_frame_stack_bottom) { // returning from switch()
- if (slp_frame_stack_bottom.f_back) alert('slp_frame_stack_bottom.f_back');
+ if (slp_frame_stack_bottom.f_back) log('slp_frame_stack_bottom.f_back');
slp_frame_stack_bottom.f_back = f_back;
}
}
- LOG("finished slp_main_loop");
}
function slp_entry_point(funcstring) {
- LOG("starting slp_standalone_entry_point");
+ slp_stack_depth = 0; /// initial stack depth
var result = eval(funcstring);
- LOG("RESULT = " + result);
- LOG("slp_frame_stack_bottom = " + slp_frame_stack_bottom);
- if (slp_frame_stack_bottom) {
- // if the stack unwound we need to run the dispatch loop
- // to retrieve the actual result
+ if (slp_frame_stack_bottom) { // get with dispatch loop when stack unwound
slp_main_loop();
result = slp_return_value;
}
- LOG("FINAL RESULT = " + result);
- LOG("finished slp_standalone_entry_point");
return result;
}
Modified: pypy/dist/pypy/translator/js/test/test_stackless.py
==============================================================================
--- pypy/dist/pypy/translator/js/test/test_stackless.py (original)
+++ pypy/dist/pypy/translator/js/test/test_stackless.py Thu Dec 1 13:11:32 2005
@@ -2,6 +2,7 @@
from pypy.rpython.rstack import stack_unwind, stack_frames_depth, stack_too_big
from pypy.rpython.rstack import yield_current_frame_to_caller
+from pypy.rpython.lltypesystem import lltype
from pypy.translator.js.test.runtest import compile_function
from pypy.translator.js import conftest
@@ -12,9 +13,6 @@
# ____________________________________________________________
def test_stack_depth():
- if not conftest.option.jsstackless:
- py.test.skip("stackless disabled (enable with py.test --stackless)")
-
def g1():
"just to check Void special cases around the code"
def g2(ignored):
@@ -37,9 +35,6 @@
assert data.strip() == '10'
def test_stack_withptr():
- if not conftest.option.jsstackless:
- py.test.skip("stackless disabled (enable with py.test --stackless)")
-
def f(n):
if n > 0:
res = f(n-1)
@@ -56,9 +51,6 @@
assert data.strip() == '10'
def test_stackless_manytimes():
- if not conftest.option.jsstackless:
- py.test.skip("stackless disabled (enable with py.test --stackless)")
-
def f(n):
if n > 0:
stack_frames_depth()
@@ -76,9 +68,7 @@
assert data.strip() == '100'
def test_stackless_arguments():
- if not conftest.option.jsstackless:
- py.test.skip("stackless disabled (enable with py.test --stackless)")
- py.test.skip("stackless feature not incomplete")
+ py.test.skip("stackless feature incomplete (empty Object mallocs)")
def f(n, d, t):
if n > 0:
@@ -97,10 +87,6 @@
def test_stack_too_big():
- if not conftest.option.jsstackless:
- py.test.skip("stackless disabled (enable with py.test --stackless)")
- #py.test.skip("stackless feature not incomplete")
-
def f1():
return stack_too_big()
def f2():
@@ -121,13 +107,10 @@
def fn():
return f(0)
data = wrap_stackless_function(fn)
- assert int(data.strip()) > 500
+ assert int(data.strip()) == 494
def test_stack_unwind():
- if not conftest.option.jsstackless:
- py.test.skip("stackless disabled (enable with py.test --stackless)")
-
def f():
stack_unwind()
return 42
@@ -136,24 +119,17 @@
assert int(data.strip()) == 42
def test_auto_stack_unwind():
- if not conftest.option.jsstackless:
- py.test.skip("stackless disabled (enable with py.test --stackless)")
- py.test.skip("stackless feature not incomplete")
-
def f(n):
if n == 1:
return 1
return (n+f(n-1)) % 1291
def fn():
- return f(10**6)
+ return f(10**4)
data = wrap_stackless_function(fn)
- assert int(data.strip()) == 704
-
+ assert int(data.strip()) == 697 #10**4==697(6seconds, 10**5==545(45seconds)
-def test_yield_frame():
- if not conftest.option.jsstackless:
- py.test.skip("stackless disabled (enable with py.test --stackless)")
+def test_yield_frame1():
py.test.skip("stackless feature not incomplete")
def g(lst):
@@ -172,7 +148,7 @@
lst.append(5)
frametop_after_return = frametop_before_6.switch()
lst.append(7)
- assert frametop_after_return is None
+ #assert frametop_after_return is None
n = 0
for i in lst:
n = n*10 + i
@@ -180,3 +156,31 @@
data = wrap_stackless_function(f)
assert int(data.strip()) == 1234567
+
+def test_yield_frame2():
+ py.test.skip("stackless feature incomplete (exception handling?)")
+
+ S = lltype.GcStruct("base", ('a', lltype.Signed))
+ s = lltype.malloc(S)
+
+ def g(x):
+ x.a <<= 2
+ frametop_before_5 = yield_current_frame_to_caller()
+ x.a <<= 4
+ frametop_before_7 = frametop_before_5.switch()
+ x.a <<= 6
+ return frametop_before_7
+
+ def f():
+ s.a = 1
+ frametop_before_4 = g(s)
+ s.a += 3
+ frametop_before_6 = frametop_before_4.switch()
+ s.a += 5
+ frametop_after_return = frametop_before_6.switch()
+ s.a += 7
+ #assert frametop_after_return is None
+ return s.a
+
+ data = wrap_stackless_function(f)
+ assert int(data.strip()) == 7495
More information about the Pypy-commit
mailing list