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

antocuni at codespeak.net antocuni at codespeak.net
Fri Sep 7 19:15:01 CEST 2007


Author: antocuni
Date: Fri Sep  7 19:14:59 2007
New Revision: 46407

Modified:
   pypy/dist/pypy/translator/cli/constant.py
   pypy/dist/pypy/translator/jvm/constant.py
   pypy/dist/pypy/translator/jvm/generator.py
   pypy/dist/pypy/translator/jvm/test/test_constant.py
   pypy/dist/pypy/translator/oosupport/constant.py
   pypy/dist/pypy/translator/oosupport/metavm.py
Log:
Split the methods that initialize the constants, if they become too large.



Modified: pypy/dist/pypy/translator/cli/constant.py
==============================================================================
--- pypy/dist/pypy/translator/cli/constant.py	(original)
+++ pypy/dist/pypy/translator/cli/constant.py	Fri Sep  7 19:14:59 2007
@@ -294,11 +294,11 @@
             return True
         return False
     
-    def initialize_data(self, gen):
+    def initialize_data(self, constgen, gen):
         # special case: dict of void, ignore the values
         if self._check_for_void_dict(gen):
             return 
-        return super(CLIDictMixin, self).initialize_data(gen)    
+        return super(CLIDictMixin, self).initialize_data(constgen, gen)
 
 # ______________________________________________________________________
 # Constant Classes
@@ -390,7 +390,7 @@
         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):
+    def initialize_data(self, constgen, gen):
         return
 
         
@@ -403,7 +403,7 @@
     def get_type(self, include_class=True):
         return 'class ' + WEAKREF
     
-    def initialize_data(self, gen):
+    def initialize_data(self, constgen, gen):
         if self.value is not None:
             push_constant(self.db, self.value._TYPE, self.value, gen)
             gen.ilasm.call_method(

Modified: pypy/dist/pypy/translator/jvm/constant.py
==============================================================================
--- pypy/dist/pypy/translator/jvm/constant.py	(original)
+++ pypy/dist/pypy/translator/jvm/constant.py	Fri Sep  7 19:14:59 2007
@@ -17,6 +17,8 @@
 
 class JVMConstantGenerator(BaseConstantGenerator):
 
+    MAX_INSTRUCTION_COUNT = 20000
+
     def __init__(self, db):
         BaseConstantGenerator.__init__(self, db)
         self.num_constants = 0
@@ -112,6 +114,13 @@
         # in JVM, this is done first, in gen_constants()
         return
 
+    def _consider_split_current_function(self, gen):
+        if gen.get_instruction_count() >= self.MAX_INSTRUCTION_COUNT:
+            const = self.current_const
+            gen.pop(const.value._TYPE)
+            self._new_step(gen)
+            self._push_constant_during_init(gen, const)
+
     def _declare_step(self, gen, stepnum):
         self.step_classes.append(JvmClassType('pypy.ConstantInit_%d' % stepnum))
         gen.begin_class(self.step_classes[-1], jObject)
@@ -149,7 +158,7 @@
         else:
             gen.push_null(jObject)
 
-    def initialize_data(self, ilasm):
+    def initialize_data(self, constgen, gen):
         return
     
 class JVMCustomDictConst(CustomDictConst):
@@ -191,7 +200,7 @@
             push_constant(self.db, self.value._TYPE, self.value, gen)
         gen.finalize_cast_ptr_to_weak_address(TYPE)
 
-    def initialize_data(self, gen):
+    def initialize_data(self, constgen, gen):
         gen.pop(ootype.ROOT)
         return True
     

Modified: pypy/dist/pypy/translator/jvm/generator.py
==============================================================================
--- pypy/dist/pypy/translator/jvm/generator.py	(original)
+++ pypy/dist/pypy/translator/jvm/generator.py	Fri Sep  7 19:14:59 2007
@@ -1366,3 +1366,5 @@
             tryendlbl.jasmin_syntax(),
             catchlbl.jasmin_syntax()))
                        
+    def get_instruction_count(self):
+        return self.curfunc.instr_counter

Modified: pypy/dist/pypy/translator/jvm/test/test_constant.py
==============================================================================
--- pypy/dist/pypy/translator/jvm/test/test_constant.py	(original)
+++ pypy/dist/pypy/translator/jvm/test/test_constant.py	Fri Sep  7 19:14:59 2007
@@ -3,6 +3,4 @@
 from pypy.translator.jvm.test.runtest import JvmTest
 
 class TestConstant(BaseTestConstant, JvmTest):
-
-    def test_many_constants(self):
-        py.test.skip('Initializing a large constant list generates a function too large for the JVM limits')
+    pass

Modified: pypy/dist/pypy/translator/oosupport/constant.py
==============================================================================
--- pypy/dist/pypy/translator/oosupport/constant.py	(original)
+++ pypy/dist/pypy/translator/oosupport/constant.py	Fri Sep  7 19:14:59 2007
@@ -265,7 +265,8 @@
             self._consider_step(gen)
             gen.add_comment("Constant: %s" % const.name)
             self._push_constant_during_init(gen, const)
-            if not const.initialize_data(gen):
+            self.current_const = const
+            if not const.initialize_data(self, gen):
                 gen.pop(const.OOTYPE())
 
     def _consider_step(self, gen):
@@ -273,11 +274,23 @@
         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 % MAX_CONST_PER_STEP) == 0:
-            self._end_step(gen)
-            self._declare_step(gen, self._step_counter) # open the next step
+        if self._all_counter % MAX_CONST_PER_STEP == 0:
+            self._new_step(gen)
         self._all_counter += 1
 
+    def _consider_split_current_function(self, gen):
+        """
+        Called during constant initialization; if the backend thinks
+        the current function is too large, it can close it and open a
+        new one, pushing again the constant on the stack. The default
+        implementatio does nothing.
+        """
+        pass
+
+    def _new_step(self, gen):
+        self._end_step(gen)
+        self._declare_step(gen, self._step_counter) # open the next step
+
     def _end_step(self, gen):
         """ Ends the current step if one has begun. """
         if self._all_counter != 0:
@@ -393,7 +406,7 @@
         assert not self.is_null()
         gen.new(self.value._TYPE)
 
-    def initialize_data(self, gen):
+    def initialize_data(self, constgen, gen):
         """
         Initializes the internal data.  Begins with a pointer to
         the constant on the stack.  Normally returns something
@@ -441,7 +454,7 @@
             value = self.value._items[f_name]            
             self._record_const_if_complex(FIELD_TYPE, value)
 
-    def initialize_data(self, gen):
+    def initialize_data(self, constgen, gen):
         assert not self.is_null()
         SELFTYPE = self.value._TYPE
         for f_name, (FIELD_TYPE, f_default) in self.value._TYPE._fields.iteritems():
@@ -509,7 +522,7 @@
 
         return const_list
 
-    def initialize_data(self, gen):
+    def initialize_data(self, constgen, gen):
         assert not self.is_null()
 
         # Get a list of all the constants we'll need to initialize.
@@ -525,6 +538,7 @@
 
         # Store each of our fields in the sorted order
         for FIELD_TYPE, INSTANCE, name, value in const_list:
+            constgen._consider_split_current_function(gen)
             gen.dup(SELFTYPE)
             push_constant(self.db, FIELD_TYPE, value, gen)
             gen.set_field(INSTANCE, name)
@@ -550,7 +564,7 @@
         INSTANCE = self.value._INSTANCE
         gen.getclassobject(INSTANCE)
 
-    def initialize_data(self, gen):
+    def initialize_data(self, constgen, gen):
         pass
 
 # ______________________________________________________________________
@@ -596,7 +610,7 @@
         except:
             return False
 
-    def initialize_data(self, gen):
+    def initialize_data(self, constgen, gen):
         assert not self.is_null()
         SELFTYPE = self.value._TYPE
         ITEMTYPE = self.value._TYPE._ITEMTYPE
@@ -607,6 +621,7 @@
 
         # set each item in the list using the OOTYPE methods
         for idx, item in enumerate(self.value._list):
+            constgen._consider_split_current_function(gen)
             gen.dup(SELFTYPE)
             push_constant(self.db, ootype.Signed, idx, gen)
             push_constant(self.db, ITEMTYPE, item, gen)
@@ -631,7 +646,7 @@
             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):
+    def initialize_data(self, constgen, gen):
         assert not self.is_null()
         SELFTYPE = self.value._TYPE
         KEYTYPE = self.value._TYPE._KEYTYPE
@@ -644,6 +659,7 @@
             return
 
         for key, value in self.value._dict.iteritems():
+            constgen._consider_split_current_function(gen)
             gen.dup(SELFTYPE)
             gen.add_comment('  key=%r value=%r' % (key,value))
             push_constant(self.db, KEYTYPE, key, gen)
@@ -669,7 +685,7 @@
         self.db.pending_function(self.value.graph)
         self.delegate_type = self.db.record_delegate(self.value._TYPE)
 
-    def initialize_data(self, ilasm):
+    def initialize_data(self, constgen, gen):
         raise NotImplementedError
 
 # ______________________________________________________________________

Modified: pypy/dist/pypy/translator/oosupport/metavm.py
==============================================================================
--- pypy/dist/pypy/translator/oosupport/metavm.py	(original)
+++ pypy/dist/pypy/translator/oosupport/metavm.py	Fri Sep  7 19:14:59 2007
@@ -195,7 +195,14 @@
         value.  TYPE will be one of the types enumerated in
         oosupport.constant.PRIMITIVE_TYPES.  value will be its
         corresponding ootype implementation. """
-        raise NotImplementedError        
+        raise NotImplementedError
+
+    def get_instrution_count(self):
+        """
+        Return the number of opcodes in the current function, or -1
+        if the backend doesn't care about it. Default is -1
+        """
+        return -1
 
 class InstructionList(list):
     def render(self, generator, op):


More information about the pypy-svn mailing list