[pypy-svn] r64691 - in pypy/branch/pyjitpl5/pypy/jit: backend backend/llgraph backend/test metainterp metainterp/test
arigo at codespeak.net
arigo at codespeak.net
Sun Apr 26 16:35:55 CEST 2009
Author: arigo
Date: Sun Apr 26 16:35:53 2009
New Revision: 64691
Modified:
pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py
pypy/branch/pyjitpl5/pypy/jit/backend/model.py
pypy/branch/pyjitpl5/pypy/jit/backend/test/runner.py
pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py
pypy/branch/pyjitpl5/pypy/jit/metainterp/compile.py
pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py
pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py
pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py
pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py
Log:
Replace _save_recursive_call() with an interface change. The idea is
that the backend should not patch the real boxes in-place, but only
expose the result via an interface, get_latest_value_xxx(). The
front-end will then copy the values into the boxes in a try:finally:,
and restore their value afterwards. It's expected to be much safer than
the previous hack.
Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py (original)
+++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py Sun Apr 26 16:35:53 2009
@@ -176,28 +176,20 @@
raise Exception("bad box in valueboxes: %r" % (box,))
# run the loop
fail_index = llimpl.frame_execute(frame)
- # we hit a FAIL operation. Fish for the values
- # (in a real backend, this should be done by the FAIL operation
- # itself, not here)
- op = self.fail_ops[fail_index]
- for i in range(len(op.args)):
- box = op.args[i]
- if isinstance(box, history.BoxInt):
- value = llimpl.frame_int_getvalue(frame, i)
- box.changevalue_int(value)
- elif isinstance(box, history.BoxPtr):
- value = llimpl.frame_ptr_getvalue(frame, i)
- box.changevalue_ptr(value)
- elif self.is_oo and isinstance(box, history.BoxObj):
- value = llimpl.frame_ptr_getvalue(frame, i)
- box.changevalue_obj(value)
- elif isinstance(box, history.ConstInt):
- pass
- elif isinstance(box, history.ConstPtr):
- pass
- else:
- raise Exception("bad box in 'fail': %r" % (box,))
- return op
+ # we hit a FAIL operation.
+ self.latest_frame = frame
+ return self.fail_ops[fail_index]
+
+ def get_latest_value_int(self, index):
+ return llimpl.frame_int_getvalue(self.latest_frame, index)
+
+ def get_latest_value_ptr(self, index):
+ return llimpl.frame_ptr_getvalue(self.latest_frame, index)
+
+ def get_latest_value_obj(self, index):
+ return llimpl.frame_ptr_getvalue(self.latest_frame, index)
+
+ # ----------
def get_exception(self):
return self.cast_adr_to_int(llimpl.get_exception())
Modified: pypy/branch/pyjitpl5/pypy/jit/backend/model.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/backend/model.py (original)
+++ pypy/branch/pyjitpl5/pypy/jit/backend/model.py Sun Apr 26 16:35:53 2009
@@ -9,7 +9,22 @@
Returns the ResOperation that failed, of type rop.FAIL.
"""
raise NotImplementedError
-
+
+ def get_latest_value_int(self, index):
+ """Returns the value for the index'th argument to the
+ lastest rop.FAIL. Returns an int."""
+ raise NotImplementedError
+
+ def get_latest_value_ptr(self, index):
+ """Returns the value for the index'th argument to the
+ lastest rop.FAIL. Returns a ptr."""
+ raise NotImplementedError
+
+ def get_latest_value_obj(self, index):
+ """Returns the value for the index'th argument to the
+ lastest rop.FAIL. Returns an obj."""
+ raise NotImplementedError
+
def get_exception(self):
raise NotImplementedError
Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/runner.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/backend/test/runner.py (original)
+++ pypy/branch/pyjitpl5/pypy/jit/backend/test/runner.py Sun Apr 26 16:35:53 2009
@@ -29,8 +29,10 @@
self.guard_failed = False
else:
self.guard_failed = True
- if result_type != 'void':
- return res.args[0]
+ if result_type == 'int':
+ return BoxInt(self.cpu.get_latest_value_int(0))
+ elif result_type == 'ptr':
+ return BoxPtr(self.cpu.get_latest_value_ptr(0))
def get_compiled_single_operation(self, opnum, result_type, valueboxes,
descr):
Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py (original)
+++ pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py Sun Apr 26 16:35:53 2009
@@ -44,31 +44,32 @@
class IndirectCallset(history.AbstractValue):
def __init__(self, codewriter, graphs):
- keys = []
- values = []
+ self.keys = []
+ self.values = []
for graph in graphs:
fnptr = codewriter.rtyper.getcallable(graph)
fnaddress = codewriter.ts.cast_fnptr_to_root(fnptr)
- keys.append(fnaddress)
- values.append(codewriter.get_jitcode(graph))
+ self.keys.append(fnaddress)
+ self.values.append(codewriter.get_jitcode(graph))
+ self.dict = None
- def bytecode_for_address(fnaddress):
- if we_are_translated():
- if self.dict is None:
- # Build the dictionary at run-time. This is needed
- # because the keys are function addresses, so they
- # can change from run to run.
- self.dict = {}
- for i in range(len(keys)):
- self.dict[keys[i]] = values[i]
- return self.dict[fnaddress]
- else:
+ def bytecode_for_address(self, fnaddress):
+ if we_are_translated():
+ if self.dict is None:
+ # Build the dictionary at run-time. This is needed
+ # because the keys are function addresses, so they
+ # can change from run to run.
+ self.dict = {}
+ keys = self.keys
+ values = self.values
for i in range(len(keys)):
- if fnaddress == keys[i]:
- return values[i]
- raise KeyError(fnaddress)
- self.bytecode_for_address = bytecode_for_address
- self.dict = None
+ self.dict[keys[i]] = values[i]
+ return self.dict[fnaddress]
+ else:
+ for i in range(len(self.keys)):
+ if fnaddress == self.keys[i]:
+ return self.values[i]
+ raise KeyError(fnaddress)
class SwitchDict(history.AbstractValue):
"Get a 'dict' attribute mapping integer values to bytecode positions."
Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/compile.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/metainterp/compile.py (original)
+++ pypy/branch/pyjitpl5/pypy/jit/metainterp/compile.py Sun Apr 26 16:35:53 2009
@@ -6,7 +6,8 @@
from pypy.jit.metainterp.resoperation import ResOperation, rop
from pypy.jit.metainterp.history import TreeLoop, log, Box, History
-from pypy.jit.metainterp.history import AbstractDescr, BoxInt, BoxPtr
+from pypy.jit.metainterp.history import AbstractDescr, BoxInt, BoxPtr, BoxObj
+from pypy.jit.metainterp import history
from pypy.jit.metainterp.specnode import NotSpecNode
from pypy.rlib.debug import debug_print
@@ -58,7 +59,7 @@
else:
if target_loop is not None:
show_loop(metainterp, target_loop)
- if target_loop is not None and target_loop not in map_loop2descr:
+ if target_loop is not None and type(target_loop) is not TerminatingLoop:
target_loop.check_consistency()
return target_loop
@@ -71,7 +72,7 @@
errmsg += ': ' + str(error)
else:
errmsg = None
- if loop is None or loop in map_loop2descr:
+ if loop is None or type(loop) is TerminatingLoop:
extraloops = []
else:
extraloops = [loop]
@@ -122,50 +123,94 @@
# ____________________________________________________________
-class DoneWithThisFrameDescr0(AbstractDescr):
+class DoneWithThisFrameDescrVoid(AbstractDescr):
def handle_fail_op(self, metainterp_sd, fail_op):
- raise metainterp_sd.DoneWithThisFrame(None)
+ assert metainterp_sd.result_type == history.VOID
+ raise metainterp_sd.DoneWithThisFrameVoid()
-class DoneWithThisFrameDescr1(AbstractDescr):
+class DoneWithThisFrameDescrInt(AbstractDescr):
def handle_fail_op(self, metainterp_sd, fail_op):
+ assert metainterp_sd.result_type == history.INT
resultbox = fail_op.args[0]
- raise metainterp_sd.DoneWithThisFrame(resultbox)
+ if isinstance(resultbox, BoxInt):
+ result = metainterp_sd.cpu.get_latest_value_int(0)
+ else:
+ assert isinstance(resultbox, history.Const)
+ result = resultbox.getint()
+ raise metainterp_sd.DoneWithThisFrameInt(result)
+
+class DoneWithThisFrameDescrPtr(AbstractDescr):
+ def handle_fail_op(self, metainterp_sd, fail_op):
+ assert metainterp_sd.result_type == history.PTR
+ resultbox = fail_op.args[0]
+ if isinstance(resultbox, BoxPtr):
+ result = metainterp_sd.cpu.get_latest_value_ptr(0)
+ else:
+ assert isinstance(resultbox, history.Const)
+ result = resultbox.getptr_base()
+ raise metainterp_sd.DoneWithThisFramePtr(result)
+
+class DoneWithThisFrameDescrObj(AbstractDescr):
+ def handle_fail_op(self, metainterp_sd, fail_op):
+ assert metainterp_sd.result_type == history.OBJ
+ resultbox = fail_op.args[0]
+ if isinstance(resultbox, BoxObj):
+ result = metainterp_sd.cpu.get_latest_value_obj(0)
+ else:
+ assert isinstance(resultbox, history.Const)
+ result = resultbox.getobj()
+ raise metainterp_sd.DoneWithThisFrameObj(result)
class ExitFrameWithExceptionDescr(AbstractDescr):
def handle_fail_op(self, metainterp_sd, fail_op):
assert len(fail_op.args) == 1
valuebox = fail_op.args[0]
- raise metainterp_sd.ExitFrameWithException(valuebox)
-
-done_with_this_frame_descr_0 = DoneWithThisFrameDescr0()
-done_with_this_frame_descr_1 = DoneWithThisFrameDescr1()
+ if isinstance(valuebox, BoxPtr):
+ value = metainterp_sd.cpu.get_latest_value_ptr(0)
+ else:
+ assert isinstance(valuebox, history.Const)
+ value = valuebox.getptr_base()
+ raise metainterp_sd.ExitFrameWithException(value)
+
+done_with_this_frame_descr_void = DoneWithThisFrameDescrVoid()
+done_with_this_frame_descr_int = DoneWithThisFrameDescrInt()
+done_with_this_frame_descr_ptr = DoneWithThisFrameDescrPtr()
+done_with_this_frame_descr_obj = DoneWithThisFrameDescrObj()
exit_frame_with_exception_descr = ExitFrameWithExceptionDescr()
-map_loop2descr = {}
+
+class TerminatingLoop(TreeLoop):
+ pass
# pseudo-loops to make the life of optimize.py easier
-_loop = TreeLoop('done_with_this_frame_int')
+_loop = TerminatingLoop('done_with_this_frame_int')
_loop.specnodes = [NotSpecNode()]
_loop.inputargs = [BoxInt()]
+_loop.finishdescr = done_with_this_frame_descr_int
loops_done_with_this_frame_int = [_loop]
-map_loop2descr[_loop] = done_with_this_frame_descr_1
-_loop = TreeLoop('done_with_this_frame_ptr')
+_loop = TerminatingLoop('done_with_this_frame_ptr')
_loop.specnodes = [NotSpecNode()]
_loop.inputargs = [BoxPtr()]
+_loop.finishdescr = done_with_this_frame_descr_ptr
loops_done_with_this_frame_ptr = [_loop]
-map_loop2descr[_loop] = done_with_this_frame_descr_1
-_loop = TreeLoop('done_with_this_frame_void')
+_loop = TerminatingLoop('done_with_this_frame_obj')
+_loop.specnodes = [NotSpecNode()]
+_loop.inputargs = [BoxObj()]
+_loop.finishdescr = done_with_this_frame_descr_obj
+loops_done_with_this_frame_obj = [_loop]
+
+_loop = TerminatingLoop('done_with_this_frame_void')
_loop.specnodes = []
_loop.inputargs = []
+_loop.finishdescr = done_with_this_frame_descr_void
loops_done_with_this_frame_void = [_loop]
-map_loop2descr[_loop] = done_with_this_frame_descr_0
-_loop = TreeLoop('exit_frame_with_exception')
+_loop = TerminatingLoop('exit_frame_with_exception')
_loop.specnodes = [NotSpecNode()]
_loop.inputargs = [BoxPtr()]
+_loop.finishdescr = exit_frame_with_exception_descr
loops_exit_frame_with_exception = [_loop]
-map_loop2descr[_loop] = exit_frame_with_exception_descr
del _loop
@@ -181,7 +226,49 @@
def handle_fail_op(self, metainterp_sd, fail_op):
from pypy.jit.metainterp.pyjitpl import MetaInterp
metainterp = MetaInterp(metainterp_sd)
- return metainterp.handle_guard_failure(fail_op, self)
+ patch = self.patch_boxes_temporarily(metainterp_sd, fail_op)
+ try:
+ return metainterp.handle_guard_failure(fail_op, self)
+ finally:
+ self.restore_patched_boxes(metainterp_sd, fail_op, patch)
+
+ def patch_boxes_temporarily(self, metainterp_sd, fail_op):
+ # A bit indirect: when we hit a rop.FAIL, the current values are
+ # stored somewhere in the CPU backend. Below we fetch them and
+ # copy them into the real boxes, i.e. the 'fail_op.args'. We
+ # are in a try:finally path at the end of which, in
+ # restore_patched_boxes(), we can safely undo exactly the
+ # changes done here.
+ cpu = metainterp_sd.cpu
+ patch = []
+ for i in range(len(fail_op.args)):
+ box = fail_op.args[i]
+ patch.append(box.clonebox())
+ if isinstance(box, BoxInt):
+ srcvalue = cpu.get_latest_value_int(i)
+ box.changevalue_int(srcvalue)
+ elif isinstance(box, BoxPtr):
+ srcvalue = cpu.get_latest_value_ptr(i)
+ box.changevalue_ptr(srcvalue)
+ elif cpu.is_oo and isinstance(box, BoxObj):
+ srcvalue = cpu.get_latest_value_obj(i)
+ box.changevalue_obj(srcvalue)
+ else:
+ assert False
+ return patch
+
+ def restore_patched_boxes(self, metainterp_sd, fail_op, patch):
+ for i in range(len(patch)-1, -1, -1):
+ srcbox = patch[i]
+ dstbox = fail_op.args[i]
+ if isinstance(srcbox, BoxInt):
+ srcbox.changevalue_int(dstbox.getint())
+ elif isinstance(srcbox, BoxPtr):
+ srcbox.changevalue_ptr(dstbox.getptr_base())
+ elif metainterp_sd.cpu.is_oo and isinstance(srcbox, BoxObj):
+ srcbox.changevalue_obj(dstbox.getobj())
+ else:
+ assert False
def get_guard_op(self):
guard_op = self.history.operations[self.history_guard_index]
@@ -270,13 +357,13 @@
def prepare_last_operation(new_loop, target_loop):
op = new_loop.operations[-1]
- if target_loop not in map_loop2descr:
+ if not isinstance(target_loop, TerminatingLoop):
# normal case
op.jump_target = target_loop
else:
- # The target_loop is a pseudo-loop done_with_this_frame. Replace
- # the operation with the real operation we want, i.e. a FAIL.
- descr = map_loop2descr[target_loop]
+ # The target_loop is a pseudo-loop, e.g. done_with_this_frame.
+ # Replace the operation with the real operation we want, i.e. a FAIL.
+ descr = target_loop.finishdescr
new_op = ResOperation(rop.FAIL, op.args, None, descr=descr)
new_loop.operations[-1] = new_op
Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py (original)
+++ pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py Sun Apr 26 16:35:53 2009
@@ -16,6 +16,7 @@
# ____________________________________________________________
+VOID = 'v'
INT = 'i'
PTR = 'p'
OBJ = 'o'
@@ -295,11 +296,11 @@
def get_(self):
return ootype.ooidentityhash(self.value) # XXX: check me
- def getaddr(self, cpu):
- # so far this is used only when calling
- # CodeWriter.IndirectCallset.bytecode_for_address. We don't need a
- # real addr, but just a key for the dictionary
- return self.value
+## def getaddr(self, cpu):
+## # so far this is used only when calling
+## # CodeWriter.IndirectCallset.bytecode_for_address. We don't need a
+## # real addr, but just a key for the dictionary
+## return self.value
def equals(self, other):
return self.value == other.getobj()
Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original)
+++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Sun Apr 26 16:35:53 2009
@@ -529,7 +529,11 @@
def opimpl_indirect_call(self, pc, indirectcallset, box, varargs):
box = self.implement_guard_value(pc, box)
cpu = self.metainterp.cpu
- jitcode = indirectcallset.bytecode_for_address(box.getaddr(cpu))
+ if cpu.is_oo:
+ key = box.getobj()
+ else:
+ key = box.getaddr(cpu)
+ jitcode = indirectcallset.bytecode_for_address(key)
f = self.metainterp.newframe(jitcode)
f.setup_call(varargs)
return True
@@ -806,6 +810,19 @@
self.options = options
self.globaldata = MetaInterpGlobalData()
+ RESULT = portal_graph.getreturnvar().concretetype
+ kind = history.getkind(RESULT)
+ if kind == 'void':
+ self.result_type = history.VOID
+ elif kind == 'int':
+ self.result_type = history.INT
+ elif kind == 'ptr':
+ self.result_type = history.PTR
+ elif kind == 'obj':
+ self.result_type = history.OBJ
+ else:
+ assert False
+
self.opcode_implementations = []
self.opcode_names = []
self.opname_to_index = {}
@@ -868,28 +885,10 @@
class MetaInterpGlobalData(object):
def __init__(self):
- self.metainterp_doing_call = None
self._debug_history = []
self.compiled_merge_points = r_dict(history.mp_eq, history.mp_hash)
# { greenkey: list-of-MergePoints }
- def set_metainterp_doing_call(self, metainterp):
- self.save_recursive_call()
- self.metainterp_doing_call = metainterp
-
- def unset_metainterp_doing_call(self, metainterp):
- if self.metainterp_doing_call != metainterp:
- metainterp._restore_recursive_call()
- self.metainterp_doing_call = None
-
- def save_recursive_call(self):
- if self.metainterp_doing_call is not None:
- self.metainterp_doing_call._save_recursive_call()
- self.metainterp_doing_call = None
-
- def assert_empty(self):
- assert self.metainterp_doing_call is None
-
# ____________________________________________________________
class MetaInterp(object):
@@ -917,7 +916,18 @@
else:
if not isinstance(self.history, history.BlackHole):
self.compile_done_with_this_frame(resultbox)
- raise self.staticdata.DoneWithThisFrame(resultbox)
+ sd = self.staticdata
+ if sd.result_type == history.VOID:
+ assert resultbox is None
+ raise sd.DoneWithThisFrameVoid
+ elif sd.result_type == history.INT:
+ raise sd.DoneWithThisFrameInt(resultbox.getint())
+ elif sd.result_type == history.PTR:
+ raise sd.DoneWithThisFramePtr(resultbox.getptr_base())
+ elif self.cpu.is_oo and sd.result_type == history.OBJ:
+ raise sd.DoneWithThisFrameObj(resultbox.getobj())
+ else:
+ assert False
def finishframe_exception(self, exceptionbox, excvaluebox):
if we_are_translated(): # detect and propagate AssertionErrors early
@@ -939,7 +949,7 @@
self.framestack.pop()
if not isinstance(self.history, history.BlackHole):
self.compile_exit_frame_with_exception(excvaluebox)
- raise self.staticdata.ExitFrameWithException(excvaluebox)
+ raise self.staticdata.ExitFrameWithException(excvaluebox.getptr_base())
def create_empty_history(self):
self.history = history.History(self.cpu)
@@ -954,9 +964,6 @@
@specialize.arg(1)
def execute_and_record(self, opnum, argboxes, descr=None):
- # detect recursions when using rop.CALL
- if opnum == rop.CALL:
- self.staticdata.globaldata.set_metainterp_doing_call(self)
# execute the operation first
history.check_descr(descr)
resbox = executor.execute(self.cpu, opnum, argboxes, descr)
@@ -972,82 +979,11 @@
resbox = resbox.nonconstbox() # ensure it is a Box
else:
assert resbox is None or isinstance(resbox, Box)
- if opnum == rop.CALL:
- self.staticdata.globaldata.unset_metainterp_doing_call(self)
# record the operation if not constant-folded away
if not canfold:
self.history.record(opnum, argboxes, resbox, descr)
return resbox
- def _save_recursive_call(self):
- # A bit of a hack: we need to be safe against box.changevalue_xxx()
- # called by cpu.execute_operations(), in case we are recursively
- # in another MetaInterp. Temporarily save away the content of the
- # boxes.
- log('recursive call to execute_operations()!')
- saved_env = []
- framestack = []
- for f in self.framestack:
- newenv = []
- #
- box = f.exception_box
- if isinstance(box, Box):
- saved_env.append(box.clonebox())
- box = f.exc_value_box
- if isinstance(box, Box):
- saved_env.append(box.clonebox())
- #
- for box in f.env:
- if isinstance(box, Box):
- saved_env.append(box.clonebox())
- newenv.append(box)
- framestack.append(newenv)
- pseudoframe = instantiate(MIFrame)
- pseudoframe.env = saved_env
- pseudoframe._saved_framestack = framestack
- self.framestack.append(pseudoframe)
-
- def _restore_recursive_call(self):
- log('recursion detected, restoring state')
- if not we_are_translated():
- assert not hasattr(self.framestack[-1], 'jitcode')
- assert hasattr(self.framestack[-2], 'jitcode')
- pseudoframe = self.framestack.pop()
- saved_env = pseudoframe.env
- i = 0
- assert len(pseudoframe._saved_framestack) == len(self.framestack)
- for j in range(len(self.framestack)):
- f = self.framestack[j]
- #
- box = f.exception_box
- if isinstance(box, BoxInt):
- box.changevalue_int(saved_env[i].getint())
- i += 1
- box = f.exc_value_box
- if isinstance(box, BoxPtr):
- box.changevalue_ptr(saved_env[i].getptr_base())
- i += 1
- #
- pseudoenv = pseudoframe._saved_framestack[j]
- assert len(f.env) == len(pseudoenv)
- for k in range(len(f.env)):
- box = f.env[k]
- if isinstance(box, BoxInt):
- assert isinstance(pseudoenv[k], BoxInt)
- box.changevalue_int(saved_env[i].getint())
- i += 1
- elif isinstance(box, BoxPtr):
- assert isinstance(pseudoenv[k], BoxPtr)
- box.changevalue_ptr(saved_env[i].getptr_base())
- i += 1
- else:
- if isinstance(box, ConstInt):
- assert box.getint() == pseudoenv[k].getint()
- elif isinstance(box, ConstPtr):
- assert box.getptr_base() == pseudoenv[k].getptr_base()
- assert isinstance(box, Const)
- assert i == len(saved_env)
-
def _interpret(self):
# Execute the frames forward until we raise a DoneWithThisFrame,
# a ContinueRunningNormally, or a GenerateMergePoint exception.
@@ -1204,15 +1140,22 @@
def compile_done_with_this_frame(self, exitbox):
# temporarily put a JUMP to a pseudo-loop
- if exitbox is not None:
- exits = [exitbox]
- if isinstance(exitbox, BoxInt) or isinstance(exitbox, ConstInt):
- loops = compile.loops_done_with_this_frame_int
- else:
- loops = compile.loops_done_with_this_frame_ptr
- else:
+ sd = self.staticdata
+ if sd.result_type == history.VOID:
+ assert exitbox is None
exits = []
loops = compile.loops_done_with_this_frame_void
+ elif sd.result_type == history.INT:
+ exits = [exitbox]
+ loops = compile.loops_done_with_this_frame_int
+ elif sd.result_type == history.PTR:
+ exits = [exitbox]
+ loops = compile.loops_done_with_this_frame_ptr
+ elif sd.cpu.is_oo and sd.result_type == history.OBJ:
+ exits = [exitbox]
+ loops = compile.loops_done_with_this_frame_obj
+ else:
+ assert False
self.history.record(rop.JUMP, exits, None)
target_loop = compile.compile_new_bridge(self, loops, self.resumekey)
assert target_loop is loops[0]
Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py (original)
+++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py Sun Apr 26 16:35:53 2009
@@ -77,14 +77,16 @@
cw.make_one_bytecode(graph_key, False, called_from)
metainterp.staticdata.portal_code = maingraph
metainterp.staticdata.state = FakeWarmRunnerDesc()
- metainterp.staticdata.DoneWithThisFrame = DoneWithThisFrame
+ metainterp.staticdata.DoneWithThisFrameInt = DoneWithThisFrame
+ metainterp.staticdata.DoneWithThisFramePtr = DoneWithThisFrame
+ metainterp.staticdata.DoneWithThisFrameObj = DoneWithThisFrame
self.metainterp = metainterp
try:
metainterp.compile_and_run_once(*args)
except DoneWithThisFrame, e:
#if conftest.option.view:
# metainterp.stats.view()
- return e.args[0].value
+ return e.args[0]
else:
raise Exception("FAILED")
Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py (original)
+++ pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py Sun Apr 26 16:35:53 2009
@@ -270,9 +270,9 @@
# except ContinueRunningNormally, e:
# *args = *e.new_args
# except DoneWithThisFrame, e:
- # return e.result
+ # return e.return
# except ExitFrameWithException, e:
- # raise e.type, e.value
+ # raise Exception, e.value
#
# def portal(*args):
# while 1:
@@ -288,17 +288,37 @@
portal_ptr = self.ts.functionptr(PORTALFUNC, 'portal',
graph = portalgraph)
- class DoneWithThisFrame(JitException):
- def __init__(self, resultbox):
- self.resultbox = resultbox
+ class DoneWithThisFrameVoid(JitException):
def __str__(self):
- return 'DoneWithThisFrame(%s)' % (self.resultbox,)
+ return 'DoneWithThisFrameVoid()'
+
+ class DoneWithThisFrameInt(JitException):
+ def __init__(self, result):
+ assert lltype.typeOf(result) is lltype.Signed
+ self.result = result
+ def __str__(self):
+ return 'DoneWithThisFrameInt(%s)' % (self.result,)
+
+ class DoneWithThisFramePtr(JitException):
+ def __init__(self, result):
+ assert lltype.typeOf(result) == llmemory.GCREF
+ self.result = result
+ def __str__(self):
+ return 'DoneWithThisFramePtr(%s)' % (self.result,)
+
+ class DoneWithThisFrameObj(JitException):
+ def __init__(self, result):
+ assert ootype.typeOf(result) == ootype.Object
+ self.result = result
+ def __str__(self):
+ return 'DoneWithThisFrameObj(%s)' % (self.result,)
class ExitFrameWithException(JitException):
- def __init__(self, valuebox):
- self.valuebox = valuebox
+ def __init__(self, value):
+ assert lltype.typeOf(value) == llmemory.GCREF
+ self.value = value
def __str__(self):
- return 'ExitFrameWithException(%s)' % (self.valuebox,)
+ return 'ExitFrameWithException(%s)' % (self.value,)
class ContinueRunningNormally(JitException):
def __init__(self, args):
@@ -308,15 +328,22 @@
return 'ContinueRunningNormally(%s)' % (
', '.join(map(str, self.args)),)
- self.DoneWithThisFrame = DoneWithThisFrame
+ self.DoneWithThisFrameVoid = DoneWithThisFrameVoid
+ self.DoneWithThisFrameInt = DoneWithThisFrameInt
+ self.DoneWithThisFramePtr = DoneWithThisFramePtr
+ self.DoneWithThisFrameObj = DoneWithThisFrameObj
self.ExitFrameWithException = ExitFrameWithException
self.ContinueRunningNormally = ContinueRunningNormally
- self.metainterp_sd.DoneWithThisFrame = DoneWithThisFrame
+ self.metainterp_sd.DoneWithThisFrameVoid = DoneWithThisFrameVoid
+ self.metainterp_sd.DoneWithThisFrameInt = DoneWithThisFrameInt
+ self.metainterp_sd.DoneWithThisFramePtr = DoneWithThisFramePtr
+ self.metainterp_sd.DoneWithThisFrameObj = DoneWithThisFrameObj
self.metainterp_sd.ExitFrameWithException = ExitFrameWithException
self.metainterp_sd.ContinueRunningNormally = ContinueRunningNormally
rtyper = self.translator.rtyper
portalfunc_ARGS = unrolling_iterable(list(enumerate(PORTALFUNC.ARGS)))
RESULT = PORTALFUNC.RESULT
+ result_kind = history.getkind(RESULT)
def ll_portal_runner(*args):
while 1:
@@ -328,10 +355,21 @@
for i, ARG in portalfunc_ARGS:
v = unwrap(ARG, e.args[i])
args = args + (v,)
- except DoneWithThisFrame, e:
- return unwrap(RESULT, e.resultbox)
+ except DoneWithThisFrameVoid:
+ assert result_kind == 'void'
+ return
+ except DoneWithThisFrameInt, e:
+ assert result_kind == 'int'
+ return lltype.cast_primitive(RESULT, e.result)
+ except DoneWithThisFramePtr, e:
+ assert result_kind == 'ptr'
+ return lltype.cast_opaque_ptr(RESULT, e.result)
+ except DoneWithThisFrameObj, e:
+ assert result_kind == 'obj'
+ return ootype.cast_from_object(RESULT, e.result)
except ExitFrameWithException, e:
- value = e.valuebox.getptr(lltype.Ptr(rclass.OBJECT))
+ value = lltype.cast_opaque_ptr(lltype.Ptr(rclass.OBJECT),
+ e.value)
if not we_are_translated():
raise LLException(value.typeptr, value)
else:
@@ -512,10 +550,8 @@
loop = cell.bridge
boxes = cell.fill_boxes(*args[num_green_args:])
# ---------- execute assembler ----------
- warmrunnerdesc.metainterp_sd.globaldata.save_recursive_call()
while True: # until interrupted by an exception
metainterp_sd = warmrunnerdesc.metainterp_sd
- metainterp_sd.globaldata.assert_empty()
fail_op = metainterp_sd.cpu.execute_operations(loop, boxes)
loop, boxes = fail_op.descr.handle_fail_op(metainterp_sd,
fail_op)
More information about the Pypy-commit
mailing list