[pypy-svn] r19870 - in pypy/dist/pypy/translator/js: . test

ericvrp at codespeak.net ericvrp at codespeak.net
Mon Nov 14 14:36:49 CET 2005


Author: ericvrp
Date: Mon Nov 14 14:36:47 2005
New Revision: 19870

Modified:
   pypy/dist/pypy/translator/js/codewriter.py
   pypy/dist/pypy/translator/js/database.py
   pypy/dist/pypy/translator/js/funcnode.py
   pypy/dist/pypy/translator/js/js.py
   pypy/dist/pypy/translator/js/opwriter.py
   pypy/dist/pypy/translator/js/test/runtest.py
   pypy/dist/pypy/translator/js/test/test_stackless.py
Log:
Stackless Javascript, work in progress...


Modified: pypy/dist/pypy/translator/js/codewriter.py
==============================================================================
--- pypy/dist/pypy/translator/js/codewriter.py	(original)
+++ pypy/dist/pypy/translator/js/codewriter.py	Mon Nov 14 14:36:47 2005
@@ -52,7 +52,7 @@
         self.indent_more()
         self.append("case %d:" % blocknum)
         self.indent_more()
-        self._currentblocknum = blocknum
+        self._current_blocknum = blocknum
 
     def closeblock(self):
         if not self._skip_closeblock:
@@ -65,7 +65,7 @@
         self.append(decl)
 
     def _goto_block(self, blocknum):
-        if blocknum == self._currentblocknum + 1:
+        if blocknum == self._current_blocknum + 1:
             self._skip_closeblock = True
         else:
             self.append('block = ' + str(blocknum))
@@ -109,8 +109,9 @@
         self.decl     = decl
         self.funcnode = funcnode
         self.blocks   = blocks
-        self._save_blocknum   = len(blocks)+1000
-        self._resume_blocknum = len(blocks)+1001
+        self._savehandler_blocknum   = 1000
+        self._resumehandler_blocknum = 1001
+        self._resume_blocknum        = 2000
         self._usedvars = {}
         paramstr = decl.split('(')[1][:-1]
         for param in paramstr.split(','):
@@ -132,7 +133,7 @@
             self.append("var %s" % ', '.join(self._usedvars.keys()))
             
         if self.js.stackless:
-            initial_block = "slp_frame_stack_top ? %d : 0" % self._resume_blocknum
+            initial_block = "slp_frame_stack_top ? %d : 0" % self._resumehandler_blocknum
         else:
             initial_block = '0'
 
@@ -142,18 +143,18 @@
 
     def closefunc(self): 
         if self.js.stackless:   #save&restore all local variable for now
-            self.openblock(self._save_blocknum)
+            self.openblock(self._savehandler_blocknum)
             self.comment('save block for stackless feature')
             self.append('slp_frame_stack_top = new Array(slp_resume_block, %s)' % ', '.join(self._usedvars.keys()))
             self.append('return undefined')
             self.skip_closeblock()
             self.closeblock()
 
-            self.openblock(self._resume_blocknum)
+            self.openblock(self._resumehandler_blocknum)
             self.comment('resume block for stackless feature')
-            self.append('block = slp_frame_stack_top[0]')
+            self.append('%-19s = slp_frame_stack_top[0]' % 'block')
             for i, k in enumerate(self._usedvars.keys()):
-                self.append('%s = slp_frame_stack_top[%d]' % (k, i+1))
+                self.append('%-19s = slp_frame_stack_top[%d]' % (k, i+1))
             self.append('slp_frame_stack_top = null')
             self.closeblock()
 
@@ -180,6 +181,12 @@
         if not exceptions:
             assert no_exception is None
             self.append('%s = %s(%s)' % (targetvar, functionref, args))
+            if self.js.stackless:
+                self.append('if (slp_frame_stack_bottom) { slp_resume_block = %d; block = %d; break; }' % (self._resume_blocknum, self._savehandler_blocknum))
+                self.indent_less()
+                self.append('case %d:' % self._resume_blocknum)
+                self.indent_more()
+                self._resume_blocknum += 1
         else:
             assert no_exception is not None
             no_exception_label, no_exception_exit = no_exception

Modified: pypy/dist/pypy/translator/js/database.py
==============================================================================
--- pypy/dist/pypy/translator/js/database.py	(original)
+++ pypy/dist/pypy/translator/js/database.py	Mon Nov 14 14:36:47 2005
@@ -2,7 +2,7 @@
 import sys
 
 from pypy.translator.js.support import JavascriptNameManager
-from pypy.translator.js.funcnode import FuncNode
+from pypy.translator.js.funcnode import FuncNode, ExternalFuncNode
 from pypy.translator.js.structnode import StructNode, StructVarsizeNode
 from pypy.translator.js.arraynode import ArrayNode, StrArrayNode, VoidArrayNode
 from pypy.translator.js.opaquenode import OpaqueNode
@@ -35,7 +35,11 @@
     def create_constant_node(self, type_, value):
         node = None
         if isinstance(type_, lltype.FuncType):
-            node = FuncNode(self, value)
+            if getattr(value._callable, "suggested_primitive", False):
+                log('suggested_primitive (external function)', value.graph.name)
+                node = ExternalFuncNode(self, value)
+            else:
+                node = FuncNode(self, value)
 
         elif isinstance(type_, lltype.Struct):
             if type_._arrayfld:

Modified: pypy/dist/pypy/translator/js/funcnode.py
==============================================================================
--- pypy/dist/pypy/translator/js/funcnode.py	(original)
+++ pypy/dist/pypy/translator/js/funcnode.py	Mon Nov 14 14:36:47 2005
@@ -112,3 +112,11 @@
         assert len(block.inputargs) == 2
         codewriter.throw( str(block.inputargs[1]) )
         codewriter.skip_closeblock()
+
+
+class ExternalFuncNode(Node):
+    def __init__(self, db, value):
+        self.db = db
+        self.value = value
+        self.ref   = db.namespace.uniquename(value.graph.name)
+        self.graph = value.graph

Modified: pypy/dist/pypy/translator/js/js.py
==============================================================================
--- pypy/dist/pypy/translator/js/js.py	(original)
+++ pypy/dist/pypy/translator/js/js.py	Mon Nov 14 14:36:47 2005
@@ -8,6 +8,7 @@
 '''
 
 import py
+import os
 
 from pypy.rpython.rmodel import inputconst, getfunctionptr
 from pypy.rpython.lltypesystem import lltype
@@ -18,6 +19,12 @@
 from pypy.translator.js.log import log
 from pypy.translator.js import conftest
 
+def _path_join(root_path, *paths):
+    path = root_path
+    for p in paths:
+        path = os.path.join(path, p)
+    return path
+
 class JS(object):   # JS = Javascript
     def __init__(self, translator, entrypoint=None, stackless=False):
         self.db = Database(translator)
@@ -67,11 +74,12 @@
         codewriter.newline()
 
         if self.stackless:
-            codewriter.comment("Global data for stackless feature")
-            codewriter.newline()
-            codewriter.append("slp_frame_stack_top = null")
-            codewriter.append("slp_resume_block    = 0")
-            codewriter.newline()
+            s = 'll_stackless.js'
+        else:
+            s = 'stack.js'
+        src_filename = _path_join(os.path.dirname(__file__), 'src', s)
+        f.write(open(src_filename).read())
+
         f.close()
 
         entry_point= c.value._obj

Modified: pypy/dist/pypy/translator/js/opwriter.py
==============================================================================
--- pypy/dist/pypy/translator/js/opwriter.py	(original)
+++ pypy/dist/pypy/translator/js/opwriter.py	Mon Nov 14 14:36:47 2005
@@ -242,9 +242,6 @@
         targetvar = self.db.repr_arg(op.result)
         functionref = self.db.repr_arg(op_args[0])
         argrefs = self.db.repr_arg_multi(op_args[1:])
-        if functionref == 'll_stack_check': #XXX what to do here?
-            self.codewriter.comment('Skipping: %s = %s()' % (targetvar, functionref))
-            return
         self.codewriter.call(targetvar, functionref, argrefs)
 
     def invoke(self, op):
@@ -316,6 +313,7 @@
             f = self.db.namespace.ensure_non_reserved(op.args[1].value)
             self.codewriter.append('%s = %s.%s' % (targetvar, struct, f)) #XXX move to codewriter
         else:
+            self.codewriter.comment('getfield')
             self._skipped(op)
  
     def getsubstruct(self, op): 
@@ -336,6 +334,7 @@
             f = self.db.namespace.ensure_non_reserved(op.args[1].value)
             self.codewriter.append('%s.%s = %s' % (struct, f, valuevar)) #XXX move to codewriter
         else:
+            self.codewriter.comment('setfield')
             self._skipped(op)
 
     def getarrayitem(self, op):        
@@ -351,6 +350,7 @@
             #self.codewriter.load(targetvar, targettype, tmpvar)
             self.codewriter.load(targetvar, array, (index,))
         else:
+            self.codewriter.comment('getarrayitem')
             self._skipped(op)
 
     def getarraysubstruct(self, op):        
@@ -375,6 +375,7 @@
             #self.codewriter.store(valuetype, valuevar, tmpvar) 
             self.codewriter.store(array, (index,), valuevar)
         else:
+            self.codewriter.comment('setarrayitem')
             self._skipped(op)
 
     def getarraysize(self, op):
@@ -385,3 +386,7 @@
         #targettype = self.db.repr_arg_type(op.result)
         #self.codewriter.load(targetvar, targettype, tmpvar)
         self.codewriter.append('%s = %s.length' % (targetvar, array)) #XXX move to codewriter
+
+    #Stackless
+    def yield_current_frame_to_caller(self, op):
+        self._skipped(op)

Modified: pypy/dist/pypy/translator/js/test/runtest.py
==============================================================================
--- pypy/dist/pypy/translator/js/test/runtest.py	(original)
+++ pypy/dist/pypy/translator/js/test/runtest.py	Mon Nov 14 14:36:47 2005
@@ -17,19 +17,18 @@
 
 
 class compile_function(object):
-    def __init__(self, function, annotation, view=False):
+    def __init__(self, function, annotation, stackless=False, view=False):
         if not use_browsertest and not _CLI_is_on_path():
             py.test.skip('Javascript CLI (js) not found')
 
         t = Translator(function)
         a = t.annotate(annotation)
-        a.simplify()
         t.specialize()
         t.backend_optimizations(inline_threshold=0, mallocs=False)
         #t.backend_optimizations()
         if view:
             t.view()
-        self.js = JS(t, function)
+        self.js = JS(t, function, stackless)
         self.js.write_source()
 
     def __call__(self, *kwds):

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	Mon Nov 14 14:36:47 2005
@@ -1,33 +1,20 @@
 import py
 
-from pypy.translator.translator import Translator
-from pypy.translator.tool.cbuild import build_executable
-from pypy.annotation.model import SomeList, SomeString
-from pypy.annotation.listdef import ListDef
 from pypy.rpython.rstack import stack_unwind, stack_frames_depth, stack_too_big
 from pypy.rpython.rstack import yield_current_frame_to_caller
-import os
+from pypy.translator.js.test.runtest import compile_function
+from pypy.translator.js import conftest
 
 def wrap_stackless_function(fn):
-    def entry_point(argv):
-        os.write(1, str(fn())+"\n")
-        return 0
-
-    t = Translator(entry_point)
-    s_list_of_strings = SomeList(ListDef(None, SomeString()))
-    s_list_of_strings.listdef.resize()
-    ann = t.annotate([s_list_of_strings])
-    t.specialize()
-    cbuilder = t.cbuilder(standalone=True)
-    cbuilder.stackless = True
-    cbuilder.generate_source()
-    cbuilder.compile()
-    return cbuilder.cmdexec('')
+    jsfn = compile_function(fn, [], stackless=True)
+    return str(jsfn()) + "\n"
 
 # ____________________________________________________________
 
 def test_stack_depth():
-    py.test.skip("stackless not implemented yet")
+    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):
@@ -50,7 +37,9 @@
     assert data.strip() == '10'
 
 def test_stack_withptr():
-    py.test.skip("stackless not implemented yet")
+    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)
@@ -67,7 +56,9 @@
     assert data.strip() == '10'
 
 def test_stackless_manytimes():
-    py.test.skip("stackless not implemented yet")
+    if not conftest.option.jsstackless:
+        py.test.skip("stackless disabled (enable with py.test --stackless)")
+
     def f(n):
         if n > 0:
             stack_frames_depth()
@@ -85,7 +76,9 @@
     assert data.strip() == '100'
 
 def test_stackless_arguments():
-    py.test.skip("stackless not implemented yet")
+    if not conftest.option.jsstackless:
+        py.test.skip("stackless disabled (enable with py.test --stackless)")
+
     def f(n, d, t):
         if n > 0:
             res = f(n-1, d, t)
@@ -103,7 +96,9 @@
 
 
 def test_stack_too_big():
-    py.test.skip("stackless not implemented yet")
+    if not conftest.option.jsstackless:
+        py.test.skip("stackless disabled (enable with py.test --stackless)")
+
     def f1():
         return stack_too_big()
     def f2():
@@ -128,7 +123,9 @@
 
 
 def test_stack_unwind():
-    py.test.skip("stackless not implemented yet")
+    if not conftest.option.jsstackless:
+        py.test.skip("stackless disabled (enable with py.test --stackless)")
+
     def f():
         stack_unwind()
         return 42
@@ -137,7 +134,9 @@
     assert int(data.strip()) == 42
 
 def test_auto_stack_unwind():
-    py.test.skip("stackless not implemented yet")
+    if not conftest.option.jsstackless:
+        py.test.skip("stackless disabled (enable with py.test --stackless)")
+
     def f(n):
         if n == 1:
             return 1
@@ -150,7 +149,8 @@
 
 
 def test_yield_frame():
-    py.test.skip("stackless not implemented yet")
+    if not conftest.option.jsstackless:
+        py.test.skip("stackless disabled (enable with py.test --stackless)")
 
     def g(lst):
         lst.append(2)



More information about the Pypy-commit mailing list