[pypy-svn] r68695 - in pypy/trunk/pypy: interpreter jit/backend/cli jit/backend/llgraph jit/metainterp jit/metainterp/test module/pypyjit module/pypyjit/test rlib

arigo at codespeak.net arigo at codespeak.net
Wed Oct 21 18:35:40 CEST 2009


Author: arigo
Date: Wed Oct 21 18:35:39 2009
New Revision: 68695

Added:
   pypy/trunk/pypy/jit/metainterp/test/test_warmstate.py
      - copied unchanged from r68692, pypy/branch/warmspot-jitinfo/pypy/jit/metainterp/test/test_warmstate.py
   pypy/trunk/pypy/jit/metainterp/warmstate.py
      - copied unchanged from r68692, pypy/branch/warmspot-jitinfo/pypy/jit/metainterp/warmstate.py
Modified:
   pypy/trunk/pypy/interpreter/pycode.py
   pypy/trunk/pypy/jit/backend/cli/runner.py
   pypy/trunk/pypy/jit/backend/llgraph/llimpl.py
   pypy/trunk/pypy/jit/backend/llgraph/runner.py
   pypy/trunk/pypy/jit/metainterp/compile.py
   pypy/trunk/pypy/jit/metainterp/pyjitpl.py
   pypy/trunk/pypy/jit/metainterp/support.py
   pypy/trunk/pypy/jit/metainterp/test/test_compile.py
   pypy/trunk/pypy/jit/metainterp/test/test_warmspot.py
   pypy/trunk/pypy/jit/metainterp/test/test_ztranslation.py
   pypy/trunk/pypy/jit/metainterp/virtualizable.py
   pypy/trunk/pypy/jit/metainterp/warmspot.py
   pypy/trunk/pypy/module/pypyjit/interp_jit.py
   pypy/trunk/pypy/module/pypyjit/test/test_jit_setup.py
   pypy/trunk/pypy/rlib/jit.py
Log:
Finish the merge of the 'warmspot-jitinfo' branch.

Clean up the WarmEnterState class, move it to its own file, test it, and
add support for a JitDriver hook to replace the approximate hashtable
logic.  Implement the corresponding hook for pypy-c-jit.


Modified: pypy/trunk/pypy/interpreter/pycode.py
==============================================================================
--- pypy/trunk/pypy/interpreter/pycode.py	(original)
+++ pypy/trunk/pypy/interpreter/pycode.py	Wed Oct 21 18:35:39 2009
@@ -84,6 +84,9 @@
         self.hidden_applevel = hidden_applevel
         self.magic = magic
         self._signature = cpython_code_signature(self)
+        self._initialize()
+
+    def _initialize(self):
         # Precompute what arguments need to be copied into cellvars
         self._args_as_cellvars = []
         
@@ -116,7 +119,7 @@
 
         self._compute_flatcall()
 
-        if space.config.objspace.std.withcelldict:
+        if self.space.config.objspace.std.withcelldict:
             from pypy.objspace.std.celldict import init_code
             init_code(self)
 

Modified: pypy/trunk/pypy/jit/backend/cli/runner.py
==============================================================================
--- pypy/trunk/pypy/jit/backend/cli/runner.py	(original)
+++ pypy/trunk/pypy/jit/backend/cli/runner.py	Wed Oct 21 18:35:39 2009
@@ -319,7 +319,7 @@
     def __init__(self, TYPE):
         DescrWithKey.__init__(self, TYPE)
         from pypy.jit.backend.llgraph.runner import boxresult
-        from pypy.jit.metainterp.warmspot import unwrap
+        from pypy.jit.metainterp.warmstate import unwrap
         ARRAY = ootype.Array(TYPE)
         def create():
             if isinstance(TYPE, ootype.OOType):
@@ -482,7 +482,7 @@
     def __init__(self, TYPE, fieldname):
         DescrWithKey.__init__(self, (TYPE, fieldname))
         from pypy.jit.backend.llgraph.runner import boxresult
-        from pypy.jit.metainterp.warmspot import unwrap
+        from pypy.jit.metainterp.warmstate import unwrap
         _, T = TYPE._lookup_field(fieldname)
         def getfield(objbox):
             obj = objbox.getref(TYPE)

Modified: pypy/trunk/pypy/jit/backend/llgraph/llimpl.py
==============================================================================
--- pypy/trunk/pypy/jit/backend/llgraph/llimpl.py	(original)
+++ pypy/trunk/pypy/jit/backend/llgraph/llimpl.py	Wed Oct 21 18:35:39 2009
@@ -807,7 +807,6 @@
     op_getarrayitem_gc_pure = op_getarrayitem_gc
 
     def op_setarrayitem_gc(self, typedescr, obj, index, objnewvalue):
-        from pypy.jit.metainterp.warmspot import unwrap
         array = ootype.cast_from_object(typedescr.ARRAY, obj)
         if ootype.typeOf(objnewvalue) == ootype.Object:
             newvalue = ootype.cast_from_object(typedescr.TYPE, objnewvalue)

Modified: pypy/trunk/pypy/jit/backend/llgraph/runner.py
==============================================================================
--- pypy/trunk/pypy/jit/backend/llgraph/runner.py	(original)
+++ pypy/trunk/pypy/jit/backend/llgraph/runner.py	Wed Oct 21 18:35:39 2009
@@ -9,7 +9,7 @@
 from pypy.rpython.llinterp import LLInterpreter
 from pypy.jit.metainterp import history
 from pypy.jit.metainterp.history import REF, INT, FLOAT
-from pypy.jit.metainterp.warmspot import unwrap
+from pypy.jit.metainterp.warmstate import unwrap
 from pypy.jit.metainterp.resoperation import ResOperation, rop
 from pypy.jit.backend import model
 from pypy.jit.backend.llgraph import llimpl, symbolic

Modified: pypy/trunk/pypy/jit/metainterp/compile.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/compile.py	(original)
+++ pypy/trunk/pypy/jit/metainterp/compile.py	Wed Oct 21 18:35:39 2009
@@ -262,8 +262,8 @@
             new_loop_token)
         # store the new loop in compiled_merge_points too
         glob = metainterp_sd.globaldata
-        greenargs = glob.unpack_greenkey(self.original_greenkey)
-        old_loop_tokens = glob.compiled_merge_points.setdefault(greenargs, [])
+        old_loop_tokens = glob.get_compiled_merge_points(
+            self.original_greenkey)
         # it always goes at the end of the list, as it is the most
         # general loop token
         old_loop_tokens.append(new_loop_token)

Modified: pypy/trunk/pypy/jit/metainterp/pyjitpl.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/pyjitpl.py	(original)
+++ pypy/trunk/pypy/jit/metainterp/pyjitpl.py	Wed Oct 21 18:35:39 2009
@@ -1,7 +1,7 @@
 import py, os
 from pypy.rpython.lltypesystem import llmemory
 from pypy.rpython.ootypesystem import ootype
-from pypy.rlib.objectmodel import we_are_translated, r_dict
+from pypy.rlib.objectmodel import we_are_translated
 from pypy.rlib.unroll import unrolling_iterable
 from pypy.rlib.debug import debug_print
 
@@ -1099,15 +1099,25 @@
         #
         state = staticdata.state
         if state is not None:
-            self.unpack_greenkey = state.unwrap_greenkey
-            self.compiled_merge_points = r_dict(state.comparekey,state.hashkey)
-                # { (greenargs): [MergePoints] }
+            self.jit_cell_at_key = state.jit_cell_at_key
         else:
-            self.compiled_merge_points = {}    # for tests only; not RPython
-            self.unpack_greenkey = tuple
+            # for tests only; not RPython
+            class JitCell:
+                compiled_merge_points = None
+            _jitcell_dict = {}
+            def jit_cell_at_key(greenkey):
+                greenkey = tuple(greenkey)
+                return _jitcell_dict.setdefault(greenkey, JitCell())
+            self.jit_cell_at_key = jit_cell_at_key
         if staticdata.virtualizable_info:
             self.blackhole_virtualizable = staticdata.virtualizable_info.null_vable
 
+    def get_compiled_merge_points(self, greenkey):
+        cell = self.jit_cell_at_key(greenkey)
+        if cell.compiled_merge_points is None:
+            cell.compiled_merge_points = []
+        return cell.compiled_merge_points
+
     def get_fail_descr_number(self, descr):
         assert isinstance(descr, history.AbstractFailDescr)
         lst = self.fail_descr_list
@@ -1496,8 +1506,7 @@
         self.history.inputargs = original_boxes[num_green_args:]
         greenkey = original_boxes[:num_green_args]
         glob = self.staticdata.globaldata
-        greenargs = glob.unpack_greenkey(greenkey)
-        old_loop_tokens = glob.compiled_merge_points.setdefault(greenargs, [])
+        old_loop_tokens = glob.get_compiled_merge_points(greenkey)
         self.history.record(rop.JUMP, live_arg_boxes[num_green_args:], None)
         loop_token = compile.compile_new_loop(self, old_loop_tokens,
                                               greenkey, start)
@@ -1508,10 +1517,8 @@
         num_green_args = self.staticdata.num_green_args
         greenkey = live_arg_boxes[:num_green_args]
         glob = self.staticdata.globaldata
-        greenargs = glob.unpack_greenkey(greenkey)
-        try:
-            old_loop_tokens = glob.compiled_merge_points[greenargs]
-        except KeyError:
+        old_loop_tokens = glob.get_compiled_merge_points(greenkey)
+        if len(old_loop_tokens) == 0:
             return
         self.history.record(rop.JUMP, live_arg_boxes[num_green_args:], None)
         target_loop_token = compile.compile_new_bridge(self, old_loop_tokens,
@@ -1565,7 +1572,7 @@
 
     def _initialize_from_start(self, original_boxes, num_green_args, *args):
         if args:
-            from pypy.jit.metainterp.warmspot import wrap
+            from pypy.jit.metainterp.warmstate import wrap
             box = wrap(self.cpu, args[0], num_green_args > 0)
             original_boxes.append(box)
             self._initialize_from_start(original_boxes, num_green_args-1,

Modified: pypy/trunk/pypy/jit/metainterp/support.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/support.py	(original)
+++ pypy/trunk/pypy/jit/metainterp/support.py	Wed Oct 21 18:35:39 2009
@@ -74,16 +74,15 @@
 def maybe_on_top_of_llinterp(rtyper, fnptr):
     # Run a generated graph on top of the llinterp for testing.
     # When translated, this just returns the fnptr.
-    llinterp = LLInterpreter(rtyper)  #, exc_data_ptr=exc_data_ptr)
     funcobj = get_funcobj(fnptr)
     if hasattr(funcobj, 'graph'):
+        llinterp = LLInterpreter(rtyper)  #, exc_data_ptr=exc_data_ptr)
         def on_top_of_llinterp(*args):
             return llinterp.eval_graph(funcobj.graph, list(args))
     else:
-        assert isinstance(fnptr, ootype._meth)
-        assert hasattr(fnptr, '_callable')
+        assert hasattr(funcobj, '_callable')
         def on_top_of_llinterp(*args):
-            return fnptr._callable(*args)
+            return funcobj._callable(*args)
     return on_top_of_llinterp
 
 class Entry(ExtRegistryEntry):

Modified: pypy/trunk/pypy/jit/metainterp/test/test_compile.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/test/test_compile.py	(original)
+++ pypy/trunk/pypy/jit/metainterp/test/test_compile.py	Wed Oct 21 18:35:39 2009
@@ -41,7 +41,7 @@
     optimize_loop = staticmethod(optimize.optimize_loop)
     debug_level = 0
 
-class FakeGlobalData():
+class FakeGlobalData:
     loopnumbering = 0
 
 class FakeMetaInterpStaticData:

Modified: pypy/trunk/pypy/jit/metainterp/test/test_warmspot.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/test/test_warmspot.py	(original)
+++ pypy/trunk/pypy/jit/metainterp/test/test_warmspot.py	Wed Oct 21 18:35:39 2009
@@ -1,39 +1,13 @@
 import py
-from pypy.jit.metainterp.warmspot import ll_meta_interp, hash_whatever
-from pypy.jit.metainterp.warmspot import get_stats, equal_whatever
+from pypy.jit.metainterp.warmspot import ll_meta_interp
+from pypy.jit.metainterp.warmspot import get_stats
 from pypy.rlib.jit import JitDriver, OPTIMIZER_FULL, OPTIMIZER_SIMPLE
 from pypy.rlib.jit import unroll_safe
 from pypy.jit.backend.llgraph import runner
-from pypy.rpython.test.test_llinterp import interpret
 
 from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin
 
 
-def test_hash_equal_whatever_lltype():
-    from pypy.rpython.lltypesystem import lltype, rstr
-    s1 = rstr.mallocstr(2)
-    s2 = rstr.mallocstr(2)
-    s1.chars[0] = 'x'; s1.chars[1] = 'y'
-    s2.chars[0] = 'x'; s2.chars[1] = 'y'
-    def fn(x):
-        assert hash_whatever(lltype.typeOf(x), x) == 42
-        assert (hash_whatever(lltype.typeOf(s1), s1) ==
-                hash_whatever(lltype.typeOf(s2), s2))
-        assert equal_whatever(lltype.typeOf(s1), s1, s2)
-    fn(42)
-    interpret(fn, [42], type_system='lltype')
-
-def test_hash_equal_whatever_ootype():
-    from pypy.rpython.ootypesystem import ootype
-    def fn(c):
-        s1 = ootype.oostring("xy", -1)
-        s2 = ootype.oostring("x" + chr(c), -1)
-        assert (hash_whatever(ootype.typeOf(s1), s1) ==
-                hash_whatever(ootype.typeOf(s2), s2))
-        assert equal_whatever(ootype.typeOf(s1), s1, s2)
-    fn(ord('y'))
-    interpret(fn, [ord('y')], type_system='ootype')
-
 class Exit(Exception):
     def __init__(self, result):
         self.result = result
@@ -90,20 +64,6 @@
         res = self.meta_interp(f, [60])
         assert res == f(30)
 
-    def test_hash_collision(self):
-        mydriver = JitDriver(reds = ['n'], greens = ['m'])
-        def f(n):
-            m = 0
-            while n > 0:
-                mydriver.can_enter_jit(n=n, m=m)
-                mydriver.jit_merge_point(n=n, m=m)
-                n -= 1
-                if not (n % 11):
-                    m = (m+n) & 3
-            return m
-        res = self.meta_interp(f, [110], hash_bits=1)
-        assert res == f(110)
-
     def test_location(self):
         def get_printable_location(n):
             return 'GREEN IS %d.' % n

Modified: pypy/trunk/pypy/jit/metainterp/test/test_ztranslation.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/test/test_ztranslation.py	(original)
+++ pypy/trunk/pypy/jit/metainterp/test/test_ztranslation.py	Wed Oct 21 18:35:39 2009
@@ -4,6 +4,8 @@
 from pypy.rlib.jit import JitDriver, OPTIMIZER_FULL, unroll_parameters
 from pypy.rlib.jit import PARAMETERS, dont_look_inside
 from pypy.jit.metainterp.jitprof import Profiler
+from pypy.rpython.lltypesystem import lltype, llmemory
+from pypy.rpython.ootypesystem import ootype
 
 class TranslationTest:
 
@@ -18,6 +20,7 @@
         # - set_param interface
         # - profiler
         # - full optimizer
+        # - jitdriver hooks
 
         class Frame(object):
             _virtualizable2_ = ['i']
@@ -25,8 +28,24 @@
             def __init__(self, i):
                 self.i = i
 
+        class JitCellCache:
+            entry = None
+        jitcellcache = JitCellCache()
+        def set_jitcell_at(entry):
+            jitcellcache.entry = entry
+        def get_jitcell_at():
+            return jitcellcache.entry
+        def get_printable_location():
+            return '(hello world)'
+        def can_inline():
+            return False
+
         jitdriver = JitDriver(greens = [], reds = ['frame', 'total'],
-                              virtualizables = ['frame'])
+                              virtualizables = ['frame'],
+                              get_jitcell_at=get_jitcell_at,
+                              set_jitcell_at=set_jitcell_at,
+                              get_printable_location=get_printable_location,
+                              can_inline=can_inline)
         def f(i):
             for param in unroll_parameters:
                 defl = PARAMETERS[param]

Modified: pypy/trunk/pypy/jit/metainterp/virtualizable.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/virtualizable.py	(original)
+++ pypy/trunk/pypy/jit/metainterp/virtualizable.py	Wed Oct 21 18:35:39 2009
@@ -6,7 +6,7 @@
 from pypy.rlib.unroll import unrolling_iterable
 from pypy.jit.metainterp.typesystem import deref, fieldType, arrayItem
 from pypy.jit.metainterp import history
-from pypy.jit.metainterp.warmspot import wrap, unwrap
+from pypy.jit.metainterp.warmstate import wrap, unwrap
 
 
 class VirtualizableInfo:

Modified: pypy/trunk/pypy/jit/metainterp/warmspot.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/warmspot.py	(original)
+++ pypy/trunk/pypy/jit/metainterp/warmspot.py	Wed Oct 21 18:35:39 2009
@@ -10,7 +10,6 @@
 from pypy.objspace.flow.model import checkgraph, Link, copygraph
 from pypy.rlib.objectmodel import we_are_translated
 from pypy.rlib.unroll import unrolling_iterable
-from pypy.rlib.jit import PARAMETERS, OPTIMIZER_SIMPLE, OPTIMIZER_FULL
 from pypy.rlib.rarithmetic import r_uint, intmask
 from pypy.rlib.debug import debug_print
 from pypy.rpython.lltypesystem.lloperation import llop
@@ -24,7 +23,6 @@
 from pypy.jit.metainterp.typesystem import LLTypeHelper, OOTypeHelper
 from pypy.jit.metainterp.jitprof import Profiler, EmptyProfiler
 from pypy.rlib.jit import DEBUG_STEPS, DEBUG_DETAILED, DEBUG_OFF, DEBUG_PROFILE
-from pypy.rlib.nonconst import NonConstant
 
 # ____________________________________________________________
 # Bootstrapping
@@ -63,7 +61,7 @@
     clear_tcache()
     return jittify_and_run(interp, graph, args, backendopt=backendopt, **kwds)
 
-def jittify_and_run(interp, graph, args, repeat=1, hash_bits=None,
+def jittify_and_run(interp, graph, args, repeat=1,
                     backendopt=False, trace_limit=sys.maxint,
                     debug_level=DEBUG_STEPS, inline=False, **kwds):
     translator = interp.typer.annotator.translator
@@ -74,9 +72,6 @@
     warmrunnerdesc.state.set_param_trace_limit(trace_limit)
     warmrunnerdesc.state.set_param_inlining(inline)
     warmrunnerdesc.state.set_param_debug(debug_level)
-    warmrunnerdesc.state.create_tables_now()             # for tests
-    if hash_bits:
-        warmrunnerdesc.state.set_param_hash_bits(hash_bits)
     warmrunnerdesc.finish()
     res = interp.eval_graph(graph, args)
     if not kwds.get('translate_support_code', False):
@@ -167,7 +162,7 @@
         self.build_meta_interp(CPUClass, **kwds)
         self.make_args_specification()
         self.rewrite_jit_merge_point(policy)
-        self.make_driverhook_graph()
+        self.make_driverhook_graphs()
         if self.jitdriver.virtualizables:
             from pypy.jit.metainterp.virtualizable import VirtualizableInfo
             self.metainterp_sd.virtualizable_info = VirtualizableInfo(self)
@@ -269,8 +264,9 @@
                                                   warmrunnerdesc=self)
         
     def make_enter_function(self):
-        WarmEnterState = make_state_class(self)
-        state = WarmEnterState()
+        from pypy.jit.metainterp.warmstate import WarmEnterState
+        state = WarmEnterState(self)
+        maybe_compile_and_run = state.make_entry_point()
         self.state = state
 
         def crash_in_jit(e):
@@ -288,7 +284,7 @@
         if self.translator.rtyper.type_system.name == 'lltypesystem':
             def maybe_enter_jit(*args):
                 try:
-                    state.maybe_compile_and_run(*args)
+                    maybe_compile_and_run(*args)
                 except JitException:
                     raise     # go through
                 except Exception, e:
@@ -296,7 +292,7 @@
             maybe_enter_jit._always_inline_ = True
         else:
             def maybe_enter_jit(*args):
-                state.maybe_compile_and_run(*args)
+                maybe_compile_and_run(*args)
             maybe_enter_jit._always_inline_ = True
 
         self.maybe_enter_jit_fn = maybe_enter_jit
@@ -312,24 +308,38 @@
                                                   args_s, s_result)
             annhelper.finish()
         
-    def make_driverhook_graph(self):
+    def make_driverhook_graphs(self):
+        from pypy.rlib.jit import BaseJitCell
+        bk = self.rtyper.annotator.bookkeeper
+        classdef = bk.getuniqueclassdef(BaseJitCell)
+        s_BaseJitCell_or_None = annmodel.SomeInstance(classdef,
+                                                      can_be_None=True)
+        s_BaseJitCell_not_None = annmodel.SomeInstance(classdef)
+        s_Str = annmodel.SomeString()
+        #
+        annhelper = MixLevelHelperAnnotator(self.translator.rtyper)
+        self.set_jitcell_at_ptr = self._make_hook_graph(
+            annhelper, self.jitdriver.set_jitcell_at, annmodel.s_None,
+            s_BaseJitCell_not_None)
+        self.get_jitcell_at_ptr = self._make_hook_graph(
+            annhelper, self.jitdriver.get_jitcell_at, s_BaseJitCell_or_None)
         self.can_inline_ptr = self._make_hook_graph(
-            self.jitdriver.can_inline, bool)
+            annhelper, self.jitdriver.can_inline, annmodel.s_Bool)
         self.get_printable_location_ptr = self._make_hook_graph(
-            self.jitdriver.get_printable_location, str)
+            annhelper, self.jitdriver.get_printable_location, s_Str)
+        annhelper.finish()
 
-    def _make_hook_graph(self, func, rettype):
-        from pypy.annotation.signature import annotationoftype
+    def _make_hook_graph(self, annhelper, func, s_result, s_first_arg=None):
         if func is None:
             return None
-        annhelper = MixLevelHelperAnnotator(self.translator.rtyper)
-        s_result = annotationoftype(rettype)
-        RETTYPE = annhelper.rtyper.getrepr(s_result).lowleveltype
-        FUNC, PTR = self.cpu.ts.get_FuncType(self.green_args_spec, RETTYPE)
+        #
+        extra_args_s = []
+        if s_first_arg is not None:
+            extra_args_s.append(s_first_arg)
+        #
         args_s = self.portal_args_s[:len(self.green_args_spec)]
-        graph = annhelper.getgraph(func, args_s, s_result)
-        funcptr = annhelper.graph2delayed(graph, FUNC)
-        annhelper.finish()
+        graph = annhelper.getgraph(func, extra_args_s + args_s, s_result)
+        funcptr = annhelper.graph2delayed(graph)
         return funcptr
 
     def make_args_specification(self):
@@ -346,6 +356,7 @@
                 self.green_args_spec.append(TYPE)
             else:
                 self.red_args_types.append(history.getkind(TYPE))
+        self.num_green_args = len(self.green_args_spec)
         RESTYPE = graph.getreturnvar().concretetype
         (self.JIT_ENTER_FUNCTYPE,
          self.PTR_JIT_ENTER_FUNCTYPE) = self.cpu.ts.get_FuncType(ALLARGS, lltype.Void)
@@ -465,6 +476,7 @@
                 # accepts boxes as argument, but unpacks them immediately
                 # before we raise the exception -- the boxes' values will
                 # be modified in a 'finally' by restore_patched_boxes().
+                from pypy.jit.metainterp.warmstate import unwrap
                 for i, name, ARG in portalfunc_ARGS:
                     v = unwrap(ARG, argboxes[i])
                     setattr(self, name, v)
@@ -585,392 +597,3 @@
     assert len(reds_v) == numreds
     return ([v for v in greens_v if v.concretetype is not lltype.Void],
             [v for v in reds_v if v.concretetype is not lltype.Void])
-
-def unwrap(TYPE, box):
-    if TYPE is lltype.Void:
-        return None
-    if isinstance(TYPE, lltype.Ptr):
-        return box.getref(TYPE)
-    if isinstance(TYPE, ootype.OOType):
-        return box.getref(TYPE)
-    if TYPE == lltype.Float:
-        return box.getfloat()
-    else:
-        return lltype.cast_primitive(TYPE, box.getint())
-unwrap._annspecialcase_ = 'specialize:arg(0)'
-
-def wrap(cpu, value, in_const_box=False):
-    if isinstance(lltype.typeOf(value), lltype.Ptr):
-        if lltype.typeOf(value).TO._gckind == 'gc':
-            value = lltype.cast_opaque_ptr(llmemory.GCREF, value)
-            if in_const_box:
-                return history.ConstPtr(value)
-            else:
-                return history.BoxPtr(value)
-        else:
-            adr = llmemory.cast_ptr_to_adr(value)
-            value = cpu.cast_adr_to_int(adr)
-            # fall through to the end of the function
-    elif isinstance(lltype.typeOf(value), ootype.OOType):
-        value = ootype.cast_to_object(value)
-        if in_const_box:
-            return history.ConstObj(value)
-        else:
-            return history.BoxObj(value)
-    elif isinstance(value, float):
-        if in_const_box:
-            return history.ConstFloat(value)
-        else:
-            return history.BoxFloat(value)
-    else:
-        value = intmask(value)
-    if in_const_box:
-        return history.ConstInt(value)
-    else:
-        return history.BoxInt(value)
-wrap._annspecialcase_ = 'specialize:ll'
-
-def equal_whatever(TYPE, x, y):
-    if isinstance(TYPE, lltype.Ptr):
-        if TYPE.TO is rstr.STR or TYPE.TO is rstr.UNICODE:
-            return rstr.LLHelpers.ll_streq(x, y)
-    if TYPE is ootype.String or TYPE is ootype.Unicode:
-        return x.ll_streq(y)
-    return x == y
-equal_whatever._annspecialcase_ = 'specialize:arg(0)'
-
-def hash_whatever(TYPE, x):
-    # Hash of lltype or ootype object.
-    # Only supports strings, unicodes and regular instances,
-    # as well as primitives that can meaningfully be cast to Signed.
-    if isinstance(TYPE, lltype.Ptr):
-        if TYPE.TO is rstr.STR or TYPE.TO is rstr.UNICODE:
-            return rstr.LLHelpers.ll_strhash(x)    # assumed not null
-        else:
-            if x:
-                return lltype.identityhash(x)
-            else:
-                return 0
-    elif TYPE is ootype.String or TYPE is ootype.Unicode:
-        return x.ll_hash()
-    elif isinstance(TYPE, ootype.OOType):
-        if x:
-            return ootype.identityhash(x)
-        else:
-            return 0
-    else:
-        return lltype.cast_primitive(lltype.Signed, x)
-hash_whatever._annspecialcase_ = 'specialize:arg(0)'
-
-# ____________________________________________________________
-
-def make_state_class(warmrunnerdesc):
-    jitdriver = warmrunnerdesc.jitdriver
-    num_green_args = len(jitdriver.greens)
-    warmrunnerdesc.num_green_args = num_green_args
-    green_args_spec = unrolling_iterable(warmrunnerdesc.green_args_spec)
-    green_args_names = unrolling_iterable(jitdriver.greens)
-    green_args_spec_names = unrolling_iterable(zip(
-        warmrunnerdesc.green_args_spec, jitdriver.greens))
-    red_args_types = unrolling_iterable(warmrunnerdesc.red_args_types)
-    #
-    metainterp_sd = warmrunnerdesc.metainterp_sd
-    vinfo = metainterp_sd.virtualizable_info
-    if vinfo is None:
-        vable_static_fields = []
-        vable_array_fields = []
-    else:
-        vable_static_fields = unrolling_iterable(
-            zip(vinfo.static_extra_types, vinfo.static_fields))
-        vable_array_fields = unrolling_iterable(
-            zip(vinfo.arrayitem_extra_types, vinfo.array_fields))
-    #
-    if num_green_args:
-        MAX_HASH_TABLE_BITS = 28
-    else:
-        MAX_HASH_TABLE_BITS = 1
-    THRESHOLD_LIMIT = sys.maxint // 2
-    #
-    getlength = warmrunnerdesc.cpu.ts.getlength
-    getarrayitem = warmrunnerdesc.cpu.ts.getarrayitem
-    setarrayitem = warmrunnerdesc.cpu.ts.setarrayitem
-    #
-    rtyper = warmrunnerdesc.translator.rtyper
-    can_inline_ptr = warmrunnerdesc.can_inline_ptr
-    get_printable_location_ptr = warmrunnerdesc.get_printable_location_ptr
-    #
-    class MachineCodeEntryPoint(object):
-        next = None    # linked list
-        def __init__(self, entry_loop_token, *greenargs):
-            self.entry_loop_token = entry_loop_token
-            i = 0
-            for name in green_args_names:
-                setattr(self, 'green_' + name, greenargs[i])
-                i = i + 1
-        def equalkey(self, *greenargs):
-            i = 0
-            for TYPE, name in green_args_spec_names:
-                myvalue = getattr(self, 'green_' + name)
-                if not equal_whatever(TYPE, myvalue, greenargs[i]):
-                    return False
-                i = i + 1
-            return True
-        def set_future_values(self, *redargs):
-            i = 0
-            for typecode in red_args_types:
-                set_future_value(i, redargs[i], typecode)
-                i = i + 1
-            if vinfo is not None:
-                virtualizable = redargs[vinfo.index_of_virtualizable -
-                                        num_green_args]
-                virtualizable = vinfo.cast_to_vtype(virtualizable)
-                for typecode, fieldname in vable_static_fields:
-                    x = getattr(virtualizable, fieldname)
-                    set_future_value(i, x, typecode)
-                    i = i + 1
-                for typecode, fieldname in vable_array_fields:
-                    lst = getattr(virtualizable, fieldname)
-                    for j in range(getlength(lst)):
-                        x = getarrayitem(lst, j)
-                        set_future_value(i, x, typecode)
-                        i = i + 1
-
-    def set_future_value(j, value, typecode):
-        cpu = metainterp_sd.cpu
-        if typecode == 'ref':
-            refvalue = cpu.ts.cast_to_ref(value)
-            cpu.set_future_value_ref(j, refvalue)
-        elif typecode == 'int':
-            intvalue = lltype.cast_primitive(lltype.Signed, value)
-            cpu.set_future_value_int(j, intvalue)
-        elif typecode == 'float':
-            assert isinstance(value, float)
-            cpu.set_future_value_float(j, value)
-        else:
-            assert False
-    set_future_value._annspecialcase_ = 'specialize:ll_and_arg(2)'
-
-    class WarmEnterState:
-        def __init__(self):
-            # initialize the state with the default values of the
-            # parameters specified in rlib/jit.py
-            for name, default_value in PARAMETERS.items():
-                meth = getattr(self, 'set_param_' + name)
-                meth(default_value)
-
-        def set_param_threshold(self, threshold):
-            if threshold < 2:
-                threshold = 2
-            self.increment_threshold = (THRESHOLD_LIMIT // threshold) + 1
-            # the number is at least 1, and at most about half THRESHOLD_LIMIT
-
-        def set_param_trace_eagerness(self, value):
-            self.trace_eagerness = value
-
-        def set_param_trace_limit(self, value):
-            self.trace_limit = value
-
-        def set_param_inlining(self, value):
-            self.inlining = value
-
-        def set_param_hash_bits(self, value):
-            if value < 1:
-                value = 1
-            elif value > MAX_HASH_TABLE_BITS:
-                value = MAX_HASH_TABLE_BITS
-            # the tables are initialized with the correct size only in
-            # create_tables_now()
-            self.hashbits = value
-            self.hashtablemask = 0
-            self.mccounters = [0]
-            self.mcentrypoints = [None]
-            # invariant: (self.mccounters[j] < 0) if and only if
-            #            (self.mcentrypoints[j] is not None)
-
-        def set_param_optimizer(self, optimizer):
-            if optimizer == OPTIMIZER_SIMPLE:
-                from pypy.jit.metainterp import simple_optimize
-                self.optimize_loop = simple_optimize.optimize_loop
-                self.optimize_bridge = simple_optimize.optimize_bridge
-            elif optimizer == OPTIMIZER_FULL:
-                from pypy.jit.metainterp import optimize
-                self.optimize_loop = optimize.optimize_loop
-                self.optimize_bridge = optimize.optimize_bridge
-            else:
-                raise ValueError("unknown optimizer")
-
-        def set_param_debug(self, value):
-            self.debug_level = value
-            metainterp_sd.profiler.set_printing(value >= DEBUG_PROFILE)
-
-        def create_tables_now(self):
-            count = 1 << self.hashbits
-            self.hashtablemask = count - 1
-            self.mccounters = [0] * count
-            self.mcentrypoints = [None] * count
-
-        # Only use the hash of the arguments as the profiling key.
-        # Indeed, this is all a heuristic, so if things are designed
-        # correctly, the occasional mistake due to hash collision is
-        # not too bad.
-
-        def maybe_compile_and_run(self, *args):
-            globaldata = metainterp_sd.globaldata
-            if NonConstant(False):
-                # make sure we always see the saner optimizer from an annotation
-                # point of view, otherwise we get lots of blocked ops
-                self.set_param_optimizer(OPTIMIZER_FULL)
-                
-            # get the greenargs and look for the cell corresponding to the hash
-            greenargs = args[:num_green_args]
-            argshash = self.getkeyhash(*greenargs) & self.hashtablemask
-            counter = self.mccounters[argshash]
-            if vinfo:
-                virtualizable = args[vinfo.index_of_virtualizable]
-                virtualizable = vinfo.cast_to_vtype(virtualizable)
-                assert virtualizable != globaldata.blackhole_virtualizable, "reentering same frame via blackhole"
-            if counter >= 0:
-                # update the profiling counter
-                n = counter + self.increment_threshold
-                if n <= THRESHOLD_LIMIT:       # bound not reached
-                    self.mccounters[argshash] = n
-                    return
-                if self.hashtablemask == 0: # must really create the tables now
-                    self.create_tables_now()
-                    return
-                metainterp = MetaInterp(metainterp_sd)
-                try:
-                    loop_token = metainterp.compile_and_run_once(*args)
-                except warmrunnerdesc.ContinueRunningNormally:
-                    # the trace got too long, reset the counter
-                    self.mccounters[argshash] = 0
-                    raise
-
-            else:
-                # machine code was already compiled for these greenargs
-                # (or we have a hash collision)
-                cell = self.mcentrypoints[argshash]
-                if not cell.equalkey(*greenargs):
-                    # hash collision
-                    loop_token = self.handle_hash_collision(cell, argshash,
-                                                            *args)
-                    if loop_token is None:
-                        return
-                else:
-                    # get the assembler and fill in the boxes
-                    cell.set_future_values(*args[num_green_args:])
-                    loop_token = cell.entry_loop_token
-            # ---------- execute assembler ----------
-            while True:     # until interrupted by an exception
-                metainterp_sd.profiler.start_running()
-                fail_index = metainterp_sd.cpu.execute_token(loop_token)
-                metainterp_sd.profiler.end_running()
-                fail_descr = globaldata.get_fail_descr_from_number(fail_index)
-                loop_token = fail_descr.handle_fail(metainterp_sd)
-
-        maybe_compile_and_run._dont_inline_ = True
-
-        def handle_hash_collision(self, firstcell, argshash, *args):
-            greenargs = args[:num_green_args]
-            # search the linked list for the correct cell
-            cell = firstcell
-            while cell.next is not None:
-                nextcell = cell.next
-                if nextcell.equalkey(*greenargs):
-                    # found, move to the front of the linked list
-                    cell.next = nextcell.next
-                    nextcell.next = firstcell
-                    self.mcentrypoints[argshash] = nextcell
-                    nextcell.set_future_values(*args[num_green_args:])
-                    return nextcell.entry_loop_token
-                cell = nextcell
-            # not found at all, do profiling
-            counter = self.mccounters[argshash]
-            assert counter < 0          # by invariant
-            n = counter + self.increment_threshold
-            if n < 0:      # bound not reached
-                self.mccounters[argshash] = n
-                return None
-            metainterp = MetaInterp(metainterp_sd)
-            # XXX ContinueRunningNormally => "reset" counters
-            return metainterp.compile_and_run_once(*args)
-        handle_hash_collision._dont_inline_ = True
-
-        def unwrap_greenkey(self, greenkey):
-            greenargs = ()
-            i = 0
-            for TYPE in green_args_spec:
-                value = unwrap(TYPE, greenkey[i])
-                greenargs += (value,)
-                i = i + 1
-            return greenargs
-        unwrap_greenkey._always_inline_ = True
-
-        def comparekey(greenargs1, greenargs2):
-            i = 0
-            for TYPE in green_args_spec:
-                if not equal_whatever(TYPE, greenargs1[i], greenargs2[i]):
-                    return False
-                i = i + 1
-            return True
-        comparekey = staticmethod(comparekey)
-
-        def hashkey(greenargs):
-            return intmask(WarmEnterState.getkeyhash(*greenargs))
-        hashkey = staticmethod(hashkey)
-
-        def getkeyhash(*greenargs):
-            result = r_uint(0x345678)
-            i = 0
-            mult = r_uint(1000003)
-            for TYPE in green_args_spec:
-                if i > 0:
-                    result = result * mult
-                    mult = mult + 82520 + 2*len(greenargs)
-                item = greenargs[i]
-                result = result ^ hash_whatever(TYPE, item)
-                i = i + 1
-            return result         # returns a r_uint
-        getkeyhash._always_inline_ = True
-        getkeyhash = staticmethod(getkeyhash)
-
-        def must_compile_from_failure(self, key):
-            key.counter += 1
-            return key.counter >= self.trace_eagerness
-
-        def reset_counter_from_failure(self, key):
-            key.counter = 0
-
-        def attach_unoptimized_bridge_from_interp(self, greenkey,
-                                                  entry_loop_token):
-            greenargs = self.unwrap_greenkey(greenkey)
-            newcell = MachineCodeEntryPoint(entry_loop_token, *greenargs)
-            argshash = self.getkeyhash(*greenargs) & self.hashtablemask
-            oldcell = self.mcentrypoints[argshash]
-            newcell.next = oldcell     # link
-            self.mcentrypoints[argshash] = newcell
-            self.mccounters[argshash] = -THRESHOLD_LIMIT-1
-
-        if can_inline_ptr is None:
-            def can_inline_callable(self, greenkey):
-                return True
-        else:
-            def can_inline_callable(self, greenkey):
-                args = self.unwrap_greenkey(greenkey)
-                fn = support.maybe_on_top_of_llinterp(rtyper, can_inline_ptr)
-                return fn(*args)
-
-        if get_printable_location_ptr is None:
-            def get_location_str(self, greenkey):
-                return '(no jitdriver.get_printable_location!)'
-        else:
-            def get_location_str(self, greenkey):
-                args = self.unwrap_greenkey(greenkey)
-                fn = support.maybe_on_top_of_llinterp(rtyper,
-                                                  get_printable_location_ptr)
-                res = fn(*args)
-                if not we_are_translated() and not isinstance(res, str):
-                    res = hlstr(res)
-                return res
-
-    return WarmEnterState

Modified: pypy/trunk/pypy/module/pypyjit/interp_jit.py
==============================================================================
--- pypy/trunk/pypy/module/pypyjit/interp_jit.py	(original)
+++ pypy/trunk/pypy/module/pypyjit/interp_jit.py	Wed Oct 21 18:35:39 2009
@@ -50,9 +50,16 @@
 def leave(next_instr, pycode, frame, ec):
     from pypy.interpreter.executioncontext import ExecutionContext
     # can't use a method here, since this function is seen later than the main
-    # annotation
+    # annotation       XXX no longer true, could be fixed
     ExecutionContext._jit_rechain_frame(ec, frame)
 
+def get_jitcell_at(next_instr, bytecode):
+    return bytecode.jit_cells.get(next_instr, None)
+
+def set_jitcell_at(newcell, next_instr, bytecode):
+    bytecode.jit_cells[next_instr] = newcell
+
+
 class PyPyJitDriver(JitDriver):
     reds = ['frame', 'ec']
     greens = ['next_instr', 'pycode']
@@ -68,7 +75,9 @@
 
 pypyjitdriver = PyPyJitDriver(can_inline = can_inline,
                               get_printable_location = get_printable_location,
-                              leave = leave)
+                              leave = leave,
+                              get_jitcell_at = get_jitcell_at,
+                              set_jitcell_at = set_jitcell_at)
 
 class __extend__(PyFrame):
 
@@ -94,6 +103,20 @@
                                     pycode=f.getcode())
         return jumpto
 
+
+PyCode__initialize = PyCode._initialize
+
+class __extend__(PyCode):
+    __metaclass__ = extendabletype
+
+    def _initialize(self):
+        PyCode__initialize(self)
+        self.jit_cells = {}
+
+    def _freeze_(self):
+        self.jit_cells = {}
+        return False
+
 # ____________________________________________________________
 #
 # Public interface    

Modified: pypy/trunk/pypy/module/pypyjit/test/test_jit_setup.py
==============================================================================
--- pypy/trunk/pypy/module/pypyjit/test/test_jit_setup.py	(original)
+++ pypy/trunk/pypy/module/pypyjit/test/test_jit_setup.py	Wed Oct 21 18:35:39 2009
@@ -9,8 +9,8 @@
         # this just checks that the module is setting up things correctly, and
         # the resulting code makes sense on top of CPython.
         import pypyjit
-        pypyjit.set_param(threshold=5, hash_bits=9)
-        pypyjit.set_param("trace_eagerness=3,hash_bits=7")
+        pypyjit.set_param(threshold=5, inlining=1)
+        pypyjit.set_param("trace_eagerness=3,inlining=0")
 
         def f(x, y):
             return x*y+1

Modified: pypy/trunk/pypy/rlib/jit.py
==============================================================================
--- pypy/trunk/pypy/rlib/jit.py	(original)
+++ pypy/trunk/pypy/rlib/jit.py	Wed Oct 21 18:35:39 2009
@@ -94,7 +94,6 @@
 
 PARAMETERS = {'threshold': 1000,
               'trace_eagerness': 200,
-              'hash_bits': 14,
               'trace_limit': 10000,
               'inlining': False,
               'optimizer': OPTIMIZER_FULL,
@@ -114,6 +113,7 @@
     virtualizables = []
     
     def __init__(self, greens=None, reds=None, virtualizables=None,
+                 get_jitcell_at=None, set_jitcell_at=None,
                  can_inline=None, get_printable_location=None,
                  leave=None):
         if greens is not None:
@@ -128,6 +128,8 @@
             assert v in self.reds
         self._alllivevars = dict.fromkeys(self.greens + self.reds)
         self._make_extregistryentries()
+        self.get_jitcell_at = get_jitcell_at
+        self.set_jitcell_at = set_jitcell_at
         self.get_printable_location = get_printable_location
         self.can_inline = can_inline
         self.leave = leave
@@ -194,6 +196,10 @@
 #
 # Annotation and rtyping of some of the JitDriver methods
 
+class BaseJitCell(object):
+    __slots__ = ()
+
+
 class ExtEnterLeaveMarker(ExtRegistryEntry):
     # Replace a call to myjitdriver.jit_merge_point(**livevars)
     # with an operation jit_marker('jit_merge_point', myjitdriver, livevars...)
@@ -218,17 +224,21 @@
 
     def annotate_hooks(self, **kwds_s):
         driver = self.instance.im_self
+        s_jitcell = self.bookkeeper.valueoftype(BaseJitCell)
+        self.annotate_hook(driver.get_jitcell_at, driver.greens, **kwds_s)
+        self.annotate_hook(driver.set_jitcell_at, driver.greens, [s_jitcell],
+                           **kwds_s)
         self.annotate_hook(driver.can_inline, driver.greens, **kwds_s)
         self.annotate_hook(driver.get_printable_location, driver.greens, **kwds_s)
         self.annotate_hook(driver.leave, driver.greens + driver.reds, **kwds_s)
 
-    def annotate_hook(self, func, variables, **kwds_s):
+    def annotate_hook(self, func, variables, args_s=[], **kwds_s):
         if func is None:
             return
         bk = self.bookkeeper
         s_func = bk.immutablevalue(func)
         uniquekey = 'jitdriver.%s' % func.func_name
-        args_s = []
+        args_s = args_s[:]
         for name in variables:
             s_arg = kwds_s['s_' + name]
             args_s.append(s_arg)



More information about the Pypy-commit mailing list