def __init__(self, *args, **kwargs): OOFunction.__init__(self, *args, **kwargs) if hasattr(self.db.genoo, 'exceptiontransformer'): self.auto_propagate_exceptions = False namespace = getattr(self.graph.func, '_namespace_', None) if namespace: if '.' in namespace: self.namespace, self.classname = namespace.rsplit('.', 1) else: self.namespace = None self.classname = namespace else: self.namespace = None self.classname = None
def __init__(self, db, classty, name, jargtypes, jrettype, graph, is_static): """ classty: the JvmClassType object this is a part of (even static functions have a class) name: the name of the function jargtypes: JvmType of each argument jrettype: JvmType this function returns graph: the graph representing the body of the function is_static: boolean flag indicate whether func is static (!) """ OOFunction.__init__(self, db, graph, name, not is_static) self.classty = classty self.jargtypes = jargtypes self.jrettype = jrettype self._block_labels = {}
def _dont_store(self, to_load, to_store): # ugly workaround to make the exceptiontransformer work with # valuetypes: when exceptiontransforming a function whose result is a # .NET valuetype, it tries to store a null into the return variable. # Since it is not possible to store a null into a valuetype, and that # in that case the value is not used anyway, we simply ignore it. from rpython.translator.cli.dotnet import NativeInstance if isinstance(to_load, flowmodel.Constant): value = to_load.value is_null = (not isinstance(value, CDefinedIntSymbolic)) and (not value) T = ootype.typeOf(to_load.value) if isinstance(T, NativeInstance) and T._is_value_type and is_null: return True return OOFunction._dont_store(self, to_load, to_store)
def record_ll_meta_exc(self, ll_meta_exc): # record the type only if it doesn't belong to a native_class ll_exc = ll_meta_exc._INSTANCE NATIVE_INSTANCE = ll_exc._hints.get('NATIVE_INSTANCE', None) if NATIVE_INSTANCE is None: OOFunction.record_ll_meta_exc(self, ll_meta_exc)
def _render_op(self, op): self.generator.add_comment(str(op)) OOFunction._render_op(self, op)
def render_normal_block(self, block): """ Overload OOFunction.render_normal_block: we intercept blocks where the exitcase tests a bool variable with one use so as to generate more efficient code. For example, the naive code generation for a test like 'if x < y' yields something like: push x push y jump_if_less_than true false: push 0 jump done true: push 1 done: store_into_local_var load_from_local_var jump_if_true true_destination jump false_destination when it could (should) be push x push y jump_if_less_than true_destination jump false_destination """ def not_in_link_args(v): for link in block.exits: if v in link.args: return False return True def true_false_exits(): if block.exits[0].exitcase: return block.exits[0], block.exits[1] return block.exits[1], block.exits[0] if block.operations: # Look for a case where the block switches on a bool variable # which is produced by the last operation and not used # anywhere else, and where the last operation is a comparison. # Watch out for a last operation like: # v1 = same_as([int_lt(i, j)]) last_op = block.operations[-1] while (last_op.opname == "same_as" and isinstance(last_op.args[0], SubOperation)): last_op = last_op.args[0].op if (block.exitswitch is not None and block.exitswitch.concretetype is ootype.Bool and block.operations[-1].result is block.exitswitch and can_branch_directly(last_op.opname) and not_in_link_args(block.exitswitch)): self.generator.add_comment( "short-circuit final comparison on %s, block has %d ops" % ( block.exitswitch, len(block.operations))) for op in block.operations[:-1]: self._render_op(op) self.generator.add_comment( "inlining comparison: %r" % (last_op),) for arg in last_op.args: self.ilasm.load(arg) truelink, falselink = true_false_exits() true_label = self.next_label('link_true') branch_if(self.ilasm, last_op.opname, true_label) self._follow_link(falselink) self.set_label(true_label) self._follow_link(truelink) return return OOFunction.render_normal_block(self, block)