[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