[pypy-svn] r34349 - in pypy/dist/pypy/translator: cli jvm oosupport

niko at codespeak.net niko at codespeak.net
Tue Nov 7 22:24:22 CET 2006


Author: niko
Date: Tue Nov  7 22:24:19 2006
New Revision: 34349

Added:
   pypy/dist/pypy/translator/cli/constant.py
Removed:
   pypy/dist/pypy/translator/cli/constgenerator.py
Modified:
   pypy/dist/pypy/translator/cli/class_.py
   pypy/dist/pypy/translator/cli/database.py
   pypy/dist/pypy/translator/cli/function.py
   pypy/dist/pypy/translator/cli/gencli.py
   pypy/dist/pypy/translator/cli/ilgenerator.py
   pypy/dist/pypy/translator/jvm/constant.py
   pypy/dist/pypy/translator/jvm/database.py
   pypy/dist/pypy/translator/jvm/genjvm.py
   pypy/dist/pypy/translator/oosupport/constant.py
   pypy/dist/pypy/translator/oosupport/database.py
   pypy/dist/pypy/translator/oosupport/function.py
   pypy/dist/pypy/translator/oosupport/genoo.py
Log:
Next iteration of unified JVM/CLI constant support.  In this version,
the CLI code uses the same constant code as JVM, but the CLI has its
own version of the methods which generate bytecode.  Final iteration is
to remove those methods by implementing them generically in oosupport and
implementing the required methods in the "metavm" generator interface.
Towards that end, this check-in also includes a "CLIBaseGenerator" class
that includes most of the metavm generator implementation, but not those
parts that are specific to a particular function (like loading a variable).

All tests continue to pass in CLI and JS on my machine.



Modified: pypy/dist/pypy/translator/cli/class_.py
==============================================================================
--- pypy/dist/pypy/translator/cli/class_.py	(original)
+++ pypy/dist/pypy/translator/cli/class_.py	Tue Nov  7 22:24:19 2006
@@ -1,6 +1,8 @@
 from pypy.rpython.ootypesystem import ootype
 from pypy.translator.cli.node import Node
 from pypy.translator.cli.cts import CTS
+from pypy.translator.oosupport.constant import push_constant
+from pypy.translator.cli.ilgenerator import CLIBaseGenerator
 
 try:
     set
@@ -73,6 +75,8 @@
             return
 
         self.ilasm = ilasm
+
+        gen = CLIBaseGenerator(self.db, ilasm)
         if self.namespace:
             ilasm.begin_namespace(self.namespace)
 
@@ -109,8 +113,7 @@
                 if isinstance(METH.RESULT, ootype.OOType):
                     ilasm.opcode('ldnull')
                 else:
-                    from pypy.translator.cli.database import AbstractConst
-                    AbstractConst.load(self.db, METH.RESULT, 0, ilasm)
+                    push_constant(self.db, METH.RESULT, 0, gen)
                 ilasm.opcode('ret')
                 ilasm.end_function()
 
@@ -120,7 +123,6 @@
             ilasm.end_namespace()
 
     def _ctor(self):
-        from pypy.translator.cli.database import AbstractConst
         self.ilasm.begin_function('.ctor', [], 'void', False, 'specialname', 'rtspecialname', 'instance')
         self.ilasm.opcode('ldarg.0')
         self.ilasm.call('instance void %s::.ctor()' % self.get_base_class())
@@ -130,7 +132,7 @@
             f_name = self.cts.escape_name(f_name)
             if cts_type != 'void':
                 self.ilasm.opcode('ldarg.0')
-                AbstractConst.load(self.db, F_TYPE, f_default, self.ilasm)
+                push_constant(self.db, F_TYPE, f_default, self)
                 class_name = self.db.class_name(self.INSTANCE)
                 self.ilasm.set_field((cts_type, class_name, f_name))
 

Added: pypy/dist/pypy/translator/cli/constant.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/cli/constant.py	Tue Nov  7 22:24:19 2006
@@ -0,0 +1,616 @@
+"""
+___________________________________________________________________________
+CLI Constants
+
+This module extends the oosupport/constant.py to be specific to the
+CLI.
+
+Currently, it is not terribly well integrated with the constant
+framework.  In particular, each kind of constant overloads the
+create_pointer() and initialize_data() methods with some CLI-specific
+stuff, rather than implementing the more general generator interface.
+This allowed me to cut and paste from the old CLI code, but should
+eventually be changed.  I have included some commented routines
+showing how the code should eventually look.
+
+The CLI implementation is broken into three sections:
+
+* Constant Generators: different generators implementing different
+  techniques for loading constants (Static fields, singleton fields, etc)
+
+* Mixins: mixins are used to add a few CLI-specific methods to each
+  constant class.  Basically, any time I wanted to extend a base class
+  (such as AbstractConst or DictConst), I created a mixin, and then
+  mixed it in to each sub-class of that base-class.
+
+* Subclasses: here are the CLI specific classes.  Eventually, these
+  probably wouldn't need to exist at all (the JVM doesn't have any,
+  for example), or could simply have empty bodies and exist to
+  combine a mixin and the generic base class.  For now, though, they
+  contain the create_pointer() and initialize_data() routines.
+"""
+
+from pypy.translator.oosupport.constant import \
+     push_constant, WeakRefConst, StaticMethodConst, CustomDictConst, \
+     ListConst, ClassConst, InstanceConst, RecordConst, DictConst, \
+     BaseConstantGenerator
+from pypy.translator.cli.support import string_literal
+from pypy.rpython.ootypesystem import ootype
+from pypy.rlib.objectmodel import CDefinedIntSymbolic
+from pypy.translator.cli.comparer import EqualityComparer
+from pypy.rpython.lltypesystem import lltype
+from pypy.translator.cli.cts import PYPY_DICT_OF_VOID, WEAKREF
+
+CONST_NAMESPACE = 'pypy.runtime'
+CONST_CLASSNAME = 'Constants'
+CONST_CLASS = '%s.%s' % (CONST_NAMESPACE, CONST_CLASSNAME)
+
+DEBUG_CONST_INIT = False
+DEBUG_CONST_INIT_VERBOSE = False
+MAX_CONST_PER_STEP = 100
+SERIALIZE = False
+
+DEFINED_INT_SYMBOLICS = {'MALLOC_ZERO_FILLED':1}
+
+def isnan(v):
+        return v != v*1.0 or (v == 1.0 and v == 2.0)
+
+def isinf(v):
+    return v!=0 and (v == v*2)
+
+# ______________________________________________________________________
+# MetaVM Generator interface
+
+class CLIGeneratorForConstants(object):
+
+    ''' Very minimal "implementation" of oosupport.metavm.Generator
+    interface.  Just what is actually used. '''
+    
+    def __init__(self, ilasm):
+        self.ilasm = ilasm
+        
+    def add_section(self, text):
+        return
+    
+    def add_comment(self, text):
+        return
+    
+    def pop(self, OOTYPE):
+        self.ilasm.pop()
+
+# ______________________________________________________________________
+# Constant Generators
+#
+# Different generators implementing different techniques for loading
+# constants (Static fields, singleton fields, etc)
+
+class CLIBaseConstGenerator(BaseConstantGenerator):
+    """
+    Base of all CLI constant generators.  It implements the oosupport
+    constant generator in terms of the CLI interface.
+    """
+
+    def __init__(self, db):
+        BaseConstantGenerator.__init__(self, db)
+        self.cts = db.genoo.TypeSystem(db)
+
+    def _begin_gen_constants(self, ilasm, all_constants):
+        self.ilasm = ilasm
+        self.begin_class()
+        gen = CLIGeneratorForConstants(ilasm)
+        return gen
+
+    def _end_gen_constants(self, gen, numsteps):
+        assert gen.ilasm is self.ilasm
+        self.end_class()
+
+    def begin_class(self):
+        self.ilasm.begin_namespace(CONST_NAMESPACE)
+        self.ilasm.begin_class(CONST_CLASSNAME, beforefieldinit=True)
+
+    def end_class(self):
+        self.ilasm.end_class()
+        self.ilasm.end_namespace()
+
+    def _declare_const(self, gen, const):
+        self.ilasm.field(const.name, const.get_type(), static=True)
+
+    def push_primitive_constant(self, gen, TYPE, value):
+        ilasm = gen.ilasm
+        if TYPE is ootype.Void:
+            pass
+        elif TYPE is ootype.Bool:
+            ilasm.opcode('ldc.i4', str(int(value)))
+        elif TYPE is ootype.Char or TYPE is ootype.UniChar:
+            ilasm.opcode('ldc.i4', ord(value))
+        elif TYPE is ootype.Float:
+            if isinf(value):
+                ilasm.opcode('ldc.r8', '(00 00 00 00 00 00 f0 7f)')
+            elif isnan(value):
+                ilasm.opcode('ldc.r8', '(00 00 00 00 00 00 f8 ff)')
+            else:
+                ilasm.opcode('ldc.r8', repr(value))
+        elif isinstance(value, CDefinedIntSymbolic):
+            ilasm.opcode('ldc.i4', DEFINED_INT_SYMBOLICS[value.expr])
+        elif TYPE in (ootype.Signed, ootype.Unsigned):
+            ilasm.opcode('ldc.i4', str(value))
+        elif TYPE in (ootype.SignedLongLong, ootype.UnsignedLongLong):
+            ilasm.opcode('ldc.i8', str(value))
+        elif TYPE is ootype.String:
+            if value._str is None:
+                ilasm.opcode('ldnull')
+            else:
+                ilasm.opcode("ldstr", string_literal(value._str))
+        else:
+            assert False, "Unexpected constant type"
+
+    def downcast_constant(self, gen, const, EXPECTED_TYPE):
+        type = self.cts.lltype_to_cts(EXPECTED_TYPE)
+        gen.ilasm.opcode('castclass', type)
+
+class FieldConstGenerator(CLIBaseConstGenerator):
+    pass
+
+class StaticFieldConstGenerator(FieldConstGenerator):
+
+    # _________________________________________________________________
+    # OOSupport interface
+    
+    def push_constant(self, gen, const):
+        type_ = const.get_type()
+        gen.ilasm.load_static_constant(type_, CONST_NAMESPACE, CONST_CLASSNAME, const.name)
+        
+    def _push_constant_during_init(self, gen, const):
+        full_name = '%s::%s' % (CONST_CLASS, const.name)
+        gen.ilasm.opcode('ldsfld %s %s' % (const.get_type(), full_name))
+
+    def _store_constant(self, gen, const):
+        type_ = const.get_type()
+        gen.ilasm.store_static_constant(type_, CONST_NAMESPACE, CONST_CLASSNAME, const.name)
+
+    # _________________________________________________________________
+    # CLI interface
+
+    def _declare_step(self, gen, stepnum):
+        gen.ilasm.begin_function(
+            'step%d' % stepnum, [], 'void', False, 'static')
+
+    def _close_step(self, gen, stepnum):
+        gen.ilasm.ret()
+        gen.ilasm.end_function()
+
+    def _end_gen_constants(self, gen, numsteps):
+
+        self.ilasm.begin_function('.cctor', [], 'void', False, 'static',
+                                  'specialname', 'rtspecialname', 'default')
+        self.ilasm.stderr('CONST: initialization starts', DEBUG_CONST_INIT)
+        for i in range(numsteps):
+            self.ilasm.stderr('CONST: step %d of %d' % (i, numsteps),
+                              DEBUG_CONST_INIT)
+            step_name = 'step%d' % i
+            self.ilasm.call('void %s::%s()' % (CONST_CLASS, step_name))
+        self.ilasm.stderr('CONST: initialization completed', DEBUG_CONST_INIT)
+        self.ilasm.ret()
+        self.ilasm.end_function()
+
+        super(StaticFieldConstGenerator, self)._end_gen_constants(
+            gen, numsteps)
+
+class InstanceFieldConstGenerator(FieldConstGenerator):
+    
+    # _________________________________________________________________
+    # OOSupport interface
+    
+    def push_constant(self, gen, const):
+        # load the singleton instance
+        gen.ilasm.opcode('ldsfld class %s %s::Singleton' % (CONST_CLASS, CONST_CLASS))
+        gen.ilasm.opcode('ldfld %s %s::%s' % (const.get_type(), CONST_CLASS, const.name))
+
+    def _push_constant_during_init(self, gen, const):
+        # during initialization, we load the 'this' pointer from our
+        # argument rather than the singleton argument
+        gen.ilasm.opcode('ldarg.0')
+        gen.ilasm.opcode('ldfld %s %s::%s' % (const.get_type(), CONST_CLASS, const.name))
+
+    def _pre_store_constant(self, gen, const):
+        gen.ilasm.opcode('ldarg.0')
+        
+    def _store_constant(self, gen, const):
+        gen.ilasm.set_field((const.get_type(), CONST_CLASS, const.name))
+
+    # _________________________________________________________________
+    # CLI interface
+
+    def _declare_const(self, gen, all_constants):
+        gen.ilasm.field(const.name, const.get_type(), static=False)
+    
+    def _declare_step(self, gen, stepnum):
+        gen.ilasm.begin_function('step%d' % stepnum, [], 'void', False)
+
+    def _close_step(self, gen, stepnum):
+        gen.ilasm.ret()
+        gen.ilasm.end_function()
+
+    def _end_gen_constants(self, gen, numsteps):
+
+        ilasm = gen.ilasm
+
+        ilasm.begin_function('.ctor', [], 'void', False, 'specialname', 'rtspecialname', 'instance')
+        ilasm.opcode('ldarg.0')
+        ilasm.call('instance void object::.ctor()')
+
+        ilasm.opcode('ldarg.0')
+        ilasm.opcode('stsfld class %s %s::Singleton' % (CONST_CLASS, CONST_CLASS))
+        
+        for i in range(numsteps):
+            step_name = 'step%d' % i
+            ilasm.opcode('ldarg.0')
+            ilasm.call('instance void %s::%s()' % (CONST_CLASS, step_name))
+        ilasm.ret()
+        ilasm.end_function()
+
+        # declare&init the Singleton containing the constants
+        ilasm.field('Singleton', 'class %s' % CONST_CLASS, static=True)
+        ilasm.begin_function('.cctor', [], 'void', False, 'static', 'specialname', 'rtspecialname', 'default')
+        if SERIALIZE:
+            self._serialize_ctor()
+        else:
+            self._plain_ctor()
+        ilasm.end_function()
+
+        super(StaticFieldConstGenerator, self)._end_gen_constants(gen, numsteps)
+
+    def _plain_ctor(self):
+        self.ilasm.new('instance void class %s::.ctor()' % CONST_CLASS)
+        self.ilasm.pop()
+        self.ilasm.ret()
+
+    def _serialize_ctor(self):
+        self.ilasm.opcode('ldstr "constants.dat"')
+        self.ilasm.call('object [pypylib]pypy.runtime.Utils::Deserialize(string)')
+        self.ilasm.opcode('dup')
+        self.ilasm.opcode('brfalse initialize')
+        self.ilasm.stderr('Constants deserialized successfully')        
+        self.ilasm.opcode('stsfld class %s %s::Singleton' % (CONST_CLASS, CONST_CLASS))
+        self.ilasm.ret()
+        self.ilasm.label('initialize')
+        self.ilasm.pop()
+        self.ilasm.stderr('Cannot deserialize constants... initialize them!')
+        self.ilasm.new('instance void class %s::.ctor()' % CONST_CLASS)
+        self.ilasm.opcode('ldstr "constants.dat"')
+        self.ilasm.call('void [pypylib]pypy.runtime.Utils::Serialize(object, string)')
+        self.ilasm.ret()
+
+class LazyConstGenerator(StaticFieldConstGenerator):
+    def push_constant(self, ilasm, const):
+        getter_name = '%s::%s' % (CONST_CLASS, 'get_%s' % const.name)
+        ilasm.call('%s %s()' % (const.get_type(), getter_name))
+
+    def _create_pointers(self, gen, all_constants):
+        # overload to do nothing since we handle everything in lazy fashion
+        pass
+
+    def _initialize_data(self, gen, all_constants):
+        # overload to do nothing since we handle everything in lazy fashion
+        pass
+
+    def _declare_const(self, gen, const):
+        # Declare the field
+        super(LazyConstGenerator, self)._declare_const(gen, const)
+
+        # Create the method for accessing the field
+        getter_name = 'get_%s' % const.name
+        type_ = const.get_type()
+        self.ilasm.begin_function(getter_name, [], type_, False, 'static')
+        self.ilasm.load_static_constant(type_, CONST_NAMESPACE, CONST_CLASS, const.name)
+        # if it's already initialized, just return it
+        self.ilasm.opcode('dup')
+        self.ilasm.opcode('brfalse', 'initialize')
+        self.ilasm.opcode('ret')
+        # else, initialize!
+        self.ilasm.label('initialize')
+        self.ilasm.opcode('pop') # discard the null value we know is on the stack
+        const.instantiate(ilasm)
+        self.ilasm.opcode('dup') # two dups because const.init pops the value at the end
+        self.ilasm.opcode('dup')
+        self.ilasm.store_static_constant(type_, CONST_NAMESPACE, CONST_CLASS, const.name)
+        const.init(ilasm)
+        self.ilasm.opcode('ret')
+        self.ilasm.end_function()
+
+# ______________________________________________________________________
+# Mixins
+#
+# Mixins are used to add a few CLI-specific methods to each constant
+# class.  Basically, any time I wanted to extend a base class (such as
+# AbstractConst or DictConst), I created a mixin, and then mixed it in
+# to each sub-class of that base-class.  Kind of awkward.
+
+class CLIBaseConstMixin(object):
+    """ A mix-in with a few extra methods the CLI backend uses """
+    
+    def get_type(self, include_class=True):
+        """ Returns the CLI type for this constant's representation """
+        return self.cts.lltype_to_cts(self.value._TYPE, include_class)
+    
+    def push_inline(self, gen, TYPE):
+        """ Overload the oosupport version so that we use the CLI opcode
+        for pushing NULL """
+        assert self.is_null()
+        gen.ilasm.opcode('ldnull')
+
+class CLIDictMixin(CLIBaseConstMixin):
+    # Eventually code should look more like this:
+    #def _check_for_void_dict(self, gen):
+    #    KEYTYPE = self.value._TYPE._KEYTYPE
+    #    keytype = self.cts.lltype_to_cts(KEYTYPE)
+    #    keytype_T = self.cts.lltype_to_cts(self.value._TYPE.KEYTYPE_T)
+    #    VALUETYPE = self.value._TYPE._VALUETYPE
+    #    valuetype = self.cts.lltype_to_cts(VALUETYPE)
+    #    valuetype_T = self.cts.lltype_to_cts(self.value._TYPE.VALUETYPE_T)
+    #    if VALUETYPE is ootype.Void:
+    #        class_name = PYPY_DICT_OF_VOID % keytype
+    #        for key in self.value._dict:
+    #            gen.ilasm.opcode('dup')
+    #            push_constant(self.db, KEYTYPE, key, gen)
+    #            meth = 'void class %s::ll_set(%s)' % (class_name, keytype_T)
+    #            gen.ilasm.call_method(meth, False)
+    #        gen.ilasm.opcode('pop')
+    #        return True
+    #    return False
+    #
+    #def initialize_data(self, gen):
+    #    # special case: dict of void, ignore the values
+    #    if _check_for_void_dict(self, gen):
+    #        return
+    #    return super(CLIDictMixin, self).record_dependencies()
+
+    def initialize_data(self, gen):
+        assert not self.is_null()
+        class_name = self.get_type(False)
+        KEYTYPE = self.value._TYPE._KEYTYPE
+        keytype = self.cts.lltype_to_cts(KEYTYPE)
+        keytype_T = self.cts.lltype_to_cts(self.value._TYPE.KEYTYPE_T)
+
+        VALUETYPE = self.value._TYPE._VALUETYPE
+        valuetype = self.cts.lltype_to_cts(VALUETYPE)
+        valuetype_T = self.cts.lltype_to_cts(self.value._TYPE.VALUETYPE_T)
+
+        if KEYTYPE is ootype.Void:
+            assert VALUETYPE is ootype.Void
+            return
+
+        # special case: dict of void, ignore the values
+        if VALUETYPE is ootype.Void:
+            class_name = PYPY_DICT_OF_VOID % keytype
+            for key in self.value._dict:
+                gen.ilasm.opcode('dup')
+                push_constant(self.db, KEYTYPE, key, gen)
+                meth = 'void class %s::ll_set(%s)' % (class_name, keytype_T)
+                gen.ilasm.call_method(meth, False)
+            return
+
+        for key, value in self.value._dict.iteritems():
+            gen.ilasm.opcode('dup')
+            push_constant(self.db, KEYTYPE, key, gen)
+            push_constant(self.db, VALUETYPE, value, gen)
+            meth = 'void class [pypylib]pypy.runtime.Dict`2<%s, %s>::ll_set(%s, %s)' %\
+                   (keytype, valuetype, keytype_T, valuetype_T)
+            gen.ilasm.call_method(meth, False)
+    
+
+# ______________________________________________________________________
+# Constant Classes
+#
+# Here we overload a few methods, and mix in the base classes above.
+# Note that the mix-ins go first so that they overload methods where
+# required.
+#
+# Eventually, these probably wouldn't need to exist at all (the JVM
+# doesn't have any, for example), or could simply have empty bodies
+# and exist to combine a mixin and the generic base class.  For now,
+# though, they contain the create_pointer() and initialize_data()
+# routines.  In order to get rid of them, we would need to implement
+# the generator interface in the CLI.
+
+class CLIRecordConst(CLIBaseConstMixin, RecordConst):
+    # Eventually code should look more like this:
+    #def create_pointer(self, gen):
+    #    self.db.const_count.inc('Record')
+    #    super(CLIRecordConst, self).create_pointer(gen)
+
+    def create_pointer(self, gen):
+        assert not self.is_null()
+        class_name = self.get_type(False)
+        gen.ilasm.new('instance void class %s::.ctor()' % class_name)
+        self.db.const_count.inc('Record')
+
+    def initialize_data(self, gen):
+        assert not self.is_null()
+        class_name = self.get_type(False)        
+        for f_name, (FIELD_TYPE, f_default) in self.value._TYPE._fields.iteritems():
+            if FIELD_TYPE is not ootype.Void:
+                f_type = self.cts.lltype_to_cts(FIELD_TYPE)
+                value = self.value._items[f_name]
+                gen.ilasm.opcode('dup')
+                push_constant(self.db, FIELD_TYPE, value, gen)
+                gen.ilasm.set_field((f_type, class_name, f_name))
+
+class CLIInstanceConst(CLIBaseConstMixin, InstanceConst):
+    # Eventually code should look more like this:
+    #def create_pointer(self, gen):
+    #    self.db.const_count.inc('Instance')
+    #    self.db.const_count.inc('Instance', INSTANCE)
+    #    super(CLIInstanceConst, self).create_pointer(gen)
+
+    def create_pointer(self, gen):
+        assert not self.is_null()
+        INSTANCE = self.value._TYPE
+        gen.ilasm.new('instance void class %s::.ctor()' % self.db.class_name(INSTANCE))
+        self.db.const_count.inc('Instance')
+        self.db.const_count.inc('Instance', INSTANCE)
+
+    def initialize_data(self, gen):
+        assert not self.is_null()
+        INSTANCE = self.value._TYPE
+        if INSTANCE is not self.static_type:
+            gen.ilasm.opcode('castclass', self.cts.lltype_to_cts(INSTANCE, include_class=False))
+
+        # XXX, horrible hack: first collect all consts, then render
+        # CustomDicts at last because their ll_set could need other
+        # fields already initialized. We should really think a more
+        # general way to handle such things.
+        const_list = []
+        while INSTANCE is not None:
+            for name, (TYPE, default) in INSTANCE._fields.iteritems():
+                if TYPE is ootype.Void:
+                    continue
+                value = getattr(self.value, name)
+                const_list.append((TYPE, INSTANCE, name, value))
+            INSTANCE = INSTANCE._superclass
+
+        def mycmp(x, y):
+            if isinstance(x[0], ootype.CustomDict) and not isinstance(y[0], ootype.CustomDict):
+                return 1 # a CustomDict is always greater than non-CustomDicts
+            elif isinstance(y[0], ootype.CustomDict) and not isinstance(x[0], ootype.CustomDict):
+                return -1 # a non-CustomDict is always less than CustomDicts
+            else:
+                return cmp(x, y)
+        const_list.sort(mycmp)
+        
+        for TYPE, INSTANCE, name, value in const_list:
+            type_ = self.cts.lltype_to_cts(TYPE)
+            gen.ilasm.opcode('dup')
+            push_constant(self.db, TYPE, value, gen)
+            gen.ilasm.opcode('stfld %s %s::%s' % (type_, self.db.class_name(INSTANCE), name))
+
+class CLIClassConst(CLIBaseConstMixin, ClassConst):
+    def is_inline(self):
+        return True
+
+    def push_inline(self, gen, EXPECTED_TYPE):
+        if not self.is_null():
+            INSTANCE = self.value._INSTANCE
+            gen.ilasm.opcode('ldtoken', self.db.class_name(INSTANCE))
+            gen.ilasm.call('class [mscorlib]System.Type class [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)')
+            return
+        super(CLIClassConst, self).push_inline(gen, EXPECTED_TYPE)
+    pass
+
+class CLIListConst(CLIBaseConstMixin, ListConst):
+
+    # Eventually code should look more like this:
+    #def _do_not_initialize(self):
+    #    # Check if it is a list of all zeroes:
+    #    try:
+    #        if self.value._list == [0] * len(self.value._list):
+    #            return True
+    #    except:
+    #        pass
+    #    return super(CLIListConst, self)._do_not_initialize(self)
+    #
+    #def create_pointer(self, gen):
+    #    self.db.const_count.inc('List')
+    #    self.db.const_count.inc('List', self.value._TYPE._ITEMTYPE)
+    #    self.db.const_count.inc('List', len(self.value._list))
+    #    super(CLIListConst, self).create_pointer(gen)        
+
+    def create_pointer(self, gen):
+        assert not self.is_null()
+        class_name = self.get_type(False)
+        push_constant(self.db, ootype.Signed, len(self.value._list), gen)
+        gen.ilasm.new('instance void class %s::.ctor(int32)' % class_name)
+        self.db.const_count.inc('List')
+        self.db.const_count.inc('List', self.value._TYPE._ITEMTYPE)
+        self.db.const_count.inc('List', len(self.value._list))
+
+    def _list_of_zeroes(self):
+        try:
+            return self.value._list == [0] * len(self.value._list)
+        except:
+            return False
+
+    def initialize_data(self, gen):
+        assert not self.is_null()
+        ITEMTYPE = self.value._TYPE._ITEMTYPE
+        itemtype = self.cts.lltype_to_cts(ITEMTYPE)
+        itemtype_T = self.cts.lltype_to_cts(self.value._TYPE.ITEMTYPE_T)
+
+        # special case: List(Void); only resize it, don't care of the contents
+        # special case: list of zeroes, don't need to initialize every item
+        if ITEMTYPE is ootype.Void or self._list_of_zeroes():
+            push_constant(self.db, ootype.Signed, len(self.value._list), gen)            
+            meth = 'void class %s::_ll_resize(int32)' % self.get_type(False) #PYPY_LIST_OF_VOID
+            gen.ilasm.call_method(meth, False)
+            return True
+        
+        for item in self.value._list:
+            gen.ilasm.opcode('dup')
+            push_constant(self.db, ITEMTYPE, item, gen)
+            meth = 'void class [pypylib]pypy.runtime.List`1<%s>::Add(%s)' % (itemtype, itemtype_T)
+            gen.ilasm.call_method(meth, False)
+
+class CLIDictConst(CLIDictMixin, DictConst):
+
+    # Eventually code should look more like this:
+    #def create_pointer(self, gen):
+    #    self.db.const_count.inc('Dict')
+    #    self.db.const_count.inc('Dict', self.value._TYPE._KEYTYPE, self.value._TYPE._VALUETYPE)
+    #    super(CLIDictConst, self).create_pointer(gen)        
+        
+    def create_pointer(self, gen):
+        assert not self.is_null()
+        class_name = self.get_type(False)
+        gen.ilasm.new('instance void class %s::.ctor()' % class_name)
+        self.db.const_count.inc('Dict')
+        self.db.const_count.inc('Dict', self.value._TYPE._KEYTYPE, self.value._TYPE._VALUETYPE)
+        
+class CLICustomDictConst(CLIDictMixin, CustomDictConst):
+    def record_dependencies(self):
+        if not self.value:
+            return
+        eq = self.value._dict.key_eq
+        hash = self.value._dict.key_hash
+        self.comparer = EqualityComparer(self.db, self.value._TYPE._KEYTYPE, eq, hash)
+        self.db.pending_node(self.comparer)
+        super(CLICustomDictConst, self).record_dependencies()
+
+    def create_pointer(self, gen):
+        assert not self.is_null()
+        gen.ilasm.new(self.comparer.get_ctor())
+        class_name = self.get_type()
+        gen.ilasm.new('instance void %s::.ctor(class '
+                      '[mscorlib]System.Collections.Generic.IEqualityComparer`1<!0>)'
+                  % class_name)
+        self.db.const_count.inc('CustomDict')
+        self.db.const_count.inc('CustomDict', self.value._TYPE._KEYTYPE, self.value._TYPE._VALUETYPE)
+
+class CLIStaticMethodConst(CLIBaseConstMixin, StaticMethodConst):
+    def create_pointer(self, gen):
+        assert not self.is_null()
+        signature = self.cts.graph_to_signature(self.value.graph)
+        gen.ilasm.opcode('ldnull')
+        gen.ilasm.opcode('ldftn', signature)
+        gen.ilasm.new('instance void class %s::.ctor(object, native int)' % self.delegate_type)
+        self.db.const_count.inc('StaticMethod')
+        
+    def initialize_data(self, gen):
+        return
+
+        
+class CLIWeakRefConst(CLIBaseConstMixin, WeakRefConst):
+    def create_pointer(self, gen):
+        gen.ilasm.opcode('ldnull')
+        gen.ilasm.new('instance void %s::.ctor(object)' % self.get_type())
+        self.db.const_count.inc('WeakRef')
+
+    def get_type(self, include_class=True):
+        return 'class ' + WEAKREF
+    
+    def initialize_data(self, gen):
+        if self.value is not None:
+            push_constant(self.db, self.value._TYPE, self.value, gen)
+            gen.ilasm.call_method(
+                'void %s::set_Target(object)' % self.get_type(), True)
+            return True
+    

Modified: pypy/dist/pypy/translator/cli/database.py
==============================================================================
--- pypy/dist/pypy/translator/cli/database.py	(original)
+++ pypy/dist/pypy/translator/cli/database.py	Tue Nov  7 22:24:19 2006
@@ -1,6 +1,5 @@
 import operator
 import string
-from pypy.translator.cli.cts import CTS, PYPY_LIST_OF_VOID, PYPY_DICT_OF_VOID, WEAKREF
 from pypy.translator.cli.function import Function, log
 from pypy.translator.cli.class_ import Class
 from pypy.translator.cli.record import Record
@@ -8,25 +7,18 @@
 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.constgenerator import StaticFieldConstGenerator, InstanceFieldConstGenerator, LazyConstGenerator
 from pypy.rpython.ootypesystem import ootype
 from pypy.rpython.ootypesystem.module import ll_os
-from pypy.rpython.lltypesystem import lltype
-from pypy.rpython.lltypesystem import llmemory
 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
 
 try:
     set
 except NameError:
     from sets import Set as set
 
-#CONST_GENERATOR = InstanceFieldConstGenerator
-CONST_GENERATOR = StaticFieldConstGenerator
-#CONST_GENERATOR = LazyConstGenerator
-
-
 BUILTIN_RECORDS = {
     ootype.Record({"item0": ootype.Signed, "item1": ootype.Signed}):
     '[pypylib]pypy.runtime.Record_Signed_Signed',
@@ -40,20 +32,9 @@
     ll_os.STAT_RESULT: '[pypylib]pypy.runtime.Record_Stat_Result',
     }
 
-DEFINED_INT_SYMBOLICS = {'MALLOC_ZERO_FILLED':1}
-
-def isnan(v):
-        return v != v*1.0 or (v == 1.0 and v == 2.0)
-
-def isinf(v):
-    return v!=0 and (v == v*2)
-
-class LowLevelDatabase(object):
+class LowLevelDatabase(OODatabase):
     def __init__(self, genoo):
-        self._pending_nodes = set()
-        self._rendered_nodes = set()
-        self.genoo = genoo
-        self.cts = genoo.TypeSystem(self)
+        OODatabase.__init__(self, genoo)
         self.classes = {} # INSTANCE --> class_name
         self.classnames = set() # (namespace, name)
         self.recordnames = {} # RECORD --> name
@@ -62,13 +43,9 @@
         self.consts = {}  # value --> AbstractConst
         self.delegates = {} # StaticMethod --> type_name
         self.const_count = Counter() # store statistics about constants
-        self.const_names = set()
-        self.name_count = 0
-        self.locked = False
 
     def next_count(self):
-        self.name_count += 1
-        return self.name_count
+        return self.unique()
 
     def _default_record_name(self, RECORD):
         trans = string.maketrans('<>(), :', '_______')
@@ -133,14 +110,6 @@
         self.pending_node(r)
         return name
 
-    def pending_node(self, node):
-        if node in self._pending_nodes or node in self._rendered_nodes:
-            return
-
-        assert not self.locked # sanity check
-        self._pending_nodes.add(node)
-        node.dependencies()
-
     def record_function(self, graph, name):
         self.functions[graph] = name
 
@@ -166,16 +135,6 @@
         except KeyError:
             return self.recordnames[RECORD]
 
-    def record_const(self, value):
-        if value in self.consts:
-            const = self.consts[value]
-        else:
-            const = AbstractConst.make(self, value, self.next_count())
-            self.consts[value] = const
-            self.pending_node(const)
-
-        return const
-
     def record_delegate(self, TYPE):
         try:
             return self.delegates[TYPE]
@@ -184,497 +143,3 @@
             self.delegates[TYPE] = name
             self.pending_node(Delegate(self, TYPE, name))
             return name
-
-
-    def gen_constants(self, ilasm):
-        self.locked = True # new pending nodes are not allowed here
-        generator = CONST_GENERATOR(ilasm)
-        generator.begin_class()
-        
-        const_list = [const for const in self.consts.itervalues() if not const.is_inline()]
-        const_list.sort(key=operator.attrgetter('PRIORITY'))
-        num_const = len(const_list)
-
-        # render field definitions
-        for const in const_list:
-            assert not const.is_null()
-            generator.declare_const(const)
-
-        generator.generate_consts(const_list)
-        generator.end_class()
-        log.INFO("%d constants rendered" % num_const)
-        self.locked = False
-
-
-
-class AbstractConst(Node):
-    PRIORITY = 0
-    
-    def make(db, value, count):
-        if isinstance(value, ootype._view):
-            static_type = value._TYPE
-            value = value._inst
-        else:
-            static_type = None
-
-        if isinstance(value, ootype._instance):
-            return InstanceConst(db, value, static_type, count)
-        elif isinstance(value, ootype._record):
-            return RecordConst(db, value, count)
-        elif isinstance(value, ootype._list):
-            return ListConst(db, value, count)
-        elif isinstance(value, ootype._static_meth):
-            return StaticMethodConst(db, value, count)
-        elif isinstance(value, ootype._class):
-            return ClassConst(db, value, count)
-        elif isinstance(value, ootype._custom_dict):
-            return CustomDictConst(db, value, count)
-        elif isinstance(value, ootype._dict):
-            return DictConst(db, value, count)
-        elif isinstance(value, llmemory.fakeweakaddress):
-            return WeakRefConst(db, value, count)
-        else:
-            assert False, 'Unknown constant: %s' % value
-    make = staticmethod(make)
-
-    PRIMITIVE_TYPES = set([ootype.Void, ootype.Bool, ootype.Char, ootype.UniChar,
-                           ootype.Float, ootype.Signed, ootype.Unsigned, ootype.String,
-                           lltype.SignedLongLong, lltype.UnsignedLongLong])
-
-    def is_primitive(cls, TYPE):
-        return TYPE in cls.PRIMITIVE_TYPES
-    is_primitive = classmethod(is_primitive)
-
-    def load(cls, db, TYPE, value, ilasm):
-        if TYPE is ootype.Void:
-            pass
-        elif TYPE is ootype.Bool:
-            ilasm.opcode('ldc.i4', str(int(value)))
-        elif TYPE is ootype.Char or TYPE is ootype.UniChar:
-            ilasm.opcode('ldc.i4', ord(value))
-        elif TYPE is ootype.Float:
-            if isinf(value):
-                ilasm.opcode('ldc.r8', '(00 00 00 00 00 00 f0 7f)')
-            elif isnan(value):
-                ilasm.opcode('ldc.r8', '(00 00 00 00 00 00 f8 ff)')
-            else:
-                ilasm.opcode('ldc.r8', repr(value))
-        elif isinstance(value, CDefinedIntSymbolic):
-            ilasm.opcode('ldc.i4', DEFINED_INT_SYMBOLICS[value.expr])
-        elif TYPE in (ootype.Signed, ootype.Unsigned):
-            ilasm.opcode('ldc.i4', str(value))
-        elif TYPE in (lltype.SignedLongLong, lltype.UnsignedLongLong):
-            ilasm.opcode('ldc.i8', str(value))
-        elif TYPE is ootype.String:
-            if value._str is None:
-                ilasm.opcode('ldnull')
-            else:
-                ilasm.opcode("ldstr", string_literal(value._str))
-        else:
-            assert TYPE not in cls.PRIMITIVE_TYPES
-            const = db.record_const(value)
-            if const.is_null():
-                ilasm.opcode('ldnull')
-            else:
-                const._load(ilasm, TYPE)
-    load = classmethod(load)
-
-    def __hash__(self):
-        return hash(self.value)
-
-    def __eq__(self, other):
-        return self.value == other.value
-
-    def __ne__(self, other):
-        return not self == other
-
-    def __repr__(self):
-        return '<Const %s %s>' % (self.name, self.value)
-
-    def get_name(self):
-        pass
-
-    def get_type(self):
-        pass
-
-    def is_null(self):
-        return self.value is ootype.null(self.value._TYPE)
-
-    def is_inline(self):
-        """
-        Inline constants are not stored as static fields in the
-        Constant class, but they are newly created on the stack every
-        time they are used. Classes overriding is_inline should
-        override _load too.
-        """
-        return self.is_null() # by default only null constants are inlined
-
-    def _load(self, ilasm, EXPECTED_TYPE):
-        """
-        Load the constant onto the stack.
-        """
-        cts = CTS(self.db)
-        cts_static_type = self.get_type()
-        CONST_GENERATOR.load_const(ilasm, self)
-
-        if cts_static_type != cts.lltype_to_cts(EXPECTED_TYPE):
-            ilasm.opcode('castclass', cts.lltype_to_cts(EXPECTED_TYPE, include_class=False))
-
-    def record_const_maybe(self, TYPE, value):
-        if AbstractConst.is_primitive(TYPE):
-            return
-        self.db.record_const(value)
-
-    def render(self, ilasm):
-        pass
-
-    def dependencies(self):
-        """
-        Record all constants that are needed to correctly initialize
-        the object.
-        """
-
-    def instantiate(self, ilasm):
-        """
-        Instantiate the the object which represent the constant and
-        leave a reference to it on the stack.
-        """
-        raise NotImplementedError
-
-    def init(self, ilasm):
-        """
-        Do some sort of extra initialization, if needed. It assume the
-        object to be initialized is on the stack. Don't leave anything
-        on the stack.
-        """
-        assert not self.is_null()
-        ilasm.opcode('pop')
-
-
-class RecordConst(AbstractConst):
-    def __init__(self, db, record, count):
-        self.db = db
-        self.cts = CTS(db)        
-        self.value = record
-        self.name = 'RECORD__%d' % count
-
-    def get_type(self, include_class=True):
-        return self.cts.lltype_to_cts(self.value._TYPE, include_class)
-
-    def dependencies(self):
-        if self.value is ootype.null(self.value._TYPE):
-            return
-        for f_name, (FIELD_TYPE, f_default) in self.value._TYPE._fields.iteritems():
-            value = self.value._items[f_name]            
-            self.record_const_maybe(FIELD_TYPE, value)
-
-    def instantiate(self, ilasm):
-        assert not self.is_null()
-        class_name = self.get_type(False)
-        ilasm.new('instance void class %s::.ctor()' % class_name)
-        self.db.const_count.inc('Record')
-
-    def init(self, ilasm):
-        assert not self.is_null()
-        class_name = self.get_type(False)        
-        for f_name, (FIELD_TYPE, f_default) in self.value._TYPE._fields.iteritems():
-            if FIELD_TYPE is not ootype.Void:
-                f_type = self.cts.lltype_to_cts(FIELD_TYPE)
-                value = self.value._items[f_name]
-                ilasm.opcode('dup')
-                AbstractConst.load(self.db, FIELD_TYPE, value, ilasm)            
-                ilasm.set_field((f_type, class_name, f_name))
-        ilasm.opcode('pop')
-
-class StaticMethodConst(AbstractConst):
-    def __init__(self, db, sm, count):
-        self.db = db
-        self.cts = CTS(db)
-        self.value = sm
-        self.name = 'DELEGATE__%d' % count
-
-    def get_type(self, include_class=True):
-        return self.cts.lltype_to_cts(self.value._TYPE, include_class)
-
-    def dependencies(self):
-        if self.value is ootype.null(self.value._TYPE):
-            return
-        self.db.pending_function(self.value.graph)
-        self.delegate_type = self.db.record_delegate(self.value._TYPE)
-
-    def instantiate(self, ilasm):
-        assert not self.is_null()
-        signature = self.cts.graph_to_signature(self.value.graph)
-        ilasm.opcode('ldnull')
-        ilasm.opcode('ldftn', signature)
-        ilasm.new('instance void class %s::.ctor(object, native int)' % self.delegate_type)
-        self.db.const_count.inc('StaticMethod')
-
-class ClassConst(AbstractConst):
-    def __init__(self, db, class_, count):
-        self.db = db
-        self.cts = CTS(db)
-        self.value = class_
-        self.name = 'CLASS__%d' % count
-
-    def get_type(self, include_class=True):
-        return self.cts.lltype_to_cts(self.value._TYPE, include_class)
-
-    def dependencies(self):
-        INSTANCE = self.value._INSTANCE
-        if INSTANCE is not None:
-            self.cts.lltype_to_cts(INSTANCE) # force scheduling class generation
-
-    def is_null(self):
-        return self.value._INSTANCE is None
-
-    def is_inline(self):
-        return True
-
-    def _load(self, ilasm, EXPECTED_TYPE):
-        assert not self.is_null()
-        INSTANCE = self.value._INSTANCE
-        ilasm.opcode('ldtoken', self.db.class_name(INSTANCE))
-        ilasm.call('class [mscorlib]System.Type class [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)')
-
-class ListConst(AbstractConst):
-    def __init__(self, db, list_, count):
-        self.db = db
-        self.cts = CTS(db)
-        self.value = list_
-        self.name = 'LIST__%d' % count
-
-    def get_type(self, include_class=True):
-        return self.cts.lltype_to_cts(self.value._TYPE, include_class)
-
-    def dependencies(self):
-        if not self.value:
-            return
-        for item in self.value._list:
-            self.record_const_maybe(self.value._TYPE._ITEMTYPE, item)
-
-    def instantiate(self, ilasm):
-        assert not self.is_null()
-        class_name = self.get_type(False)
-        AbstractConst.load(self.db, ootype.Signed, len(self.value._list), ilasm)
-        ilasm.new('instance void class %s::.ctor(int32)' % class_name)
-        self.db.const_count.inc('List')
-        self.db.const_count.inc('List', self.value._TYPE._ITEMTYPE)
-        self.db.const_count.inc('List', len(self.value._list))
-
-    def _list_of_zeroes(self):
-        try:
-            return self.value._list == [0] * len(self.value._list)
-        except:
-            return False
-
-    def init(self, ilasm):
-        assert not self.is_null()
-        ITEMTYPE = self.value._TYPE._ITEMTYPE
-        itemtype = self.cts.lltype_to_cts(ITEMTYPE)
-        itemtype_T = self.cts.lltype_to_cts(self.value._TYPE.ITEMTYPE_T)
-
-        # special case: List(Void); only resize it, don't care of the contents
-        # special case: list of zeroes, don't need to initialize every item
-        if ITEMTYPE is ootype.Void or self._list_of_zeroes():
-            AbstractConst.load(self.db, ootype.Signed, len(self.value._list), ilasm)            
-            meth = 'void class %s::_ll_resize(int32)' % self.get_type(False) #PYPY_LIST_OF_VOID
-            ilasm.call_method(meth, False)
-            return
-        
-        for item in self.value._list:
-            ilasm.opcode('dup')
-            AbstractConst.load(self.db, ITEMTYPE, item, ilasm)
-            meth = 'void class [pypylib]pypy.runtime.List`1<%s>::Add(%s)' % (itemtype, itemtype_T)
-            ilasm.call_method(meth, False)
-        ilasm.opcode('pop')
-
-class DictConst(AbstractConst):
-    def __init__(self, db, dict_, count):
-        self.db = db
-        self.cts = CTS(db)
-        self.value = dict_
-        self.name = 'DICT__%d' % count
-
-    def get_type(self, include_class=True):
-        return self.cts.lltype_to_cts(self.value._TYPE, include_class)
-
-    def dependencies(self):
-        if not self.value:
-            return
-        
-        for key, value in self.value._dict.iteritems():
-            self.record_const_maybe(self.value._TYPE._KEYTYPE, key)
-            self.record_const_maybe(self.value._TYPE._VALUETYPE, value)
-
-    def instantiate(self, ilasm):
-        assert not self.is_null()
-        class_name = self.get_type(False)
-        ilasm.new('instance void class %s::.ctor()' % class_name)
-        self.db.const_count.inc('Dict')
-        self.db.const_count.inc('Dict', self.value._TYPE._KEYTYPE, self.value._TYPE._VALUETYPE)
-        
-    def init(self, ilasm):
-        assert not self.is_null()
-        class_name = self.get_type(False)
-        KEYTYPE = self.value._TYPE._KEYTYPE
-        keytype = self.cts.lltype_to_cts(KEYTYPE)
-        keytype_T = self.cts.lltype_to_cts(self.value._TYPE.KEYTYPE_T)
-
-        VALUETYPE = self.value._TYPE._VALUETYPE
-        valuetype = self.cts.lltype_to_cts(VALUETYPE)
-        valuetype_T = self.cts.lltype_to_cts(self.value._TYPE.VALUETYPE_T)
-
-        if KEYTYPE is ootype.Void:
-            assert VALUETYPE is ootype.Void
-            ilasm.opcode('pop')
-            return
-
-        # special case: dict of void, ignore the values
-        if VALUETYPE is ootype.Void:
-            class_name = PYPY_DICT_OF_VOID % keytype
-            for key in self.value._dict:
-                ilasm.opcode('dup')
-                AbstractConst.load(self.db, KEYTYPE, key, ilasm)
-                meth = 'void class %s::ll_set(%s)' % (class_name, keytype_T)
-                ilasm.call_method(meth, False)
-            ilasm.opcode('pop')
-            return
-
-        for key, value in self.value._dict.iteritems():
-            ilasm.opcode('dup')
-            AbstractConst.load(self.db, KEYTYPE, key, ilasm)
-            AbstractConst.load(self.db, VALUETYPE, value, ilasm)
-            meth = 'void class [pypylib]pypy.runtime.Dict`2<%s, %s>::ll_set(%s, %s)' %\
-                   (keytype, valuetype, keytype_T, valuetype_T)
-            ilasm.call_method(meth, False)
-        ilasm.opcode('pop')
-
-class CustomDictConst(DictConst):
-    PRIORITY = 100
-    
-    def dependencies(self):
-        if not self.value:
-            return
-
-        eq = self.value._dict.key_eq
-        hash = self.value._dict.key_hash
-        self.comparer = EqualityComparer(self.db, self.value._TYPE._KEYTYPE, eq, hash)
-        self.db.pending_node(self.comparer)
-        DictConst.dependencies(self)
-
-    def instantiate(self, ilasm):
-        assert not self.is_null()
-        ilasm.new(self.comparer.get_ctor())
-        class_name = self.get_type()
-        ilasm.new('instance void %s::.ctor(class '
-                  '[mscorlib]System.Collections.Generic.IEqualityComparer`1<!0>)'
-                  % class_name)
-        self.db.const_count.inc('CustomDict')
-        self.db.const_count.inc('CustomDict', self.value._TYPE._KEYTYPE, self.value._TYPE._VALUETYPE)
-
-
-class InstanceConst(AbstractConst):
-    def __init__(self, db, obj, static_type, count):
-        self.db = db
-        self.cts = CTS(db)
-        self.value = obj
-        if static_type is None:
-            self.static_type = obj._TYPE
-        else:
-            self.static_type = static_type
-            self.cts.lltype_to_cts(obj._TYPE) # force scheduling of obj's class
-        class_name = db.class_name(obj._TYPE).replace('.', '_')
-        self.name = '%s__%d' % (class_name, count)
-
-    def get_type(self):
-        return self.cts.lltype_to_cts(self.static_type)
-
-    def dependencies(self):
-        if not self.value:
-            return
-
-        INSTANCE = self.value._TYPE
-        while INSTANCE is not None:
-            for name, (TYPE, default) in INSTANCE._fields.iteritems():
-                if TYPE is ootype.Void:
-                    continue
-                type_ = self.cts.lltype_to_cts(TYPE) # record type
-                value = getattr(self.value, name) # record value
-                self.record_const_maybe(TYPE, value)
-            INSTANCE = INSTANCE._superclass
-
-    def is_null(self):
-        return not self.value
-
-    def instantiate(self, ilasm):
-        assert not self.is_null()
-        INSTANCE = self.value._TYPE
-        ilasm.new('instance void class %s::.ctor()' % self.db.class_name(INSTANCE))
-        self.db.const_count.inc('Instance')
-        self.db.const_count.inc('Instance', INSTANCE)
-
-    def init(self, ilasm):
-        assert not self.is_null()
-        INSTANCE = self.value._TYPE
-        if INSTANCE is not self.static_type:
-            ilasm.opcode('castclass', self.cts.lltype_to_cts(INSTANCE, include_class=False))
-
-        # XXX, horrible hack: first collect all consts, then render
-        # CustomDicts at last because their ll_set could need other
-        # fields already initialized. We should really think a more
-        # general way to handle such things.
-        const_list = []
-        while INSTANCE is not None:
-            for name, (TYPE, default) in INSTANCE._fields.iteritems():
-                if TYPE is ootype.Void:
-                    continue
-                value = getattr(self.value, name)
-                const_list.append((TYPE, INSTANCE, name, value))
-            INSTANCE = INSTANCE._superclass
-
-        def mycmp(x, y):
-            if isinstance(x[0], ootype.CustomDict) and not isinstance(y[0], ootype.CustomDict):
-                return 1 # a CustomDict is always greater than non-CustomDicts
-            elif isinstance(y[0], ootype.CustomDict) and not isinstance(x[0], ootype.CustomDict):
-                return -1 # a non-CustomDict is always less than CustomDicts
-            else:
-                return cmp(x, y)
-        const_list.sort(mycmp)
-        
-        for TYPE, INSTANCE, name, value in const_list:
-            type_ = self.cts.lltype_to_cts(TYPE)
-            ilasm.opcode('dup')
-            AbstractConst.load(self.db, TYPE, value, ilasm)
-            ilasm.opcode('stfld %s %s::%s' % (type_, self.db.class_name(INSTANCE), name))
-
-        ilasm.opcode('pop')
-
-class WeakRefConst(AbstractConst):
-    def __init__(self, db, fakeaddr, count):
-        self.db = db
-        self.cts = CTS(db)
-        self.value = fakeaddr.get()
-        self.name = 'WEAKREF__%d' % count
-
-    def get_type(self, include_class=True):
-        return 'class ' + WEAKREF
-
-    def is_null(self):
-        return False
-
-    def dependencies(self):
-        if self.value is not None:
-            self.db.record_const(self.value)
-
-    def instantiate(self, ilasm):
-        ilasm.opcode('ldnull')
-        ilasm.new('instance void %s::.ctor(object)' % self.get_type())
-        self.db.const_count.inc('WeakRef')
-
-    def init(self, ilasm):
-        if self.value is not None:
-            AbstractConst.load(self.db, self.value._TYPE, self.value, ilasm)        
-            ilasm.call_method('void %s::set_Target(object)' % self.get_type(), True)
-        else:
-            ilasm.opcode('pop')

Modified: pypy/dist/pypy/translator/cli/function.py
==============================================================================
--- pypy/dist/pypy/translator/cli/function.py	(original)
+++ pypy/dist/pypy/translator/cli/function.py	Tue Nov  7 22:24:19 2006
@@ -4,9 +4,7 @@
     from sets import Set as set
 
 from pypy.objspace.flow import model as flowmodel
-from pypy.rpython.lltypesystem.lltype import Signed, Unsigned, Void, Bool, Float
-from pypy.rpython.lltypesystem.lltype import SignedLongLong, UnsignedLongLong
-from pypy.rpython.ootypesystem import ootype
+from pypy.rpython.lltypesystem.lltype import Void
 from pypy.translator.oosupport.function import Function as OOFunction
 from pypy.translator.cli.option import getoption
 from pypy.translator.cli.cts import CTS
@@ -15,8 +13,9 @@
 from pypy.translator.cli.node import Node
 from pypy.translator.cli.class_ import Class
 from pypy.translator.cli.support import log
+from pypy.translator.cli.ilgenerator import CLIBaseGenerator
 
-class Function(OOFunction, Node, Generator):
+class Function(OOFunction, Node, CLIBaseGenerator):
 
     def __init__(self, *args, **kwargs):
         OOFunction.__init__(self, *args, **kwargs)
@@ -98,56 +97,8 @@
         self.ilasm.opcode('throw')
 
 
-    # Generator interface
-
-    def add_comment(self, text):
-        pass
-    
-    def function_signature(self, graph, func_name=None):
-        return self.cts.graph_to_signature(graph, False, func_name)
-
-    def class_name(self, TYPE):
-        if isinstance(TYPE, ootype.Instance):
-            return self.db.class_name(TYPE)
-        elif isinstance(TYPE, ootype.Record):
-            return self.db.get_record_name(TYPE)
-
-    def emit(self, instr, *args):
-        self.ilasm.opcode(instr, *args)
-
-    def call_graph(self, graph, func_name=None):
-        if func_name is None: # else it is a suggested primitive
-            self.db.pending_function(graph)
-        func_sig = self.function_signature(graph, func_name)
-        self.ilasm.call(func_sig)
-
-    def call_signature(self, signature):
-        self.ilasm.call(signature)
-
-    def cast_to(self, lltype):
-        cts_type = self.cts.lltype_to_cts(lltype, False)
-        self.ilasm.opcode('castclass', cts_type)
-
-    def new(self, obj):
-        self.ilasm.new(self.cts.ctor_name(obj))
-
-    def set_field(self, obj, name):
-        self.ilasm.opcode('stfld ' + self.field_name(obj, name))
-
-    def get_field(self, obj, name):
-        self.ilasm.opcode('ldfld ' + self.field_name(obj, name))
-
-    def call_method(self, obj, name):
-        # TODO: use callvirt only when strictly necessary
-        signature, virtual = self.cts.method_signature(obj, name)
-        self.ilasm.call_method(signature, virtual)
-
-    def downcast(self, TYPE):
-        type = self.cts.lltype_to_cts(TYPE)
-        return self.ilasm.opcode('castclass', type)
-
-    def instantiate(self):
-        self.call_signature('object [pypylib]pypy.runtime.Utils::RuntimeNew(class [mscorlib]System.Type)')
+    # Those parts of the generator interface that are function
+    # specific
 
     def load(self, v):
         if isinstance(v, flowmodel.Variable):
@@ -160,14 +111,8 @@
             else:
                 self.ilasm.load_local(v)
 
-        elif isinstance(v, flowmodel.Constant):
-            self._load_const(v)
         else:
-            assert False
-
-    def _load_const(self, const):
-        from pypy.translator.cli.database import AbstractConst
-        AbstractConst.load(self.db, const.concretetype, const.value, self.ilasm)
+            super(Function, self).load(v)
 
     def store(self, v):
         if isinstance(v, flowmodel.Variable):
@@ -175,12 +120,3 @@
                 self.ilasm.store_local(v)
         else:
             assert False
-
-    def isinstance(self, class_name):
-        self.ilasm.opcode('isinst', class_name)
-
-    def branch_unconditionally(self, target_label):
-        self.ilasm.branch(target_label)
-
-    def branch_conditionally(self, cond, target_label):
-        self.ilasm.branch_if(cond, target_label)

Modified: pypy/dist/pypy/translator/cli/gencli.py
==============================================================================
--- pypy/dist/pypy/translator/cli/gencli.py	(original)
+++ pypy/dist/pypy/translator/cli/gencli.py	Tue Nov  7 22:24:19 2006
@@ -20,6 +20,7 @@
 from pypy.translator.cli.prebuiltnodes import get_prebuilt_nodes
 from pypy.translator.cli.stackopt import StackOptGenerator
 from pypy.translator.cli import query
+from pypy.translator.cli import constant
 
 try:
     set
@@ -36,6 +37,16 @@
     opcodes = opcodes
     Database = LowLevelDatabase
     log = log
+    
+    ConstantGenerator = constant.StaticFieldConstGenerator
+    InstanceConst = constant.CLIInstanceConst
+    RecordConst = constant.CLIRecordConst
+    ClassConst = constant.CLIClassConst
+    ListConst = constant.CLIListConst
+    StaticMethodConst = constant.CLIStaticMethodConst
+    CustomDictConst = constant.CLICustomDictConst
+    DictConst = constant.CLIDictConst
+    WeakRefConst = constant.CLIWeakRefConst
 
     def __init__(self, tmpdir, translator, entrypoint, config=None):
         GenOO.__init__(self, tmpdir, translator, entrypoint, config)

Modified: pypy/dist/pypy/translator/cli/ilgenerator.py
==============================================================================
--- pypy/dist/pypy/translator/cli/ilgenerator.py	(original)
+++ pypy/dist/pypy/translator/cli/ilgenerator.py	Tue Nov  7 22:24:19 2006
@@ -1,5 +1,9 @@
 from pypy.rpython.lltypesystem.lltype import Signed, Unsigned, Void, Bool, Float
 from pypy.rpython.lltypesystem.lltype import SignedLongLong, UnsignedLongLong
+from pypy.rpython.ootypesystem import ootype
+from pypy.translator.oosupport.metavm import Generator
+from pypy.translator.oosupport.constant import push_constant
+from pypy.objspace.flow import model as flowmodel
 
 class CodeGenerator(object):
     def __init__(self, out, indentstep = 4, startblock = '{', endblock = '}'):
@@ -239,5 +243,82 @@
             self.opcode('ldstr', string_literal(msg))
             self.call_method('void class [mscorlib]System.IO.TextWriter::WriteLine(string)', virtual=True)
 
+    def add_comment(self, text):
+        self.out.write('// %s\n' % text)
+
     def flush(self):
         pass
+
+class CLIBaseGenerator(Generator):
+    
+    """ Implements those parts of the metavm generator that are not
+    tied to any particular function."""
+
+    def __init__(self, db, ilasm):
+        self.ilasm = ilasm
+        self.db = db
+        self.cts = db.genoo.TypeSystem(db)
+
+    def add_comment(self, text):
+        pass
+    
+    def function_signature(self, graph, func_name=None):
+        return self.cts.graph_to_signature(graph, False, func_name)
+
+    def class_name(self, TYPE):
+        if isinstance(TYPE, ootype.Instance):
+            return self.db.class_name(TYPE)
+        elif isinstance(TYPE, ootype.Record):
+            return self.db.get_record_name(TYPE)
+
+    def emit(self, instr, *args):
+        self.ilasm.opcode(instr, *args)
+
+    def call_graph(self, graph, func_name=None):
+        if func_name is None: # else it is a suggested primitive
+            self.db.pending_function(graph)
+        func_sig = self.function_signature(graph, func_name)
+        self.ilasm.call(func_sig)
+
+    def call_signature(self, signature):
+        self.ilasm.call(signature)
+
+    def cast_to(self, lltype):
+        cts_type = self.cts.lltype_to_cts(lltype, False)
+        self.ilasm.opcode('castclass', cts_type)
+
+    def new(self, obj):
+        self.ilasm.new(self.cts.ctor_name(obj))
+
+    def set_field(self, obj, name):
+        self.ilasm.opcode('stfld ' + self.field_name(obj, name))
+
+    def get_field(self, obj, name):
+        self.ilasm.opcode('ldfld ' + self.field_name(obj, name))
+
+    def call_method(self, obj, name):
+        # TODO: use callvirt only when strictly necessary
+        signature, virtual = self.cts.method_signature(obj, name)
+        self.ilasm.call_method(signature, virtual)
+
+    def downcast(self, TYPE):
+        type = self.cts.lltype_to_cts(TYPE)
+        return self.ilasm.opcode('castclass', type)
+
+    def instantiate(self):
+        self.call_signature('object [pypylib]pypy.runtime.Utils::RuntimeNew(class [mscorlib]System.Type)')
+
+    def load(self, v):
+        if isinstance(v, flowmodel.Constant):
+            push_constant(self.db, v.concretetype, v.value, self)
+        else:
+            assert False
+
+    def isinstance(self, class_name):
+        self.ilasm.opcode('isinst', class_name)
+
+    def branch_unconditionally(self, target_label):
+        self.ilasm.branch(target_label)
+
+    def branch_conditionally(self, cond, target_label):
+        self.ilasm.branch_if(cond, target_label)

Modified: pypy/dist/pypy/translator/jvm/constant.py
==============================================================================
--- pypy/dist/pypy/translator/jvm/constant.py	(original)
+++ pypy/dist/pypy/translator/jvm/constant.py	Tue Nov  7 22:24:19 2006
@@ -2,80 +2,54 @@
      Field, Method, ACONST_NULL, ICONST, LDC, DCONST_0, DCONST_1, LDC2
 from pypy.translator.oosupport.constant import \
      RecordConst, InstanceConst, ClassConst
-from pypy.translator.jvm.typesystem import jPyPyConst
+from pypy.translator.jvm.typesystem import \
+     jPyPyConst, jObject
 
 # ___________________________________________________________________________
-# Simple Constants
-#
-# We create simple dummy constant objects that follow the same
-# inteface as the complex constants from oosupport/constant.py.  None
-# of these requires initialization, so they only support push() and
-# they should never find their way into the database's constant list.
-
-class Const(object):
-    def push(self, gen):
-        """ Emits code required to reference a constant.  Usually invoked
-        by generator.emit() """
-        raise NotImplementedError
-
-class VoidConst(object):
-    def push(self, gen):
-        pass
-
-class NullConst(object):
-    def push(self, gen):
-        gen.emit(ACONST_NULL)
-
-class DoubleConst(Const):
-    def __init__(self, value):
-        self.value = value
-    def push(self, gen):
-        if value == 0.0:
-            gen.emit(DCONST_0)
-        elif value == 1.0:
-            gen.emit(DCONST_1)
-        else:
-            gen.emit(LDC2, self.value)
-
-class UnicodeConst(Const):
-    def __init__(self, value):
-        self.value = value
-    def push(self, gen):
-        assert isinstance(self.value, unicode)
-        gen.emit(LDC, res)
+# Constant Generator
 
-# ___________________________________________________________________________
-# Complex Constants
+class JVMConstantGenerator(BaseConstantGenerator):
 
-class JVMFieldStorage(object):
-    """ A mix-in for the oosupport constant classes that stores the
-    pointer for the constant into a field on a class.  It implements
-    the push() and store() methods used by the oosupport classes and
-    elsewhere."""
-    def __init__(self):
-        # Note that self.name and self.value are set by the oosupport
-        # constance class:
-        fieldty = self.db.lltype_to_cts(self.value._TYPE)
-        self.fieldobj = Field(jPyPyConst.name, self.name, fieldty, True)
+    # _________________________________________________________________
+    # Constant Operations
+    #
+    # We store constants in static fields of the jPyPyConst class.
+    
+    def _init_constant(self, const):
+        fieldty = self.db.lltype_to_cts(const.OOTYPE())
+        const.fieldobj = Field(jPyPyConst.name, const.name, fieldty, True)
+
+    def push_constant(self, gen, const):
+        const.fieldobj.load(gen)
+
+    def _store_constant(self, gen, const):
+        const.fieldobj.store(gen)
+
+    # _________________________________________________________________
+    # Constant Generation
+    
+    def _begin_gen_constants(self, gen, all_constants):
+        gen.begin_class(jPyPyConst, jObject)
+
+    def _declare_const(self, gen, const):
+        gen.add_field(c.fieldobj)
+
+    def _declare_step(self, gen, stepnum):
+        next_nm = "constant_init_%d" % stepnum
+        gen.begin_function(next_nm, [], [], jVoid, True)
+
+    def _close_step(self, gen, stepnum):
+        gen.return_val(jVoid)
+        gen.end_function()    # end constant_init_N where N == stepnum
+    
+    def _end_gen_constants(self, gen, numsteps):
+        # The static init code just needs to call constant_init_1..N
+        gen.begin_function('<clinit>', [], [], jVoid, True)
+        for x in range(numsteps):
+            m = jvmgen.Method.s(jPyPyConst, "constant_init_%d" % x, [], jVoid)
+            gen.emit(m)
+        gen.return_val(jVoid)
+        gen.end_function()
         
-    def push(self, gen):
-        self.fieldobj.load(gen)
-
-    def store(self, gen):
-        self.fieldobj.store(gen)
-
-class JVMRecordConst(RecordConst, JVMFieldStorage):
-    def __init__(self, db, record, count):
-        RecordConst.__init__(self, db, record, count)
-        JVMFieldStorage.__init__(self)
-
-class JVMInstanceConst(InstanceConst, JVMFieldStorage):
-    def __init__(self, db, obj, record, count):
-        InstanceConst.__init__(self, db, obj, record, count)
-        JVMFieldStorage.__init__(self)
-
-class JVMClassConst(ClassConst, JVMFieldStorage):
-    def __init__(self, db, class_, count):
-        ClassConst.__init__(self, db, class_, count)
-        JVMFieldStorage.__init__(self)
-
+        gen.end_class()
+    

Modified: pypy/dist/pypy/translator/jvm/database.py
==============================================================================
--- pypy/dist/pypy/translator/jvm/database.py	(original)
+++ pypy/dist/pypy/translator/jvm/database.py	Tue Nov  7 22:24:19 2006
@@ -162,54 +162,6 @@
         return res
 
     # _________________________________________________________________
-    # Constant Emitting
-    #
-    # We place all constants in a special "constant" class
-    #
-    # XXX I don't particularly like this code being here.  database
-    # shouldn't be so specific?  Guess it's okay...
-
-    RecordConst = jvmconst.JVMRecordConst
-    InstanceConst = jvmconst.JVMInstanceConst
-    ClassConst = jvmconst.JVMClassConst
-    
-    def _begin_gen_constants(self, gen, all_constants):
-        gen.begin_class(jPyPyConst, jObject)
-
-        for c in all_constants:
-            assert isinstance(c, jvmconst.JVMFieldStorage)
-            gen.add_field(c.fieldobj)
-
-        # the constant initialization code is broken up into special
-        # methods that are then invoked from <clinit> --- this is to
-        # prevent the init functions from getting too big
-        self._constant_steps = 1
-        gen.begin_function('constant_init_0', [], [], jVoid, True)
-        return gen
-    
-    def _interrupt_gen_constants(self):
-        gen.return_val(jVoid)
-        gen.end_function()    # end constant_init_N
-        
-        next_nm = "constant_init_%d" % self._constant_steps
-        self._constant_steps += 1
-        gen.begin_function(next_nm, [], [], jVoid, True)
-    
-    def _end_gen_constants(self, gen):
-        gen.return_val(jVoid)
-        gen.end_function()    # end constant_init_N
-
-        # The static init code just needs to call constant_init_1..N
-        gen.begin_function('<clinit>', [], [], jVoid, True)
-        for x in range(self._constant_steps):
-            m = jvmgen.Method.s(jPyPyConst, "constant_init_%d" % x, [], jVoid)
-            gen.emit(m)
-        gen.return_val(jVoid)
-        gen.end_function()
-        
-        gen.end_class()
-
-    # _________________________________________________________________
     # Type printing functions
     #
     # Returns a method that prints details about the value out to

Modified: pypy/dist/pypy/translator/jvm/genjvm.py
==============================================================================
--- pypy/dist/pypy/translator/jvm/genjvm.py	(original)
+++ pypy/dist/pypy/translator/jvm/genjvm.py	Tue Nov  7 22:24:19 2006
@@ -172,6 +172,10 @@
     Database = Database
     opcodes = opcodes
     log = log
+
+    RecordConst = jvmconst.JVMRecordConst
+    InstanceConst = jvmconst.JVMInstanceConst
+    ClassConst = jvmconst.JVMClassConst
     
     def __init__(self, tmpdir, translator, entrypoint):
         """

Modified: pypy/dist/pypy/translator/oosupport/constant.py
==============================================================================
--- pypy/dist/pypy/translator/oosupport/constant.py	(original)
+++ pypy/dist/pypy/translator/oosupport/constant.py	Tue Nov  7 22:24:19 2006
@@ -6,26 +6,28 @@
 we create an object and record it in the database.  These objects
 contain the knowledge about how to access the value of the constant,
 as well as the how to initialize it.  The constants are initialized in
-several phases so that interdependencies do not prevent a problem.
+two phases so that interdependencies do not prevent a problem.
 
-The initialization process works like this:
+The initialization process works in two phases:
 
 1. create_pointer(): this creates uninitialized pointers, so that
    circular references can be handled.
 
-2. initialize_opaque(): initializes all objects except for
-   CustomDicts.  This basically allows any operation that treats the
-   object as an opaque pointer.  Most initializations complete here.
-
-3. initialize_full(): initializes custom dicts: objects are inserted
-   into dicts here because their fields have been initialized.  This
-   assumes that no custom dicts are inserted into any other custom dicts.
+2. initialize_data(): initializes everything else.  The constants are
+   first sorted by PRIORITY so that CustomDicts are initialized last.
 
-These three methods will be invoked by the database's gen_constants()
+These two methods will be invoked by the ConstantGenerator's gen_constants()
 routine.
+
+A backend will typically create its own version of each kind of Const class,
+adding at minimum a push() and store() method.  A custom variant of
+BaseConstantGenerator is also needed.  These classes can also be chosen
+by the genoo.py subclass of the backend
 """
 
+from pypy.rpython.lltypesystem import llmemory
 from pypy.rpython.ootypesystem import ootype
+import operator
 
 PRIMITIVE_TYPES = set([ootype.Void, ootype.Bool, ootype.Char, ootype.UniChar,
                        ootype.Float, ootype.Signed, ootype.Unsigned,
@@ -36,29 +38,273 @@
     return TYPE in PRIMITIVE_TYPES
 
 def push_constant(db, TYPE, value, gen):
-    """ Class method that pushes the value of the specified
-    constant onto the stack.  May or may not create an abstract constant
-    object.
+    """ General method that pushes the value of the specified constant
+    onto the stack.  Use this when you want to load a constant value.
+    May or may not create an abstract constant object.
     
     db --- a Database
     TYPE --- the ootype of the constant
-    value --- the ootype instance
+    value --- the ootype instance (ootype._list, int, etc)
     gen --- a metavm.Generator
     """
+
+    constgen = db.constant_generator
+    
     if is_primitive(TYPE):
-        return gen.push_primitive_constant(TYPE, value)
+        return constgen.push_primitive_constant(gen, TYPE, value)
 
-    const = db.record_const(value)
-    if const.is_null():
-        gen.push_null(TYPE)
+    const = constgen.record_const(value)
+    if const.is_inline():
+        const.push_inline(gen, TYPE)
     else:
-        const.push(gen)
+        constgen.push_constant(gen, const)
+        if TYPE is not const.OOTYPE():
+            constgen.downcast_constant(gen, value, TYPE)
 
 # ______________________________________________________________________
 # Constant generator
+#
+# The back-end can specify which constant generator to use by setting
+# genoo.ConstantGenerator to the appropriate class.  The
+# ConstantGenerator handles invoking the constant's initialization
+# routines, as well as loading and storing them.
+#
+# For the most part, no code needs to interact with the constant
+# generator --- the rest of the code base should always invoke
+# push_constant(), which may delegate to the constant generator if
+# needed.
+
+class BaseConstantGenerator(object):
+
+    def __init__(self, db):
+        self.db = db
+        self.genoo = db.genoo
+        self.cache = {}
+
+    # _________________________________________________________________
+    # Constant Operations
+    #
+    # Methods for loading and storing the value of constants.  Clearly,
+    # storing the value of a constant is only done internally.  These
+    # must be overloaded by the specific backend.  Note that there
+    # are some more specific variants below that do not have to be overloaded
+    # but may be.
+
+    def push_constant(self, gen, const):
+        """
+        gen --- a generator
+        const --- an AbstractConst object
+
+        Loads the constant onto the stack.  Can be invoked at any time.
+        """        
+        raise NotImplementedError
+
+    def _store_constant(self, gen, const):
+        """
+        gen --- a generator
+        const --- an AbstractConst object
+
+        stores the constant from the stack
+        """
+        raise NotImplementedError
+
+    # _________________________________________________________________
+    # Optional Constant Operations
+    #
+    # These allow various hooks at convenient times.  All of them are
+    # already implemented and you don't need to overload them.
+
+    def push_primitive_constant(self, gen, TYPE, value):
+        """ Invoked when an attempt is made to push a primitive
+        constant.  Normally just passes the call onto the code
+        generator. """
+        gen.push_primitive_constant(TYPE, value)
+
+    def downcast_constant(self, gen, const, EXPECTED_TYPE):
+        """ Invoked when the expected type of a const does not match
+        const.OOTYPE().  The constant has been pushed.  Normally just
+        invokes gen.downcast.  When it finishes, constant should still
+        be on the stack. """
+        gen.downcast(EXPECTED_TYPE)
+    
+    def _init_constant(self, const):
+        """
+        const --- a freshly created AbstractConst object
+
+        Gives the generator a chance to set any fields it wants on the
+        constant just after the object is first created.  Not invoked
+        while generating constant initialization code, but before.
+        """
+        pass
+    
+    def _push_constant_during_init(self, gen, const):
+        """
+        gen --- a generator
+        const --- an AbstractConst object
+
+        Just like push_constant, but only invoked during
+        initialization.  By default simply invokes push_constant().
+        """        
+        return self.push_constant(gen, const)
+
+    def _pre_store_constant(self, gen, const):
+        """
+        gen --- a generator
+        const --- an AbstractConst object
+
+        invoked before the constant's create_pointer() routine is
+        called, to prepare the stack in any way needed.  Typically
+        does nothing, but sometimes pushes the 'this' pointer if the
+        constant will be stored in the field of a singleton object.
+        """
+        pass
+        
+    # _________________________________________________________________
+    # Constant Object Creation
+    #
+    # Code that deals with creating AbstractConst objects and recording
+    # them.  You should not need to change anything here.
+    
+    def record_const(self, value):
+        """ Returns an object representing the constant, remembering
+        also any details needed to initialize the constant.  value
+        should be an ootype constant value.  Not generally called
+        directly, but it can be if desired. """
+        assert not is_primitive(value)
+        if value in self.cache:
+            return self.cache[value]
+        const = self._create_complex_const(value)
+        self.cache[value] = const
+        self._init_constant(const)
+        const.record_dependencies()
+        return const
 
-class ConstantGenerator(object):
-    pass
+    def _create_complex_const(self, value):
+
+        """ A helper method which creates a Constant wrapper object for
+        the given value.  Uses the types defined in the sub-class. """
+        
+        # Determine if the static type differs from the dynamic type.
+        if isinstance(value, ootype._view):
+            static_type = value._TYPE
+            value = value._inst
+        else:
+            static_type = None
+
+        # Find the appropriate kind of Const object.
+        genoo = self.genoo
+        uniq = self.db.unique()
+        if isinstance(value, ootype._instance):
+            return genoo.InstanceConst(self.db, value, static_type, uniq)
+        elif isinstance(value, ootype._record):
+            return genoo.RecordConst(self.db, value, uniq)
+        elif isinstance(value, ootype._class):
+            return genoo.ClassConst(self.db, value, uniq)
+        elif isinstance(value, ootype._list):
+            return genoo.ListConst(self.db, value, uniq)
+        elif isinstance(value, ootype._static_meth):
+            return genoo.StaticMethodConst(self.db, value, uniq)
+        elif isinstance(value, ootype._custom_dict):
+            return genoo.CustomDictConst(self.db, value, uniq)
+        elif isinstance(value, ootype._dict):
+            return genoo.DictConst(self.db, value, uniq)
+        elif isinstance(value, llmemory.fakeweakaddress):
+            return genoo.WeakRefConst(self.db, value, uniq)
+        else:
+            assert False, 'Unknown constant: %s' % value        
+
+    # _________________________________________________________________
+    # Constant Generation
+    #
+    # You will not generally need to overload any of the functions
+    # in this section.
+
+    def gen_constants(self, ilasm):
+
+        # Sort constants by priority.  Don't bother with inline
+        # constants.
+        all_constants = [c for c in self.cache.values() if not c.is_inline()]
+        all_constants.sort(key=lambda c: (c.PRIORITY, c.count))
+
+        # Counters to track how many steps we have emitted so far, etc.
+        # See _consider_step() for more information.
+        self._step_counter = 0
+        self._all_counter = 0
+
+        # Now, emit the initialization code:
+        gen = self._begin_gen_constants(ilasm, all_constants)
+        for const in all_constants:
+            self._declare_const(gen, const)
+        self._create_pointers(gen, all_constants)
+        self._initialize_data(gen, all_constants)
+        self._end_step(gen)
+        self._end_gen_constants(gen, self._step_counter)
+
+    def _create_pointers(self, gen, all_constants):
+        """ Iterates through each constant, creating the pointer for it
+        and storing it. """
+        gen.add_section("Create Pointer Phase")
+        for const in all_constants:
+            gen.add_comment("Constant: %s" % const.name)
+            self._pre_store_constant(gen, const)
+            self._consider_step(gen)
+            const.create_pointer(gen)
+            self._store_constant(gen, const)
+
+    def _initialize_data(self, gen, all_constants):
+        """ Iterates through each constant, initializing its data. """
+        gen.add_section("Initialize Data Phase")
+        for const in all_constants:
+            gen.add_comment("Constant: %s" % const.name)
+            self._push_constant_during_init(gen, const)
+            self._consider_step(gen)
+            if not const.initialize_data(gen):
+                gen.pop(const.OOTYPE())
+
+    def _consider_step(self, gen):
+        """ Considers whether to start a new step at this point.  We
+        start a new step every so often to ensure the initialization
+        functions don't get too large and upset mono or the JVM or
+        what have you. """
+        if (self._all_counter % 100) == 0:
+            self._end_step(gen)
+            self._declare_step(gen, self._step_counter) # open the next step
+        self._all_counter += 1
+
+    def _end_step(self, gen):
+        """ Ends the current step if one has begun. """
+        if self._all_counter != 0:
+            self._close_step(gen, self._step_counter) # close previous step
+            self._step_counter += 1
+
+    # _________________________________________________________________
+    # Abstract functions you must overload
+
+    def _begin_gen_constants(self, ilasm, all_constants):
+        """ Invoked with the assembler and sorted list of constants
+        before anything else.  Expected to return a generator that will
+        be passed around after that (the parameter named 'gen'). """
+        raise NotImplementedError
+
+    def _declare_const(self, gen, const):
+        """ Invoked once for each constant before any steps are created. """
+        raise NotImplementedError        
+
+    def _declare_step(self, gen, stepnum):
+        """ Invoked to begin step #stepnum.  stepnum starts with 0 (!)
+        and proceeds monotonically. If _declare_step() is invoked,
+        there will always be a corresponding call to _close_step(). """
+        raise NotImplementedError     
+    
+    def _close_step(self, gen, stepnum):
+        """ Invoked to end step #stepnum.  Never invoked without a
+        corresponding call from _declare_step() first. """
+        raise NotImplementedError        
+    
+    def _end_gen_constants(self, gen, numsteps):
+        """ Invoked as the very last thing.  numsteps is the total number
+        of steps that were created. """
+        raise NotImplementedError        
 
 # ______________________________________________________________________
 # Constant base class
@@ -66,6 +312,12 @@
 class AbstractConst(object):
     PRIORITY = 0
 
+    def __init__(self, db, value, count):
+        self.db = db
+        self.cts = db.genoo.TypeSystem(db)
+        self.value = value
+        self.count = count
+
     # ____________________________________________________________
     # Hashing, equality comparison, and repr()
     #
@@ -86,13 +338,13 @@
 
     # ____________________________________________________________
     # Simple query routines
+
+    def OOTYPE(self):
+        return self.value._TYPE
     
     def get_name(self):
         pass
 
-    def get_type(self):
-        pass
-
     def is_null(self):
         return self.value is ootype.null(self.value._TYPE)
 
@@ -101,29 +353,20 @@
         Inline constants are not stored as static fields in the
         Constant class, but they are newly created on the stack every
         time they are used. Classes overriding is_inline should
-        override _load too.
+        override push_inline too.  By default only NULL constants are
+        inlined.
         """
-        return self.is_null() # by default only null constants are inlined
+        return self.is_null()
 
-    # ____________________________________________________________
-    # Loading and storing the constant
-    #
-    # These method are left here as an example.  They are commented
-    # out because they must be implemented by the backend as a mix-in,
-    # and this way there is no conflict between the two base classes.
-
-    #def push(self, gen):
-    #    """
-    #    Pushes the value of this constant onto the stack.
-    #    """
-    #    raise NotImplementedException
-
-    #def store(self, gen):
-    #    """
-    #    The value of the constant will be pushed onto the stack;
-    #    store places it somewhere so it can later be loaded.
-    #    """
-    #    raise NotImplementedException
+    def push_inline(self, gen, EXPECTED_TYPE):
+        """
+        Invoked by push_constant() when is_inline() returns true.
+        By default, just pushes NULL as only NULL constants are inlined.
+        If you overload this, overload is_inline() too.
+        """
+        assert self.is_inline() and self.is_null()
+        return gen.push_null(EXPECTED_TYPE)
+        
 
     # ____________________________________________________________
     # Initializing the constant
@@ -141,23 +384,16 @@
         Creates the pointer representing this object, but does not
         initialize its fields.  First phase of initialization.
         """
-        raise NotImplementedException
-
-    def initialize_opaque(self, gen):
-        """
-        Initializes any constants that only use other constants in an
-        opaque fashion, without relying on them being fully initialized.
-        The big exception are custom dictionaries.
-        """
-        raise NotImplementedException
+        assert not self.is_null()
+        gen.new(self.value._TYPE)
 
-    def initialize_full(self, gen):
+    def initialize_data(self, gen):
         """
-        Initializes all remaining constants, such as custom dicts,
-        that inspect the fields of their arguments.  If it is ever the
-        case that such constants try to access one another, we'll need
-        to add a dependence graph, but currently the execution order
-        of this function between constants is undefined.
+        Initializes the internal data.  Begins with a pointer to
+        the constant on the stack.  Normally returns something
+        false (like, say, None) --- but returns True if it consumes
+        the pointer from the stack in the process; otherwise, a pop
+        is automatically inserted afterwards.
         """
         raise NotImplementedException
 
@@ -166,7 +402,7 @@
     
     def _record_const_if_complex(self, TYPE, value):
         if not is_primitive(TYPE):
-            self.db.record_const(value)
+            self.db.constant_generator.record_const(value)
 
 
 # ______________________________________________________________________
@@ -174,9 +410,7 @@
     
 class RecordConst(AbstractConst):
     def __init__(self, db, record, count):
-        self.db = db
-        self.cts = db.genoo.TypeSystem(db)
-        self.value = record
+        AbstractConst.__init__(self, db, record, count)
         self.name = 'RECORD__%d' % count
 
     def record_dependencies(self):
@@ -186,34 +420,22 @@
             value = self.value._items[f_name]            
             self._record_const_if_complex(FIELD_TYPE, value)
 
-    def create_pointer(self, gen):
-        assert not self.is_null()
-        gen.new(self.value._TYPE)
-        self.store(gen)
-
-    def initialize_opaque(self, gen):
+    def initialize_data(self, gen):
         assert not self.is_null()
-        self.push(gen)
         SELFTYPE = self.value._TYPE
         for f_name, (FIELD_TYPE, f_default) in self.value._TYPE._fields.iteritems():
             if FIELD_TYPE is not ootype.Void:
                 gen.dup(SELFTYPE)
-                #gen.load(value)
-                load(self.db, FIELD_TYPE, value, gen)
+                push_constant(self.db, FIELD_TYPE, value, gen)
                 gen.set_field(SELFTYPE, f_name)
         gen.pop(SELFTYPE)
 
-    def initialize_full(self, gen):
-        pass
-
 # ______________________________________________________________________
 # Instances
     
 class InstanceConst(AbstractConst):
     def __init__(self, db, obj, static_type, count):
-        self.db = db
-        self.value = obj
-        self.cts = db.genoo.TypeSystem(db)
+        AbstractConst.__init__(self, db, obj, count)
         if static_type is None:
             self.static_type = obj._TYPE
         else:
@@ -240,11 +462,6 @@
     def is_null(self):
         return not self.value
 
-    def create_pointer(self, gen):
-        assert not self.is_null()
-        gen.new(self.value._TYPE)
-        self.store(gen)
-
     def _sorted_const_list(self):
         # XXX, horrible hack: first collect all consts, then render
         # CustomDicts at last because their ll_set could need other
@@ -271,7 +488,7 @@
 
         return const_list
 
-    def initialize_opaque(self, gen):
+    def initialize_data(self, gen):
         assert not self.is_null()
 
         # Get a list of all the constants we'll need to initialize.
@@ -282,7 +499,6 @@
         # Push ourself on the stack, and cast to our actual type if it
         # is not the same as our static type
         SELFTYPE = self.value._TYPE
-        self.push(gen)
         if SELFTYPE is not self.static_type:
             gen.downcast(SELFTYPE)
 
@@ -295,17 +511,12 @@
         # Pop selves from stack when done.
         gen.pop(SELFTYPE)
 
-    def initialize_full(self, gen):
-        pass
-
 # ______________________________________________________________________
 # Class constants
 
 class ClassConst(AbstractConst):
     def __init__(self, db, class_, count):
-        self.db = db
-        self.cts = db.genoo.TypeSystem(db)
-        self.value = class_
+        AbstractConst.__init__(self, db, class_, count)
         self.name = 'CLASS__%d' % count
 
     def record_dependencies(self):
@@ -316,17 +527,144 @@
     def is_null(self):
         return self.value._INSTANCE is None
 
-    def is_inline(self):
-        return True
-
     def create_pointer(self, gen):
         assert not self.is_null()
         INSTANCE = self.value._INSTANCE
         gen.getclassobject(INSTANCE)
-        self.store(gen)
 
-    def initialize_opaque(self, gen):
+    def initialize_data(self, gen):
         pass
 
-    def initialize_full(self, gen):
-        pass
+# ______________________________________________________________________
+# List constants
+
+class ListConst(AbstractConst):
+    def __init__(self, db, list, count):
+        AbstractConst.__init__(self, db, list, count)
+        self.name = 'LIST__%d' % count
+
+    def record_dependencies(self):
+        if not self.value:
+            return
+        for item in self.value._list:
+            self._record_const_if_complex(self.value._TYPE._ITEMTYPE, item)
+
+    def create_pointer(self, gen):
+        assert not self.is_null()
+        SELFTYPE = self.value._TYPE
+
+        # XXX --- should we add something special to the generator for
+        # this?  I want it to look exactly like it would in normal
+        # opcodes...but of course under current system I can't know
+        # what normal opcodes would look like as they fall under the
+        # perview of each backend rather than oosupport
+        
+        # Create the list
+        gen.new(SELFTYPE)
+        
+        # And then resize it to the correct size
+        gen.dup()
+        push_constant(self.db, ootype.Signed, len(self.value._list), gen)
+        gen.call_method(SELFTYPE, '_ll_resize')
+
+    def _do_not_initialize(self):
+        """ Returns True if the list should not be initialized; this
+        can be overloaded by the backend if your conditions are wider.
+        The default is not to initialize if the list is a list of
+        Void. """
+        return self.value._TYPE._ITEMTYPE is ootype.Void
+        try:
+            return self.value._list == [0] * len(self.value._list)
+        except:
+            return False
+
+    def initialize_data(self, gen):
+        assert not self.is_null()
+        SELFTYPE = self.value._TYPE
+        ITEMTYPE = self.value._TYPE._ITEMTYPE
+
+        # check for special cases and avoid initialization
+        if self._do_not_initialize():
+            return
+
+        # set each item in the list using the OOTYPE methods
+        for idx, item in enumerate(self.value._list):
+            gen.dup(SELFTYPE)
+            push_constant(self.db, ootype.Signed, idx, gen)
+            push_constant(self.db, ITEMTYPE, item, gen)
+            gen.call_method(SELFFTYPE, 'll_setitem_fast')
+
+# ______________________________________________________________________
+# Dictionary constants
+
+class DictConst(AbstractConst):
+    def __init__(self, db, dict, count):
+        AbstractConst.__init__(self, db, dict, count)
+        self.name = 'DICT__%d' % count
+
+    def record_dependencies(self):
+        if not self.value:
+            return
+        
+        for key, value in self.value._dict.iteritems():
+            self._record_const_if_complex(self.value._TYPE._KEYTYPE, key)
+            self._record_const_if_complex(self.value._TYPE._VALUETYPE, value)
+
+    def initialize_data(self, gen):
+        assert not self.is_null()
+        SELFTYPE = self.value._TYPE
+        KEYTYPE = self.value._TYPE._KEYTYPE
+        VALUETYPE = self.value._TYPE._VALUETYPE
+
+        if KEYTYPE is ootype.Void:
+            assert VALUETYPE is ootype.Void
+            return
+
+        for key, value in self.value._dict.iteritems():
+            gen.dup(SELFTYPE)
+            push_constant(self.db, KEYTYPE, key, gen)
+            if VALUETYPE is ootype.Void:
+                # special case dict of Void
+                gen.dup(KEYTYPE)
+            else:
+                push_constant(self.db, VALUETYPE, value, gen)
+            gen.call_method(SELFTYPE, 'll_set')
+
+class CustomDictConst(DictConst):
+    PRIORITY = 100
+
+# ______________________________________________________________________
+# Static method constants
+
+class StaticMethodConst(AbstractConst):
+    def __init__(self, db, sm, count):
+        AbstractConst.__init__(self, db, sm, count)
+        self.name = 'DELEGATE__%d' % count
+
+    def record_dependencies(self):
+        if self.value is ootype.null(self.value._TYPE):
+            return
+        self.db.pending_function(self.value.graph)
+        self.delegate_type = self.db.record_delegate(self.value._TYPE)
+
+    def initialize_data(self, ilasm):
+        raise NotImplementedError
+
+# ______________________________________________________________________
+# Weak Reference constants
+
+class WeakRefConst(AbstractConst):
+    def __init__(self, db, fakeaddr, count):
+        AbstractConst.__init__(self, db, fakeaddr.get(), count)
+        self.name = 'WEAKREF__%d' % count
+
+    def OOTYPE(self):
+        # Not sure what goes here...?
+        return None
+    
+    def is_null(self):
+        return False
+
+    def record_dependencies(self):
+        if self.value is not None:
+            self.db.constant_generator.record_const(self.value)

Modified: pypy/dist/pypy/translator/oosupport/database.py
==============================================================================
--- pypy/dist/pypy/translator/oosupport/database.py	(original)
+++ pypy/dist/pypy/translator/oosupport/database.py	Tue Nov  7 22:24:19 2006
@@ -8,8 +8,9 @@
         self.cts = genoo.TypeSystem(self)
         self._pending_nodes = set()
         self._rendered_nodes = set()
-        self._const_cache = {}
         self._unique_counter = 0
+        self.constant_generator = genoo.ConstantGenerator(self)
+        self.locked = False # new pending nodes are not allowed here
 
     # ____________________________________________________________
     # Miscellaneous
@@ -30,45 +31,18 @@
 
     def gen_constants(self, ilasm):
         """ Renders the constants uncovered during the graph walk"""
+        self.locked = True # new pending nodes are not allowed here
+        self.constant_generator.gen_constants(ilasm)
+        self.locked = False
 
-        # Now, emit the initialization code:
-        all_constants = self._const_cache.values()
-        gen = self._begin_gen_constants(ilasm, all_constants)
-        gen.add_section("Create Pointer Phase")
-        ctr = 0
-        for const in all_constants:
-            gen.add_comment("Constant: %s" % const.name)
-            const.create_pointer(gen)
-            ctr = self._consider_interrupt(gen, ctr)
-        gen.add_section("Initialize Opaque Phase")
-        for const in all_constants:
-            gen.add_comment("Constant: %s" % const.name)
-            const.initialize_opaque(gen)
-            ctr = self._consider_interrupt(gen, ctr)
-        gen.add_section("Initialize Full Phase")
-        for const in all_constants:
-            gen.add_comment("Constant: %s" % const.name)
-            const.initialize_full(gen)
-            ctr = self._consider_interrupt(gen, ctr)
-        self._end_gen_constants(gen)
-
-    def _consider_interrupt(self, gen, ctr):
-        ctr += 1
-        if (ctr % 100) == 0: self._interrupt_gen_constants(gen)
-        return ctr
+    # ____________________________________________________________
+    # Generation phases
 
-    def _begin_gen_constants(self):
-        # returns a generator
+    def record_delegate(self, OOTYPE):
+        """ Returns a backend-specific type for a delegate class...
+        details currently undefined. """
         raise NotImplementedError
 
-    def _interrupt_gen_constants(self):
-        # invoked every so often so as to break up the generated
-        # code and not create one massive function
-        pass
-    
-    def _end_gen_constants(self, gen):
-        raise NotImplementedError        
-
     # ____________________________________________________________
     # Node creation
     #
@@ -89,8 +63,11 @@
     def pending_node(self, node):
         """ Adds a node to the worklist, so long as it is not already there
         and has not already been rendered. """
-        if node not in self._rendered_nodes:
-            self._pending_nodes.add(node)
+        assert not self.locked # sanity check
+        if node in self._pending_nodes or node in self._rendered_nodes:
+            return
+        self._pending_nodes.add(node)
+        node.dependencies()
             
     def len_pending(self):
         return len(self._pending_nodes)
@@ -98,61 +75,3 @@
     def pop(self):
         return self._pending_nodes.pop()
 
-    # ____________________________________________________________
-    # Constants
-
-    # Defines the subclasses used to represent complex constants by
-    # _create_complex_const:
-    
-    InstanceConst = None
-    RecordConst = None
-    ClassConst = None
-
-    def record_const(self, value):
-        """ Returns an object representing the constant, remembering also
-        any details needed to initialize the constant.  value should be an
-        ootype constant value """
-        assert not is_primitive(value)
-        if value in self._const_cache:
-            return self._const_cache[value]
-        const = self._create_complex_const(value)
-        self._const_cache[value] = const
-        const.record_dependencies()
-        return const
-
-    def push_primitive_const(self, gen, value):
-        """ Helper which pushes a primitive constant onto the stack """ 
-        raise NotImplementedException
-
-    def _create_complex_const(self, value):
-
-        """ A helper method which creates a Constant wrapper object for
-        the given value.  Uses the types defined in the sub-class. """
-        
-        # Determine if the static type differs from the dynamic type.
-        if isinstance(value, ootype._view):
-            static_type = value._TYPE
-            value = value._inst
-        else:
-            static_type = None
-
-        # Find the appropriate kind of Const object.
-        if isinstance(value, ootype._instance):
-            return self.InstanceConst(self, value, static_type, self.unique())
-        elif isinstance(value, ootype._record):
-            return self.RecordConst(self, value, self.unique())
-        elif isinstance(value, ootype._class):
-            return self.ClassConst(self, value, self.unique())
-        #elif isinstance(value, ootype._list):
-        #    return ListConst(db, value, count)
-        #elif isinstance(value, ootype._static_meth):
-        #    return StaticMethodConst(db, value, count)
-        #elif isinstance(value, ootype._custom_dict):
-        #    return CustomDictConst(db, value, count)
-        #elif isinstance(value, ootype._dict):
-        #    return DictConst(db, value, count)
-        #elif isinstance(value, llmemory.fakeweakaddress):
-        #    return WeakRefConst(db, value, count)
-        else:
-            assert False, 'Unknown constant: %s' % value
-

Modified: pypy/dist/pypy/translator/oosupport/function.py
==============================================================================
--- pypy/dist/pypy/translator/oosupport/function.py	(original)
+++ pypy/dist/pypy/translator/oosupport/function.py	Tue Nov  7 22:24:19 2006
@@ -132,7 +132,7 @@
                 continue # see above
             assert issubclass(link.exitcase, Exception)
             ll_meta_exc = link.llexitcase
-            self.db.record_const(ll_meta_exc)
+            self.db.constant_generator.record_const(ll_meta_exc)
             self.begin_catch(link.llexitcase)
             self.store_exception_and_link(link)
             target_label = self._get_block_name(link.target)

Modified: pypy/dist/pypy/translator/oosupport/genoo.py
==============================================================================
--- pypy/dist/pypy/translator/oosupport/genoo.py	(original)
+++ pypy/dist/pypy/translator/oosupport/genoo.py	Tue Nov  7 22:24:19 2006
@@ -11,6 +11,19 @@
     opcodes = None
     log = None
 
+    # Defines the subclasses used to represent complex constants by
+    # _create_complex_const:
+    
+    ConstantGenerator = None
+    InstanceConst = None
+    RecordConst = None
+    ClassConst = None
+    ListConst = None
+    StaticMethodConst = None
+    CustomDictConst = None
+    DictConst = None
+    WeakRefConst = None
+
     def __init__(self, tmpdir, translator, entrypoint, config=None):
         self.tmpdir = tmpdir
         self.translator = translator



More information about the Pypy-commit mailing list