from pypy.translator.backendopt.support import log, all_operations, annotate import pypy.rpython.raisingops.raisingops log = log.raisingop2directcall def is_raisingop(op): s = op.opname if (not s.startswith('int_') and not s.startswith('uint_') and not s.startswith('float_') and not s.startswith('llong_')): return False if not s.endswith('_zer') and not s.endswith('_ovf') and not s.endswith('_val'): #not s in special_operations: return False return True def raisingop2direct_call(translator, graphs=None): """search for operations that could raise an exception and change that operation into a direct_call to a function from the raisingops directory. This function also needs to be annotated and specialized. note: this could be extended to allow for any operation to be changed into a direct_call to a (RPython) function! """ #special_operations = "int_floordiv int_mod".split() if graphs is None: graphs = translator.graphs log('starting') seen = {} for op in all_operations(graphs): if not is_raisingop(op): continue func = getattr(pypy.rpython.raisingops.raisingops, op.opname, None) if not func: log.warning("%s not found" % op.opname) continue if op.opname not in seen: seen[op.opname] = 0 seen[op.opname] += 1 op.args.insert(0, annotate(translator, func, op.result, op.args)) op.opname = 'direct_call' #statistics... for k, v in seen.iteritems(): log("%dx %s" % (v, k)) #specialize newly annotated functions if seen != {}: translator.rtyper.specialize_more_blocks() #rename some operations (that were introduced in the newly specialized graphs) #so this transformation becomes idempotent... #for op in all_operations(graphs): # if op.opname in special_operations: # log('renamed %s to %s_' % (op.opname, op.opname)) # op.opname += '_' #selfdiagnostics... assert that there are no more raisingops for op in all_operations(graphs): if is_raisingop(op): log.warning("%s not transformed" % op.opname) #translator.view() log('finished')