[pypy-svn] r65866 - in pypy/branch/pyjitpl5/pypy: jit/metainterp jit/metainterp/test rpython/lltypesystem
arigo at codespeak.net
arigo at codespeak.net
Mon Jun 22 17:40:04 CEST 2009
Author: arigo
Date: Mon Jun 22 17:40:03 2009
New Revision: 65866
Modified:
pypy/branch/pyjitpl5/pypy/jit/metainterp/TODO
pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py
pypy/branch/pyjitpl5/pypy/jit/metainterp/compile.py
pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py
pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py
pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py
pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rvirtualizable2.py
Log:
Restart support for virtualizables, now done in codewriter.py and
pyjitpl.py.
Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/TODO
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/metainterp/TODO (original)
+++ pypy/branch/pyjitpl5/pypy/jit/metainterp/TODO Mon Jun 22 17:40:03 2009
@@ -7,3 +7,5 @@
* kill empty pairs setup_exception_block/teardown_exception_block
* long term: memory management of the compiled code (free old code)
+
+* 'resume_info' should be shared (see pyjitpl.py)
Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py (original)
+++ pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py Mon Jun 22 17:40:03 2009
@@ -791,6 +791,13 @@
RESULT = op.result.concretetype
if RESULT is lltype.Void:
return
+ # check for virtualizable
+ if self.is_virtualizable_getset(op):
+ vinfo = self.codewriter.metainterp_sd.virtualizable_info
+ index = vinfo.field_to_extra_box[op.args[1].value]
+ self.emit('getfield_vable', index)
+ self.register_var(op.result)
+ return
# check for deepfrozen structures that force constant-folding
if deref(v_inst.concretetype)._hints.get('immutable'):
pure = '_pure'
@@ -816,6 +823,12 @@
RESULT = v_value.concretetype
if RESULT is lltype.Void:
return
+ # check for virtualizable
+ if self.is_virtualizable_getset(op):
+ vinfo = self.codewriter.metainterp_sd.virtualizable_info
+ index = vinfo.field_to_extra_box[op.args[1].value]
+ self.emit('setfield_vable', index, self.var_position(v_value))
+ return
argname = getattr(deref(v_inst.concretetype), '_gckind', 'gc')
self.emit('setfield_%s' % (argname,))
self.emit(self.var_position(v_inst))
@@ -830,6 +843,15 @@
return (op.args[1].value == 'typeptr' and
deref(op.args[0].concretetype)._hints.get('typeptr'))
+ def is_virtualizable_getset(self, op):
+ # XXX check more carefully; for now assumes that every access of
+ # an object of exactly the type VTYPEPTR is a virtualizable access
+ vinfo = self.codewriter.metainterp_sd.virtualizable_info
+ if vinfo is not None:
+ return op.args[0].concretetype == vinfo.VTYPEPTR
+ else:
+ return False
+
def handle_getfield_typeptr(self, op):
# special-casing for getting the typeptr of an object
self.minimize_variables()
Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/compile.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/metainterp/compile.py (original)
+++ pypy/branch/pyjitpl5/pypy/jit/metainterp/compile.py Mon Jun 22 17:40:03 2009
@@ -240,8 +240,10 @@
class ResumeGuardDescr(AbstractDescr):
- def __init__(self, resume_info, consts, history, history_guard_index):
+ def __init__(self, resume_info, vable_nums, consts,
+ history, history_guard_index):
self.resume_info = resume_info
+ self.vable_nums = vable_nums # None if no virtualizable
self.counter = 0
self.history = history
assert history_guard_index >= 0
Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original)
+++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Mon Jun 22 17:40:03 2009
@@ -460,6 +460,14 @@
def opimpl_setfield_raw(self, box, fielddesc, valuebox):
self.execute(rop.SETFIELD_RAW, [box, valuebox], descr=fielddesc)
+ @arguments("int")
+ def opimpl_getfield_vable(self, index):
+ resbox = self.metainterp.virtualizable_boxes[index]
+ self.make_result_box(resbox)
+ @arguments("int", "box")
+ def opimpl_setfield_vable(self, index, valuebox):
+ self.metainterp.virtualizable_boxes[index] = valuebox
+
def perform_call(self, jitcode, varargs):
if (isinstance(self.metainterp.history, history.BlackHole) and
jitcode.calldescr is not None):
@@ -729,13 +737,7 @@
check_args(*liveboxes)
self.pc = pc
self.exception_target = exception_target
- self.env = []
- for num in nums:
- if num >= 0:
- box = liveboxes[num]
- else:
- box = consts[~num]
- self.env.append(box)
+ self.env = _consume_nums(nums, liveboxes, consts)
if DEBUG >= 2:
values = ' '.join([box.repr_rpython() for box in self.env])
log('setup_resume_at_op %s:%d [%s] %d' % (self.jitcode.name,
@@ -761,7 +763,8 @@
def generate_guard(self, pc, opnum, box, extraargs=[]):
if isinstance(box, Const): # no need for a guard
return
- if isinstance(self.metainterp.history, history.BlackHole):
+ metainterp = self.metainterp
+ if isinstance(metainterp.history, history.BlackHole):
return
saved_pc = self.pc
self.pc = pc
@@ -771,30 +774,22 @@
liveboxes = []
consts = []
memo = {}
- for frame in self.metainterp.framestack:
- nums = []
- for framebox in frame.env:
- assert framebox is not None
- if isinstance(framebox, Box):
- try:
- num = memo[framebox]
- except KeyError:
- num = len(liveboxes)
- memo[framebox] = num
- liveboxes.append(framebox)
- else:
- num = ~len(consts)
- consts.append(framebox)
- nums.append(num)
+ if metainterp.staticdata.virtualizable_info is None:
+ vable_nums = None
+ else:
+ vable_nums = _generate_nums(metainterp.virtualizable_boxes,
+ memo, liveboxes, consts)
+ for frame in metainterp.framestack:
+ nums = _generate_nums(frame.env, memo, liveboxes, consts)
resume_info.append((frame.jitcode, frame.pc, nums,
frame.exception_target))
if box is not None:
moreargs = [box] + extraargs
else:
moreargs = list(extraargs)
- guard_op = self.metainterp.history.record(opnum, moreargs, None)
- resumedescr = compile.ResumeGuardDescr(resume_info, consts,
- self.metainterp.history, len(self.metainterp.history.operations)-1)
+ guard_op = metainterp.history.record(opnum, moreargs, None)
+ resumedescr = compile.ResumeGuardDescr(resume_info, vable_nums, consts,
+ metainterp.history, len(metainterp.history.operations)-1)
op = history.ResOperation(rop.FAIL, liveboxes, None, descr=resumedescr)
guard_op.suboperations = [op]
self.pc = saved_pc
@@ -827,7 +822,37 @@
# ____________________________________________________________
+def _generate_nums(frameboxes, memo, liveboxes, consts):
+ nums = []
+ for framebox in frameboxes:
+ assert framebox is not None
+ if isinstance(framebox, Box):
+ try:
+ num = memo[framebox]
+ except KeyError:
+ num = len(liveboxes)
+ memo[framebox] = num
+ liveboxes.append(framebox)
+ else:
+ num = ~len(consts)
+ consts.append(framebox)
+ nums.append(num)
+ return nums
+
+def _consume_nums(nums, liveboxes, consts):
+ env = []
+ for num in nums:
+ if num >= 0:
+ box = liveboxes[num]
+ else:
+ box = consts[~num]
+ env.append(box)
+ return env
+
+# ____________________________________________________________
+
class MetaInterpStaticData(object):
+ virtualizable_info = None
def __init__(self, portal_graph, graphs, cpu, stats, options,
optimizer=None, profile=None, warmrunnerdesc=None):
@@ -1109,6 +1134,8 @@
return self.designate_target_loop(gmp)
def reached_can_enter_jit(self, live_arg_boxes):
+ if self.staticdata.virtualizable_info is not None:
+ live_arg_boxes += self.virtualizable_boxes
# Called whenever we reach the 'can_enter_jit' hint.
# First, attempt to make a bridge:
# - if self.resumekey is a ResumeGuardDescr, it starts from a guard
@@ -1274,34 +1301,8 @@
def _initialize_from_start(self, original_boxes, num_green_args, *args):
if args:
- value = args[0]
- if isinstance(lltype.typeOf(value), lltype.Ptr):
- if lltype.typeOf(value).TO._gckind == 'gc':
- value = lltype.cast_opaque_ptr(llmemory.GCREF, value)
- if num_green_args > 0:
- cls = ConstPtr
- else:
- cls = BoxPtr
- else:
- adr = llmemory.cast_ptr_to_adr(value)
- value = self.cpu.cast_adr_to_int(adr)
- if num_green_args > 0:
- cls = ConstInt
- else:
- cls = BoxInt
- elif isinstance(lltype.typeOf(value), ootype.OOType):
- value = ootype.cast_to_object(value)
- if num_green_args > 0:
- cls = ConstObj
- else:
- cls = BoxObj
- else:
- if num_green_args > 0:
- cls = ConstInt
- else:
- cls = BoxInt
- value = intmask(value)
- box = cls(value)
+ from pypy.jit.metainterp.warmspot 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,
*args[1:])
@@ -1318,6 +1319,7 @@
f = self.newframe(self.staticdata.portal_code)
f.pc = 0
f.env = original_boxes[:]
+ self.initialize_virtualizable(original_boxes)
return original_boxes
def initialize_state_from_guard_failure(self, guard_failure):
@@ -1347,9 +1349,21 @@
# the BlackHole is invalid because it doesn't start with
# guard_failure.key.guard_op.suboperations, but that's fine
self.rebuild_state_after_failure(resumedescr.resume_info,
+ resumedescr.vable_nums,
resumedescr.consts,
guard_failure.args)
+ def initialize_virtualizable(self, original_boxes):
+ vinfo = self.staticdata.virtualizable_info
+ if vinfo is not None:
+ virtualizable_box = original_boxes[vinfo.index_in_boxes]
+ virtualizable = virtualizable_box.getptr(vinfo.VTYPEPTR)
+ # The field 'virtualizable_boxes' is not even present
+ # if 'virtualizable_info' is None. Check for that first.
+ self.virtualizable_boxes = vinfo.read_boxes(self.cpu,
+ virtualizable)
+ original_boxes += self.virtualizable_boxes
+
def handle_exception(self):
etype = self.cpu.get_exception()
evalue = self.cpu.get_exc_value()
@@ -1368,9 +1382,13 @@
frame.generate_guard(frame.pc, rop.GUARD_NO_EXCEPTION, None, [])
return False
- def rebuild_state_after_failure(self, resume_info, consts, newboxes):
+ def rebuild_state_after_failure(self, resume_info, vable_nums, consts,
+ newboxes):
if not we_are_translated():
self._debug_history.append(['guard_failure', None, None])
+ if self.staticdata.virtualizable_info is not None:
+ self.virtualizable_boxes = _consume_nums(vable_nums,
+ newboxes, consts)
self.framestack = []
for jitcode, pc, nums, exception_target in resume_info:
f = self.newframe(jitcode)
Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py (original)
+++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py Mon Jun 22 17:40:03 2009
@@ -43,7 +43,6 @@
return xy
def test_preexisting_access(self):
- py.test.skip("bugs")
myjitdriver = JitDriver(greens = [], reds = ['n', 'xy'],
virtualizables = ['xy'])
def f(n):
Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py (original)
+++ pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py Mon Jun 22 17:40:03 2009
@@ -131,6 +131,8 @@
self.build_meta_interp(**kwds)
self.make_args_specification()
self.rewrite_jit_merge_point()
+ if self.jitdriver.virtualizables:
+ self.metainterp_sd.virtualizable_info = VirtualizableInfo(self)
self.metainterp_sd.generate_bytecode(policy, self.ts)
self.make_enter_function()
self.rewrite_can_enter_jit()
@@ -463,6 +465,34 @@
call_final_function(self.translator, finish_profiler,
annhelper = self.annhelper)
+class VirtualizableInfo:
+ def __init__(self, warmrunnerdesc):
+ jitdriver = warmrunnerdesc.jitdriver
+ assert len(jitdriver.virtualizables) == 1 # for now
+ [vname] = jitdriver.virtualizables
+ index = len(jitdriver.greens) + jitdriver.reds.index(vname)
+ VTYPEPTR = warmrunnerdesc.JIT_ENTER_FUNCTYPE.ARGS[index]
+ fields = VTYPEPTR.TO._adtmeths['access'].redirected_fields
+ self.VTYPEPTR = VTYPEPTR
+ self.index_in_boxes = index
+ self.num_extra_boxes = len(fields)
+ self.field_to_extra_box = dict([(name, i)
+ for (i, name) in enumerate(fields)])
+ #
+ def read_boxes(cpu, virtualizable):
+ boxes = []
+ for fieldname in unroll_fields:
+ x = getattr(virtualizable, fieldname)
+ boxes.append(wrap(cpu, x))
+ return boxes
+ #
+ unroll_fields = unrolling_iterable(fields)
+ self.read_boxes = read_boxes
+
+ def _freeze_(self):
+ return True
+
+
def decode_hp_hint_args(op):
# Returns (list-of-green-vars, list-of-red-vars) without Voids.
assert op.opname == 'jit_marker'
@@ -486,6 +516,32 @@
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)
+ else:
+ value = intmask(value)
+ if in_const_box:
+ return history.ConstInt(value)
+ else:
+ return history.BoxInt(value)
+wrap._annspecialcase_ = 'specialize:llargtype(1)'
+
def equal_whatever(TYPE, x, y):
if isinstance(TYPE, lltype.Ptr):
if TYPE.TO is rstr.STR or TYPE.TO is rstr.UNICODE:
Modified: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rvirtualizable2.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rvirtualizable2.py (original)
+++ pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rvirtualizable2.py Mon Jun 22 17:40:03 2009
@@ -24,6 +24,7 @@
# as long as no valid pointer has been put in the structure
# by the JIT, accessing the fields should raise, in order
# to prevent constant-folding
+ import py
py.test.raises(lltype.UninitializedMemoryAccess, "getset.get")
py.test.raises(lltype.UninitializedMemoryAccess, "getset.set")
self.getsets[fieldname] = getset
More information about the Pypy-commit
mailing list