[pypy-svn] r69528 - in pypy/branch/compress-virtuals-resumedata2/pypy: . jit/backend/llgraph jit/backend/llvm/test jit/backend/test jit/backend/x86 jit/backend/x86/test jit/metainterp jit/metainterp/test objspace/std/test translator/c/test
pedronis at codespeak.net
pedronis at codespeak.net
Mon Nov 23 11:05:17 CET 2009
Author: pedronis
Date: Mon Nov 23 11:05:16 2009
New Revision: 69528
Modified:
pypy/branch/compress-virtuals-resumedata2/pypy/ (props changed)
pypy/branch/compress-virtuals-resumedata2/pypy/jit/backend/llgraph/llimpl.py
pypy/branch/compress-virtuals-resumedata2/pypy/jit/backend/llgraph/runner.py
pypy/branch/compress-virtuals-resumedata2/pypy/jit/backend/llvm/test/conftest.py (props changed)
pypy/branch/compress-virtuals-resumedata2/pypy/jit/backend/test/runner_test.py
pypy/branch/compress-virtuals-resumedata2/pypy/jit/backend/x86/assembler.py
pypy/branch/compress-virtuals-resumedata2/pypy/jit/backend/x86/regalloc.py
pypy/branch/compress-virtuals-resumedata2/pypy/jit/backend/x86/test/test_gc_integration.py (props changed)
pypy/branch/compress-virtuals-resumedata2/pypy/jit/backend/x86/test/test_virtual.py
pypy/branch/compress-virtuals-resumedata2/pypy/jit/metainterp/compile.py
pypy/branch/compress-virtuals-resumedata2/pypy/jit/metainterp/history.py
pypy/branch/compress-virtuals-resumedata2/pypy/jit/metainterp/jitprof.py
pypy/branch/compress-virtuals-resumedata2/pypy/jit/metainterp/logger.py (props changed)
pypy/branch/compress-virtuals-resumedata2/pypy/jit/metainterp/optimizeopt.py
pypy/branch/compress-virtuals-resumedata2/pypy/jit/metainterp/pyjitpl.py
pypy/branch/compress-virtuals-resumedata2/pypy/jit/metainterp/resume.py
pypy/branch/compress-virtuals-resumedata2/pypy/jit/metainterp/test/test_jitprof.py
pypy/branch/compress-virtuals-resumedata2/pypy/jit/metainterp/test/test_optimizeopt.py
pypy/branch/compress-virtuals-resumedata2/pypy/jit/metainterp/test/test_pyjitpl.py
pypy/branch/compress-virtuals-resumedata2/pypy/jit/metainterp/test/test_resume.py
pypy/branch/compress-virtuals-resumedata2/pypy/jit/metainterp/test/test_virtual.py
pypy/branch/compress-virtuals-resumedata2/pypy/objspace/std/test/test_setobject.py (props changed)
pypy/branch/compress-virtuals-resumedata2/pypy/translator/c/test/test_refcount.py (props changed)
Log:
merge the work done on the original branch here
Modified: pypy/branch/compress-virtuals-resumedata2/pypy/jit/backend/llgraph/llimpl.py
==============================================================================
--- pypy/branch/compress-virtuals-resumedata2/pypy/jit/backend/llgraph/llimpl.py (original)
+++ pypy/branch/compress-virtuals-resumedata2/pypy/jit/backend/llgraph/llimpl.py Mon Nov 23 11:05:16 2009
@@ -364,7 +364,10 @@
op = loop.operations[-1]
if op.fail_args is None:
op.fail_args = []
- op.fail_args.append(_variables[intvar])
+ if intvar == -1:
+ op.fail_args.append(None)
+ else:
+ op.fail_args.append(_variables[intvar])
def compile_redirect_fail(old_loop, old_index, new_loop):
old_loop = _from_opaque(old_loop)
@@ -407,23 +410,27 @@
except GuardFailed:
assert op.is_guard()
_stats.exec_conditional_jumps += 1
- if op.fail_args:
- args = [self.getenv(v) for v in op.fail_args]
- else:
- args = []
if op.jump_target is not None:
# a patched guard, pointing to further code
+ args = [self.getenv(v) for v in op.fail_args if v]
assert len(op.jump_target.inputargs) == len(args)
self.env = dict(zip(op.jump_target.inputargs, args))
operations = op.jump_target.operations
opindex = 0
continue
else:
+ fail_args = []
+ if op.fail_args:
+ for fail_arg in op.fail_args:
+ if fail_arg is None:
+ fail_args.append(None)
+ else:
+ fail_args.append(self.getenv(fail_arg))
# a non-patched guard
if self.verbose:
log.trace('failed: %s' % (
- ', '.join(map(str, args)),))
- self.fail_args = args
+ ', '.join(map(str, fail_args)),))
+ self.fail_args = fail_args
return op.fail_index
#verbose = self.verbose
assert (result is None) == (op.result is None)
Modified: pypy/branch/compress-virtuals-resumedata2/pypy/jit/backend/llgraph/runner.py
==============================================================================
--- pypy/branch/compress-virtuals-resumedata2/pypy/jit/backend/llgraph/runner.py (original)
+++ pypy/branch/compress-virtuals-resumedata2/pypy/jit/backend/llgraph/runner.py Mon Nov 23 11:05:16 2009
@@ -171,7 +171,10 @@
index = llimpl.compile_add_fail(c, fail_index)
faildescr._compiled_fail = c, index
for box in op.fail_args:
- llimpl.compile_add_fail_arg(c, var2index[box])
+ if box is not None:
+ llimpl.compile_add_fail_arg(c, var2index[box])
+ else:
+ llimpl.compile_add_fail_arg(c, -1)
x = op.result
if x is not None:
if isinstance(x, history.BoxInt):
Modified: pypy/branch/compress-virtuals-resumedata2/pypy/jit/backend/test/runner_test.py
==============================================================================
--- pypy/branch/compress-virtuals-resumedata2/pypy/jit/backend/test/runner_test.py (original)
+++ pypy/branch/compress-virtuals-resumedata2/pypy/jit/backend/test/runner_test.py Mon Nov 23 11:05:16 2009
@@ -125,6 +125,27 @@
res = self.cpu.get_latest_value_int(0)
assert res == 10
+ def test_compile_with_holes_in_fail_args(self):
+ i0 = BoxInt()
+ i1 = BoxInt()
+ i2 = BoxInt()
+ looptoken = LoopToken()
+ operations = [
+ ResOperation(rop.INT_ADD, [i0, ConstInt(1)], i1),
+ ResOperation(rop.INT_LE, [i1, ConstInt(9)], i2),
+ ResOperation(rop.GUARD_TRUE, [i2], None, descr=BasicFailDescr(2)),
+ ResOperation(rop.JUMP, [i1], None, descr=looptoken),
+ ]
+ inputargs = [i0]
+ operations[2].fail_args = [None, None, i1, None]
+
+ self.cpu.compile_loop(inputargs, operations, looptoken)
+ self.cpu.set_future_value_int(0, 2)
+ fail = self.cpu.execute_token(looptoken)
+ assert fail == 2
+ res = self.cpu.get_latest_value_int(2)
+ assert res == 10
+
def test_backends_dont_keep_loops_alive(self):
import weakref, gc
self.cpu.dont_keepalive_stuff = True
@@ -183,6 +204,40 @@
res = self.cpu.get_latest_value_int(0)
assert res == 20
+ def test_compile_bridge_with_holes(self):
+ i0 = BoxInt()
+ i1 = BoxInt()
+ i2 = BoxInt()
+ faildescr1 = BasicFailDescr(1)
+ faildescr2 = BasicFailDescr(2)
+ looptoken = LoopToken()
+ operations = [
+ ResOperation(rop.INT_ADD, [i0, ConstInt(1)], i1),
+ ResOperation(rop.INT_LE, [i1, ConstInt(9)], i2),
+ ResOperation(rop.GUARD_TRUE, [i2], None, descr=faildescr1),
+ ResOperation(rop.JUMP, [i1], None, descr=looptoken),
+ ]
+ inputargs = [i0]
+ operations[2].fail_args = [None, i1, None]
+ self.cpu.compile_loop(inputargs, operations, looptoken)
+
+ i1b = BoxInt()
+ i3 = BoxInt()
+ bridge = [
+ ResOperation(rop.INT_LE, [i1b, ConstInt(19)], i3),
+ ResOperation(rop.GUARD_TRUE, [i3], None, descr=faildescr2),
+ ResOperation(rop.JUMP, [i1b], None, descr=looptoken),
+ ]
+ bridge[1].fail_args = [i1b]
+
+ self.cpu.compile_bridge(faildescr1, [i1b], bridge)
+
+ self.cpu.set_future_value_int(0, 2)
+ fail = self.cpu.execute_token(looptoken)
+ assert fail == 2
+ res = self.cpu.get_latest_value_int(0)
+ assert res == 20
+
def test_finish(self):
i0 = BoxInt()
class UntouchableFailDescr(AbstractFailDescr):
Modified: pypy/branch/compress-virtuals-resumedata2/pypy/jit/backend/x86/assembler.py
==============================================================================
--- pypy/branch/compress-virtuals-resumedata2/pypy/jit/backend/x86/assembler.py (original)
+++ pypy/branch/compress-virtuals-resumedata2/pypy/jit/backend/x86/assembler.py Mon Nov 23 11:05:16 2009
@@ -738,7 +738,7 @@
""" assert that all args are actually Boxes
"""
for arg in args:
- assert isinstance(arg, Box)
+ assert arg is None or isinstance(arg, Box)
def implement_guard_recovery(self, guard_opnum, faildescr, failargs,
fail_locs):
@@ -754,6 +754,8 @@
pos = mc.tell()
for i in range(len(failargs)):
arg = failargs[i]
+ if arg is None:
+ continue
loc = locs[i]
if isinstance(loc, REG):
if arg.type == FLOAT:
@@ -767,6 +769,8 @@
mc.MOV(heap(adr), loc)
for i in range(len(failargs)):
arg = failargs[i]
+ if arg is None:
+ continue
loc = locs[i]
if not isinstance(loc, REG):
if arg.type == FLOAT:
Modified: pypy/branch/compress-virtuals-resumedata2/pypy/jit/backend/x86/regalloc.py
==============================================================================
--- pypy/branch/compress-virtuals-resumedata2/pypy/jit/backend/x86/regalloc.py (original)
+++ pypy/branch/compress-virtuals-resumedata2/pypy/jit/backend/x86/regalloc.py Mon Nov 23 11:05:16 2009
@@ -203,7 +203,8 @@
def possibly_free_vars(self, vars):
for var in vars:
- self.possibly_free_var(var)
+ if var is not None:
+ self.possibly_free_var(var)
def make_sure_var_in_reg(self, var, forbidden_vars=[],
selected_reg=None, imm_fine=True,
@@ -239,9 +240,12 @@
def _update_bindings(self, locs, inputargs):
# XXX this should probably go to llsupport/regalloc.py
used = {}
- for i in range(len(inputargs)):
+ i = 0
+ for loc in locs:
+ if loc is None: # xxx bit kludgy
+ continue
arg = inputargs[i]
- loc = locs[i]
+ i += 1
if arg.type == FLOAT:
if isinstance(loc, REG):
self.xrm.reg_bindings[arg] = loc
@@ -360,6 +364,8 @@
longevity[arg] = (start_live[arg], i)
if op.is_guard():
for arg in op.fail_args:
+ if arg is None: # hole
+ continue
assert isinstance(arg, Box)
if arg not in start_live:
print "Bogus arg in guard %d at %d" % (op.opnum, i)
@@ -373,6 +379,8 @@
return longevity
def loc(self, v):
+ if v is None:
+ return None
if v.type == FLOAT:
return self.xrm.loc(v)
return self.rm.loc(v)
Modified: pypy/branch/compress-virtuals-resumedata2/pypy/jit/backend/x86/test/test_virtual.py
==============================================================================
--- pypy/branch/compress-virtuals-resumedata2/pypy/jit/backend/x86/test/test_virtual.py (original)
+++ pypy/branch/compress-virtuals-resumedata2/pypy/jit/backend/x86/test/test_virtual.py Mon Nov 23 11:05:16 2009
@@ -1,4 +1,4 @@
-from pypy.jit.metainterp.test.test_virtual import VirtualTests
+from pypy.jit.metainterp.test.test_virtual import VirtualTests, VirtualMiscTests
from pypy.jit.backend.x86.test.test_basic import Jit386Mixin
class MyClass:
@@ -13,3 +13,8 @@
@staticmethod
def _new():
return MyClass()
+
+class TestsVirtualMisc(Jit386Mixin, VirtualMiscTests):
+ # for the individual tests see
+ # ====> ../../../metainterp/test/test_virtual.py
+ pass
Modified: pypy/branch/compress-virtuals-resumedata2/pypy/jit/metainterp/compile.py
==============================================================================
--- pypy/branch/compress-virtuals-resumedata2/pypy/jit/metainterp/compile.py (original)
+++ pypy/branch/compress-virtuals-resumedata2/pypy/jit/metainterp/compile.py Mon Nov 23 11:05:16 2009
@@ -233,7 +233,12 @@
def store_final_boxes(self, guard_op, boxes):
guard_op.fail_args = boxes
self.guard_opnum = guard_op.opnum
- self.fail_arg_types = [box.type for box in boxes]
+ fail_arg_types = [history.HOLE] * len(boxes)
+ for i in range(len(boxes)):
+ box = boxes[i]
+ if box:
+ fail_arg_types[i] = box.type
+ self.fail_arg_types = fail_arg_types
def handle_fail(self, metainterp_sd):
from pypy.jit.metainterp.pyjitpl import MetaInterp
Modified: pypy/branch/compress-virtuals-resumedata2/pypy/jit/metainterp/history.py
==============================================================================
--- pypy/branch/compress-virtuals-resumedata2/pypy/jit/metainterp/history.py (original)
+++ pypy/branch/compress-virtuals-resumedata2/pypy/jit/metainterp/history.py Mon Nov 23 11:05:16 2009
@@ -15,6 +15,7 @@
INT = 'i'
REF = 'r'
FLOAT = 'f'
+HOLE = '_'
FAILARGS_LIMIT = 1000
@@ -756,8 +757,9 @@
ops = op.descr._debug_suboperations
TreeLoop.check_consistency_of_branch(ops, seen.copy())
for box in op.fail_args or []:
- assert isinstance(box, Box)
- assert box in seen
+ if box is not None:
+ assert isinstance(box, Box)
+ assert box in seen
else:
assert op.fail_args is None
box = op.result
Modified: pypy/branch/compress-virtuals-resumedata2/pypy/jit/metainterp/jitprof.py
==============================================================================
--- pypy/branch/compress-virtuals-resumedata2/pypy/jit/metainterp/jitprof.py (original)
+++ pypy/branch/compress-virtuals-resumedata2/pypy/jit/metainterp/jitprof.py Mon Nov 23 11:05:16 2009
@@ -20,6 +20,10 @@
OPT_FORCINGS
ABORT_TOO_LONG
ABORT_BRIDGE
+NVIRTUALS
+NVHOLES
+NVREUSED
+NVRIGHTHOLES
"""
def _setup():
@@ -175,6 +179,10 @@
self._print_intline("forcings", cnt[OPT_FORCINGS])
self._print_intline("trace too long", cnt[ABORT_TOO_LONG])
self._print_intline("bridge abort", cnt[ABORT_BRIDGE])
+ self._print_intline("nvirtuals", cnt[NVIRTUALS])
+ self._print_intline("nvholes", cnt[NVHOLES])
+ self._print_intline("nvrightholes", cnt[NVRIGHTHOLES])
+ self._print_intline("nvreused", cnt[NVREUSED])
def _print_line_time(self, string, i, tim):
final = "%s:%s\t%d\t%f\n" % (string, " " * max(0, 13-len(string)), i, tim)
Modified: pypy/branch/compress-virtuals-resumedata2/pypy/jit/metainterp/optimizeopt.py
==============================================================================
--- pypy/branch/compress-virtuals-resumedata2/pypy/jit/metainterp/optimizeopt.py (original)
+++ pypy/branch/compress-virtuals-resumedata2/pypy/jit/metainterp/optimizeopt.py Mon Nov 23 11:05:16 2009
@@ -2,7 +2,7 @@
ConstFloat
from pypy.jit.metainterp.history import Const, ConstInt, ConstPtr, ConstObj, REF
from pypy.jit.metainterp.resoperation import rop, ResOperation
-from pypy.jit.metainterp.jitprof import OPT_OPS, OPT_GUARDS, OPT_FORCINGS
+from pypy.jit.metainterp import jitprof
from pypy.jit.metainterp.executor import execute_nonspec
from pypy.jit.metainterp.specnode import SpecNode, NotSpecNode, ConstantSpecNode
from pypy.jit.metainterp.specnode import AbstractVirtualStructSpecNode
@@ -62,6 +62,9 @@
def get_args_for_fail(self, modifier):
pass
+ def make_virtual_info(self, modifier, fieldnums):
+ raise NotImplementedError # should not be called on this level
+
def is_constant(self):
return self.level == LEVEL_CONSTANT
@@ -134,9 +137,10 @@
class AbstractVirtualValue(OptValue):
- _attrs_ = ('optimizer', 'keybox', 'source_op')
+ _attrs_ = ('optimizer', 'keybox', 'source_op', '_cached_vinfo')
box = None
level = LEVEL_NONNULL
+ _cached_vinfo = None
def __init__(self, optimizer, keybox, source_op=None):
self.optimizer = optimizer
@@ -155,6 +159,19 @@
self._really_force()
return self.box
+ def make_virtual_info(self, modifier, fieldnums):
+ vinfo = self._cached_vinfo
+ if vinfo is not None and resume.tagged_list_eq(
+ vinfo.fieldnums, fieldnums):
+ return vinfo
+ vinfo = self._make_virtual(modifier)
+ vinfo.fieldnums = fieldnums
+ self._cached_vinfo = vinfo
+ return vinfo
+
+ def _make_virtual(self, modifier):
+ raise NotImplementedError("abstract base")
+
class AbstractVirtualStructValue(AbstractVirtualValue):
_attrs_ = ('_fields', '_cached_sorted_fields')
@@ -207,14 +224,11 @@
# we have already seen the very same keybox
lst = self._get_field_descr_list()
fieldboxes = [self._fields[ofs].get_key_box() for ofs in lst]
- self._make_virtual(modifier, lst, fieldboxes)
+ modifier.register_virtual_fields(self.keybox, fieldboxes)
for ofs in lst:
fieldvalue = self._fields[ofs]
fieldvalue.get_args_for_fail(modifier)
- def _make_virtual(self, modifier, fielddescrs, fieldboxes):
- raise NotImplementedError
-
class VirtualValue(AbstractVirtualStructValue):
level = LEVEL_KNOWNCLASS
@@ -224,10 +238,9 @@
assert isinstance(known_class, Const)
self.known_class = known_class
- def _make_virtual(self, modifier, fielddescrs, fieldboxes):
- modifier.make_virtual(self.keybox, self.known_class,
- fielddescrs, fieldboxes)
-
+ def _make_virtual(self, modifier):
+ fielddescrs = self._get_field_descr_list()
+ return modifier.make_virtual(self.known_class, fielddescrs)
class VStructValue(AbstractVirtualStructValue):
@@ -235,10 +248,9 @@
AbstractVirtualStructValue.__init__(self, optimizer, keybox, source_op)
self.structdescr = structdescr
- def _make_virtual(self, modifier, fielddescrs, fieldboxes):
- modifier.make_vstruct(self.keybox, self.structdescr,
- fielddescrs, fieldboxes)
-
+ def _make_virtual(self, modifier):
+ fielddescrs = self._get_field_descr_list()
+ return modifier.make_vstruct(self.structdescr, fielddescrs)
class VArrayValue(AbstractVirtualValue):
@@ -282,11 +294,14 @@
const = self.optimizer.new_const_item(self.arraydescr)
for itemvalue in self._items:
itemboxes.append(itemvalue.get_key_box())
- modifier.make_varray(self.keybox, self.arraydescr, itemboxes)
+ modifier.register_virtual_fields(self.keybox, itemboxes)
for itemvalue in self._items:
if itemvalue is not self.constvalue:
itemvalue.get_args_for_fail(modifier)
+ def _make_virtual(self, modifier):
+ return modifier.make_varray(self.arraydescr)
+
class __extend__(SpecNode):
def setup_virtual_node(self, optimizer, box, newinputargs):
raise NotImplementedError
@@ -359,7 +374,7 @@
self.bool_boxes = {}
def forget_numberings(self, virtualbox):
- self.metainterp_sd.profiler.count(OPT_FORCINGS)
+ self.metainterp_sd.profiler.count(jitprof.OPT_FORCINGS)
self.resumedata_memo.forget_numberings(virtualbox)
def getinterned(self, box):
@@ -480,6 +495,8 @@
else:
self.optimize_default(op)
self.loop.operations = self.newoperations
+ # accumulate counters
+ self.resumedata_memo.update_counters(self.metainterp_sd.profiler)
def emit_operation(self, op, must_clone=True):
self.heap_op_optimizer.emitting_operation(op)
@@ -492,9 +509,9 @@
op = op.clone()
must_clone = False
op.args[i] = box
- self.metainterp_sd.profiler.count(OPT_OPS)
+ self.metainterp_sd.profiler.count(jitprof.OPT_OPS)
if op.is_guard():
- self.metainterp_sd.profiler.count(OPT_GUARDS)
+ self.metainterp_sd.profiler.count(jitprof.OPT_GUARDS)
self.store_final_boxes_in_guard(op)
elif op.can_raise():
self.exception_might_have_happened = True
@@ -507,7 +524,7 @@
assert isinstance(descr, compile.ResumeGuardDescr)
modifier = resume.ResumeDataVirtualAdder(descr, self.resumedata_memo)
newboxes = modifier.finish(self.values)
- if len(newboxes) > self.metainterp_sd.options.failargs_limit:
+ if len(newboxes) > self.metainterp_sd.options.failargs_limit: # XXX be careful here
raise compile.GiveUp
descr.store_final_boxes(op, newboxes)
#
Modified: pypy/branch/compress-virtuals-resumedata2/pypy/jit/metainterp/pyjitpl.py
==============================================================================
--- pypy/branch/compress-virtuals-resumedata2/pypy/jit/metainterp/pyjitpl.py (original)
+++ pypy/branch/compress-virtuals-resumedata2/pypy/jit/metainterp/pyjitpl.py Mon Nov 23 11:05:16 2009
@@ -1683,21 +1683,20 @@
def initialize_state_from_guard_failure(self, resumedescr, must_compile):
# guard failure: rebuild a complete MIFrame stack
self.in_recursion = -1 # always one portal around
- inputargs = self.load_values_from_failure(resumedescr)
- warmrunnerstate = self.staticdata.state
+ inputargs_and_holes = self.load_values_from_failure(resumedescr)
if must_compile:
self.history = history.History(self.cpu)
- self.history.inputargs = inputargs
+ self.history.inputargs = [box for box in inputargs_and_holes if box]
self.staticdata.profiler.start_tracing()
else:
self.staticdata.profiler.start_blackhole()
self.history = None # this means that is_blackholing() is true
- self.rebuild_state_after_failure(resumedescr, inputargs)
+ self.rebuild_state_after_failure(resumedescr, inputargs_and_holes)
def load_values_from_failure(self, resumedescr):
cpu = self.cpu
fail_arg_types = resumedescr.fail_arg_types
- inputargs = []
+ inputargs_and_holes = []
for i in range(len(fail_arg_types)):
boxtype = fail_arg_types[i]
if boxtype == history.INT:
@@ -1706,10 +1705,12 @@
box = cpu.ts.BoxRef(cpu.get_latest_value_ref(i))
elif boxtype == history.FLOAT:
box = history.BoxFloat(cpu.get_latest_value_float(i))
+ elif boxtype == history.HOLE:
+ box = None
else:
assert False, "bad box type: num=%d" % ord(boxtype)
- inputargs.append(box)
- return inputargs
+ inputargs_and_holes.append(box)
+ return inputargs_and_holes
def initialize_virtualizable(self, original_boxes):
vinfo = self.staticdata.virtualizable_info
Modified: pypy/branch/compress-virtuals-resumedata2/pypy/jit/metainterp/resume.py
==============================================================================
--- pypy/branch/compress-virtuals-resumedata2/pypy/jit/metainterp/resume.py (original)
+++ pypy/branch/compress-virtuals-resumedata2/pypy/jit/metainterp/resume.py Mon Nov 23 11:05:16 2009
@@ -1,6 +1,7 @@
import sys, os
from pypy.jit.metainterp.history import Box, Const, ConstInt, INT, REF
from pypy.jit.metainterp.resoperation import rop
+from pypy.jit.metainterp import jitprof
from pypy.rpython.lltypesystem import rffi
from pypy.rlib import rarithmetic
from pypy.rlib.objectmodel import we_are_translated
@@ -84,12 +85,21 @@
# please rpython :(
return rarithmetic.widen(x) == rarithmetic.widen(y)
+def tagged_list_eq(tl1, tl2):
+ if len(tl1) != len(tl2):
+ return False
+ for i in range(len(tl1)):
+ if not tagged_eq(tl1[i], tl2[i]):
+ return False
+ return True
+
TAGCONST = 0
TAGINT = 1
TAGBOX = 2
TAGVIRTUAL = 3
-UNASSIGNED = tag(-1, TAGBOX)
+UNASSIGNED = tag(-2 ** 12 - 1, TAGBOX)
+UNASSIGNEDVIRTUAL = tag(-2 ** 12 - 1, TAGVIRTUAL)
NULLREF = tag(-1, TAGCONST)
@@ -101,6 +111,13 @@
self.large_ints = {}
self.refs = cpu.ts.new_ref_dict_2()
self.numberings = {}
+ self.cached_boxes = {}
+ self.cached_virtuals = {}
+
+ self.nvirtuals = 0
+ self.nvholes = 0
+ self.nvrightholes = 0
+ self.nvreused = 0
def getconst(self, const):
if const.type == INT:
@@ -135,6 +152,8 @@
self.consts.append(const)
return result
+ # env numbering
+
def number(self, values, snapshot):
if snapshot is None:
return None, {}, 0
@@ -173,7 +192,42 @@
def forget_numberings(self, virtualbox):
# XXX ideally clear only the affected numberings
self.numberings.clear()
+ self.clear_box_virtual_numbers()
+
+ # caching for virtuals and boxes inside them
+
+ def num_cached_boxes(self):
+ return len(self.cached_boxes)
+
+ def assign_number_to_box(self, box, boxes):
+ if box in self.cached_boxes:
+ num = self.cached_boxes[box]
+ boxes[-num-1] = box
+ else:
+ boxes.append(box)
+ num = -len(boxes)
+ self.cached_boxes[box] = num
+ return num
+
+ def num_cached_virtuals(self):
+ return len(self.cached_virtuals)
+
+ def assign_number_to_virtual(self, box):
+ if box in self.cached_virtuals:
+ num = self.cached_virtuals[box]
+ else:
+ num = self.cached_virtuals[box] = -len(self.cached_virtuals) - 1
+ return num
+ def clear_box_virtual_numbers(self):
+ self.cached_boxes.clear()
+ self.cached_virtuals.clear()
+
+ def update_counters(self, profiler):
+ profiler.count(jitprof.NVIRTUALS, self.nvirtuals)
+ profiler.count(jitprof.NVHOLES, self.nvholes)
+ profiler.count(jitprof.NVREUSED, self.nvreused)
+ profiler.count(jitprof.NVRIGHTHOLES, self.nvrightholes)
_frame_info_placeholder = (None, 0, 0)
@@ -185,30 +239,19 @@
#self.virtuals = []
#self.vfieldboxes = []
- def make_virtual(self, virtualbox, known_class, fielddescrs, fieldboxes):
- vinfo = VirtualInfo(known_class, fielddescrs)
- self._make_virtual(virtualbox, vinfo, fieldboxes)
-
- def make_vstruct(self, virtualbox, typedescr, fielddescrs, fieldboxes):
- vinfo = VStructInfo(typedescr, fielddescrs)
- self._make_virtual(virtualbox, vinfo, fieldboxes)
-
- def make_varray(self, virtualbox, arraydescr, itemboxes):
- vinfo = VArrayInfo(arraydescr)
- self._make_virtual(virtualbox, vinfo, itemboxes)
-
- def _make_virtual(self, virtualbox, vinfo, fieldboxes):
- if virtualbox in self.liveboxes_from_env:
- tagged = self.liveboxes_from_env[virtualbox]
- i, _ = untag(tagged)
- assert self.virtuals[i] is None
- self.virtuals[i] = vinfo
- self.vfieldboxes[i] = fieldboxes
- else:
- tagged = tag(len(self.virtuals), TAGVIRTUAL)
- self.virtuals.append(vinfo)
- self.vfieldboxes.append(fieldboxes)
+ def make_virtual(self, known_class, fielddescrs):
+ return VirtualInfo(known_class, fielddescrs)
+
+ def make_vstruct(self, typedescr, fielddescrs):
+ return VStructInfo(typedescr, fielddescrs)
+
+ def make_varray(self, arraydescr):
+ return VArrayInfo(arraydescr)
+
+ def register_virtual_fields(self, virtualbox, fieldboxes):
+ tagged = self.liveboxes_from_env.get(virtualbox, UNASSIGNEDVIRTUAL)
self.liveboxes[virtualbox] = tagged
+ self.vfieldboxes[virtualbox] = fieldboxes
self._register_boxes(fieldboxes)
def register_box(self, box):
@@ -234,7 +277,8 @@
def finish(self, values):
# compute the numbering
storage = self.storage
- numb, liveboxes_from_env, v = self.memo.number(values, storage.rd_snapshot)
+ numb, liveboxes_from_env, v = self.memo.number(values,
+ storage.rd_snapshot)
self.liveboxes_from_env = liveboxes_from_env
self.liveboxes = {}
storage.rd_numb = numb
@@ -243,8 +287,7 @@
# collect liveboxes and virtuals
n = len(liveboxes_from_env) - v
liveboxes = [None]*n
- self.virtuals = [None]*v
- self.vfieldboxes = [None]*v
+ self.vfieldboxes = {}
for box, tagged in liveboxes_from_env.iteritems():
i, tagbits = untag(tagged)
if tagbits == TAGBOX:
@@ -254,31 +297,57 @@
value = values[box]
value.get_args_for_fail(self)
- self._number_virtuals(liveboxes)
+ self._number_virtuals(liveboxes, values, v)
storage.rd_consts = self.memo.consts
dump_storage(storage, liveboxes)
return liveboxes[:]
- def _number_virtuals(self, liveboxes):
+ def _number_virtuals(self, liveboxes, values, num_env_virtuals):
+ memo = self.memo
+ new_liveboxes = [None] * memo.num_cached_boxes()
for box, tagged in self.liveboxes.iteritems():
i, tagbits = untag(tagged)
if tagbits == TAGBOX:
+ assert box not in self.liveboxes_from_env
assert tagged_eq(tagged, UNASSIGNED)
- self.liveboxes[box] = tag(len(liveboxes), TAGBOX)
- liveboxes.append(box)
+ index = memo.assign_number_to_box(box, new_liveboxes)
+ self.liveboxes[box] = tag(index, TAGBOX)
else:
assert tagbits == TAGVIRTUAL
+ if tagged_eq(tagged, UNASSIGNEDVIRTUAL):
+ assert box not in self.liveboxes_from_env
+ index = memo.assign_number_to_virtual(box)
+ self.liveboxes[box] = tag(index, TAGVIRTUAL)
+ new_liveboxes.reverse()
+ liveboxes.extend(new_liveboxes)
storage = self.storage
storage.rd_virtuals = None
- if len(self.virtuals) > 0:
- storage.rd_virtuals = self.virtuals[:]
- for i in range(len(storage.rd_virtuals)):
- vinfo = storage.rd_virtuals[i]
- fieldboxes = self.vfieldboxes[i]
- vinfo.fieldnums = [self._gettagged(box)
- for box in fieldboxes]
+ vfieldboxes = self.vfieldboxes
+ if vfieldboxes:
+ length = num_env_virtuals + memo.num_cached_virtuals()
+ virtuals = storage.rd_virtuals = [None] * length
+ memo.nvirtuals += length
+ memo.nvholes += length - len(vfieldboxes)
+ for virtualbox, fieldboxes in vfieldboxes.iteritems():
+ num, _ = untag(self.liveboxes[virtualbox])
+ value = values[virtualbox]
+ fieldnums = [self._gettagged(box)
+ for box in fieldboxes]
+ vinfo = value.make_virtual_info(self, fieldnums)
+ # if a new vinfo instance is made, we get the fieldnums list we
+ # pass in as an attribute. hackish.
+ if vinfo.fieldnums is not fieldnums:
+ memo.nvreused += 1
+ virtuals[num] = vinfo
+ # count right holes
+ r = 0
+ while r < length:
+ if virtuals[-1-r]:
+ break
+ r += 1
+ memo.nvrightholes += r
def _gettagged(self, box):
if isinstance(box, Const):
@@ -392,10 +461,15 @@
def _prepare_virtuals(self, metainterp, virtuals):
if virtuals:
- self.virtuals = [vinfo.allocate(metainterp) for vinfo in virtuals]
+ self.virtuals = [None] * len(virtuals)
for i in range(len(virtuals)):
vinfo = virtuals[i]
- vinfo.setfields(metainterp, self.virtuals[i], self._decode_box)
+ if vinfo is not None:
+ self.virtuals[i] = vinfo.allocate(metainterp)
+ for i in range(len(virtuals)):
+ vinfo = virtuals[i]
+ if vinfo is not None:
+ vinfo.setfields(metainterp, self.virtuals[i], self._decode_box)
def consume_boxes(self):
numb = self.cur_numb
@@ -450,8 +524,14 @@
for const in storage.rd_consts:
debug_print('\tconst', const.repr_rpython())
for box in liveboxes:
- debug_print('\tbox', box.repr_rpython())
+ if box is None:
+ debug_print('\tbox', 'None')
+ else:
+ debug_print('\tbox', box.repr_rpython())
if storage.rd_virtuals is not None:
for virtual in storage.rd_virtuals:
- virtual.debug_prints()
+ if virtual is None:
+ debug_print('\t\t', 'None')
+ else:
+ virtual.debug_prints()
debug_stop("jit-resume")
Modified: pypy/branch/compress-virtuals-resumedata2/pypy/jit/metainterp/test/test_jitprof.py
==============================================================================
--- pypy/branch/compress-virtuals-resumedata2/pypy/jit/metainterp/test/test_jitprof.py (original)
+++ pypy/branch/compress-virtuals-resumedata2/pypy/jit/metainterp/test/test_jitprof.py Mon Nov 23 11:05:16 2009
@@ -63,7 +63,8 @@
]
assert profiler.events == expected
assert profiler.times == [2, 1, 1, 1]
- assert profiler.counters == [1, 1, 1, 1, 4, 3, 1, 1, 7, 1, 0, 0, 0]
+ assert profiler.counters == [1, 1, 1, 1, 4, 3, 1, 1, 7, 1, 0, 0, 0,
+ 0, 0, 0, 0]
def test_simple_loop_with_call(self):
@dont_look_inside
Modified: pypy/branch/compress-virtuals-resumedata2/pypy/jit/metainterp/test/test_optimizeopt.py
==============================================================================
--- pypy/branch/compress-virtuals-resumedata2/pypy/jit/metainterp/test/test_optimizeopt.py (original)
+++ pypy/branch/compress-virtuals-resumedata2/pypy/jit/metainterp/test/test_optimizeopt.py Mon Nov 23 11:05:16 2009
@@ -74,6 +74,22 @@
lst2 = virt1._get_field_descr_list()
assert lst1 is lst2
+def test_reuse_vinfo():
+ class FakeVInfo(object):
+ pass
+ class FakeVirtualValue(optimizeopt.AbstractVirtualValue):
+ def _make_virtual(self, *args):
+ return FakeVInfo()
+ v1 = FakeVirtualValue(None, None, None)
+ vinfo1 = v1.make_virtual_info(None, [1, 2, 4])
+ vinfo2 = v1.make_virtual_info(None, [1, 2, 4])
+ assert vinfo1 is vinfo2
+ vinfo3 = v1.make_virtual_info(None, [1, 2, 6])
+ assert vinfo3 is not vinfo2
+ vinfo4 = v1.make_virtual_info(None, [1, 2, 6])
+ assert vinfo3 is vinfo4
+
+
# ____________________________________________________________
def equaloplists(oplist1, oplist2, strict_fail_args=True, remap={}):
Modified: pypy/branch/compress-virtuals-resumedata2/pypy/jit/metainterp/test/test_pyjitpl.py
==============================================================================
--- pypy/branch/compress-virtuals-resumedata2/pypy/jit/metainterp/test/test_pyjitpl.py (original)
+++ pypy/branch/compress-virtuals-resumedata2/pypy/jit/metainterp/test/test_pyjitpl.py Mon Nov 23 11:05:16 2009
@@ -1,7 +1,8 @@
# some unit tests for the bytecode decoding
-from pypy.jit.metainterp import pyjitpl, codewriter, resoperation
+from pypy.jit.metainterp import pyjitpl, codewriter, resoperation, history
+from pypy.jit.metainterp import jitprof
from pypy.jit.metainterp.history import AbstractFailDescr, BoxInt, ConstInt
from pypy.jit.metainterp.history import History
from pypy.jit.metainterp.resoperation import ResOperation, rop
@@ -154,3 +155,39 @@
assert metainterp_sd.get_name_from_address(123) == 'a'
assert metainterp_sd.get_name_from_address(456) == 'b'
assert metainterp_sd.get_name_from_address(789) == ''
+
+def test_initialize_state_from_guard_failure():
+ from pypy.jit.metainterp.typesystem import llhelper
+ calls = []
+
+ class FakeCPU:
+ ts = llhelper
+
+ def get_latest_value_int(self, index):
+ return index
+
+ class FakeStaticData:
+ cpu = FakeCPU()
+ profiler = jitprof.EmptyProfiler()
+
+ metainterp = pyjitpl.MetaInterp(FakeStaticData())
+
+ def rebuild_state_after_failure(descr, newboxes):
+ calls.append(newboxes)
+ metainterp.rebuild_state_after_failure = rebuild_state_after_failure
+
+ class FakeResumeDescr:
+ pass
+ resumedescr = FakeResumeDescr()
+ resumedescr.fail_arg_types = [history.INT, history.HOLE,
+ history.INT, history.HOLE,
+ history.INT]
+
+ metainterp.initialize_state_from_guard_failure(resumedescr, True)
+
+ inp = metainterp.history.inputargs
+ assert len(inp) == 3
+ assert [box.value for box in inp] == [0, 2, 4]
+ b0, b2, b4 = inp
+ assert len(calls) == 1
+ assert calls[0] == [b0, None, b2, None, b4]
Modified: pypy/branch/compress-virtuals-resumedata2/pypy/jit/metainterp/test/test_resume.py
==============================================================================
--- pypy/branch/compress-virtuals-resumedata2/pypy/jit/metainterp/test/test_resume.py (original)
+++ pypy/branch/compress-virtuals-resumedata2/pypy/jit/metainterp/test/test_resume.py Mon Nov 23 11:05:16 2009
@@ -1,6 +1,7 @@
import py
from pypy.rpython.lltypesystem import lltype, llmemory, rffi
-from pypy.jit.metainterp.optimizeopt import VirtualValue, OptValue
+from pypy.jit.metainterp.optimizeopt import VirtualValue, OptValue, VArrayValue
+from pypy.jit.metainterp.optimizeopt import VStructValue
from pypy.jit.metainterp.resume import *
from pypy.jit.metainterp.history import BoxInt, BoxPtr, ConstInt, ConstAddr
from pypy.jit.metainterp.history import ConstPtr, ConstFloat
@@ -33,6 +34,12 @@
assert tagged_eq(UNASSIGNED, UNASSIGNED)
assert not tagged_eq(tag(1, TAGBOX), UNASSIGNED)
+def test_tagged_list_eq():
+ assert tagged_list_eq([UNASSIGNED, tag(1, TAGBOX), tag(-2, TAGVIRTUAL)],
+ [UNASSIGNED, tag(1, TAGBOX), tag(-2, TAGVIRTUAL)])
+ assert not tagged_list_eq([tag(1, TAGBOX)], [tag(-2, TAGBOX)])
+ assert not tagged_list_eq([tag(1, TAGBOX), tag(-2, TAGBOX)], [tag(1, TAGBOX)])
+
class MyMetaInterp:
def __init__(self, cpu=None):
if cpu is None:
@@ -105,6 +112,22 @@
lst = reader.consume_boxes()
assert lst == [b1s, b2s, b3s]
+
+def test_prepare_virtuals():
+ class FakeVinfo(object):
+ def allocate(self, metainterp):
+ return "allocated"
+ def setfields(self, metainterp, virtual, func):
+ assert virtual == "allocated"
+ class FakeStorage(object):
+ rd_virtuals = [FakeVinfo(), None]
+ rd_numb = []
+ rd_consts = []
+ class FakeMetainterp(object):
+ cpu = None
+ reader = ResumeDataReader(FakeStorage(), [], FakeMetainterp())
+ assert reader.virtuals == ["allocated", None]
+
# ____________________________________________________________
@@ -356,20 +379,21 @@
modifier = ResumeDataVirtualAdder(storage, memo)
liveboxes = modifier.finish(values)
assert len(storage.rd_virtuals) == 1
- assert storage.rd_virtuals[0].fieldnums == [tag(len(liveboxes)-1, TAGBOX),
+ assert storage.rd_virtuals[0].fieldnums == [tag(-1, TAGBOX),
tag(0, TAGCONST)]
b6 = BoxPtr()
v6 = virtual_value(b6, c2, None)
v6.setfield(LLtypeMixin.nextdescr, v6)
values = {b2: virtual_value(b2, b4, v6), b6: v6}
+ memo.clear_box_virtual_numbers()
modifier = ResumeDataVirtualAdder(storage2, memo)
liveboxes2 = modifier.finish(values)
assert len(storage2.rd_virtuals) == 2
assert storage2.rd_virtuals[0].fieldnums == [tag(len(liveboxes2)-1, TAGBOX),
- tag(1, TAGVIRTUAL)]
+ tag(-1, TAGVIRTUAL)]
assert storage2.rd_virtuals[1].fieldnums == [tag(2, TAGINT),
- tag(1, TAGVIRTUAL)]
+ tag(-1, TAGVIRTUAL)]
# now on to resuming
metainterp = MyMetaInterp()
@@ -398,6 +422,33 @@
FakeFrame("code2", 10, -1, c3, b2t, b4t)]
assert metainterp.framestack == fs2
+def test_rebuild_from_resumedata_two_guards_w_shared_virtuals():
+ b1, b2, b3, b4, b5, b6 = [BoxPtr(), BoxPtr(), BoxInt(), BoxPtr(), BoxInt(), BoxInt()]
+ c1, c2, c3, c4 = [ConstInt(1), ConstInt(2), ConstInt(3),
+ LLtypeMixin.nodebox.constbox()]
+ storage = Storage()
+ fs = [FakeFrame("code0", 0, -1, c1, b2, b3)]
+ capture_resumedata(fs, None, storage)
+
+ memo = ResumeDataLoopMemo(LLtypeMixin.cpu)
+ values = {b2: virtual_value(b2, b5, c4)}
+ modifier = ResumeDataVirtualAdder(storage, memo)
+ liveboxes = modifier.finish(values)
+ assert len(storage.rd_virtuals) == 1
+ assert storage.rd_virtuals[0].fieldnums == [tag(-1, TAGBOX),
+ tag(0, TAGCONST)]
+
+ storage2 = Storage()
+ fs = [FakeFrame("code0", 0, -1, b1, b4, b2)]
+ capture_resumedata(fs, None, storage2)
+ values[b4] = virtual_value(b4, b6, c4)
+ modifier = ResumeDataVirtualAdder(storage2, memo)
+ liveboxes = modifier.finish(values)
+ assert len(storage2.rd_virtuals) == 2
+ assert storage2.rd_virtuals[1].fieldnums == storage.rd_virtuals[0].fieldnums
+ assert storage2.rd_virtuals[1] is storage.rd_virtuals[0]
+
+
def test_resumedata_top_recursive_virtuals():
b1, b2, b3 = [BoxPtr(), BoxPtr(), BoxInt()]
storage = Storage()
@@ -413,9 +464,9 @@
liveboxes = modifier.finish(values)
assert liveboxes == [b3]
assert len(storage.rd_virtuals) == 2
- assert storage.rd_virtuals[0].fieldnums == [tag(0, TAGBOX),
+ assert storage.rd_virtuals[0].fieldnums == [tag(-1, TAGBOX),
tag(1, TAGVIRTUAL)]
- assert storage.rd_virtuals[1].fieldnums == [tag(0, TAGBOX),
+ assert storage.rd_virtuals[1].fieldnums == [tag(-1, TAGBOX),
tag(0, TAGVIRTUAL)]
@@ -553,31 +604,76 @@
tag(1, TAGVIRTUAL)]
assert numb5.prev is numb4
+def test_ResumeDataLoopMemo_number_boxes():
+ memo = ResumeDataLoopMemo(LLtypeMixin.cpu)
+ b1, b2 = [BoxInt(), BoxInt()]
+ assert memo.num_cached_boxes() == 0
+ boxes = []
+ num = memo.assign_number_to_box(b1, boxes)
+ assert num == -1
+ assert boxes == [b1]
+ assert memo.num_cached_boxes() == 1
+ boxes = [None]
+ num = memo.assign_number_to_box(b1, boxes)
+ assert num == -1
+ assert boxes == [b1]
+ num = memo.assign_number_to_box(b2, boxes)
+ assert num == -2
+ assert boxes == [b1, b2]
+
+ assert memo.num_cached_boxes() == 2
+ boxes = [None, None]
+ num = memo.assign_number_to_box(b2, boxes)
+ assert num == -2
+ assert boxes == [None, b2]
+ num = memo.assign_number_to_box(b1, boxes)
+ assert num == -1
+ assert boxes == [b1, b2]
+
+ memo.clear_box_virtual_numbers()
+ assert memo.num_cached_boxes() == 0
+
+def test_ResumeDataLoopMemo_number_virtuals():
+ memo = ResumeDataLoopMemo(LLtypeMixin.cpu)
+ b1, b2 = [BoxInt(), BoxInt()]
+ assert memo.num_cached_virtuals() == 0
+ num = memo.assign_number_to_virtual(b1)
+ assert num == -1
+ assert memo.num_cached_virtuals() == 1
+ num = memo.assign_number_to_virtual(b1)
+ assert num == -1
+ num = memo.assign_number_to_virtual(b2)
+ assert num == -2
+
+ assert memo.num_cached_virtuals() == 2
+ num = memo.assign_number_to_virtual(b2)
+ assert num == -2
+ num = memo.assign_number_to_virtual(b1)
+ assert num == -1
+
+ memo.clear_box_virtual_numbers()
+ assert memo.num_cached_virtuals() == 0
-def test__make_virtual():
+def test_register_virtual_fields():
b1, b2 = BoxInt(), BoxInt()
vbox = BoxPtr()
modifier = ResumeDataVirtualAdder(None, None)
modifier.liveboxes_from_env = {}
modifier.liveboxes = {}
- modifier.virtuals = []
- modifier.vfieldboxes = []
- modifier.make_virtual(vbox, None, ['a', 'b'], [b1, b2])
- assert modifier.liveboxes == {vbox: tag(0, TAGVIRTUAL), b1: UNASSIGNED,
+ modifier.vfieldboxes = {}
+ modifier.register_virtual_fields(vbox, [b1, b2])
+ assert modifier.liveboxes == {vbox: UNASSIGNEDVIRTUAL, b1: UNASSIGNED,
b2: UNASSIGNED}
- assert len(modifier.virtuals) == 1
- assert modifier.vfieldboxes == [[b1, b2]]
+ assert modifier.vfieldboxes == {vbox: [b1, b2]}
modifier = ResumeDataVirtualAdder(None, None)
modifier.liveboxes_from_env = {vbox: tag(0, TAGVIRTUAL)}
modifier.liveboxes = {}
- modifier.virtuals = [None]
- modifier.vfieldboxes = [None]
- modifier.make_virtual(vbox, None, ['a', 'b', 'c'], [b1, b2, vbox])
+ modifier.vfieldboxes = {}
+ modifier.register_virtual_fields(vbox, [b1, b2, vbox])
assert modifier.liveboxes == {b1: UNASSIGNED, b2: UNASSIGNED,
vbox: tag(0, TAGVIRTUAL)}
- assert len(modifier.virtuals) == 1
- assert modifier.vfieldboxes == [[b1, b2, vbox]]
+ assert modifier.vfieldboxes == {vbox: [b1, b2, vbox]}
def _resume_remap(liveboxes, expected, *newvalues):
newboxes = []
@@ -692,22 +788,26 @@
modifier = ResumeDataVirtualAdder(storage, memo)
modifier.liveboxes_from_env = {}
modifier.liveboxes = {}
- modifier.virtuals = []
- modifier.vfieldboxes = []
- modifier.make_virtual(b2s,
- ConstAddr(LLtypeMixin.node_vtable_adr,
- LLtypeMixin.cpu),
- [LLtypeMixin.nextdescr, LLtypeMixin.valuedescr],
- [b4s, c1s]) # new fields
- modifier.make_virtual(b4s,
- ConstAddr(LLtypeMixin.node_vtable_adr2,
- LLtypeMixin.cpu),
- [LLtypeMixin.nextdescr, LLtypeMixin.valuedescr,
- LLtypeMixin.otherdescr],
- [b2s, b3s, b5s]) # new fields
+ modifier.vfieldboxes = {}
+
+ v2 = VirtualValue(None, ConstAddr(LLtypeMixin.node_vtable_adr,
+ LLtypeMixin.cpu), b2s)
+ v2._fields = {LLtypeMixin.nextdescr: b4s,
+ LLtypeMixin.valuedescr: c1s}
+ v2._cached_sorted_fields = [LLtypeMixin.nextdescr, LLtypeMixin.valuedescr]
+ v4 = VirtualValue(None, ConstAddr(LLtypeMixin.node_vtable_adr2,
+ LLtypeMixin.cpu), b4s)
+ v4._fields = {LLtypeMixin.nextdescr: b2s,
+ LLtypeMixin.valuedescr: b3s,
+ LLtypeMixin.otherdescr: b5s}
+ v4._cached_sorted_fields = [LLtypeMixin.nextdescr, LLtypeMixin.valuedescr,
+ LLtypeMixin.otherdescr]
+ modifier.register_virtual_fields(b2s, [b4s, c1s])
+ modifier.register_virtual_fields(b4s, [b2s, b3s, b5s])
+ values = {b2s: v2, b4s: v4}
liveboxes = []
- modifier._number_virtuals(liveboxes)
+ modifier._number_virtuals(liveboxes, values, 0)
storage.rd_consts = memo.consts[:]
storage.rd_numb = None
# resume
@@ -722,22 +822,25 @@
metainterp = MyMetaInterp()
reader = ResumeDataReader(storage, newboxes, metainterp)
assert len(reader.virtuals) == 2
- b2t = reader._decode_box(tag(0, TAGVIRTUAL))
- b4t = reader._decode_box(tag(1, TAGVIRTUAL))
+ b2t = reader._decode_box(modifier._gettagged(b2s))
+ b4t = reader._decode_box(modifier._gettagged(b4s))
trace = metainterp.trace
- expected = [
- (rop.NEW_WITH_VTABLE, [ConstAddr(LLtypeMixin.node_vtable_adr,
+ b2new = (rop.NEW_WITH_VTABLE, [ConstAddr(LLtypeMixin.node_vtable_adr,
LLtypeMixin.cpu)],
- b2t, None),
- (rop.NEW_WITH_VTABLE, [ConstAddr(LLtypeMixin.node_vtable_adr2,
+ b2t, None)
+ b4new = (rop.NEW_WITH_VTABLE, [ConstAddr(LLtypeMixin.node_vtable_adr2,
LLtypeMixin.cpu)],
- b4t, None),
- (rop.SETFIELD_GC, [b2t, b4t], None, LLtypeMixin.nextdescr),
- (rop.SETFIELD_GC, [b2t, c1s], None, LLtypeMixin.valuedescr),
- (rop.SETFIELD_GC, [b4t, b2t], None, LLtypeMixin.nextdescr),
- (rop.SETFIELD_GC, [b4t, b3t], None, LLtypeMixin.valuedescr),
- (rop.SETFIELD_GC, [b4t, b5t], None, LLtypeMixin.otherdescr),
- ]
+ b4t, None)
+ b2set = [(rop.SETFIELD_GC, [b2t, b4t], None, LLtypeMixin.nextdescr),
+ (rop.SETFIELD_GC, [b2t, c1s], None, LLtypeMixin.valuedescr)]
+ b4set = [(rop.SETFIELD_GC, [b4t, b2t], None, LLtypeMixin.nextdescr),
+ (rop.SETFIELD_GC, [b4t, b3t], None, LLtypeMixin.valuedescr),
+ (rop.SETFIELD_GC, [b4t, b5t], None, LLtypeMixin.otherdescr)]
+ if untag(modifier._gettagged(b2s))[0] == -2:
+ expected = [b2new, b4new] + b2set + b4set
+ else:
+ expected = [b4new, b2new] + b4set + b2set
+
for x, y in zip(expected, trace):
assert x == y
ptr = b2t.value._obj.container._as_ptr()
@@ -757,13 +860,17 @@
modifier = ResumeDataVirtualAdder(storage, memo)
modifier.liveboxes_from_env = {}
modifier.liveboxes = {}
- modifier.virtuals = []
- modifier.vfieldboxes = []
- modifier.make_varray(b2s,
- LLtypeMixin.arraydescr,
- [b4s, c1s]) # new fields
+ modifier.vfieldboxes = {}
+
+ class FakeOptimizer(object):
+ def new_const_item(self, descr):
+ return None
+ v2 = VArrayValue(FakeOptimizer(), LLtypeMixin.arraydescr, 2, b2s)
+ v2._items = [b4s, c1s]
+ modifier.register_virtual_fields(b2s, [b4s, c1s])
liveboxes = []
- modifier._number_virtuals(liveboxes)
+ values = {b2s: v2}
+ modifier._number_virtuals(liveboxes, values, 0)
dump_storage(storage, liveboxes)
storage.rd_consts = memo.consts[:]
storage.rd_numb = None
@@ -803,14 +910,13 @@
modifier = ResumeDataVirtualAdder(storage, memo)
modifier.liveboxes_from_env = {}
modifier.liveboxes = {}
- modifier.virtuals = []
- modifier.vfieldboxes = []
- modifier.make_vstruct(b2s,
- LLtypeMixin.ssize,
- [LLtypeMixin.adescr, LLtypeMixin.bdescr],
- [c1s, b4s]) # new fields
+ modifier.vfieldboxes = {}
+ v2 = VStructValue(None, LLtypeMixin.ssize, b2s)
+ v2._fields = {LLtypeMixin.adescr: c1s, LLtypeMixin.bdescr: b4s}
+ v2._cached_sorted_fields = [LLtypeMixin.adescr, LLtypeMixin.bdescr]
+ modifier.register_virtual_fields(b2s, [c1s, b4s])
liveboxes = []
- modifier._number_virtuals(liveboxes)
+ modifier._number_virtuals(liveboxes, {b2s: v2}, 0)
dump_storage(storage, liveboxes)
storage.rd_consts = memo.consts[:]
storage.rd_numb = None
Modified: pypy/branch/compress-virtuals-resumedata2/pypy/jit/metainterp/test/test_virtual.py
==============================================================================
--- pypy/branch/compress-virtuals-resumedata2/pypy/jit/metainterp/test/test_virtual.py (original)
+++ pypy/branch/compress-virtuals-resumedata2/pypy/jit/metainterp/test/test_virtual.py Mon Nov 23 11:05:16 2009
@@ -304,6 +304,8 @@
# ENTER - compile the leaving path
self.check_enter_count(4)
+class VirtualMiscTests:
+
def test_guards_around_forcing(self):
class A(object):
def __init__(self, x):
@@ -329,6 +331,29 @@
return 0
self.meta_interp(f, [50])
+ def test_guards_and_holes(self):
+ class A(object):
+ def __init__(self, x):
+ self.x = x
+ mydriver = JitDriver(reds = ['n', 'tot'], greens = [])
+
+ def f(n):
+ tot = 0
+ while n > 0:
+ mydriver.can_enter_jit(n=n, tot=tot)
+ mydriver.jit_merge_point(n=n, tot=tot)
+ a = A(n)
+ b = A(n+1)
+ if n % 9 == 0:
+ tot += (a.x + b.x) % 3
+ c = A(n+1)
+ if n % 10 == 0:
+ tot -= (c.x + a.x) % 3
+ n -= 1
+ return tot
+ r = self.meta_interp(f, [70])
+ expected = f(70)
+ assert r == expected
# ____________________________________________________________
# Run 1: all the tests instantiate a real RPython class
@@ -435,3 +460,11 @@
p = lltype.malloc(NODE2)
p.parent.typeptr = vtable2
return p
+
+# misc
+
+class TestOOTypeMisc(VirtualMiscTests, OOJitMixin):
+ pass
+
+class TestLLTypeMisc(VirtualMiscTests, LLJitMixin):
+ pass
More information about the Pypy-commit
mailing list