[pypy-svn] r34887 - in pypy/branch/mininal-c-backend/pypy: . annotation annotation/test config doc interpreter interpreter/astcompiler jit/codegen/i386 jit/codegen/i386/test jit/codegen/llgraph jit/codegen/llvm jit/codegen/llvm/lib jit/codegen/llvm/test jit/codegen/ppc jit/codegen/ppc/test jit/hintannotator jit/hintannotator/test jit/timeshifter jit/timeshifter/test jit/tl lang/automata lib lib/constraint lib/distributed lib/pyontology lib/pyontology/test lib/test2 module/__builtin__ module/__builtin__/test module/_file module/_file/test module/_stackless module/_stackless/test module/pypymagic module/pypymagic/test module/rctime/test objspace objspace/cclp objspace/std objspace/std/test rlib rlib/parsing/test rlib/test rpython rpython/lltypesystem rpython/memory/gctransform rpython/test tool/build translator translator/asm/ppcgen translator/backendopt translator/backendopt/test translator/cl translator/cli translator/cli/src translator/cli/test translator/js translator/js/demo/jsdemo translator/js/demo/jsdemo/test translator/js/doc translator/js/modules translator/js/modules/test translator/llvm translator/oosupport translator/test translator/tool

ale at codespeak.net ale at codespeak.net
Thu Nov 23 12:29:25 CET 2006


Author: ale
Date: Thu Nov 23 12:28:43 2006
New Revision: 34887

Added:
   pypy/branch/mininal-c-backend/pypy/jit/codegen/ppc/test/test_genc_ts.py
      - copied unchanged from r34886, pypy/dist/pypy/jit/codegen/ppc/test/test_genc_ts.py
   pypy/branch/mininal-c-backend/pypy/jit/timeshifter/test/test_vdict.py
      - copied unchanged from r34886, pypy/dist/pypy/jit/timeshifter/test/test_vdict.py
   pypy/branch/mininal-c-backend/pypy/jit/timeshifter/vdict.py
      - copied unchanged from r34886, pypy/dist/pypy/jit/timeshifter/vdict.py
   pypy/branch/mininal-c-backend/pypy/lib/distributed/   (props changed)
      - copied from r34886, pypy/dist/pypy/lib/distributed/
   pypy/branch/mininal-c-backend/pypy/lib/distributed/__init__.py
      - copied unchanged from r34886, pypy/dist/pypy/lib/distributed/__init__.py
   pypy/branch/mininal-c-backend/pypy/lib/distributed/objkeeper.py
      - copied unchanged from r34886, pypy/dist/pypy/lib/distributed/objkeeper.py
   pypy/branch/mininal-c-backend/pypy/lib/distributed/protocol.py
      - copied unchanged from r34886, pypy/dist/pypy/lib/distributed/protocol.py
   pypy/branch/mininal-c-backend/pypy/module/_stackless/clonable.py   (props changed)
      - copied unchanged from r34886, pypy/dist/pypy/module/_stackless/clonable.py
   pypy/branch/mininal-c-backend/pypy/module/_stackless/test/test_clonable.py
      - copied unchanged from r34886, pypy/dist/pypy/module/_stackless/test/test_clonable.py
   pypy/branch/mininal-c-backend/pypy/module/pypymagic/test/test_special.py
      - copied unchanged from r34886, pypy/dist/pypy/module/pypymagic/test/test_special.py
   pypy/branch/mininal-c-backend/pypy/rpython/controllerentry.py
      - copied unchanged from r34886, pypy/dist/pypy/rpython/controllerentry.py
   pypy/branch/mininal-c-backend/pypy/translator/cli/test/test_streamio.py
      - copied unchanged from r34885, pypy/dist/pypy/translator/cli/test/test_streamio.py
   pypy/branch/mininal-c-backend/pypy/translator/js/demo/jsdemo/support.py
      - copied unchanged from r34885, pypy/dist/pypy/translator/js/demo/jsdemo/support.py
   pypy/branch/mininal-c-backend/pypy/translator/js/demo/jsdemo/test/   (props changed)
      - copied from r34885, pypy/dist/pypy/translator/js/demo/jsdemo/test/
   pypy/branch/mininal-c-backend/pypy/translator/js/demo/jsdemo/test/__init__.py
      - copied unchanged from r34885, pypy/dist/pypy/translator/js/demo/jsdemo/test/__init__.py
   pypy/branch/mininal-c-backend/pypy/translator/js/demo/jsdemo/test/test_demo.py
      - copied unchanged from r34885, pypy/dist/pypy/translator/js/demo/jsdemo/test/test_demo.py
Removed:
   pypy/branch/mininal-c-backend/pypy/lib/_osfilewrapper.py
   pypy/branch/mininal-c-backend/pypy/lib/distributed.py
   pypy/branch/mininal-c-backend/pypy/lib/test2/test_osfilewrapper.py
   pypy/branch/mininal-c-backend/pypy/module/__builtin__/test/test_special.py
Modified:
   pypy/branch/mininal-c-backend/pypy/annotation/annrpython.py
   pypy/branch/mininal-c-backend/pypy/annotation/binaryop.py
   pypy/branch/mininal-c-backend/pypy/annotation/bookkeeper.py
   pypy/branch/mininal-c-backend/pypy/annotation/builtin.py
   pypy/branch/mininal-c-backend/pypy/annotation/dictdef.py
   pypy/branch/mininal-c-backend/pypy/annotation/model.py
   pypy/branch/mininal-c-backend/pypy/annotation/test/test_annrpython.py
   pypy/branch/mininal-c-backend/pypy/annotation/unaryop.py
   pypy/branch/mininal-c-backend/pypy/config/pypyoption.py
   pypy/branch/mininal-c-backend/pypy/conftest.py
   pypy/branch/mininal-c-backend/pypy/doc/_ref.txt
   pypy/branch/mininal-c-backend/pypy/doc/stackless.txt
   pypy/branch/mininal-c-backend/pypy/interpreter/astcompiler/pycodegen.py
   pypy/branch/mininal-c-backend/pypy/interpreter/executioncontext.py
   pypy/branch/mininal-c-backend/pypy/interpreter/mixedmodule.py
   pypy/branch/mininal-c-backend/pypy/jit/codegen/i386/rgenop.py
   pypy/branch/mininal-c-backend/pypy/jit/codegen/i386/test/test_genc_ts.py
   pypy/branch/mininal-c-backend/pypy/jit/codegen/llgraph/llimpl.py
   pypy/branch/mininal-c-backend/pypy/jit/codegen/llgraph/rgenop.py
   pypy/branch/mininal-c-backend/pypy/jit/codegen/llvm/   (props changed)
   pypy/branch/mininal-c-backend/pypy/jit/codegen/llvm/lib/libllvmjit.cpp
   pypy/branch/mininal-c-backend/pypy/jit/codegen/llvm/llvmjit.py
   pypy/branch/mininal-c-backend/pypy/jit/codegen/llvm/test/test_llvmjit.py
   pypy/branch/mininal-c-backend/pypy/jit/codegen/ppc/conftest.py
   pypy/branch/mininal-c-backend/pypy/jit/codegen/ppc/instruction.py
   pypy/branch/mininal-c-backend/pypy/jit/codegen/ppc/regalloc.py
   pypy/branch/mininal-c-backend/pypy/jit/codegen/ppc/rgenop.py
   pypy/branch/mininal-c-backend/pypy/jit/hintannotator/model.py
   pypy/branch/mininal-c-backend/pypy/jit/hintannotator/test/test_annotator.py
   pypy/branch/mininal-c-backend/pypy/jit/timeshifter/hrtyper.py
   pypy/branch/mininal-c-backend/pypy/jit/timeshifter/oop.py
   pypy/branch/mininal-c-backend/pypy/jit/timeshifter/rcontainer.py
   pypy/branch/mininal-c-backend/pypy/jit/timeshifter/rtimeshift.py
   pypy/branch/mininal-c-backend/pypy/jit/timeshifter/rvalue.py
   pypy/branch/mininal-c-backend/pypy/jit/timeshifter/test/test_portal.py
   pypy/branch/mininal-c-backend/pypy/jit/timeshifter/test/test_promotion.py
   pypy/branch/mininal-c-backend/pypy/jit/timeshifter/test/test_timeshift.py
   pypy/branch/mininal-c-backend/pypy/jit/timeshifter/test/test_tlc.py
   pypy/branch/mininal-c-backend/pypy/jit/timeshifter/transform.py
   pypy/branch/mininal-c-backend/pypy/jit/timeshifter/vlist.py
   pypy/branch/mininal-c-backend/pypy/jit/tl/tlc.py
   pypy/branch/mininal-c-backend/pypy/lang/automata/dfa.py
   pypy/branch/mininal-c-backend/pypy/lib/constraint/   (props changed)
   pypy/branch/mininal-c-backend/pypy/lib/pyontology/constraint_classes.py
   pypy/branch/mininal-c-backend/pypy/lib/pyontology/pyontology.py
   pypy/branch/mininal-c-backend/pypy/lib/pyontology/sparql_grammar.py   (props changed)
   pypy/branch/mininal-c-backend/pypy/lib/pyontology/test/test_ontology.py
   pypy/branch/mininal-c-backend/pypy/lib/pyontology/test/test_sparql.py   (contents, props changed)
   pypy/branch/mininal-c-backend/pypy/lib/stackless.py
   pypy/branch/mininal-c-backend/pypy/lib/test2/test_binascii.py   (props changed)
   pypy/branch/mininal-c-backend/pypy/lib/test2/test_distributed.py
   pypy/branch/mininal-c-backend/pypy/module/__builtin__/__init__.py
   pypy/branch/mininal-c-backend/pypy/module/__builtin__/importing.py
   pypy/branch/mininal-c-backend/pypy/module/__builtin__/special.py
   pypy/branch/mininal-c-backend/pypy/module/_file/app_file.py
   pypy/branch/mininal-c-backend/pypy/module/_file/test/test_file.py
   pypy/branch/mininal-c-backend/pypy/module/_stackless/__init__.py
   pypy/branch/mininal-c-backend/pypy/module/_stackless/coroutine.py
   pypy/branch/mininal-c-backend/pypy/module/_stackless/interp_clonable.py
   pypy/branch/mininal-c-backend/pypy/module/_stackless/interp_greenlet.py
   pypy/branch/mininal-c-backend/pypy/module/pypymagic/__init__.py
   pypy/branch/mininal-c-backend/pypy/module/pypymagic/interp_magic.py
   pypy/branch/mininal-c-backend/pypy/module/rctime/test/test_rctime.py
   pypy/branch/mininal-c-backend/pypy/objspace/cclp/misc.py
   pypy/branch/mininal-c-backend/pypy/objspace/logic.py
   pypy/branch/mininal-c-backend/pypy/objspace/std/multimethod.py
   pypy/branch/mininal-c-backend/pypy/objspace/std/objspace.py
   pypy/branch/mininal-c-backend/pypy/objspace/std/proxyobject.py
   pypy/branch/mininal-c-backend/pypy/objspace/std/test/test_multimethod.py
   pypy/branch/mininal-c-backend/pypy/objspace/std/test/test_proxy.py
   pypy/branch/mininal-c-backend/pypy/objspace/std/test/test_proxy_function.py
   pypy/branch/mininal-c-backend/pypy/objspace/std/test/test_proxy_internals.py
   pypy/branch/mininal-c-backend/pypy/objspace/std/test/test_strjoinobject.py
   pypy/branch/mininal-c-backend/pypy/objspace/std/transparent.py
   pypy/branch/mininal-c-backend/pypy/rlib/objectmodel.py
   pypy/branch/mininal-c-backend/pypy/rlib/parsing/test/test_ebnfparse.py
   pypy/branch/mininal-c-backend/pypy/rlib/streamio.py
   pypy/branch/mininal-c-backend/pypy/rlib/test/test_streamio.py
   pypy/branch/mininal-c-backend/pypy/rpython/annlowlevel.py
   pypy/branch/mininal-c-backend/pypy/rpython/callparse.py
   pypy/branch/mininal-c-backend/pypy/rpython/llinterp.py
   pypy/branch/mininal-c-backend/pypy/rpython/lltypesystem/lloperation.py
   pypy/branch/mininal-c-backend/pypy/rpython/lltypesystem/opimpl.py
   pypy/branch/mininal-c-backend/pypy/rpython/lltypesystem/rdict.py
   pypy/branch/mininal-c-backend/pypy/rpython/lltypesystem/rlist.py
   pypy/branch/mininal-c-backend/pypy/rpython/lltypesystem/rstr.py
   pypy/branch/mininal-c-backend/pypy/rpython/lltypesystem/rtupletype.py
   pypy/branch/mininal-c-backend/pypy/rpython/memory/gctransform/framework.py
   pypy/branch/mininal-c-backend/pypy/rpython/memory/gctransform/transform.py
   pypy/branch/mininal-c-backend/pypy/rpython/rbuiltin.py
   pypy/branch/mininal-c-backend/pypy/rpython/rint.py
   pypy/branch/mininal-c-backend/pypy/rpython/rlist.py
   pypy/branch/mininal-c-backend/pypy/rpython/rpbc.py
   pypy/branch/mininal-c-backend/pypy/rpython/rtuple.py
   pypy/branch/mininal-c-backend/pypy/rpython/test/test_rpbc.py
   pypy/branch/mininal-c-backend/pypy/rpython/test/test_rtuple.py
   pypy/branch/mininal-c-backend/pypy/tool/build/README.txt
   pypy/branch/mininal-c-backend/pypy/translator/asm/ppcgen/ppc_assembler.py
   pypy/branch/mininal-c-backend/pypy/translator/backendopt/all.py
   pypy/branch/mininal-c-backend/pypy/translator/backendopt/graphanalyze.py
   pypy/branch/mininal-c-backend/pypy/translator/backendopt/inline.py
   pypy/branch/mininal-c-backend/pypy/translator/backendopt/test/test_inline.py
   pypy/branch/mininal-c-backend/pypy/translator/cl/opformatter.py
   pypy/branch/mininal-c-backend/pypy/translator/cli/constant.py
   pypy/branch/mininal-c-backend/pypy/translator/cli/database.py
   pypy/branch/mininal-c-backend/pypy/translator/cli/dotnet.py
   pypy/branch/mininal-c-backend/pypy/translator/cli/function.py
   pypy/branch/mininal-c-backend/pypy/translator/cli/ilgenerator.py
   pypy/branch/mininal-c-backend/pypy/translator/cli/src/pypylib.cs
   pypy/branch/mininal-c-backend/pypy/translator/cli/test/test_constant.py
   pypy/branch/mininal-c-backend/pypy/translator/cli/test/test_dict.py
   pypy/branch/mininal-c-backend/pypy/translator/cli/test/test_dotnet.py
   pypy/branch/mininal-c-backend/pypy/translator/interactive.py
   pypy/branch/mininal-c-backend/pypy/translator/js/demo/jsdemo/example.py
   pypy/branch/mininal-c-backend/pypy/translator/js/demo/jsdemo/pythonconsole.py
   pypy/branch/mininal-c-backend/pypy/translator/js/doc/dom.txt
   pypy/branch/mininal-c-backend/pypy/translator/js/modules/dom.py
   pypy/branch/mininal-c-backend/pypy/translator/js/modules/test/test_dom.py
   pypy/branch/mininal-c-backend/pypy/translator/js/opcodes.py
   pypy/branch/mininal-c-backend/pypy/translator/llvm/opwriter.py
   pypy/branch/mininal-c-backend/pypy/translator/oosupport/constant.py
   pypy/branch/mininal-c-backend/pypy/translator/test/test_interactive.py
   pypy/branch/mininal-c-backend/pypy/translator/tool/cbuild.py
   pypy/branch/mininal-c-backend/pypy/translator/tool/pdbplus.py
Log:
svn merge -r 34627:HEAD to branch


Modified: pypy/branch/mininal-c-backend/pypy/annotation/annrpython.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/annotation/annrpython.py	(original)
+++ pypy/branch/mininal-c-backend/pypy/annotation/annrpython.py	Thu Nov 23 12:28:43 2006
@@ -564,6 +564,10 @@
                 # later by reflowing).  Throw the BlockedInference up to
                 # processblock().
                 raise
+
+        except annmodel.HarmlesslyBlocked:
+            return
+
         else:
             # dead code removal: don't follow all exits if the exitswitch
             # is known

Modified: pypy/branch/mininal-c-backend/pypy/annotation/binaryop.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/annotation/binaryop.py	(original)
+++ pypy/branch/mininal-c-backend/pypy/annotation/binaryop.py	Thu Nov 23 12:28:43 2006
@@ -5,7 +5,7 @@
 import py
 import operator
 from pypy.annotation.pairtype import pair, pairtype
-from pypy.annotation.model import SomeObject, SomeInteger, SomeBool
+from pypy.annotation.model import SomeObject, SomeInteger, SomeBool, s_Bool
 from pypy.annotation.model import SomeString, SomeChar, SomeList, SomeDict
 from pypy.annotation.model import SomeUnicodeCodePoint
 from pypy.annotation.model import SomeTuple, SomeImpossibleValue, s_ImpossibleValue
@@ -112,42 +112,42 @@
             return immutablevalue(obj1.const < obj2.const)
         else:
             getbookkeeper().count("non_int_comp", obj1, obj2)
-            return SomeBool()
+            return s_Bool
 
     def le((obj1, obj2)):
         if obj1.is_immutable_constant() and obj2.is_immutable_constant():
             return immutablevalue(obj1.const <= obj2.const)
         else:
             getbookkeeper().count("non_int_comp", obj1, obj2)
-            return SomeBool()
+            return s_Bool
 
     def eq((obj1, obj2)):
         if obj1.is_immutable_constant() and obj2.is_immutable_constant():
             return immutablevalue(obj1.const == obj2.const)
         else:
             getbookkeeper().count("non_int_eq", obj1, obj2)
-            return SomeBool()
+            return s_Bool
 
     def ne((obj1, obj2)):
         if obj1.is_immutable_constant() and obj2.is_immutable_constant():
             return immutablevalue(obj1.const != obj2.const)
         else:
             getbookkeeper().count("non_int_eq", obj1, obj2)
-            return SomeBool()
+            return s_Bool
 
     def gt((obj1, obj2)):
         if obj1.is_immutable_constant() and obj2.is_immutable_constant():
             return immutablevalue(obj1.const > obj2.const)
         else:
             getbookkeeper().count("non_int_comp", obj1, obj2)
-            return SomeBool()
+            return s_Bool
 
     def ge((obj1, obj2)):
         if obj1.is_immutable_constant() and obj2.is_immutable_constant():
             return immutablevalue(obj1.const >= obj2.const)
         else:
             getbookkeeper().count("non_int_comp", obj1, obj2)
-            return SomeBool()
+            return s_Bool
 
     def cmp((obj1, obj2)):
         getbookkeeper().count("cmp", obj1, obj2)
@@ -270,16 +270,15 @@
     pow_ovf = _clone(pow, [ZeroDivisionError, OverflowError])
 
     def _compare_helper((int1, int2), opname, operation):
+        r = SomeBool()
         if int1.is_immutable_constant() and int2.is_immutable_constant():
-            r = immutablevalue(operation(int1.const, int2.const))
+            r.const = operation(int1.const, int2.const)
         else:
             # XXX VERY temporary hack
             if (opname == 'ge' and int2.is_immutable_constant() and
                 int2.const == 0 and
                 not rarithmetic.signedtype(int1.knowntype)):
-                r = immutablevalue(True)
-            else:
-                r = SomeBool()
+                r.const = True
         knowntypedata = {}
         # XXX HACK HACK HACK
         # propagate nonneg information between the two arguments
@@ -335,6 +334,36 @@
                 s.knowntypedata = ktd
         return s 
 
+    def and_((boo1, boo2)):
+        s = SomeBool()
+        if boo1.is_constant():
+            if not boo1.const:
+                s.const = False
+            else:
+                return boo2
+        if boo2.is_constant():
+            if not boo2.const:
+                s.const = False
+        return s
+
+    def or_((boo1, boo2)):
+        s = SomeBool()
+        if boo1.is_constant():
+            if boo1.const:
+                s.const = True
+            else:
+                return boo2
+        if boo2.is_constant():
+            if boo2.const:
+                s.const = True
+        return s
+        
+    def xor((boo1, boo2)):
+        s = SomeBool()
+        if boo1.is_constant() and boo2.is_constant():
+            s.const = boo1.const ^ boo2.const
+        return s
+        
 class __extend__(pairtype(SomeString, SomeString)):
 
     def union((str1, str2)):
@@ -386,7 +415,7 @@
 
     def eq((lst1, lst2)):
         lst1.listdef.agree(lst2.listdef)
-        return SomeBool()
+        return s_Bool
     ne = eq
 
 

Modified: pypy/branch/mininal-c-backend/pypy/annotation/bookkeeper.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/annotation/bookkeeper.py	(original)
+++ pypy/branch/mininal-c-backend/pypy/annotation/bookkeeper.py	Thu Nov 23 12:28:43 2006
@@ -247,6 +247,8 @@
 
     def consider_call_site_for_pbc(self, s_callable, opname, args_s, s_result):
         descs = s_callable.descriptions.keys()
+        if not descs:
+            return
         family = descs[0].getcallfamily()
         args = self.build_args(opname, args_s)
         s_callable.getKind().consider_call_site(self, family, descs, args,

Modified: pypy/branch/mininal-c-backend/pypy/annotation/builtin.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/annotation/builtin.py	(original)
+++ pypy/branch/mininal-c-backend/pypy/annotation/builtin.py	Thu Nov 23 12:28:43 2006
@@ -4,13 +4,13 @@
 
 import sys
 from pypy.annotation.model import SomeInteger, SomeObject, SomeChar, SomeBool
-from pypy.annotation.model import SomeString, SomeTuple, SomeSlice
+from pypy.annotation.model import SomeString, SomeTuple, SomeSlice, s_Bool
 from pypy.annotation.model import SomeUnicodeCodePoint, SomeAddress
 from pypy.annotation.model import SomeFloat, SomeWeakGcAddress, unionof
 from pypy.annotation.model import SomePBC, SomeInstance, SomeDict
 from pypy.annotation.model import SomeExternalObject
 from pypy.annotation.model import annotation_to_lltype, lltype_to_annotation, ll_to_annotation
-from pypy.annotation.model import add_knowntypedata
+from pypy.annotation.model import add_knowntypedata, not_const
 from pypy.annotation.model import s_ImpossibleValue
 from pypy.annotation.bookkeeper import getbookkeeper
 from pypy.annotation import description
@@ -299,7 +299,7 @@
     return immutablevalue(None)
 
 def robjmodel_hint(s, **kwds_s):
-    return s
+    return not_const(s)
 
 def llmemory_cast_ptr_to_adr(s):
     return SomeAddress()
@@ -339,7 +339,7 @@
     raise TypeError, "unicodedate.decimal() calls should not happen at interp-level"    
 
 def test(*args):
-    return SomeBool()
+    return s_Bool
 
 def import_func(*args):
     return SomeObject()
@@ -517,7 +517,7 @@
 def instanceof(i, I):
     assert I.is_constant()
     assert isinstance(I.const, ootype.Instance)
-    return SomeBool()
+    return s_Bool
 
 def classof(i):
     assert isinstance(i, SomeOOInstance) 
@@ -526,7 +526,7 @@
 def subclassof(class1, class2):
     assert isinstance(class1, SomeOOClass) 
     assert isinstance(class2, SomeOOClass) 
-    return SomeBool()
+    return s_Bool
 
 def runtimenew(c):
     assert isinstance(c, SomeOOClass)

Modified: pypy/branch/mininal-c-backend/pypy/annotation/dictdef.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/annotation/dictdef.py	(original)
+++ pypy/branch/mininal-c-backend/pypy/annotation/dictdef.py	Thu Nov 23 12:28:43 2006
@@ -1,5 +1,5 @@
 from pypy.annotation.model import SomeObject, s_ImpossibleValue
-from pypy.annotation.model import SomeInteger, SomeBool, unionof
+from pypy.annotation.model import SomeInteger, s_Bool, unionof
 from pypy.annotation.model import SomeInstance
 from pypy.annotation.listdef import ListItem
 
@@ -62,7 +62,7 @@
 
         def check_eqfn(annotator, graph):
             s = annotator.binding(graph.getreturnvar())
-            assert SomeBool().contains(s), (
+            assert s_Bool.contains(s), (
                 "the custom eq function of an r_dict must return a boolean"
                 " (got %r)" % (s,))
         self.bookkeeper.emulate_pbc_call(myeq, self.s_rdict_eqfn, [s_key, s_key],

Modified: pypy/branch/mininal-c-backend/pypy/annotation/model.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/annotation/model.py	(original)
+++ pypy/branch/mininal-c-backend/pypy/annotation/model.py	Thu Nov 23 12:28:43 2006
@@ -474,6 +474,7 @@
 
 
 s_None = SomePBC([], can_be_None=True)
+s_Bool = SomeBool()
 s_ImpossibleValue = SomeImpossibleValue()
 
 # ____________________________________________________________
@@ -549,7 +550,7 @@
 NUMBER = object()
 annotation_to_ll_map = [
     (s_None, lltype.Void),   # also matches SomeImpossibleValue()
-    (SomeBool(), lltype.Bool),
+    (s_Bool, lltype.Bool),
     (SomeInteger(knowntype=r_ulonglong), NUMBER),    
     (SomeFloat(), lltype.Float),
     (SomeChar(), lltype.Char),
@@ -658,6 +659,18 @@
             r[truth_v] = unionof(ktd1[truth_v], ktd2[truth_v])
     return r
 
+def not_const(s_obj):
+    if s_obj.is_constant():
+        new_s_obj = SomeObject()
+        new_s_obj.__class__ = s_obj.__class__
+        dic = new_s_obj.__dict__ = s_obj.__dict__.copy()
+        if 'const' in dic:
+            del new_s_obj.const
+        else:
+            del new_s_obj.const_box
+        s_obj = new_s_obj
+    return s_obj
+
 # ____________________________________________________________
 # internal
 
@@ -700,6 +713,11 @@
         return s_ImpossibleValue
     setattr(cls, name, default_op)
 
+class HarmlesslyBlocked(Exception):
+    """Raised by the unaryop/binaryop to signal a harmless kind of
+    BlockedInference: the current block is blocked, but not in a way
+    that gives 'Blocked block' errors at the end of annotation."""
+
 #
 # safety check that no-one is trying to make annotation and translation
 # faster by providing the -O option to Python.

Modified: pypy/branch/mininal-c-backend/pypy/annotation/test/test_annrpython.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/annotation/test/test_annrpython.py	(original)
+++ pypy/branch/mininal-c-backend/pypy/annotation/test/test_annrpython.py	Thu Nov 23 12:28:43 2006
@@ -1,9 +1,11 @@
 
 import autopath
 import py.test
+from pypy import conftest
 from pypy.tool.udir import udir
 
-from pypy.annotation.annrpython import annmodel
+from pypy.annotation import model as annmodel
+from pypy.annotation.annrpython import RPythonAnnotator as _RPythonAnnotator
 from pypy.translator.translator import graphof as tgraphof
 from pypy.annotation import policy
 from pypy.annotation import specialize
@@ -42,7 +44,15 @@
     def setup_class(cls): 
         cls.space = FlowObjSpace() 
 
-    from pypy.annotation.annrpython import RPythonAnnotator
+    def teardown_method(self, meth):
+        assert annmodel.s_Bool == annmodel.SomeBool()
+
+    class RPythonAnnotator(_RPythonAnnotator):
+        def build_types(self, *args):
+            s = _RPythonAnnotator.build_types(self, *args)
+            if conftest.option.view:
+                self.translator.view()
+            return s
 
     def make_fun(self, func):
         import inspect
@@ -55,11 +65,6 @@
         funcgraph.source = inspect.getsource(func)
         return funcgraph
 
-    def show(self, a):
-        from pypy import conftest
-        if conftest.option.view:
-            a.translator.view()
-
     def test_simple_func(self):
         """
         one test source:
@@ -2293,7 +2298,6 @@
 
         a = self.RPythonAnnotator()
         a.build_types(f, [])
-        self.show(a)
         v1, v2 = graphof(a, readout).getargs()
         assert not a.bindings[v1].is_constant()
         assert not a.bindings[v2].is_constant()
@@ -2323,7 +2327,6 @@
 
         a = self.RPythonAnnotator()
         s = a.build_types(fun, [int])
-        self.show(a)
         assert isinstance(s, annmodel.SomeChar)
 
     def test_range_nonneg(self):
@@ -2334,7 +2337,6 @@
             return 0
         a = self.RPythonAnnotator()
         s = a.build_types(fun, [int, int])
-        self.show(a)
         assert isinstance(s, annmodel.SomeInteger)
         assert s.nonneg
 
@@ -2346,7 +2348,6 @@
             return 0
         a = self.RPythonAnnotator()
         s = a.build_types(fun, [int, int])
-        self.show(a)
         assert isinstance(s, annmodel.SomeInteger)
         assert s.nonneg
 
@@ -2403,6 +2404,40 @@
                 from pypy.annotation.classdef import NoSuchSlotError
                 py.test.raises(NoSuchSlotError, a.build_types, fun, [int])
 
+
+    def test_simple_controllerentry(self):
+        from pypy.rpython.controllerentry import Controller, ControllerEntry
+
+        class C:
+            "Imagine some magic here to have a foo attribute on instances"
+
+        def fun():
+            lst = []
+            c = C()
+            c.foo = lst    # side-effect on lst!  well, it's a test
+            return c.foo, lst[0]
+
+        class C_Controller(Controller):
+            knowntype = C
+
+            def new(self):
+                return "4"
+
+            def get_foo(self, obj):
+                return obj + "2"
+
+            def set_foo(self, obj, value):
+                value.append(obj)
+
+        class Entry(ControllerEntry):
+            _about_ = C
+            _controller_ = C_Controller
+
+        a = self.RPythonAnnotator(policy=policy.AnnotatorPolicy())
+        s = a.build_types(fun, [])
+        assert s.const == ("42", "4")
+
+
 def g(n):
     return [0,1,2,n]
 

Modified: pypy/branch/mininal-c-backend/pypy/annotation/unaryop.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/annotation/unaryop.py	(original)
+++ pypy/branch/mininal-c-backend/pypy/annotation/unaryop.py	Thu Nov 23 12:28:43 2006
@@ -7,8 +7,8 @@
      SomeDict, SomeUnicodeCodePoint, SomeTuple, SomeImpossibleValue, \
      SomeInstance, SomeBuiltin, SomeFloat, SomeIterator, SomePBC, \
      SomeExternalObject, SomeTypedAddressAccess, SomeAddress, \
-     SomeCTypesObject, s_ImpossibleValue, \
-     unionof, set, missing_operation, add_knowntypedata
+     SomeCTypesObject, s_ImpossibleValue, s_Bool, \
+     unionof, set, missing_operation, add_knowntypedata, HarmlesslyBlocked
 from pypy.annotation.bookkeeper import getbookkeeper
 from pypy.annotation import builtin
 from pypy.annotation.binaryop import _clone ## XXX where to put this?
@@ -60,24 +60,22 @@
                                               s_cls, vars)
         if obj.is_constant() and s_cls.is_constant():
             return immutablevalue(issubclass(obj.const, s_cls.const))
-        return SomeBool()
+        return s_Bool
 
     def len(obj):
         return SomeInteger(nonneg=True)
 
-    def is_true_behavior(obj):
+    def is_true_behavior(obj, s):
         if obj.is_immutable_constant():
-            return immutablevalue(bool(obj.const))
+            s.const = bool(obj.const)
         else:
             s_len = obj.len()
             if s_len.is_immutable_constant():
-                return immutablevalue(s_len.const > 0)
-            else:
-                return SomeBool()
+                s.const = s_len.const > 0
 
     def is_true(s_obj):
-        r = s_obj.is_true_behavior()
-        assert isinstance(r, SomeBool)
+        r = SomeBool()
+        s_obj.is_true_behavior(r)
 
         bk = getbookkeeper()
         knowntypedata = r.knowntypedata = {}
@@ -174,7 +172,7 @@
         return SomeObject()
 
     def op_contains(obj, s_element):
-        return SomeBool()
+        return s_Bool
 
     def hint(self, *args_s):
         return self
@@ -192,7 +190,7 @@
     def is_true(self):
         if self.is_immutable_constant():
             return getbookkeeper().immutablevalue(bool(self.const))
-        return SomeBool()
+        return s_Bool
 
     def hash(flt):
         return SomeInteger()
@@ -318,7 +316,7 @@
 
     def op_contains(lst, s_element):
         lst.listdef.generalize(s_element)
-        return SomeBool()
+        return s_Bool
 
     def hint(lst, *args_s):
         hints = args_s[-1].const
@@ -399,16 +397,16 @@
 
     def op_contains(dct, s_element):
         dct.dictdef.generalize_key(s_element)
-        return SomeBool()
+        return s_Bool
 
 
 class __extend__(SomeString):
 
     def method_startswith(str, frag):
-        return SomeBool()
+        return s_Bool
 
     def method_endswith(str, frag):
-        return SomeBool()
+        return s_Bool
 
     def method_find(str, frag, start=None, end=None):
         return SomeInteger()
@@ -468,22 +466,22 @@
         return immutablevalue(1)
 
     def method_isspace(chr):
-        return SomeBool()
+        return s_Bool
 
     def method_isdigit(chr):
-        return SomeBool()
+        return s_Bool
 
     def method_isalpha(chr):
-        return SomeBool()
+        return s_Bool
 
     def method_isalnum(chr):
-        return SomeBool()
+        return s_Bool
 
     def method_islower(chr):
-        return SomeBool()
+        return s_Bool
 
     def method_isupper(chr):
-        return SomeBool()
+        return s_Bool
 
 class __extend__(SomeUnicodeCodePoint):
 
@@ -526,6 +524,9 @@
                 s_result = ins.classdef.lookup_filter(s_result, attr)
             elif isinstance(s_result, SomeImpossibleValue):
                 ins.classdef.check_missing_attribute_update(attr)
+                if ins.classdef.classdesc.allslots is not None:
+                    if attr in ins.classdef.classdesc.allslots:
+                        raise HarmlesslyBlocked("getattr on a slot")
             return s_result
         return SomeObject()
     getattr.can_only_throw = []
@@ -548,11 +549,9 @@
         getbookkeeper().needs_hash_support[ins.classdef] = True
         return SomeInteger()
 
-    def is_true_behavior(ins):
-        if ins.can_be_None:
-            return SomeBool()
-        else:
-            return immutablevalue(True)
+    def is_true_behavior(ins, s):
+        if not ins.can_be_None:
+            s.const = True
 
 
 class __extend__(SomeBuiltin):
@@ -594,13 +593,11 @@
         d = [desc.bind_under(classdef, name) for desc in pbc.descriptions]
         return SomePBC(d, can_be_None=pbc.can_be_None)
 
-    def is_true_behavior(pbc):
+    def is_true_behavior(pbc, s):
         if pbc.isNone():
-            return immutablevalue(False)
-        elif pbc.can_be_None:
-            return SomeBool()
-        else:
-            return immutablevalue(True)
+            s.const = False
+        elif not pbc.can_be_None:
+            s.const = True
 
 
 class __extend__(SomeExternalObject):
@@ -649,7 +646,7 @@
         return ll_to_annotation(v)
 
     def is_true(p):
-        return SomeBool()
+        return s_Bool
 
 class __extend__(SomeExternalBuiltin):
     def getattr(p, s_attr):
@@ -680,7 +677,7 @@
         return obj.knowntype.get_field(name)
     
     def is_true(p):
-        return SomeBool()
+        return s_Bool
 
 class __extend__(SomeLLADTMeth):
 
@@ -706,7 +703,7 @@
             setattr(r.ootype._example(), s_attr.const, v._example())
 
     def is_true(p):
-        return SomeBool()
+        return s_Bool
 
 class __extend__(SomeOOBoundMeth):
     def simple_call(m, *args_s):
@@ -739,7 +736,7 @@
             return SomeObject()
 
     def is_true(cto):
-        return SomeBool()
+        return s_Bool
 
     def simple_call(cto, *args_s):
         # for variables containing ctypes function pointers
@@ -761,4 +758,4 @@
     getattr.can_only_throw = []
 
     def is_true(s_addr):
-        return SomeBool()
+        return s_Bool

Modified: pypy/branch/mininal-c-backend/pypy/config/pypyoption.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/config/pypyoption.py	(original)
+++ pypy/branch/mininal-c-backend/pypy/config/pypyoption.py	Thu Nov 23 12:28:43 2006
@@ -1,6 +1,6 @@
 import autopath
 import py, os
-from pypy.config.config import OptionDescription, BoolOption, IntOption
+from pypy.config.config import OptionDescription, BoolOption, IntOption, ArbitraryOption
 from pypy.config.config import ChoiceOption, StrOption, to_optparse, Config
 
 modulepath = py.magic.autopath().dirpath().dirpath().join("module")
@@ -58,6 +58,9 @@
         BoolOption("logbytecodes",
                    "keep track of bytecode usage",
                    default=False),
+
+        BoolOption("usepycfiles", "Write and read pyc files when importing",
+                   default=True),
        
         OptionDescription("std", "Standard Object Space Options", [
             BoolOption("withtproxy", "support transparent proxies",
@@ -159,6 +162,12 @@
         BoolOption("debug_transform", "Perform the debug transformation",
                    default=False, cmdline="--debug-transform", negation=False),
 
+        BoolOption("instrument", "internal: turn instrumentation on",
+                   default=False, cmdline=None),
+
+        ArbitraryOption("instrumentctl", "internal",
+                   default=None),        
+
         # portability options
         BoolOption("vanilla",
                    "Try to be as portable as possible, which is not much",
@@ -203,6 +212,10 @@
                        "optimizer remove the asserts", default=False),
             IntOption("inline_threshold", "Threshold when to inline functions",
                       default=1, cmdline=None),
+            StrOption("profile_based_inline",
+                      "Use call count profiling to drive inlining"
+                      ", specify arguments",
+                      default=None, cmdline="--prof-based-inline"),
         ]),
 
         OptionDescription("cli", "GenCLI options", [

Modified: pypy/branch/mininal-c-backend/pypy/conftest.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/conftest.py	(original)
+++ pypy/branch/mininal-c-backend/pypy/conftest.py	Thu Nov 23 12:28:43 2006
@@ -113,6 +113,9 @@
     def unpackiterable(self, itr):
         return list(itr)
 
+    def is_true(self, obj):
+        return bool(obj)
+
 
 class OpErrKeyboardInterrupt(KeyboardInterrupt):
     pass

Modified: pypy/branch/mininal-c-backend/pypy/doc/_ref.txt
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/doc/_ref.txt	(original)
+++ pypy/branch/mininal-c-backend/pypy/doc/_ref.txt	Thu Nov 23 12:28:43 2006
@@ -1,4 +1,5 @@
 .. _`demo/`: ../../demo
+.. _`demo/pickle_coroutine.py`: ../../demo/pickle_coroutine.py
 .. _`lib-python/`: ../../lib-python
 .. _`lib-python/2.4.1/dis.py`: ../../lib-python/2.4.1/dis.py
 .. _`annotation/`:
@@ -48,7 +49,10 @@
 .. _`objspace/thunk.py`: ../../pypy/objspace/thunk.py
 .. _`objspace/trace.py`:
 .. _`pypy/objspace/trace.py`: ../../pypy/objspace/trace.py
+.. _`pypy/rlib`: ../../pypy/rlib
 .. _`pypy/rlib/objectmodel.py`: ../../pypy/rlib/objectmodel.py
+.. _`pypy/rlib/rarithmetic.py`: ../../pypy/rlib/rarithmetic.py
+.. _`pypy/rlib/test`: ../../pypy/rlib/test
 .. _`pypy/rpython`:
 .. _`pypy/rpython/`:
 .. _`rpython/`: ../../pypy/rpython

Modified: pypy/branch/mininal-c-backend/pypy/doc/stackless.txt
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/doc/stackless.txt	(original)
+++ pypy/branch/mininal-c-backend/pypy/doc/stackless.txt	Thu Nov 23 12:28:43 2006
@@ -112,6 +112,42 @@
     catch it, and that ``try: finally:`` clauses are not honored.  This
     will be fixed in the future.)
 
+Example
+~~~~~~~
+
+Here is a classical producer/consumer example: an algorithm computes a
+sequence of values, while another consumes them.  For our purposes we
+assume that the producer can generate several values at once, and the
+consumer can process up to 3 values in a batch - it can also process
+batches with less than 3 values without waiting for the producer (which
+would be messy to express with a classical Python generator). ::
+
+    def producer(lst):
+        while True:
+            ...compute some more values...
+            lst.extend(new_values)
+            coro_consumer.switch()
+
+    def consumer(lst):
+        while True:
+            # First ask the producer for more values if needed
+            while len(lst) == 0:
+                coro_producer.switch()
+            # Process the available values in a batch, but at most 3
+            batch = lst[:3]
+            del lst[:3]
+            ...process batch...
+
+    # Initialize two coroutines with a shared list as argument
+    exchangelst = []
+    coro_producer = coroutine()
+    coro_producer.bind(producer, exchangelst)
+    coro_consumer = coroutine()
+    coro_consumer.bind(consumer, exchangelst)
+
+    # Start running the consumer coroutine
+    coro_consumer.switch()
+
 
 Tasklets and channels
 +++++++++++++++++++++
@@ -135,7 +171,7 @@
 as possible. This makes the code somewhat unpythonic.
 
 Bird's eye view of tasklets and channels
-----------------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 Tasklets are a bit like threads: they encapsulate a function in such a way that
 they can be suspended/restarted any time. Unlike threads, they won't
@@ -158,6 +194,44 @@
 is removed from the scheduling queue and will be reinserted when it
 becomes unblocked.
 
+Example
+~~~~~~~
+
+Here is a many-producers many-consumers example, where any consumer can
+process the result of any producer.  For this situation we set up a
+single channel where all producer send, and on which all consumers
+wait::
+
+    def producer(chan):
+        while True:
+            chan.send(...next value...)
+
+    def consumer(chan):
+        while True:
+            x = chan.receive()
+            ...do something with x...
+
+    # Set up the N producer and M consumer tasklets
+    common_channel = stackless.channel()
+    for i in range(N):
+        stackless.tasklet(producer, common_channel)()
+    for i in range(M):
+        stackless.tasklet(consumer, common_channel)()
+
+    # Run it all
+    stackless.run()
+
+Each item sent over the channel is received by one of the waiting
+consumers; which one is not specified.  The producers block until their
+item is consumed: the channel is not a queue, but rather a meeting point
+which causes tasklets to block until both a consumer and a producer are
+ready.  In practice, the reason for having several consumers receiving
+on a single channel is that some of the consumers can be busy in other
+ways part of the time.  For example, each consumer might receive a
+database request, process it, and send the result to a further channel
+before it asks for the next request.  In this situation, further
+requests can still be received by other consumers.
+
 
 Greenlets
 +++++++++
@@ -169,8 +243,14 @@
 precise tree, which fully determines their order of execution.
 
 For usage reference, see the documentation of the `Py lib greenlets`_.
-The PyPy interface is identical, except that the ``greenlet`` class is
-in the ``stackless`` module instead of in the ``py.magic`` module.
+The PyPy interface is identical.  You should use ``py.magic.greenlet``
+instead of ``stackless.greenlet`` directly, because the Py lib can now
+give you the latter when you ask for the former on top of PyPy.
+
+PyPy's greenlets do not suffer from the cyclic GC limitation that the
+CPython greenlets have: greenlets referencing each other via local
+variables tend to leak on top of CPython (where it is mostly impossible
+to do the right thing).  It works correctly on top of PyPy.
 
 
 Coroutine Pickling
@@ -222,7 +302,99 @@
 interface that allows an RPython program to artifically rebuild a chain
 of calls in a reflective way, completely from scratch, and jump to it.
 
-XXX examples, limitations?
+Example
+~~~~~~~
+
+(See `demo/pickle_coroutine.py`_ for the complete source of this demo.)
+
+Consider a program which contains a part performing a long-running
+computation::
+
+    def ackermann(x, y):
+        if x == 0:
+            return y + 1
+        if y == 0:
+            return ackermann(x - 1, 1)
+        return ackermann(x - 1, ackermann(x, y - 1))
+
+By using pickling, we can save the state of the computation while it is
+running, for the purpose of restoring it later and continuing the
+computation at another time or on a different machine.  However,
+pickling does not produce a whole-program dump: it can only pickle
+individual coroutines.  This means that the computation should be
+started in its own coroutine::
+
+    # Make a coroutine that will run 'ackermann(3, 8)'
+    coro = coroutine()
+    coro.bind(ackermann, 3, 8)
+
+    # Now start running the coroutine
+    result = coro.switch()
+
+The coroutine itself must switch back to the main program when it needs
+to be interrupted (we can only pickle suspended coroutines).  Due to
+current limitations this requires an explicit check in the
+``ackermann()`` function::
+
+    def ackermann(x, y):
+        if interrupt_flag:      # test a global flag
+            main.switch()       # and switch back to 'main' if it is set
+        if x == 0:
+            return y + 1
+        if y == 0:
+            return ackermann(x - 1, 1)
+        return ackermann(x - 1, ackermann(x, y - 1))
+
+The global ``interrupt_flag`` would be set for example by a timeout, or
+by a signal handler reacting to Ctrl-C, etc.  It causes the coroutine to
+transfer control back to the main program.  The execution comes back
+just after the line ``coro.switch()``, where we can pickle the coroutine
+if necessary::
+
+    if not coro.is_alive:
+        print "finished; the result is:", result
+    else:
+        # save the state of the suspended coroutine
+        f = open('demo.pickle', 'w')
+        pickle.dump(coro, f)
+        f.close()
+
+The process can then stop.  At any later time, or on another machine,
+we can reload the file and restart the coroutine with::
+
+    f = open('demo.pickle', 'r')
+    coro = pickle.load(f)
+    f.close()
+    result = coro.switch()
+
+Limitations
+~~~~~~~~~~~
+
+Coroutine pickling is subject to some limitations.  First of all, it is
+not a whole-program "memory dump".  It means that only the "local" state
+of a coroutine is saved.  The local state is defined to include the
+chain of calls and the local variables, but not for example the value of
+any global variable.
+
+As in normal Python, the pickle will not include any function object's
+code, any class definition, etc., but only references to functions and
+classes.  Unlike normal Python, the pickle contains frames.  A pickled
+frame stores a bytecode index, representing the current execution
+position.  This means that the user program cannot be modified *at all*
+between pickling and unpickling!
+
+On the other hand, the pickled data is fairly independent from the
+platform and from the PyPy version.
+
+Pickling/unpickling fails if the coroutine is suspended in a state that
+involves Python frames which were *indirectly* called.  To define this
+more precisely, a Python function can issue a regular function or method
+call to invoke another Python function - this is a *direct* call and can
+be pickled and unpickled.  But there are many ways to invoke a Python
+function indirectly.  For example, most operators can invoke a special
+method ``__xyz__()`` on a class, various built-in functions can call
+back Python functions, signals can invoke signal handlers, and so on.
+These cases are not supported yet.
 
 
 Coroutine Cloning
@@ -413,9 +585,34 @@
 
             ...generators_view.getcurrent()...
 
-Then the composition ``grab_values()`` works as expected.
-
-XXX a few words about how
+Then the composition ``grab_values()`` works as expected, because the
+two views are independent.  The coroutine captured as ``self.caller`` in
+the ``generator_iterator.next()`` method is the main coroutine of the
+``generators_view``.  It is no longer the same object as the main
+coroutine of the ``producer_view``, so when ``data_producer()`` issues
+the following command::
+
+    main_coro.switch()
+
+the control flow cannot accidentally jump back to
+``generator_iterator.next()``.  In other words, from the point of view
+of ``producer_view``, the function ``grab_next_value()`` always runs in
+its main coroutine ``main_coro`` and the function ``data_producer`` in
+its coroutine ``producer_coro``.  This is the case independently of
+which ``generators_view``-based coroutine is the current one when
+``grab_next_value()`` is called.
+
+Only code that has explicit access to the ``producer_view`` or its
+coroutine objects can perform switches that are relevant for the
+generator code.  If the view object and the coroutine objects that share
+this view are all properly encapsulated inside the generator logic, no
+external code can accidentally temper with the expected control flow any
+longer.
+
+In conclusion: we will probably change the app-level interface of PyPy's
+stackless module in the future to not expose coroutines and greenlets at
+all, but only views.  They are not much more difficult to use, and they
+scale automatically to larger programs.
 
 
 .. _`Stackless Python`: http://www.stackless.com

Modified: pypy/branch/mininal-c-backend/pypy/interpreter/astcompiler/pycodegen.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/interpreter/astcompiler/pycodegen.py	(original)
+++ pypy/branch/mininal-c-backend/pypy/interpreter/astcompiler/pycodegen.py	Thu Nov 23 12:28:43 2006
@@ -137,6 +137,8 @@
     """Defines basic code generator for Python bytecode
     """
 
+    localsfullyknown = False
+
     def __init__(self, space, graph):
         self.space = space
         self.setups = [] 

Modified: pypy/branch/mininal-c-backend/pypy/interpreter/executioncontext.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/interpreter/executioncontext.py	(original)
+++ pypy/branch/mininal-c-backend/pypy/interpreter/executioncontext.py	Thu Nov 23 12:28:43 2006
@@ -38,45 +38,41 @@
         if not frame.hide():
             self.framestack.pop()
 
-    # coroutine: subcontext support
-    def subcontext_new(coobj):
-        coobj.framestack = new_framestack()
-        coobj.w_tracefunc = None
-        coobj.w_profilefunc = None
-        coobj.is_tracing = 0
-    subcontext_new = staticmethod(subcontext_new)
-
-    def subcontext_enter(self, next):
-        self.framestack = next.framestack
-        self.w_tracefunc = next.w_tracefunc
-        self.w_profilefunc = next.w_profilefunc
-        self.is_tracing = next.is_tracing
-
-    def subcontext_leave(self, current):
-        current.framestack = self.framestack
-        current.w_tracefunc = self.w_tracefunc
-        current.w_profilefunc = self.w_profilefunc
-        current.is_tracing = self.is_tracing
-
-    # coroutine: I think this is all, folks!
-
-    # well, not quite: we need an interface for pickling
-    def subcontext_getstate(coobj):
-        # we just save the framestack
-        space = coobj.space
-        items = [space.wrap(item) for item in coobj.framestack.items]
-        return space.newtuple(items)
-    subcontext_getstate = staticmethod(subcontext_getstate)
-
-    def subcontext_setstate(coobj, w_state):
-        from pypy.interpreter.pyframe import PyFrame
-        space = coobj.space
-        items = [space.interp_w(PyFrame, item)
-                 for item in space.unpackiterable(w_state)]
-        coobj.framestack.items = items
-    subcontext_setstate = staticmethod(subcontext_setstate)
 
-    # coroutine: now I really I think this is all, folks!
+    class Subcontext(object):
+        # coroutine: subcontext support
+
+        def __init__(self):
+            self.framestack = new_framestack()
+            self.w_tracefunc = None
+            self.w_profilefunc = None
+            self.is_tracing = 0
+
+        def enter(self, ec):
+            ec.framestack = self.framestack
+            ec.w_tracefunc = self.w_tracefunc
+            ec.w_profilefunc = self.w_profilefunc
+            ec.is_tracing = self.is_tracing
+
+        def leave(self, ec):
+            self.framestack = ec.framestack
+            self.w_tracefunc = ec.w_tracefunc
+            self.w_profilefunc = ec.w_profilefunc
+            self.is_tracing = ec.is_tracing
+
+        # the following interface is for pickling and unpickling
+        def getstate(self, space):
+            # we just save the framestack
+            items = [space.wrap(item) for item in self.framestack.items]
+            return space.newtuple(items)
+
+        def setstate(self, space, w_state):
+            from pypy.interpreter.pyframe import PyFrame
+            items = [space.interp_w(PyFrame, w_item)
+                     for w_item in space.unpackiterable(w_state)]
+            self.framestack.items = items
+        # coroutine: I think this is all, folks!
+
 
     def get_builtin(self):
         try:

Modified: pypy/branch/mininal-c-backend/pypy/interpreter/mixedmodule.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/interpreter/mixedmodule.py	(original)
+++ pypy/branch/mininal-c-backend/pypy/interpreter/mixedmodule.py	Thu Nov 23 12:28:43 2006
@@ -88,7 +88,15 @@
             if '__doc__' not in loaders:
                 loaders['__doc__'] = cls.get__doc__
 
-    buildloaders = classmethod(buildloaders) 
+    buildloaders = classmethod(buildloaders)
+
+    def extra_interpdef(self, name, spec):
+        cls = self.__class__
+        pkgroot = cls.__module__
+        loader = getinterpevalloader(pkgroot, spec)
+        space = self.space
+        w_obj = loader(space)
+        space.setattr(space.wrap(self), space.wrap(name), w_obj)
 
     def get__file__(cls, space): 
         """ NOT_RPYTHON. 

Modified: pypy/branch/mininal-c-backend/pypy/jit/codegen/i386/rgenop.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/jit/codegen/i386/rgenop.py	(original)
+++ pypy/branch/mininal-c-backend/pypy/jit/codegen/i386/rgenop.py	Thu Nov 23 12:28:43 2006
@@ -297,6 +297,12 @@
             op = eax
         return self.returnvar(op)
 
+    def genop_getarraysubstruct(self, arraytoken, gv_ptr, gv_index):
+        self.mc.MOV(edx, gv_ptr.operand(self))
+        op = self.itemaddr(edx, arraytoken, gv_index)
+        self.mc.LEA(eax, op)
+        return self.returnvar(eax)
+
     def genop_getarraysize(self, arraytoken, gv_ptr):
         lengthoffset, startoffset, itemoffset = arraytoken
         self.mc.MOV(edx, gv_ptr.operand(self))
@@ -813,6 +819,9 @@
     def genop_getarrayitem(self, arraytoken, gv_ptr, gv_index):
         return dummy_var
 
+    def genop_getarraysubstruct(self, arraytoken, gv_ptr, gv_index):
+        return dummy_var
+
     def genop_getarraysize(self, arraytoken, gv_ptr):
         return dummy_var
 

Modified: pypy/branch/mininal-c-backend/pypy/jit/codegen/i386/test/test_genc_ts.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/jit/codegen/i386/test/test_genc_ts.py	(original)
+++ pypy/branch/mininal-c-backend/pypy/jit/codegen/i386/test/test_genc_ts.py	Thu Nov 23 12:28:43 2006
@@ -140,6 +140,9 @@
     def check_insns(self, expected=None, **counts):
         "Cannot check instructions in the generated assembler."
 
+    def check_flexswitches(self, expected_count):
+        "Cannot check instructions in the generated assembler."
+
 class TestTimeshiftI386(I386TimeshiftingTestMixin,
                         test_timeshift.TestTimeshift):
 

Modified: pypy/branch/mininal-c-backend/pypy/jit/codegen/llgraph/llimpl.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/jit/codegen/llgraph/llimpl.py	(original)
+++ pypy/branch/mininal-c-backend/pypy/jit/codegen/llgraph/llimpl.py	Thu Nov 23 12:28:43 2006
@@ -396,6 +396,7 @@
     from pypy import conftest
     if conftest.option.view:
         graph = from_opaque_object(graph)
+        eliminate_empty_blocks(graph)
         graph.show()
 
 # ____________________________________________________________

Modified: pypy/branch/mininal-c-backend/pypy/jit/codegen/llgraph/rgenop.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/jit/codegen/llgraph/rgenop.py	(original)
+++ pypy/branch/mininal-c-backend/pypy/jit/codegen/llgraph/rgenop.py	Thu Nov 23 12:28:43 2006
@@ -107,6 +107,11 @@
         return LLVar(llimpl.genop(self.b, 'getarrayitem', vars_gv,
                                   gv_ITEMTYPE.v))
 
+    def genop_getarraysubstruct(self, gv_ITEMTYPE, gv_ptr, gv_index):
+        vars_gv = [gv_ptr.v, gv_index.v]
+        return LLVar(llimpl.genop(self.b, 'getarraysubstruct', vars_gv,
+                                  gv_ITEMTYPE.v))
+
     def genop_setarrayitem(self, gv_ITEMTYPE, gv_ptr, gv_index, gv_value):
         vars_gv = [gv_ptr.v, gv_index.v, gv_value.v]
         return LLVar(llimpl.genop(self.b, 'setarrayitem', vars_gv,
@@ -232,7 +237,10 @@
     @staticmethod
     @specialize.memo()
     def arrayToken(A):
-        return LLConst(llimpl.constTYPE(A.OF))
+        ITEMTYPE = A.OF
+        if isinstance(ITEMTYPE, lltype.ContainerType):
+            ITEMTYPE = lltype.Ptr(ITEMTYPE)
+        return LLConst(llimpl.constTYPE(ITEMTYPE))
 
     @staticmethod
     @specialize.memo()

Modified: pypy/branch/mininal-c-backend/pypy/jit/codegen/llvm/lib/libllvmjit.cpp
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/jit/codegen/llvm/lib/libllvmjit.cpp	(original)
+++ pypy/branch/mininal-c-backend/pypy/jit/codegen/llvm/lib/libllvmjit.cpp	Thu Nov 23 12:28:43 2006
@@ -20,59 +20,45 @@
 using namespace llvm;
 
 
-ExecutionEngine*    g_execution_engine;
+Module*             gp_module           = new Module("llvmjit");
+ExecutionEngine*    gp_execution_engine = ExecutionEngine::create(
+                        new ExistingModuleProvider(gp_module), false);
 
 
 void    restart() {
-    delete g_execution_engine; //XXX test if this correctly cleans up including generated code
-    g_execution_engine = NULL;
+    delete gp_execution_engine; //XXX test if this correctly cleans up including generated code
+
+    gp_module           = new Module("llvmjit");
+    gp_execution_engine = ExecutionEngine::create(new ExistingModuleProvider(gp_module), false);
 }
 
 
 int     compile(const char* llsource) {
-    Module*     module = ParseAssemblyString(llsource, new Module("llvmjit"));
+    Module*     module = ParseAssemblyString(llsource, gp_module);
     if (!module) {
-        std::cerr << "Error: can not parse " << llsource << "\n" << std::flush;
+        std::cerr << "Can not parse:\n" << llsource << "\n" << std::flush;
         return false;
     }
 
-    //std::ostream *Out = new std::ofstream("temp-libllvmjit.bc",
-    //        std::ios::out | std::ios::trunc | std::ios::binary);
-    //WriteBytecodeToFile(module, *Out); //XXX what to do with the 3rd param (NoCompress)?
-
-    ModuleProvider* module_provider = new ExistingModuleProvider(module);
-    if (!g_execution_engine) {
-        g_execution_engine = ExecutionEngine::create(module_provider, false);
-    } else {
-        g_execution_engine->addModuleProvider(module_provider);
-    }
-
     return true;
 }
 
 
 void*   find_function(const char* name) {
-    if (!g_execution_engine)    return NULL; //note: decided not to be treated as an error
-
-    return g_execution_engine->FindFunctionNamed(name); //note: can be NULL
+    return gp_execution_engine->FindFunctionNamed(name); //note: can be NULL
 }
 
 
 int     execute(const void* function, int param) { //XXX allow different function signatures
-    if (!g_execution_engine) {
-        std::cerr << "Error: no llvm code compiled yet!\n" << std::flush;
-        return -1;
-    }
-
     if (!function) {
-        std::cerr << "Error: no function supplied to libllvmjit.execute(...)\n" << std::flush;
+        std::cerr << "No function supplied to libllvmjit.execute(...)\n" << std::flush;
         return -1;
     }
 
     std::vector<GenericValue> args;
     args.push_back((void*)param);
 
-    GenericValue gv = g_execution_engine->runFunction((Function*)function, args);
+    GenericValue gv = gp_execution_engine->runFunction((Function*)function, args);
     return gv.IntVal;
 }
 

Modified: pypy/branch/mininal-c-backend/pypy/jit/codegen/llvm/llvmjit.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/jit/codegen/llvm/llvmjit.py	(original)
+++ pypy/branch/mininal-c-backend/pypy/jit/codegen/llvm/llvmjit.py	Thu Nov 23 12:28:43 2006
@@ -7,6 +7,7 @@
     This file contains the ctypes specification to use the llvmjit library!
 '''
 from pypy.rpython.rctypes import implementation
+from pypy.rpython.rctypes.tool.util import load_library
 
 from ctypes import _CFuncPtr, _FUNCFLAG_CDECL
 from ctypes import *
@@ -31,10 +32,10 @@
 
 if not os.path.exists(path):
     import py
-    py.test.skip("libllvmjit.so compilation failed (no llvm headers?)")
+    py.test.skip("libllvmjit.so compilation failed (no llvm headers or llvm version not up to date?)")
 
 #load the actual library
-llvmjit = cdll.LoadLibrary(os.path.abspath(path))
+llvmjit = load_library(os.path.abspath(path))
 class _FuncPtr(_CFuncPtr):
     _flags_ = _FUNCFLAG_CDECL
     # aaarghdistutilsunixaaargh (may need something different for standalone builds...)
@@ -56,11 +57,3 @@
 execute.restype  = c_int
 execute.argtypes = [c_void_p, c_int]
 
-#helpers...
-class FindFunction(object):
-    def __init__(self, function_name):
-        self.function = find_function(function_name)
-
-    def __call__(self, param):  #XXX this does not seem to translate, how to do it instead?
-        return execute(self.function, param)
-

Modified: pypy/branch/mininal-c-backend/pypy/jit/codegen/llvm/test/test_llvmjit.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/jit/codegen/llvm/test/test_llvmjit.py	(original)
+++ pypy/branch/mininal-c-backend/pypy/jit/codegen/llvm/test/test_llvmjit.py	Thu Nov 23 12:28:43 2006
@@ -27,7 +27,9 @@
     ret int %n2
 }'''
 
-llacross1 = '''declare int %across2(int %n2)
+llacross1 = '''declare int %across2(int)
+
+implementation
 
 int %across1(int %n) {
 block0:
@@ -42,7 +44,9 @@
     ret int %n3
 }'''
 
-llacross2 = '''declare int %across1(int %n2)
+llacross2 = '''declare int %across1(int %dsf)
+
+implementation
 
 int %across2(int %n) {
 block0:
@@ -60,10 +64,9 @@
 #helpers
 def execute(llsource, function_name, param):
     assert llvmjit.compile(llsource)
-    f = llvmjit.FindFunction(function_name)
-    assert f.function
-    return llvmjit.execute(f.function, param)
-    #return function(param) #XXX this does not seem to translate, how to do it instead?
+    function = llvmjit.find_function(function_name)
+    assert function
+    return llvmjit.execute(function, param)
 
 #tests...
 def test_restart():
@@ -90,6 +93,10 @@
     llvmjit.restart()
     assert execute(llsquare, 'square', 4) == 4 * 4
 
+def test_execute_nothing():
+    llvmjit.restart()
+    assert llvmjit.execute(None, 4) == -1 #-1 == no function supplied
+
 def test_execute_multiple():
     llvmjit.restart()
     llvmjit.compile(llsquare)
@@ -104,13 +111,13 @@
     llvmjit.restart()
     llvmjit.compile(llsquare)
     llvmjit.compile(llmul2)
-    square = llvmjit.FindFunction('square')
-    mul2   = llvmjit.FindFunction('mul2')
+    square = llvmjit.find_function('square')
+    mul2   = llvmjit.find_function('mul2')
     for i in range(5):
-        assert square(i) == i * i
-        assert mul2(i) == i * 2
+        assert llvmjit.execute(square, i) == i * i
+        assert llvmjit.execute(mul2  , i) == i * 2
 
-def DONTtest_execute_across_module():
+def test_execute_across_module():
     def my_across1(n):
         return n * 3
 
@@ -126,11 +133,11 @@
     llvmjit.restart()
     llvmjit.compile(llacross1)
     llvmjit.compile(llacross2)
-    across1to2 = llvmjit.FindFunction('across1to2')
-    across2to1 = llvmjit.FindFunction('across2to1')
+    across1to2 = llvmjit.find_function('across1to2')
+    across2to1 = llvmjit.find_function('across2to1')
     for i in range(5):
-        assert across1to2(i) == my_across1to2(i)
-        assert across2to1(i) == my_across2to1(i)
+        assert llvmjit.execute(across1to2, i) == my_across1to2(i)
+        assert llvmjit.execute(across2to1, i) == my_across2to1(i)
 
 
 def DONTtest_modify_global_data():

Modified: pypy/branch/mininal-c-backend/pypy/jit/codegen/ppc/conftest.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/jit/codegen/ppc/conftest.py	(original)
+++ pypy/branch/mininal-c-backend/pypy/jit/codegen/ppc/conftest.py	Thu Nov 23 12:28:43 2006
@@ -17,7 +17,10 @@
 
 Option = py.test.Config.Option
 
-option = py.test.Config.addoptions("ppc options", 
-        Option('--trap', action="store_true", default=False, 
-               dest="trap", 
+option = py.test.Config.addoptions("ppc options",
+        Option('--trap', action="store_true", default=False,
+               dest="trap",
+               help=""),
+        Option('--debug-print', action="store_true", default=False,
+               dest="debug_print",
                help=""))

Modified: pypy/branch/mininal-c-backend/pypy/jit/codegen/ppc/instruction.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/jit/codegen/ppc/instruction.py	(original)
+++ pypy/branch/mininal-c-backend/pypy/jit/codegen/ppc/instruction.py	Thu Nov 23 12:28:43 2006
@@ -157,6 +157,44 @@
                      self.result_reg.number,
                      self.imm.value)
 
+class Insn_None__GPR_GPR_IMM(Insn):
+    def __init__(self, methptr, args):
+        Insn.__init__(self)
+        self.methptr = methptr
+        self.imm = args[2]
+
+        self.result = None
+        self.result_regclass = NO_REGISTER
+        self.reg_args = args[:2]
+        self.reg_arg_regclasses = [GP_REGISTER, GP_REGISTER]
+    def allocate(self, allocator):
+        self.reg1 = allocator.loc_of(self.reg_args[0])
+        self.reg2 = allocator.loc_of(self.reg_args[1])
+    def emit(self, asm):
+        self.methptr(asm,
+                     self.reg1.number,
+                     self.reg2.number,
+                     self.imm.value)
+
+class Insn_None__GPR_GPR_GPR(Insn):
+    def __init__(self, methptr, args):
+        Insn.__init__(self)
+        self.methptr = methptr
+
+        self.result = None
+        self.result_regclass = NO_REGISTER
+        self.reg_args = args
+        self.reg_arg_regclasses = [GP_REGISTER, GP_REGISTER, GP_REGISTER]
+    def allocate(self, allocator):
+        self.reg1 = allocator.loc_of(self.reg_args[0])
+        self.reg2 = allocator.loc_of(self.reg_args[1])
+        self.reg3 = allocator.loc_of(self.reg_args[2])
+    def emit(self, asm):
+        self.methptr(asm,
+                     self.reg1.number,
+                     self.reg2.number,
+                     self.reg3.number)
+
 class CMPInsn(Insn):
     info = (0,0) # please the annotator for tests that don't use CMPW/CMPWI
     pass
@@ -267,10 +305,16 @@
         self.argnumber = argnumber
         self.arg = arg
     def allocate(self, allocator):
-        self.loc = allocator.loc_of(self.arg)
+        from pypy.jit.codegen.ppc.rgenop import Var
+        if isinstance(self.arg, Var):
+            self.loc = allocator.loc_of(self.arg)
+        else:
+            self.loc = None
     def emit(self, asm):
         targetreg = 3+self.argnumber
-        if self.loc.is_register:
+        if self.loc is None:
+            self.arg.load_now(asm, gprs[targetreg])
+        elif self.loc.is_register:
             asm.mr(targetreg, self.loc.number)
         else:
             asm.lwz(targetreg, rFP, self.loc.offset)

Modified: pypy/branch/mininal-c-backend/pypy/jit/codegen/ppc/regalloc.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/jit/codegen/ppc/regalloc.py	(original)
+++ pypy/branch/mininal-c-backend/pypy/jit/codegen/ppc/regalloc.py	Thu Nov 23 12:28:43 2006
@@ -4,10 +4,15 @@
      CMPInsn, Spill, Unspill, stack_slot, \
      rSCRATCH
 
+from pypy.jit.codegen.ppc.conftest import option
+
+DEBUG_PRINT = option.debug_print
+
 class RegisterAllocation:
     def __init__(self, freeregs, initial_mapping, initial_spill_offset):
-        #print
-        #print "RegisterAllocation __init__", initial_mapping
+        if DEBUG_PRINT:
+            print
+            print "RegisterAllocation __init__", initial_mapping.items()
 
         self.insns = []   # output list of instructions
 
@@ -74,7 +79,8 @@
         if freeregs:
             reg = freeregs.pop()
             self.set(newarg, reg)
-            #print "allocate_reg: Putting %r into fresh register %r" % (newarg, reg)
+            if DEBUG_PRINT:
+                print "allocate_reg: Putting %r into fresh register %r" % (newarg, reg)
             return reg
 
         # if not, find something to spill
@@ -93,11 +99,13 @@
 
         self.spill(reg, argtospill)
 
-        #print "allocate_reg: Spilled %r to %r." % (argtospill, self.loc_of(argtospill))
+        if DEBUG_PRINT:
+            print "allocate_reg: Spilled %r to %r." % (argtospill, self.loc_of(argtospill))
 
         # update data structures to put newarg into the register
         self.set(newarg, reg)
-        #print "allocate_reg: Put %r in stolen reg %r." % (newarg, reg)
+        if DEBUG_PRINT:
+            print "allocate_reg: Put %r in stolen reg %r." % (newarg, reg)
         return reg
 
     def _promote(self, arg):
@@ -127,32 +135,37 @@
         # Walk through instructions in forward order
         for insn in insns2:
 
-            #print "Processing instruction", insn,
-            #print "with args", insn.reg_args, "and result", insn.result, ":"
+            if DEBUG_PRINT:
+                print "Processing instruction", insn,
+                print "with args", insn.reg_args, "and result", insn.result, ":"
 
-            #print "LRU list was:", self.lru
+                print "LRU list was:", self.lru
 
             # put things into the lru
             for arg in insn.reg_args:
                 self._promote(arg)
             if insn.result:
                 self._promote(insn.result)
-            #print "LRU list is now:", self.lru
+            if DEBUG_PRINT:
+                print "LRU list is now:", self.lru
 
             # We need to allocate a register for each used
             # argument that is not already in one
             for i in range(len(insn.reg_args)):
                 arg = insn.reg_args[i]
                 argcls = insn.reg_arg_regclasses[i]
-                #print "Allocating register for", arg, "..."
+                if DEBUG_PRINT:
+                    print "Allocating register for", arg, "..."
                 argloc = self.loc_of(arg)
-                #print "currently in", argloc
+                if DEBUG_PRINT:
+                    print "currently in", argloc
 
                 if not argloc.is_register:
                     # It has no register now because it has been spilled
                     self.forget(arg, argloc)
                     newargloc = self._allocate_reg(argcls, arg)
-                    #print "unspilling to", newargloc
+                    if DEBUG_PRINT:
+                        print "unspilling to", newargloc
                     self.insns.append(Unspill(arg, newargloc, argloc))
                     self.free_stack_slots.append(argloc)
                 elif argloc.regclass != argcls:
@@ -174,13 +187,15 @@
                         self.insns.append(
                             newargloc.move_from_gpr(self, gpr))
                 else:
-                    #print "it was in ", argloc
+                    if DEBUG_PRINT:
+                        print "it was in ", argloc
                     pass
 
             # Need to allocate a register for the destination
             assert not insn.result or insn.result not in self.var2loc
             if insn.result_regclass != NO_REGISTER:
-                #print "Allocating register for result %r..." % (insn.result,)
+                if DEBUG_PRINT:
+                    print "Allocating register for result %r..." % (insn.result,)
                 resultreg = self._allocate_reg(insn.result_regclass, insn.result)
                 if isinstance(insn, CMPInsn):
                     self.crfinfo[resultreg.number] = insn.info

Modified: pypy/branch/mininal-c-backend/pypy/jit/codegen/ppc/rgenop.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/jit/codegen/ppc/rgenop.py	(original)
+++ pypy/branch/mininal-c-backend/pypy/jit/codegen/ppc/rgenop.py	Thu Nov 23 12:28:43 2006
@@ -14,12 +14,16 @@
 from pypy.translator.asm.ppcgen.rassemblermaker import make_rassembler
 from pypy.translator.asm.ppcgen.ppc_assembler import MyPPCAssembler
 
+from pypy.jit.codegen.i386.rgenop import gc_malloc_fnaddr
+
 class RPPCAssembler(make_rassembler(MyPPCAssembler)):
     def emit(self, value):
         self.mc.write(value)
 
 NSAVEDREGISTERS = 19
 
+DEBUG_TRAP = option.trap
+
 _var_index = [0]
 class Var(GenVar):
     def __init__(self):
@@ -211,19 +215,100 @@
         self.insns.append(insn.CALL(gv_result, gv_fnptr))
         return gv_result
 
-##     def genop_getfield(self, fieldtoken, gv_ptr):
-##     def genop_setfield(self, fieldtoken, gv_ptr, gv_value):
-##     def genop_getsubstruct(self, fieldtoken, gv_ptr):
-##     def genop_getarrayitem(self, arraytoken, gv_ptr, gv_index):
-##     def genop_getarraysize(self, arraytoken, gv_ptr):
-##     def genop_setarrayitem(self, arraytoken, gv_ptr, gv_index, gv_value):
-##     def genop_malloc_fixedsize(self, alloctoken):
-##     def genop_malloc_varsize(self, varsizealloctoken, gv_size):
+    def genop_getfield(self, fieldtoken, gv_ptr):
+        gv_result = Var()
+        self.insns.append(
+            insn.Insn_GPR__GPR_IMM(RPPCAssembler.lwz,
+                                   gv_result, [gv_ptr, IntConst(fieldtoken)]))
+        return gv_result
+
+    def genop_setfield(self, fieldtoken, gv_ptr, gv_value):
+        gv_result = Var()
+        self.insns.append(
+            insn.Insn_None__GPR_GPR_IMM(RPPCAssembler.stw,
+                                        [gv_value, gv_ptr, IntConst(fieldtoken)]))
+        return gv_result
+
+    def genop_getsubstruct(self, fieldtoken, gv_ptr):
+        gv_result = Var()
+        self.insns.append(
+            insn.Insn_GPR__GPR_IMM(RPPCAssembler.addi,
+                                   gv_result, [gv_ptr, IntConst(fieldtoken)]))
+        return gv_result
+
+    def genop_getarrayitem(self, arraytoken, gv_ptr, gv_index):
+        _, _, itemsize = arraytoken
+        assert itemsize == 4
+        gv_itemoffset = self.itemoffset(arraytoken, gv_index)
+        gv_result = Var()
+        if gv_itemoffset.fits_in_immediate():
+            self.insns.append(
+                insn.Insn_GPR__GPR_IMM(RPPCAssembler.lwz,
+                                       gv_result, [gv_ptr, gv_itemoffset]))
+        else:
+            self.insns.append(
+                insn.Insn_GPR__GPR_GPR(RPPCAssembler.lwzx,
+                                       gv_result, [gv_ptr, gv_itemoffset]))
+        return gv_result
+
+    def genop_getarraysubstruct(self, arraytoken, gv_ptr, gv_index):
+        _, _, itemsize = arraytoken
+        assert itemsize == 4
+        gv_itemoffset = self.itemoffset(arraytoken, gv_index)
+        gv_result = Var()
+        if gv_itemoffset.fits_in_immediate():
+            self.insns.append(
+                insn.Insn_GPR__GPR_IMM(RPPCAssembler.addi,
+                                       gv_result, [gv_ptr, gv_itemoffset]))
+        else:
+            self.insns.append(
+                insn.Insn_GPR__GPR_GPR(RPPCAssembler.add,
+                                       gv_result, [gv_ptr, gv_itemoffset]))
+        return gv_result
+
+    def genop_getarraysize(self, arraytoken, gv_ptr):
+        lengthoffset, _, _ = arraytoken
+        gv_result = Var()
+        self.insns.append(
+                insn.Insn_GPR__GPR_IMM(RPPCAssembler.lwz,
+                                       gv_result, [gv_ptr, IntConst(lengthoffset)]))
+        return gv_result
+
+    def genop_setarrayitem(self, arraytoken, gv_ptr, gv_index, gv_value):
+        _, _, itemsize = arraytoken
+        assert itemsize == 4
+        gv_itemoffset = self.itemoffset(arraytoken, gv_index)
+        gv_result = Var()
+        if gv_itemoffset.fits_in_immediate():
+            self.insns.append(
+                insn.Insn_None__GPR_GPR_IMM(RPPCAssembler.stw,
+                                            [gv_value, gv_ptr, gv_itemoffset]))
+        else:
+            self.insns.append(
+                insn.Insn_None__GPR_GPR_GPR(RPPCAssembler.stwx,
+                                            [gv_value, gv_ptr, gv_itemoffset]))
+
+    def genop_malloc_fixedsize(self, alloctoken):
+        return self.genop_call(1, # COUGH
+                               IntConst(gc_malloc_fnaddr()),
+                               [IntConst(alloctoken)])
+
+    def genop_malloc_varsize(self, varsizealloctoken, gv_size):
+        gv_itemoffset = self.itemoffset(varsizealloctoken, gv_size)
+        gv_result = self.genop_call(1, # COUGH
+                                    IntConst(gc_malloc_fnaddr()),
+                                    [gv_itemoffset])
+        lengthoffset, _, _ = varsizealloctoken
+        self.insns.append(
+            insn.Insn_None__GPR_GPR_IMM(RPPCAssembler.stw,
+                                        [gv_size, gv_result, IntConst(lengthoffset)]))
+        return gv_result
 
     def genop_same_as(self, kindtoken, gv_arg):
         if not isinstance(gv_arg, Var):
             gv_result = Var()
             gv_arg.load(self.insns, gv_result)
+            return gv_result
         else:
             return gv_arg
 
@@ -330,6 +415,20 @@
     # ----------------------------------------------------------------
     # ppc-specific interface:
 
+    def itemoffset(self, arraytoken, gv_index):
+        # if gv_index is constant, this can return a constant...
+        lengthoffset, startoffset, itemsize = arraytoken
+
+        gv_offset = Var()
+        self.insns.append(
+            insn.Insn_GPR__GPR_IMM(RPPCAssembler.mulli,
+                                   gv_offset, [gv_index, IntConst(itemsize)]))
+        gv_itemoffset = Var()
+        self.insns.append(
+            insn.Insn_GPR__GPR_IMM(RPPCAssembler.addi,
+                               gv_itemoffset, [gv_offset, IntConst(startoffset)]))
+        return gv_itemoffset
+
     def make_fresh_from_jump(self, initial_var2loc):
         self.fresh_from_jump = True
         self.initial_var2loc = initial_var2loc
@@ -337,7 +436,7 @@
 
     def _write_prologue(self, sigtoken):
         numargs = sigtoken     # for now
-        if not we_are_translated() and option.trap:
+        if DEBUG_TRAP:
             self.asm.trap()
         inputargs = [Var() for i in range(numargs)]
         assert self.initial_var2loc is None
@@ -371,6 +470,8 @@
         # save stack pointer into linkage area and set stack pointer for us.
         self.asm.stwu(rSP, rSP, -minspace)
 
+        self.emit_stack_adjustment()
+
         return inputargs
 
     def _var_offset(self, v):
@@ -399,8 +500,8 @@
         allocator = RegisterAllocation(
             self.rgenop.freeregs, self.initial_var2loc, self.initial_spill_offset)
         self.insns = allocator.allocate_for_insns(self.insns)
-        if self.insns:
-            self.patch_stack_adjustment(self._stack_size(allocator.spill_offset))
+        #if self.insns:
+        self.patch_stack_adjustment(self._stack_size(allocator.spill_offset))
         for insn in self.insns:
             insn.emit(self.asm)
         return allocator
@@ -549,12 +650,21 @@
             insn.CMPWI(self.cmp2info['ne'], gv_result, [gv_arg, self.rgenop.genconst(0)]))
         return gv_result
 
+    def op_bool_not(self, gv_arg):
+        gv_result = Var()
+        self.insns.append(
+            insn.CMPWI(self.cmp2info['eq'], gv_result, [gv_arg, self.rgenop.genconst(0)]))
+        return gv_result
+
     def op_int_neg(self, gv_arg):
         gv_result = Var()
         self.insns.append(
             insn.Insn_GPR__GPR(RPPCAssembler.neg, gv_result, gv_arg))
         return gv_result
 
+    op_ptr_nonzero = op_int_is_true
+    op_ptr_iszero  = op_bool_not        # for now
+
 
 class RPPCGenOp(AbstractRGenOp):
 
@@ -607,21 +717,38 @@
 ##     @staticmethod
 ##     def erasedType(T):
 
-##     @staticmethod
-##     @specialize.memo()
-##     def fieldToken(T, name):
+    @staticmethod
+    @specialize.memo()
+    def fieldToken(T, name):
+        return llmemory.offsetof(T, name)
 
-##     @staticmethod
-##     @specialize.memo()
-##     def allocToken(T):
+    @staticmethod
+    @specialize.memo()
+    def allocToken(T):
+        return llmemory.sizeof(T)
 
-##     @staticmethod
-##     @specialize.memo()
-##     def varsizeAllocToken(T):
+    @staticmethod
+    @specialize.memo()
+    def varsizeAllocToken(T):
+        if isinstance(T, lltype.Array):
+            return RPPCGenOp.arrayToken(T)
+        else:
+            # var-sized structs
+            arrayfield = T._arrayfld
+            ARRAYFIELD = getattr(T, arrayfield)
+            arraytoken = RPPCGenOp.arrayToken(ARRAYFIELD)
+            length_offset, items_offset, item_size = arraytoken
+            arrayfield_offset = llmemory.offsetof(T, arrayfield)
+            return (arrayfield_offset+length_offset,
+                    arrayfield_offset+items_offset,
+                    item_size)
 
-##     @staticmethod
-##     @specialize.memo()
-##     def arrayToken(A):
+    @staticmethod
+    @specialize.memo()
+    def arrayToken(A):
+        return (llmemory.ArrayLengthOffset(A),
+                llmemory.ArrayItemsOffset(A),
+                llmemory.ItemOffset(A.OF))
 
     @staticmethod
     @specialize.memo()

Modified: pypy/branch/mininal-c-backend/pypy/jit/hintannotator/model.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/jit/hintannotator/model.py	(original)
+++ pypy/branch/mininal-c-backend/pypy/jit/hintannotator/model.py	Thu Nov 23 12:28:43 2006
@@ -125,9 +125,10 @@
 
 class SomeLLAbstractValue(annmodel.SomeObject):
 
-    def __init__(self, T):
+    def __init__(self, T, deepfrozen=False):
         self.concretetype = T
         assert self.__class__ != SomeLLAbstractValue
+        self.deepfrozen = deepfrozen
 
     def is_green(self, frame=None):
         return False
@@ -138,11 +139,10 @@
 
     def __init__(self, T, origins, eager_concrete=False, myorigin=None,
                  deepfrozen=False):
-        SomeLLAbstractValue.__init__(self, T)
+        SomeLLAbstractValue.__init__(self, T, deepfrozen)
         self.origins = origins
         self.eager_concrete = eager_concrete
         self.myorigin = myorigin
-        self.deepfrozen = deepfrozen
         assert myorigin is None or myorigin.spaceop is not None
 
     def fmt_origins(self, origins):
@@ -198,6 +198,7 @@
 
 
 class SomeLLAbstractContainer(SomeLLAbstractValue):
+    deepfrozen = False     # XXX for now
 
     def __init__(self, contentdef):
         self.contentdef = contentdef
@@ -249,6 +250,15 @@
     else:
         return hs.concretetype
 
+def deepunfreeze(hs):
+    if hs.deepfrozen:
+        hs1 = annmodel.SomeObject()
+        hs1.__class__ = hs.__class__
+        hs1.__dict__ = hs.__dict__.copy()
+        hs1.deepfrozen = False
+        hs = hs1
+    return hs
+
 # ____________________________________________________________
 # operations
 
@@ -281,7 +291,7 @@
     def getfield(hs_v1, hs_fieldname):
         S = hs_v1.concretetype.TO
         FIELD_TYPE = getattr(S, hs_fieldname.const)
-        return SomeLLAbstractVariable(FIELD_TYPE)
+        return SomeLLAbstractVariable(FIELD_TYPE, hs_v1.deepfrozen)
 
     def setfield(hs_v1, hs_fieldname, hs_value):
         pass
@@ -289,7 +299,7 @@
     def getsubstruct(hs_v1, hs_fieldname):
         S = hs_v1.concretetype.TO
         FIELD_TYPE = getattr(S, hs_fieldname.const)
-        return SomeLLAbstractVariable(lltype.Ptr(FIELD_TYPE))
+        return SomeLLAbstractVariable(lltype.Ptr(FIELD_TYPE), hs_v1.deepfrozen)
 
 ##    def getarrayitem(hs_v1, hs_index):
 ##        ARRAY = hs_v1.concretetype.TO
@@ -437,28 +447,44 @@
 class __extend__(pairtype(SomeLLAbstractValue, SomeLLAbstractValue)):
 
     def getarrayitem((hs_v1, hs_v2)):
-        return SomeLLAbstractVariable(hs_v1.concretetype.TO.OF)
+        return SomeLLAbstractVariable(hs_v1.concretetype.TO.OF,
+                                      hs_v1.deepfrozen)
 
     def setarrayitem((hs_v1, hs_v2), hs_v3):
         pass
 
+    def getarraysubstruct((hs_v1, hs_v2)):
+        return SomeLLAbstractVariable(lltype.Ptr(hs_v1.concretetype.TO.OF),
+                                      hs_v1.deepfrozen)
+
     def union((hs_v1, hs_v2)):
+        if hs_v1.deepfrozen != hs_v2.deepfrozen:
+            hs_v1 = deepunfreeze(hs_v1)
+            hs_v2 = deepunfreeze(hs_v2)
+            if hs_v1 == hs_v2:
+                return hs_v1
+        return pair(hs_v1, hs_v2).union_frozen_equal()
+
+    def invalid_union((hs_v1, hs_v2)):
         raise annmodel.UnionError("%s %s don't mix" % (hs_v1, hs_v2))
 
+    union_frozen_equal = invalid_union
+
 
 class __extend__(pairtype(SomeLLAbstractVariable, SomeLLAbstractConstant),
                  pairtype(SomeLLAbstractConstant, SomeLLAbstractVariable)):
 
-    def union((hs_v1, hs_v2)):
+    def union_frozen_equal((hs_v1, hs_v2)):
         assert hs_v1.concretetype == hs_v2.concretetype
-        if getattr(hs_v1, 'eager_concrete', False) or getattr(hs_v2, 'eager_concrete', False):
-            raise annmodel.UnionError("%s %s don't mix" % (hs_v1, hs_v2))
-        return SomeLLAbstractVariable(hs_v1.concretetype)
+        if (getattr(hs_v1, 'eager_concrete', False) or
+            getattr(hs_v2, 'eager_concrete', False)):
+            pair(hs_v1, hs_v2).invalid_union()
+        return SomeLLAbstractVariable(hs_v1.concretetype, hs_v1.deepfrozen)
 
 
 class __extend__(pairtype(SomeLLAbstractConstant, SomeLLAbstractConstant)):
 
-    def union((hs_c1, hs_c2)):
+    def union_frozen_equal((hs_c1, hs_c2)):
         assert hs_c1.concretetype == hs_c2.concretetype
         d = newset(hs_c1.origins, hs_c2.origins)
         if hs_c1.myorigin is hs_c2.myorigin:
@@ -469,7 +495,7 @@
                                       eager_concrete = hs_c1.eager_concrete and
                                                        hs_c2.eager_concrete,
                                       myorigin = myorigin,
-                                      deepfrozen = hs_c1.deepfrozen and hs_c2.deepfrozen)
+                                      deepfrozen = hs_c1.deepfrozen)
 
 
     def getarrayitem((hs_c1, hs_index)):
@@ -496,9 +522,9 @@
         
 class __extend__(pairtype(SomeLLAbstractContainer, SomeLLAbstractContainer)):
 
-    def union((hs_cont1, hs_cont2)):
+    def union_frozen_equal((hs_cont1, hs_cont2)):
         contentdef = hs_cont1.contentdef.union(hs_cont2.contentdef)
-        return SomeLLAbstractContainer(contentdef)
+        return SomeLLAbstractContainer(contentdef)   # XXX deepfrozen?
 
     def ptr_eq((hs_cont1, hs_cont2)):
         return SomeLLAbstractConstant(lltype.Bool, {})
@@ -508,15 +534,15 @@
 
 
 class __extend__(pairtype(SomeLLAbstractContainer, SomeLLAbstractValue)):
-    def union((hs_cont1, hs_val2)):
+    def union_frozen_equal((hs_cont1, hs_val2)):
         hs_cont1.contentdef.mark_degenerated()
         assert hs_cont1.concretetype == hs_val2.concretetype
-        return SomeLLAbstractVariable(hs_cont1.concretetype)
+        return SomeLLAbstractVariable(hs_cont1.concretetype) # XXX deepfrozen?
 
 
 class __extend__(pairtype(SomeLLAbstractValue, SomeLLAbstractContainer)):
-    def union((hs_val1, hs_cont2)):
-        return pair(hs_cont2, hs_val1).union()
+    def union_frozen_equal((hs_val1, hs_cont2)):
+        return pair(hs_cont2, hs_val1).union_frozen_equal()
 
 
 class __extend__(pairtype(SomeLLAbstractContainer, SomeLLAbstractValue),
@@ -550,6 +576,8 @@
     operation_name, args = ll_func.oopspec.split('(', 1)
     assert args.endswith(')')
     args = args[:-1] + ','     # trailing comma to force tuple syntax
+    if args.strip() == ',':
+        args = '()'
     argnames = ll_func.func_code.co_varnames[:len(args_hs)]
     d = dict(zip(argnames, args_hs))
     argtuple = eval(args, d)

Modified: pypy/branch/mininal-c-backend/pypy/jit/hintannotator/test/test_annotator.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/jit/hintannotator/test/test_annotator.py	(original)
+++ pypy/branch/mininal-c-backend/pypy/jit/hintannotator/test/test_annotator.py	Thu Nov 23 12:28:43 2006
@@ -525,6 +525,17 @@
     assert isinstance(ha.binding(v2), SomeLLAbstractConstant)
     assert ha.binding(v1).deepfrozen
 
+def test_deepfreeze_variables():
+    l1 = [[1], [2, 3], [4], []]
+    def ll_function(i):
+        i = hint(i, variable=True)
+        l = hint(l1, deepfreeze=True)
+        return l[i]
+
+    hs, ha = hannotate(ll_function, [int], annotator=True, policy=P_NOVIRTUAL)
+    assert isinstance(hs, SomeLLAbstractVariable)
+    assert hs.deepfrozen
+
 def test_propagate_fixing_across_func_arguments():
     def ll_func2(z):
         z = hint(z, concrete=True)

Modified: pypy/branch/mininal-c-backend/pypy/jit/timeshifter/hrtyper.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/jit/timeshifter/hrtyper.py	(original)
+++ pypy/branch/mininal-c-backend/pypy/jit/timeshifter/hrtyper.py	Thu Nov 23 12:28:43 2006
@@ -160,6 +160,10 @@
                 if nextgraph not in seen:
                     pending.append(nextgraph)
                     seen[nextgraph] = True
+        # only keep the hint-annotated graphs that are really useful
+        self.annotator.translator.graphs = [graph
+            for graph in self.annotator.translator.graphs
+            if graph in seen]
         if view:
             self.annotator.translator.view()     # in the middle
         for graph in seen:
@@ -456,9 +460,9 @@
                     del link.args[0]    # Void
                 link.args = [v_jitstate] + link.args
 
-    def generic_translate_operation(self, hop, force=False):
+    def generic_translate_operation(self, hop):
         # detect constant-foldable all-green operations
-        if not force and hop.spaceop.opname not in rtimeshift.FOLDABLE_OPS:
+        if hop.spaceop.opname not in rtimeshift.FOLDABLE_GREEN_OPS:
             return None
         green = True
         for r_arg in hop.args_r:
@@ -492,7 +496,7 @@
                                                [c_opdesc, v_jitstate]    + args_v,
                                                ts.s_RedBox)
 
-    def translate_op_debug_log_exc(self, hop): # don't timeshift debug_log_exc
+    def translate_op_debug_assert(self, hop):
         pass
 
     def translate_op_keepalive(self,hop):
@@ -522,49 +526,39 @@
                                                    ts.s_RedBox)
         # non virtual case        
         PTRTYPE = originalconcretetype(hop.args_s[0])
-        if PTRTYPE.TO._hints.get('immutable', False): # foldable if all green
-            res = self.generic_translate_operation(hop, force=True)
-            if res is not None:
-                return res
-            
         v_argbox, c_fieldname = hop.inputargs(self.getredrepr(PTRTYPE),
                                               green_void_repr)
         v_argbox = hop.llops.as_ptrredbox(v_argbox)
+        c_deepfrozen = inputconst(lltype.Bool, hop.args_s[0].deepfrozen)
         structdesc = rcontainer.StructTypeDesc(self.RGenOp, PTRTYPE.TO)
         fielddesc = structdesc.getfielddesc(c_fieldname.value)
         c_fielddesc = inputconst(lltype.Void, fielddesc)
         s_fielddesc = ts.rtyper.annotator.bookkeeper.immutablevalue(fielddesc)
         v_jitstate = hop.llops.getjitstate()
         return hop.llops.genmixlevelhelpercall(rtimeshift.ll_gengetfield,
-            [ts.s_JITState, s_fielddesc, ts.s_PtrRedBox],
-            [v_jitstate,    c_fielddesc, v_argbox      ],
+            [ts.s_JITState, annmodel.s_Bool, s_fielddesc, ts.s_PtrRedBox],
+            [v_jitstate   , c_deepfrozen   , c_fielddesc, v_argbox      ],
             ts.s_RedBox)
 
     def translate_op_getarrayitem(self, hop):
         PTRTYPE = originalconcretetype(hop.args_s[0])
-        if PTRTYPE.TO._hints.get('immutable', False): # foldable if all green
-            res = self.generic_translate_operation(hop, force=True)
-            if res is not None:
-                return res
-
         ts = self
         v_argbox, v_index = hop.inputargs(self.getredrepr(PTRTYPE),
                                           self.getredrepr(lltype.Signed))
+        c_deepfrozen = inputconst(lltype.Bool, hop.args_s[0].deepfrozen)
         fielddesc = rcontainer.ArrayFieldDesc(self.RGenOp, PTRTYPE.TO)
         c_fielddesc = inputconst(lltype.Void, fielddesc)
         s_fielddesc = ts.rtyper.annotator.bookkeeper.immutablevalue(fielddesc)
         v_jitstate = hop.llops.getjitstate()
         return hop.llops.genmixlevelhelpercall(
             rtimeshift.ll_gengetarrayitem,
-            [ts.s_JITState, s_fielddesc, ts.s_RedBox, ts.s_RedBox],
-            [v_jitstate,    c_fielddesc, v_argbox,    v_index    ],
+            [ts.s_JITState, annmodel.s_Bool, s_fielddesc,
+                                ts.s_RedBox, ts.s_RedBox],
+            [v_jitstate,       c_deepfrozen, c_fielddesc,
+                                   v_argbox,    v_index ],
             ts.s_RedBox)
 
     def translate_op_getarraysize(self, hop):
-        res = self.generic_translate_operation(hop, force=True)
-        if res is not None:
-            return res
-        
         PTRTYPE = originalconcretetype(hop.args_s[0])
         ts = self
         [v_argbox] = hop.inputargs(self.getredrepr(PTRTYPE))
@@ -652,6 +646,22 @@
             [v_jitstate,    c_fielddesc, v_argbox      ],
             ts.s_RedBox)
 
+    def translate_op_getarraysubstruct(self, hop):
+        PTRTYPE = originalconcretetype(hop.args_s[0])
+        ts = self
+        v_argbox, v_index = hop.inputargs(self.getredrepr(PTRTYPE),
+                                          self.getredrepr(lltype.Signed))
+        fielddesc = rcontainer.ArrayFieldDesc(self.RGenOp, PTRTYPE.TO)
+        c_fielddesc = inputconst(lltype.Void, fielddesc)
+        s_fielddesc = ts.rtyper.annotator.bookkeeper.immutablevalue(fielddesc)
+        v_jitstate = hop.llops.getjitstate()
+        return hop.llops.genmixlevelhelpercall(
+            rtimeshift.ll_gengetarraysubstruct,
+            [ts.s_JITState, s_fielddesc, ts.s_RedBox, ts.s_RedBox],
+            [v_jitstate,    c_fielddesc, v_argbox,    v_index    ],
+            ts.s_RedBox)
+
+
     def translate_op_cast_pointer(self, hop):
         FROM_TYPE = originalconcretetype(hop.args_s[0])
         [v_argbox] = hop.inputargs(self.getredrepr(FROM_TYPE))
@@ -685,19 +695,36 @@
         ts = self
         PTRTYPE = originalconcretetype(hop.args_s[0])
         v_argbox, = hop.inputargs(self.getredrepr(PTRTYPE))
+        v_argbox = hop.llops.as_ptrredbox(v_argbox)
         v_jitstate = hop.llops.getjitstate()
         c_reverse = hop.inputconst(lltype.Bool, reverse)
         return hop.llops.genmixlevelhelpercall(rtimeshift.ll_genptrnonzero,
-            [ts.s_JITState, ts.s_RedBox, annmodel.SomeBool()],
-            [v_jitstate,    v_argbox,    c_reverse          ],
+            [ts.s_JITState, ts.s_PtrRedBox, annmodel.s_Bool],
+            [v_jitstate   , v_argbox      , c_reverse      ],
             ts.s_RedBox)
 
     def translate_op_ptr_iszero(self, hop):
         return self.translate_op_ptr_nonzero(hop, reverse=True)
 
+    def translate_op_ptr_eq(self, hop, reverse=False):
+        ts = self
+        PTRTYPE = originalconcretetype(hop.args_s[0])
+        r_ptr = self.getredrepr(PTRTYPE)
+        v_argbox0, v_argbox1 = hop.inputargs(r_ptr, r_ptr)
+        v_argbox0 = hop.llops.as_ptrredbox(v_argbox0)
+        v_argbox1 = hop.llops.as_ptrredbox(v_argbox1)
+        v_jitstate = hop.llops.getjitstate()
+        c_reverse = hop.inputconst(lltype.Bool, reverse)
+        return hop.llops.genmixlevelhelpercall(rtimeshift.ll_genptreq,
+            [ts.s_JITState, ts.s_PtrRedBox, ts.s_PtrRedBox, annmodel.s_Bool],
+            [v_jitstate   , v_argbox0     , v_argbox1     , c_reverse      ],
+            ts.s_RedBox)
+
+    def translate_op_ptr_ne(self, hop):
+        return self.translate_op_ptr_eq(hop, reverse=True)
 
-    # special operations inserted by the HintGraphTransformer
 
+    # special operations inserted by the HintGraphTransformer
 
     def translate_op_ensure_queue(self, hop, prefix=''):
         mpfamily = hop.args_v[0].value
@@ -1017,7 +1044,10 @@
         # Pass them as constant Nones.
         ts = self
         ll_handler = oopspecdesc.ll_handler
-        missing_args = ((ll_handler.func_code.co_argcount - 2) -
+
+        couldfold = oopspecdesc.couldfold
+        
+        missing_args = ((ll_handler.func_code.co_argcount - 2 - couldfold) -
                         len(oopspecdesc.argtuple))
         assert missing_args >= 0
         if missing_args > 0:
@@ -1027,9 +1057,17 @@
             args_v.extend([hop.llops.genconst(ll_None)] * missing_args)
 
         args_s = [ts.s_RedBox] * len(args_v)
+
         if oopspecdesc.is_method:
             args_s[0] = ts.s_PtrRedBox    # for more precise annotations
             args_v[0] = hop.llops.as_ptrredbox(args_v[0])
+
+        if couldfold:
+            args_s.insert(0, annmodel.s_Bool)
+            hs_self = hop.args_s[oopspecdesc.argtuple[0].n]
+            c_deepfrozen = inputconst(lltype.Bool, hs_self.deepfrozen)
+            args_v.insert(0, c_deepfrozen)
+        
         RESULT = originalconcretetype(hop.s_result)
         if RESULT is lltype.Void:
             s_result = annmodel.s_None

Modified: pypy/branch/mininal-c-backend/pypy/jit/timeshifter/oop.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/jit/timeshifter/oop.py	(original)
+++ pypy/branch/mininal-c-backend/pypy/jit/timeshifter/oop.py	Thu Nov 23 12:28:43 2006
@@ -3,6 +3,7 @@
 from pypy.jit.timeshifter.rcontainer import cachedtype
 from pypy.jit.timeshifter import rvalue, rtimeshift
 from pypy.translator.c import exceptiontransform
+from pypy.rlib.unroll import unrolling_iterable
 
 
 class Index:
@@ -13,6 +14,8 @@
 class OopSpecDesc:
     __metaclass__ = cachedtype
 
+    do_call = None
+
     def __init__(self, hrtyper, fnobj):
         ll_func = fnobj._callable
         FUNCTYPE = lltype.typeOf(fnobj)
@@ -22,6 +25,8 @@
         operation_name, args = ll_func.oopspec.split('(', 1)
         assert args.endswith(')')
         args = args[:-1] + ','     # trailing comma to force tuple syntax
+        if args.strip() == ',':
+            args = '()'
         argnames = ll_func.func_code.co_varnames[:nb_args]
         d = dict(zip(argnames, [Index(n) for n in range(nb_args)]))
         self.argtuple = eval(args, d)
@@ -40,21 +45,28 @@
 
         RGenOp = hrtyper.RGenOp
         self.args_gv = [None] * nb_args
-        self.gv_fnptr = RGenOp.constPrebuiltGlobal(fnobj._as_ptr())
-        self.result_kind = RGenOp.kindToken(FUNCTYPE.RESULT)
+        fnptr = fnobj._as_ptr()
+        self.gv_fnptr = RGenOp.constPrebuiltGlobal(fnptr)
+        result_kind = RGenOp.kindToken(FUNCTYPE.RESULT)
+        self.result_kind = result_kind
         if FUNCTYPE.RESULT is lltype.Void:
             self.errorbox = None
         else:
             error_value = exceptiontransform.error_value(FUNCTYPE.RESULT)
             self.errorbox = rvalue.redbox_from_prebuilt_value(RGenOp,
                                                               error_value)
-        self.redboxbuilder = rvalue.ll_redboxbuilder(FUNCTYPE.RESULT)
+        redboxbuilder = rvalue.ll_redboxbuilder(FUNCTYPE.RESULT)
+        self.redboxbuilder = redboxbuilder
         self.sigtoken = RGenOp.sigToken(FUNCTYPE)
 
         if operation_name == 'newlist':
             typename, method = 'list', 'oop_newlist'
             SELFTYPE = FUNCTYPE.RESULT.TO
             self.is_method = False
+        elif operation_name == 'newdict':
+            typename, method = 'dict', 'oop_newdict'
+            SELFTYPE = FUNCTYPE.RESULT.TO
+            self.is_method = False
         else:
             typename, method = operation_name.split('.')
             method = 'oop_%s_%s' % (typename, method)
@@ -65,6 +77,7 @@
                              None, None, [method])
         self.typedesc = vmodule.TypeDesc(hrtyper, SELFTYPE)
         self.ll_handler = getattr(vmodule, method)
+        self.couldfold = getattr(self.ll_handler, 'couldfold', False)
 
         # exception handling
         graph = fnobj.graph
@@ -72,15 +85,41 @@
         self.can_raise = etrafo.raise_analyzer.analyze_direct_call(graph)
         self.fetch_global_excdata = hrtyper.fetch_global_excdata
 
-    def residual_call(self, jitstate, argboxes):
+        if self.couldfold:
+            ARGS = FUNCTYPE.ARGS
+            argpos = unrolling_iterable(enumerate(self.argpositions))
+
+            def do_call(jitstate, argboxes):
+                args = (None,)*nb_args
+                for i, pos in argpos:
+                    if pos >= 0:
+                        T = ARGS[pos]
+                        v = rvalue.ll_getvalue(argboxes[i], T)
+                        args = args[:pos] +(v,) + args[pos+1:]
+                result = fnptr(*args)
+                if FUNCTYPE.RESULT == lltype.Void:
+                    return None
+                return rvalue.ll_fromvalue(jitstate, result)
+
+            self.do_call = do_call
+            
+    def residual_call(self, jitstate, argboxes, deepfrozen=False):
         builder = jitstate.curbuilder
         args_gv = self.args_gv[:]
         argpositions = self.argpositions
+        fold = deepfrozen
         for i in range(len(argpositions)):
             pos = argpositions[i]
             if pos >= 0:
                 gv_arg = argboxes[i].getgenvar(builder)
                 args_gv[pos] = gv_arg
+                fold &= gv_arg.is_const
+        if fold:
+            try:
+                return self.do_call(jitstate, argboxes)
+            except Exception, e:
+                jitstate.residual_exception(e)
+                return self.errorbox
         gv_result = builder.genop_call(self.sigtoken, self.gv_fnptr, args_gv)
         if self.can_raise:
             self.fetch_global_excdata(jitstate)
@@ -88,11 +127,7 @@
 
     def residual_exception(self, jitstate, ExcCls):
         ll_evalue = get_ll_instance_for_exccls(ExcCls)
-        ll_etype  = ll_evalue.typeptr
-        etypebox  = rvalue.ll_fromvalue(jitstate, ll_etype)
-        evaluebox = rvalue.ll_fromvalue(jitstate, ll_evalue)
-        rtimeshift.setexctypebox (jitstate, etypebox )
-        rtimeshift.setexcvaluebox(jitstate, evaluebox)
+        jitstate.residual_ll_exception(ll_evalue)
         return self.errorbox
     residual_exception._annspecialcase_ = 'specialize:arg(2)'
 

Modified: pypy/branch/mininal-c-backend/pypy/jit/timeshifter/rcontainer.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/jit/timeshifter/rcontainer.py	(original)
+++ pypy/branch/mininal-c-backend/pypy/jit/timeshifter/rcontainer.py	Thu Nov 23 12:28:43 2006
@@ -2,6 +2,11 @@
 from pypy.rpython.lltypesystem import lltype
 from pypy.rpython.annlowlevel import cachedtype
 from pypy.jit.timeshifter import rvalue
+from pypy.rlib.unroll import unrolling_iterable
+
+from pypy.rpython.lltypesystem import lloperation
+debug_print = lloperation.llop.debug_print
+debug_pdb = lloperation.llop.debug_pdb
 
 class AbstractContainer(object):
     __slots__ = []
@@ -15,6 +20,20 @@
     def op_getsubstruct(self, jitstate, fielddesc):
         raise NotImplementedError
 
+
+class VirtualContainer(AbstractContainer):
+    __slots__ = []
+
+
+class FrozenContainer(AbstractContainer):
+    __slots__ = []
+
+    def exactmatch(self, vstruct, outgoingvarboxes, memo):
+        raise NotImplementedError
+    
+    def unfreeze(self, incomingvarboxes, memo):
+        raise NotImplementedError
+
 # ____________________________________________________________
 
 class StructTypeDesc(object):
@@ -23,6 +42,7 @@
     arrayfielddesc = None
     alloctoken = None
     varsizealloctoken = None
+    materialize = None
     
     def __init__(self, RGenOp, TYPE):
         self.TYPE = TYPE
@@ -58,6 +78,22 @@
         self.fielddesc_by_name = fielddesc_by_name
         self.innermostdesc = innermostdesc
 
+        self.immutable = TYPE._hints.get('immutable', False)
+        self.noidentity = TYPE._hints.get('noidentity', False)
+
+        if self.immutable and self.noidentity:
+            descs = unrolling_iterable(fielddescs)
+            def materialize(rgenop, boxes):
+                s = lltype.malloc(TYPE)
+                i = 0
+                for desc in descs:
+                    v = rvalue.ll_getvalue(boxes[i], desc.RESTYPE)
+                    setattr(s, desc.fieldname, v)
+                    i = i + 1
+                return rgenop.genconst(s)
+
+            self.materialize = materialize
+                
     def getfielddesc(self, name):
         return self.fielddesc_by_name[name]
 
@@ -137,7 +173,7 @@
 
 # ____________________________________________________________
 
-class FrozenVirtualStruct(AbstractContainer):
+class FrozenVirtualStruct(FrozenContainer):
 
     def __init__(self, typedesc):
         self.typedesc = typedesc
@@ -178,6 +214,7 @@
         ownbox = typedesc.factory()
         contmemo[self] = ownbox
         vstruct = ownbox.content
+        assert isinstance(vstruct, VirtualStruct)
         self_boxes = self.fz_content_boxes
         for i in range(len(self_boxes)):
             fz_box = self_boxes[i]
@@ -186,11 +223,7 @@
         return ownbox
 
 
-class AbstractStruct(AbstractContainer):
-    pass
-
-
-class VirtualStruct(AbstractStruct):
+class VirtualStruct(VirtualContainer):
 
     def __init__(self, typedesc):
         self.typedesc = typedesc
@@ -208,6 +241,17 @@
         typedesc = self.typedesc
         boxes = self.content_boxes
         self.content_boxes = None
+        if typedesc.materialize is not None:
+            for box in boxes:
+                if box is None or not box.is_constant():
+                    break
+            else:
+                gv = typedesc.materialize(builder.rgenop, boxes)
+                self.ownbox.genvar = gv
+                self.ownbox.content = None
+                return
+        debug_print(lltype.Void, "FORCE CONTAINER")
+        #debug_pdb(lltype.Void)
         genvar = builder.genop_malloc_fixedsize(typedesc.alloctoken)
         # force the box pointing to this VirtualStruct
         self.ownbox.genvar = genvar
@@ -253,8 +297,46 @@
     def op_getsubstruct(self, jitstate, fielddesc):
         return self.ownbox
 
+# ____________________________________________________________
 
-class PartialDataStruct(AbstractStruct):
+class FrozenPartialDataStruct(AbstractContainer):
+
+    def __init__(self):
+        self.fz_data = []
+
+    def getfzbox(self, searchindex):
+        for index, fzbox in self.fz_data:
+            if index == searchindex:
+                return fzbox
+        else:
+            return None
+
+    def match(self, box, partialdatamatch):
+        content = box.content
+        if not isinstance(content, PartialDataStruct):
+            return False
+
+        cankeep = {}
+        for index, subbox in content.data:
+            selfbox = self.getfzbox(index)
+            if selfbox is not None and selfbox.is_constant_equal(subbox):
+                cankeep[index] = None
+        fullmatch = len(cankeep) == len(self.fz_data)
+        try:
+            prevkeep = partialdatamatch[box]
+        except KeyError:
+            partialdatamatch[box] = cankeep
+        else:
+            if prevkeep is not None:
+                d = {}
+                for index in prevkeep:
+                    if index in cankeep:
+                        d[index] = None
+                partialdatamatch[box] = d
+        return fullmatch
+
+
+class PartialDataStruct(AbstractContainer):
 
     def __init__(self):
         self.data = []
@@ -276,6 +358,19 @@
         else:
             self.data.append((searchindex, box))
 
+    def partialfreeze(self, memo):
+        contmemo = memo.containers
+        assert self not in contmemo     # contmemo no longer used
+        result = contmemo[self] = FrozenPartialDataStruct()
+        for index, box in self.data:
+            if box.is_constant():
+                frozenbox = box.freeze(memo)
+                result.fz_data.append((index, frozenbox))
+        if len(result.fz_data) == 0:
+            return None
+        else:
+            return result
+
     def copy(self, memo):
         result = PartialDataStruct()
         for index, box in self.data:
@@ -294,3 +389,18 @@
             contmemo[self] = None
             for index, box in self.data:
                 box.enter_block(incoming, memo)
+
+    def cleanup_partial_data(self, keep):
+        if keep is None:
+            return None
+        j = 0
+        data = self.data
+        for i in range(len(data)):
+            item = data[i]
+            if item[0] in keep:
+                data[j] = item
+                j += 1
+        if j == 0:
+            return None
+        del data[j:]
+        return self

Modified: pypy/branch/mininal-c-backend/pypy/jit/timeshifter/rtimeshift.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/jit/timeshifter/rtimeshift.py	(original)
+++ pypy/branch/mininal-c-backend/pypy/jit/timeshifter/rtimeshift.py	Thu Nov 23 12:28:43 2006
@@ -2,7 +2,7 @@
 from pypy.annotation import model as annmodel
 from pypy.rpython.lltypesystem import lltype, lloperation, llmemory
 from pypy.jit.hintannotator.model import originalconcretetype
-from pypy.jit.timeshifter import rvalue
+from pypy.jit.timeshifter import rvalue, rcontainer
 from pypy.rlib.unroll import unrolling_iterable
 from pypy.rpython.annlowlevel import cachedtype, base_ptr_lltype
 from pypy.rpython.annlowlevel import cast_instance_to_base_ptr
@@ -10,6 +10,10 @@
 
 FOLDABLE_OPS = dict.fromkeys(lloperation.enum_foldable_ops())
 
+FOLDABLE_GREEN_OPS = FOLDABLE_OPS.copy()
+FOLDABLE_GREEN_OPS['getfield'] = None
+FOLDABLE_GREEN_OPS['getarrayitem'] = None
+
 debug_view = lloperation.llop.debug_view
 debug_print = lloperation.llop.debug_print
 
@@ -96,8 +100,8 @@
     genvar = jitstate.curbuilder.genop_malloc_varsize(alloctoken, gv_size)
     return rvalue.PtrRedBox(contdesc.ptrkind, genvar)
 
-def ll_gengetfield(jitstate, fielddesc, argbox):
-    if fielddesc.immutable and argbox.is_constant():
+def ll_gengetfield(jitstate, deepfrozen, fielddesc, argbox):
+    if (fielddesc.immutable or deepfrozen) and argbox.is_constant():
         res = getattr(rvalue.ll_getvalue(argbox, fielddesc.PTRTYPE),
                       fielddesc.fieldname)
         return rvalue.ll_fromvalue(jitstate, res)
@@ -113,8 +117,9 @@
         return rvalue.ll_fromvalue(jitstate, res)
     return argbox.op_getsubstruct(jitstate, fielddesc)
 
-def ll_gengetarrayitem(jitstate, fielddesc, argbox, indexbox):
-    if fielddesc.immutable and argbox.is_constant() and indexbox.is_constant():
+def ll_gengetarrayitem(jitstate, deepfrozen, fielddesc, argbox, indexbox):
+    if ((fielddesc.immutable or deepfrozen) and argbox.is_constant()
+                                            and indexbox.is_constant()):
         array = rvalue.ll_getvalue(argbox, fielddesc.PTRTYPE)
         res = array[rvalue.ll_getvalue(indexbox, lltype.Signed)]
         return rvalue.ll_fromvalue(jitstate, res)
@@ -125,6 +130,19 @@
                                                     
     return fielddesc.redboxcls(fielddesc.kind, genvar)
 
+def ll_gengetarraysubstruct(jitstate, fielddesc, argbox, indexbox):
+    if argbox.is_constant() and indexbox.is_constant():
+        array = rvalue.ll_getvalue(argbox, fielddesc.PTRTYPE)
+        res = array[rvalue.ll_getvalue(indexbox, lltype.Signed)]
+        return rvalue.ll_fromvalue(jitstate, res)
+    genvar = jitstate.curbuilder.genop_getarraysubstruct(
+        fielddesc.arraytoken,
+        argbox.getgenvar(jitstate.curbuilder),
+        indexbox.getgenvar(jitstate.curbuilder))
+                                                    
+    return fielddesc.redboxcls(fielddesc.kind, genvar)
+
+
 def ll_gensetarrayitem(jitstate, fielddesc, destbox, indexbox, valuebox):
     genvar = jitstate.curbuilder.genop_setarrayitem(
         fielddesc.arraytoken,
@@ -149,7 +167,6 @@
     if argbox.is_constant():
         addr = rvalue.ll_getvalue(argbox, llmemory.Address)
         return rvalue.ll_fromvalue(jitstate, bool(addr) ^ reverse)
-    assert isinstance(argbox, rvalue.PtrRedBox)
     builder = jitstate.curbuilder
     if argbox.content is None:
         gv_addr = argbox.getgenvar(builder)
@@ -161,6 +178,23 @@
         gv_res = builder.rgenop.genconst(True ^ reverse)
     return rvalue.IntRedBox(builder.rgenop.kindToken(lltype.Bool), gv_res)
 
+def ll_genptreq(jitstate, argbox0, argbox1, reverse):
+    builder = jitstate.curbuilder
+    if argbox0.content is not None or argbox1.content is not None:
+        equal = argbox0.content is argbox1.content
+        return rvalue.ll_fromvalue(jitstate, equal ^ reverse)
+    elif argbox0.is_constant() and argbox1.is_constant():
+        addr0 = rvalue.ll_getvalue(argbox0, llmemory.Address)
+        addr1 = rvalue.ll_getvalue(argbox1, llmemory.Address)
+        return rvalue.ll_fromvalue(jitstate, (addr0 == addr1) ^ reverse)
+    gv_addr0 = argbox0.getgenvar(builder)
+    gv_addr1 = argbox1.getgenvar(builder)
+    if reverse:
+        gv_res = builder.genop2("ptr_ne", gv_addr0, gv_addr1)
+    else:
+        gv_res = builder.genop2("ptr_eq", gv_addr0, gv_addr1)
+    return rvalue.IntRedBox(builder.rgenop.kindToken(lltype.Bool), gv_res)
+
 # ____________________________________________________________
 # other jitstate/graph level operations
 
@@ -185,6 +219,7 @@
     outgoingvarboxes = []
     res = frozen.exactmatch(jitstate, outgoingvarboxes, memo)
     assert res, "exactmatch() failed"
+    cleanup_partial_data(memo.partialdatamatch)
     newblock = enter_next_block(jitstate, outgoingvarboxes)
     states_dic[key] = frozen, newblock
     if global_resumer is not None and global_resumer is not return_marker:
@@ -217,6 +252,7 @@
     # We need a more general block.  Do it by generalizing all the
     # redboxes from outgoingvarboxes, by making them variables.
     # Then we make a new block based on this new state.
+    cleanup_partial_data(memo.partialdatamatch)
     replace_memo = rvalue.copy_memo()
     for box in outgoingvarboxes:
         box.forcevar(jitstate.curbuilder, replace_memo)
@@ -228,6 +264,14 @@
     return False       # continue
 retrieve_jitstate_for_merge._annspecialcase_ = "specialize:arglltype(2)"
 
+def cleanup_partial_data(partialdatamatch):
+    # remove entries from PartialDataStruct unless they matched
+    # their frozen equivalent
+    for box, keep in partialdatamatch.iteritems():
+        content = box.content
+        if isinstance(content, rcontainer.PartialDataStruct):
+            box.content = content.cleanup_partial_data(keep)
+
 def merge_generalized(jitstate):
     resuming = jitstate.resuming
     if resuming is None:
@@ -794,6 +838,17 @@
         self.exc_value_box = self.exc_value_box.replace(memo)
 
 
+    def residual_ll_exception(self, ll_evalue):
+        ll_etype  = ll_evalue.typeptr
+        etypebox  = rvalue.ll_fromvalue(self, ll_etype)
+        evaluebox = rvalue.ll_fromvalue(self, ll_evalue)
+        setexctypebox (self, etypebox )
+        setexcvaluebox(self, evaluebox)
+
+    def residual_exception(self, e):
+        self.residual_ll_exception(cast_instance_to_base_ptr(e))
+        
+
 def ensure_queue(jitstate, DispatchQueueClass):
     return DispatchQueueClass()
 ensure_queue._annspecialcase_ = 'specialize:arg(1)'

Modified: pypy/branch/mininal-c-backend/pypy/jit/timeshifter/rvalue.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/jit/timeshifter/rvalue.py	(original)
+++ pypy/branch/mininal-c-backend/pypy/jit/timeshifter/rvalue.py	Thu Nov 23 12:28:43 2006
@@ -14,7 +14,9 @@
     return Memo()
 
 def exactmatch_memo():
-    return Memo()
+    memo = Memo()
+    memo.partialdatamatch = {}
+    return memo
 
 def copy_memo():
     return Memo()
@@ -242,29 +244,35 @@
         try:
             return boxmemo[self]
         except KeyError:
+            content = self.content
             if not self.genvar:
-                assert self.content is not None
+                from pypy.jit.timeshifter import rcontainer
+                assert isinstance(content, rcontainer.VirtualContainer)
                 result = FrozenPtrVirtual(self.kind)
                 boxmemo[self] = result
-                result.fz_content = self.content.freeze(memo)
+                result.fz_content = content.freeze(memo)
+                return result
+            elif self.genvar.is_const:
+                result = FrozenPtrConst(self.kind, self.genvar)
+            elif content is None:
+                result = FrozenPtrVar(self.kind)
             else:
-                if self.is_constant():
-                    result = FrozenPtrConst(self.kind, self.genvar)
-                else:
-                    result = FrozenPtrVar(self.kind)
-                    # if self.content is not None, it's a PartialDataStruct
-                    # - for now, we always remove it while freezing so that
-                    #   we exactly match our frozen version
-                    # XXX unsure if it's the correct place to do that.
-                    # XXX maybe in exactmatch??
-                    self.content = None
+                # if self.content is not None, it's a PartialDataStruct
+                from pypy.jit.timeshifter import rcontainer
+                assert isinstance(content, rcontainer.PartialDataStruct)
+                result = FrozenPtrVarWithPartialData(self.kind)
                 boxmemo[self] = result
+                result.fz_partialcontent = content.partialfreeze(memo)
+                return result
+            boxmemo[self] = result
             return result
 
     def getgenvar(self, builder):
         if not self.genvar:
-            assert self.content
-            self.content.force_runtime_container(builder)
+            content = self.content
+            from pypy.jit.timeshifter import rcontainer
+            assert isinstance(content, rcontainer.VirtualContainer)
+            content.force_runtime_container(builder)
             assert self.genvar
         return self.genvar
 
@@ -288,28 +296,21 @@
     def __init__(self, kind):
         self.kind = kind
 
+    def is_constant_equal(self, box):
+        return False
 
-class FrozenIntConst(FrozenValue):
 
-    def __init__(self, kind, gv_const):
-        self.kind = kind
-        self.gv_const = gv_const
+class FrozenConst(FrozenValue):
 
     def exactmatch(self, box, outgoingvarboxes, memo):
-        if (box.is_constant() and
-            self.gv_const.revealconst(lltype.Signed) ==
-               box.genvar.revealconst(lltype.Signed)):
+        if self.is_constant_equal(box):
             return True
         else:
             outgoingvarboxes.append(box)
             return False
 
-    def unfreeze(self, incomingvarboxes, memo):
-        # XXX could return directly the original IntRedBox
-        return IntRedBox(self.kind, self.gv_const)
-
 
-class FrozenIntVar(FrozenValue):
+class FrozenVar(FrozenValue):
 
     def exactmatch(self, box, outgoingvarboxes, memo):
         memo = memo.boxes
@@ -323,6 +324,25 @@
             outgoingvarboxes.append(box)
             return False
 
+
+class FrozenIntConst(FrozenConst):
+
+    def __init__(self, kind, gv_const):
+        self.kind = kind
+        self.gv_const = gv_const
+
+    def is_constant_equal(self, box):
+        return (box.is_constant() and
+                self.gv_const.revealconst(lltype.Signed) ==
+                box.genvar.revealconst(lltype.Signed))
+
+    def unfreeze(self, incomingvarboxes, memo):
+        # XXX could return directly the original IntRedBox
+        return IntRedBox(self.kind, self.gv_const)
+
+
+class FrozenIntVar(FrozenVar):
+
     def unfreeze(self, incomingvarboxes, memo):
         memo = memo.boxes
         if self not in memo:
@@ -334,38 +354,22 @@
             return memo[self]
 
 
-class FrozenDoubleConst(FrozenValue):
+class FrozenDoubleConst(FrozenConst):
 
     def __init__(self, kind, gv_const):
         self.kind = kind
         self.gv_const = gv_const
 
-    def exactmatch(self, box, outgoingvarboxes, memo):
-        if (box.is_constant() and
-            self.gv_const.revealconst(lltype.Float) ==
-               box.genvar.revealconst(lltype.Float)):
-            return True
-        else:
-            outgoingvarboxes.append(box)
-            return False
+    def is_constant_equal(self, box):
+        return (box.is_constant() and
+                self.gv_const.revealconst(lltype.Float) ==
+                box.genvar.revealconst(lltype.Float))
 
     def unfreeze(self, incomingvarboxes, memo):
         return DoubleRedBox(self.kind, self.gv_const)
 
 
-class FrozenDoubleVar(FrozenValue):
-
-    def exactmatch(self, box, outgoingvarboxes, memo):
-        memo = memo.boxes
-        if self not in memo:
-            memo[self] = box
-            outgoingvarboxes.append(box)
-            return True
-        elif memo[self] is box:
-            return True
-        else:
-            outgoingvarboxes.append(box)
-            return False
+class FrozenDoubleVar(FrozenVar):
 
     def unfreeze(self, incomingvarboxes, memo):
         memo = memo.boxes
@@ -378,38 +382,32 @@
             return memo[self]
 
 
-class FrozenPtrConst(FrozenValue):
+class FrozenPtrConst(FrozenConst):
 
     def __init__(self, kind, gv_const):
         self.kind = kind
         self.gv_const = gv_const
 
+    def is_constant_equal(self, box):
+        return (box.is_constant() and
+                self.gv_const.revealconst(llmemory.Address) ==
+                box.genvar.revealconst(llmemory.Address))
+
     def exactmatch(self, box, outgoingvarboxes, memo):
-        if (box.is_constant() and
-            self.gv_const.revealconst(llmemory.Address) ==
-               box.genvar.revealconst(llmemory.Address)):
-            return True
-        else:
-            outgoingvarboxes.append(box)
-            return False
+        assert isinstance(box, PtrRedBox)
+        memo.partialdatamatch[box] = None     # could do better
+        return FrozenConst.exactmatch(self, box, outgoingvarboxes, memo)
 
     def unfreeze(self, incomingvarboxes, memo):
         return PtrRedBox(self.kind, self.gv_const)
 
 
-class FrozenPtrVar(FrozenValue):
+class FrozenPtrVar(FrozenVar):
 
     def exactmatch(self, box, outgoingvarboxes, memo):
-        memo = memo.boxes
-        if self not in memo:
-            memo[self] = box
-            outgoingvarboxes.append(box)
-            return True
-        elif memo[self] is box:
-            return True
-        else:
-            outgoingvarboxes.append(box)
-            return False
+        assert isinstance(box, PtrRedBox)
+        memo.partialdatamatch[box] = None
+        return FrozenVar.exactmatch(self, box, outgoingvarboxes, memo)
 
     def unfreeze(self, incomingvarboxes, memo):
         memo = memo.boxes
@@ -422,6 +420,19 @@
             return memo[self]
 
 
+class FrozenPtrVarWithPartialData(FrozenPtrVar):
+
+    def exactmatch(self, box, outgoingvarboxes, memo):
+        if self.fz_partialcontent is None:
+            return FrozenPtrVar.exactmatch(self, box, outgoingvarboxes, memo)
+        assert isinstance(box, PtrRedBox)
+        partialdatamatch = self.fz_partialcontent.match(box,
+                                                        memo.partialdatamatch)
+        # skip the parent's exactmatch()!
+        exact = FrozenVar.exactmatch(self, box, outgoingvarboxes, memo)
+        return exact and partialdatamatch
+
+
 class FrozenPtrVirtual(FrozenValue):
 
     def exactmatch(self, box, outgoingvarboxes, memo):

Modified: pypy/branch/mininal-c-backend/pypy/jit/timeshifter/test/test_portal.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/jit/timeshifter/test/test_portal.py	(original)
+++ pypy/branch/mininal-c-backend/pypy/jit/timeshifter/test/test_portal.py	Thu Nov 23 12:28:43 2006
@@ -3,6 +3,7 @@
 from