[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