[pypy-svn] r74572 - in pypy/branch/blackhole-improvement/pypy/jit: backend backend/llgraph metainterp
arigo at codespeak.net
arigo at codespeak.net
Wed May 19 15:37:11 CEST 2010
Author: arigo
Date: Wed May 19 15:37:09 2010
New Revision: 74572
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/backend/model.py
pypy/branch/blackhole-improvement/pypy/jit/metainterp/blackhole.py
pypy/branch/blackhole-improvement/pypy/jit/metainterp/pyjitpl.py
Log:
Whack at exception handling until test_div_overflow passes.
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 19 15:37:09 2010
@@ -766,6 +766,8 @@
raise NotImplementedError
def op_call(self, calldescr, func, *args):
+ global _last_exception
+ assert _last_exception is None, "exception left behind"
assert _call_args_i == _call_args_r == _call_args_f == []
for x in args:
T = lltype.typeOf(x)
@@ -777,7 +779,15 @@
_call_args_f.append(x)
else:
raise TypeError(x)
- return _do_call_common(func)
+ try:
+ return _do_call_common(func)
+ except LLException, lle:
+ _last_exception = lle
+ d = {'v': None,
+ REF: lltype.nullptr(llmemory.GCREF.TO),
+ INT: 0,
+ FLOAT: 0.0}
+ return d[calldescr.typeinfo]
op_call_pure = op_call
@@ -1088,55 +1098,38 @@
_last_exception = None
-def get_exception():
- if _last_exception:
- return llmemory.cast_ptr_to_adr(_last_exception.args[0])
- else:
- return llmemory.NULL
-
-def get_exc_value():
- if _last_exception:
- return lltype.cast_opaque_ptr(llmemory.GCREF, _last_exception.args[1])
+def grab_exc_value():
+ global _last_exception
+ if _last_exception is not None:
+ result = _last_exception.args[1]
+ _last_exception = None
+ return lltype.cast_opaque_ptr(llmemory.GCREF, result)
else:
return lltype.nullptr(llmemory.GCREF.TO)
-def clear_exception():
- global _last_exception
- _last_exception = None
-
-_pseudo_exceptions = {}
+##_pseudo_exceptions = {}
-def _get_error(Class):
- if _llinterp.typer is not None:
- llframe = _llinterp.frame_class(None, None, _llinterp)
- try:
- llframe.make_llexception(Class())
- except LLException, e:
- return e
- else:
- assert 0, "should have raised"
- else:
- # for tests, a random emulated ll_inst will do
- if Class not in _pseudo_exceptions:
- ll_inst = lltype.malloc(rclass.OBJECT, zero=True)
- ll_inst.typeptr = lltype.malloc(rclass.OBJECT_VTABLE,
- immortal=True)
- _pseudo_exceptions[Class] = LLException(ll_inst.typeptr, ll_inst)
- return _pseudo_exceptions[Class]
-
-def get_overflow_error():
- return llmemory.cast_ptr_to_adr(_get_error(OverflowError).args[0])
-
-def get_overflow_error_value():
- return lltype.cast_opaque_ptr(llmemory.GCREF,
- _get_error(OverflowError).args[1])
-
-def get_zero_division_error():
- return llmemory.cast_ptr_to_adr(_get_error(ZeroDivisionError).args[0])
-
-def get_zero_division_error_value():
- return lltype.cast_opaque_ptr(llmemory.GCREF,
- _get_error(ZeroDivisionError).args[1])
+##def _get_error(Class):
+## if _llinterp.typer is not None:
+## llframe = _llinterp.frame_class(None, None, _llinterp)
+## try:
+## llframe.make_llexception(Class())
+## except LLException, e:
+## return e
+## else:
+## assert 0, "should have raised"
+## else:
+## # for tests, a random emulated ll_inst will do
+## if Class not in _pseudo_exceptions:
+## ll_inst = lltype.malloc(rclass.OBJECT, zero=True)
+## ll_inst.typeptr = lltype.malloc(rclass.OBJECT_VTABLE,
+## immortal=True)
+## _pseudo_exceptions[Class] = LLException(ll_inst.typeptr, ll_inst)
+## return _pseudo_exceptions[Class]
+
+##def get_overflow_error_value():
+## return lltype.cast_opaque_ptr(llmemory.GCREF,
+## _get_error(OverflowError).args[1])
def force(opaque_frame):
frame = _from_opaque(opaque_frame)
@@ -1513,13 +1506,7 @@
setannotation(frame_ptr_getvalue, annmodel.SomePtr(llmemory.GCREF))
setannotation(frame_float_getvalue, annmodel.SomeFloat())
-setannotation(get_exception, annmodel.SomeAddress())
-setannotation(get_exc_value, annmodel.SomePtr(llmemory.GCREF))
-setannotation(clear_exception, annmodel.s_None)
-setannotation(get_overflow_error, annmodel.SomeAddress())
-setannotation(get_overflow_error_value, annmodel.SomePtr(llmemory.GCREF))
-setannotation(get_zero_division_error, annmodel.SomeAddress())
-setannotation(get_zero_division_error_value, annmodel.SomePtr(llmemory.GCREF))
+setannotation(grab_exc_value, annmodel.SomePtr(llmemory.GCREF))
setannotation(force, annmodel.SomeInteger())
setannotation(get_forced_token_frame, s_Frame)
setannotation(get_frame_forced_token, annmodel.SomeAddress())
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 19 15:37:09 2010
@@ -274,11 +274,8 @@
token = history.getkind(RESULT)
return self.getdescr(0, token[0], extrainfo=extrainfo)
- def get_exception(self):
- return self.cast_adr_to_int(llimpl.get_exception())
-
- def get_exc_value(self):
- return llimpl.get_exc_value()
+ def grab_exc_value(self):
+ return llimpl.grab_exc_value()
def arraydescrof(self, A):
assert isinstance(A, lltype.GcArray)
Modified: pypy/branch/blackhole-improvement/pypy/jit/backend/model.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/backend/model.py (original)
+++ pypy/branch/blackhole-improvement/pypy/jit/backend/model.py Wed May 19 15:37:09 2010
@@ -100,19 +100,8 @@
they no longer keep objects alive)."""
raise NotImplementedError
- def get_exception(self):
- raise NotImplementedError
-
- def get_exc_value(self):
- raise NotImplementedError
-
- def clear_exception(self):
- raise NotImplementedError
-
- def get_overflow_error(self):
- raise NotImplementedError
-
- def get_zero_division_error(self):
+ def grab_exc_value(self):
+ """Return and clear the exception set by the latest execute_token()."""
raise NotImplementedError
@staticmethod
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 19 15:37:09 2010
@@ -32,21 +32,19 @@
NULL = lltype.nullptr(llmemory.GCREF.TO)
-def get_standard_error_llexception(rtyper, Class):
+def _get_standard_error(rtyper, Class):
exdata = rtyper.getexceptiondata()
clsdef = rtyper.annotator.bookkeeper.getuniqueclassdef(Class)
evalue = exdata.get_standard_ll_exc_instance(rtyper, clsdef)
- etype = rclass.ll_type(evalue)
- return LLException(etype, evalue)
+ return evalue
def get_llexception(cpu, e):
if we_are_translated():
return XXX(e)
if isinstance(e, LLException):
- return e # ok
+ return e.args[1] # ok
if isinstance(e, OverflowError):
- return get_standard_error_llexception(cpu.rtyper,
- OverflowError)
+ return _get_standard_error(cpu.rtyper, OverflowError)
raise # leave other exceptions to be propagated
# ____________________________________________________________
@@ -180,7 +178,7 @@
print '-> %s!' % (e.__class__.__name__,)
if resulttype == 'i' or resulttype == 'r' or resulttype == 'f':
position += 1
- self.exception_pc = position
+ self.position = position
raise
if verbose and not we_are_translated():
@@ -291,21 +289,21 @@
self.registers_f[index] = value
def run(self):
- code = self.jitcode.code
- position = self.position
while True:
try:
- self.dispatch_loop(self, code, position)
+ self.dispatch_loop(self, self.jitcode.code, self.position)
except LeaveFrame:
break
except Exception, e:
e = get_llexception(self.cpu, e)
- position = self.handle_exception_in_frame(e, code)
+ self.handle_exception_in_frame(e)
def get_result_i(self):
+ assert self._return_type == 'i'
return self.tmpreg_i
def get_result_r(self):
+ assert self._return_type == 'r'
result = self.tmpreg_r
if we_are_translated():
self.tmpreg_r = NULL
@@ -314,14 +312,18 @@
return result
def get_result_f(self):
+ assert self._return_type == 'f'
return self.tmpreg_f
+ def get_result_v(self):
+ assert self._return_type == 'v'
+
def _get_result_anytype(self):
"NOT_RPYTHON"
- if self._return_type == 'int': return self.get_result_i()
- if self._return_type == 'ref': return self.get_result_r()
- if self._return_type == 'float': return self.get_result_f()
- if self._return_type == 'void': return None
+ if self._return_type == 'i': return self.get_result_i()
+ if self._return_type == 'r': return self.get_result_r()
+ if self._return_type == 'f': return self.get_result_f()
+ if self._return_type == 'v': return None
raise ValueError(self._return_type)
def cleanup_registers(self):
@@ -332,21 +334,24 @@
self.registers_r[i] = NULL
self.exception_last_value = None
- def handle_exception_in_frame(self, e, code):
+ def handle_exception_in_frame(self, e):
# This frame raises an exception. First try to see if
# the exception is handled in the frame itself.
- position = self.exception_pc # <-- just after the insn that raised
+ code = self.jitcode.code
+ position = self.position
opcode = ord(code[position])
if opcode != self.op_catch_exception:
# no 'catch_exception' insn follows: just reraise
- raise Exception, e
+ if we_are_translated():
+ raise Exception, e
+ else:
+ etype = rclass.ll_type(e)
+ raise LLException(etype, e)
else:
# else store the exception on 'self', and jump to the handler
- if not we_are_translated(): # get the lltyped exception
- e = e.args[1] # object out of the LLException
self.exception_last_value = e
target = ord(code[position+1]) | (ord(code[position+2])<<8)
- return target
+ self.position = target
# XXX must be specialized
def copy_constants(self, registers, constants):
@@ -586,28 +591,24 @@
@arguments("self", "i")
def bhimpl_int_return(self, a):
self.tmpreg_i = a
- if not we_are_translated():
- self._return_type = "int"
+ self._return_type = 'i'
raise LeaveFrame
@arguments("self", "r")
def bhimpl_ref_return(self, a):
self.tmpreg_r = a
- if not we_are_translated():
- self._return_type = "ref"
+ self._return_type = 'r'
raise LeaveFrame
@arguments("self", "f")
def bhimpl_float_return(self, a):
self.tmpreg_f = a
- if not we_are_translated():
- self._return_type = "float"
+ self._return_type = 'f'
raise LeaveFrame
@arguments("self")
def bhimpl_void_return(self):
- if not we_are_translated():
- self._return_type = "void"
+ self._return_type = 'v'
raise LeaveFrame
@arguments("i", "L", "pc", returns="L")
@@ -935,6 +936,80 @@
def bhimpl_unicodesetitem(cpu, unicode, index, newchr):
cpu.bh_unicodesetitem(unicode, index, newchr)
+ # ----------
+ # helpers to resume running in blackhole mode when a guard failed
+
+ def _resume_mainloop(self, current_exc):
+ try:
+ # if there is a current exception, raise it now
+ # (it may be caught by a catch_operation in this frame)
+ if current_exc:
+ self.handle_exception_in_frame(current_exc)
+ # unless the call above raised again the exception,
+ # we now proceed to interpret the bytecode in this frame
+ self.run()
+ #
+ except Exception, e:
+ # if we get an exception, return it to the caller frame
+ current_exc = get_llexception(self.cpu, e)
+ if not self.nextblackholeinterp:
+ self._exit_frame_with_exception(current_exc)
+ return current_exc
+ #
+ # pass the frame's return value to the caller
+ caller = self.nextblackholeinterp
+ if not caller:
+ self._done_with_this_frame()
+ kind = self._return_type
+ if kind == 'i':
+ caller._setup_return_value_i(self.get_result_i())
+ elif kind == 'r':
+ caller._setup_return_value_r(self.get_result_r())
+ elif kind == 'f':
+ caller._setup_return_value_f(self.get_result_f())
+ else:
+ assert kind == 'v'
+ return NULL
+
+ def _prepare_resume_from_failure(self, opnum):
+ from pypy.jit.metainterp.resoperation import rop
+ if opnum == rop.GUARD_TRUE: # a goto_if_not_xxx that jumps only now
+ self.position = self.jitcode.follow_jump(self.position)
+ elif opnum == rop.GUARD_FALSE: # a goto_if_not that stops jumping
+ pass
+ elif opnum == rop.GUARD_NO_EXCEPTION or opnum == rop.GUARD_EXCEPTION:
+ pass
+ else:
+ raise NotImplementedError(opnum)
+
+ # connect the return of values from the called frame to the
+ # 'xxx_call_yyy' instructions from the caller frame
+ def _setup_return_value_i(self, result):
+ self.registers_i[ord(self.jitcode.code[position-1])] = result
+ def _setup_return_value_r(self, result):
+ self.registers_r[ord(self.jitcode.code[position-1])] = result
+ def _setup_return_value_f(self, result):
+ self.registers_f[ord(self.jitcode.code[position-1])] = result
+
+ def _exit_frame_with_exception(self, e):
+ xxx
+
+ def _done_with_this_frame(self):
+ # rare case: we only get there if the blackhole interps all returned
+ # normally (in general we get a ContinueRunningNormally exception).
+ sd = self.builder.metainterp_sd
+ if sd.result_type == 'void':
+ self.get_result_v()
+ raise sd.DoneWithThisFrameVoid()
+ elif sd.result_type == 'int':
+ raise sd.DoneWithThisFrameInt(self.get_result_i())
+ elif sd.result_type == 'ref':
+ raise sd.DoneWithThisFrameRef(self.get_result_r())
+ elif sd.result_type == 'float':
+ raise sd.DoneWithThisFrameFloat(self.get_result_f())
+ else:
+ assert False
+
# ____________________________________________________________
def resume_in_blackhole(metainterp_sd, resumedescr):
@@ -947,47 +1022,13 @@
False) # XXX
# XXX virtualrefs
# XXX virtualizable
- _prepare_resume_from_failure(blackholeinterp, resumedescr.guard_opnum)
+ blackholeinterp._prepare_resume_from_failure(resumedescr.guard_opnum)
try:
- blackholeinterp = _resume_mainloop(blackholeinterp)
+ current_exc = blackholeinterp.cpu.grab_exc_value()
+ current_exc = lltype.cast_opaque_ptr(rclass.OBJECTPTR, current_exc)
+ while True:
+ current_exc = blackholeinterp._resume_mainloop(current_exc)
+ blackholeinterp = blackholeinterp.nextblackholeinterp
finally:
metainterp_sd.profiler.end_blackhole()
debug_stop('jit-blackhole')
- # rare case: we only get there if the blackhole interps all returned
- # normally (in general we get a ContinueRunningNormally exception).
- _done_with_this_frame(blackholeinterp)
-
-def _resume_mainloop(blackholeinterp):
- while True:
- try:
- blackholeinterp.run()
- finally:
- blackholeinterp.builder.release_interp(blackholeinterp)
- #...x.x.x...
- assert blackholeinterp.nextblackholeinterp is None # XXX
- break
- xxx
- return blackholeinterp
-
-def _prepare_resume_from_failure(blackholeinterp, opnum):
- from pypy.jit.metainterp.resoperation import rop
- if opnum == rop.GUARD_TRUE: # a goto_if_not_xxx that jumps only now
- blackholeinterp.position = blackholeinterp.jitcode.follow_jump(
- blackholeinterp.position)
- elif opnum == rop.GUARD_FALSE: # a goto_if_not that stops jumping
- pass
- else:
- raise NotImplementedError(opnum)
-
-def _done_with_this_frame(blackholeinterp):
- sd = blackholeinterp.builder.metainterp_sd
- if sd.result_type == 'void':
- raise sd.DoneWithThisFrameVoid()
- elif sd.result_type == 'int':
- raise sd.DoneWithThisFrameInt(blackholeinterp.get_result_i())
- elif sd.result_type == 'ref':
- raise sd.DoneWithThisFrameRef(blackholeinterp.get_result_r())
- elif sd.result_type == 'float':
- raise sd.DoneWithThisFrameFloat(blackholeinterp.get_result_f())
- else:
- assert False
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 19 15:37:09 2010
@@ -1413,8 +1413,6 @@
# to generate either GUARD_EXCEPTION or GUARD_NO_EXCEPTION, and also
# to handle the following opcodes 'goto_if_exception_mismatch'.
llexception = get_llexception(self.cpu, exception)
- if not we_are_translated():
- llexception = llexception.args[1]
llexception = self.cpu.ts.cast_to_ref(llexception)
exc_value_box = self.cpu.ts.get_exc_value_box(llexception)
if constant:
@@ -1600,7 +1598,12 @@
pass
elif (opnum == rop.GUARD_NO_EXCEPTION or opnum == rop.GUARD_EXCEPTION
or opnum == rop.GUARD_NOT_FORCED):
- xxx #self.handle_exception()
+ exception = self.cpu.grab_exc_value()
+ if exception:
+ self.execute_raised(exception)
+ else:
+ self.execute_did_not_raise()
+ self.handle_possible_exception()
elif opnum == rop.GUARD_NO_OVERFLOW: # an overflow now detected
xxx #self.raise_overflow_error()
elif opnum == rop.GUARD_NONNULL or opnum == rop.GUARD_ISNULL:
More information about the Pypy-commit
mailing list