[pypy-svn] r74494 - in pypy/branch/blackhole-improvement/pypy/jit: backend/llgraph codewriter codewriter/test metainterp metainterp/test
arigo at codespeak.net
arigo at codespeak.net
Wed May 12 09:18:31 CEST 2010
Author: arigo
Date: Wed May 12 09:18:28 2010
New Revision: 74494
Added:
pypy/branch/blackhole-improvement/pypy/jit/codewriter/effectinfo.py
- copied, changed from r74456, pypy/branch/blackhole-improvement/pypy/jit/metainterp/effectinfo.py
pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_effectinfo.py
- copied, changed from r74456, pypy/branch/blackhole-improvement/pypy/jit/metainterp/test/test_effectinfo.py
Removed:
pypy/branch/blackhole-improvement/pypy/jit/metainterp/effectinfo.py
pypy/branch/blackhole-improvement/pypy/jit/metainterp/test/test_effectinfo.py
Modified:
pypy/branch/blackhole-improvement/pypy/jit/backend/llgraph/llimpl.py
pypy/branch/blackhole-improvement/pypy/jit/backend/llgraph/runner.py
pypy/branch/blackhole-improvement/pypy/jit/codewriter/assembler.py
pypy/branch/blackhole-improvement/pypy/jit/codewriter/call.py
pypy/branch/blackhole-improvement/pypy/jit/codewriter/flatten.py
pypy/branch/blackhole-improvement/pypy/jit/codewriter/format.py
pypy/branch/blackhole-improvement/pypy/jit/codewriter/jitcode.py
pypy/branch/blackhole-improvement/pypy/jit/codewriter/jtransform.py
pypy/branch/blackhole-improvement/pypy/jit/codewriter/liveness.py
pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_assembler.py
pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_codewriter.py
pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_flatten.py
pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_jtransform.py
pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_regalloc.py
pypy/branch/blackhole-improvement/pypy/jit/metainterp/blackhole.py
pypy/branch/blackhole-improvement/pypy/jit/metainterp/history.py
pypy/branch/blackhole-improvement/pypy/jit/metainterp/pyjitpl.py
pypy/branch/blackhole-improvement/pypy/jit/metainterp/typesystem.py
Log:
General progress.
Modified: pypy/branch/blackhole-improvement/pypy/jit/backend/llgraph/llimpl.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/backend/llgraph/llimpl.py (original)
+++ pypy/branch/blackhole-improvement/pypy/jit/backend/llgraph/llimpl.py Wed May 12 09:18:28 2010
@@ -1185,19 +1185,19 @@
array = array._obj.container
return array.getlength()
-def do_strlen(_, string):
+def do_strlen(string):
str = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), string)
return len(str.chars)
-def do_strgetitem(_, string, index):
+def do_strgetitem(string, index):
str = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), string)
return ord(str.chars[index])
-def do_unicodelen(_, string):
+def do_unicodelen(string):
uni = lltype.cast_opaque_ptr(lltype.Ptr(rstr.UNICODE), string)
return len(uni.chars)
-def do_unicodegetitem(_, string, index):
+def do_unicodegetitem(string, index):
uni = lltype.cast_opaque_ptr(lltype.Ptr(rstr.UNICODE), string)
return ord(uni.chars[index])
@@ -1311,18 +1311,18 @@
newvalue = cast_from_ptr(FIELDTYPE, newvalue)
setattr(ptr, fieldname, newvalue)
-def do_newstr(_, length):
+def do_newstr(length):
x = rstr.mallocstr(length)
return cast_to_ptr(x)
-def do_newunicode(_, length):
+def do_newunicode(length):
return cast_to_ptr(rstr.mallocunicode(length))
-def do_strsetitem(_, string, index, newvalue):
+def do_strsetitem(string, index, newvalue):
str = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), string)
str.chars[index] = chr(newvalue)
-def do_unicodesetitem(_, string, index, newvalue):
+def do_unicodesetitem(string, index, newvalue):
uni = lltype.cast_opaque_ptr(lltype.Ptr(rstr.UNICODE), string)
uni.chars[index] = unichr(newvalue)
Modified: pypy/branch/blackhole-improvement/pypy/jit/backend/llgraph/runner.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/backend/llgraph/runner.py (original)
+++ pypy/branch/blackhole-improvement/pypy/jit/backend/llgraph/runner.py Wed May 12 09:18:28 2010
@@ -315,23 +315,17 @@
## array = arraybox.getref_base()
## return history.BoxInt(llimpl.do_arraylen_gc(arraydescr, array))
-## def do_strlen(self, stringbox):
-## string = stringbox.getref_base()
-## return history.BoxInt(llimpl.do_strlen(0, string))
+ def bh_strlen(self, string):
+ return llimpl.do_strlen(string)
-## def do_strgetitem(self, stringbox, indexbox):
-## string = stringbox.getref_base()
-## index = indexbox.getint()
-## return history.BoxInt(llimpl.do_strgetitem(0, string, index))
+ def bh_strgetitem(self, string, index):
+ return llimpl.do_strgetitem(string, index)
-## def do_unicodelen(self, stringbox):
-## string = stringbox.getref_base()
-## return history.BoxInt(llimpl.do_unicodelen(0, string))
+ def bh_unicodelen(self, string):
+ return llimpl.do_unicodelen(string)
-## def do_unicodegetitem(self, stringbox, indexbox):
-## string = stringbox.getref_base()
-## index = indexbox.getint()
-## return history.BoxInt(llimpl.do_unicodegetitem(0, string, index))
+ def bh_unicodegetitem(self, string, index):
+ return llimpl.do_unicodegetitem(string, index)
## def do_getarrayitem_gc(self, arraybox, indexbox, arraydescr):
## assert isinstance(arraydescr, Descr)
@@ -509,25 +503,17 @@
## def do_same_as(self, box1):
## return box1.clonebox()
-## def do_newstr(self, lengthbox):
-## length = lengthbox.getint()
-## return history.BoxPtr(llimpl.do_newstr(0, length))
-
-## def do_newunicode(self, lengthbox):
-## length = lengthbox.getint()
-## return history.BoxPtr(llimpl.do_newunicode(0, length))
+ def bh_newstr(self, length):
+ return llimpl.do_newstr(length)
-## def do_strsetitem(self, stringbox, indexbox, newvaluebox):
-## string = stringbox.getref_base()
-## index = indexbox.getint()
-## newvalue = newvaluebox.getint()
-## llimpl.do_strsetitem(0, string, index, newvalue)
+ def bh_newunicode(self, length):
+ return llimpl.do_newunicode(length)
-## def do_unicodesetitem(self, stringbox, indexbox, newvaluebox):
-## string = stringbox.getref_base()
-## index = indexbox.getint()
-## newvalue = newvaluebox.getint()
-## llimpl.do_unicodesetitem(0, string, index, newvalue)
+ def bh_strsetitem(self, string, index, newvalue):
+ llimpl.do_strsetitem(string, index, newvalue)
+
+ def bh_unicodesetitem(self, string, index, newvalue):
+ llimpl.do_unicodesetitem(string, index, newvalue)
def bh_call_i(self, func, calldescr, args_i, args_r, args_f):
self._prepare_call(INT, calldescr, args_i, args_r, args_f)
Modified: pypy/branch/blackhole-improvement/pypy/jit/codewriter/assembler.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/codewriter/assembler.py (original)
+++ pypy/branch/blackhole-improvement/pypy/jit/codewriter/assembler.py Wed May 12 09:18:28 2010
@@ -1,6 +1,6 @@
from pypy.jit.metainterp.history import AbstractDescr, getkind
from pypy.jit.codewriter.flatten import Register, Label, TLabel, KINDS
-from pypy.jit.codewriter.flatten import ListOfKind
+from pypy.jit.codewriter.flatten import ListOfKind, IndirectCallTargets
from pypy.jit.codewriter.format import format_assembler
from pypy.jit.codewriter.jitcode import SwitchDictDescr, JitCode
from pypy.objspace.flow.model import Constant
@@ -12,6 +12,7 @@
def __init__(self):
self.insns = {}
self.descrs = []
+ self.indirectcalltargets = set() # set of JitCodes
self._descr_dict = {}
self._count_jitcodes = 0
@@ -26,6 +27,7 @@
self.check_result()
if jitcode is None:
jitcode = JitCode(ssarepr.name)
+ jitcode._ssarepr = ssarepr
self.make_jitcode(jitcode)
if self._count_jitcodes < 20: # stop if we have a lot of them
jitcode._dump = format_assembler(ssarepr)
@@ -142,6 +144,8 @@
self.code.append(chr(num & 0xFF))
self.code.append(chr(num >> 8))
argcodes.append('d')
+ elif isinstance(x, IndirectCallTargets):
+ self.indirectcalltargets.update(x.lst)
else:
raise NotImplementedError(x)
#
Modified: pypy/branch/blackhole-improvement/pypy/jit/codewriter/call.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/codewriter/call.py (original)
+++ pypy/branch/blackhole-improvement/pypy/jit/codewriter/call.py Wed May 12 09:18:28 2010
@@ -5,13 +5,13 @@
from pypy.jit.codewriter import support
from pypy.jit.codewriter.jitcode import JitCode
+from pypy.jit.codewriter.effectinfo import VirtualizableAnalyzer
+from pypy.jit.codewriter.effectinfo import effectinfo_from_writeanalyze
+from pypy.jit.codewriter import effectinfo as ef
from pypy.translator.simplify import get_funcobj, get_functype
from pypy.rpython.lltypesystem import lltype, llmemory
-
from pypy.translator.backendopt.canraise import RaiseAnalyzer
from pypy.translator.backendopt.writeanalyze import ReadWriteAnalyzer
-from pypy.jit.metainterp.effectinfo import VirtualizableAnalyzer
-from pypy.jit.metainterp.effectinfo import effectinfo_from_writeanalyze
class CallControl(object):
@@ -146,6 +146,12 @@
return jitcode
def get_jitcode_calldescr(self, graph):
+ """Return the calldescr that describes calls to the 'graph'.
+ This returns a calldescr that is appropriate to attach to the
+ jitcode corresponding to 'graph'. It has no extra effectinfo,
+ because it is not needed there; it is only used by the blackhole
+ interp to really do the call corresponding to 'inline_call' ops.
+ """
fnptr = self.rtyper.getcallable(graph)
FUNC = get_functype(lltype.typeOf(fnptr))
if self.rtyper.type_system.name == 'ootypesystem':
@@ -158,6 +164,13 @@
return (fnaddr, calldescr)
def getcalldescr(self, op):
+ """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
@@ -167,15 +180,46 @@
assert NON_VOID_ARGS == [T for T in ARGS if T is not lltype.Void]
assert RESULT == FUNC.RESULT
# ok
+ # get the 'pure' and 'loopinvariant' flags from the function object
+ pure = False
+ loopinvariant = False
+ if op.opname == "direct_call":
+ func = getattr(get_funcobj(op.args[0].value), '_callable', None)
+ pure = getattr(func, "_pure_function_", False)
+ loopinvariant = getattr(func, "_jit_loop_invariant_", False)
+ if loopinvariant:
+ assert not NON_VOID_ARGS, ("arguments not supported for "
+ "loop-invariant function!")
+ # build the extraeffect
+ if self.virtualizable_analyzer.analyze(op):
+ extraeffect = ef.EF_FORCES_VIRTUAL_OR_VIRTUALIZABLE
+ elif loopinvariant:
+ extraeffect = ef.EF_LOOPINVARIANT
+ elif pure:
+ # XXX check what to do about exceptions (also MemoryError?)
+ extraeffect = ef.EF_PURE
+ elif self._canraise(op):
+ extraeffect = ef.EF_CAN_RAISE
+ else:
+ extraeffect = ef.EF_CANNOT_RAISE
+ #
effectinfo = effectinfo_from_writeanalyze(
- self.readwrite_analyzer.analyze(op),
- self.cpu,
- self.virtualizable_analyzer.analyze(op))
- calldescr = self.cpu.calldescrof(FUNC, tuple(NON_VOID_ARGS), RESULT,
- effectinfo)
+ self.readwrite_analyzer.analyze(op), self.cpu, extraeffect)
+ #
+ if pure or loopinvariant:
+ assert effectinfo is not None
+ assert extraeffect != ef.EF_FORCES_VIRTUAL_OR_VIRTUALIZABLE
+ #
+ return self.cpu.calldescrof(FUNC, tuple(NON_VOID_ARGS), RESULT,
+ effectinfo)
+
+ def _canraise(self, op):
try:
- canraise = self.raise_analyzer.can_raise(op)
+ return self.raise_analyzer.can_raise(op)
except lltype.DelayedPointer:
- canraise = True # if we need to look into the delayed ptr that is
- # the portal, then it's certainly going to raise
- return calldescr, canraise
+ return True # if we need to look into the delayed ptr that is
+ # the portal, then it's certainly going to raise
+
+ def calldescr_canraise(self, calldescr):
+ effectinfo = calldescr.get_extra_info()
+ return effectinfo is None or effectinfo.extraeffect >= ef.EF_CAN_RAISE
Copied: pypy/branch/blackhole-improvement/pypy/jit/codewriter/effectinfo.py (from r74456, pypy/branch/blackhole-improvement/pypy/jit/metainterp/effectinfo.py)
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/metainterp/effectinfo.py (original)
+++ pypy/branch/blackhole-improvement/pypy/jit/codewriter/effectinfo.py Wed May 12 09:18:28 2010
@@ -4,28 +4,35 @@
from pypy.rpython.ootypesystem import ootype
from pypy.translator.backendopt.graphanalyze import BoolGraphAnalyzer
+# the 'extraeffect' field is one of the following values:
+EF_PURE = 0 # pure function (and cannot raise)
+EF_CANNOT_RAISE = 1 # a function which cannot raise
+EF_CAN_RAISE = 2 # normal function (can raise)
+EF_LOOPINVARIANT = 3 # special: call it only once per loop
+EF_FORCES_VIRTUAL_OR_VIRTUALIZABLE = 4 # can raise and force virtualizables
+
+
class EffectInfo(object):
_cache = {}
def __new__(cls, readonly_descrs_fields,
write_descrs_fields, write_descrs_arrays,
- forces_virtual_or_virtualizable=False):
+ extraeffect=EF_CAN_RAISE):
key = (frozenset(readonly_descrs_fields),
frozenset(write_descrs_fields),
frozenset(write_descrs_arrays),
- forces_virtual_or_virtualizable)
+ extraeffect)
if key in cls._cache:
return cls._cache[key]
result = object.__new__(cls)
result.readonly_descrs_fields = readonly_descrs_fields
result.write_descrs_fields = write_descrs_fields
result.write_descrs_arrays = write_descrs_arrays
- result.forces_virtual_or_virtualizable= forces_virtual_or_virtualizable
+ result.extraeffect = extraeffect
cls._cache[key] = result
return result
-def effectinfo_from_writeanalyze(effects, cpu,
- forces_virtual_or_virtualizable=False):
+def effectinfo_from_writeanalyze(effects, cpu, extraeffect=EF_CAN_RAISE):
from pypy.translator.backendopt.writeanalyze import top_set
if effects is top_set:
return None
@@ -62,7 +69,7 @@
return EffectInfo(readonly_descrs_fields,
write_descrs_fields,
write_descrs_arrays,
- forces_virtual_or_virtualizable)
+ extraeffect)
def consider_struct(TYPE, fieldname):
if fieldType(TYPE, fieldname) is lltype.Void:
Modified: pypy/branch/blackhole-improvement/pypy/jit/codewriter/flatten.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/codewriter/flatten.py (original)
+++ pypy/branch/blackhole-improvement/pypy/jit/codewriter/flatten.py Wed May 12 09:18:28 2010
@@ -44,6 +44,12 @@
def __iter__(self):
return iter(self.content)
+class IndirectCallTargets(object):
+ def __init__(self, lst):
+ self.lst = lst # list of JitCodes
+ def __repr__(self):
+ return '<IndirectCallTargets>'
+
KINDS = ['int', 'ref', 'float']
# ____________________________________________________________
@@ -194,7 +200,7 @@
linkfalse, linktrue = linktrue, linkfalse
opname = 'goto_if_not'
if isinstance(block.exitswitch, tuple):
- # special case produced by jitter.optimize_goto_if_not()
+ # special case produced by jtransform.optimize_goto_if_not()
if block.exitswitch[0] != 'int_is_true':
opname = 'goto_if_not_' + block.exitswitch[0]
opargs = block.exitswitch[1:]
@@ -303,6 +309,8 @@
v = ListOfKind(v.kind, lst)
elif isinstance(v, AbstractDescr):
pass
+ elif isinstance(v, IndirectCallTargets):
+ pass
else:
raise NotImplementedError(type(v))
args.append(v)
Modified: pypy/branch/blackhole-improvement/pypy/jit/codewriter/format.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/codewriter/format.py (original)
+++ pypy/branch/blackhole-improvement/pypy/jit/codewriter/format.py Wed May 12 09:18:28 2010
@@ -2,7 +2,7 @@
from pypy.objspace.flow.model import Constant
from pypy.rpython.lltypesystem import lltype
from pypy.jit.codewriter.flatten import SSARepr, Label, TLabel, Register
-from pypy.jit.codewriter.flatten import ListOfKind
+from pypy.jit.codewriter.flatten import ListOfKind, IndirectCallTargets
from pypy.jit.codewriter.jitcode import SwitchDictDescr
from pypy.jit.metainterp.history import AbstractDescr
@@ -28,7 +28,7 @@
return '<SwitchDictDescr %s>' % (
', '.join(['%s:%s' % (key, getlabelname(lbl))
for key, lbl in x._labels]))
- elif isinstance(x, AbstractDescr):
+ elif isinstance(x, (AbstractDescr, IndirectCallTargets)):
return '%r' % (x,)
else:
return '<unknown object: %r>' % (x,)
Modified: pypy/branch/blackhole-improvement/pypy/jit/codewriter/jitcode.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/codewriter/jitcode.py (original)
+++ pypy/branch/blackhole-improvement/pypy/jit/codewriter/jitcode.py Wed May 12 09:18:28 2010
@@ -13,6 +13,7 @@
self.fnaddr = fnaddr
self.calldescr = calldescr
self._called_from = called_from # debugging
+ self._ssarepr = None # debugging
def setup(self, code='', constants_i=[], constants_r=[], constants_f=[],
num_regs_i=256, num_regs_r=256, num_regs_f=256,
@@ -92,11 +93,21 @@
return ' '.join(lst)
def _missing_liveness(self, pc):
- raise KeyError("missing liveness[%d]" % (pc,))
+ raise MissingLiveness("missing liveness[%d]\n%s" % (pc, self.dump()))
+
+ def dump(self):
+ if self._ssarepr is None:
+ return '<no dump available>'
+ else:
+ from pypy.jit.codewriter.format import format_assembler
+ return format_assembler(self._ssarepr)
def __repr__(self):
return '<JitCode %r>' % self.name
+class MissingLiveness(Exception):
+ pass
+
class SwitchDictDescr(AbstractDescr):
"Get a 'dict' attribute mapping integer values to bytecode positions."
Modified: pypy/branch/blackhole-improvement/pypy/jit/codewriter/jtransform.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/codewriter/jtransform.py (original)
+++ pypy/branch/blackhole-improvement/pypy/jit/codewriter/jtransform.py Wed May 12 09:18:28 2010
@@ -3,9 +3,8 @@
from pypy.jit.metainterp.history import getkind
from pypy.objspace.flow.model import SpaceOperation, Variable, Constant
from pypy.objspace.flow.model import Block, Link, c_last_exception
-from pypy.jit.codewriter.flatten import ListOfKind
+from pypy.jit.codewriter.flatten import ListOfKind, IndirectCallTargets
from pypy.jit.codewriter import support, heaptracker
-from pypy.translator.simplify import get_funcobj
from pypy.rlib import objectmodel
from pypy.rlib.jit import _we_are_jitted
@@ -217,14 +216,14 @@
args_f = []
for v in op.args[1:]:
self.add_in_correct_list(v, args_i, args_r, args_f)
- if args_f: kinds = 'irf'
+ reskind = getkind(op.result.concretetype)[0]
+ if args_f or reskind == 'f': kinds = 'irf'
elif args_i: kinds = 'ir'
else: kinds = 'r'
sublists = []
if 'i' in kinds: sublists.append(ListOfKind('int', args_i))
if 'r' in kinds: sublists.append(ListOfKind('ref', args_r))
if 'f' in kinds: sublists.append(ListOfKind('float', args_f))
- reskind = getkind(op.result.concretetype)[0]
return SpaceOperation('%s_%s_%s' % (namebase, kinds, reskind),
initialargs + sublists, op.result)
@@ -237,35 +236,16 @@
else: raise AssertionError(kind)
lst.append(v)
- def handle_residual_call(self, op):
+ def handle_residual_call(self, op, extraargs=[]):
"""A direct_call turns into the operation 'residual_call_xxx' if it
is calling a function that we don't want to JIT. The initial args
- of 'residual_call_xxx' are the constant function to call, and its
- calldescr."""
- calldescr, canraise = self.callcontrol.getcalldescr(op)
- #
- pure = False
- loopinvariant = False
- if op.opname == "direct_call":
- func = getattr(get_funcobj(op.args[0].value), '_callable', None)
- pure = getattr(func, "_pure_function_", False)
- loopinvariant = getattr(func, "_jit_loop_invariant_", False)
- if pure or loopinvariant:
- effectinfo = calldescr.get_extra_info()
- assert (effectinfo is not None and
- not effectinfo.forces_virtual_or_virtualizable)
- if loopinvariant:
- name = 'G_residual_call_loopinvariant'
- assert not non_void_args, ("arguments not supported for "
- "loop-invariant function!")
- elif pure:
- # XXX check what to do about exceptions (also MemoryError?)
- name = 'residual_call_pure'
- elif canraise:
+ of 'residual_call_xxx' are the function to call, and its calldescr."""
+ calldescr = self.callcontrol.getcalldescr(op)
+ if self.callcontrol.calldescr_canraise(calldescr):
name = 'G_residual_call'
else:
name = 'residual_call'
- return self.rewrite_call(op, name, [op.args[0], calldescr])
+ return self.rewrite_call(op, name, [op.args[0], calldescr] + extraargs)
def handle_regular_call(self, op):
"""A direct_call turns into the operation 'inline_call_xxx' if it
@@ -276,6 +256,17 @@
called_from=self.graph)
return self.rewrite_call(op, 'G_inline_call', [jitcode])
+ handle_residual_indirect_call = handle_residual_call
+
+ def handle_regular_indirect_call(self, op):
+ """An indirect call where at least one target has a JitCode."""
+ lst = []
+ for targetgraph in self.callcontrol.graphs_from(op):
+ jitcode = self.callcontrol.get_jitcode(targetgraph,
+ called_from=self.graph)
+ lst.append(jitcode)
+ return self.handle_residual_call(op, [IndirectCallTargets(lst)])
+
def _do_builtin_call(self, op, oopspec_name=None, args=None, extra=None):
if oopspec_name is None: oopspec_name = op.opname
if args is None: args = op.args
Modified: pypy/branch/blackhole-improvement/pypy/jit/codewriter/liveness.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/codewriter/liveness.py (original)
+++ pypy/branch/blackhole-improvement/pypy/jit/codewriter/liveness.py Wed May 12 09:18:28 2010
@@ -2,7 +2,7 @@
# Some instruction require liveness information (the ones that can end up
-# in generate_guard() in pyjitpl.py); jitter.py prefixes these opnames
+# in generate_guard() in pyjitpl.py); jtransform.py prefixes these opnames
# with a 'G_'. Additionally, boolean and general switches in the flow graph
# will turn in 'goto_if_not_*' operations, which also require liveness info.
Modified: pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_assembler.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_assembler.py (original)
+++ pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_assembler.py Wed May 12 09:18:28 2010
@@ -1,7 +1,8 @@
import py, struct
from pypy.jit.codewriter.assembler import Assembler
from pypy.jit.codewriter.flatten import SSARepr, Label, TLabel, Register
-from pypy.jit.codewriter.flatten import ListOfKind
+from pypy.jit.codewriter.flatten import ListOfKind, IndirectCallTargets
+from pypy.jit.codewriter.jitcode import MissingLiveness
from pypy.jit.metainterp.history import AbstractDescr
from pypy.objspace.flow.model import Constant
from pypy.rpython.lltypesystem import lltype, llmemory
@@ -138,6 +139,16 @@
assert assembler.insns == {'foobar/d': 0}
assert assembler.descrs == descrs[::-1]
+def test_assemble_indirect_call():
+ lst1 = ["somejitcode1", "somejitcode2"]
+ lst2 = ["somejitcode1", "somejitcode3"]
+ ssarepr = SSARepr("test")
+ ssarepr.insns = [('foobar', IndirectCallTargets(lst1)),
+ ('foobar', IndirectCallTargets(lst2))]
+ assembler = Assembler()
+ assembler.assemble(ssarepr)
+ assert assembler.indirectcalltargets == set(lst1).union(lst2)
+
def test_num_regs():
assembler = Assembler()
ssarepr = SSARepr("test")
@@ -183,10 +194,10 @@
assert assembler.insns == {'int_add/ici': 0,
'int_mul/iii': 1,
'int_return/i': 2}
- py.test.raises(KeyError, jitcode._live_vars, 0)
- py.test.raises(KeyError, jitcode._live_vars, 3)
- py.test.raises(KeyError, jitcode._live_vars, 5)
- py.test.raises(KeyError, jitcode._live_vars, 24)
+ py.test.raises(MissingLiveness, jitcode._live_vars, 0)
+ py.test.raises(MissingLiveness, jitcode._live_vars, 3)
+ py.test.raises(MissingLiveness, jitcode._live_vars, 5)
+ py.test.raises(MissingLiveness, jitcode._live_vars, 24)
assert jitcode._live_vars(4) == '%i0'
assert jitcode._live_vars(8) == '%i0 %i1'
assert jitcode._live_vars(12) == '%i0'
Modified: pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_codewriter.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_codewriter.py (original)
+++ pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_codewriter.py Wed May 12 09:18:28 2010
@@ -44,9 +44,11 @@
assert jitcode.num_regs_r() == 0
assert jitcode.num_regs_f() == 0
assert jitcode._live_vars(5) == '%i0 %i1'
+ #
+ from pypy.jit.codewriter.jitcode import MissingLiveness
for i in range(len(jitcode.code)+1):
if i != 5:
- py.test.raises(KeyError, jitcode._live_vars, i)
+ py.test.raises(MissingLiveness, jitcode._live_vars, i)
def test_call():
def ggg(x):
Copied: pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_effectinfo.py (from r74456, pypy/branch/blackhole-improvement/pypy/jit/metainterp/test/test_effectinfo.py)
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/metainterp/test/test_effectinfo.py (original)
+++ pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_effectinfo.py Wed May 12 09:18:28 2010
@@ -1,7 +1,7 @@
from pypy.rpython.lltypesystem.rclass import OBJECT
from pypy.rpython.lltypesystem import lltype
from pypy.rpython.ootypesystem import ootype
-from pypy.jit.metainterp.effectinfo import effectinfo_from_writeanalyze
+from pypy.jit.codewriter.effectinfo import effectinfo_from_writeanalyze
class FakeCPU:
def fielddescrof(self, T, fieldname):
Modified: pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_flatten.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_flatten.py (original)
+++ pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_flatten.py Wed May 12 09:18:28 2010
@@ -45,14 +45,18 @@
return FakeDescr()
class FakeCallControl:
+ _descr_cannot_raise = FakeDescr()
def guess_call_kind(self, op):
return 'residual'
def getcalldescr(self, op):
try:
- can_raise = 'cannot_raise' not in op.args[0].value._obj.graph.name
+ if 'cannot_raise' in op.args[0].value._obj.graph.name:
+ return self._descr_cannot_raise
except AttributeError:
- can_raise = True
- return FakeDescr(), can_raise
+ pass
+ return FakeDescr()
+ def calldescr_canraise(self, calldescr):
+ return calldescr is not self._descr_cannot_raise
def fake_regallocs():
return {'int': FakeRegAlloc(),
Modified: pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_jtransform.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_jtransform.py (original)
+++ pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_jtransform.py Wed May 12 09:18:28 2010
@@ -31,7 +31,9 @@
def guess_call_kind(self, op):
return 'residual'
def getcalldescr(self, op):
- return 'calldescr', True
+ return 'calldescr'
+ def calldescr_canraise(self, calldescr):
+ return True
class FakeRegularCallControl:
def guess_call_kind(self, op):
@@ -42,6 +44,19 @@
assert graph == 'somegraph'
return 'somejitcode'
+class FakeIndirectCallControl:
+ def guess_call_kind(self, op):
+ return 'regular'
+ def graphs_from(self, op):
+ return ['somegraph1', 'somegraph2']
+ def getcalldescr(self, op):
+ return 'calldescr'
+ def get_jitcode(self, graph, called_from=None):
+ assert graph in ('somegraph1', 'somegraph2')
+ return 'somejitcode' + graph[-1]
+ def calldescr_canraise(self, calldescr):
+ return True
+
def test_optimize_goto_if_not():
v1 = Variable()
@@ -156,11 +171,13 @@
if with_r: ARGS += [rclass.OBJECTPTR, lltype.Ptr(rstr.STR)]
if with_f: ARGS += [lltype.Float, lltype.Float]
random.shuffle(ARGS)
+ if RESTYPE == lltype.Float: with_f = True
if with_f: expectedkind = 'irf' # all kinds
elif with_i: expectedkind = 'ir' # integers and references
else: expectedkind = 'r' # only references
yield residual_call_test, ARGS, RESTYPE, expectedkind
yield direct_call_test, ARGS, RESTYPE, expectedkind
+ yield indirect_call_test, ARGS, RESTYPE, expectedkind
def get_direct_call_op(argtypes, restype):
FUNC = lltype.FuncType(argtypes, restype)
@@ -207,6 +224,29 @@
kind = getkind(v.concretetype)
assert kind == 'void' or kind[0] in expectedkind
+def indirect_call_test(argtypes, restype, expectedkind):
+ op = get_direct_call_op(argtypes, restype)
+ op.opname = 'indirect_call'
+ op.args[0] = varoftype(op.args[0].concretetype)
+ op.args.append(Constant(['somegraph1', 'somegraph2'], lltype.Void))
+ tr = Transformer(FakeCPU(), FakeIndirectCallControl())
+ tr.graph = 'someinitialgraph'
+ op1 = tr.rewrite_operation(op)
+ reskind = getkind(restype)[0]
+ assert op1.opname == 'G_residual_call_%s_%s' % (expectedkind, reskind)
+ assert op1.result == op.result
+ assert op1.args[0] == op.args[0]
+ assert op1.args[1] == 'calldescr'
+ assert op1.args[2].lst == ['somejitcode1', 'somejitcode2']
+ assert len(op1.args) == 3 + len(expectedkind)
+ for sublist, kind1 in zip(op1.args[3:], expectedkind):
+ assert sublist.kind.startswith(kind1)
+ assert list(sublist) == [v for v in op.args[1:]
+ if getkind(v.concretetype) == sublist.kind]
+ for v in op.args[1:]:
+ kind = getkind(v.concretetype)
+ assert kind == 'void' or kind[0] in expectedkind
+
def test_getfield():
# XXX a more compact encoding would be possible, something along
# the lines of getfield_gc_r %r0, $offset, %r1
Modified: pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_regalloc.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_regalloc.py (original)
+++ pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_regalloc.py Wed May 12 09:18:28 2010
@@ -18,7 +18,7 @@
def check_assembler(self, graph, expected, transform=False):
# 'transform' can be False only for simple graphs. More complex
- # graphs must first be transformed by jitter.py before they can be
+ # graphs must first be transformed by jtransform.py before they can be
# subjected to register allocation and flattening.
if transform:
from pypy.jit.codewriter.jtransform import transform_graph
Modified: pypy/branch/blackhole-improvement/pypy/jit/metainterp/blackhole.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/metainterp/blackhole.py (original)
+++ pypy/branch/blackhole-improvement/pypy/jit/metainterp/blackhole.py Wed May 12 09:18:28 2010
@@ -218,7 +218,7 @@
# Get the bhimpl_xxx method. If we get an AttributeError here,
# it means that either the implementation is missing, or that it
# should not appear here at all but instead be transformed away
- # by codewriter/jitter.py.
+ # by codewriter/jtransform.py.
unboundmethod = getattr(BlackholeInterpreter, 'bhimpl_' + name).im_func
verbose = self.verbose
argtypes = unrolling_iterable(unboundmethod.argtypes)
@@ -726,9 +726,6 @@
@arguments("cpu", "i", "d", "R", returns="r")
def bhimpl_residual_call_r_r(cpu, func, calldescr, args_r):
return cpu.bh_call_r(func, calldescr, None, args_r, None)
- @arguments("cpu", "i", "d", "R", returns="f")
- def bhimpl_residual_call_r_f(cpu, func, calldescr, args_r):
- return cpu.bh_call_f(func, calldescr, None, args_r, None)
@arguments("cpu", "i", "d", "R")
def bhimpl_residual_call_r_v(cpu, func, calldescr, args_r):
cpu.bh_call_v(func, calldescr, None, args_r, None)
@@ -739,9 +736,6 @@
@arguments("cpu", "i", "d", "I", "R", returns="r")
def bhimpl_residual_call_ir_r(cpu, func, calldescr, args_i, args_r):
return cpu.bh_call_r(func, calldescr, args_i, args_r, None)
- @arguments("cpu", "i", "d", "I", "R", returns="f")
- def bhimpl_residual_call_ir_f(cpu, func, calldescr, args_i, args_r):
- return cpu.bh_call_f(func, calldescr, args_i, args_r, None)
@arguments("cpu", "i", "d", "I", "R")
def bhimpl_residual_call_ir_v(cpu, func, calldescr, args_i, args_r):
cpu.bh_call_v(func, calldescr, args_i, args_r, None)
@@ -767,10 +761,6 @@
def bhimpl_inline_call_r_r(cpu, jitcode, args_r):
return cpu.bh_call_r(jitcode.get_fnaddr_as_int(), jitcode.calldescr,
None, args_r, None)
- @arguments("cpu", "j", "R", returns="f")
- def bhimpl_inline_call_r_f(cpu, jitcode, args_r):
- return cpu.bh_call_f(jitcode.get_fnaddr_as_int(), jitcode.calldescr,
- None, args_r, None)
@arguments("cpu", "j", "R")
def bhimpl_inline_call_r_v(cpu, jitcode, args_r):
return cpu.bh_call_v(jitcode.get_fnaddr_as_int(), jitcode.calldescr,
@@ -784,10 +774,6 @@
def bhimpl_inline_call_ir_r(cpu, jitcode, args_i, args_r):
return cpu.bh_call_r(jitcode.get_fnaddr_as_int(), jitcode.calldescr,
args_i, args_r, None)
- @arguments("cpu", "j", "I", "R", returns="f")
- def bhimpl_inline_call_ir_f(cpu, jitcode, args_i, args_r):
- return cpu.bh_call_f(jitcode.get_fnaddr_as_int(), jitcode.calldescr,
- args_i, args_r, None)
@arguments("cpu", "j", "I", "R")
def bhimpl_inline_call_ir_v(cpu, jitcode, args_i, args_r):
return cpu.bh_call_v(jitcode.get_fnaddr_as_int(), jitcode.calldescr,
@@ -880,3 +866,29 @@
@arguments("cpu", "r", returns="i")
def bhimpl_cast_ptr_to_int(cpu, p):
return cpu.bh_cast_ptr_to_int(p)
+
+ @arguments("cpu", "i", returns="r")
+ def bhimpl_newstr(cpu, length):
+ return cpu.bh_newstr(length)
+ @arguments("cpu", "r", returns="i")
+ def bhimpl_strlen(cpu, string):
+ return cpu.bh_strlen(string)
+ @arguments("cpu", "r", "i", returns="i")
+ def bhimpl_strgetitem(cpu, string, index):
+ return cpu.bh_strgetitem(string, index)
+ @arguments("cpu", "r", "i", "i")
+ def bhimpl_strsetitem(cpu, string, index, newchr):
+ cpu.bh_strsetitem(string, index, newchr)
+
+ @arguments("cpu", "i", returns="r")
+ def bhimpl_newunicode(cpu, length):
+ return cpu.bh_newunicode(length)
+ @arguments("cpu", "r", returns="i")
+ def bhimpl_unicodelen(cpu, unicode):
+ return cpu.bh_unicodelen(unicode)
+ @arguments("cpu", "r", "i", returns="i")
+ def bhimpl_unicodegetitem(cpu, unicode, index):
+ return cpu.bh_unicodegetitem(unicode, index)
+ @arguments("cpu", "r", "i", "i")
+ def bhimpl_unicodesetitem(cpu, unicode, index, newchr):
+ cpu.bh_unicodesetitem(unicode, index, newchr)
Modified: pypy/branch/blackhole-improvement/pypy/jit/metainterp/history.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/metainterp/history.py (original)
+++ pypy/branch/blackhole-improvement/pypy/jit/metainterp/history.py Wed May 12 09:18:28 2010
@@ -360,7 +360,11 @@
def _get_str(self): # for debugging only
from pypy.rpython.annlowlevel import hlstr
from pypy.rpython.lltypesystem import rstr
- return hlstr(lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), self.value))
+ try:
+ return hlstr(lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR),
+ self.value))
+ except lltype.UninitializedMemoryAccess:
+ return '<uninitialized string>'
class ConstObj(Const):
type = REF
Modified: pypy/branch/blackhole-improvement/pypy/jit/metainterp/pyjitpl.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/metainterp/pyjitpl.py (original)
+++ pypy/branch/blackhole-improvement/pypy/jit/metainterp/pyjitpl.py Wed May 12 09:18:28 2010
@@ -22,6 +22,7 @@
from pypy.rlib.jit import DEBUG_OFF, DEBUG_PROFILE, DEBUG_STEPS, DEBUG_DETAILED
from pypy.jit.metainterp.compile import GiveUp
from pypy.jit.codewriter.jitcode import JitCode, SwitchDictDescr
+from pypy.jit.codewriter import effectinfo as ef
# ____________________________________________________________
@@ -167,10 +168,10 @@
for _opimpl in ['int_add_ovf', 'int_sub_ovf', 'int_mul_ovf']:
exec py.code.Source('''
- @arguments("orgpc", "box", "box")
- def opimpl_%s(self, pc, b1, b2):
+ @arguments("box", "box")
+ def opimpl_%s(self, b1, b2):
resbox = self.execute(rop.%s, b1, b2)
- self.metainterp.handle_possible_overflow_error(pc)
+ self.metainterp.handle_possible_overflow_error()
return resbox
''' % (_opimpl, _opimpl.upper())).compile()
@@ -289,9 +290,9 @@
self.load_int() # past the 'box' argument
self.ignore_varargs() # past the 'livelist' argument
- @arguments("orgpc", "box", "descr")
- def opimpl_switch(self, pc, valuebox, switchdict):
- box = self.implement_guard_value(pc, valuebox)
+ @arguments("box", "descr")
+ def opimpl_switch(self, valuebox, switchdict):
+ box = self.implement_guard_value(valuebox)
switchvalue = box.getint()
assert isinstance(switchdict, SwitchDictDescr)
try:
@@ -632,11 +633,9 @@
opimpl_inline_call_r_i = _opimpl_inline_call1
opimpl_inline_call_r_r = _opimpl_inline_call1
- opimpl_inline_call_r_f = _opimpl_inline_call1
opimpl_inline_call_r_v = _opimpl_inline_call1
opimpl_inline_call_ir_i = _opimpl_inline_call2
opimpl_inline_call_ir_r = _opimpl_inline_call2
- opimpl_inline_call_ir_f = _opimpl_inline_call2
opimpl_inline_call_ir_v = _opimpl_inline_call2
opimpl_inline_call_irf_i = _opimpl_inline_call3
opimpl_inline_call_irf_r = _opimpl_inline_call3
@@ -645,21 +644,19 @@
@arguments("box", "descr", "boxes")
def _opimpl_residual_call1(self, funcbox, calldescr, argboxes):
- return self.do_residual_call(funcbox, calldescr, argboxes, exc=True)
+ return self.do_residual_or_indirect_call(funcbox, calldescr, argboxes)
@arguments("box", "descr", "boxes2")
def _opimpl_residual_call2(self, funcbox, calldescr, argboxes):
- return self.do_residual_call(funcbox, calldescr, argboxes, exc=True)
+ return self.do_residual_or_indirect_call(funcbox, calldescr, argboxes)
@arguments("box", "descr", "boxes3")
def _opimpl_residual_call3(self, funcbox, calldescr, argboxes):
- return self.do_residual_call(funcbox, calldescr, argboxes, exc=True)
+ return self.do_residual_or_indirect_call(funcbox, calldescr, argboxes)
opimpl_residual_call_r_i = _opimpl_residual_call1
opimpl_residual_call_r_r = _opimpl_residual_call1
- opimpl_residual_call_r_f = _opimpl_residual_call1
opimpl_residual_call_r_v = _opimpl_residual_call1
opimpl_residual_call_ir_i = _opimpl_residual_call2
opimpl_residual_call_ir_r = _opimpl_residual_call2
- opimpl_residual_call_ir_f = _opimpl_residual_call2
opimpl_residual_call_ir_v = _opimpl_residual_call2
opimpl_residual_call_irf_i = _opimpl_residual_call3
opimpl_residual_call_irf_r = _opimpl_residual_call3
@@ -705,28 +702,6 @@
call_position)
return res
- @XXX #arguments("descr", "varargs")
- def opimpl_residual_call_noexception(self, calldescr, varargs):
- self.do_residual_call(varargs, descr=calldescr, exc=False)
-
- @XXX #arguments("descr", "varargs")
- def opimpl_residual_call_pure(self, calldescr, varargs):
- self.execute_varargs(rop.CALL_PURE, varargs, descr=calldescr, exc=False)
-
- @XXX #arguments("orgpc", "descr", "box", "varargs")
- def opimpl_indirect_call(self, pc, calldescr, box, varargs):
- box = self.implement_guard_value(pc, box)
- cpu = self.metainterp.cpu
- key = cpu.ts.getaddr_for_box(cpu, box)
- jitcode = self.metainterp.staticdata.bytecode_for_address(key)
- if jitcode is not None:
- # we should follow calls to this graph
- return self.perform_call(jitcode, varargs)
- else:
- # but we should not follow calls to that graph
- return self.do_residual_call([box] + varargs,
- descr=calldescr, exc=True)
-
@XXX #arguments("orgpc", "methdescr", "varargs")
def opimpl_oosend(self, pc, methdescr, varargs):
objbox = varargs[0]
@@ -743,37 +718,37 @@
return self.execute_varargs(rop.OOSEND, varargs,
descr=methdescr, exc=True)
- @XXX #arguments("box")
- def opimpl_strlen(self, str):
- self.execute(rop.STRLEN, str)
-
- @XXX #arguments("box")
- def opimpl_unicodelen(self, str):
- self.execute(rop.UNICODELEN, str)
-
- @XXX #arguments("box", "box")
- def opimpl_strgetitem(self, str, index):
- self.execute(rop.STRGETITEM, str, index)
+ @arguments("box")
+ def opimpl_strlen(self, strbox):
+ return self.execute(rop.STRLEN, strbox)
- @XXX #arguments("box", "box")
- def opimpl_unicodegetitem(self, str, index):
- self.execute(rop.UNICODEGETITEM, str, index)
+ @arguments("box")
+ def opimpl_unicodelen(self, unicodebox):
+ return self.execute(rop.UNICODELEN, unicodebox)
- @XXX #arguments("box", "box", "box")
- def opimpl_strsetitem(self, str, index, newchar):
- self.execute(rop.STRSETITEM, str, index, newchar)
-
- @XXX #arguments("box", "box", "box")
- def opimpl_unicodesetitem(self, str, index, newchar):
- self.execute(rop.UNICODESETITEM, str, index, newchar)
+ @arguments("box", "box")
+ def opimpl_strgetitem(self, strbox, indexbox):
+ return self.execute(rop.STRGETITEM, strbox, indexbox)
+
+ @arguments("box", "box")
+ def opimpl_unicodegetitem(self, unicodebox, indexbox):
+ return self.execute(rop.UNICODEGETITEM, unicodebox, indexbox)
+
+ @arguments("box", "box", "box")
+ def opimpl_strsetitem(self, strbox, indexbox, newcharbox):
+ return self.execute(rop.STRSETITEM, strbox, indexbox, newcharbox)
+
+ @arguments("box", "box", "box")
+ def opimpl_unicodesetitem(self, unicodebox, indexbox, newcharbox):
+ self.execute(rop.UNICODESETITEM, unicodebox, indexbox, newcharbox)
- @XXX #arguments("box")
- def opimpl_newstr(self, length):
- self.execute(rop.NEWSTR, length)
+ @arguments("box")
+ def opimpl_newstr(self, lengthbox):
+ return self.execute(rop.NEWSTR, lengthbox)
- @XXX #arguments("box")
- def opimpl_newunicode(self, length):
- self.execute(rop.NEWUNICODE, length)
+ @arguments("box")
+ def opimpl_newunicode(self, lengthbox):
+ return self.execute(rop.NEWUNICODE, lengthbox)
@XXX #arguments("descr", "varargs")
def opimpl_residual_oosend_canraise(self, methdescr, varargs):
@@ -787,9 +762,9 @@
def opimpl_residual_oosend_pure(self, methdescr, boxes):
self.execute_varargs(rop.OOSEND_PURE, boxes, descr=methdescr, exc=False)
- @arguments("orgpc", "box")
- def opimpl_int_guard_value(self, pc, box):
- return self.implement_guard_value(pc, box)
+ @arguments("box")
+ def opimpl_int_guard_value(self, box):
+ return self.implement_guard_value(box)
@XXX #arguments("orgpc", "int")
def opimpl_guard_green(self, pc, boxindex):
@@ -802,10 +777,10 @@
constbox = self.implement_guard_value(pc, box)
self.env[boxindex] = constbox
- @arguments("orgpc", "box")
- def opimpl_guard_class(self, pc, box):
+ @arguments("box")
+ def opimpl_guard_class(self, box):
clsbox = self.cls_of_box(box)
- self.generate_guard(pc, rop.GUARD_CLASS, box, [clsbox])
+ self.generate_guard(rop.GUARD_CLASS, box, [clsbox])
return clsbox
## @XXX #arguments("orgpc", "box", "builtin")
@@ -1029,7 +1004,7 @@
metainterp.attach_debug_info(guard_op)
return guard_op
- def implement_guard_value(self, pc, box):
+ def implement_guard_value(self, box):
"""Promote the given Box into a Const. Note: be careful, it's a
bit unclear what occurs if a single opcode needs to generate
several ones and/or ones not near the beginning."""
@@ -1037,7 +1012,7 @@
return box # no promotion needed, already a Const
else:
promoted_box = box.constbox()
- self.generate_guard(pc, rop.GUARD_VALUE, box, [promoted_box])
+ self.generate_guard(rop.GUARD_VALUE, box, [promoted_box])
self.metainterp.replace_box(box, promoted_box)
return promoted_box
@@ -1057,15 +1032,16 @@
resbox = self.metainterp.execute_and_record_varargs(opnum, argboxes,
descr=descr)
if exc:
- self.metainterp.handle_possible_exception(self.pc)
+ self.metainterp.handle_possible_exception()
else:
self.metainterp.assert_no_exception()
return resbox
- def do_residual_call(self, funcbox, descr, argboxes, exc):
+ def do_residual_call(self, funcbox, descr, argboxes):
allboxes = [funcbox] + argboxes
effectinfo = descr.get_extra_info()
- if 0:# XXX effectinfo is None or effectinfo.forces_virtual_or_virtualizable:
+ if (effectinfo is None or
+ effectinfo.extraeffect == ef.EF_FORCES_VIRTUAL_OR_VIRTUALIZABLE):
# residual calls require attention to keep virtualizables in-sync
self.metainterp.vable_and_vrefs_before_residual_call()
# xxx do something about code duplication
@@ -1080,7 +1056,31 @@
else:
return self.metainterp.assert_no_exception()
else:
- return self.execute_varargs(rop.CALL, allboxes, descr, exc)
+ effect = effectinfo.extraeffect
+ if effect == ef.EF_CANNOT_RAISE:
+ opnum, exc = rop.CALL, False
+ elif effect == ef.EF_PURE:
+ opnum, exc = rop.CALL_PURE, False
+ elif effect == ef.EF_LOOPINVARIANT:
+ opnum, exc = rop.CALL_LOOPINVARIANT, True
+ else:
+ opnum, exc = rop.CALL, True
+ return self.execute_varargs(opnum, allboxes, descr, exc)
+
+ def do_residual_or_indirect_call(self, funcbox, calldescr, argboxes):
+ """The 'residual_call' operation is emitted in two cases:
+ when we have to generate a residual CALL operation, but also
+ to handle an indirect_call that may need to be inlined."""
+ funcbox = self.implement_guard_value(funcbox)
+ sd = self.metainterp.staticdata
+ key = sd.cpu.ts.getaddr_for_box(funcbox)
+ jitcode = sd.bytecode_for_address(key)
+ if jitcode is not None:
+ # we should follow calls to this graph
+ return self.metainterp.perform_call(jitcode, argboxes)
+ else:
+ # but we should not follow calls to that graph
+ return self.do_residual_call(funcbox, calldescr, argboxes)
# ____________________________________________________________
@@ -1100,14 +1100,12 @@
RESULT = codewriter.portal_graph.getreturnvar().concretetype
self.result_type = history.getkind(RESULT)
- self.setup_insns(codewriter.assembler.insns)
- self.setup_descrs(codewriter.assembler.descrs)
+ asm = codewriter.assembler
+ self.setup_insns(asm.insns)
+ self.setup_descrs(asm.descrs)
+ self.setup_indirectcalltargets(asm.indirectcalltargets)
self.profiler = ProfilerClass()
-
- self.indirectcall_keys = []
- self.indirectcall_values = []
-
self.warmrunnerdesc = warmrunnerdesc
backendmodule = self.cpu.__module__
@@ -1140,6 +1138,9 @@
def setup_descrs(self, descrs):
self.opcode_descrs = descrs
+ def setup_indirectcalltargets(self, indirectcalltargets):
+ self.indirectcalltargets = list(indirectcalltargets)
+
def finish_setup(self, optimizer=None):
warmrunnerdesc = self.warmrunnerdesc
if warmrunnerdesc is not None:
@@ -1192,24 +1193,16 @@
# because the keys are function addresses, so they
# can change from run to run.
d = {}
- keys = self.indirectcall_keys
- values = self.indirectcall_values
- for i in range(len(keys)):
- d[keys[i]] = values[i]
+ for jitcode in self.indirectcalltargets:
+ d[jitcode.fnaddr] = jitcode
self.globaldata.indirectcall_dict = d
return d.get(fnaddress, None)
else:
- for i in range(len(self.indirectcall_keys)):
- if fnaddress == self.indirectcall_keys[i]:
- return self.indirectcall_values[i]
+ for jitcode in self.indirectcalltargets:
+ if jitcode.fnaddr == fnaddress:
+ return jitcode
return None
- # ---------- construction-time interface ----------
-
- def _register_indirect_call_target(self, fnaddress, jitcode):
- self.indirectcall_keys.append(fnaddress)
- self.indirectcall_values.append(jitcode)
-
# ---------------- logging ------------------------
def log(self, msg):
@@ -1273,7 +1266,7 @@
return False # XXX get rid of this method
def perform_call(self, jitcode, boxes, greenkey=None):
- # when tracing, this bytecode causes the subfunction to be entered
+ # causes the metainterp to enter the given subfunction
f = self.newframe(jitcode, greenkey)
f.setup_call(boxes)
raise ChangeFrame
@@ -1865,26 +1858,26 @@
# mark by replacing it with ConstPtr(NULL)
self.virtualref_boxes[i+1] = self.cpu.ts.CONST_NULL
- def handle_possible_exception(self, pc):
+ def handle_possible_exception(self):
frame = self.framestack[-1]
if self.last_exc_value_box:
exception_box = self.cpu.ts.cls_of_box(self.last_exc_value_box)
- op = frame.generate_guard(pc, rop.GUARD_EXCEPTION,
+ op = frame.generate_guard(rop.GUARD_EXCEPTION,
None, [exception_box])
if op:
op.result = self.last_exc_value_box
self.finishframe_exception()
else:
- frame.generate_guard(pc, rop.GUARD_NO_EXCEPTION, None, [])
+ frame.generate_guard(rop.GUARD_NO_EXCEPTION, None, [])
- def handle_possible_overflow_error(self, pc):
+ def handle_possible_overflow_error(self):
frame = self.framestack[-1]
if self.last_exc_value_box:
- frame.generate_guard(pc, rop.GUARD_OVERFLOW, None)
+ frame.generate_guard(rop.GUARD_OVERFLOW, None)
assert isinstance(self.last_exc_value_box, Const)
self.finishframe_exception()
else:
- frame.generate_guard(pc, rop.GUARD_NO_OVERFLOW, None)
+ frame.generate_guard(rop.GUARD_NO_OVERFLOW, None)
def assert_no_exception(self):
assert not self.last_exc_value_box
@@ -2066,7 +2059,6 @@
args = ()
next_argcode = 0
code = self.bytecode
- orgpc = position
position += 1
for argtype in argtypes:
if argtype == "box": # a box, of whatever type
@@ -2129,8 +2121,6 @@
argcodes[next_argcode + 2])
next_argcode = next_argcode + 3
position = position3 + 1 + length3
- elif argtype == "orgpc":
- value = orgpc
else:
raise AssertionError("bad argtype: %r" % (argtype,))
args += (value,)
Modified: pypy/branch/blackhole-improvement/pypy/jit/metainterp/typesystem.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/metainterp/typesystem.py (original)
+++ pypy/branch/blackhole-improvement/pypy/jit/metainterp/typesystem.py Wed May 12 09:18:28 2010
@@ -128,8 +128,8 @@
return lltype.cast_opaque_ptr(llmemory.GCREF, value)
cast_to_ref._annspecialcase_ = 'specialize:ll'
- def getaddr_for_box(self, cpu, box):
- return box.getaddr(cpu)
+ def getaddr_for_box(self, box):
+ return box.getaddr()
def rd_eq(ref1, ref2):
return ref1 == ref2
@@ -230,7 +230,7 @@
return ootype.cast_to_object(value)
cast_to_ref._annspecialcase_ = 'specialize:ll'
- def getaddr_for_box(self, cpu, box):
+ def getaddr_for_box(self, box):
return box.getref_base()
llhelper = LLTypeHelper()
More information about the Pypy-commit
mailing list