[pypy-svn] r39686 - pypy/dist/pypy/translator/js

fijal at codespeak.net fijal at codespeak.net
Fri Mar 2 15:33:19 CET 2007


Author: fijal
Date: Fri Mar  2 15:33:16 2007
New Revision: 39686

Modified:
   pypy/dist/pypy/translator/js/asmgen.py
   pypy/dist/pypy/translator/js/database.py
   pypy/dist/pypy/translator/js/function.py
   pypy/dist/pypy/translator/js/jts.py
   pypy/dist/pypy/translator/js/metavm.py
   pypy/dist/pypy/translator/js/support.py
Log:
(fijal, antonio) Major cleanup, use more code from oosupport


Modified: pypy/dist/pypy/translator/js/asmgen.py
==============================================================================
--- pypy/dist/pypy/translator/js/asmgen.py	(original)
+++ pypy/dist/pypy/translator/js/asmgen.py	Fri Mar  2 15:33:16 2007
@@ -113,12 +113,13 @@
         real_args = ",".join(l)
         self.right_hand.append("%s ( %s )" % (func_name, real_args))
 
-    def branch_if(self, arg, exitcase):
+    def branch_if(self, exitcase):
         def mapping(exitc):
             if exitc in ['True', 'False']:
                 return exitc.lower()
             return exitc
-        
+
+        arg = self.right_hand.pop()
         if hasattr(arg,'name'):
             arg_name = self.subst_table.get(arg.name, arg.name)
         else:
@@ -153,6 +154,7 @@
         self.codegenerator.openblock()
     
     def branch_else(self):
+        self.right_hand.pop()
         self.codegenerator.closeblock()
         self.codegenerator.write("else")
         self.codegenerator.openblock()
@@ -163,10 +165,6 @@
     def label(self, *args):
         self.codegenerator.openblock()
 
-    def branch(self, *args):
-        #self . codegenerator . closeblock ()
-        pass
-    
     def change_name(self, from_name, to_name):
     #    if isinstance(from_name,Variable) and isinstance(to_name,Variable):
     #        self.subst_table[from_name.name] = to_name.name

Modified: pypy/dist/pypy/translator/js/database.py
==============================================================================
--- pypy/dist/pypy/translator/js/database.py	(original)
+++ pypy/dist/pypy/translator/js/database.py	Fri Mar  2 15:33:16 2007
@@ -78,7 +78,7 @@
         try:
             return self.function_names[graph]
         except KeyError:
-            real_name = self.name_manager.uniquename(name)
+            real_name = self.name_manager.uniquename(name, lenmax=1111111)
             self.function_names[graph] = real_name
             return real_name
 

Modified: pypy/dist/pypy/translator/js/function.py
==============================================================================
--- pypy/dist/pypy/translator/js/function.py	(original)
+++ pypy/dist/pypy/translator/js/function.py	Fri Mar  2 15:33:16 2007
@@ -8,325 +8,40 @@
 from pypy.rpython.lltypesystem.lltype import SignedLongLong, UnsignedLongLong
 from pypy.rpython.ootypesystem import ootype
 from pypy.translator.oosupport.metavm import Generator,InstructionList
-from pypy.translator.cli.node import Node
+from pypy.translator.oosupport import function
 
 from pypy.translator.js.log import log
 from types import FunctionType
 
 import re
 
-class Function(Node, Generator):
-    def __init__(self, db, graph, name=None, is_method=False, is_entrypoint=False, _class = None):
-        self.db = db
-        self.cts = db.genoo.TypeSystem(db)
-        self.graph = graph
-        self.name = name or self.db.get_uniquename(self.graph, graph.name)
-        self.is_method = is_method
-        self.is_entrypoint = is_entrypoint
-        self.blocknum = {}
-        self._class = _class
-        self._set_args()
-        self._set_locals()
-        self.order = 0
-
-    def get_name(self):
-        return self.name
-
-    def __hash__(self):
-        return hash(self.graph)
-
-    def __eq__(self, other):
-        return self.graph == other.graph
-    
-    def __cmp__(self, other):
-        return cmp(self.order, other.order)
-
-    def _is_return_block(self, block):
-        return self.graph.returnblock is block
-    
-    def _is_raise_block(self, block):
-        return self.graph.exceptblock is block
-        
-    def loop_render_block(self, block, stop_blocks = []):
-        # FIXME: This code is awfull, some refactoring please
-        if block in stop_blocks:
-            return
-        log("Rendering block %r"%block)
-        
-        handle_exc = (block.exitswitch == flowmodel.c_last_exception)
-        if handle_exc:
-            self.ilasm.begin_try()
-
-        for op in block.operations:
-            self._render_op(op)
-        
-        if len(block.exits) == 0:
-            # return block
-            return_var = block.inputargs[0]
-            if return_var.concretetype is not Void:
-                self.load(return_var)
-                self.ilasm.ret()
-        elif block.exitswitch is None:
-            # single exit block
-            assert(len(block.exits) == 1)
-            link = block.exits[0]
-            self._setup_link(link)
-            self.render_block(link.target, stop_blocks)
-        elif block.exitswitch is flowmodel.c_last_exception:
-            # we've got exception block
-            raise NotImplementedError("Exception handling not implemented")
-        else:
-            if self.loops.has_key((True,block)) and self.loops.has_key((False,block)):
-                # double loop
-                #self.ilasm.branch_while
-                self.ilasm.branch_while_true()
-                self.ilasm.branch_if(block.exitswitch, self.loops[(True,block)])
-                self._setup_link(block.exits[True])
-                self.render_block(block.exits[True].target, stop_blocks+[block])
-                self.ilasm.branch_else()
-                self._setup_link(block.exits[False])
-                self.render_block(block.exits[False].target, stop_blocks+[block])
-                self.ilasm.close_branch()
-                for op in block.operations:
-                    self._render_op(op)
-                self.ilasm.close_branch()
-            elif self.loops.has_key((True, block)) or self.loops.has_key((False, block)):
-                # we've got loop
-                try:
-                    loop_case = self.loops[(True, block)]
-                except KeyError:
-                    loop_case = self.loops[(False, block)]
-                self.ilasm.branch_while(block.exitswitch, loop_case)
-                exit_case = block.exits[loop_case]
-                self._setup_link(exit_case)
-                self.render_block(exit_case.target, stop_blocks+[block])
-                for op in block.operations:
-                    self._render_op(op)
-                self.ilasm.close_branch()
-                exit_case = block.exits[not loop_case]
-                self._setup_link(exit_case)
-                #log (  )
-                self.render_block(exit_case.target, stop_blocks+[block])
-                #raise NotImplementedError ( "loop" )
-            else:
-                # just a simple if
-                assert(len(block.exits) == 2)
-                self.ilasm.branch_if(block.exitswitch, True)
-                self._setup_link(block.exits[True])
-                self.render_block(block.exits[True].target, stop_blocks)
-                self.ilasm.branch_else()
-                self._setup_link(block.exits[False])
-                self.render_block(block.exits[False].target, stop_blocks)
-                self.ilasm.close_branch()
-    
-    def render_block_operations(self, block):
-        for op in block.operations:
-            self._render_op(op)
-    
-    def render_block(self, startblock):
-        """ Block rendering routine using for variable trick
-        """
-        def basename(x):
-            return str(x).replace('.', '_')#[-1]
-        
-        self.ilasm.begin_for()
-        
-        block_map = {}
-        blocknum = 0
-        
-        graph = self.graph
-        
-        for block in graph.iterblocks():
-            block_map[block] = blocknum
-            blocknum += 1
-        
-        for block in graph.iterblocks():
-            self.ilasm.write_case(block_map[block])
-            
-            is_exc_block = (block.exitswitch is flowmodel.c_last_exception)
-            
-            if is_exc_block:
-                self.ilasm.begin_try()
-                
-            self.render_block_operations(block)
-            if self._is_return_block(block):
-                return_var = block.inputargs[0]
-                #if return_var.concretetype is not Void:
-                self.load(return_var)
-                self.ilasm.ret()
-            elif self._is_raise_block(block):
-                self.ilasm.throw(block.inputargs[1])
-            elif block.exitswitch is None:
-                self._setup_link(block.exits[0])
-                self.ilasm.jump_block(block_map[block.exits[0].target])
-            elif block.exitswitch is flowmodel.c_last_exception:
-                link = [i for i in block.exits if i.exitcase is None][0]
-                self._setup_link(link)
-                self.ilasm.jump_block(block_map[link.target])
-                self.ilasm.catch()
-                first = False
-                for link in [i for i in block.exits if i.exitcase is not None]:
-                    # XXX: Fix for 2.5
-                    class_name = str(link.exitcase)
-                    m = re.search("'(.*?)'", class_name)
-                    if not m:
-                        real_name = class_name
-                    else:
-                        real_name = m.group(1)
-                    s = "isinstanceof(exc, %s)"%basename(real_name)
-                    if not first:
-                        first = True
-                        self.ilasm.branch_if_string(s)
-                    else:
-                        self.ilasm.branch_elsif_string(s)
-                    self._setup_link(link, True)
-                    self.ilasm.jump_block(block_map[link.target])
-                # otherwise just re-raise it
-                self.ilasm.close_branch()
-                self.ilasm.throw_real("exc")
-                self.ilasm.close_branch()
-            elif len(block.exits) == 2:
-                self.ilasm.branch_if(block.exitswitch, True)
-                self._setup_link(block.exits[True])
-                self.ilasm.jump_block(block_map[block.exits[True].target])
-                self.ilasm.branch_else()
-                self._setup_link(block.exits[False])
-                self.ilasm.jump_block(block_map[block.exits[False].target])
-                self.ilasm.close_branch()
+class BaseGenerator(object):
+    def load(self, v):
+        if isinstance(v, flowmodel.Variable):
+            if v.name in self.argset:
+                selftype, selfname = self.args[0]
+                if self.is_method and v.name == selfname:
+                    self.ilasm.load_self()
+                else:
+                    self.ilasm.load_arg(v)
             else:
-                raise TypeError("Unknow block.exitswitch type %r"%block.exitswitch)
-        
-        self.ilasm.end_for()
-        #self.render_operations(
-
-    def render(self,ilasm):
-        if self.db.graph_name(self.graph) is not None and not self.is_method:
-            return # already rendered
-        
-        if self.is_method:
-            args = self.args[1:] # self is implicit
-        else:
-            args = self.args
-        
-        self.ilasm = ilasm
-        
-        #self.loops = LoopFinder(self.graph.startblock).loops
-        if self.is_method:
-            self.ilasm.begin_method(self.name, self._class, [i[1] for i in args])
-        else:
-            self.ilasm.begin_function(self.name, args)
-        #log("loops: %r"%self.loops)
-
-        # render all variables
-        
-        self.ilasm.set_locals(",".join(self.locals))
-        
-        self.render_block(self.graph.startblock)
-
-        self.ilasm.end_function()
-        if self.is_method:
-            pass # TODO
+                self.ilasm.load_local(v)
+        elif isinstance(v, flowmodel.Constant):
+            self.db.load_const(v.concretetype, v.value, self.ilasm)
         else:
-            self.db.record_function(self.graph, self.name)
-
-    def _setup_link(self, link, is_exc_link = False):
-        target = link.target
-        for to_load, to_store in zip(link.args, target.inputargs):
-            if to_load.concretetype is not Void:
-                if is_exc_link and isinstance(to_load, flowmodel.Variable) and re.match("last_exc_value", to_load.name):
-                    self.ilasm.load_str("exc")
-                else:
-                    self.load(to_load)
-                self.store(to_store)
-
+            assert False
 
-    def _set_locals(self):
-        # this code is partly borrowed from pypy.translator.c.funcgen.FunctionCodeGenerator
-        # TODO: refactoring to avoid code duplication
-        # and borrowed again from gencli
-
-        graph = self.graph
-        mix = [graph.getreturnvar()]
-        for block in graph.iterblocks():
-            self.blocknum[block] = len(self.blocknum)
-            mix.extend(block.inputargs)
-
-            for op in block.operations:
-                mix.extend(op.args)
-                mix.append(op.result)
-                if getattr(op, "cleanup", None) is not None:
-                    cleanup_finally, cleanup_except = op.cleanup
-                    for cleanupop in cleanup_finally + cleanup_except:
-                        mix.extend(cleanupop.args)
-                        mix.append(cleanupop.result)
-            for link in block.exits:
-                mix.extend(link.getextravars())
-                mix.extend(link.args)
-
-        # filter only locals variables, i.e.:
-        #  - must be variables
-        #  - must appear only once
-        #  - must not be function parameters
-        #  - must not have 'void' type
-
-        args = {}
-        for ctstype, name in self.args:
-            args[name] = True
-        
-        locals = []
-        seen = {}
-        for v in mix:
-            is_var = isinstance(v, flowmodel.Variable)
-            if id(v) not in seen and is_var and v.name not in args:
-                locals.append(v.name)
-                seen[id(v)] = True
-
-        self.locals = locals
-
-    def _set_args(self):
-        args = self.graph.getargs()
-        self.args = map(self.cts.llvar_to_cts, args)
-        self.argset = set([argname for argtype, argname in self.args])
-
-    def _get_block_name(self, block):
-        return 'block%s' % self.blocknum[block]
-
-    def _search_for_classes(self, op):
-        for arg in op.args:
-            lltype = None
-            if isinstance(arg, flowmodel.Variable):
-                lltype = arg.concretetype
-            elif isinstance(arg, flowmodel.Constant):
-                lltype = arg.value
-
-            if isinstance(lltype, ootype._view) and isinstance(lltype._inst, ootype._instance):
-                lltype = lltype._inst._TYPE
-
-            if isinstance(lltype, ootype.Instance):
-                self.db.pending_class(lltype)
-
-    def _render_op(self, op):
-        # FIXME: what to do here?
-        instr_list = self.db.genoo.opcodes.get(op.opname, None)
-        if instr_list is not None:
-            #assert isinstance(instr_list, InstructionList)
-            instr_list.render(self, op)
-        else:
-            if getoption('nostop'):
-                log.WARNING('Unknown opcode: %s ' % op)
-                self.ilasm.opcode(str(op))
+    def store(self, v):
+        if isinstance(v, flowmodel.Variable):
+            if v.concretetype is not Void:
+                self.ilasm.store_local(v)
             else:
-                assert False, 'Unknown opcode: %s ' % op
-
-    def field_name(self, obj, field):
-        class_, type_ = obj._lookup_field(field)
-        assert type_ is not None, 'Cannot find the field %s in the object %s' % (field, obj)
-        
-        class_name = self.class_name(class_)
-        field_type = self.cts.lltype_to_cts(type_)
-        return (field_type, class_name, field)
-
-    # following methods belongs to the Generator interface
+                self.ilasm.store_void()
+        else:
+            assert False
+    
+    def change_name(self, name, to_name):
+        self.ilasm.change_name(name, to_name)
 
     def add_comment(self, text):
         pass
@@ -342,7 +57,7 @@
 
     def call_graph(self, graph):
         self.db.pending_function(graph)
-        func_sig = self.function_signature(graph)        
+        func_sig = self.function_signature(graph)
         self.ilasm.call(func_sig)
     
     def call_external(self, name, args):
@@ -377,22 +92,6 @@
     
     def downcast(self, TYPE):
         pass
-
-    def load(self, v):
-        if isinstance(v, flowmodel.Variable):
-            if v.name in self.argset:
-                selftype, selfname = self.args[0]
-                if self.is_method and v.name == selfname:
-                    self.ilasm.load_self()
-                else:
-                    self.ilasm.load_arg(v)
-            else:
-                self.ilasm.load_local(v)
-
-        elif isinstance(v, flowmodel.Constant):
-            self.db.load_const(v.concretetype, v.value, self.ilasm)
-        else:
-            assert False
         
     def load_special(self, v):
         # special case for loading value
@@ -405,19 +104,7 @@
             self.ilasm.load_str(name)
         else:
             self.load(v)
-    
-    def store(self, v):
-        if isinstance(v, flowmodel.Variable):
-            if v.concretetype is not Void:
-                self.ilasm.store_local(v)
-            else:
-                self.ilasm.store_void()
-        else:
-            assert False
-    
-    def change_name(self, name, to_name):
-        self.ilasm.change_name(name, to_name)
-    
+            
     def cast_function(self, name, num):
         self.ilasm.cast_function(name, num)
 
@@ -440,3 +127,101 @@
         self.load(base_obj)
         self.load(item)
         self.ilasm.list_getitem()
+
+    def branch_unconditionally(self, target_label):
+        self.ilasm.jump_block(self.block_map[target_label])
+
+    def branch_conditionally(self, exitcase, target_label):
+        self.ilasm.branch_if(exitcase)
+        self.ilasm.jump_block(self.block_map[target_label])
+        self.ilasm.close_branch()
+
+class Function(function.Function, BaseGenerator):
+    def __init__(self, db, graph, name=None, is_method=False,
+                 is_entrypoint=False, _class=None):
+        self._class = _class
+        super(Function, self).__init__(db, graph, name, is_method, is_entrypoint)
+        self._set_args()
+        self._set_locals()
+        self.order = 0
+        self.name = name or self.db.get_uniquename(self.graph, self.graph.name)
+
+    def _setup_link(self, link, is_exc_link = False):
+        target = link.target
+        for to_load, to_store in zip(link.args, target.inputargs):
+            if to_load.concretetype is not Void:
+                if is_exc_link and isinstance(to_load, flowmodel.Variable) and re.match("last_exc_value", to_load.name):
+                    self.ilasm.load_str("exc")
+                else:
+                    self.load(to_load)
+                self.store(to_store)
+
+    def _create_generator(self, ilasm):
+        return self
+
+    def begin_render(self):
+        block_map = {}
+        for blocknum, block in enumerate(self.graph.iterblocks()):
+            block_map[self._get_block_name(block)] = blocknum
+        self.block_map = block_map
+
+        if self.is_method:
+            args = self.args[1:] # self is implicit
+        else:
+            args = self.args
+        if self.is_method:
+            self.ilasm.begin_method(self.name, self._class, [i[1] for i in args])
+        else:
+            self.ilasm.begin_function(self.name, args)
+        self.ilasm.set_locals(",".join([i[1] for i in self.locals]))
+        self.ilasm.begin_for()
+
+    def render_return_block(self, block):
+        return_var = block.inputargs[0]
+        if return_var.concretetype is not Void:
+            self.load(return_var)
+            self.ilasm.ret()
+        else:
+            self.ilasm.load_void()
+            self.ilasm.ret()
+
+    def end_render(self):
+        self.ilasm.end_for()        
+        self.ilasm.end_function()
+
+    def render_raise_block(self, block):
+        self.ilasm.throw(block.inputargs[1])
+
+    def end_try(self, target_label):
+        self.ilasm.jump_block(self.block_map[target_label])
+        self.ilasm.catch()
+        #self.ilasm.close_branch()
+
+    def record_ll_meta_exc(self, ll_meta_exc):
+        pass
+
+    def begin_catch(self, llexitcase):
+        real_name = self.cts.lltype_to_cts(llexitcase._inst.class_._INSTANCE)
+        s = "isinstanceof(exc, %s)"%real_name
+        self.ilasm.branch_if_string(s)
+    
+    def end_catch(self, target_label):
+        """ Ends the catch block, and branchs to the given target_label as the
+        last item in the catch block """
+        self.ilasm.close_branch()
+
+    def store_exception_and_link(self, link):
+        self._setup_link(link, True)
+        self.ilasm.jump_block(self.block_map[self._get_block_name(link.target)])
+
+    def after_except_block(self):
+        #self.ilasm.close_branch()
+        self.ilasm.throw_real("exc")
+        self.ilasm.close_branch()
+
+    def set_label(self, label):
+        self.ilasm.write_case(self.block_map[label])
+        #self.ilasm.label(label)
+
+    def begin_try(self):
+        self.ilasm.begin_try()

Modified: pypy/dist/pypy/translator/js/jts.py
==============================================================================
--- pypy/dist/pypy/translator/js/jts.py	(original)
+++ pypy/dist/pypy/translator/js/jts.py	Fri Mar  2 15:33:16 2007
@@ -27,8 +27,11 @@
     def __init__(self, db):
         self.db = db
     
-    def __class(self, name):
-        return name.replace(".", "_")
+    #def __class(self, name):
+    #    return name.replace(".", "_")
+
+    def escape_name(self, name):
+        return name.replace('.', '_')
     
     def llvar_to_cts(self, var):
         return 'var ', var.name
@@ -36,7 +39,7 @@
     def lltype_to_cts(self, t):
         if isinstance(t, ootype.Instance):
             self.db.pending_class(t)
-            return self.__class(t._name)
+            return self.escape_name(t._name)
         elif isinstance(t, ootype.List):
             return "Array"
         elif isinstance(t, lltype.Primitive):
@@ -57,7 +60,8 @@
     def graph_to_signature(self, graph, is_method = False, func_name = None):
         func_name = func_name or self.db.get_uniquename(graph,graph.name)
         
-        args = graph.getargs()
+        args = [arg for arg in graph.getargs() if
+                arg.concretetype is not ootype.Void]
         if is_method:
             args = args[1:]
 

Modified: pypy/dist/pypy/translator/js/metavm.py
==============================================================================
--- pypy/dist/pypy/translator/js/metavm.py	(original)
+++ pypy/dist/pypy/translator/js/metavm.py	Fri Mar  2 15:33:16 2007
@@ -63,7 +63,8 @@
 
     def _render_function(self, generator, graph, args):
         for func_arg in args[1:]: # push parameters
-            generator.load(func_arg)
+            if func_arg.concretetype is not ootype.Void:
+                generator.load(func_arg)
         generator.call_graph(graph)
     
     def _render_method(self, generator, method_name, args):

Modified: pypy/dist/pypy/translator/js/support.py
==============================================================================
--- pypy/dist/pypy/translator/js/support.py	(original)
+++ pypy/dist/pypy/translator/js/support.py	Fri Mar  2 15:33:16 2007
@@ -55,10 +55,8 @@
         
         self.predefined = set(predefined_classes_and_objects)
 
-    def uniquename(self, name):
-        #if self.js.compress and name != self.js.functions[0].func_name and is_optimized_function(name) and name.startswith("ll_issubclass__object_vtablePtr_object_vtablePtr"):
-        #    name = 'f'
-        return NameManager.uniquename(self, name)
+    #def uniquename(self, name, lenmax=0):
+    #    return NameManager.uniquename(self, , lenmax)
 
     def ensure_non_reserved(self, name):
         while name in self.reserved:


More information about the pypy-svn mailing list