Example #1
0
 def produce_potential_short_preamble_ops(self, optimizer, shortboxes,
                                          descr):
     if self._lazy_setfield is not None:
         return
     for structvalue in self._cached_fields_getfield_op.keys():
         op = self._cached_fields_getfield_op[structvalue]
         if not op:
             continue
         if optimizer.getvalue(op.getarg(0)) in optimizer.opaque_pointers:
             continue
         if structvalue in self._cached_fields:
             if op.getopnum() == rop.SETFIELD_GC:
                 result = op.getarg(1)
                 if isinstance(result, Const):
                     newresult = result.clonebox()
                     optimizer.make_constant(newresult, result)
                     result = newresult
                 getop = ResOperation(rop.GETFIELD_GC, [op.getarg(0)],
                                      result, op.getdescr())
                 shortboxes.add_potential(getop, synthetic=True)
             if op.getopnum() == rop.SETARRAYITEM_GC:
                 result = op.getarg(2)
                 if isinstance(result, Const):
                     newresult = result.clonebox()
                     optimizer.make_constant(newresult, result)
                     result = newresult
                 getop = ResOperation(
                     rop.GETARRAYITEM_GC,
                     [op.getarg(0), op.getarg(1)], result, op.getdescr())
                 shortboxes.add_potential(getop, synthetic=True)
             elif op.result is not None:
                 shortboxes.add_potential(op)
Example #2
0
def copy_str_content(string_optimizer,
                     srcbox,
                     targetbox,
                     srcoffsetbox,
                     offsetbox,
                     lengthbox,
                     mode,
                     need_next_offset=True):
    if isinstance(srcbox, ConstPtr) and isinstance(srcoffsetbox, Const):
        M = 5
    else:
        M = 2
    if isinstance(lengthbox, ConstInt) and lengthbox.value <= M:
        # up to M characters are done "inline", i.e. with STRGETITEM/STRSETITEM
        # instead of just a COPYSTRCONTENT.
        for i in range(lengthbox.value):
            charbox = _strgetitem(string_optimizer, srcbox, srcoffsetbox, mode)
            srcoffsetbox = _int_add(string_optimizer, srcoffsetbox, CONST_1)
            assert isinstance(targetbox, BoxPtr)  # ConstPtr never makes sense
            string_optimizer.emit_operation(
                ResOperation(mode.STRSETITEM, [targetbox, offsetbox, charbox],
                             None))
            offsetbox = _int_add(string_optimizer, offsetbox, CONST_1)
    else:
        if need_next_offset:
            nextoffsetbox = _int_add(string_optimizer, offsetbox, lengthbox)
        else:
            nextoffsetbox = None
        assert isinstance(targetbox, BoxPtr)  # ConstPtr never makes sense
        op = ResOperation(
            mode.COPYSTRCONTENT,
            [srcbox, targetbox, srcoffsetbox, offsetbox, lengthbox], None)
        string_optimizer.emit_operation(op)
        offsetbox = nextoffsetbox
    return offsetbox
Example #3
0
 def has_pure_result(self, opnum, args, descr):
     op = ResOperation(opnum, args, None, descr)
     key = self.optimizer.make_args_key(op)
     op = self.optimizer.pure_operations.get(key, None)
     if op is None:
         return False
     return op.getdescr() is descr
Example #4
0
 def gen_malloc_nursery(self, size, v_result):
     """Try to generate or update a CALL_MALLOC_NURSERY.
     If that fails, generate a plain CALL_MALLOC_GC instead.
     """
     size = self.round_up_for_allocation(size)
     if not self.gc_ll_descr.can_use_nursery_malloc(size):
         return False
     #
     op = None
     if self._op_malloc_nursery is not None:
         # already a MALLOC_NURSERY: increment its total size
         total_size = self._op_malloc_nursery.getarg(0).getint()
         total_size += size
         if self.gc_ll_descr.can_use_nursery_malloc(total_size):
             # if the total size is still reasonable, merge it
             self._op_malloc_nursery.setarg(0, ConstInt(total_size))
             op = ResOperation(rop.INT_ADD, [
                 self._v_last_malloced_nursery,
                 ConstInt(self._previous_size)
             ], v_result)
     if op is None:
         # if we failed to merge with a previous MALLOC_NURSERY, emit one
         self.emitting_an_operation_that_can_collect()
         op = ResOperation(rop.CALL_MALLOC_NURSERY, [ConstInt(size)],
                           v_result)
         self._op_malloc_nursery = op
     #
     self.newops.append(op)
     self._previous_size = size
     self._v_last_malloced_nursery = v_result
     self.recent_mallocs[v_result] = None
     return True
Example #5
0
def patch_new_loop_to_load_virtualizable_fields(loop, jitdriver_sd):
    vinfo = jitdriver_sd.virtualizable_info
    extra_ops = []
    inputargs = loop.inputargs
    vable_box = inputargs[jitdriver_sd.index_of_virtualizable]
    i = jitdriver_sd.num_red_args
    loop.inputargs = inputargs[:i]
    for descr in vinfo.static_field_descrs:
        assert i < len(inputargs)
        box = inputargs[i]
        extra_ops.append(ResOperation(rop.GETFIELD_GC, [vable_box], box,
                                      descr))
        i += 1
    arrayindex = 0
    for descr in vinfo.array_field_descrs:
        vable = vable_box.getref_base()
        arraylen = vinfo.get_array_length(vable, arrayindex)
        arraybox = BoxPtr()
        extra_ops.append(
            ResOperation(rop.GETFIELD_GC, [vable_box], arraybox, descr))
        arraydescr = vinfo.array_descrs[arrayindex]
        assert i + arraylen <= len(inputargs)
        for index in range(arraylen):
            box = inputargs[i]
            extra_ops.append(
                ResOperation(rop.GETARRAYITEM_GC,
                             [arraybox, ConstInt(index)],
                             box,
                             descr=arraydescr))
            i += 1
        arrayindex += 1
    assert i == len(inputargs)
    loop.operations = extra_ops + loop.operations
Example #6
0
    def find_rewritable_bool(self, op, args):
        try:
            oldopnum = opboolinvers[op.getopnum()]
        except KeyError:
            pass
        else:
            targs = self.optimizer.make_args_key(
                ResOperation(oldopnum, [args[0], args[1]], None))
            if self.try_boolinvers(op, targs):
                return True

        try:
            oldopnum = opboolreflex[
                op.getopnum()]  # FIXME: add INT_ADD, INT_MUL
        except KeyError:
            pass
        else:
            targs = self.optimizer.make_args_key(
                ResOperation(oldopnum, [args[1], args[0]], None))
            oldop = self.get_pure_result(targs)
            if oldop is not None and oldop.getdescr() is op.getdescr():
                self.make_equal_to(op.result, self.getvalue(oldop.result))
                return True

        try:
            oldopnum = opboolinvers[opboolreflex[op.getopnum()]]
        except KeyError:
            pass
        else:
            targs = self.optimizer.make_args_key(
                ResOperation(oldopnum, [args[1], args[0]], None))
            if self.try_boolinvers(op, targs):
                return True

        return False
Example #7
0
 def get_token_for_call(self, cpu):
     if self.loop_token is not None:
         return self.loop_token
     args = [BoxInt()] + self.instantiate_arg_classes()
     if self.get_result_size(cpu.translate_support_code) == 0:
         result = None
         result_list = []
     else:
         if self.returns_a_pointer():
             result = BoxPtr()
         elif self.returns_a_float():
             result = BoxFloat()
         else:
             result = BoxInt()
         result_list = [result]
     operations = [
         ResOperation(rop.CALL, args[:], result, self),
         ResOperation(rop.GUARD_NO_EXCEPTION, [],
                      None,
                      descr=BasicFailDescr()),
         ResOperation(rop.FINISH, result_list, None, descr=BasicFailDescr())
     ]
     operations[1].fail_args = []
     loop_token = LoopToken()
     # note: the 'args' that we pass below is not the same object as the
     # 'args[:]' that was passed above to ResOperation, because we want
     # the argument to ResOperation to be non-resizable, but the argument
     # to compile_loop to be resizable.
     cpu.compile_loop(args, operations, loop_token)
     self.loop_token = loop_token
     return loop_token
Example #8
0
 def store_final_boxes_in_guard(self, op):
     descr = op.getdescr()
     assert isinstance(descr, compile.ResumeGuardDescr)
     modifier = resume.ResumeDataVirtualAdder(descr, self.resumedata_memo)
     newboxes = modifier.finish(self.values, self.pendingfields)
     if len(newboxes) > self.metainterp_sd.options.failargs_limit: # XXX be careful here
         compile.giveup()
     descr.store_final_boxes(op, newboxes)
     #
     if op.getopnum() == rop.GUARD_VALUE:
         if self.getvalue(op.getarg(0)) in self.bool_boxes:
             # Hack: turn guard_value(bool) into guard_true/guard_false.
             # This is done after the operation is emitted to let
             # store_final_boxes_in_guard set the guard_opnum field of the
             # descr to the original rop.GUARD_VALUE.
             constvalue = op.getarg(1).getint()
             if constvalue == 0:
                 opnum = rop.GUARD_FALSE
             elif constvalue == 1:
                 opnum = rop.GUARD_TRUE
             else:
                 raise AssertionError("uh?")
             newop = ResOperation(opnum, [op.getarg(0)], op.result, descr)
             newop.setfailargs(op.getfailargs())
             return newop
         else:
             # a real GUARD_VALUE.  Make it use one counter per value.
             descr.make_a_counter_per_value(op)
     return op
Example #9
0
File: pure.py Project: njues/Sypy
 def has_pure_result(self, opnum, args, descr):
     op = ResOperation(opnum, args, None, descr)
     key = self.optimizer.make_args_key(op)
     op = self.pure_operations.get(key, None)
     if op is None:
         return False
     return op.getdescr() is descr
Example #10
0
 def store_final_boxes_in_guard(self, op):
     descr = op.getdescr()
     assert isinstance(descr, compile.ResumeGuardDescr)
     modifier = resume.ResumeDataVirtualAdder(descr, self.resumedata_memo)
     try:
         newboxes = modifier.finish(self, self.pendingfields)
         if len(newboxes) > self.metainterp_sd.options.failargs_limit:
             raise resume.TagOverflow
     except resume.TagOverflow:
         raise compile.giveup()
     descr.store_final_boxes(op, newboxes)
     #
     if op.getopnum() == rop.GUARD_VALUE:
         if self.getvalue(op.getarg(0)) in self.bool_boxes:
             # Hack: turn guard_value(bool) into guard_true/guard_false.
             # This is done after the operation is emitted to let
             # store_final_boxes_in_guard set the guard_opnum field of the
             # descr to the original rop.GUARD_VALUE.
             constvalue = op.getarg(1).getint()
             if constvalue == 0:
                 opnum = rop.GUARD_FALSE
             elif constvalue == 1:
                 opnum = rop.GUARD_TRUE
             else:
                 raise AssertionError("uh?")
             newop = ResOperation(opnum, [op.getarg(0)], op.result, descr)
             newop.setfailargs(op.getfailargs())
             return newop
         else:
             # a real GUARD_VALUE.  Make it use one counter per value.
             descr.make_a_counter_per_value(op)
     return op
Example #11
0
    def optimize_VIRTUAL_REF_FINISH(self, op):
        # This operation is used in two cases.  In normal cases, it
        # is the end of the frame, and op.getarg(1) is NULL.  In this
        # case we just clear the vref.virtual_token, because it contains
        # a stack frame address and we are about to leave the frame.
        # In that case vref.forced should still be NULL, and remains
        # NULL; and accessing the frame through the vref later is
        # *forbidden* and will raise InvalidVirtualRef.
        #
        # In the other (uncommon) case, the operation is produced
        # earlier, because the vref was forced during tracing already.
        # In this case, op.getarg(1) is the virtual to force, and we
        # have to store it in vref.forced.
        #
        vrefinfo = self.optimizer.metainterp_sd.virtualref_info
        seo = self.optimizer.send_extra_operation

        # - set 'forced' to point to the real object
        objbox = op.getarg(1)
        if not self.optimizer.cpu.ts.CONST_NULL.same_constant(objbox):
            seo(ResOperation(rop.SETFIELD_GC, op.getarglist(), None,
                             descr = vrefinfo.descr_forced))

        # - set 'virtual_token' to TOKEN_NONE
        args = [op.getarg(0), ConstInt(vrefinfo.TOKEN_NONE)]
        seo(ResOperation(rop.SETFIELD_GC, args, None,
                         descr = vrefinfo.descr_virtual_token))
Example #12
0
 def get_token_for_call(self, cpu):
     if self.loop_token is not None:
         return self.loop_token
     args = [BoxInt()] + self.instantiate_arg_classes()
     if self.get_result_size(cpu.translate_support_code) == 0:
         result = None
         result_list = []
     else:
         if self.returns_a_pointer():
             result = BoxPtr()
         elif self.returns_a_float():
             result = BoxFloat()
         else:
             result = BoxInt()
         result_list = [result]
     operations = [
         ResOperation(rop.CALL, args, result, self),
         ResOperation(rop.GUARD_NO_EXCEPTION, [], None,
                      descr=BasicFailDescr()),
         ResOperation(rop.FINISH, result_list, None,
                      descr=BasicFailDescr())]
     operations[1].fail_args = []
     loop_token = LoopToken()
     cpu.compile_loop(args, operations, loop_token)
     self.loop_token = loop_token
     return loop_token
Example #13
0
    def export_state(self, targetop):
        original_jump_args = targetop.getarglist()
        jump_args = [
            self.getvalue(a).get_key_box() for a in original_jump_args
        ]

        assert self.optimizer.loop.resume_at_jump_descr
        resume_at_jump_descr = self.optimizer.loop.resume_at_jump_descr.clone_if_mutable(
        )
        assert isinstance(resume_at_jump_descr, ResumeGuardDescr)
        resume_at_jump_descr.rd_snapshot = self.fix_snapshot(
            jump_args, resume_at_jump_descr.rd_snapshot)

        modifier = VirtualStateAdder(self.optimizer)
        virtual_state = modifier.get_virtual_state(jump_args)

        values = [self.getvalue(arg) for arg in jump_args]
        inputargs = virtual_state.make_inputargs(values, self.optimizer)
        short_inputargs = virtual_state.make_inputargs(values,
                                                       self.optimizer,
                                                       keyboxes=True)

        if self.boxes_created_this_iteration is not None:
            for box in self.inputargs:
                self.boxes_created_this_iteration[box] = True

        short_boxes = ShortBoxes(self.optimizer, inputargs,
                                 self.boxes_created_this_iteration)

        self.optimizer.clear_newoperations()
        for i in range(len(original_jump_args)):
            if values[i].is_virtual():
                values[i].force_box(self.optimizer)
            if original_jump_args[i] is not jump_args[i]:
                op = ResOperation(rop.SAME_AS, [jump_args[i]],
                                  original_jump_args[i])
                self.optimizer.emit_operation(op)
        inputarg_setup_ops = self.optimizer.get_newoperations()

        target_token = targetop.getdescr()
        assert isinstance(target_token, TargetToken)
        targetop.initarglist(inputargs)
        target_token.virtual_state = virtual_state
        target_token.short_preamble = [
            ResOperation(rop.LABEL, short_inputargs, None)
        ]
        target_token.resume_at_jump_descr = resume_at_jump_descr

        exported_values = {}
        for box in inputargs:
            exported_values[box] = self.optimizer.getvalue(box)
        for op in short_boxes.operations():
            if op and op.result:
                box = op.result
                exported_values[box] = self.optimizer.getvalue(box)

        target_token.exported_state = ExportedState(short_boxes,
                                                    inputarg_setup_ops,
                                                    exported_values)
Example #14
0
 def rewrite_assembler(self, cpu, operations):
     # Perform two kinds of rewrites in parallel:
     #
     # - Add COND_CALLs to the write barrier before SETFIELD_GC and
     #   SETARRAYITEM_GC operations.
     #
     # - Remove all uses of ConstPtrs away from the assembler.
     #   Idea: when running on a moving GC, we can't (easily) encode
     #   the ConstPtrs in the assembler, because they can move at any
     #   point in time.  Instead, we store them in 'gcrefs.list', a GC
     #   but nonmovable list; and here, we modify 'operations' to
     #   replace direct usage of ConstPtr with a BoxPtr loaded by a
     #   GETFIELD_RAW from the array 'gcrefs.list'.
     #
     newops = []
     for op in operations:
         if op.opnum == rop.DEBUG_MERGE_POINT:
             continue
         # ---------- replace ConstPtrs with GETFIELD_RAW ----------
         # xxx some performance issue here
         for i in range(len(op.args)):
             v = op.args[i]
             if isinstance(v, ConstPtr) and bool(v.value):
                 addr = self.gcrefs.get_address_of_gcref(v.value)
                 # ^^^even for non-movable objects, to record their presence
                 if rgc.can_move(v.value):
                     box = BoxPtr(v.value)
                     addr = cpu.cast_adr_to_int(addr)
                     newops.append(
                         ResOperation(rop.GETFIELD_RAW, [ConstInt(addr)],
                                      box, self.single_gcref_descr))
                     op.args[i] = box
         # ---------- write barrier for SETFIELD_GC ----------
         if op.opnum == rop.SETFIELD_GC:
             v = op.args[1]
             if isinstance(
                     v, BoxPtr) or (isinstance(v, ConstPtr)
                                    and bool(v.value)):  # store a non-NULL
                 self._gen_write_barrier(newops, op.args[0], v)
                 op = ResOperation(rop.SETFIELD_RAW,
                                   op.args,
                                   None,
                                   descr=op.descr)
         # ---------- write barrier for SETARRAYITEM_GC ----------
         if op.opnum == rop.SETARRAYITEM_GC:
             v = op.args[2]
             if isinstance(
                     v, BoxPtr) or (isinstance(v, ConstPtr)
                                    and bool(v.value)):  # store a non-NULL
                 self._gen_write_barrier(newops, op.args[0], v)
                 op = ResOperation(rop.SETARRAYITEM_RAW,
                                   op.args,
                                   None,
                                   descr=op.descr)
         # ----------
         newops.append(op)
     del operations[:]
     operations.extend(newops)
Example #15
0
def convert_old_style_to_targets(loop, jump):
    newloop = TreeLoop(loop.name)
    newloop.inputargs = loop.inputargs
    newloop.operations = [ResOperation(rop.LABEL, loop.inputargs, None, descr=FakeDescr())] + \
                      loop.operations
    if not jump:
        assert newloop.operations[-1].getopnum() == rop.JUMP
        newloop.operations[-1] = ResOperation(rop.LABEL, newloop.operations[-1].getarglist(), None, descr=FakeDescr())
    return newloop
Example #16
0
 def exc_handling(guard_op):
     # operations need to start with correct GUARD_EXCEPTION
     if guard_op._exc_box is None:
         op = ResOperation(rop.GUARD_NO_EXCEPTION, [], None)
     else:
         op = ResOperation(rop.GUARD_EXCEPTION, [guard_op._exc_box],
                           BoxPtr())
     op.descr = BasicFailDescr()
     op.fail_args = []
     return op
Example #17
0
 def optimize_NEW_ARRAY(self, op):
     sizebox = self.get_constant_box(op.getarg(0))
     if sizebox is not None:
         # if the original 'op' did not have a ConstInt as argument,
         # build a new one with the ConstInt argument
         if not isinstance(op.getarg(0), ConstInt):
             op = ResOperation(rop.NEW_ARRAY, [sizebox], op.result, descr=op.getdescr())
         self.make_varray(op.getdescr(), sizebox.getint(), op.result, op)
     else:
         self.getvalue(op.result).ensure_nonnull()
         self.emit_operation(op)
Example #18
0
 def optimize_NEW_ARRAY(self, op):
     sizebox = self.get_constant_box(op.getarg(0))
     if sizebox is not None:
         # if the original 'op' did not have a ConstInt as argument,
         # build a new one with the ConstInt argument
         if not isinstance(op.getarg(0), ConstInt):
             op = ResOperation(rop.NEW_ARRAY, [sizebox], op.result,
                               descr=op.getdescr())
         self.make_varray(op.getdescr(), sizebox.getint(), op.result, op)
     else:
         self.getvalue(op.result).ensure_nonnull()
         self.emit_operation(op)
Example #19
0
 def parse_result_op(self, line):
     res, op = line.split("=", 1)
     res = res.strip()
     op = op.strip()
     opnum, args, descr, fail_args = self.parse_op(op)
     if res in self.vars:
         raise ParseError("Double assign to var %s in line: %s" % (res, line))
     rvar = self.box_for_var(res)
     self.vars[res] = rvar
     res = ResOperation(opnum, args, rvar, descr)
     res.fail_args = fail_args
     return res
Example #20
0
def compile_tmp_callback(cpu,
                         jitdriver_sd,
                         greenboxes,
                         redargtypes,
                         memory_manager=None):
    """Make a LoopToken that corresponds to assembler code that just
    calls back the interpreter.  Used temporarily: a fully compiled
    version of the code may end up replacing it.
    """
    jitcell_token = make_jitcell_token(jitdriver_sd)
    nb_red_args = jitdriver_sd.num_red_args
    assert len(redargtypes) == nb_red_args
    inputargs = []
    for kind in redargtypes:
        if kind == history.INT: box = BoxInt()
        elif kind == history.REF: box = BoxPtr()
        elif kind == history.FLOAT: box = BoxFloat()
        else: raise AssertionError
        inputargs.append(box)
    k = jitdriver_sd.portal_runner_adr
    funcbox = history.ConstInt(heaptracker.adr2int(k))
    callargs = [funcbox] + greenboxes + inputargs
    #
    result_type = jitdriver_sd.result_type
    if result_type == history.INT:
        result = BoxInt()
    elif result_type == history.REF:
        result = BoxPtr()
    elif result_type == history.FLOAT:
        result = BoxFloat()
    elif result_type == history.VOID:
        result = None
    else:
        assert 0, "bad result_type"
    if result is not None:
        finishargs = [result]
    else:
        finishargs = []
    #
    jd = jitdriver_sd
    faildescr = PropagateExceptionDescr()
    operations = [
        ResOperation(rop.CALL, callargs, result, descr=jd.portal_calldescr),
        ResOperation(rop.GUARD_NO_EXCEPTION, [], None, descr=faildescr),
        ResOperation(rop.FINISH, finishargs, None, descr=jd.portal_finishtoken)
    ]
    operations[1].setfailargs([])
    operations = get_deep_immutable_oplist(operations)
    cpu.compile_loop(inputargs, operations, jitcell_token, log=False)
    if memory_manager is not None:  # for tests
        memory_manager.keep_loop_alive(jitcell_token)
    return jitcell_token
Example #21
0
 def parse_result_op(self, line):
     res, op = line.split("=", 1)
     res = res.strip()
     op = op.strip()
     opnum, args, descr, fail_args = self.parse_op(op)
     if res in self.vars:
         raise ParseError("Double assign to var %s in line: %s" %
                          (res, line))
     rvar = self.box_for_var(res)
     self.vars[res] = rvar
     res = ResOperation(opnum, args, rvar, descr)
     res.fail_args = fail_args
     return res
Example #22
0
 def _optimize_NEWSTR(self, op, mode):
     length_box = self.get_constant_box(op.getarg(0))
     if length_box:
         # if the original 'op' did not have a ConstInt as argument,
         # build a new one with the ConstInt argument
         if not isinstance(op.getarg(0), ConstInt):
             op = ResOperation(mode.NEWSTR, [length_box], op.result)
         vvalue = self.make_vstring_plain(op.result, op, mode)
         vvalue.setup(length_box.getint())
     else:
         self.getvalue(op.result).ensure_nonnull()
         self.emit_operation(op)
         self.pure(mode.STRLEN, [op.result], op.getarg(0))
Example #23
0
 def gen_guard(self, builder, r):
     if r.random() < 0.5:
         return GuardClassOperation.gen_guard(self, builder, r)
     else:
         v = BoxPtr(lltype.nullptr(llmemory.GCREF.TO))
         op = ResOperation(rop.SAME_AS, [ConstPtr(v.value)], v)
         builder.loop.operations.append(op)
         v2, S2 = builder.get_structptr_var(r, must_have_vtable=True)
         vtable2 = S2._hints['vtable']._as_ptr()
         c_vtable2 = ConstAddr(llmemory.cast_ptr_to_adr(vtable2),
                               builder.cpu)
         op = ResOperation(self.opnum, [v, c_vtable2], None)
         return op, False
Example #24
0
 def _optimize_NEWSTR(self, op, mode):
     length_box = self.get_constant_box(op.getarg(0))
     if length_box:
         # if the original 'op' did not have a ConstInt as argument,
         # build a new one with the ConstInt argument
         if not isinstance(op.getarg(0), ConstInt):
             op = ResOperation(mode.NEWSTR, [length_box], op.result)
         vvalue = self.make_vstring_plain(op.result, op, mode)
         vvalue.setup(length_box.getint())
     else:
         self.getvalue(op.result).ensure_nonnull()
         self.emit_operation(op)
         self.pure(mode.STRLEN, [op.result], op.getarg(0))
Example #25
0
 def produce_into(self, builder, r):
     fail_subset = builder.subset_of_intvars(r)
     subset, f, exc = self.raising_func_code(builder, r)
     TP = lltype.FuncType([lltype.Signed] * len(subset), lltype.Void)
     ptr = llhelper(lltype.Ptr(TP), f)
     c_addr = ConstAddr(llmemory.cast_ptr_to_adr(ptr), builder.cpu)
     args = [c_addr] + subset
     descr = builder.cpu.calldescrof(TP, TP.ARGS, TP.RESULT)
     self.put(builder, args, descr)
     exc_box = ConstAddr(llmemory.cast_ptr_to_adr(exc), builder.cpu)
     op = ResOperation(rop.GUARD_EXCEPTION, [exc_box], BoxPtr(),
                       descr=BasicFailDescr())
     op.setfailargs(fail_subset)
     builder.loop.operations.append(op)
Example #26
0
 def make_guards(self, box, guards):
     if self.has_lower and self.lower > MININT:
         bound = self.lower
         res = BoxInt()
         op = ResOperation(rop.INT_GE, [box, ConstInt(bound)], res)
         guards.append(op)
         op = ResOperation(rop.GUARD_TRUE, [res], None)
         guards.append(op)
     if self.has_upper and self.upper < MAXINT:
         bound = self.upper
         res = BoxInt()
         op = ResOperation(rop.INT_LE, [box, ConstInt(bound)], res)
         guards.append(op)
         op = ResOperation(rop.GUARD_TRUE, [res], None)
         guards.append(op)
Example #27
0
 def produce_into(self, builder, r):
     fail_subset = builder.subset_of_intvars(r)
     subset, f, exc = self.raising_func_code(builder, r)
     TP = lltype.FuncType([lltype.Signed] * len(subset), lltype.Void)
     ptr = llhelper(lltype.Ptr(TP), f)
     c_addr = ConstAddr(llmemory.cast_ptr_to_adr(ptr), builder.cpu)
     args = [c_addr] + subset
     descr = self.getcalldescr(builder, TP)
     self.put(builder, args, descr)
     exc_box = ConstAddr(llmemory.cast_ptr_to_adr(exc), builder.cpu)
     op = ResOperation(rop.GUARD_EXCEPTION, [exc_box],
                       BoxPtr(),
                       descr=BasicFailDescr())
     op.setfailargs(fail_subset)
     builder.loop.operations.append(op)
Example #28
0
 def produce_into(self, builder, r):
     subset, f, exc = self.raising_func_code(builder, r)
     TP = lltype.FuncType([lltype.Signed] * len(subset), lltype.Void)
     ptr = llhelper(lltype.Ptr(TP), f)
     c_addr = ConstAddr(llmemory.cast_ptr_to_adr(ptr), builder.cpu)
     args = [c_addr] + subset
     descr = self.getcalldescr(builder, TP)
     self.put(builder, args, descr)
     op = ResOperation(rop.GUARD_NO_EXCEPTION, [], BoxPtr(),
                       descr=BasicFailDescr())
     op._exc_box = ConstAddr(llmemory.cast_ptr_to_adr(exc), builder.cpu)
     op.setfailargs(builder.subset_of_intvars(r))
     builder.should_fail_by = op
     builder.guard_op = op
     builder.loop.operations.append(op)
Example #29
0
 def generate_modified_call(self, oopspecindex, args, result, mode):
     oopspecindex += mode.OS_offset
     cic = self.optimizer.metainterp_sd.callinfocollection
     calldescr, func = cic.callinfo_for_oopspec(oopspecindex)
     op = ResOperation(rop.CALL, [ConstInt(func)] + args, result,
                       descr=calldescr)
     self.emit_operation(op)
Example #30
0
 def create_op(self, opnum, args, result, descr):
     if opnum == ESCAPE_OP.OPNUM:
         return ESCAPE_OP(opnum, args, result, descr)
     if opnum == FORCE_SPILL.OPNUM:
         return FORCE_SPILL(opnum, args, result, descr)
     else:
         return ResOperation(opnum, args, result, descr)
Example #31
0
 def _optimize_CALL_ARRAYCOPY(self, op):
     source_value = self.getvalue(op.getarg(1))
     dest_value = self.getvalue(op.getarg(2))
     source_start_box = self.get_constant_box(op.getarg(3))
     dest_start_box = self.get_constant_box(op.getarg(4))
     length = self.get_constant_box(op.getarg(5))
     if (source_value.is_virtual() and source_start_box and dest_start_box
             and length
             and (dest_value.is_virtual() or length.getint() <= 8)):
         from pypy.jit.metainterp.optimizeopt.virtualize import VArrayValue
         assert isinstance(source_value, VArrayValue)
         source_start = source_start_box.getint()
         dest_start = dest_start_box.getint()
         for index in range(length.getint()):
             val = source_value.getitem(index + source_start)
             if dest_value.is_virtual():
                 dest_value.setitem(index + dest_start, val)
             else:
                 newop = ResOperation(rop.SETARRAYITEM_GC, [
                     op.getarg(2),
                     ConstInt(index + dest_start),
                     val.get_key_box()
                 ],
                                      None,
                                      descr=source_value.arraydescr)
                 self.emit_operation(newop)
         return True
     if length and length.getint() == 0:
         return True  # 0-length arraycopy
     return False
Example #32
0
 def _gen_write_barrier(self, cpu, newops, v_base, v_value):
     v_tid = BoxInt()
     newops.append(
         ResOperation(rop.GETFIELD_RAW, [v_base],
                      v_tid,
                      descr=self.fielddescr_tid))
     llop1 = self.llop1
     funcptr = llop1.get_write_barrier_failing_case(self.WB_FUNCPTR)
     funcaddr = llmemory.cast_ptr_to_adr(funcptr)
     c_func = ConstInt(cpu.cast_adr_to_int(funcaddr))
     args = [v_tid, self.c_jit_wb_if_flag, c_func, v_base, v_value]
     newops.append(
         ResOperation(rop.COND_CALL_GC_WB,
                      args,
                      None,
                      descr=self.calldescr_jit_wb))
Example #33
0
    def do_getsetarrayitem(self, op, oopspec):
        ffitypeval = self.getvalue(op.getarg(1))
        widthval = self.getvalue(op.getarg(2))
        offsetval = self.getvalue(op.getarg(5))
        if not ffitypeval.is_constant() or not widthval.is_constant() or not offsetval.is_constant():
            return [op]

        ffitypeaddr = ffitypeval.box.getaddr()
        ffitype = llmemory.cast_adr_to_ptr(ffitypeaddr, clibffi.FFI_TYPE_P)
        offset = offsetval.box.getint()
        width = widthval.box.getint()
        descr = self._get_interior_descr(ffitype, width, offset)

        arglist = [
            self.getvalue(op.getarg(3)).force_box(self.optimizer),
            self.getvalue(op.getarg(4)).force_box(self.optimizer),
        ]
        if oopspec == EffectInfo.OS_LIBFFI_GETARRAYITEM:
            opnum = rop.GETINTERIORFIELD_RAW
        elif oopspec == EffectInfo.OS_LIBFFI_SETARRAYITEM:
            opnum = rop.SETINTERIORFIELD_RAW
            arglist.append(self.getvalue(op.getarg(6)).force_box(self.optimizer))
        else:
            assert False
        return [
            ResOperation(opnum, arglist, op.result, descr=descr),
        ]
Example #34
0
 def test_mark_gc_roots(self):
     cpu = CPU(None, None)
     cpu.setup_once()
     regalloc = RegAlloc(MockAssembler(cpu, MockGcDescr(False)))
     regalloc.assembler.datablockwrapper = 'fakedatablockwrapper'
     boxes = [BoxPtr() for i in range(len(X86RegisterManager.all_regs))]
     longevity = {}
     for box in boxes:
         longevity[box] = (0, 1)
     regalloc.fm = X86FrameManager()
     regalloc.rm = X86RegisterManager(longevity,
                                      regalloc.fm,
                                      assembler=regalloc.assembler)
     regalloc.xrm = X86XMMRegisterManager(longevity,
                                          regalloc.fm,
                                          assembler=regalloc.assembler)
     cpu = regalloc.assembler.cpu
     for box in boxes:
         regalloc.rm.try_allocate_reg(box)
     TP = lltype.FuncType([], lltype.Signed)
     calldescr = cpu.calldescrof(TP, TP.ARGS, TP.RESULT,
                                 EffectInfo.MOST_GENERAL)
     regalloc.rm._check_invariants()
     box = boxes[0]
     regalloc.position = 0
     regalloc.consider_call(
         ResOperation(rop.CALL, [box], BoxInt(), calldescr))
     assert len(regalloc.assembler.movs) == 3
     #
     mark = regalloc.get_mark_gc_roots(cpu.gc_ll_descr.gcrootmap)
     assert mark[0] == 'compressed'
     base = -WORD * FRAME_FIXED_SIZE
     expected = ['ebx', 'esi', 'edi', base, base - WORD, base - WORD * 2]
     assert dict.fromkeys(mark[1:]) == dict.fromkeys(expected)
Example #35
0
 def _gen_call_malloc_gc(self, args, v_result, descr):
     """Generate a CALL_MALLOC_GC with the given args."""
     self.emitting_an_operation_that_can_collect()
     op = ResOperation(rop.CALL_MALLOC_GC, args, v_result, descr)
     self.newops.append(op)
     # mark 'v_result' as freshly malloced
     self.recent_mallocs[v_result] = None
Example #36
0
 def do(self, opnum, argboxes, descr=None):
     v_result = execute_nonspec(self.cpu, opnum, argboxes, descr)
     if isinstance(v_result, Const):
         v_result = v_result.clonebox()
     self.loop.operations.append(
         ResOperation(opnum, argboxes, v_result, descr))
     return v_result
Example #37
0
 def _really_force(self):
     if self.source_op is None:
         # this case should not occur; I only managed to get it once
         # in pypy-c-jit and couldn't reproduce it.  The point is
         # that it relies on optimizefindnode.py computing exactly
         # the right level of specialization, and it seems that there
         # is still a corner case where it gets too specialized for
         # optimizeopt.py.  Let's not crash in release-built
         # pypy-c-jit's.  XXX find out when
         from pypy.rlib.debug import ll_assert
         ll_assert(False, "_really_force: source_op is None")
         raise InvalidLoop
     #
     newoperations = self.optimizer.newoperations
     newoperations.append(self.source_op)
     self.box = box = self.source_op.result
     #
     iteritems = self._fields.iteritems()
     if not we_are_translated():  #random order is fine, except for tests
         iteritems = list(iteritems)
         iteritems.sort(key=lambda (x, y): x.sort_key())
     for ofs, value in iteritems:
         if value.is_null():
             continue
         subbox = value.force_box()
         op = ResOperation(rop.SETFIELD_GC, [box, subbox], None, descr=ofs)
         newoperations.append(op)
     self._fields = None
Example #38
0
 def _gen_write_barrier(self, newops, v_base, v_value):
     args = [v_base, v_value]
     newops.append(
         ResOperation(rop.COND_CALL_GC_WB,
                      args,
                      None,
                      descr=self.write_barrier_descr))
Example #39
0
 def produce_into(self, builder, r):
     fail_subset = builder.subset_of_intvars(r)
     original_intvars = builder.intvars[:]
     super(AbstractOvfOperation, self).produce_into(builder, r)
     if builder.cpu._overflow_flag:   # overflow detected
         del builder.cpu._overflow_flag
         op = ResOperation(rop.GUARD_OVERFLOW, [], None)
         # the overflowed result should not be used any more, but can
         # be used on the failure path: recompute fail_subset including
         # the result, and then remove it from builder.intvars.
         fail_subset = builder.subset_of_intvars(r)
         builder.intvars[:] = original_intvars
     else:
         op = ResOperation(rop.GUARD_NO_OVERFLOW, [], None)
     op.descr = BasicFailDescr()
     op.fail_args = fail_subset
     builder.loop.operations.append(op)
Example #40
0
 def produce_into(self, builder, r):
     fail_subset = builder.subset_of_intvars(r)
     subset, f = self.non_raising_func_code(builder, r)
     if len(subset) == 0:
         RES = lltype.Void
     else:
         RES = lltype.Signed
     TP = lltype.FuncType([lltype.Signed] * len(subset), RES)
     ptr = llhelper(lltype.Ptr(TP), f)
     c_addr = ConstAddr(llmemory.cast_ptr_to_adr(ptr), builder.cpu)
     args = [c_addr] + subset
     descr = builder.cpu.calldescrof(TP, TP.ARGS, TP.RESULT)
     self.put(builder, args, descr)
     op = ResOperation(rop.GUARD_NO_EXCEPTION, [], None,
                       descr=BasicFailDescr())
     op.fail_args = fail_subset
     builder.loop.operations.append(op)
Example #41
0
 def produce_into(self, builder, r):
     subset, f, exc = self.raising_func_code(builder, r)
     TP = lltype.FuncType([lltype.Signed] * len(subset), lltype.Void)
     ptr = llhelper(lltype.Ptr(TP), f)
     c_addr = ConstAddr(llmemory.cast_ptr_to_adr(ptr), builder.cpu)
     args = [c_addr] + subset
     descr = builder.cpu.calldescrof(TP, TP.ARGS, TP.RESULT)
     self.put(builder, args, descr)
     assert builder.cpu.get_exception()
     builder.cpu.clear_exception()
     op = ResOperation(rop.GUARD_NO_EXCEPTION, [], BoxPtr(),
                       descr=builder.make_fail_descr())
     op._exc_box = ConstAddr(llmemory.cast_ptr_to_adr(exc), builder.cpu)
     op.fail_args = builder.subset_of_intvars(r)
     builder.should_fail_by = op
     builder.guard_op = op
     builder.loop.operations.append(op)
Example #42
0
 def produce_into(self, builder, r):
     subset, f, exc = self.raising_func_code(builder, r)
     TP = lltype.FuncType([lltype.Signed] * len(subset), lltype.Void)
     ptr = llhelper(lltype.Ptr(TP), f)
     c_addr = ConstAddr(llmemory.cast_ptr_to_adr(ptr), builder.cpu)
     args = [c_addr] + subset
     descr = builder.cpu.calldescrof(TP, TP.ARGS, TP.RESULT)
     self.put(builder, args, descr)
     while True:
         _, vtableptr = builder.get_random_structure_type_and_vtable(r)
         if vtableptr != exc:
             break
     other_box = ConstAddr(llmemory.cast_ptr_to_adr(vtableptr), builder.cpu)
     op = ResOperation(rop.GUARD_EXCEPTION, [other_box], BoxPtr(),
                       descr=BasicFailDescr())
     op._exc_box = ConstAddr(llmemory.cast_ptr_to_adr(exc), builder.cpu)
     op.setfailargs(builder.subset_of_intvars(r))
     builder.should_fail_by = op
     builder.guard_op = op
     builder.loop.operations.append(op)
Example #43
0
 def _really_force(self, optforce):
     if self.mode is mode_string:
         s = self.get_constant_string_spec(mode_string)
         if s is not None:
             c_s = get_const_ptr_for_string(s)
             self.make_constant(c_s)
             return
     else:
         s = self.get_constant_string_spec(mode_unicode)
         if s is not None:
             c_s = get_const_ptr_for_unicode(s)
             self.make_constant(c_s)
             return
     assert self.source_op is not None
     self.box = box = self.source_op.result
     lengthbox = self.getstrlen(optforce, self.mode)
     op = ResOperation(self.mode.NEWSTR, [lengthbox], box)
     if not we_are_translated():
         op.name = 'FORCE'
     optforce.emit_operation(op)
     self.string_copy_parts(optforce, box, CONST_0, self.mode)
Example #44
0
 def produce_into(self, builder, r):
     subset, f = self.non_raising_func_code(builder, r)
     if len(subset) == 0:
         RES = lltype.Void
     else:
         RES = lltype.Signed
     TP = lltype.FuncType([lltype.Signed] * len(subset), RES)
     ptr = llhelper(lltype.Ptr(TP), f)
     c_addr = ConstAddr(llmemory.cast_ptr_to_adr(ptr), builder.cpu)
     args = [c_addr] + subset
     descr = builder.cpu.calldescrof(TP, TP.ARGS, TP.RESULT)
     self.put(builder, args, descr)
     _, vtableptr = builder.get_random_structure_type_and_vtable(r)
     exc_box = ConstAddr(llmemory.cast_ptr_to_adr(vtableptr), builder.cpu)
     op = ResOperation(rop.GUARD_EXCEPTION, [exc_box], BoxPtr(),
                       descr=BasicFailDescr())
     op.fail_args = builder.subset_of_intvars(r)
     op._exc_box = None
     builder.should_fail_by = op
     builder.guard_op = op
     builder.loop.operations.append(op)
Example #45
0
 def handle_malloc_operation(self, op):
     opnum = op.getopnum()
     if opnum == rop.NEW:
         self.handle_new_fixedsize(op.getdescr(), op)
     elif opnum == rop.NEW_WITH_VTABLE:
         classint = op.getarg(0).getint()
         descr = heaptracker.vtable2descr(self.cpu, classint)
         self.handle_new_fixedsize(descr, op)
         if self.gc_ll_descr.fielddescr_vtable is not None:
             op = ResOperation(rop.SETFIELD_GC,
                               [op.result, ConstInt(classint)], None,
                               descr=self.gc_ll_descr.fielddescr_vtable)
             self.newops.append(op)
     elif opnum == rop.NEW_ARRAY:
         descr = op.getdescr()
         assert isinstance(descr, ArrayDescr)
         self.handle_new_array(descr, op)
     elif opnum == rop.NEWSTR:
         self.handle_new_array(self.gc_ll_descr.str_descr, op)
     elif opnum == rop.NEWUNICODE:
         self.handle_new_array(self.gc_ll_descr.unicode_descr, op)
     else:
         raise NotImplementedError(op.getopname())
Example #46
0
 def produce_into(self, builder, r):
     fail_subset = builder.subset_of_intvars(r)
     original_intvars = builder.intvars[:]
     super(AbstractOvfOperation, self).produce_into(builder, r)
     if builder.fakemetainterp._got_exc:  # overflow detected
         assert isinstance(builder.fakemetainterp._got_exc, OverflowError)
         op = ResOperation(rop.GUARD_OVERFLOW, [], None)
         # the overflowed result should not be used any more, but can
         # be used on the failure path: recompute fail_subset including
         # the result, and then remove it from builder.intvars.
         fail_subset = builder.subset_of_intvars(r)
         builder.intvars[:] = original_intvars
     else:
         op = ResOperation(rop.GUARD_NO_OVERFLOW, [], None)
     op.setdescr(BasicFailDescr())
     op.setfailargs(fail_subset)
     builder.loop.operations.append(op)
Example #47
0
 def parse_op_no_result(self, line):
     opnum, args, descr, fail_args = self.parse_op(line)
     res = ResOperation(opnum, args, None, descr)
     res.fail_args = fail_args
     return res
Example #48
0
 def optimize_VIRTUAL_REF(self, op):
     op = ResOperation(rop.SAME_AS, [op.getarg(0)], op.result)
     self.emit_operation(op)
Example #49
0
File: unroll.py Project: ieure/pypy
    def propagate_all_forward(self):
        loop = self.optimizer.loop
        jumpop = loop.operations[-1]
        if jumpop.getopnum() == rop.JUMP:
            loop.operations = loop.operations[:-1]
        else:
            loopop = None

        self.optimizer.propagate_all_forward()


        if jumpop:
            assert jumpop.getdescr() is loop.token
            jump_args = jumpop.getarglist()
            jumpop.initarglist([])
            #virtual_state = [self.getvalue(a).is_virtual() for a in jump_args]
            modifier = VirtualStateAdder(self.optimizer)
            virtual_state = modifier.get_virtual_state(jump_args)

            loop.preamble.operations = self.optimizer.newoperations
            loop.preamble.quasi_immutable_deps = (
                self.optimizer.quasi_immutable_deps)
            self.optimizer = self.optimizer.reconstruct_for_next_iteration()
            inputargs = self.inline(self.cloned_operations,
                                    loop.inputargs, jump_args)
            loop.inputargs = inputargs
            jmp = ResOperation(rop.JUMP, loop.inputargs[:], None)
            jmp.setdescr(loop.token)
            loop.preamble.operations.append(jmp)

            loop.operations = self.optimizer.newoperations
            loop.quasi_immutable_deps = self.optimizer.quasi_immutable_deps

            start_resumedescr = loop.preamble.start_resumedescr.clone_if_mutable()
            assert isinstance(start_resumedescr, ResumeGuardDescr)
            snapshot = start_resumedescr.rd_snapshot
            while snapshot is not None:
                snapshot_args = snapshot.boxes 
                new_snapshot_args = []
                for a in snapshot_args:
                    if not isinstance(a, Const):
                        a = loop.preamble.inputargs[jump_args.index(a)]
                    new_snapshot_args.append(a)
                snapshot.boxes = new_snapshot_args
                snapshot = snapshot.prev

            short = self.create_short_preamble(loop.preamble, loop)
            if short:
                if False:
                    # FIXME: This should save some memory but requires
                    # a lot of tests to be fixed...
                    loop.preamble.operations = short[:]

                # Turn guards into conditional jumps to the preamble
                for i in range(len(short)):
                    op = short[i]
                    if op.is_guard():
                        op = op.clone()
                        op.setfailargs(None)
                        op.setdescr(start_resumedescr.clone_if_mutable())
                        short[i] = op

                short_loop = TreeLoop('short preamble')
                short_loop.inputargs = loop.preamble.inputargs[:]
                short_loop.operations = short

                # Clone ops and boxes to get private versions and 
                newargs = [a.clonebox() for a in short_loop.inputargs]
                inliner = Inliner(short_loop.inputargs, newargs)
                short_loop.inputargs = newargs
                ops = [inliner.inline_op(op) for op in short_loop.operations]
                short_loop.operations = ops
                descr = start_resumedescr.clone_if_mutable()
                inliner.inline_descr_inplace(descr)
                short_loop.start_resumedescr = descr

                assert isinstance(loop.preamble.token, LoopToken)
                if loop.preamble.token.short_preamble:
                    loop.preamble.token.short_preamble.append(short_loop)
                else:
                    loop.preamble.token.short_preamble = [short_loop]
                short_loop.virtual_state = virtual_state

                # Forget the values to allow them to be freed
                for box in short_loop.inputargs:
                    box.forget_value()
                for op in short_loop.operations:
                    if op.result:
                        op.result.forget_value()
Example #50
0
    def propagate_all_forward(self):
        loop = self.optimizer.loop
        jumpop = loop.operations[-1]
        if jumpop.getopnum() == rop.JUMP:
            loop.operations = loop.operations[:-1]
        else:
            loopop = None

        self.optimizer.propagate_all_forward()

        if jumpop:
            assert jumpop.getdescr() is loop.token
            jump_args = jumpop.getarglist()
            jumpop.initarglist([])
            self.optimizer.flush()

            KillHugeIntBounds(self.optimizer).apply()

            loop.preamble.operations = self.optimizer.newoperations
            jump_args = [self.getvalue(a).get_key_box() for a in jump_args]

            start_resumedescr = loop.preamble.start_resumedescr.clone_if_mutable()
            self.start_resumedescr = start_resumedescr
            assert isinstance(start_resumedescr, ResumeGuardDescr)
            start_resumedescr.rd_snapshot = self.fix_snapshot(loop, jump_args, start_resumedescr.rd_snapshot)

            modifier = VirtualStateAdder(self.optimizer)
            virtual_state = modifier.get_virtual_state(jump_args)

            values = [self.getvalue(arg) for arg in jump_args]
            inputargs = virtual_state.make_inputargs(values)
            short_inputargs = virtual_state.make_inputargs(values, keyboxes=True)

            self.constant_inputargs = {}
            for box in jump_args:
                const = self.get_constant_box(box)
                if const:
                    self.constant_inputargs[box] = const

            sb = ShortBoxes(self.optimizer, inputargs + self.constant_inputargs.keys())
            self.short_boxes = sb
            preamble_optimizer = self.optimizer
            loop.preamble.quasi_immutable_deps = self.optimizer.quasi_immutable_deps
            self.optimizer = self.optimizer.new()
            loop.quasi_immutable_deps = self.optimizer.quasi_immutable_deps

            logops = self.optimizer.loop.logops
            if logops:
                args = ", ".join([logops.repr_of_arg(arg) for arg in inputargs])
                debug_print("inputargs:       " + args)
                args = ", ".join([logops.repr_of_arg(arg) for arg in short_inputargs])
                debug_print("short inputargs: " + args)
                self.short_boxes.debug_print(logops)

            # Force virtuals amoung the jump_args of the preamble to get the
            # operations needed to setup the proper state of those virtuals
            # in the peeled loop
            inputarg_setup_ops = []
            preamble_optimizer.newoperations = []
            seen = {}
            for box in inputargs:
                if box in seen:
                    continue
                seen[box] = True
                value = preamble_optimizer.getvalue(box)
                inputarg_setup_ops.extend(value.make_guards(box))
            for box in short_inputargs:
                if box in seen:
                    continue
                seen[box] = True
                value = preamble_optimizer.getvalue(box)
                value.force_box()
            preamble_optimizer.flush()
            inputarg_setup_ops += preamble_optimizer.newoperations

            # Setup the state of the new optimizer by emiting the
            # short preamble operations and discarding the result
            self.optimizer.emitting_dissabled = True
            for op in inputarg_setup_ops:
                self.optimizer.send_extra_operation(op)
            seen = {}
            for op in self.short_boxes.operations():
                self.ensure_short_op_emitted(op, self.optimizer, seen)
                if op and op.result:
                    # The order of these guards is not important as
                    # self.optimizer.emitting_dissabled is False
                    value = preamble_optimizer.getvalue(op.result)
                    for guard in value.make_guards(op.result):
                        self.optimizer.send_extra_operation(guard)
                    newresult = self.optimizer.getvalue(op.result).get_key_box()
                    if newresult is not op.result:
                        self.short_boxes.alias(newresult, op.result)
            self.optimizer.flush()
            self.optimizer.emitting_dissabled = False

            # XXX Hack to prevent the arraylen/strlen/unicodelen ops generated
            #     by value.make_guards() from ending up in pure_operations
            for key, op in self.optimizer.pure_operations.items():
                if not self.short_boxes.has_producer(op.result):
                    del self.optimizer.pure_operations[key]

            initial_inputargs_len = len(inputargs)
            self.inliner = Inliner(loop.inputargs, jump_args)

            short = self.inline(inputargs, self.cloned_operations, loop.inputargs, short_inputargs, virtual_state)

            loop.inputargs = inputargs
            args = [preamble_optimizer.getvalue(self.short_boxes.original(a)).force_box() for a in inputargs]
            jmp = ResOperation(rop.JUMP, args, None)
            jmp.setdescr(loop.token)
            loop.preamble.operations.append(jmp)

            loop.operations = self.optimizer.newoperations
            maxguards = self.optimizer.metainterp_sd.warmrunnerdesc.memory_manager.max_retrace_guards

            if self.optimizer.emitted_guards > maxguards:
                loop.preamble.token.retraced_count = sys.maxint

            if short:
                assert short[-1].getopnum() == rop.JUMP
                short[-1].setdescr(loop.token)

                # Turn guards into conditional jumps to the preamble
                for i in range(len(short)):
                    op = short[i]
                    if op.is_guard():
                        op = op.clone()
                        op.setfailargs(None)
                        descr = self.start_resumedescr.clone_if_mutable()
                        op.setdescr(descr)
                        short[i] = op

                short_loop = TreeLoop("short preamble")
                short_loop.inputargs = short_inputargs
                short_loop.operations = short

                # Clone ops and boxes to get private versions and
                boxmap = {}
                newargs = [None] * len(short_loop.inputargs)
                for i in range(len(short_loop.inputargs)):
                    a = short_loop.inputargs[i]
                    if a in boxmap:
                        newargs[i] = boxmap[a]
                    else:
                        newargs[i] = a.clonebox()
                        boxmap[a] = newargs[i]
                inliner = Inliner(short_loop.inputargs, newargs)
                for box, const in self.constant_inputargs.items():
                    inliner.argmap[box] = const
                short_loop.inputargs = newargs
                ops = [inliner.inline_op(op) for op in short_loop.operations]
                short_loop.operations = ops
                descr = self.start_resumedescr.clone_if_mutable()
                inliner.inline_descr_inplace(descr)
                short_loop.start_resumedescr = descr

                assert isinstance(loop.preamble.token, LoopToken)
                if loop.preamble.token.short_preamble:
                    loop.preamble.token.short_preamble.append(short_loop)
                else:
                    loop.preamble.token.short_preamble = [short_loop]
                short_loop.virtual_state = virtual_state

                # Forget the values to allow them to be freed
                for box in short_loop.inputargs:
                    box.forget_value()
                for op in short_loop.operations:
                    if op.result:
                        op.result.forget_value()
Example #51
0
    def propagate_all_forward(self):
        loop = self.optimizer.loop
        self.optimizer.clear_newoperations()

        start_label = loop.operations[0]
        if start_label.getopnum() == rop.LABEL:
            loop.operations = loop.operations[1:]
            # We need to emit the label op before import_state() as emitting it
            # will clear heap caches
            self.optimizer.send_extra_operation(start_label)
        else:
            start_label = None            

        jumpop = loop.operations[-1]
        if jumpop.getopnum() == rop.JUMP or jumpop.getopnum() == rop.LABEL:
            loop.operations = loop.operations[:-1]
        else:
            jumpop = None

        self.import_state(start_label)
        self.optimizer.propagate_all_forward(clear=False)

        if not jumpop:
            return

        cell_token = jumpop.getdescr()
        assert isinstance(cell_token, JitCellToken)
        stop_label = ResOperation(rop.LABEL, jumpop.getarglist(), None, TargetToken(cell_token))

        
        if jumpop.getopnum() == rop.JUMP:
            if self.jump_to_already_compiled_trace(jumpop):
                # Found a compiled trace to jump to
                if self.short:
                    # Construct our short preamble
                    assert start_label
                    self.close_bridge(start_label)
                return

            if start_label and self.jump_to_start_label(start_label, stop_label):
                # Initial label matches, jump to it
                jumpop = ResOperation(rop.JUMP, stop_label.getarglist(), None,
                                      descr=start_label.getdescr())
                if self.short:
                    # Construct our short preamble
                    self.close_loop(start_label, jumpop)
                else:
                    self.optimizer.send_extra_operation(jumpop)
                return

            if cell_token.target_tokens:
                limit = self.optimizer.metainterp_sd.warmrunnerdesc.memory_manager.retrace_limit
                if cell_token.retraced_count < limit:
                    cell_token.retraced_count += 1
                    debug_print('Retracing (%d/%d)' % (cell_token.retraced_count, limit))
                else:
                    debug_print("Retrace count reached, jumping to preamble")
                    assert cell_token.target_tokens[0].virtual_state is None
                    jumpop.setdescr(cell_token.target_tokens[0])
                    self.optimizer.send_extra_operation(jumpop)
                    return

        # Found nothing to jump to, emit a label instead
        
        if self.short:
            # Construct our short preamble
            assert start_label
            self.close_bridge(start_label)

        self.optimizer.flush()
        KillHugeIntBounds(self.optimizer).apply()

        loop.operations = self.optimizer.get_newoperations()
        self.export_state(stop_label)
        loop.operations.append(stop_label)
Example #52
0
File: unroll.py Project: ieure/pypy
    def create_short_preamble(self, preamble, loop):
        #return None # Dissable

        preamble_ops = preamble.operations
        loop_ops = loop.operations

        boxmap = BoxMap()
        state = ExeState(self.optimizer)
        short_preamble = []
        loop_i = preamble_i = 0
        while preamble_i < len(preamble_ops):

            op = preamble_ops[preamble_i]
            try:
                newop = self.inliner.inline_op(op, ignore_result=True,
                                               ignore_failargs=True)
            except KeyError:
                debug_print("create_short_preamble failed due to",
                            "new boxes created during optimization.",
                            "op:", op.getopnum(),
                            "at preamble position: ", preamble_i,
                            "loop position: ", loop_i)
                return None
                
            if self.sameop(newop, loop_ops[loop_i]) \
               and loop_i < len(loop_ops):
                try:
                    boxmap.link_ops(op, loop_ops[loop_i])
                except ImpossibleLink:
                    debug_print("create_short_preamble failed due to",
                                "impossible link of "
                                "op:", op.getopnum(),
                                "at preamble position: ", preamble_i,
                                "loop position: ", loop_i)
                    return None
                loop_i += 1
            else:
                if not state.safe_to_move(op):
                    debug_print("create_short_preamble failed due to",
                                "unsafe op:", op.getopnum(),
                                "at preamble position: ", preamble_i,
                                "loop position: ", loop_i)
                    return None
                short_preamble.append(op)
                
            state.update(op)
            preamble_i += 1

        if loop_i < len(loop_ops):
            debug_print("create_short_preamble failed due to",
                        "loop contaning ops not in preamble"
                        "at position", loop_i)
            return None

        
        jumpargs = []
        for i in range(len(loop.inputargs)):
            try:
                jumpargs.append(boxmap.get_preamblebox(loop.inputargs[i]))
            except KeyError:
                debug_print("create_short_preamble failed due to",
                            "input arguments not located")
                return None

        jmp = ResOperation(rop.JUMP, jumpargs[:], None)
        jmp.setdescr(loop.token)
        short_preamble.append(jmp)

        # Check that boxes used as arguemts are produced.
        seen = {}
        for box in preamble.inputargs:
            seen[box] = True
        for op in short_preamble:
            for box in op.getarglist():
                if isinstance(box, Const):
                    continue
                if box not in seen:
                    debug_print("create_short_preamble failed due to",
                                "op arguments not produced")
                    return None
            if op.result:
                seen[op.result] = True
        
        return short_preamble