Example #1
0
def test_include_write_array():
    A = lltype.GcArray(lltype.Signed)
    effects = frozenset([("array", lltype.Ptr(A))])
    effectinfo = effectinfo_from_writeanalyze(effects, FakeCPU())
    assert not effectinfo.readonly_descrs_fields
    assert not effectinfo.write_descrs_fields
    assert list(effectinfo.write_descrs_arrays) == [('arraydescr', A)]
Example #2
0
def test_include_write_field():
    S = lltype.GcStruct("S", ("a", lltype.Signed))
    effects = frozenset([("struct", lltype.Ptr(S), "a")])
    effectinfo = effectinfo_from_writeanalyze(effects, FakeCPU())
    assert list(effectinfo._write_descrs_fields) == [('fielddescr', S, "a")]
    assert not effectinfo._readonly_descrs_fields
    assert not effectinfo._write_descrs_arrays
Example #3
0
def test_include_write_array():
    A = lltype.GcArray(lltype.Signed)
    effects = frozenset([("array", lltype.Ptr(A))])
    effectinfo = effectinfo_from_writeanalyze(effects, FakeCPU())
    assert not effectinfo.readonly_descrs_fields
    assert not effectinfo.write_descrs_fields
    assert list(effectinfo.write_descrs_arrays) == [('arraydescr', A)]
Example #4
0
def test_include_write_field():
    S = lltype.GcStruct("S", ("a", lltype.Signed))
    effects = frozenset([("struct", lltype.Ptr(S), "a")])
    effectinfo = effectinfo_from_writeanalyze(effects, FakeCPU())
    assert list(effectinfo.write_descrs_fields) == [('fielddescr', S, "a")]
    assert not effectinfo.readonly_descrs_fields
    assert not effectinfo.write_descrs_arrays
Example #5
0
def test_filter_out_struct_with_void():
    effects = frozenset([
        ("struct", lltype.Ptr(lltype.GcStruct("x", ("a", lltype.Void))), "a")
    ])
    effectinfo = effectinfo_from_writeanalyze(effects, None)
    assert not effectinfo.readonly_descrs_fields
    assert not effectinfo.write_descrs_fields
    assert not effectinfo.write_descrs_arrays
Example #6
0
 def getcalldescr(self, op, oopspecindex=EffectInfo.OS_NONE,
                  extraeffect=None, extradescr=None):
     """Return the calldescr that describes all calls done by 'op'.
     This returns a calldescr that we can put in the corresponding
     call operation in the calling jitcode.  It gets an effectinfo
     describing the effect of the call: which field types it may
     change, whether it can force virtualizables, whether it can
     raise, etc.
     """
     NON_VOID_ARGS = [x.concretetype for x in op.args[1:]
                                     if x.concretetype is not lltype.Void]
     RESULT = op.result.concretetype
     # check the number and type of arguments
     FUNC = op.args[0].concretetype.TO
     ARGS = FUNC.ARGS
     if NON_VOID_ARGS != [T for T in ARGS if T is not lltype.Void]:
         raise Exception(
             "in operation %r: caling a function with signature %r, "
             "but passing actual arguments (ignoring voids) of types %r"
             % (op, FUNC, NON_VOID_ARGS))
     if RESULT != FUNC.RESULT:
         raise Exception(
             "in operation %r: caling a function with signature %r, "
             "but the actual return type is %r" % (op, FUNC, RESULT))
     # ok
     # get the 'elidable' and 'loopinvariant' flags from the function object
     elidable = False
     loopinvariant = False
     call_release_gil_target = llmemory.NULL
     if op.opname == "direct_call":
         funcobj = op.args[0].value._obj
         assert getattr(funcobj, 'calling_conv', 'c') == 'c', (
             "%r: getcalldescr() with a non-default call ABI" % (op,))
         func = getattr(funcobj, '_callable', None)
         elidable = getattr(func, "_elidable_function_", False)
         loopinvariant = getattr(func, "_jit_loop_invariant_", False)
         if loopinvariant:
             assert not NON_VOID_ARGS, ("arguments not supported for "
                                        "loop-invariant function!")
         if getattr(func, "_call_aroundstate_target_", None):
             call_release_gil_target = func._call_aroundstate_target_
             call_release_gil_target = llmemory.cast_ptr_to_adr(
                 call_release_gil_target)
     elif op.opname == 'indirect_call':
         # check that we're not trying to call indirectly some
         # function with the special flags
         graphs = op.args[-1].value
         for graph in (graphs or ()):
             if not hasattr(graph, 'func'):
                 continue
             error = None
             if hasattr(graph.func, '_elidable_function_'):
                 error = '@jit.elidable'
             if hasattr(graph.func, '_jit_loop_invariant_'):
                 error = '@jit.loop_invariant'
             if hasattr(graph.func, '_call_aroundstate_target_'):
                 error = '_call_aroundstate_target_'
             if not error:
                 continue
             raise Exception(
                 "%r is an indirect call to a family of functions "
                 "(or methods) that includes %r. However, the latter "
                 "is marked %r. You need to use an indirection: replace "
                 "it with a non-marked function/method which calls the "
                 "marked function." % (op, graph, error))
     # build the extraeffect
     random_effects = self.randomeffects_analyzer.analyze(op)
     if random_effects:
         extraeffect = EffectInfo.EF_RANDOM_EFFECTS
     # random_effects implies can_invalidate
     can_invalidate = random_effects or self.quasiimmut_analyzer.analyze(op)
     if extraeffect is None:
         if self.virtualizable_analyzer.analyze(op):
             extraeffect = EffectInfo.EF_FORCES_VIRTUAL_OR_VIRTUALIZABLE
         elif loopinvariant:
             extraeffect = EffectInfo.EF_LOOPINVARIANT
         elif elidable:
             if self._canraise(op):
                 extraeffect = EffectInfo.EF_ELIDABLE_CAN_RAISE
             else:
                 extraeffect = EffectInfo.EF_ELIDABLE_CANNOT_RAISE
         elif self._canraise(op):
             extraeffect = EffectInfo.EF_CAN_RAISE
         else:
             extraeffect = EffectInfo.EF_CANNOT_RAISE
     #
     # check that the result is really as expected
     if loopinvariant:
         if extraeffect != EffectInfo.EF_LOOPINVARIANT:
             raise Exception(
             "in operation %r: this calls a _jit_loop_invariant_ function,"
             " but this contradicts other sources (e.g. it can have random"
             " effects): EF=%s" % (op, extraeffect))
     if elidable:
         if extraeffect not in (EffectInfo.EF_ELIDABLE_CANNOT_RAISE,
                                EffectInfo.EF_ELIDABLE_CAN_RAISE):
             raise Exception(
             "in operation %r: this calls an _elidable_function_,"
             " but this contradicts other sources (e.g. it can have random"
             " effects): EF=%s" % (op, extraeffect))
     #
     effectinfo = effectinfo_from_writeanalyze(
         self.readwrite_analyzer.analyze(op, self.seen), self.cpu,
         extraeffect, oopspecindex, can_invalidate, call_release_gil_target,
         extradescr,
     )
     #
     assert effectinfo is not None
     if elidable or loopinvariant:
         assert extraeffect != EffectInfo.EF_FORCES_VIRTUAL_OR_VIRTUALIZABLE
         # XXX this should also say assert not can_invalidate, but
         #     it can't because our analyzer is not good enough for now
         #     (and getexecutioncontext() can't really invalidate)
     #
     return self.cpu.calldescrof(FUNC, tuple(NON_VOID_ARGS), RESULT,
                                 effectinfo)
Example #7
0
 def getcalldescr(self,
                  op,
                  oopspecindex=EffectInfo.OS_NONE,
                  extraeffect=None,
                  extradescr=None):
     """Return the calldescr that describes all calls done by 'op'.
     This returns a calldescr that we can put in the corresponding
     call operation in the calling jitcode.  It gets an effectinfo
     describing the effect of the call: which field types it may
     change, whether it can force virtualizables, whether it can
     raise, etc.
     """
     NON_VOID_ARGS = [
         x.concretetype for x in op.args[1:]
         if x.concretetype is not lltype.Void
     ]
     RESULT = op.result.concretetype
     # check the number and type of arguments
     FUNC = op.args[0].concretetype.TO
     ARGS = FUNC.ARGS
     if NON_VOID_ARGS != [T for T in ARGS if T is not lltype.Void]:
         raise Exception(
             "in operation %r: caling a function with signature %r, "
             "but passing actual arguments (ignoring voids) of types %r" %
             (op, FUNC, NON_VOID_ARGS))
     if RESULT != FUNC.RESULT:
         raise Exception(
             "in operation %r: caling a function with signature %r, "
             "but the actual return type is %r" % (op, FUNC, RESULT))
     # ok
     # get the 'elidable' and 'loopinvariant' flags from the function object
     elidable = False
     loopinvariant = False
     call_release_gil_target = EffectInfo._NO_CALL_RELEASE_GIL_TARGET
     if op.opname == "direct_call":
         funcobj = op.args[0].value._obj
         assert getattr(funcobj, 'calling_conv', 'c') == 'c', (
             "%r: getcalldescr() with a non-default call ABI" % (op, ))
         func = getattr(funcobj, '_callable', None)
         elidable = getattr(func, "_elidable_function_", False)
         loopinvariant = getattr(func, "_jit_loop_invariant_", False)
         if loopinvariant:
             assert not NON_VOID_ARGS, ("arguments not supported for "
                                        "loop-invariant function!")
         if getattr(func, "_call_aroundstate_target_", None):
             tgt_func, tgt_saveerr = func._call_aroundstate_target_
             tgt_func = llmemory.cast_ptr_to_adr(tgt_func)
             call_release_gil_target = (tgt_func, tgt_saveerr)
     elif op.opname == 'indirect_call':
         # check that we're not trying to call indirectly some
         # function with the special flags
         graphs = op.args[-1].value
         for graph in (graphs or ()):
             if not hasattr(graph, 'func'):
                 continue
             error = None
             if hasattr(graph.func, '_elidable_function_'):
                 error = '@jit.elidable'
             if hasattr(graph.func, '_jit_loop_invariant_'):
                 error = '@jit.loop_invariant'
             if hasattr(graph.func, '_call_aroundstate_target_'):
                 error = '_call_aroundstate_target_'
             if not error:
                 continue
             raise Exception(
                 "%r is an indirect call to a family of functions "
                 "(or methods) that includes %r. However, the latter "
                 "is marked %r. You need to use an indirection: replace "
                 "it with a non-marked function/method which calls the "
                 "marked function." % (op, graph, error))
     # build the extraeffect
     random_effects = self.randomeffects_analyzer.analyze(op)
     if random_effects:
         extraeffect = EffectInfo.EF_RANDOM_EFFECTS
     # random_effects implies can_invalidate
     can_invalidate = random_effects or self.quasiimmut_analyzer.analyze(op)
     if extraeffect is None:
         if self.virtualizable_analyzer.analyze(op):
             extraeffect = EffectInfo.EF_FORCES_VIRTUAL_OR_VIRTUALIZABLE
         elif loopinvariant:
             extraeffect = EffectInfo.EF_LOOPINVARIANT
         elif elidable:
             cr = self._canraise(op)
             if cr == "mem":
                 extraeffect = EffectInfo.EF_ELIDABLE_OR_MEMORYERROR
             elif cr:
                 extraeffect = EffectInfo.EF_ELIDABLE_CAN_RAISE
             else:
                 extraeffect = EffectInfo.EF_ELIDABLE_CANNOT_RAISE
         elif self._canraise(op):  # True or "mem"
             extraeffect = EffectInfo.EF_CAN_RAISE
         else:
             extraeffect = EffectInfo.EF_CANNOT_RAISE
     #
     # check that the result is really as expected
     if loopinvariant:
         if extraeffect != EffectInfo.EF_LOOPINVARIANT:
             raise Exception(
                 "in operation %r: this calls a _jit_loop_invariant_ function,"
                 " but this contradicts other sources (e.g. it can have random"
                 " effects): EF=%s" % (op, extraeffect))
     if elidable:
         if extraeffect not in (EffectInfo.EF_ELIDABLE_CANNOT_RAISE,
                                EffectInfo.EF_ELIDABLE_OR_MEMORYERROR,
                                EffectInfo.EF_ELIDABLE_CAN_RAISE):
             raise Exception(
                 "in operation %r: this calls an elidable function,"
                 " but this contradicts other sources (e.g. it can have random"
                 " effects): EF=%s" % (op, extraeffect))
         elif RESULT is lltype.Void:
             raise Exception(
                 "in operation %r: this calls an elidable function "
                 "but the function has no result" % (op, ))
     #
     effectinfo = effectinfo_from_writeanalyze(
         self.readwrite_analyzer.analyze(op, self.seen_rw),
         self.cpu,
         extraeffect,
         oopspecindex,
         can_invalidate,
         call_release_gil_target,
         extradescr,
         self.collect_analyzer.analyze(op, self.seen_gc),
     )
     #
     assert effectinfo is not None
     if elidable or loopinvariant:
         assert (effectinfo.extraeffect <
                 EffectInfo.EF_FORCES_VIRTUAL_OR_VIRTUALIZABLE)
         # XXX this should also say assert not can_invalidate, but
         #     it can't because our analyzer is not good enough for now
         #     (and getexecutioncontext() can't really invalidate)
     #
     return self.cpu.calldescrof(FUNC, tuple(NON_VOID_ARGS), RESULT,
                                 effectinfo)
Example #8
0
def test_filter_out_array_of_void():
    effects = frozenset([("array", lltype.Ptr(lltype.GcArray(lltype.Void)))])
    effectinfo = effectinfo_from_writeanalyze(effects, None)
    assert not effectinfo._readonly_descrs_fields
    assert not effectinfo._write_descrs_fields
    assert not effectinfo._write_descrs_arrays
Example #9
0
def test_filter_out_typeptr():
    effects = frozenset([("struct", lltype.Ptr(OBJECT), "typeptr")])
    effectinfo = effectinfo_from_writeanalyze(effects, None)
    assert not effectinfo._readonly_descrs_fields
    assert not effectinfo._write_descrs_fields
    assert not effectinfo._write_descrs_arrays
Example #10
0
def test_filter_out_struct_with_void():
    effects = frozenset([("struct", lltype.Ptr(lltype.GcStruct("x", ("a", lltype.Void))), "a")])
    effectinfo = effectinfo_from_writeanalyze(effects, None)
    assert not effectinfo._readonly_descrs_fields
    assert not effectinfo._write_descrs_fields
    assert not effectinfo._write_descrs_arrays
Example #11
0
File: call.py Project: charred/pypy
 def getcalldescr(self, op, oopspecindex=EffectInfo.OS_NONE,
                  extraeffect=None):
     """Return the calldescr that describes all calls done by 'op'.
     This returns a calldescr that we can put in the corresponding
     call operation in the calling jitcode.  It gets an effectinfo
     describing the effect of the call: which field types it may
     change, whether it can force virtualizables, whether it can
     raise, etc.
     """
     NON_VOID_ARGS = [x.concretetype for x in op.args[1:]
                                     if x.concretetype is not lltype.Void]
     RESULT = op.result.concretetype
     # check the number and type of arguments
     FUNC = op.args[0].concretetype.TO
     ARGS = FUNC.ARGS
     assert NON_VOID_ARGS == [T for T in ARGS if T is not lltype.Void]
     assert RESULT == FUNC.RESULT
     # ok
     # get the 'elidable' and 'loopinvariant' flags from the function object
     elidable = False
     loopinvariant = False
     call_release_gil_target = llmemory.NULL
     if op.opname == "direct_call":
         funcobj = op.args[0].value._obj
         assert getattr(funcobj, 'calling_conv', 'c') == 'c', (
             "%r: getcalldescr() with a non-default call ABI" % (op,))
         func = getattr(funcobj, '_callable', None)
         elidable = getattr(func, "_elidable_function_", False)
         loopinvariant = getattr(func, "_jit_loop_invariant_", False)
         if loopinvariant:
             assert not NON_VOID_ARGS, ("arguments not supported for "
                                        "loop-invariant function!")
         if getattr(func, "_call_aroundstate_target_", None):
             call_release_gil_target = func._call_aroundstate_target_
             call_release_gil_target = llmemory.cast_ptr_to_adr(
                 call_release_gil_target)
     # build the extraeffect
     random_effects = self.randomeffects_analyzer.analyze(op)
     if random_effects:
         extraeffect = EffectInfo.EF_RANDOM_EFFECTS
     # random_effects implies can_invalidate
     can_invalidate = random_effects or self.quasiimmut_analyzer.analyze(op)
     if extraeffect is None:
         if self.virtualizable_analyzer.analyze(op):
             extraeffect = EffectInfo.EF_FORCES_VIRTUAL_OR_VIRTUALIZABLE
         elif loopinvariant:
             extraeffect = EffectInfo.EF_LOOPINVARIANT
         elif elidable:
             if self._canraise(op):
                 extraeffect = EffectInfo.EF_ELIDABLE_CAN_RAISE
             else:
                 extraeffect = EffectInfo.EF_ELIDABLE_CANNOT_RAISE
         elif self._canraise(op):
             extraeffect = EffectInfo.EF_CAN_RAISE
         else:
             extraeffect = EffectInfo.EF_CANNOT_RAISE
     #
     effectinfo = effectinfo_from_writeanalyze(
         self.readwrite_analyzer.analyze(op), self.cpu, extraeffect,
         oopspecindex, can_invalidate, call_release_gil_target,
     )
     #
     assert effectinfo is not None
     if elidable or loopinvariant:
         assert extraeffect != EffectInfo.EF_FORCES_VIRTUAL_OR_VIRTUALIZABLE
         # XXX this should also say assert not can_invalidate, but
         #     it can't because our analyzer is not good enough for now
         #     (and getexecutioncontext() can't really invalidate)
     #
     return self.cpu.calldescrof(FUNC, tuple(NON_VOID_ARGS), RESULT,
                                 effectinfo)
Example #12
0
def test_filter_out_array_of_void():
    effects = frozenset([("array", lltype.Ptr(lltype.GcArray(lltype.Void)))])
    effectinfo = effectinfo_from_writeanalyze(effects, None)
    assert not effectinfo.readonly_descrs_fields
    assert not effectinfo.write_descrs_fields
    assert not effectinfo.write_descrs_arrays
Example #13
0
def test_filter_out_typeptr():
    effects = frozenset([("struct", lltype.Ptr(OBJECT), "typeptr")])
    effectinfo = effectinfo_from_writeanalyze(effects, None)
    assert not effectinfo.readonly_descrs_fields
    assert not effectinfo.write_descrs_fields
    assert not effectinfo.write_descrs_arrays