[pypy-svn] r43472 - in pypy/dist/pypy/translator/jvm: . src/pypy
niko at codespeak.net
niko at codespeak.net
Fri May 18 13:26:08 CEST 2007
Author: niko
Date: Fri May 18 13:26:07 2007
New Revision: 43472
Removed:
pypy/dist/pypy/translator/jvm/src/pypy/ExceptionWrapper.java
Modified:
pypy/dist/pypy/translator/jvm/database.py
pypy/dist/pypy/translator/jvm/generator.py
pypy/dist/pypy/translator/jvm/genjvm.py
pypy/dist/pypy/translator/jvm/node.py
pypy/dist/pypy/translator/jvm/typesystem.py
Log:
Remove the exception wrapper system completely. We now throw
the exceptions natively; any attempt to throw an RPython object
that does not descend from Exception will yield a ClassCastException
Modified: pypy/dist/pypy/translator/jvm/database.py
==============================================================================
--- pypy/dist/pypy/translator/jvm/database.py (original)
+++ pypy/dist/pypy/translator/jvm/database.py Fri May 18 13:26:07 2007
@@ -5,7 +5,7 @@
from cStringIO import StringIO
from pypy.rpython.lltypesystem import lltype
-from pypy.rpython.ootypesystem import ootype
+from pypy.rpython.ootypesystem import ootype, rclass
from pypy.translator.jvm import typesystem as jvmtype
from pypy.translator.jvm import node, methods
from pypy.translator.jvm.option import getoption
@@ -493,6 +493,15 @@
assert False, "Untranslatable type %s!" % OOT
+ def exception_root_object(self):
+ """
+ Returns a JvmType representing the version of Object that
+ serves as the root of all exceptions.
+ """
+ self.lltype_to_cts(rclass.OBJECT)
+ assert self._object_interf
+ return self._object_exc_impl
+
# _________________________________________________________________
# Uh....
#
Modified: pypy/dist/pypy/translator/jvm/generator.py
==============================================================================
--- pypy/dist/pypy/translator/jvm/generator.py (original)
+++ pypy/dist/pypy/translator/jvm/generator.py Fri May 18 13:26:07 2007
@@ -286,6 +286,12 @@
class Method(object):
+ # Create a constructor:
+ def c(classty, argtypes):
+ return Method(classty.name, "<init>", argtypes, jVoid,
+ opcode=INVOKESPECIAL)
+ c = staticmethod(c)
+
# Create a virtual method:
def v(classty, methnm, argtypes, rettype):
"""
@@ -376,19 +382,18 @@
PYPYSTRTODOUBLE = Method.s(jPyPy, 'str_to_double', (jString,), jDouble)
PYPYSTRTOCHAR = Method.s(jPyPy, 'str_to_char', (jString,), jChar)
PYPYDUMP = Method.s(jPyPy, 'dump', (jString,), jVoid)
+PYPYDUMPEXCWRAPPER = Method.s(jPyPy, 'dump_exc_wrapper', (jObject,), jVoid)
PYPYSERIALIZEBOOLEAN = Method.s(jPyPy, 'serialize_boolean', (jBool,), jString)
PYPYSERIALIZEUINT = Method.s(jPyPy, 'serialize_uint', (jInt,), jString)
PYPYSERIALIZEVOID = Method.s(jPyPy, 'serialize_void', (), jString)
PYPYESCAPEDCHAR = Method.s(jPyPy, 'escaped_char', (jChar,), jString)
PYPYESCAPEDSTRING = Method.s(jPyPy, 'escaped_string', (jString,), jString)
PYPYSERIALIZEOBJECT = Method.s(jPyPy, 'serializeObject', (jObject,), jString)
-PYPYDUMPEXCWRAPPER = Method.s(jPyPy, 'dump_exc_wrapper', (jObject,), jVoid)
PYPYRUNTIMENEW = Method.s(jPyPy, 'RuntimeNew', (jClass,), jObject)
PYPYSTRING2BYTES = Method.s(jPyPy, 'string2bytes', (jString,), jByteArray)
PYPYARRAYTOLIST = Method.s(jPyPy, 'array_to_list', (jObjectArray,), jArrayList)
OBJECTGETCLASS = Method.v(jObject, 'getClass', (), jClass)
CLASSGETNAME = Method.v(jClass, 'getName', (), jString)
-EXCWRAPWRAP = Method.s(jPyPyExcWrap, 'wrap', (jObject,), jPyPyExcWrap)
CUSTOMDICTMAKE = Method.s(jPyPyCustomDict, 'make',
(jPyPyEquals, jPyPyHashCode), jPyPyCustomDict)
@@ -452,8 +457,6 @@
PYPYINTERLINK= Field(jPyPy.name, 'interlink', jPyPyInterlink, True)
-EXCWRAPOBJ = Field(jPyPyExcWrap.name, 'object', jObject, False)
-
# ___________________________________________________________________________
# Generator State
@@ -772,6 +775,10 @@
jclasstype, jscalartype.unbox_method, (), jscalartype)
self.emit(jmethod)
+ def swap(self):
+ """ Swaps the two words highest on the stack. """
+ self.emit(SWAP)
+
# __________________________________________________________________
# Exception Handling
@@ -789,32 +796,16 @@
"""
self.endtrylbl = self.unique_label("end_try", mark=True)
- def begin_catch(self, excclsty):
+ def begin_catch(self, jexcclsty):
"""
Begins a catch region corresponding to the last try; there can
be more than one call to begin_catch, in which case the last
try region is reused.
- 'excclsty' --- a JvmType for the class of exception to be caught
+ 'jexcclsty' --- a JvmType for the class of exception to be caught
"""
catchlbl = self.unique_label("catch", mark=True)
self.try_catch_region(
- jPyPyExcWrap, self.begintrylbl, self.endtrylbl, catchlbl)
-
- # emit the code to unwrap the exception, check the type
- # of the unwrapped object, and re-throw the exception
- # if it not the right type
- catch = self.unique_label('catch')
- self.emit(DUP)
- EXCWRAPOBJ.load(self)
- self.emit(INSTANCEOF, excclsty)
- self.emit(IFNE, catch)
- self.emit(ATHROW)
-
- # If it IS the right type, just dereference and get the
- # wrapped Python object
- self.mark(catch)
- EXCWRAPOBJ.load(self)
- self.emit(CHECKCAST, excclsty)
+ jexcclsty, self.begintrylbl, self.endtrylbl, catchlbl)
def end_catch(self):
"""
@@ -823,14 +814,14 @@
"""
return
- def try_catch_region(self, excclsty, trystartlbl, tryendlbl, catchlbl):
+ def try_catch_region(self, jexcclsty, trystartlbl, tryendlbl, catchlbl):
"""
Indicates a try/catch region.
Either invoked directly, or from the begin_catch() routine:
the latter is invoked by the oosupport code.
- 'excclsty' --- a JvmType for the class of exception to be caught
+ 'jexcclsty' --- a JvmType for the class of exception to be caught
'trystartlbl', 'tryendlbl' --- labels marking the beginning and end
of the try region
'catchlbl' --- label marking beginning of catch region
@@ -952,7 +943,12 @@
jtype = self.db.lltype_to_cts(TYPE)
self._instr(INSTANCEOF, jtype)
+ # included for compatibility with oosupport, but instanceof_jtype
+ # follows our naming convention better
def isinstance(self, jtype):
+ return self.instanceof_jtype(jtype)
+
+ def instanceof_jtype(self, jtype):
self._instr(INSTANCEOF, jtype)
def branch_unconditionally(self, target_label):
@@ -1008,7 +1004,7 @@
self.new_with_jtype(jtype)
def new_with_jtype(self, jtype):
- ctor = Method(jtype.name, "<init>", (), jVoid, opcode=INVOKESPECIAL)
+ ctor = Method.c(jtype, ())
self.emit(NEW, jtype)
self.emit(DUP)
self.emit(ctor)
@@ -1023,6 +1019,9 @@
def dup(self, OOTYPE):
jvmtype = self.db.lltype_to_cts(OOTYPE)
+ self.dup_jtype(jvmtype)
+
+ def dup_jtype(self, jvmtype):
if jvmtype.descriptor.type_width() == 1:
self.emit(DUP)
else:
@@ -1092,12 +1091,6 @@
def throw(self):
""" Throw the object from top of the stack as an exception """
-
- # We have to deal with the problem that exceptions must
- # derive from Throwable, but our exception hierarchy in OOTYPE
- # does not (today). For now, we use a wrapper class, which is
- # probably the worst answer of all, but an easy one.
- self.emit(EXCWRAPWRAP)
self._instr(ATHROW)
def iabs(self):
@@ -1301,9 +1294,9 @@
self.curclass.out(' %-60s\n' % (instr_text,))
self.curfunc.instr_counter+=1
- def try_catch_region(self, excclsty, trystartlbl, tryendlbl, catchlbl):
+ def try_catch_region(self, jexcclsty, trystartlbl, tryendlbl, catchlbl):
self.curclass.out(' .catch %s from %s to %s using %s\n' % (
- excclsty.descriptor.int_class_name(),
+ jexcclsty.descriptor.int_class_name(),
trystartlbl.jasmin_syntax(),
tryendlbl.jasmin_syntax(),
catchlbl.jasmin_syntax()))
Modified: pypy/dist/pypy/translator/jvm/genjvm.py
==============================================================================
--- pypy/dist/pypy/translator/jvm/genjvm.py (original)
+++ pypy/dist/pypy/translator/jvm/genjvm.py Fri May 18 13:26:07 2007
@@ -132,7 +132,6 @@
'CustomDict',
'DictItemsIterator',
'Equals',
- 'ExceptionWrapper',
'Filter',
'FilterIterator',
'FilterSet',
Modified: pypy/dist/pypy/translator/jvm/node.py
==============================================================================
--- pypy/dist/pypy/translator/jvm/node.py (original)
+++ pypy/dist/pypy/translator/jvm/node.py Fri May 18 13:26:07 2007
@@ -143,7 +143,8 @@
gen.goto(done_printing)
gen.end_try()
- gen.begin_catch(jObject)
+ jexc = self.db.exception_root_object()
+ gen.begin_catch(jexc)
gen.emit(jvmgen.PYPYDUMPEXCWRAPPER) # dumps to stdout
gen.end_catch()
@@ -289,8 +290,9 @@
def begin_catch(self, llexitcase):
ll_meta_exc = llexitcase
ll_exc = ll_meta_exc._inst.class_._INSTANCE
- cts_exc = self.cts.lltype_to_cts(ll_exc)
- self.ilasm.begin_catch(cts_exc)
+ jtype = self.cts.lltype_to_cts(ll_exc)
+ assert jtype.throwable # SHOULD only try to catch subtypes of Exception
+ self.ilasm.begin_catch(jtype)
def end_catch(self, exit_lbl):
self.ilasm.goto(exit_lbl)
@@ -324,6 +326,15 @@
def render_raise_block(self, block):
exc = block.inputargs[1]
self.ilasm.load(exc)
+
+ # Check whether the static type is known to be throwable.
+ # If not, emit a CHECKCAST to the base exception type.
+ # According to Samuele, no non-Exceptions should be thrown,
+ # but this is not enforced by the RTyper or annotator.
+ jtype = self.db.lltype_to_cts(exc.concretetype)
+ if not jtype.throwable:
+ self.ilasm.downcast_jtype(self.db.exception_root_object())
+
self.ilasm.throw()
def _trace(self, str):
@@ -625,13 +636,13 @@
"java.lang.String", supercls is a Class object
"""
JvmClassType.__init__(self, name)
- self.super_class = supercls # JvmType; if None, must use set_super_class
self.rendered = False # has rendering occurred?
self.abstract = False # is this an abstract class?
self.fields = {} # maps field name to jvmgen.Field object
self.interfaces = [] # list of JvmTypes
self.methods = {} # maps method name to a Function object*
self.abstract_methods = {} # maps method name to jvmgen.Method object
+ self.set_super_class(supercls)
# * --- actually maps to an object that defines the
# attributes: name, method() and render(). Usually, this is a
@@ -645,6 +656,10 @@
def set_super_class(self, supercls):
self.super_class = supercls
+ # Throwability is inherited:
+ if self.super_class and self.super_class.throwable:
+ self.throwable = True
+
def add_field(self, fieldobj, fielddef):
""" Creates a new field accessed via the jvmgen.Field
descriptor 'fieldobj'. Must be called before render()."""
@@ -739,4 +754,3 @@
gen.emit(self.helper)
gen.return_val(jVoid)
gen.end_function()
-
Modified: pypy/dist/pypy/translator/jvm/typesystem.py
==============================================================================
--- pypy/dist/pypy/translator/jvm/typesystem.py (original)
+++ pypy/dist/pypy/translator/jvm/typesystem.py Fri May 18 13:26:07 2007
@@ -136,9 +136,10 @@
only work to obtain the descriptor. We use it on occasion for classes
like java.lang.Object etc.
"""
- def __init__(self, classnm):
+ def __init__(self, classnm, throwable=False):
JvmType.__init__(self, desc_for_class(classnm))
- self.name = classnm # public String, like 'java.lang.Object'
+ self.name = classnm # public; String, like 'java.lang.Object'
+ self.throwable = throwable # public; boolean
def lookup_field(self, fieldnm):
raise KeyError(fieldnm) # we treat as opaque type
def lookup_method(self, methodnm):
@@ -153,7 +154,7 @@
jByteClass = JvmClassType('java.lang.Byte')
jCharClass = JvmClassType('java.lang.Character')
jBoolClass = JvmClassType('java.lang.Boolean')
-jThrowable = JvmClassType('java.lang.Throwable')
+jThrowable = JvmClassType('java.lang.Throwable', throwable=True)
jObject = JvmClassType('java.lang.Object')
jString = JvmClassType('java.lang.String')
jCharSequence = JvmClassType('java.lang.CharSequence')
@@ -175,7 +176,7 @@
jPyPyInterlink = JvmClassType('pypy.Interlink')
jPyPyCustomDict = JvmClassType('pypy.CustomDict')
-jArithmeticException = JvmClassType('java.lang.ArithmeticException')
+jArithmeticException = JvmClassType('java.lang.ArithmeticException', throwable=True)
class JvmScalarType(JvmType):
"""
More information about the Pypy-commit
mailing list