Esempio n. 1
0
    def optimize_INT_ADD(self, op):
        arg1 = get_box_replacement(op.getarg(0))
        arg2 = get_box_replacement(op.getarg(1))
        if self.is_raw_ptr(arg1) or self.is_raw_ptr(arg2):
            return self.emit(op)
        v1 = self.getintbound(arg1)
        v2 = self.getintbound(arg2)

        # Optimize for addition chains in code "b = a + 1; c = b + 1" by
        # detecting the int_add chain, and swapping with "b = a + 1;
        # c = a + 2". If b is not used elsewhere, the backend eliminates
        # it.

        # either v1 or v2 can be a constant, swap the arguments around if
        # v1 is the constant
        if v1.is_constant():
            arg1, arg2 = arg2, arg1
            v1, v2 = v2, v1
        # if both are constant, the pure optimization will deal with it
        if v2.is_constant() and not v1.is_constant():
            arg1 = self.optimizer.as_operation(arg1)
            if arg1 is not None:
                if arg1.getopnum() == rop.INT_ADD:
                    prod_arg1 = get_box_replacement(arg1.getarg(0))
                    prod_arg2 = get_box_replacement(arg1.getarg(1))
                    prod_v1 = self.getintbound(prod_arg1)
                    prod_v2 = self.getintbound(prod_arg2)

                    # same thing here: prod_v1 or prod_v2 can be a
                    # constant
                    if prod_v1.is_constant():
                        prod_arg1, prod_arg2 = prod_arg2, prod_arg1
                        prod_v1, prod_v2 = prod_v2, prod_v1
                    if prod_v2.is_constant():
                        sum = intmask(arg2.getint() + prod_arg2.getint())
                        arg1 = prod_arg1
                        arg2 = ConstInt(sum)
                        op = self.replace_op_with(op,
                                                  rop.INT_ADD,
                                                  args=[arg1, arg2])

        return self.emit(op)
Esempio n. 2
0
 def make_guards(self, op, short, optimizer):
     if self._known_class is not None:
         if not optimizer.cpu.remove_gctypeptr:
             short.append(ResOperation(rop.GUARD_NONNULL, [op]))
             short.append(ResOperation(rop.GUARD_IS_OBJECT, [op]))
             short.append(
                 ResOperation(rop.GUARD_CLASS, [op, self._known_class]))
         else:
             short.append(
                 ResOperation(rop.GUARD_NONNULL_CLASS,
                              [op, self._known_class]))
     elif self.descr is not None:
         short.append(ResOperation(rop.GUARD_NONNULL, [op]))
         if not optimizer.cpu.remove_gctypeptr:
             short.append(ResOperation(rop.GUARD_IS_OBJECT, [op]))
         short.append(
             ResOperation(rop.GUARD_SUBCLASS,
                          [op, ConstInt(self.descr.get_vtable())]))
     else:
         AbstractStructPtrInfo.make_guards(self, op, short, optimizer)
Esempio n. 3
0
File: gc.py Progetto: weijiwei/pypy
 def _rewrite_changeable_constptrs(self, op, ops_with_movable_const_ptr,
                                   moving_obj_tracker):
     newops = []
     for arg_i in ops_with_movable_const_ptr[op]:
         v = op.getarg(arg_i)
         # assert to make sure we got what we expected
         assert isinstance(v, ConstPtr)
         result_ptr = BoxPtr()
         array_index = moving_obj_tracker.get_array_index(v)
         load_op = ResOperation(rop.GETARRAYITEM_GC, [
             moving_obj_tracker.const_ptr_gcref_array,
             ConstInt(array_index)
         ],
                                result_ptr,
                                descr=moving_obj_tracker.ptr_array_descr)
         newops.append(load_op)
         op.setarg(arg_i, result_ptr)
     #
     newops.append(op)
     return newops
Esempio n. 4
0
 def force_box(self, op, optforce=None):
     op = get_box_replacement(op)
     if optforce is None:
         #import pdb; pdb.set_trace()
         optforce = self
     info = op.get_forwarded()
     if self.optunroll and self.optunroll.potential_extra_ops:
         # XXX hack
         try:
             preamble_op = self.optunroll.potential_extra_ops.pop(op)
         except KeyError:
             pass
         else:
             sb = self.optunroll.short_preamble_producer
             sb.add_preamble_op(preamble_op)
     if info is not None:
         if op.type == 'i' and info.is_constant():
             return ConstInt(info.getint())
         return info.force_box(op, optforce)
     return op
Esempio n. 5
0
    def _optimize_CALL_INT_PY_MOD(self, op):
        arg1 = op.getarg(1)
        b1 = self.getintbound(arg1)
        arg2 = op.getarg(2)
        b2 = self.getintbound(arg2)

        if b1.is_constant() and b1.getint() == 0:
            self.make_constant_int(op, 0)
            self.last_emitted_operation = REMOVED
            return True
        # This is Python's integer division: 'x // (2**shift)' can always
        # be replaced with 'x >> shift', even for negative values of x
        if not b2.is_constant():
            return False
        val = b2.getint()
        if val <= 0:
            return False
        if val == 1:
            self.make_constant_int(op, 0)
            self.last_emitted_operation = REMOVED
            return True
        elif val & (val - 1) == 0:  # val == 2**shift
            from rpython.jit.metainterp.history import DONT_CHANGE
            # x % power-of-two ==> x & (power-of-two - 1)
            # with Python's modulo, this is valid even if 'x' is negative.
            op = self.replace_op_with(
                op,
                rop.INT_AND,
                args=[arg1, ConstInt(val - 1)],
                descr=DONT_CHANGE)  # <- xxx rename? means "kill"
            self.optimizer.send_extra_operation(op)
            return True
        else:
            from rpython.jit.metainterp.optimizeopt import intdiv
            known_nonneg = b1.known_ge(IntBound(0, 0))
            operations = intdiv.modulo_operations(arg1, val, known_nonneg)
            newop = None
            for newop in operations:
                self.optimizer.send_extra_operation(newop)
            self.make_equal_to(op, newop)
            return True
Esempio n. 6
0
    def test_call_aligned_with_imm_values(self):
        cpu = self.cpu
        if not cpu.supports_floats:
            py.test.skip('requires floats')

        def func(*args):
            return float(sum(args))

        F = lltype.Float
        I = lltype.Signed
        floats = [0.7, 5.8, 0.1, 0.3, 0.9, -2.34, -3.45, -4.56]
        ints = [7, 11, 23, 13, -42, 1111, 95, 1]
        for case in range(256):
            result = 0.0
            args = []
            argslist = []
            local_floats = list(floats)
            local_ints = list(ints)
            for i in range(8):
                if case & (1 << i):
                    args.append(F)
                    arg = local_floats.pop()
                    result += arg
                    argslist.append(constfloat(arg))
                else:
                    args.append(I)
                    arg = local_ints.pop()
                    result += arg
                    argslist.append(ConstInt(arg))
            FUNC = self.FuncType(args, F)
            FPTR = self.Ptr(FUNC)
            func_ptr = llhelper(FPTR, func)
            calldescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
                                        EffectInfo.MOST_GENERAL)
            funcbox = self.get_funcbox(cpu, func_ptr)

            res = self.execute_operation(rop.CALL_F, [funcbox] + argslist,
                                         'float',
                                         descr=calldescr)
            res = longlong.getrealfloat(res)
            assert abs(res - result) < 0.0001
Esempio n. 7
0
 def make_varray(self, arraydescr, size, source_op, clear=False):
     if not info.reasonable_array_index(size):
         return False
     if arraydescr.is_array_of_structs():
         assert clear
         opinfo = info.ArrayStructInfo(arraydescr, size, is_virtual=True)
     else:
         const = self.optimizer.new_const_item(arraydescr)
         opinfo = info.ArrayPtrInfo(arraydescr,
                                    const,
                                    size,
                                    clear,
                                    is_virtual=True)
     # Replace 'source_op' with a version in which the length is
     # given as directly a Const, without relying on forwarding.
     # See test_virtual_array_length_discovered_constant_2.
     newop = self.replace_op_with(source_op,
                                  source_op.getopnum(),
                                  args=[ConstInt(size)])
     newop.set_forwarded(opinfo)
     return True
Esempio n. 8
0
    def gen_malloc_frame(self, frame_info):
        descrs = self.gc_ll_descr.getframedescrs(self.cpu)
        if self.gc_ll_descr.kind == 'boehm':
            ofs, size, sign = unpack_fielddescr(descrs.jfi_frame_depth)
            if sign:
                size = -size
            args = [ConstInt(frame_info), ConstInt(ofs), ConstInt(size)]
            size = ResOperation(rop.GC_LOAD_I, args)
            self.emit_op(size)
            frame = ResOperation(rop.NEW_ARRAY, [size],
                                 descr=descrs.arraydescr)
            self.handle_new_array(descrs.arraydescr, frame)
            return self.get_box_replacement(frame)
        else:
            # we read size in bytes here, not the length
            ofs, size, sign = unpack_fielddescr(descrs.jfi_frame_size)
            if sign:
                size = -size
            args = [ConstInt(frame_info), ConstInt(ofs), ConstInt(size)]
            size = ResOperation(rop.GC_LOAD_I, args)
            self.emit_op(size)
            frame = self.gen_malloc_nursery_varsize_frame(size)
            self.gen_initialize_tid(frame, descrs.arraydescr.tid)
            # we need to explicitely zero all the gc fields, because
            # of the unusal malloc pattern

            length = self.emit_getfield(ConstInt(frame_info),
                                        descr=descrs.jfi_frame_depth, raw=True)
            self.emit_setfield(frame, self.c_zero,
                               descr=descrs.jf_extra_stack_depth)
            self.emit_setfield(frame, self.c_null,
                               descr=descrs.jf_savedata)
            self.emit_setfield(frame, self.c_null,
                               descr=descrs.jf_force_descr)
            self.emit_setfield(frame, self.c_null,
                               descr=descrs.jf_descr)
            self.emit_setfield(frame, self.c_null,
                               descr=descrs.jf_guard_exc)
            self.emit_setfield(frame, self.c_null,
                               descr=descrs.jf_forward)
            self.gen_initialize_len(frame, length,
                                    descrs.arraydescr.lendescr)
            return self.get_box_replacement(frame)
Esempio n. 9
0
def test_bug_rshift():
    v1 = BoxInt()
    v2 = BoxInt()
    v3 = BoxInt()
    v4 = BoxInt()
    inputargs = [v1]
    operations = [
        ResOperation(rop.INT_ADD, [v1, v1], v2),
        ResOperation(rop.INT_INVERT, [v2], v3),
        ResOperation(rop.UINT_RSHIFT, [v1, ConstInt(3)], v4),
        ResOperation(rop.GUARD_FALSE, [v1], None, descr=BasicFailDescr()),
        ResOperation(rop.FINISH, [], None, descr=BasicFinalDescr(1)),
    ]
    operations[-2].setfailargs([v4, v3])
    cpu = CPU(None, None)
    cpu.setup_once()
    looptoken = JitCellToken()
    cpu.compile_loop(inputargs, operations, looptoken)
    deadframe = cpu.execute_token(looptoken, 9)
    assert cpu.get_int_value(deadframe, 0) == (9 >> 3)
    assert cpu.get_int_value(deadframe, 1) == (~18)
Esempio n. 10
0
    def optimize_INT_FLOORDIV(self, op):
        arg0 = op.getarg(0)
        b1 = self.getintbound(arg0)
        arg1 = op.getarg(1)
        b2 = self.getintbound(arg1)

        if b2.is_constant() and b2.getint() == 1:
            self.make_equal_to(op, arg0)
            return
        elif b1.is_constant() and b1.getint() == 0:
            self.make_constant_int(op, 0)
            return
        if b1.known_ge(IntBound(0, 0)) and b2.is_constant():
            val = b2.getint()
            if val & (val - 1) == 0 and val > 0:  # val == 2**shift
                op = self.replace_op_with(
                    op,
                    rop.INT_RSHIFT,
                    args=[op.getarg(0),
                          ConstInt(highest_bit(val))])
        self.emit_operation(op)
Esempio n. 11
0
 def test_int_add(self):
     # random seed: 1202
     # block length: 4
     # AssertionError: Got 1431655764, expected 357913940 for value #3
     faildescr1 = BasicFailDescr(1)
     faildescr2 = BasicFailDescr(2)
     v1 = BoxInt()
     v2 = BoxInt()
     v3 = BoxInt()
     v4 = BoxInt()
     v5 = BoxInt()
     v6 = BoxInt()
     v7 = BoxInt()
     v8 = BoxInt()
     v9 = BoxInt()
     v10 = BoxInt()
     v11 = BoxInt()
     tmp12 = BoxInt()
     cpu = CPU(None, None)
     cpu.setup_once()
     inputargs = [v1, v2, v3, v4, v5, v6, v7, v8, v9, v10]
     operations = [
         ResOperation(rop.INT_ADD, [ConstInt(-1073741825), v3], v11),
         ResOperation(rop.INT_IS_TRUE, [v1], tmp12),
         ResOperation(rop.GUARD_FALSE, [tmp12], None, descr=faildescr1),
         ResOperation(rop.GUARD_FALSE, [v1], None, descr=faildescr2),
         ]
     operations[2].setfailargs([v10, v3, v6, v11, v9, v2])
     operations[-1].setfailargs([v8, v2, v10, v6, v7, v9, v5, v4])
     looptoken = JitCellToken()
     cpu.compile_loop(inputargs, operations, looptoken)
     args = [3 , -5 , 1431655765 , 47 , 12 , 1789569706 , 15 , 939524096 , 16 , -43]
     deadframe = cpu.execute_token(looptoken, *args)
     assert cpu.get_latest_descr(deadframe).identifier == 1
     assert cpu.get_int_value(deadframe, 0) == -43
     assert cpu.get_int_value(deadframe, 1) == 1431655765
     assert cpu.get_int_value(deadframe, 2) == 1789569706
     assert cpu.get_int_value(deadframe, 3) == 357913940
     assert cpu.get_int_value(deadframe, 4) == 16
     assert cpu.get_int_value(deadframe, 5) == -5
Esempio n. 12
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:
         descr = op.getdescr()
         self.handle_new_fixedsize(descr, op)
         if self.gc_ll_descr.fielddescr_vtable is not None:
             self.emit_setfield(op, ConstInt(descr.get_vtable()),
                                descr=self.gc_ll_descr.fielddescr_vtable)
     elif opnum == rop.NEW_ARRAY or opnum == rop.NEW_ARRAY_CLEAR:
         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,
                               kind=FLAG_STR)
     elif opnum == rop.NEWUNICODE:
         self.handle_new_array(self.gc_ll_descr.unicode_descr, op,
                               kind=FLAG_UNICODE)
     else:
         raise NotImplementedError(op.getopname())
Esempio n. 13
0
 def remove_tested_failarg(self, op):
     opnum = op.getopnum()
     if not (opnum == rop.GUARD_TRUE or opnum == rop.GUARD_FALSE):
         return
     if op.getarg(0).is_vector():
         return
     try:
         i = op.getfailargs().index(op.getarg(0))
     except ValueError:
         return
     # The checked value is also in the failargs.  The front-end
     # tries not to produce it, but doesn't always succeed (and
     # it's hard to test all cases).  Rewrite it away.
     value = int(opnum == rop.GUARD_FALSE)
     op1 = ResOperation(rop.SAME_AS_I, [ConstInt(value)])
     self.emit_op(op1)
     lst = op.getfailargs()[:]
     lst[i] = op1
     newop = op.copy_and_change(opnum)
     newop.setfailargs(lst)
     self._changed_op = op
     self._changed_op_to = newop
Esempio n. 14
0
def test_execute_nonspec():
    cpu = FakeCPU()
    descr = FakeDescr()
    # cases with a descr
    # arity == -1
    argboxes = [InputArgInt(321), ConstInt(123)]
    box = _execute_arglist(cpu, FakeMetaInterp(), rop.CALL_F, argboxes,
                           FakeCallDescr())
    assert longlong.getrealfloat(box) == 42.5
    # arity == 0
    box = _execute_arglist(cpu, None, rop.NEW, [], descr)
    assert box.fakeargs == ('new', descr)
    # arity == 1
    box1 = InputArgRef()
    box = _execute_arglist(cpu, None, rop.ARRAYLEN_GC, [box1], descr)
    assert box == 55
    # arity == 2
    box2 = boxfloat(222.2)
    fielddescr = FakeFieldDescr()
    _execute_arglist(cpu, None, rop.SETFIELD_GC, [box1, box2], fielddescr)
    assert cpu.fakesetfield == (box1.getref_base(), box2.getfloatstorage(),
                                fielddescr)
    # arity == 3
    box3 = InputArgInt(33)
    arraydescr = FakeArrayDescr()
    _execute_arglist(cpu, None, rop.SETARRAYITEM_GC, [box1, box3, box2],
                     arraydescr)
    assert cpu.fakesetarrayitem == (box1.getref_base(), box3.getint(),
                                    box2.getfloatstorage(), arraydescr)
    # cases without descr
    # arity == 1
    box = _execute_arglist(cpu, None, rop.INT_INVERT, [box3])
    assert box == ~33
    # arity == 2
    box = _execute_arglist(cpu, None, rop.INT_LSHIFT, [box3, InputArgInt(3)])
    assert box == 33 << 3
    # arity == 3
    _execute_arglist(cpu, None, rop.STRSETITEM, [box1, InputArgInt(3), box3])
    assert cpu.fakestrsetitem == (box1.getref_base(), 3, box3.getint())
Esempio n. 15
0
def test_execute_nonspec():
    cpu = FakeCPU()
    descr = FakeDescr()
    # cases with a descr
    # arity == -1
    argboxes = [BoxInt(321), ConstInt(123)]
    box = execute_nonspec(cpu, FakeMetaInterp(), rop.CALL, argboxes,
                          FakeCallDescr())
    assert box.getfloat() == 42.5
    # arity == 0
    box = execute_nonspec(cpu, None, rop.NEW, [], descr)
    assert box.value.fakeargs == ('new', descr)
    # arity == 1
    box1 = BoxPtr()
    box = execute_nonspec(cpu, None, rop.ARRAYLEN_GC, [box1], descr)
    assert box.value == 55
    # arity == 2
    box2 = boxfloat(222.2)
    fielddescr = FakeFieldDescr()
    execute_nonspec(cpu, None, rop.SETFIELD_GC, [box1, box2], fielddescr)
    assert cpu.fakesetfield == (box1.value, box2.value, fielddescr)
    # arity == 3
    box3 = BoxInt(33)
    arraydescr = FakeArrayDescr()
    execute_nonspec(cpu, None, rop.SETARRAYITEM_GC, [box1, box3, box2],
                    arraydescr)
    assert cpu.fakesetarrayitem == (box1.value, box3.value, box2.value,
                                    arraydescr)
    # cases without descr
    # arity == 1
    box = execute_nonspec(cpu, None, rop.INT_INVERT, [box3])
    assert box.value == ~33
    # arity == 2
    box = execute_nonspec(cpu, None, rop.INT_LSHIFT, [box3, BoxInt(3)])
    assert box.value == 33 << 3
    # arity == 3
    execute_nonspec(cpu, None, rop.STRSETITEM, [box1, BoxInt(3), box3])
    assert cpu.fakestrsetitem == (box1.value, 3, box3.value)
Esempio n. 16
0
def test_simple_read():
    #b1, b2, b3 = [BoxInt(), InputArgRef(), BoxInt()]
    c1, c2, c3 = [ConstInt(111), ConstInt(222), ConstInt(333)]
    storage = Storage()
    storage.rd_consts = [c1, c2, c3]
    numb = Numbering(
        [
            3,
            tag(0, TAGBOX),
            tagconst(0), NULLREF,
            tag(0, TAGBOX),
            tag(1, TAGBOX)
        ] + [tagconst(1), tagconst(2)] +
        [tag(0, TAGBOX), tag(1, TAGBOX),
         tag(2, TAGBOX)])
    storage.rd_numb = numb
    #
    cpu = MyCPU([42, gcref1, -66])
    metainterp = MyMetaInterp(cpu)
    reader = ResumeDataDirectReader(metainterp, storage, "deadframe")
    _next_section(reader, 42, 111, gcrefnull, 42, gcref1)
    _next_section(reader, 222, 333)
    _next_section(reader, 42, gcref1, -66)
    #
    reader = ResumeDataBoxReader(storage, "deadframe", metainterp)
    bi, br, bf = [None] * 3, [None] * 2, [None] * 0
    bh = MyBlackholeInterp([
        lltype.Signed, lltype.Signed, llmemory.GCREF, lltype.Signed,
        llmemory.GCREF
    ])
    bh.fake_consume_boxes(reader, bi, br, bf)
    b1s = reader.liveboxes[0]
    b2s = reader.liveboxes[1]
    assert_same(bi, [b1s, ConstInt(111), b1s])
    assert_same(br, [ConstPtr(gcrefnull), b2s])
    bi, br, bf = [None] * 2, [None] * 0, [None] * 0
    bh = MyBlackholeInterp([lltype.Signed, lltype.Signed])
    bh.fake_consume_boxes(reader, bi, br, bf)
    assert_same(bi, [ConstInt(222), ConstInt(333)])
    bi, br, bf = [None] * 2, [None] * 1, [None] * 0
    bh = MyBlackholeInterp([lltype.Signed, llmemory.GCREF, lltype.Signed])
    bh.fake_consume_boxes(reader, bi, br, bf)
    b3s = reader.liveboxes[2]
    assert_same(bi, [b1s, b3s])
    assert_same(br, [b2s])
Esempio n. 17
0
    def optimize_INT_MUL(self, op):
        v1 = self.getvalue(op.getarg(0))
        v2 = self.getvalue(op.getarg(1))

        # If one side of the op is 1 the result is the other side.
        if v1.is_constant() and v1.box.getint() == 1:
            self.make_equal_to(op.result, v2)
        elif v2.is_constant() and v2.box.getint() == 1:
            self.make_equal_to(op.result, v1)
        elif (v1.is_constant() and v1.box.getint() == 0) or \
             (v2.is_constant() and v2.box.getint() == 0):
            self.make_constant_int(op.result, 0)
        else:
            for lhs, rhs in [(v1, v2), (v2, v1)]:
                if lhs.is_constant():
                    x = lhs.box.getint()
                    # x & (x - 1) == 0 is a quick test for power of 2
                    if x & (x - 1) == 0:
                        new_rhs = ConstInt(highest_bit(lhs.box.getint()))
                        op = op.copy_and_change(rop.INT_LSHIFT,
                                                args=[rhs.box, new_rhs])
                        break
            self.emit_operation(op)
Esempio n. 18
0
def patch_new_loop_to_load_virtualizable_fields(loop, jitdriver_sd, vable):
    # XXX merge with rewriting
    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]
        opnum = OpHelpers.getfield_for_descr(descr)
        emit_op(extra_ops,
                ResOperation(opnum, [vable_box], descr=descr))
        box.set_forwarded(extra_ops[-1])
        i += 1
    arrayindex = 0
    for descr in vinfo.array_field_descrs:
        arraylen = vinfo.get_array_length(vable, arrayindex)
        arrayop = ResOperation(rop.GETFIELD_GC_R, [vable_box], descr=descr)
        emit_op(extra_ops, arrayop)
        arraydescr = vinfo.array_descrs[arrayindex]
        assert i + arraylen <= len(inputargs)
        for index in range(arraylen):
            opnum = OpHelpers.getarrayitem_for_descr(arraydescr)
            box = inputargs[i]
            emit_op(extra_ops,
                ResOperation(opnum,
                             [arrayop, ConstInt(index)],
                             descr=arraydescr))
            i += 1
            box.set_forwarded(extra_ops[-1])
        arrayindex += 1
    assert i == len(inputargs)
    for op in loop.operations:
        emit_op(extra_ops, op)
    loop.operations = extra_ops
Esempio n. 19
0
    def _optimize_CALL_INT_PY_DIV(self, op):
        arg1 = op.getarg(1)
        b1 = self.getintbound(arg1)
        arg2 = op.getarg(2)
        b2 = self.getintbound(arg2)

        if b1.equal(0):
            self.make_constant_int(op, 0)
            self.last_emitted_operation = REMOVED
            return True
        if not b2.is_constant():
            return False
        val = b2.getint()
        if val <= 0:
            return False
        if val == 1:
            self.make_equal_to(op, arg1)
            self.last_emitted_operation = REMOVED
            return True
        elif val & (val - 1) == 0:  # val == 2**shift
            from rpython.jit.metainterp.history import DONT_CHANGE
            op = self.replace_op_with(
                op,
                rop.INT_RSHIFT,
                args=[arg1, ConstInt(highest_bit(val))],
                descr=DONT_CHANGE)  # <- xxx rename? means "kill"
            self.optimizer.send_extra_operation(op)
            return True
        else:
            from rpython.jit.metainterp.optimizeopt import intdiv
            known_nonneg = b1.known_nonnegative()
            operations = intdiv.division_operations(arg1, val, known_nonneg)
            newop = None
            for newop in operations:
                self.optimizer.send_extra_operation(newop)
            self.make_equal_to(op, newop)
            return True
Esempio n. 20
0
    def optimize_INT_MUL(self, op):
        arg1 = get_box_replacement(op.getarg(0))
        b1 = self.getintbound(arg1)
        arg2 = get_box_replacement(op.getarg(1))
        b2 = self.getintbound(arg2)

        # If one side of the op is 1 the result is the other side.
        if b1.equal(1):
            self.make_equal_to(op, arg2)
        elif b2.equal(1):
            self.make_equal_to(op, arg1)
        elif b1.equal(0) or b2.equal(0):
            self.make_constant_int(op, 0)
        else:
            for lhs, rhs in [(arg1, arg2), (arg2, arg1)]:
                lh_info = self.getintbound(lhs)
                if lh_info.is_constant():
                    x = lh_info.getint()
                    # x & (x - 1) == 0 is a quick test for power of 2
                    if x & (x - 1) == 0:
                        new_rhs = ConstInt(highest_bit(lh_info.getint()))
                        op = self.replace_op_with(op, rop.INT_LSHIFT, args=[rhs, new_rhs])
                        break
            return self.emit(op)
Esempio n. 21
0
 def _really_force(self, optforce):
     assert self.source_op is not None
     if not we_are_translated():
         self.source_op.name = 'FORCE ' + self.source_op.name
     # XXX two possible optimizations:
     # * if source_op is NEW_ARRAY_CLEAR, emit NEW_ARRAY if it's
     #   immediately followed by SETARRAYITEM_GC into all items (hard?)
     # * if source_op is NEW_ARRAY, emit NEW_ARRAY_CLEAR if it's
     #   followed by setting most items to zero anyway
     optforce.emit_operation(self.source_op)
     self.box = box = self.source_op.result
     for index in range(len(self._items)):
         subvalue = self._items[index]
         if subvalue is None:
             continue
         if self.clear:
             if subvalue is self.constvalue or subvalue.is_null():
                 continue
         subbox = subvalue.force_box(optforce)
         op = ResOperation(rop.SETARRAYITEM_GC,
                           [box, ConstInt(index), subbox],
                           None,
                           descr=self.arraydescr)
         optforce.emit_operation(op)
Esempio n. 22
0
def test_remove_consts_and_duplicates():
    class FakeStaticData:
        cpu = None
        warmrunnerdesc = None
    def is_another_box_like(box, referencebox):
        assert box is not referencebox
        assert isinstance(box, referencebox.clonebox().__class__)
        assert box.value == referencebox.value
        return True
    metainterp = pyjitpl.MetaInterp(FakeStaticData(), None)
    metainterp.history = History()
    b1 = BoxInt(1)
    b2 = BoxInt(2)
    c3 = ConstInt(3)
    boxes = [b1, b2, b1, c3]
    dup = {}
    metainterp.remove_consts_and_duplicates(boxes, 4, dup)
    assert boxes[0] is b1
    assert boxes[1] is b2
    assert is_another_box_like(boxes[2], b1)
    assert is_another_box_like(boxes[3], c3)
    assert equaloplists(metainterp.history.operations, [
        ResOperation(rop.SAME_AS, [b1], boxes[2]),
        ResOperation(rop.SAME_AS, [c3], boxes[3]),
        ])
    assert dup == {b1: None, b2: None}
    #
    del metainterp.history.operations[:]
    b4 = BoxInt(4)
    boxes = [b2, b4, "something random"]
    metainterp.remove_consts_and_duplicates(boxes, 2, dup)
    assert is_another_box_like(boxes[0], b2)
    assert boxes[1] is b4
    assert equaloplists(metainterp.history.operations, [
        ResOperation(rop.SAME_AS, [b2], boxes[0]),
        ])
Esempio n. 23
0
def test_make_jitdriver_callbacks_1():
    class FakeWarmRunnerDesc:
        cpu = None
        memory_manager = None
        rtyper = None
        jitcounter = DeterministicJitCounter()
    class FakeJitDriverSD:
        jitdriver = None
        _green_args_spec = [lltype.Signed, lltype.Float]
        _get_printable_location_ptr = None
        _confirm_enter_jit_ptr = None
        _get_unique_id_ptr = None
        _can_never_inline_ptr = None
        _should_unroll_one_iteration_ptr = None
        red_args_types = []
    class FakeCell:
        dont_trace_here = False
    state = WarmEnterState(FakeWarmRunnerDesc(), FakeJitDriverSD())
    def jit_getter(build, *args):
        return FakeCell()
    state.jit_getter = jit_getter
    state.make_jitdriver_callbacks()
    res = state.get_location_str([ConstInt(5), constfloat(42.5)])
    assert res == '(<unknown jitdriver>: no get_printable_location)'
Esempio n. 24
0
def test_virtual_adder_memo_const_sharing():
    b1s, b2s, b3s = [ConstInt(sys.maxint), ConstInt(2**23), ConstInt(-65)]
    storage, t = make_storage(b1s, b2s, b3s)
    metainterp_sd = FakeMetaInterpStaticData()
    memo = ResumeDataLoopMemo(metainterp_sd)
    i = t.get_iter()
    modifier = ResumeDataVirtualAdder(FakeOptimizer(i), storage, storage, i, memo)
    modifier.finish()
    assert len(memo.consts) == 2
    assert storage.rd_consts is memo.consts

    b1s, b2s, b3s = [ConstInt(sys.maxint), ConstInt(2**24), ConstInt(-65)]
    storage2, t = make_storage(b1s, b2s, b3s)
    i = t.get_iter()
    modifier2 = ResumeDataVirtualAdder(FakeOptimizer(i), storage2, storage2,
                                       i, memo)
    modifier2.finish()
    assert len(memo.consts) == 3
    assert storage2.rd_consts is memo.consts
Esempio n. 25
0
 def getstrlen(self, _, mode, lengthbox):
     if self._lengthbox is None:
         self._lengthbox = ConstInt(len(self._chars))
     return self._lengthbox
Esempio n. 26
0
    def build_bridge(self):
        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, [])
            else:
                op = ResOperation(rop.GUARD_EXCEPTION, [guard_op._exc_box])
            op.setdescr(self.builder.getfaildescr())
            op.setfailargs([])
            return op

        if self.dont_generate_more:
            return False
        r = self.r
        guard_op = self.guard_op
        fail_args = guard_op.getfailargs()
        fail_descr = guard_op.getdescr()
        op = self.should_fail_by
        if not op.getfailargs():
            return False
        for _fail_box in fail_args:
            _fail_box.set_forwarded(None)
        # generate the branch: a sequence of operations that ends in a FINISH
        subloop = DummyLoop([])
        self.subloops.append(subloop)  # keep around for debugging
        if rop.is_guard_exception(guard_op.getopnum()):
            subloop.operations.append(exc_handling(guard_op))
        bridge_builder = self.builder.fork(self.builder.cpu, subloop,
                                           op.getfailargs()[:])
        self.generate_ops(bridge_builder, r, subloop, op.getfailargs()[:])
        # note that 'self.guard_op' now points to the guard that will fail in
        # this new bridge, while 'guard_op' still points to the guard that
        # has just failed.

        if r.random() < 0.1 and self.guard_op is None:
            # Occasionally, instead of ending in a FINISH, we end in a jump
            # to another loop.  We don't do it, however, if the new bridge's
            # execution will hit 'self.guard_op', but only if it executes
            # to the FINISH normally.  (There is no point to the extra
            # complexity, as we might get the same effect by two calls
            # to build_bridge().)

            # First make up the other loop...
            #
            # New restriction: must have the same argument count and types
            # as the original loop
            subset = []
            for box in self.loop.inputargs:
                srcbox = r.choice(fail_args)
                if srcbox.type != box.type:
                    if box.type == INT:
                        srcbox = ConstInt(r.random_integer())
                    elif box.type == FLOAT:
                        srcbox = ConstFloat(r.random_float_storage())
                    else:
                        raise AssertionError(box.type)
                subset.append(srcbox)
            #
            args = []
            for x in subset:
                if x.type == INT:
                    args.append(InputArgInt(getint(x)))
                elif x.type == FLOAT:
                    args.append(InputArgFloat(getfloatstorage(x)))
                else:
                    assert 0, x.type
            rl = RandomLoop(self.builder.cpu, self.builder.fork, r, args)
            # done
            self.should_fail_by = rl.should_fail_by
            self.expected = rl.expected
            assert len(rl.loop.inputargs) == len(args)
            # The new bridge's execution will end normally at its FINISH.
            # Just replace the FINISH with the JUMP to the new loop.
            jump_op = ResOperation(rop.JUMP,
                                   subset,
                                   descr=rl.loop._targettoken)
            subloop.operations[-1] = jump_op
            self.guard_op = rl.guard_op
            self.prebuilt_ptr_consts += rl.prebuilt_ptr_consts
            self.loop._jitcelltoken.record_jump_to(rl.loop._jitcelltoken)
            self.dont_generate_more = True
        if r.random() < .05:
            return False
        dump(subloop)
        self.builder.cpu.compile_bridge(fail_descr, fail_args,
                                        subloop.operations,
                                        self.loop._jitcelltoken)

        if self.output:
            bridge_builder.print_loop(self.output, fail_descr, fail_args)
        return True
Esempio n. 27
0
 def produce_into(self, builder, r):
     if r.random() < 0.4:
         UnaryOperation.produce_into(self, builder, r)
     else:
         self.put(builder, [ConstInt(r.random_integer())])
Esempio n. 28
0
 def prepare_op_guard_no_exception(self, op, fcond):
     loc = self.make_sure_var_in_reg(ConstInt(self.cpu.pos_exception()))
     arglocs = self._prepare_guard(op, [loc])
     return arglocs
Esempio n. 29
0
 def produce_into(self, builder, r):
     v, offset = self.field_descr(builder, r)
     builder.do(self.opnum, [v, ConstInt(offset)], None)
Esempio n. 30
0
def ConstAddr(addr, cpu):
    return ConstInt(heaptracker.adr2int(addr))