[pypy-svn] r56259 - in pypy/dist/pypy: annotation rpython rpython/lltypesystem rpython/ootypesystem rpython/test translator/backendopt translator/cli translator/cli/test translator/jvm translator/jvm/src/pypy translator/jvm/test translator/oosupport/test_template

arigo at codespeak.net arigo at codespeak.net
Thu Jul 3 15:38:15 CEST 2008


Author: arigo
Date: Thu Jul  3 15:38:13 2008
New Revision: 56259

Added:
   pypy/dist/pypy/translator/jvm/src/pypy/PyPyThrowable.java
      - copied unchanged from r56130, pypy/branch/less-meta-instances/pypy/translator/jvm/src/pypy/PyPyThrowable.java
   pypy/dist/pypy/translator/oosupport/test_template/exception.py
      - copied unchanged from r56130, pypy/branch/less-meta-instances/pypy/translator/oosupport/test_template/exception.py
Modified:
   pypy/dist/pypy/annotation/description.py
   pypy/dist/pypy/annotation/model.py
   pypy/dist/pypy/rpython/llinterp.py
   pypy/dist/pypy/rpython/lltypesystem/rclass.py
   pypy/dist/pypy/rpython/lltypesystem/rpbc.py
   pypy/dist/pypy/rpython/ootypesystem/exceptiondata.py
   pypy/dist/pypy/rpython/ootypesystem/ootype.py
   pypy/dist/pypy/rpython/ootypesystem/rbuiltin.py
   pypy/dist/pypy/rpython/ootypesystem/rclass.py
   pypy/dist/pypy/rpython/ootypesystem/rootype.py
   pypy/dist/pypy/rpython/ootypesystem/rpbc.py
   pypy/dist/pypy/rpython/rclass.py
   pypy/dist/pypy/rpython/rpbc.py
   pypy/dist/pypy/rpython/test/test_normalizecalls.py
   pypy/dist/pypy/rpython/test/test_rbuiltin.py
   pypy/dist/pypy/rpython/test/test_rclass.py
   pypy/dist/pypy/translator/backendopt/inline.py
   pypy/dist/pypy/translator/cli/database.py
   pypy/dist/pypy/translator/cli/function.py
   pypy/dist/pypy/translator/cli/opcodes.py
   pypy/dist/pypy/translator/cli/test/runtest.py
   pypy/dist/pypy/translator/cli/test/test_exception.py
   pypy/dist/pypy/translator/jvm/database.py
   pypy/dist/pypy/translator/jvm/node.py
   pypy/dist/pypy/translator/jvm/opcodes.py
   pypy/dist/pypy/translator/jvm/test/test_exception.py
   pypy/dist/pypy/translator/jvm/typesystem.py
Log:
(antocuni, niko, arigo)

Merge the less-meta-instances branch.  Now ootypesystem.rclass.OBJECT is empty.
We removed the "meta" field and only create meta-classes and meta-instances
when necessary instead of systematically.  This lets us improve the oo backends
too.  In the future this might also let us map exceptions more directly to
native ones, possibly.

svn merge svn+ssh://codespeak.net/svn/pypy/branch/less-meta-instances@53334 \
          svn+ssh://codespeak.net/svn/pypy/branch/less-meta-instances@56130



Modified: pypy/dist/pypy/annotation/description.py
==============================================================================
--- pypy/dist/pypy/annotation/description.py	(original)
+++ pypy/dist/pypy/annotation/description.py	Thu Jul  3 15:38:13 2008
@@ -466,6 +466,9 @@
         for name, value in cls.__dict__.items():
             self.add_source_attribute(name, value, mixin)
 
+    def getallclassdefs(self):
+        return self._classdefs.values()
+
     def getclassdef(self, key):
         try:
             return self._classdefs[key]

Modified: pypy/dist/pypy/annotation/model.py
==============================================================================
--- pypy/dist/pypy/annotation/model.py	(original)
+++ pypy/dist/pypy/annotation/model.py	Thu Jul  3 15:38:13 2008
@@ -591,6 +591,8 @@
         return s_val.ootype
     if isinstance(s_val, SomeOOStaticMeth):
         return s_val.method
+    if isinstance(s_val, SomeOOClass):
+        return ootype.Class
     if isinstance(s_val, SomeInteriorPtr):
         p = s_val.ll_ptrtype
         if 0 in p.offsets:

Modified: pypy/dist/pypy/rpython/llinterp.py
==============================================================================
--- pypy/dist/pypy/rpython/llinterp.py	(original)
+++ pypy/dist/pypy/rpython/llinterp.py	Thu Jul  3 15:38:13 2008
@@ -37,7 +37,7 @@
         return ''.join(etype.name).rstrip('\x00')
     else:
         # ootype!
-        return etype.class_._INSTANCE._name.split(".")[-1] 
+        return etype._INSTANCE._name.split(".")[-1] 
 
 class LLInterpreter(object):
     """ low level interpreter working with concrete values. """

Modified: pypy/dist/pypy/rpython/lltypesystem/rclass.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/rclass.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/rclass.py	Thu Jul  3 15:38:13 2008
@@ -166,7 +166,10 @@
         if cast_to_typeptr:
             vtable = cast_vtable_to_typeptr(vtable)
         return vtable
-    getruntime = getvtable
+
+    def getruntime(self, expected_type):
+        assert expected_type == CLASSTYPE
+        return self.getvtable()
 
     def setup_vtable(self, vtable, rsubcls):
         """Initialize the 'self' portion of the 'vtable' belonging to the

Modified: pypy/dist/pypy/rpython/lltypesystem/rpbc.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/rpbc.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/rpbc.py	Thu Jul  3 15:38:13 2008
@@ -396,6 +396,8 @@
         v_inst1 = hop.gendirectcall(ll_instantiate, vtypeptr)
         return hop.genop('cast_pointer', [v_inst1], resulttype = r_instance)
 
+    def getlowleveltype(self):
+        return rclass.CLASSTYPE
 
 
 # ____________________________________________________________

Modified: pypy/dist/pypy/rpython/ootypesystem/exceptiondata.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/exceptiondata.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/exceptiondata.py	Thu Jul  3 15:38:13 2008
@@ -26,8 +26,8 @@
         self.fn_raise_OSError    = self.make_raise_OSError(rtyper)        
 
     def make_exception_matcher(self, rtyper):
-        # ll_exception_matcher(real_exception_meta, match_exception_meta)
-        s_classtype = annmodel.SomeOOInstance(self.lltype_of_exception_type)
+        # ll_exception_matcher(real_exception_class, match_exception_class)
+        s_classtype = annmodel.SomeOOClass(ootype.ROOT)
         helper_fn = rtyper.annotate_helper_fn(rclass.ll_issubclass, [s_classtype, s_classtype])
         return helper_fn
 
@@ -63,7 +63,6 @@
         r_class = rclass.getclassrepr(rtyper, None)
         r_class.setup()
         default_excinst = ootype.new(self.lltype_of_exception_value)
-        default_excinst.meta = r_class.get_meta_instance()
 
         # build the table in order base classes first, subclasses last
         sortedtable = []

Modified: pypy/dist/pypy/rpython/ootypesystem/ootype.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/ootype.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/ootype.py	Thu Jul  3 15:38:13 2008
@@ -47,7 +47,10 @@
 
     def _defl(self):
         return nullruntimeclass
-    
+
+    def _example(self):
+        return _class(ROOT)
+
 Class = Class()
 
 class Instance(OOType):
@@ -780,6 +783,7 @@
         self._INSTANCE = INSTANCE
 
 nullruntimeclass = _class(None)
+Class._null = nullruntimeclass
 
 class _instance(object):
     

Modified: pypy/dist/pypy/rpython/ootypesystem/rbuiltin.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/rbuiltin.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/rbuiltin.py	Thu Jul  3 15:38:13 2008
@@ -75,15 +75,14 @@
 
     v_obj, v_cls = hop.inputargs(instance_repr, class_repr)
     if isinstance(v_cls, Constant):
-        c_cls = hop.inputconst(ootype.Void, v_cls.value.class_._INSTANCE)
+        c_cls = hop.inputconst(ootype.Void, v_cls.value._INSTANCE)
         return hop.genop('instanceof', [v_obj, c_cls], resulttype=ootype.Bool)
     else:
         return hop.gendirectcall(ll_isinstance, v_obj, v_cls)
 
-def ll_isinstance(inst, meta):
-    c1 = inst.meta.class_
-    c2 = meta.class_
-    return ootype.subclassof(c1, c2)
+def ll_isinstance(inst, class_):
+    c1 = ootype.classof(inst)
+    return ootype.subclassof(c1, class_)
 
 def rtype_instantiate(hop):
     if hop.args_s[0].is_constant():
@@ -99,17 +98,12 @@
     else:
         r_instance = hop.s_result.rtyper_makerepr(hop.rtyper)
         INSTANCE = r_instance.lowleveltype
-        c_instance = hop.inputconst(ootype.Void, INSTANCE)
-        v_cls = hop.inputarg(hop.args_r[0], arg=0)
-        v_obj = hop.gendirectcall(ll_instantiate, c_instance, v_cls)
+        class_repr = rclass.get_type_repr(hop.rtyper)
+        v_cls = hop.inputarg(class_repr, arg=0)
+        v_obj = hop.genop('runtimenew', [v_cls], resulttype=ootype.ROOT)
         v_instance = hop.genop('oodowncast', [v_obj], resulttype=hop.r_result.lowleveltype)
-        c_meta = hop.inputconst(ootype.Void, "meta")
-        hop.genop("oosetfield", [v_instance, c_meta, v_cls], resulttype=ootype.Void)
         return v_instance
 
-def ll_instantiate(INST, C):
-    return ootype.runtimenew(C.class_)
-
 BUILTIN_TYPER = {}
 BUILTIN_TYPER[ootype.new] = rtype_new
 BUILTIN_TYPER[ootype.oonewarray] = rtype_oonewarray

Modified: pypy/dist/pypy/rpython/ootypesystem/rclass.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/rclass.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/rclass.py	Thu Jul  3 15:38:13 2008
@@ -7,49 +7,52 @@
 from pypy.rpython.rclass import AbstractClassRepr, AbstractInstanceRepr, \
                                 getinstancerepr, getclassrepr, get_type_repr
 from pypy.rpython.ootypesystem import ootype
+from pypy.rpython.exceptiondata import standardexceptions
 from pypy.tool.pairtype import pairtype
 from pypy.tool.sourcetools import func_with_new_name
 
-CLASSTYPE = ootype.Instance("Object_meta", ootype.ROOT,
-        fields={"class_": ootype.Class})
-OBJECT = ootype.Instance("Object", ootype.ROOT,
-        fields={'meta': CLASSTYPE})
+OBJECT = ootype.ROOT
+META = ootype.Instance("Meta", ootype.ROOT,
+                       fields={"class_": ootype.Class})
 
 
 class ClassRepr(AbstractClassRepr):
     def __init__(self, rtyper, classdef):
         AbstractClassRepr.__init__(self, rtyper, classdef)
-
+        # This is the Repr for a reference to the class 'classdef' or
+        # any subclass.  In the simple case, the lowleveltype is just
+        # ootype.Class.  If we need to store class attributes, we use a
+        # "meta" class where the attributes are defined, and the class
+        # reference is a reference to an instance of this meta class.
+        extra_access_sets = self.rtyper.class_pbc_attributes.get(
+            classdef, {})
+        has_class_attributes = bool(extra_access_sets)
         if self.classdef is not None:
             self.rbase = getclassrepr(self.rtyper, self.classdef.basedef)
-            base_type = self.rbase.lowleveltype
-            self.lowleveltype = ootype.Instance(
-                    self.classdef.name + "_meta", base_type)
+            meta_base_type = self.rbase.lowleveltype
+            baseclass_has_meta = meta_base_type != ootype.Class
+        else:
+            baseclass_has_meta = False
+
+        if not has_class_attributes and not baseclass_has_meta:
+            self.lowleveltype = ootype.Class   # simple case
         else:
-            # we are ROOT
-            self.lowleveltype = CLASSTYPE
+            if self.classdef is None:
+                raise TyperError("the root 'object' class should not have"
+                                 " class attributes")
+            if self.classdef.classdesc.pyobj in standardexceptions:
+                raise TyperError("Standard exception class %r should not have"
+                                 " class attributes" % (self.classdef.name,))
+            if not baseclass_has_meta:
+                meta_base_type = META
+            self.lowleveltype = ootype.Instance(
+                    self.classdef.name + "_meta", meta_base_type)
 
     def _setup_repr(self):
-        clsfields = {}
         pbcfields = {}
-        if self.classdef is not None:
+        if self.lowleveltype != ootype.Class:
             # class attributes
             llfields = []
-            """
-            attrs = self.classdef.attrs.items()
-            attrs.sort()
-            for name, attrdef in attrs:
-                if attrdef.readonly:
-                    s_value = attrdef.s_value
-                    s_unboundmethod = self.prepare_method(s_value)
-                    if s_unboundmethod is not None:
-                        allmethods[name] = True
-                        s_value = s_unboundmethod
-                    r = self.rtyper.getrepr(s_value)
-                    mangled_name = 'cls_' + name
-                    clsfields[name] = mangled_name, r
-                    llfields.append((mangled_name, r.lowleveltype))
-            """
             # attributes showing up in getattrs done on the class as a PBC
             extra_access_sets = self.rtyper.class_pbc_attributes.get(
                 self.classdef, {})
@@ -61,24 +64,26 @@
             
             self.rbase.setup()
             ootype.addFields(self.lowleveltype, dict(llfields))
-        #self.clsfields = clsfields
         self.pbcfields = pbcfields
         self.meta_instance = None
  
     def get_meta_instance(self, cast_to_root_meta=True):
+        if self.lowleveltype == ootype.Class:
+            raise TyperError("no meta-instance for class %r" % 
+                             (self.classdef,))
         if self.meta_instance is None:
             self.meta_instance = ootype.new(self.lowleveltype) 
             self.setup_meta_instance(self.meta_instance, self)
         
         meta_instance = self.meta_instance
         if cast_to_root_meta:
-            meta_instance = ootype.ooupcast(CLASSTYPE, meta_instance)
+            meta_instance = ootype.ooupcast(META, meta_instance)
         return meta_instance
 
     def setup_meta_instance(self, meta_instance, rsubcls):
         if self.classdef is None:
             rinstance = getinstancerepr(self.rtyper, rsubcls.classdef)
-            setattr(meta_instance, 'class_', rinstance.lowleveltype._class)
+            meta_instance.class_ = ootype.runtimeClass(rinstance.lowleveltype)
         else:
             # setup class attributes: for each attribute name at the level
             # of 'self', look up its value in the subclass rsubcls
@@ -88,14 +93,6 @@
                 llvalue = r.convert_desc_or_const(value)
                 setattr(meta_instance, mangled_name, llvalue)
 
-            #mro = list(rsubcls.classdef.getmro())
-            #for fldname in self.clsfields:
-            #    mangled_name, r = self.clsfields[fldname]
-            #    if r.lowleveltype is Void:
-            #        continue
-            #    value = rsubcls.classdef.classdesc.read_attribute(fldname, None)
-            #    if value is not None:
-            #        assign(mangled_name, value)
             # extra PBC attributes
             for (access_set, attr), (mangled_name, r) in self.pbcfields.items():
                 if rsubcls.classdef.classdesc not in access_set.descs:
@@ -107,15 +104,27 @@
                     assign(mangled_name, attrvalue)
 
             # then initialize the 'super' portion of the vtable
-            meta_instance_super = ootype.ooupcast(
-                    self.rbase.lowleveltype, meta_instance)
-            self.rbase.setup_meta_instance(meta_instance_super, rsubcls)
+            self.rbase.setup_meta_instance(meta_instance, rsubcls)
+
+    def getruntime(self, expected_type):
+        if expected_type == ootype.Class:
+            rinstance = getinstancerepr(self.rtyper, self.classdef)
+            return ootype.runtimeClass(rinstance.lowleveltype)
+        else:
+            assert ootype.isSubclass(expected_type, META)
+            meta = self.get_meta_instance(cast_to_root_meta=False)
+            return ootype.ooupcast(expected_type, meta)
 
-    getruntime = get_meta_instance
-    
     def fromclasstype(self, vclass, llops):
-        return llops.genop('oodowncast', [vclass],
-                resulttype=self.lowleveltype)
+        assert ootype.isSubclass(vclass.concretetype, META)
+        if self.lowleveltype == ootype.Class:
+            c_class_ = inputconst(ootype.Void, 'class_')
+            return llops.genop('oogetfield', [vclass, c_class_],
+                    resulttype=ootype.Class)
+        else:
+            assert ootype.isSubclass(self.lowleveltype, vclass.concretetype)
+            return llops.genop('oodowncast', [vclass],
+                    resulttype=self.lowleveltype)
 
     def getpbcfield(self, vcls, access_set, attr, llops):
         if (access_set, attr) not in self.pbcfields:
@@ -127,12 +136,11 @@
 
     def rtype_issubtype(self, hop):
         class_repr = get_type_repr(self.rtyper)
-        vmeta1, vmeta2 = hop.inputargs(class_repr, class_repr)
-        return hop.gendirectcall(ll_issubclass, vmeta1, vmeta2)
+        vcls1, vcls2 = hop.inputargs(class_repr, class_repr)
+        return hop.genop('subclassof', [vcls1, vcls2], resulttype=ootype.Bool)
 
-def ll_issubclass(meta1, meta2):
-    class1 = meta1.class_
-    class2 = meta2.class_
+def ll_issubclass(class1, class2):
+    # helper for exceptiondata.py
     return ootype.subclassof(class1, class2)
 
 # ____________________________________________________________
@@ -237,7 +245,7 @@
                     mangled = mangle(meth_name, self.rtyper.getconfig())
                     allmethods[mangled] = meth_name, s_meth
                 # else: it's the __init__ of a builtin exception
-            
+
         #
         # hash() support
         if self.rtyper.needs_hash_support(self.classdef):
@@ -255,6 +263,12 @@
         baseInstance = self.lowleveltype._superclass
         classrepr = getclassrepr(self.rtyper, self.classdef)
 
+        # if this class has a corresponding metaclass, attach
+        # a getmeta() method to get the corresponding meta_instance
+        if classrepr.lowleveltype != ootype.Class:
+            oovalue = classrepr.get_meta_instance()
+            self.attach_class_attr_accessor('getmeta', oovalue)
+
         for mangled, (name, s_value) in allmethods.iteritems():
             methdescs = s_value.descriptions
             origin = dict([(methdesc.originclassdef, methdesc) for
@@ -329,7 +343,12 @@
         
         for mangled, (s_value, value) in self.classattributes.items():
             r = self.rtyper.getrepr(s_value)
-            m = self.attach_class_attr_accessor(mangled, value, r)
+            if value is None:
+                self.attach_abstract_class_attr_accessor(mangled,
+                                                         r.lowleveltype)
+            else:
+                oovalue = r.convert_desc_or_const(value)
+                self.attach_class_attr_accessor(mangled, oovalue)
 
         # step 4: do the same with instance fields whose default
         # values are overridden in subclasses. Not sure it's the best
@@ -359,21 +378,21 @@
 
         ootype.overrideDefaultForFields(self.lowleveltype, overridden_defaults)
 
-    def attach_class_attr_accessor(self, mangled, value, r_value):
+    def attach_abstract_class_attr_accessor(self, mangled, attrtype):
+        M = ootype.Meth([], attrtype)
+        m = ootype.meth(M, _name=mangled, abstract=True)
+        ootype.addMethods(self.lowleveltype, {mangled: m})
+
+    def attach_class_attr_accessor(self, mangled, oovalue):
         def ll_getclassattr(self):
             return oovalue
 
-        M = ootype.Meth([], r_value.lowleveltype)
-        if value is None:
-            m = ootype.meth(M, _name=mangled, abstract=True)
-        else:
-            oovalue = r_value.convert_desc_or_const(value)
-            ll_getclassattr = func_with_new_name(ll_getclassattr,
-                                                 'll_get_' + mangled)
-            graph = self.rtyper.annotate_helper(ll_getclassattr, [self.lowleveltype])
-            m = ootype.meth(M, _name=mangled, _callable=ll_getclassattr,
-                            graph=graph)
-
+        M = ootype.Meth([], ootype.typeOf(oovalue))
+        ll_getclassattr = func_with_new_name(ll_getclassattr,
+                                             'll_get_' + mangled)
+        graph = self.rtyper.annotate_helper(ll_getclassattr, [self.lowleveltype])
+        m = ootype.meth(M, _name=mangled, _callable=ll_getclassattr,
+                        graph=graph)
         ootype.addMethods(self.lowleveltype, {mangled: m})
 
     def get_ll_hash_function(self):
@@ -406,14 +425,21 @@
                 return hop.genop("oosend", [cname, v_inst],
                                  resulttype = hop.r_result.lowleveltype)
         elif attr == '__class__':
-            if hop.r_result.lowleveltype is ootype.Void:
+            expected_type = hop.r_result.lowleveltype
+            if expected_type is ootype.Void:
                 # special case for when the result of '.__class__' is constant
                 [desc] = hop.s_result.descriptions
                 return hop.inputconst(ootype.Void, desc.pyobj)
+            elif expected_type == ootype.Class:
+                return hop.genop('classof', [v_inst],
+                                 resulttype = ootype.Class)
             else:
-                cmeta = inputconst(ootype.Void, "meta")
-                return hop.genop('oogetfield', [v_inst, cmeta],
-                                 resulttype=CLASSTYPE)
+                assert expected_type == META
+                _, meth = v_inst.concretetype._lookup('getmeta')
+                assert meth
+                c_getmeta = hop.inputconst(ootype.Void, 'getmeta')
+                return hop.genop('oosend', [c_getmeta, v_inst],
+                                 resulttype = META)
         else:
             raise TyperError("no attribute %r on %r" % (attr, self))
 
@@ -448,8 +474,7 @@
         if hop.args_s[0].can_be_none():
             return hop.gendirectcall(ll_inst_type, vinst)
         else:
-            cmeta = inputconst(ootype.Void, "meta")
-            return hop.genop('oogetfield', [vinst, cmeta], resulttype=CLASSTYPE)
+            return hop.genop('classof', [vinst], resulttype=ootype.Class)
 
     def null_instance(self):
         return ootype.null(self.lowleveltype)
@@ -465,10 +490,6 @@
         classrepr = getclassrepr(self.rtyper, self.classdef) 
         v_instance =  llops.genop("new",
             [inputconst(ootype.Void, self.lowleveltype)], self.lowleveltype)
-        cmeta = inputconst(ootype.Void, "meta")
-        cmeta_instance = inputconst(CLASSTYPE, classrepr.get_meta_instance())
-        llops.genop("oosetfield", [v_instance, cmeta, cmeta_instance], 
-                  resulttype=ootype.Void)
         return v_instance
         
     def initialize_prebuilt_data(self, value, classdef, result):
@@ -545,7 +566,7 @@
 
 def ll_inst_type(obj):
     if obj:
-        return obj.meta
+        return ootype.classof(obj)
     else:
         # type(None) -> NULL  (for now)
-        return ootype.null(CLASSTYPE)
+        return ootype.nullruntimeclass

Modified: pypy/dist/pypy/rpython/ootypesystem/rootype.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/rootype.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/rootype.py	Thu Jul  3 15:38:13 2008
@@ -32,6 +32,11 @@
 
 class OOClassRepr(Repr):
     lowleveltype = Class
+
+    def rtype_is_true(self, hop):
+        vlist = hop.inputargs(self)
+        return hop.genop('oononnull', vlist, resulttype=ootype.Bool)
+    
 ooclass_repr = OOClassRepr()
 
 class OOInstanceRepr(Repr):

Modified: pypy/dist/pypy/rpython/ootypesystem/rpbc.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/rpbc.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/rpbc.py	Thu Jul  3 15:38:13 2008
@@ -4,11 +4,12 @@
         AbstractFunctionsPBCRepr, AbstractMultipleUnrelatedFrozenPBCRepr, \
         none_frozen_pbc_repr
 from pypy.rpython.rclass import rtype_new_instance, getinstancerepr
+from pypy.rpython.rclass import getclassrepr, get_type_repr
 from pypy.rpython.rpbc import get_concrete_calltable
 from pypy.rpython import callparse
 from pypy.rpython.ootypesystem import ootype
 from pypy.rpython.ootypesystem.rclass import ClassRepr, InstanceRepr 
-from pypy.rpython.ootypesystem.rclass import mangle
+from pypy.rpython.ootypesystem.rclass import mangle, META
 from pypy.annotation import model as annmodel
 from pypy.annotation import description
 from pypy.tool.pairtype import pairtype
@@ -42,17 +43,24 @@
         
 class ClassesPBCRepr(AbstractClassesPBCRepr):
     
-    def _instantiate_runtime_class(self, hop, v_meta, r_instance):
+    def _instantiate_runtime_class(self, hop, v_class, r_instance):
         classdef = hop.s_result.classdef            
-        c_class_ = hop.inputconst(ootype.Void, "class_")
-        v_class = hop.genop('oogetfield', [v_meta, c_class_],
-                resulttype=ootype.Class)
         resulttype = getinstancerepr(hop.rtyper, classdef).lowleveltype
-        v_instance = hop.genop('runtimenew', [v_class], resulttype=resulttype)
-        c_meta = hop.inputconst(ootype.Void, "meta")
-        hop.genop('oosetfield', [v_instance, c_meta, v_meta],
-                resulttype=ootype.Void)
-        return v_instance
+        # convert v_class from META to ootype.Class if necessary:
+        v_class = get_type_repr(hop.rtyper).fromclasstype(v_class, hop.llops)
+        return hop.genop('runtimenew', [v_class], resulttype=resulttype)
+
+    def getlowleveltype(self):
+        classdescs = self.s_pbc.descriptions.keys()
+        # if any of the classdefs get the lowleveltype ootype.Class,
+        # we can only pick ootype.Class for us too.  Otherwise META.
+        for classdesc in classdescs:
+            for classdef in classdesc.getallclassdefs():
+                r_class = getclassrepr(self.rtyper, classdef)
+                if r_class.lowleveltype == ootype.Class:
+                    return ootype.Class
+        else:
+            return META
 
 
 def row_method_name(methodname, rowname):

Modified: pypy/dist/pypy/rpython/rclass.py
==============================================================================
--- pypy/dist/pypy/rpython/rclass.py	(original)
+++ pypy/dist/pypy/rpython/rclass.py	Thu Jul  3 15:38:13 2008
@@ -61,7 +61,8 @@
                 raise TyperError("not a subclass of %r: %r" % (
                     self.classdef.name, desc))
         
-        return getclassrepr(self.rtyper, subclassdef).getruntime()
+        r_subclass = getclassrepr(self.rtyper, subclassdef)
+        return r_subclass.getruntime(self.lowleveltype)
 
     def convert_const(self, value):
         if not isinstance(value, (type, types.ClassType)):

Modified: pypy/dist/pypy/rpython/rpbc.py
==============================================================================
--- pypy/dist/pypy/rpython/rpbc.py	(original)
+++ pypy/dist/pypy/rpython/rpbc.py	Thu Jul  3 15:38:13 2008
@@ -646,7 +646,7 @@
         if s_pbc.is_constant():
             self.lowleveltype = Void
         else:
-            self.lowleveltype = rtyper.type_system.rclass.CLASSTYPE
+            self.lowleveltype = self.getlowleveltype()
 
     def get_access_set(self, attrname):
         """Return the ClassAttrFamily corresponding to accesses to 'attrname'
@@ -669,7 +669,9 @@
             raise TyperError("%r not in %r" % (cls, self))
         if self.lowleveltype is Void:
             return None
-        return rclass.get_type_repr(self.rtyper).convert_desc(desc)
+        subclassdef = desc.getuniqueclassdef()
+        r_subclass = rclass.getclassrepr(self.rtyper, subclassdef)
+        return r_subclass.getruntime(self.lowleveltype)
 
     def convert_const(self, cls):
         if cls is None:
@@ -778,8 +780,6 @@
         if r_clspbc.lowleveltype is Void:
             return inputconst(r_cls, r_clspbc.s_pbc.const)
         # convert from ptr-to-object-vtable to ptr-to-more-precise-vtable
-        assert (r_clspbc.lowleveltype ==
-            r_clspbc.rtyper.type_system.rclass.CLASSTYPE)
         return r_cls.fromclasstype(v, llops)
 
 class __extend__(pairtype(AbstractClassesPBCRepr, AbstractClassesPBCRepr)):

Modified: pypy/dist/pypy/rpython/test/test_normalizecalls.py
==============================================================================
--- pypy/dist/pypy/rpython/test/test_normalizecalls.py	(original)
+++ pypy/dist/pypy/rpython/test/test_normalizecalls.py	Thu Jul  3 15:38:13 2008
@@ -219,6 +219,7 @@
     def test_add_more_subclasses(self):
         from pypy.rpython import rclass
         from pypy.rpython.lltypesystem.rclass import ll_issubclass
+        from pypy.rpython.lltypesystem.rclass import CLASSTYPE
         class Sub3(PBase):
             def newmethod(self):
                 return 3
@@ -232,9 +233,9 @@
             bk = translator.annotator.bookkeeper
             rtyper = translator.rtyper
             base_classdef = bk.getuniqueclassdef(PBase)
-            base_vtable = rclass.getclassrepr(rtyper, base_classdef).getruntime()
+            base_vtable = rclass.getclassrepr(rtyper, base_classdef).getruntime(CLASSTYPE)
             sub3_classdef = bk.getuniqueclassdef(Sub3)
-            sub3_vtable = rclass.getclassrepr(rtyper, sub3_classdef).getruntime()
+            sub3_vtable = rclass.getclassrepr(rtyper, sub3_classdef).getruntime(CLASSTYPE)
             assert ll_issubclass(sub3_vtable, base_vtable)
             assert not ll_issubclass(base_vtable, sub3_vtable)
 

Modified: pypy/dist/pypy/rpython/test/test_rbuiltin.py
==============================================================================
--- pypy/dist/pypy/rpython/test/test_rbuiltin.py	(original)
+++ pypy/dist/pypy/rpython/test/test_rbuiltin.py	Thu Jul  3 15:38:13 2008
@@ -530,24 +530,19 @@
         
 class TestOOtype(BaseTestRbuiltin, OORtypeMixin):
 
-    def test_instantiate_meta(self):
-        class A:
-            pass
-        def f():
-            return instantiate(A)
-        res = self.interpret(f, [])
-        assert res.meta # check that it's not null
-
     def test_instantiate_multiple_meta(self):
         class A:
-            pass
+            x = 2
         class B(A):
-            pass
+            x = 3
+        def do_stuff(cls):
+            return cls.x
         def f(i):
             if i == 1:
                 cls = A
             else:
                 cls = B
+            do_stuff(cls)
             return instantiate(cls)
         res = self.interpret(f, [1])
-        assert res.meta # check that it's not null
+        assert res.getmeta() # check that it exists

Modified: pypy/dist/pypy/rpython/test/test_rclass.py
==============================================================================
--- pypy/dist/pypy/rpython/test/test_rclass.py	(original)
+++ pypy/dist/pypy/rpython/test/test_rclass.py	Thu Jul  3 15:38:13 2008
@@ -97,16 +97,31 @@
         assert res == 4
 
     def test_runtime_exception(self):
+        class MyExc(Exception):
+            pass
+        class Sub1(MyExc):
+            pass
+        class Sub2(MyExc):
+            pass
         def pick(flag):
             if flag:
-                return TypeError
+                return Sub1
             else:
-                return ValueError
-        def f(flag):
+                return Sub2
+        def g(flag):
             ex = pick(flag)
             raise ex()
-        self.interpret_raises(TypeError, f, [True])
-        self.interpret_raises(ValueError, f, [False])
+        def f(flag):
+            try:
+                g(flag)
+            except Sub1:
+                return 1
+            except Sub2:
+                return 2
+            else:
+                return 3
+        assert self.interpret(f, [True]) == 1
+        assert self.interpret(f, [False]) == 2
 
     def test_classattr_as_defaults(self):
         def dummyfn():
@@ -815,8 +830,8 @@
         t.buildrtyper(type_system=self.type_system).specialize()
         graph = graphof(t, f)
         TYPEA = graph.startblock.operations[0].args[0].value
-        TYPEB = graph.startblock.operations[2].args[0].value
-        TYPEC = graph.startblock.operations[4].args[0].value
+        TYPEB = graph.startblock.operations[1].args[0].value
+        TYPEC = graph.startblock.operations[2].args[0].value
         _, destra = TYPEA._lookup("o__del__")
         _, destrb = TYPEB._lookup("o__del__")
         _, destrc = TYPEC._lookup("o__del__")

Modified: pypy/dist/pypy/translator/backendopt/inline.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/inline.py	(original)
+++ pypy/dist/pypy/translator/backendopt/inline.py	Thu Jul  3 15:38:13 2008
@@ -378,7 +378,8 @@
         # this rewiring does not always succeed. in the cases where it doesn't
         # there will be generic code inserted
         rclass = self.translator.rtyper.type_system.rclass
-        exc_match = self.translator.rtyper.getexceptiondata().fn_exception_match
+        excdata = self.translator.rtyper.getexceptiondata()
+        exc_match = excdata.fn_exception_match
         for link in self.entrymap[self.graph_to_inline.exceptblock]:
             copiedblock = self.copy_block(link.prevblock)
             VALUE, copiedlink = _find_exception_type(copiedblock)
@@ -388,7 +389,7 @@
             classdef = self.lltype_to_classdef[VALUE]
             rtyper = self.translator.rtyper
             classrepr = rclass.getclassrepr(rtyper, classdef)
-            vtable = classrepr.getruntime()
+            vtable = classrepr.getruntime(excdata.lltype_of_exception_type)
             var_etype = copiedlink.args[0]
             var_evalue = copiedlink.args[1]
             for exceptionlink in afterblock.exits[1:]:

Modified: pypy/dist/pypy/translator/cli/database.py
==============================================================================
--- pypy/dist/pypy/translator/cli/database.py	(original)
+++ pypy/dist/pypy/translator/cli/database.py	Thu Jul  3 15:38:13 2008
@@ -7,9 +7,9 @@
 from pypy.translator.cli.comparer import EqualityComparer
 from pypy.translator.cli.node import Node
 from pypy.translator.cli.support import string_literal, Counter
+from pypy.translator.cli.cts import types
 from pypy.rpython.ootypesystem import ootype
 from pypy.rpython.ootypesystem.module import ll_os
-from pypy.translator.cli.opcodes import opcodes
 from pypy.translator.cli import dotnet
 from pypy.rlib.objectmodel import CDefinedIntSymbolic
 from pypy.translator.oosupport.database import Database as OODatabase
@@ -130,6 +130,8 @@
         return name
 
     def class_name(self, INSTANCE):
+        if INSTANCE is ootype.ROOT:
+            return types.object.classname()
         try:
             NATIVE_INSTANCE = INSTANCE._hints['NATIVE_INSTANCE']
             return NATIVE_INSTANCE._name

Modified: pypy/dist/pypy/translator/cli/function.py
==============================================================================
--- pypy/dist/pypy/translator/cli/function.py	(original)
+++ pypy/dist/pypy/translator/cli/function.py	Thu Jul  3 15:38:13 2008
@@ -39,7 +39,7 @@
 
     def record_ll_meta_exc(self, ll_meta_exc):
         # record the type only if it doesn't belong to a native_class
-        ll_exc = ll_meta_exc._inst.class_._INSTANCE
+        ll_exc = ll_meta_exc._INSTANCE
         NATIVE_INSTANCE = ll_exc._hints.get('NATIVE_INSTANCE', None)
         if NATIVE_INSTANCE is None:
             OOFunction.record_ll_meta_exc(self, ll_meta_exc)
@@ -107,7 +107,7 @@
 
     def begin_catch(self, llexitcase):
         ll_meta_exc = llexitcase
-        ll_exc = ll_meta_exc._inst.class_._INSTANCE
+        ll_exc = ll_meta_exc._INSTANCE
         cts_exc = self.cts.lltype_to_cts(ll_exc)
         self.ilasm.begin_catch(cts_exc.classname())
 
@@ -131,7 +131,7 @@
             if isinstance(link.last_exception, flowmodel.Variable):
                 self.ilasm.opcode('dup')
                 self.store(link.last_exc_value)
-                self.ilasm.get_field(('class Object_meta', 'Object', 'meta'))
+                self.ilasm.call_method('[mscorlib]System.Type object::GetType()', virtual=True)
                 self.store(link.last_exception)
             else:
                 self.store(link.last_exc_value)

Modified: pypy/dist/pypy/translator/cli/opcodes.py
==============================================================================
--- pypy/dist/pypy/translator/cli/opcodes.py	(original)
+++ pypy/dist/pypy/translator/cli/opcodes.py	Thu Jul  3 15:38:13 2008
@@ -49,6 +49,7 @@
     'cli_fieldinfo_for_const':  [FieldInfoForConst],
     'oois':                     'ceq',
     'oononnull':                [PushAllArgs, 'ldnull', 'ceq']+Not,
+    'classof':                  [PushAllArgs, 'callvirt instance [mscorlib]System.Type object::GetType()'],
     'instanceof':               [CastTo, 'ldnull', 'cgt.un'],
     'subclassof':               [PushAllArgs, 'call bool [pypylib]pypy.runtime.Utils::SubclassOf(class [mscorlib]System.Type, class[mscorlib]System.Type)'],
     'ooidentityhash':           [PushAllArgs, 'callvirt instance int32 object::GetHashCode()'],

Modified: pypy/dist/pypy/translator/cli/test/runtest.py
==============================================================================
--- pypy/dist/pypy/translator/cli/test/runtest.py	(original)
+++ pypy/dist/pypy/translator/cli/test/runtest.py	Thu Jul  3 15:38:13 2008
@@ -99,7 +99,7 @@
             if hasattr(self.db, 'exceptiontransformer'):
                 ilasm.opcode('call', 'bool rpyexc_occured()')
                 ilasm.opcode('brfalse', 'print_result') # no exceptions
-                ilasm.opcode('call', 'Object rpyexc_fetch_value()')
+                ilasm.opcode('call', '[mscorlib]System.Object rpyexc_fetch_value()')
                 ilasm.call('string class [pypylib]pypy.test.Result::FormatException(object)')
                 ilasm.call('void class [mscorlib]System.Console::WriteLine(string)')
                 ilasm.opcode('br', 'return')
@@ -282,15 +282,22 @@
     def _skip_llinterpreter(self, reason, skipLL=True, skipOO=True):
         pass
 
-    def interpret(self, fn, args, annotation=None, backendopt=True, exctrans=False):
+    def _get_backendopt(self, backendopt):
+        if backendopt is None:
+            backendopt = getattr(self, 'backendopt', True) # enable it by default
+        return backendopt
+    
+    def interpret(self, fn, args, annotation=None, backendopt=None, exctrans=False):
+        backendopt = self._get_backendopt(backendopt)
         f = self._compile(fn, args, annotation, backendopt=backendopt, exctrans=exctrans)
         res = f(*args)
         if isinstance(res, ExceptionWrapper):
             raise res
         return res
 
-    def interpret_raises(self, exception, fn, args, backendopt=True, exctrans=False):
+    def interpret_raises(self, exception, fn, args, backendopt=None, exctrans=False):
         import exceptions # needed by eval
+        backendopt = self._get_backendopt(backendopt)
         try:
             self.interpret(fn, args, backendopt=backendopt, exctrans=exctrans)
         except ExceptionWrapper, ex:

Modified: pypy/dist/pypy/translator/cli/test/test_exception.py
==============================================================================
--- pypy/dist/pypy/translator/cli/test/test_exception.py	(original)
+++ pypy/dist/pypy/translator/cli/test/test_exception.py	Thu Jul  3 15:38:13 2008
@@ -1,81 +1,22 @@
 import py
 from pypy.translator.cli.test.runtest import CliTest
-from pypy.rpython.test.test_exception import BaseTestException
+from pypy.translator.oosupport.test_template.exception import BaseTestException
 
 class TestCliException(CliTest, BaseTestException):
     use_exception_transformer = False
+    backendopt = False
 
     def interpret(self, *args, **kwds):
         kwds['exctrans'] = self.use_exception_transformer
         return CliTest.interpret(self, *args, **kwds)
 
-    def test_nested_try(self):
-        def helper(x):
-            if x == 0:
-                raise ValueError
-        def dummy():
-            pass        
-        def fn(x):
-            try:
-                try:
-                    helper(x)
-                finally:
-                    dummy()
-            except ValueError, e:
-                 raise
-        
-        self.interpret_raises(ValueError, fn, [0])
-
-    def test_exception_not_last(self):
-        def helper(x):
-            if x == 0:
-                raise ValueError
-        def fn(x):
-            helper(x)
-            try:
-                helper(1)
-            finally:
-                return -1
-            return x
-        self.interpret_raises(ValueError, fn, [0])
-
     def test_raise_and_catch_other(self):
         pass
 
     def test_raise_prebuilt_and_catch_other(self):
         pass
 
-    def test_missing_return_block(self):
-        class Base:
-            def foo(self):
-                raise ValueError
-
-        class Derived(Base):
-            def foo(self):
-                return 42
-
-        def fn(x):
-            if x:
-                obj = Base()
-            else:
-                obj = Derived()
-            return obj.foo()
-        assert self.interpret(fn, [0]) == 42
-
-    def test_missing_handler(self):
-        def foo(x):
-            if x:
-                raise ValueError
-        
-        def fn(x):
-            try:
-                foo(x)
-            except ValueError:
-                raise
-            return 42
-        assert self.interpret(fn, [0], backendopt=False) == 42
-        self.interpret_raises(ValueError, fn, [1], backendopt=False)
-
 
 class TestCliExceptionTransformer(TestCliException):
     use_exception_transformer = True
+    backendopt = False

Modified: pypy/dist/pypy/translator/jvm/database.py
==============================================================================
--- pypy/dist/pypy/translator/jvm/database.py	(original)
+++ pypy/dist/pypy/translator/jvm/database.py	Thu Jul  3 15:38:13 2008
@@ -40,11 +40,11 @@
 
         self._constants = {}      # flowmodel.Variable --> jvm.Const
 
-        # Special fields for the Object class, see _translate_Object
-        self._object_interf = None
-        self._object_impl = None
-        self._object_exc_impl = None
-
+#        # Special fields for the Object class, see _translate_Object
+#        self._object_interf = None
+#        self._object_impl = None
+#        self._object_exc_impl = None
+#
         # Create information about the Main class we will build:
         #
         #    It will have two static fields, 'ilink' and 'pypy'.  The
@@ -182,67 +182,6 @@
         self.pending_node(clsobj)
         return clsobj
 
-    def _translate_Object(self, OBJ):
-        """
-        We handle the class 'Object' quite specially: we translate it
-        into an interface with two implementations.  One
-        implementation serves as the root of most objects, and the
-        other as the root for all exceptions.
-        """
-        assert self.is_Object(OBJ)
-        assert OBJ._superclass == ootype.ROOT
-
-        # Have we already translated Object?
-        if self._object_interf: return self._object_interf
-
-        # Create the interface and two implementations:
-        def gen_name(): return self._pkg(self._uniq(OBJ._name))
-        internm, implnm, exc_implnm = gen_name(), gen_name(), gen_name()
-        self._object_interf = node.Interface(internm)
-        self._object_impl = node.Class(implnm, supercls=jvm.jObject)
-        self._object_exc_impl = node.Class(exc_implnm, supercls=jvm.jThrowable)
-        self._object_impl.add_interface(self._object_interf)
-        self._object_exc_impl.add_interface(self._object_interf)
-
-        # Translate the fields into properties on the interface,
-        # and into actual fields on the implementations.
-        for fieldnm, (FIELDOOTY, fielddef) in OBJ._fields.iteritems():
-            if FIELDOOTY is ootype.Void: continue
-            fieldty = self.lltype_to_cts(FIELDOOTY)
-
-            # Currently use hacky convention of _jvm_FieldName for the name
-            methodnm = "_jvm_"+fieldnm
-
-            def getter_method_obj(node):
-                return jvm.Method.v(node, methodnm+"_g", [], fieldty)
-            def putter_method_obj(node):
-                return jvm.Method.v(node, methodnm+"_p", [fieldty], jvm.jVoid)
-            
-            # Add get/put methods to the interface:
-            prop = jvm.Property(
-                fieldnm, 
-                getter_method_obj(self._object_interf),
-                putter_method_obj(self._object_interf),
-                OOTYPE=FIELDOOTY)
-            self._object_interf.add_property(prop)
-
-            # Generate implementations:
-            def generate_impl(clsobj):
-                clsnm = clsobj.name
-                fieldobj = jvm.Field(clsnm, fieldnm, fieldty, False, FIELDOOTY)
-                clsobj.add_field(fieldobj, fielddef)
-                clsobj.add_method(node.GetterFunction(
-                    self, clsobj, getter_method_obj(clsobj), fieldobj))
-                clsobj.add_method(node.PutterFunction(
-                    self, clsobj, putter_method_obj(clsobj), fieldobj))
-            generate_impl(self._object_impl)
-            generate_impl(self._object_exc_impl)
-
-        # Ensure that we generate all three classes.
-        self.pending_node(self._object_interf)
-        self.pending_node(self._object_impl)
-        self.pending_node(self._object_exc_impl)
-
     def _translate_superclass_of(self, OOSUB):
         """
         Invoked to translate OOSUB's super class.  Normally just invokes
@@ -250,12 +189,9 @@
         make all exceptions descend from Throwable.
         """
         OOSUPER = OOSUB._superclass
-        if not self.is_Object(OOSUPER):
-            return self.pending_class(OOSUPER)
-        self._translate_Object(OOSUPER)          # ensure this has been done
         if OOSUB._name == "exceptions.Exception":
-            return self._object_exc_impl
-        return self._object_impl        
+            return jvm.jPyPyThrowable
+        return self.pending_class(OOSUPER)
 
     def _translate_instance(self, OOTYPE):
         assert isinstance(OOTYPE, ootype.Instance)
@@ -564,15 +500,6 @@
         TP = annotation_to_lltype(s_tp)
         return self.lltype_to_cts(TP)
 
-    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/node.py
==============================================================================
--- pypy/dist/pypy/translator/jvm/node.py	(original)
+++ pypy/dist/pypy/translator/jvm/node.py	Thu Jul  3 15:38:13 2008
@@ -22,7 +22,8 @@
 from pypy.translator.jvm.typesystem import \
      JvmGeneratedClassType, jString, jStringArray, jVoid, jThrowable, jInt, \
      jObject, JvmType, jStringBuilder, jPyPyInterlink, jCallbackInterfaces, \
-     JvmGeneratedInterfaceType, jPyPy, jPyPyAbstractMethodException
+     JvmGeneratedInterfaceType, jPyPy, jPyPyAbstractMethodException, \
+     jPyPyThrowable, OBJECTGETCLASS
 from pypy.translator.jvm.opcodes import \
      opcodes
 from pypy.translator.jvm.option import \
@@ -173,8 +174,7 @@
             gen.goto(done_printing)
             gen.end_try()
 
-            jexc = self.db.exception_root_object()
-            gen.begin_catch(jexc)
+            gen.begin_catch(jPyPyThrowable)
             gen.emit(jvm.PYPYDUMPEXCWRAPPER) # dumps to stdout
             gen.end_catch()
 
@@ -366,7 +366,7 @@
 
     def begin_catch(self, llexitcase):
         ll_meta_exc = llexitcase
-        ll_exc = ll_meta_exc._inst.class_._INSTANCE
+        ll_exc = ll_meta_exc._INSTANCE
         jtype = self.cts.lltype_to_cts(ll_exc)
         assert jtype.throwable # SHOULD only try to catch subtypes of Exception
         self.ilasm.begin_catch(jtype)
@@ -384,10 +384,11 @@
         else:
             # the exception value is on the stack, store it in the proper place
             if isinstance(link.last_exception, flowmodel.Variable):
-                self.ilasm.emit(jvm.DUP)
+                # if the code that follows is interested in the class
+                # of the exception, extract it
+                self.ilasm.dup_jtype(jPyPyThrowable)
                 self.ilasm.store(link.last_exc_value)
-                fld = self.db.lltype_to_cts(rclass.OBJECT).lookup_field('meta')
-                self.ilasm.emit(fld)
+                self.ilasm.emit(OBJECTGETCLASS)
                 self.ilasm.store(link.last_exception)
             else:
                 self.ilasm.store(link.last_exc_value)
@@ -450,8 +451,15 @@
                 can_branch_directly(last_op.opname) and
                 not_in_link_args(block.exitswitch)):
 
+                self.generator.add_comment(
+                    "short-circuit final comparison on %s, block has %d ops" % (
+                    block.exitswitch, len(block.operations)))
+
                 for op in block.operations[:-1]:
                     self._render_op(op)
+                    
+                self.generator.add_comment(
+                    "inlining comparison: %r" % (last_op),)
                 for arg in last_op.args:
                     self.ilasm.load(arg)
                 truelink, falselink = true_false_exits()
@@ -503,12 +511,12 @@
         self.ilasm.load(exc)
 
         # Check whether the static type is known to be throwable.
-        # If not, emit a CHECKCAST to the base exception type.
+        # If not, emit a CHECKCAST to throwable.
         # 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.downcast_jtype(jThrowable)
             
         self.ilasm.throw()
 

Modified: pypy/dist/pypy/translator/jvm/opcodes.py
==============================================================================
--- pypy/dist/pypy/translator/jvm/opcodes.py	(original)
+++ pypy/dist/pypy/translator/jvm/opcodes.py	Thu Jul  3 15:38:13 2008
@@ -79,6 +79,7 @@
     'oodowncast':               [DownCast, StoreResult],
     'instanceof':               [CastTo, StoreResult],
     'subclassof':               [PushAllArgs, jvm.SWAP, jvm.CLASSISASSIGNABLEFROM, StoreResult],
+    'classof':                  [PushAllArgs, jvm.OBJECTGETCLASS, StoreResult],
     'ooidentityhash':           [PushAllArgs, jvm.OBJHASHCODE, StoreResult], 
     'oohash':                   [PushAllArgs, jvm.OBJHASHCODE, StoreResult], 
     'oostring':                 [OOString, StoreResult],

Modified: pypy/dist/pypy/translator/jvm/test/test_exception.py
==============================================================================
--- pypy/dist/pypy/translator/jvm/test/test_exception.py	(original)
+++ pypy/dist/pypy/translator/jvm/test/test_exception.py	Thu Jul  3 15:38:13 2008
@@ -1,57 +1,11 @@
 import py
 from pypy.translator.jvm.test.runtest import JvmTest
-from pypy.rpython.test.test_exception import BaseTestException
+from pypy.translator.oosupport.test_template.exception import BaseTestException
 
 class TestJvmException(JvmTest, BaseTestException):
-    def test_nested_try(self):
-        def helper(x):
-            if x == 0:
-                raise ValueError
-        def dummy():
-            pass        
-        def fn(x):
-            try:
-                try:
-                    helper(x)
-                finally:
-                    dummy()
-            except ValueError, e:
-                 raise
-        
-        self.interpret_raises(ValueError, fn, [0])
-
-    def test_exception_not_last(self):
-        def helper(x):
-            if x == 0:
-                raise ValueError
-        def fn(x):
-            helper(x)
-            try:
-                helper(1)
-            finally:
-                return -1
-            return x
-        self.interpret_raises(ValueError, fn, [0])
 
     def test_raise_and_catch_other(self):
         pass
 
     def test_raise_prebuilt_and_catch_other(self):
         pass
-
-    def test_missing_return_block(self):
-        class Base:
-            def foo(self):
-                raise ValueError
-
-        class Derived(Base):
-            def foo(self):
-                return 42
-
-        def fn(x):
-            if x:
-                obj = Base()
-            else:
-                obj = Derived()
-            return obj.foo()
-        assert self.interpret(fn, [0]) == 42

Modified: pypy/dist/pypy/translator/jvm/typesystem.py
==============================================================================
--- pypy/dist/pypy/translator/jvm/typesystem.py	(original)
+++ pypy/dist/pypy/translator/jvm/typesystem.py	Thu Jul  3 15:38:13 2008
@@ -186,6 +186,7 @@
 jCharClass = JvmClassType('java.lang.Character')
 jBoolClass = JvmClassType('java.lang.Boolean')
 jThrowable = JvmClassType('java.lang.Throwable', throwable=True)
+jPyPyThrowable = JvmClassType('pypy.PyPyThrowable', throwable=True)
 jObject = JvmClassType('java.lang.Object')
 jString = JvmClassType('java.lang.String')
 jCharSequence = JvmClassType('java.lang.CharSequence')



More information about the Pypy-commit mailing list