[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