aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHakan Ardo <hakan@debian.org>2010-11-17 19:41:25 +0000
committerHakan Ardo <hakan@debian.org>2010-11-17 19:41:25 +0000
commitbaf678c574081d15f0e409eb8d004c76e87b95c2 (patch)
tree1b7f8e03b86f24a6c8a44ece82fcdb6e5602fce4 /pypy/jit/metainterp
parentBetter name (diff)
downloadpypy-baf678c574081d15f0e409eb8d004c76e87b95c2.tar.gz
pypy-baf678c574081d15f0e409eb8d004c76e87b95c2.tar.bz2
pypy-baf678c574081d15f0e409eb8d004c76e87b95c2.zip
svn merge -r78744:HEAD svn+ssh://hakanardo@codespeak.net/svn/pypy/trunk
Diffstat (limited to 'pypy/jit/metainterp')
-rw-r--r--pypy/jit/metainterp/blackhole.py4
-rw-r--r--pypy/jit/metainterp/compile.py30
-rw-r--r--pypy/jit/metainterp/logger.py3
-rw-r--r--pypy/jit/metainterp/optimizeopt/optimizer.py6
-rw-r--r--pypy/jit/metainterp/optimizeopt/string.py5
-rw-r--r--pypy/jit/metainterp/pyjitpl.py39
-rw-r--r--pypy/jit/metainterp/resoperation.py20
-rw-r--r--pypy/jit/metainterp/resume.py125
-rw-r--r--pypy/jit/metainterp/test/test_basic.py26
-rw-r--r--pypy/jit/metainterp/test/test_compile.py4
-rw-r--r--pypy/jit/metainterp/test/test_del.py9
-rw-r--r--pypy/jit/metainterp/test/test_logger.py2
-rw-r--r--pypy/jit/metainterp/test/test_oparser.py205
-rw-r--r--pypy/jit/metainterp/test/test_optimizeopt.py128
-rw-r--r--pypy/jit/metainterp/test/test_resoperation.py7
-rw-r--r--pypy/jit/metainterp/test/test_resume.py65
-rw-r--r--pypy/jit/metainterp/test/test_virtualref.py6
-rw-r--r--pypy/jit/metainterp/test/test_ztranslation.py4
-rw-r--r--pypy/jit/metainterp/virtualizable.py18
-rw-r--r--pypy/jit/metainterp/warmspot.py3
20 files changed, 337 insertions, 372 deletions
diff --git a/pypy/jit/metainterp/blackhole.py b/pypy/jit/metainterp/blackhole.py
index 700280971b..c67dc8b2fa 100644
--- a/pypy/jit/metainterp/blackhole.py
+++ b/pypy/jit/metainterp/blackhole.py
@@ -774,6 +774,10 @@ class BlackholeInterpreter(object):
def bhimpl_float_assert_green(x):
pass
+ @arguments(returns="i")
+ def bhimpl_current_trace_length():
+ return -1
+
# ----------
# the main hints and recursive calls
diff --git a/pypy/jit/metainterp/compile.py b/pypy/jit/metainterp/compile.py
index 31df49b3ff..342898daab 100644
--- a/pypy/jit/metainterp/compile.py
+++ b/pypy/jit/metainterp/compile.py
@@ -1,4 +1,5 @@
+from pypy.rpython.lltypesystem import lltype
from pypy.rpython.ootypesystem import ootype
from pypy.objspace.flow.model import Constant, Variable
from pypy.rlib.objectmodel import we_are_translated
@@ -13,6 +14,7 @@ from pypy.jit.metainterp.history import BoxPtr, BoxObj, BoxFloat, Const
from pypy.jit.metainterp import history
from pypy.jit.metainterp.typesystem import llhelper, oohelper
from pypy.jit.metainterp.optimizeutil import InvalidLoop
+from pypy.jit.metainterp.resume import NUMBERING
from pypy.jit.codewriter import heaptracker
def giveup():
@@ -52,7 +54,6 @@ def compile_new_loop(metainterp, old_loop_tokens, greenkey, start):
"""
history = metainterp.history
loop = create_empty_loop(metainterp)
- loop.greenkey = greenkey
loop.inputargs = history.inputargs
for box in loop.inputargs:
assert isinstance(box, Box)
@@ -66,7 +67,6 @@ def compile_new_loop(metainterp, old_loop_tokens, greenkey, start):
loop.operations[-1].setdescr(loop_token) # patch the target of the JUMP
loop.preamble = create_empty_loop(metainterp, 'Preamble ')
- loop.preamble.greenkey = greenkey
loop.preamble.inputargs = loop.inputargs
loop.preamble.token = make_loop_token(len(loop.inputargs), jitdriver_sd)
@@ -214,8 +214,7 @@ def make_done_loop_tokens():
}
class ResumeDescr(AbstractFailDescr):
- def __init__(self, original_greenkey):
- self.original_greenkey = original_greenkey
+ pass
class ResumeGuardDescr(ResumeDescr):
_counter = 0 # if < 0, there is one counter per value;
@@ -224,7 +223,7 @@ class ResumeGuardDescr(ResumeDescr):
# this class also gets the following attributes stored by resume.py code
rd_snapshot = None
rd_frame_info_list = None
- rd_numb = None
+ rd_numb = lltype.nullptr(NUMBERING)
rd_consts = None
rd_virtuals = None
rd_pendingfields = None
@@ -234,8 +233,7 @@ class ResumeGuardDescr(ResumeDescr):
CNT_FLOAT = -0x60000000
CNT_MASK = 0x1FFFFFFF
- def __init__(self, metainterp_sd, original_greenkey):
- ResumeDescr.__init__(self, original_greenkey)
+ def __init__(self, metainterp_sd):
self.metainterp_sd = metainterp_sd
def store_final_boxes(self, guard_op, boxes):
@@ -339,14 +337,14 @@ class ResumeGuardDescr(ResumeDescr):
res.rd_pendingfields = self.rd_pendingfields
def _clone_if_mutable(self):
- res = ResumeGuardDescr(self.metainterp_sd, self.original_greenkey)
+ res = ResumeGuardDescr(self.metainterp_sd)
self.copy_all_attrbutes_into(res)
return res
class ResumeGuardForcedDescr(ResumeGuardDescr):
- def __init__(self, metainterp_sd, original_greenkey, jitdriver_sd):
- ResumeGuardDescr.__init__(self, metainterp_sd, original_greenkey)
+ def __init__(self, metainterp_sd, jitdriver_sd):
+ ResumeGuardDescr.__init__(self, metainterp_sd)
self.jitdriver_sd = jitdriver_sd
def handle_fail(self, metainterp_sd, jitdriver_sd):
@@ -413,7 +411,6 @@ class ResumeGuardForcedDescr(ResumeGuardDescr):
def _clone_if_mutable(self):
res = ResumeGuardForcedDescr(self.metainterp_sd,
- self.original_greenkey,
self.jitdriver_sd)
self.copy_all_attrbutes_into(res)
return res
@@ -480,9 +477,8 @@ class ResumeGuardCountersFloat(AbstractResumeGuardCounters):
class ResumeFromInterpDescr(ResumeDescr):
- def __init__(self, original_greenkey, redkey):
- ResumeDescr.__init__(self, original_greenkey)
- self.redkey = redkey
+ def __init__(self, original_greenkey):
+ self.original_greenkey = original_greenkey
def compile_and_attach(self, metainterp, new_loop):
# We managed to create a bridge going from the interpreter
@@ -491,10 +487,8 @@ class ResumeFromInterpDescr(ResumeDescr):
# with completely unoptimized arguments, as in the interpreter.
metainterp_sd = metainterp.staticdata
jitdriver_sd = metainterp.jitdriver_sd
- metainterp.history.inputargs = self.redkey
- new_loop_token = make_loop_token(len(self.redkey), jitdriver_sd)
- new_loop.greenkey = self.original_greenkey
- new_loop.inputargs = self.redkey
+ redargs = new_loop.inputargs
+ new_loop_token = make_loop_token(len(redargs), jitdriver_sd)
new_loop.token = new_loop_token
send_loop_to_backend(metainterp_sd, new_loop, "entry bridge")
# send the new_loop to warmspot.py, to be called directly the next time
diff --git a/pypy/jit/metainterp/logger.py b/pypy/jit/metainterp/logger.py
index 189462f3b5..898e1b4ff8 100644
--- a/pypy/jit/metainterp/logger.py
+++ b/pypy/jit/metainterp/logger.py
@@ -81,7 +81,8 @@ class Logger(object):
op = operations[i]
if op.getopnum() == rop.DEBUG_MERGE_POINT:
loc = op.getarg(0)._get_str()
- debug_print("debug_merge_point('%s')" % (loc,))
+ reclev = op.getarg(1).getint()
+ debug_print("debug_merge_point('%s', %s)" % (loc, reclev))
continue
args = ", ".join([self.repr_of_arg(memo, op.getarg(i)) for i in range(op.numargs())])
if op.result is not None:
diff --git a/pypy/jit/metainterp/optimizeopt/optimizer.py b/pypy/jit/metainterp/optimizeopt/optimizer.py
index 2bf3551380..cbceaf4b42 100644
--- a/pypy/jit/metainterp/optimizeopt/optimizer.py
+++ b/pypy/jit/metainterp/optimizeopt/optimizer.py
@@ -86,10 +86,10 @@ class OptValue(object):
assert isinstance(constbox, Const)
self.box = constbox
self.level = LEVEL_CONSTANT
- try:
- val = self.box.getint()
+ if isinstance(constbox, ConstInt):
+ val = constbox.getint()
self.intbound = IntBound(val, val)
- except NotImplementedError:
+ else:
self.intbound = IntUnbounded()
def get_constant_class(self, cpu):
diff --git a/pypy/jit/metainterp/optimizeopt/string.py b/pypy/jit/metainterp/optimizeopt/string.py
index 949d0b63b9..6680885490 100644
--- a/pypy/jit/metainterp/optimizeopt/string.py
+++ b/pypy/jit/metainterp/optimizeopt/string.py
@@ -9,7 +9,7 @@ from pypy.jit.metainterp.optimizeopt import optimizer, virtualize
from pypy.jit.metainterp.optimizeopt.optimizer import CONST_0, CONST_1
from pypy.jit.metainterp.optimizeopt.optimizer import llhelper
from pypy.jit.metainterp.optimizeutil import _findall
-from pypy.jit.codewriter.effectinfo import EffectInfo, callinfo_for_oopspec
+from pypy.jit.codewriter.effectinfo import EffectInfo
from pypy.jit.codewriter import heaptracker
from pypy.rlib.unroll import unrolling_iterable
from pypy.rlib.objectmodel import specialize, we_are_translated
@@ -642,7 +642,8 @@ class OptString(optimizer.Optimization):
def generate_modified_call(self, oopspecindex, args, result, mode):
oopspecindex += mode.OS_offset
- calldescr, func = callinfo_for_oopspec(oopspecindex)
+ cic = self.optimizer.metainterp_sd.callinfocollection
+ calldescr, func = cic.callinfo_for_oopspec(oopspecindex)
op = ResOperation(rop.CALL, [ConstInt(func)] + args, result,
descr=calldescr)
self.optimizer.newoperations.append(op)
diff --git a/pypy/jit/metainterp/pyjitpl.py b/pypy/jit/metainterp/pyjitpl.py
index 35b8fc0360..abb8fc84d3 100644
--- a/pypy/jit/metainterp/pyjitpl.py
+++ b/pypy/jit/metainterp/pyjitpl.py
@@ -14,7 +14,7 @@ from pypy.jit.metainterp import executor
from pypy.jit.metainterp.logger import Logger
from pypy.jit.metainterp.jitprof import EmptyProfiler
from pypy.jit.metainterp.jitprof import GUARDS, RECORDED_OPS, ABORT_ESCAPE
-from pypy.jit.metainterp.jitprof import ABORT_TOO_LONG, ABORT_BRIDGE
+from pypy.jit.metainterp.jitprof import ABORT_TOO_LONG
from pypy.jit.metainterp.jitexc import JitException, get_llexception
from pypy.rlib.rarithmetic import intmask
from pypy.rlib.objectmodel import specialize
@@ -820,7 +820,8 @@ class MIFrame(object):
jitdriver_sd = self.metainterp.staticdata.jitdrivers_sd[jdindex]
self.verify_green_args(jitdriver_sd, greenboxes)
# xxx we may disable the following line in some context later
- self.debug_merge_point(jitdriver_sd, greenboxes)
+ self.debug_merge_point(jitdriver_sd, self.metainterp.in_recursion,
+ greenboxes)
if self.metainterp.seen_loop_header_for_jdindex < 0:
if not jitdriver_sd.no_loop_header or not any_operation:
return
@@ -860,13 +861,13 @@ class MIFrame(object):
assembler_call=True)
raise ChangeFrame
- def debug_merge_point(self, jitdriver_sd, greenkey):
+ def debug_merge_point(self, jitdriver_sd, in_recursion, greenkey):
# debugging: produce a DEBUG_MERGE_POINT operation
loc = jitdriver_sd.warmstate.get_location_str(greenkey)
debug_print(loc)
constloc = self.metainterp.cpu.ts.conststr(loc)
self.metainterp.history.record(rop.DEBUG_MERGE_POINT,
- [constloc], None)
+ [constloc, ConstInt(in_recursion)], None)
@arguments("box", "label")
def opimpl_goto_if_exception_mismatch(self, vtablebox, next_exc_target):
@@ -948,6 +949,11 @@ class MIFrame(object):
opimpl_ref_assert_green = _opimpl_assert_green
opimpl_float_assert_green = _opimpl_assert_green
+ @arguments()
+ def opimpl_current_trace_length(self):
+ trace_length = len(self.metainterp.history.operations)
+ return ConstInt(trace_length)
+
@arguments("box")
def opimpl_virtual_ref(self, box):
# Details on the content of metainterp.virtualref_boxes:
@@ -1042,14 +1048,11 @@ class MIFrame(object):
else:
moreargs = list(extraargs)
metainterp_sd = metainterp.staticdata
- original_greenkey = metainterp.resumekey.original_greenkey
if opnum == rop.GUARD_NOT_FORCED:
resumedescr = compile.ResumeGuardForcedDescr(metainterp_sd,
- original_greenkey,
metainterp.jitdriver_sd)
else:
- resumedescr = compile.ResumeGuardDescr(metainterp_sd,
- original_greenkey)
+ resumedescr = compile.ResumeGuardDescr(metainterp_sd)
guard_op = metainterp.history.record(opnum, moreargs, None,
descr=resumedescr)
virtualizable_boxes = None
@@ -1255,6 +1258,7 @@ class MetaInterpStaticData(object):
#
self.jitdrivers_sd = codewriter.callcontrol.jitdrivers_sd
self.virtualref_info = codewriter.callcontrol.virtualref_info
+ self.callinfocollection = codewriter.callcontrol.callinfocollection
self.setup_jitdrivers_sd(optimizer)
#
# store this information for fastpath of call_assembler
@@ -1618,7 +1622,7 @@ class MetaInterp(object):
assert jitdriver_sd is self.jitdriver_sd
self.create_empty_history()
try:
- original_boxes = self.initialize_original_boxes(jitdriver_sd,*args)
+ original_boxes = self.initialize_original_boxes(jitdriver_sd, *args)
return self._compile_and_run_once(original_boxes)
finally:
self.staticdata.profiler.end_tracing()
@@ -1629,9 +1633,8 @@ class MetaInterp(object):
self.current_merge_points = [(original_boxes, 0)]
num_green_args = self.jitdriver_sd.num_green_args
original_greenkey = original_boxes[:num_green_args]
- redkey = original_boxes[num_green_args:]
- self.resumekey = compile.ResumeFromInterpDescr(original_greenkey,
- redkey)
+ self.resumekey = compile.ResumeFromInterpDescr(original_greenkey)
+ self.history.inputargs = original_boxes[num_green_args:]
self.seen_loop_header_for_jdindex = -1
try:
self.interpret()
@@ -1653,11 +1656,7 @@ class MetaInterp(object):
debug_stop('jit-tracing')
def _handle_guard_failure(self, key):
- original_greenkey = key.original_greenkey
- # notice that here we just put the greenkey
- # use -1 to mark that we will have to give up
- # because we cannot reconstruct the beginning of the proper loop
- self.current_merge_points = [(original_greenkey, -1)]
+ self.current_merge_points = []
self.resumekey = key
self.seen_loop_header_for_jdindex = -1
try:
@@ -1721,7 +1720,7 @@ class MetaInterp(object):
num_green_args = self.jitdriver_sd.num_green_args
for j in range(len(self.current_merge_points)-1, -1, -1):
original_boxes, start = self.current_merge_points[j]
- assert len(original_boxes) == len(live_arg_boxes) or start < 0
+ assert len(original_boxes) == len(live_arg_boxes)
for i in range(num_green_args):
box1 = original_boxes[i]
box2 = live_arg_boxes[i]
@@ -1730,10 +1729,6 @@ class MetaInterp(object):
break
else:
# Found! Compile it as a loop.
- if start < 0:
- # we cannot reconstruct the beginning of the proper loop
- raise SwitchToBlackhole(ABORT_BRIDGE)
-
# raises in case it works -- which is the common case
self.compile(original_boxes, live_arg_boxes, start)
# creation of the loop was cancelled!
diff --git a/pypy/jit/metainterp/resoperation.py b/pypy/jit/metainterp/resoperation.py
index eea9079a9a..08e2e7126c 100644
--- a/pypy/jit/metainterp/resoperation.py
+++ b/pypy/jit/metainterp/resoperation.py
@@ -143,6 +143,16 @@ class AbstractResOp(object):
def can_raise(self):
return rop._CANRAISE_FIRST <= self.getopnum() <= rop._CANRAISE_LAST
+ def is_malloc(self):
+ # a slightly different meaning from can_malloc
+ return rop._MALLOC_FIRST <= self.getopnum() <= rop._MALLOC_LAST
+
+ def can_malloc(self):
+ return self.is_call() or self.is_malloc()
+
+ def is_call(self):
+ return rop._CALL_FIRST <= self.getopnum() <= rop._CALL_LAST
+
def is_ovf(self):
return rop._OVF_FIRST <= self.getopnum() <= rop._OVF_LAST
@@ -441,9 +451,13 @@ _oplist = [
'GETARRAYITEM_RAW/2d',
'GETFIELD_GC/1d',
'GETFIELD_RAW/1d',
+ '_MALLOC_FIRST',
'NEW/0d',
'NEW_WITH_VTABLE/1',
'NEW_ARRAY/1d',
+ 'NEWSTR/1',
+ 'NEWUNICODE/1',
+ '_MALLOC_LAST',
'FORCE_TOKEN/0',
'VIRTUAL_REF/2', # removed before it's passed to the backend
'_NOSIDEEFFECT_LAST', # ----- end of no_side_effect operations -----
@@ -452,19 +466,18 @@ _oplist = [
'SETARRAYITEM_RAW/3d',
'SETFIELD_GC/2d',
'SETFIELD_RAW/2d',
- 'NEWSTR/1',
'STRSETITEM/3',
'UNICODESETITEM/3',
- 'NEWUNICODE/1',
#'RUNTIMENEW/1', # ootype operation
'COND_CALL_GC_WB/2d', # [objptr, newvalue] (for the write barrier)
- 'DEBUG_MERGE_POINT/1', # debugging only
+ 'DEBUG_MERGE_POINT/2', # debugging only
'JIT_DEBUG/*', # debugging only
'VIRTUAL_REF_FINISH/2', # removed before it's passed to the backend
'COPYSTRCONTENT/5', # src, dst, srcstart, dststart, length
'COPYUNICODECONTENT/5',
'_CANRAISE_FIRST', # ----- start of can_raise operations -----
+ '_CALL_FIRST',
'CALL/*d',
'CALL_ASSEMBLER/*d', # call already compiled assembler
'CALL_MAY_FORCE/*d',
@@ -473,6 +486,7 @@ _oplist = [
#'OOSEND_PURE', # ootype operation
'CALL_PURE/*d', # removed before it's passed to the backend
# CALL_PURE(result, func, arg_1,..,arg_n)
+ '_CALL_LAST',
'_CANRAISE_LAST', # ----- end of can_raise operations -----
'_OVF_FIRST', # ----- start of is_ovf operations -----
diff --git a/pypy/jit/metainterp/resume.py b/pypy/jit/metainterp/resume.py
index 338bba1065..89a5d28354 100644
--- a/pypy/jit/metainterp/resume.py
+++ b/pypy/jit/metainterp/resume.py
@@ -4,8 +4,7 @@ from pypy.jit.metainterp.history import BoxInt, BoxPtr, BoxFloat
from pypy.jit.metainterp.history import INT, REF, FLOAT, HOLE
from pypy.jit.metainterp.resoperation import rop
from pypy.jit.metainterp import jitprof
-from pypy.jit.codewriter.effectinfo import EffectInfo, callinfo_for_oopspec
-from pypy.jit.codewriter.effectinfo import funcptr_for_oopspec
+from pypy.jit.codewriter.effectinfo import EffectInfo
from pypy.rpython.lltypesystem import lltype, llmemory, rffi, rstr
from pypy.rlib import rarithmetic
from pypy.rlib.objectmodel import we_are_translated, specialize
@@ -66,12 +65,21 @@ def capture_resumedata(framestack, virtualizable_boxes, virtualref_boxes,
snapshot = Snapshot(snapshot, boxes)
storage.rd_snapshot = snapshot
-class Numbering(object):
- __slots__ = ('prev', 'nums')
-
- def __init__(self, prev, nums):
- self.prev = prev
- self.nums = nums
+#
+# The following is equivalent to the RPython-level declaration:
+#
+# class Numbering: __slots__ = ['prev', 'nums']
+#
+# except that it is more compact in translated programs, because the
+# array 'nums' is inlined in the single NUMBERING object. This is
+# important because this is often the biggest single consumer of memory
+# in a pypy-c-jit.
+#
+NUMBERINGP = lltype.Ptr(lltype.GcForwardReference())
+NUMBERING = lltype.GcStruct('Numbering',
+ ('prev', NUMBERINGP),
+ ('nums', lltype.Array(rffi.SHORT)))
+NUMBERINGP.TO.become(NUMBERING)
TAGMASK = 3
@@ -163,7 +171,7 @@ class ResumeDataLoopMemo(object):
def number(self, values, snapshot):
if snapshot is None:
- return None, {}, 0
+ return lltype.nullptr(NUMBERING), {}, 0
if snapshot in self.numberings:
numb, liveboxes, v = self.numberings[snapshot]
return numb, liveboxes.copy(), v
@@ -172,7 +180,7 @@ class ResumeDataLoopMemo(object):
n = len(liveboxes)-v
boxes = snapshot.boxes
length = len(boxes)
- nums = [UNASSIGNED] * length
+ numb = lltype.malloc(NUMBERING, length)
for i in range(length):
box = boxes[i]
value = values.get(box, None)
@@ -191,9 +199,9 @@ class ResumeDataLoopMemo(object):
tagged = tag(n, TAGBOX)
n += 1
liveboxes[box] = tagged
- nums[i] = tagged
+ numb.nums[i] = tagged
#
- numb = Numbering(numb1, nums)
+ numb.prev = numb1
self.numberings[snapshot] = numb, liveboxes, v
return numb, liveboxes.copy(), v
@@ -298,7 +306,7 @@ class ResumeDataVirtualAdder(object):
# compute the numbering
storage = self.storage
# make sure that nobody attached resume data to this guard yet
- assert storage.rd_numb is None
+ assert not storage.rd_numb
snapshot = storage.rd_snapshot
assert snapshot is not None # is that true?
numb, liveboxes_from_env, v = self.memo.number(values, snapshot)
@@ -724,34 +732,36 @@ class ResumeDataBoxReader(AbstractResumeDataReader):
self.boxes_f = boxes_f
self._prepare_next_section(info)
- def consume_virtualizable_boxes(self, vinfo, nums):
+ def consume_virtualizable_boxes(self, vinfo, numb):
# we have to ignore the initial part of 'nums' (containing vrefs),
# find the virtualizable from nums[-1], and use it to know how many
# boxes of which type we have to return. This does not write
# anything into the virtualizable.
- virtualizablebox = self.decode_ref(nums[-1])
+ index = len(numb.nums) - 1
+ virtualizablebox = self.decode_ref(numb.nums[index])
virtualizable = vinfo.unwrap_virtualizable_box(virtualizablebox)
- return vinfo.load_list_of_boxes(virtualizable, self, nums)
+ return vinfo.load_list_of_boxes(virtualizable, self, numb)
- def consume_virtualref_boxes(self, nums, end):
+ def consume_virtualref_boxes(self, numb, end):
# Returns a list of boxes, assumed to be all BoxPtrs.
# We leave up to the caller to call vrefinfo.continue_tracing().
assert (end & 1) == 0
- return [self.decode_ref(nums[i]) for i in range(end)]
+ return [self.decode_ref(numb.nums[i]) for i in range(end)]
def consume_vref_and_vable_boxes(self, vinfo, ginfo):
- nums = self.cur_numb.nums
- self.cur_numb = self.cur_numb.prev
+ numb = self.cur_numb
+ self.cur_numb = numb.prev
if vinfo is not None:
- virtualizable_boxes = self.consume_virtualizable_boxes(vinfo, nums)
- end = len(nums) - len(virtualizable_boxes)
+ virtualizable_boxes = self.consume_virtualizable_boxes(vinfo, numb)
+ end = len(numb.nums) - len(virtualizable_boxes)
elif ginfo is not None:
- virtualizable_boxes = [self.decode_ref(nums[-1])]
- end = len(nums) - 1
+ index = len(numb.nums) - 1
+ virtualizable_boxes = [self.decode_ref(numb.nums[index])]
+ end = len(numb.nums) - 1
else:
virtualizable_boxes = None
- end = len(nums)
- virtualref_boxes = self.consume_virtualref_boxes(nums, end)
+ end = len(numb.nums)
+ virtualref_boxes = self.consume_virtualref_boxes(numb, end)
return virtualizable_boxes, virtualref_boxes
def allocate_with_vtable(self, known_class):
@@ -775,14 +785,16 @@ class ResumeDataBoxReader(AbstractResumeDataReader):
strbox, ConstInt(index), charbox)
def concat_strings(self, str1num, str2num):
- calldescr, func = callinfo_for_oopspec(EffectInfo.OS_STR_CONCAT)
+ cic = self.metainterp.staticdata.callinfocollection
+ calldescr, func = cic.callinfo_for_oopspec(EffectInfo.OS_STR_CONCAT)
str1box = self.decode_box(str1num, REF)
str2box = self.decode_box(str2num, REF)
return self.metainterp.execute_and_record_varargs(
rop.CALL, [ConstInt(func), str1box, str2box], calldescr)
def slice_string(self, strnum, startnum, lengthnum):
- calldescr, func = callinfo_for_oopspec(EffectInfo.OS_STR_SLICE)
+ cic = self.metainterp.staticdata.callinfocollection
+ calldescr, func = cic.callinfo_for_oopspec(EffectInfo.OS_STR_SLICE)
strbox = self.decode_box(strnum, REF)
startbox = self.decode_box(startnum, INT)
lengthbox = self.decode_box(lengthnum, INT)
@@ -801,14 +813,16 @@ class ResumeDataBoxReader(AbstractResumeDataReader):
strbox, ConstInt(index), charbox)
def concat_unicodes(self, str1num, str2num):
- calldescr, func = callinfo_for_oopspec(EffectInfo.OS_UNI_CONCAT)
+ cic = self.metainterp.staticdata.callinfocollection
+ calldescr, func = cic.callinfo_for_oopspec(EffectInfo.OS_UNI_CONCAT)
str1box = self.decode_box(str1num, REF)
str2box = self.decode_box(str2num, REF)
return self.metainterp.execute_and_record_varargs(
rop.CALL, [ConstInt(func), str1box, str2box], calldescr)
def slice_unicode(self, strnum, startnum, lengthnum):
- calldescr, func = callinfo_for_oopspec(EffectInfo.OS_UNI_SLICE)
+ cic = self.metainterp.staticdata.callinfocollection
+ calldescr, func = cic.callinfo_for_oopspec(EffectInfo.OS_UNI_SLICE)
strbox = self.decode_box(strnum, REF)
startbox = self.decode_box(startnum, INT)
lengthbox = self.decode_box(lengthnum, INT)
@@ -904,8 +918,8 @@ class ResumeDataBoxReader(AbstractResumeDataReader):
def blackhole_from_resumedata(blackholeinterpbuilder, jitdriver_sd, storage,
all_virtuals=None):
- resumereader = ResumeDataDirectReader(blackholeinterpbuilder.cpu, storage,
- all_virtuals)
+ resumereader = ResumeDataDirectReader(blackholeinterpbuilder.metainterp_sd,
+ storage, all_virtuals)
vinfo = jitdriver_sd.virtualizable_info
ginfo = jitdriver_sd.greenfield_info
vrefinfo = blackholeinterpbuilder.metainterp_sd.virtualref_info
@@ -940,7 +954,7 @@ def blackhole_from_resumedata(blackholeinterpbuilder, jitdriver_sd, storage,
return firstbh
def force_from_resumedata(metainterp_sd, storage, vinfo, ginfo):
- resumereader = ResumeDataDirectReader(metainterp_sd.cpu, storage)
+ resumereader = ResumeDataDirectReader(metainterp_sd, storage)
resumereader.handling_async_forcing()
vrefinfo = metainterp_sd.virtualref_info
resumereader.consume_vref_and_vable(vrefinfo, vinfo, ginfo)
@@ -954,8 +968,9 @@ class ResumeDataDirectReader(AbstractResumeDataReader):
# 1: in handle_async_forcing
# 2: resuming from the GUARD_NOT_FORCED
- def __init__(self, cpu, storage, all_virtuals=None):
- self._init(cpu, storage)
+ def __init__(self, metainterp_sd, storage, all_virtuals=None):
+ self._init(metainterp_sd.cpu, storage)
+ self.callinfocollection = metainterp_sd.callinfocollection
if all_virtuals is None: # common case
self._prepare(storage)
else:
@@ -974,23 +989,24 @@ class ResumeDataDirectReader(AbstractResumeDataReader):
info = blackholeinterp.get_current_position_info()
self._prepare_next_section(info)
- def consume_virtualref_info(self, vrefinfo, nums, end):
+ def consume_virtualref_info(self, vrefinfo, numb, end):
# we have to decode a list of references containing pairs
# [..., virtual, vref, ...] stopping at 'end'
assert (end & 1) == 0
for i in range(0, end, 2):
- virtual = self.decode_ref(nums[i])
- vref = self.decode_ref(nums[i+1])
+ virtual = self.decode_ref(numb.nums[i])
+ vref = self.decode_ref(numb.nums[i+1])
# For each pair, we store the virtual inside the vref.
vrefinfo.continue_tracing(vref, virtual)
- def consume_vable_info(self, vinfo, nums):
+ def consume_vable_info(self, vinfo, numb):
# we have to ignore the initial part of 'nums' (containing vrefs),
# find the virtualizable from nums[-1], load all other values
# from the CPU stack, and copy them into the virtualizable
if vinfo is None:
- return len(nums)
- virtualizable = self.decode_ref(nums[-1])
+ return len(numb.nums)
+ index = len(numb.nums) - 1
+ virtualizable = self.decode_ref(numb.nums[index])
virtualizable = vinfo.cast_gcref_to_vtype(virtualizable)
if self.resume_after_guard_not_forced == 1:
# in the middle of handle_async_forcing()
@@ -1002,7 +1018,7 @@ class ResumeDataDirectReader(AbstractResumeDataReader):
# is and stays 0. Note the call to reset_vable_token() in
# warmstate.py.
assert not virtualizable.vable_token
- return vinfo.write_from_resume_data_partial(virtualizable, self, nums)
+ return vinfo.write_from_resume_data_partial(virtualizable, self, numb)
def load_value_of_type(self, TYPE, tagged):
from pypy.jit.metainterp.warmstate import specialize_value
@@ -1019,12 +1035,12 @@ class ResumeDataDirectReader(AbstractResumeDataReader):
load_value_of_type._annspecialcase_ = 'specialize:arg(1)'
def consume_vref_and_vable(self, vrefinfo, vinfo, ginfo):
- nums = self.cur_numb.nums
- self.cur_numb = self.cur_numb.prev
+ numb = self.cur_numb
+ self.cur_numb = numb.prev
if self.resume_after_guard_not_forced != 2:
- end_vref = self.consume_vable_info(vinfo, nums)
+ end_vref = self.consume_vable_info(vinfo, numb)
if ginfo is not None: end_vref -= 1
- self.consume_virtualref_info(vrefinfo, nums, end_vref)
+ self.consume_virtualref_info(vrefinfo, numb, end_vref)
def allocate_with_vtable(self, known_class):
from pypy.jit.metainterp.executor import exec_new_with_vtable
@@ -1048,7 +1064,8 @@ class ResumeDataDirectReader(AbstractResumeDataReader):
str2 = self.decode_ref(str2num)
str1 = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), str1)
str2 = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), str2)
- funcptr = funcptr_for_oopspec(EffectInfo.OS_STR_CONCAT)
+ cic = self.callinfocollection
+ funcptr = cic.funcptr_for_oopspec(EffectInfo.OS_STR_CONCAT)
result = funcptr(str1, str2)
return lltype.cast_opaque_ptr(llmemory.GCREF, result)
@@ -1057,7 +1074,8 @@ class ResumeDataDirectReader(AbstractResumeDataReader):
start = self.decode_int(startnum)
length = self.decode_int(lengthnum)
str = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), str)
- funcptr = funcptr_for_oopspec(EffectInfo.OS_STR_SLICE)
+ cic = self.callinfocollection
+ funcptr = cic.funcptr_for_oopspec(EffectInfo.OS_STR_SLICE)
result = funcptr(str, start, start + length)
return lltype.cast_opaque_ptr(llmemory.GCREF, result)
@@ -1073,7 +1091,8 @@ class ResumeDataDirectReader(AbstractResumeDataReader):
str2 = self.decode_ref(str2num)
str1 = lltype.cast_opaque_ptr(lltype.Ptr(rstr.UNICODE), str1)
str2 = lltype.cast_opaque_ptr(lltype.Ptr(rstr.UNICODE), str2)
- funcptr = funcptr_for_oopspec(EffectInfo.OS_UNI_CONCAT)
+ cic = self.callinfocollection
+ funcptr = cic.funcptr_for_oopspec(EffectInfo.OS_UNI_CONCAT)
result = funcptr(str1, str2)
return lltype.cast_opaque_ptr(llmemory.GCREF, result)
@@ -1082,7 +1101,8 @@ class ResumeDataDirectReader(AbstractResumeDataReader):
start = self.decode_int(startnum)
length = self.decode_int(lengthnum)
str = lltype.cast_opaque_ptr(lltype.Ptr(rstr.UNICODE), str)
- funcptr = funcptr_for_oopspec(EffectInfo.OS_UNI_SLICE)
+ cic = self.callinfocollection
+ funcptr = cic.funcptr_for_oopspec(EffectInfo.OS_UNI_SLICE)
result = funcptr(str, start, start + length)
return lltype.cast_opaque_ptr(llmemory.GCREF, result)
@@ -1173,8 +1193,9 @@ def dump_storage(storage, liveboxes):
'at', compute_unique_id(frameinfo))
frameinfo = frameinfo.prev
numb = storage.rd_numb
- while numb is not None:
- debug_print('\tnumb', str([untag(i) for i in numb.nums]),
+ while numb:
+ debug_print('\tnumb', str([untag(numb.nums[i])
+ for i in range(len(numb.nums))]),
'at', compute_unique_id(numb))
numb = numb.prev
for const in storage.rd_consts:
diff --git a/pypy/jit/metainterp/test/test_basic.py b/pypy/jit/metainterp/test/test_basic.py
index 6b994f5d75..a96440a7bf 100644
--- a/pypy/jit/metainterp/test/test_basic.py
+++ b/pypy/jit/metainterp/test/test_basic.py
@@ -3,6 +3,7 @@ import sys
from pypy.rlib.jit import JitDriver, we_are_jitted, hint, dont_look_inside
from pypy.rlib.jit import OPTIMIZER_FULL, OPTIMIZER_SIMPLE, loop_invariant
from pypy.rlib.jit import jit_debug, assert_green, AssertGreenFailed
+from pypy.rlib.jit import unroll_safe, current_trace_length
from pypy.jit.metainterp.warmspot import ll_meta_interp, get_stats
from pypy.jit.backend.llgraph import runner
from pypy.jit.metainterp import pyjitpl, history
@@ -1837,6 +1838,31 @@ class BasicTests:
'int_add': 1, 'int_mul': 1, 'int_sub': 2,
'int_gt': 2, 'jump': 2})
+ def test_current_trace_length(self):
+ myjitdriver = JitDriver(greens = ['g'], reds = ['x'])
+ @dont_look_inside
+ def residual():
+ print "hi there"
+ @unroll_safe
+ def loop(g):
+ y = 0
+ while y < g:
+ residual()
+ y += 1
+ def f(x, g):
+ n = 0
+ while x > 0:
+ myjitdriver.can_enter_jit(x=x, g=g)
+ myjitdriver.jit_merge_point(x=x, g=g)
+ loop(g)
+ x -= 1
+ n = current_trace_length()
+ return n
+ res = self.meta_interp(f, [5, 8])
+ assert 14 < res < 42
+ res = self.meta_interp(f, [5, 2])
+ assert 4 < res < 14
+
class TestOOtype(BasicTests, OOJitMixin):
diff --git a/pypy/jit/metainterp/test/test_compile.py b/pypy/jit/metainterp/test/test_compile.py
index 98edd3f7e8..cddc61080a 100644
--- a/pypy/jit/metainterp/test/test_compile.py
+++ b/pypy/jit/metainterp/test/test_compile.py
@@ -85,7 +85,7 @@ def test_compile_new_loop():
metainterp.history.inputargs = loop.inputargs[:]
#
loop_tokens = []
- loop_token = compile_new_loop(metainterp, loop_tokens, [], 0)
+ loop_token = compile_new_loop(metainterp, loop_tokens, 0)
assert loop_tokens == [loop_token]
assert loop_token.number == 1
assert staticdata.globaldata.loopnumbering == 2
@@ -101,7 +101,7 @@ def test_compile_new_loop():
metainterp.history.operations = loop.operations[:]
metainterp.history.inputargs = loop.inputargs[:]
#
- loop_token_2 = compile_new_loop(metainterp, loop_tokens, [], 0)
+ loop_token_2 = compile_new_loop(metainterp, loop_tokens, 0)
assert loop_token_2 is loop_token
assert loop_tokens == [loop_token]
assert len(cpu.seen) == 0
diff --git a/pypy/jit/metainterp/test/test_del.py b/pypy/jit/metainterp/test/test_del.py
index 8ce32f6535..5ea0dc817f 100644
--- a/pypy/jit/metainterp/test/test_del.py
+++ b/pypy/jit/metainterp/test/test_del.py
@@ -85,6 +85,7 @@ class TestLLtype(DelTests, LLJitMixin):
def test_signal_action(self):
from pypy.module.signal.interp_signal import SignalActionFlag
action = SignalActionFlag()
+ action.has_bytecode_counter = True
#
myjitdriver = JitDriver(greens = [], reds = ['n', 'x'])
class X:
@@ -92,17 +93,17 @@ class TestLLtype(DelTests, LLJitMixin):
#
def f(n):
x = X()
- while n > 0:
+ action.reset_ticker(n)
+ while True:
myjitdriver.can_enter_jit(n=n, x=x)
myjitdriver.jit_merge_point(n=n, x=x)
x.foo = n
n -= 1
- if action.get() != 0:
+ if action.decrement_ticker(1) < 0:
break
- action.set(0)
return 42
self.meta_interp(f, [20])
- self.check_loops(getfield_raw=1, call=0, call_pure=0)
+ self.check_loops(getfield_raw=1, setfield_raw=1, call=0, call_pure=0)
class TestOOtype(DelTests, OOJitMixin):
def setup_class(cls):
diff --git a/pypy/jit/metainterp/test/test_logger.py b/pypy/jit/metainterp/test/test_logger.py
index 24618f6a09..8a2eeaa51e 100644
--- a/pypy/jit/metainterp/test/test_logger.py
+++ b/pypy/jit/metainterp/test/test_logger.py
@@ -97,7 +97,7 @@ class TestLogger(object):
def test_debug_merge_point(self):
inp = '''
[]
- debug_merge_point("info")
+ debug_merge_point("info", 0)
'''
loop, oloop = self.reparse(inp, check_equal=False)
assert loop.operations[0].getarg(0)._get_str() == 'info'
diff --git a/pypy/jit/metainterp/test/test_oparser.py b/pypy/jit/metainterp/test/test_oparser.py
deleted file mode 100644
index ef06d4a439..0000000000
--- a/pypy/jit/metainterp/test/test_oparser.py
+++ /dev/null
@@ -1,205 +0,0 @@
-
-from pypy.rpython.lltypesystem import lltype, llmemory
-
-from pypy.jit.tool.oparser import parse
-from pypy.jit.metainterp.resoperation import rop
-from pypy.jit.metainterp.history import AbstractDescr, BoxInt, LoopToken,\
- BoxFloat
-
-def test_basic_parse():
- x = """
- [i0, i1]
- # a comment
- i2 = int_add(i0, i1)
- i3 = int_sub(i2, 3) # another comment
- finish() # (tricky)
- """
- loop = parse(x)
- assert len(loop.operations) == 3
- assert [op.getopnum() for op in loop.operations] == [rop.INT_ADD, rop.INT_SUB,
- rop.FINISH]
- assert len(loop.inputargs) == 2
- assert loop.operations[-1].getdescr()
-
-def test_const_ptr_subops():
- x = """
- [p0]
- guard_class(p0, ConstClass(vtable)) []
- """
- S = lltype.Struct('S')
- vtable = lltype.nullptr(S)
- loop = parse(x, None, locals())
- assert len(loop.operations) == 1
- assert loop.operations[0].getdescr()
- assert loop.operations[0].getfailargs() == []
-
-def test_descr():
- class Xyz(AbstractDescr):
- pass
-
- x = """
- [p0]
- i1 = getfield_gc(p0, descr=stuff)
- """
- stuff = Xyz()
- loop = parse(x, None, locals())
- assert loop.operations[0].getdescr() is stuff
-
-def test_after_fail():
- x = """
- [i0]
- guard_value(i0, 3) []
- i1 = int_add(1, 2)
- """
- loop = parse(x, None, {})
- assert len(loop.operations) == 2
-
-def test_descr_setfield():
- class Xyz(AbstractDescr):
- pass
-
- x = """
- [p0]
- setfield_gc(p0, 3, descr=stuff)
- """
- stuff = Xyz()
- loop = parse(x, None, locals())
- assert loop.operations[0].getdescr() is stuff
-
-def test_boxname():
- x = """
- [i42]
- i50 = int_add(i42, 1)
- """
- loop = parse(x, None, {})
- assert str(loop.inputargs[0]) == 'i42'
- assert str(loop.operations[0].result) == 'i50'
-
-def test_getboxes():
- x = """
- [i0]
- i1 = int_add(i0, 10)
- """
- loop = parse(x, None, {})
- boxes = loop.getboxes()
- assert boxes.i0 is loop.inputargs[0]
- assert boxes.i1 is loop.operations[0].result
-
-def test_setvalues():
- x = """
- [i0]
- i1 = int_add(i0, 10)
- """
- loop = parse(x, None, {})
- loop.setvalues(i0=32, i1=42)
- assert loop.inputargs[0].value == 32
- assert loop.operations[0].result.value == 42
-
-def test_boxkind():
- x = """
- [sum0]
- """
- loop = parse(x, None, {}, boxkinds={'sum': BoxInt})
- b = loop.getboxes()
- assert isinstance(b.sum0, BoxInt)
-
-def test_getvar_const_ptr():
- x = '''
- []
- call(ConstPtr(func_ptr))
- '''
- TP = lltype.GcArray(lltype.Signed)
- NULL = lltype.cast_opaque_ptr(llmemory.GCREF, lltype.nullptr(TP))
- loop = parse(x, None, {'func_ptr' : NULL})
- assert loop.operations[0].getarg(0).value == NULL
-
-def test_jump_target():
- x = '''
- []
- jump()
- '''
- loop = parse(x)
- assert loop.operations[0].getdescr() is loop.token
-
-def test_jump_target_other():
- looptoken = LoopToken()
- x = '''
- []
- jump(descr=looptoken)
- '''
- loop = parse(x, namespace=locals())
- assert loop.operations[0].getdescr() is looptoken
-
-def test_floats():
- x = '''
- [f0]
- f1 = float_add(f0, 3.5)
- '''
- loop = parse(x)
- assert isinstance(loop.operations[0].getarg(0), BoxFloat)
-
-def test_debug_merge_point():
- x = '''
- []
- debug_merge_point("info")
- debug_merge_point('info')
- debug_merge_point('<some ('other,')> info')
- debug_merge_point('(stuff) #1')
- '''
- loop = parse(x)
- assert loop.operations[0].getarg(0)._get_str() == 'info'
- assert loop.operations[1].getarg(0)._get_str() == 'info'
- assert loop.operations[2].getarg(0)._get_str() == "<some ('other,')> info"
- assert loop.operations[3].getarg(0)._get_str() == "(stuff) #1"
-
-
-def test_descr_with_obj_print():
- x = '''
- [p0]
- setfield_gc(p0, 1, descr=<SomeDescr>)
- '''
- loop = parse(x)
- # assert did not explode
-
-example_loop_log = '''\
-# bridge out of Guard12, 6 ops
-[i0, i1, i2]
-i4 = int_add(i0, 2)
-i6 = int_sub(i1, 1)
-i8 = int_gt(i6, 3)
-guard_true(i8, descr=<Guard15>) [i4, i6]
-debug_merge_point('(no jitdriver.get_printable_location!)')
-jump(i6, i4, descr=<Loop0>)
-'''
-
-def test_parse_no_namespace():
- loop = parse(example_loop_log, no_namespace=True)
-
-def test_attach_comment_to_loop():
- loop = parse(example_loop_log, no_namespace=True)
- assert loop.comment == '# bridge out of Guard12, 6 ops'
-
-def test_parse_new_with_comma():
- # this is generated by PYPYJITLOG, check that we can handle it
- x = '''
- []
- p0 = new(, descr=<SizeDescr 12>)
- '''
- loop = parse(x)
- assert loop.operations[0].getopname() == 'new'
-
-def test_no_fail_args():
- x = '''
- [i0]
- guard_true(i0, descr=<Guard0>)
- '''
- loop = parse(x, nonstrict=True)
- assert loop.operations[0].getfailargs() == []
-
-def test_no_inputargs():
- x = '''
- i2 = int_add(i0, i1)
- '''
- loop = parse(x, nonstrict=True)
- assert loop.inputargs == []
- assert loop.operations[0].getopname() == 'int_add'
diff --git a/pypy/jit/metainterp/test/test_optimizeopt.py b/pypy/jit/metainterp/test/test_optimizeopt.py
index baf8e65777..74393e540d 100644
--- a/pypy/jit/metainterp/test/test_optimizeopt.py
+++ b/pypy/jit/metainterp/test/test_optimizeopt.py
@@ -26,6 +26,100 @@ class FakeMetaInterpStaticData(object):
self.options = Fake()
self.globaldata = Fake()
+def test_store_final_boxes_in_guard():
+ from pypy.jit.metainterp.compile import ResumeGuardDescr
+ from pypy.jit.metainterp.resume import tag, TAGBOX
+ b0 = BoxInt()
+ b1 = BoxInt()
+ opt = optimizeopt.Optimizer(FakeMetaInterpStaticData(LLtypeMixin.cpu),
+ None)
+ fdescr = ResumeGuardDescr(None)
+ op = ResOperation(rop.GUARD_TRUE, ['dummy'], None, descr=fdescr)
+ # setup rd data
+ fi0 = resume.FrameInfo(None, "code0", 11)
+ fdescr.rd_frame_info_list = resume.FrameInfo(fi0, "code1", 33)
+ snapshot0 = resume.Snapshot(None, [b0])
+ fdescr.rd_snapshot = resume.Snapshot(snapshot0, [b1])
+ #
+ opt.store_final_boxes_in_guard(op)
+ if op.getfailargs() == [b0, b1]:
+ assert list(fdescr.rd_numb.nums) == [tag(1, TAGBOX)]
+ assert list(fdescr.rd_numb.prev.nums) == [tag(0, TAGBOX)]
+ else:
+ assert op.getfailargs() == [b1, b0]
+ assert list(fdescr.rd_numb.nums) == [tag(0, TAGBOX)]
+ assert list(fdescr.rd_numb.prev.nums) == [tag(1, TAGBOX)]
+ assert fdescr.rd_virtuals is None
+ assert fdescr.rd_consts == []
+
+def test_sharing_field_lists_of_virtual():
+ class FakeOptimizer(object):
+ class cpu(object):
+ pass
+ opt = FakeOptimizer()
+ virt1 = virtualize.AbstractVirtualStructValue(opt, None)
+ lst1 = virt1._get_field_descr_list()
+ assert lst1 == []
+ lst2 = virt1._get_field_descr_list()
+ assert lst1 is lst2
+ virt1.setfield(LLtypeMixin.valuedescr, optimizeopt.OptValue(None))
+ lst3 = virt1._get_field_descr_list()
+ assert lst3 == [LLtypeMixin.valuedescr]
+ lst4 = virt1._get_field_descr_list()
+ assert lst3 is lst4
+
+ virt2 = virtualize.AbstractVirtualStructValue(opt, None)
+ lst5 = virt2._get_field_descr_list()
+ assert lst5 is lst1
+ virt2.setfield(LLtypeMixin.valuedescr, optimizeopt.OptValue(None))
+ lst6 = virt1._get_field_descr_list()
+ assert lst6 is lst3
+
+def test_reuse_vinfo():
+ class FakeVInfo(object):
+ def set_content(self, fieldnums):
+ self.fieldnums = fieldnums
+ def equals(self, fieldnums):
+ return self.fieldnums == fieldnums
+ class FakeVirtualValue(virtualize.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 test_descrlist_dict():
+ from pypy.jit.metainterp import optimizeutil
+ h1 = optimizeutil.descrlist_hash([])
+ h2 = optimizeutil.descrlist_hash([LLtypeMixin.valuedescr])
+ h3 = optimizeutil.descrlist_hash(
+ [LLtypeMixin.valuedescr, LLtypeMixin.nextdescr])
+ assert h1 != h2
+ assert h2 != h3
+ assert optimizeutil.descrlist_eq([], [])
+ assert not optimizeutil.descrlist_eq([], [LLtypeMixin.valuedescr])
+ assert optimizeutil.descrlist_eq([LLtypeMixin.valuedescr],
+ [LLtypeMixin.valuedescr])
+ assert not optimizeutil.descrlist_eq([LLtypeMixin.valuedescr],
+ [LLtypeMixin.nextdescr])
+ assert optimizeutil.descrlist_eq([LLtypeMixin.valuedescr, LLtypeMixin.nextdescr],
+ [LLtypeMixin.valuedescr, LLtypeMixin.nextdescr])
+ assert not optimizeutil.descrlist_eq([LLtypeMixin.nextdescr, LLtypeMixin.valuedescr],
+ [LLtypeMixin.valuedescr, LLtypeMixin.nextdescr])
+
+ # descrlist_eq should compare by identity of the descrs, not by the result
+ # of sort_key
+ class FakeDescr(object):
+ def sort_key(self):
+ return 1
+
+ assert not optimizeutil.descrlist_eq([FakeDescr()], [FakeDescr()])
+
# ____________________________________________________________
class Storage(compile.ResumeGuardDescr):
"for tests."
@@ -76,6 +170,8 @@ class BaseTestOptimizeOpt(BaseTest):
metainterp_sd = FakeMetaInterpStaticData(self.cpu)
if hasattr(self, 'vrefinfo'):
metainterp_sd.virtualref_info = self.vrefinfo
+ if hasattr(self, 'callinfocollection'):
+ metainterp_sd.callinfocollection = self.callinfocollection
optimize_loop_1(metainterp_sd, loop)
#
@@ -1430,7 +1526,7 @@ class OptimizeOptTest(BaseTestOptimizeOpt):
ops = """
[p1]
i1 = getfield_gc(p1, descr=valuedescr)
- debug_merge_point(15)
+ debug_merge_point(15, 0)
i2 = getfield_gc(p1, descr=valuedescr)
escape(i1)
escape(i2)
@@ -1439,7 +1535,7 @@ class OptimizeOptTest(BaseTestOptimizeOpt):
expected = """
[p1]
i1 = getfield_gc(p1, descr=valuedescr)
- debug_merge_point(15)
+ debug_merge_point(15, 0)
escape(i1)
escape(i1)
jump(p1)
@@ -4288,22 +4384,20 @@ class TestLLtype(OptimizeOptTest, LLtypeMixin):
# ----------
def optimize_strunicode_loop_extradescrs(self, ops, optops, preamble=None):
from pypy.jit.metainterp.optimizeopt import string
- def my_callinfo_for_oopspec(oopspecindex):
- calldescrtype = type(LLtypeMixin.strequaldescr)
- for value in LLtypeMixin.__dict__.values():
- if isinstance(value, calldescrtype):
- if (value.get_extra_info() and
- value.get_extra_info().oopspecindex == oopspecindex):
- # returns 0 for 'func' in this test
- return value, 0
- raise AssertionError("not found: oopspecindex=%d" % oopspecindex)
+ class FakeCallInfoCollection:
+ def callinfo_for_oopspec(self, oopspecindex):
+ calldescrtype = type(LLtypeMixin.strequaldescr)
+ for value in LLtypeMixin.__dict__.values():
+ if isinstance(value, calldescrtype):
+ extra = value.get_extra_info()
+ if extra and extra.oopspecindex == oopspecindex:
+ # returns 0 for 'func' in this test
+ return value, 0
+ raise AssertionError("not found: oopspecindex=%d" %
+ oopspecindex)
#
- saved = string.callinfo_for_oopspec
- try:
- string.callinfo_for_oopspec = my_callinfo_for_oopspec
- self.optimize_strunicode_loop(ops, optops, preamble)
- finally:
- string.callinfo_for_oopspec = saved
+ self.callinfocollection = FakeCallInfoCollection()
+ self.optimize_strunicode_loop(ops, optops, preamble)
def test_str_equal_noop1(self):
ops = """
diff --git a/pypy/jit/metainterp/test/test_resoperation.py b/pypy/jit/metainterp/test/test_resoperation.py
index b8cebb8b7a..b64390a784 100644
--- a/pypy/jit/metainterp/test/test_resoperation.py
+++ b/pypy/jit/metainterp/test/test_resoperation.py
@@ -61,3 +61,10 @@ def test_instantiate():
assert op.getarglist() == ['a', 'b']
assert op.result == 'c'
assert op.getdescr() is mydescr
+
+def test_can_malloc():
+ mydescr = AbstractDescr()
+ assert rop.ResOperation(rop.rop.NEW, [], 'b').can_malloc()
+ call = rop.ResOperation(rop.rop.CALL, ['a', 'b'], 'c', descr=mydescr)
+ assert call.can_malloc()
+ assert not rop.ResOperation(rop.rop.INT_ADD, ['a', 'b'], 'c').can_malloc()
diff --git a/pypy/jit/metainterp/test/test_resume.py b/pypy/jit/metainterp/test/test_resume.py
index 3e0a8a8fcb..bd891d9ea6 100644
--- a/pypy/jit/metainterp/test/test_resume.py
+++ b/pypy/jit/metainterp/test/test_resume.py
@@ -52,6 +52,7 @@ def test_vinfo():
class MyMetaInterp:
_already_allocated_resume_virtuals = None
+ callinfocollection = None
def __init__(self, cpu=None):
if cpu is None:
@@ -142,6 +143,13 @@ def _next_section(reader, *expected):
assert bh.written_f == expected_f
+def Numbering(prev, nums):
+ numb = lltype.malloc(NUMBERING, len(nums))
+ numb.prev = prev or lltype.nullptr(NUMBERING)
+ for i in range(len(nums)):
+ numb.nums[i] = nums[i]
+ return numb
+
def test_simple_read():
#b1, b2, b3 = [BoxInt(), BoxPtr(), BoxInt()]
c1, c2, c3 = [ConstInt(111), ConstInt(222), ConstInt(333)]
@@ -157,12 +165,12 @@ def test_simple_read():
storage.rd_numb = numb
#
cpu = MyCPU([42, gcref1, -66])
- reader = ResumeDataDirectReader(cpu, storage)
+ metainterp = MyMetaInterp(cpu)
+ reader = ResumeDataDirectReader(metainterp, storage)
_next_section(reader, 42, 111, gcrefnull, 42, gcref1)
_next_section(reader, 222, 333)
_next_section(reader, 42, gcref1, -66)
#
- metainterp = MyMetaInterp(cpu)
reader = ResumeDataBoxReader(storage, metainterp)
bi, br, bf = [None]*3, [None]*2, [None]*0
info = MyBlackholeInterp([lltype.Signed, lltype.Signed,
@@ -194,7 +202,7 @@ def test_simple_read_tagged_ints():
storage.rd_numb = numb
#
cpu = MyCPU([])
- reader = ResumeDataDirectReader(cpu, storage)
+ reader = ResumeDataDirectReader(MyMetaInterp(cpu), storage)
_next_section(reader, 100)
@@ -212,7 +220,7 @@ def test_prepare_virtuals():
class FakeMetainterp(object):
_already_allocated_resume_virtuals = None
cpu = None
- reader = ResumeDataDirectReader(None, FakeStorage())
+ reader = ResumeDataDirectReader(MyMetaInterp(None), FakeStorage())
assert reader.force_all_virtuals() == ["allocated", reader.virtual_default]
# ____________________________________________________________
@@ -391,15 +399,15 @@ def test_FrameInfo_create():
assert fi1.pc == 3
def test_Numbering_create():
- l = [1, 2]
+ l = [rffi.r_short(1), rffi.r_short(2)]
numb = Numbering(None, l)
- assert numb.prev is None
- assert numb.nums is l
+ assert not numb.prev
+ assert list(numb.nums) == l
- l1 = ['b3']
+ l1 = [rffi.r_short(3)]
numb1 = Numbering(numb, l1)
- assert numb1.prev is numb
- assert numb1.nums is l1
+ assert numb1.prev == numb
+ assert list(numb1.nums) == l1
def test_capture_resumedata():
b1, b2, b3 = [BoxInt(), BoxPtr(), BoxInt()]
@@ -765,11 +773,12 @@ def test_ResumeDataLoopMemo_number():
assert liveboxes == {b1: tag(0, TAGBOX), b2: tag(1, TAGBOX),
b3: tag(2, TAGBOX)}
- assert numb.nums == [tag(3, TAGINT), tag(2, TAGBOX), tag(0, TAGBOX),
- tag(1, TAGINT)]
- assert numb.prev.nums == [tag(0, TAGBOX), tag(1, TAGINT), tag(1, TAGBOX),
- tag(0, TAGBOX), tag(2, TAGINT)]
- assert numb.prev.prev is None
+ assert list(numb.nums) == [tag(3, TAGINT), tag(2, TAGBOX), tag(0, TAGBOX),
+ tag(1, TAGINT)]
+ assert list(numb.prev.nums) == [tag(0, TAGBOX), tag(1, TAGINT),
+ tag(1, TAGBOX),
+ tag(0, TAGBOX), tag(2, TAGINT)]
+ assert not numb.prev.prev
numb2, liveboxes2, v = memo.number({}, snap2)
assert v == 0
@@ -777,9 +786,9 @@ def test_ResumeDataLoopMemo_number():
assert liveboxes2 == {b1: tag(0, TAGBOX), b2: tag(1, TAGBOX),
b3: tag(2, TAGBOX)}
assert liveboxes2 is not liveboxes
- assert numb2.nums == [tag(3, TAGINT), tag(2, TAGBOX), tag(0, TAGBOX),
- tag(3, TAGINT)]
- assert numb2.prev is numb.prev
+ assert list(numb2.nums) == [tag(3, TAGINT), tag(2, TAGBOX), tag(0, TAGBOX),
+ tag(3, TAGINT)]
+ assert numb2.prev == numb.prev
env3 = [c3, b3, b1, c3]
snap3 = Snapshot(snap, env3)
@@ -800,9 +809,9 @@ def test_ResumeDataLoopMemo_number():
assert v == 0
assert liveboxes3 == {b1: tag(0, TAGBOX), b2: tag(1, TAGBOX)}
- assert numb3.nums == [tag(3, TAGINT), tag(4, TAGINT), tag(0, TAGBOX),
- tag(3, TAGINT)]
- assert numb3.prev is numb.prev
+ assert list(numb3.nums) == [tag(3, TAGINT), tag(4, TAGINT), tag(0, TAGBOX),
+ tag(3, TAGINT)]
+ assert numb3.prev == numb.prev
# virtual
env4 = [c3, b4, b1, c3]
@@ -813,9 +822,9 @@ def test_ResumeDataLoopMemo_number():
assert liveboxes4 == {b1: tag(0, TAGBOX), b2: tag(1, TAGBOX),
b4: tag(0, TAGVIRTUAL)}
- assert numb4.nums == [tag(3, TAGINT), tag(0, TAGVIRTUAL), tag(0, TAGBOX),
- tag(3, TAGINT)]
- assert numb4.prev is numb.prev
+ assert list(numb4.nums) == [tag(3, TAGINT), tag(0, TAGVIRTUAL),
+ tag(0, TAGBOX), tag(3, TAGINT)]
+ assert numb4.prev == numb.prev
env5 = [b1, b4, b5]
snap5 = Snapshot(snap4, env5)
@@ -826,9 +835,9 @@ def test_ResumeDataLoopMemo_number():
assert liveboxes5 == {b1: tag(0, TAGBOX), b2: tag(1, TAGBOX),
b4: tag(0, TAGVIRTUAL), b5: tag(1, TAGVIRTUAL)}
- assert numb5.nums == [tag(0, TAGBOX), tag(0, TAGVIRTUAL),
- tag(1, TAGVIRTUAL)]
- assert numb5.prev is numb4
+ assert list(numb5.nums) == [tag(0, TAGBOX), tag(0, TAGVIRTUAL),
+ tag(1, TAGVIRTUAL)]
+ assert numb5.prev == numb4
def test_ResumeDataLoopMemo_number_boxes():
memo = ResumeDataLoopMemo(FakeMetaInterpStaticData())
@@ -926,7 +935,7 @@ def test_virtual_adder_int_constants():
liveboxes = modifier.finish({})
assert storage.rd_snapshot is None
cpu = MyCPU([])
- reader = ResumeDataDirectReader(cpu, storage)
+ reader = ResumeDataDirectReader(MyMetaInterp(cpu), storage)
_next_section(reader, sys.maxint, 2**16, -65)
_next_section(reader, 2, 3)
_next_section(reader, sys.maxint, 1, sys.maxint, 2**16)
diff --git a/pypy/jit/metainterp/test/test_virtualref.py b/pypy/jit/metainterp/test/test_virtualref.py
index 097f9f99c9..e0e738207f 100644
--- a/pypy/jit/metainterp/test/test_virtualref.py
+++ b/pypy/jit/metainterp/test/test_virtualref.py
@@ -88,7 +88,11 @@ class VRefTests:
cpu.get_latest_value_int = lambda i:guard_op.getfailargs()[i].getint()
cpu.get_latest_value_ref = lambda i:guard_op.getfailargs()[i].getref_base()
cpu.clear_latest_values = lambda count: None
- resumereader = ResumeDataDirectReader(cpu, guard_op.getdescr())
+ class FakeMetaInterpSd:
+ callinfocollection = None
+ FakeMetaInterpSd.cpu = cpu
+ resumereader = ResumeDataDirectReader(FakeMetaInterpSd(),
+ guard_op.getdescr())
vrefinfo = self.metainterp.staticdata.virtualref_info
lst = []
vrefinfo.continue_tracing = lambda vref, virtual: \
diff --git a/pypy/jit/metainterp/test/test_ztranslation.py b/pypy/jit/metainterp/test/test_ztranslation.py
index 3987544b19..026e4d5dee 100644
--- a/pypy/jit/metainterp/test/test_ztranslation.py
+++ b/pypy/jit/metainterp/test/test_ztranslation.py
@@ -79,7 +79,7 @@ class TranslationTest:
res = ll_meta_interp(main, [40, 5], CPUClass=self.CPUClass,
type_system=self.type_system)
assert res == main(40, 5)
- res = rpython_ll_meta_interp(main, [40, 5], loops=2,
+ res = rpython_ll_meta_interp(main, [40, 5],
CPUClass=self.CPUClass,
type_system=self.type_system,
optimizer=OPTIMIZER_FULL,
@@ -120,7 +120,7 @@ class TranslationTest:
res = ll_meta_interp(main, [40], CPUClass=self.CPUClass,
type_system=self.type_system)
assert res == main(40)
- res = rpython_ll_meta_interp(main, [40], loops=2, CPUClass=self.CPUClass,
+ res = rpython_ll_meta_interp(main, [40], CPUClass=self.CPUClass,
type_system=self.type_system,
optimizer=OPTIMIZER_FULL,
ProfilerClass=Profiler)
diff --git a/pypy/jit/metainterp/virtualizable.py b/pypy/jit/metainterp/virtualizable.py
index c6071dab9f..baa54fdb3d 100644
--- a/pypy/jit/metainterp/virtualizable.py
+++ b/pypy/jit/metainterp/virtualizable.py
@@ -100,48 +100,48 @@ class VirtualizableInfo:
i = i + 1
assert len(boxes) == i + 1
#
- def write_from_resume_data_partial(virtualizable, reader, nums):
+ def write_from_resume_data_partial(virtualizable, reader, numb):
# Load values from the reader (see resume.py) described by
# the list of numbers 'nums', and write them in their proper
# place in the 'virtualizable'. This works from the end of
# the list and returns the index in 'nums' of the start of
# the virtualizable data found, allowing the caller to do
# further processing with the start of the list.
- i = len(nums) - 1
+ i = len(numb.nums) - 1
assert i >= 0
for ARRAYITEMTYPE, fieldname in unroll_array_fields_rev:
lst = getattr(virtualizable, fieldname)
for j in range(getlength(lst)-1, -1, -1):
i -= 1
assert i >= 0
- x = reader.load_value_of_type(ARRAYITEMTYPE, nums[i])
+ x = reader.load_value_of_type(ARRAYITEMTYPE, numb.nums[i])
setarrayitem(lst, j, x)
for FIELDTYPE, fieldname in unroll_static_fields_rev:
i -= 1
assert i >= 0
- x = reader.load_value_of_type(FIELDTYPE, nums[i])
+ x = reader.load_value_of_type(FIELDTYPE, numb.nums[i])
setattr(virtualizable, fieldname, x)
return i
#
- def load_list_of_boxes(virtualizable, reader, nums):
+ def load_list_of_boxes(virtualizable, reader, numb):
# Uses 'virtualizable' only to know the length of the arrays;
# does not write anything into it. The returned list is in
# the format expected of virtualizable_boxes, so it ends in
# the virtualizable itself.
- i = len(nums) - 1
+ i = len(numb.nums) - 1
assert i >= 0
- boxes = [reader.decode_box_of_type(self.VTYPEPTR, nums[i])]
+ boxes = [reader.decode_box_of_type(self.VTYPEPTR, numb.nums[i])]
for ARRAYITEMTYPE, fieldname in unroll_array_fields_rev:
lst = getattr(virtualizable, fieldname)
for j in range(getlength(lst)-1, -1, -1):
i -= 1
assert i >= 0
- box = reader.decode_box_of_type(ARRAYITEMTYPE, nums[i])
+ box = reader.decode_box_of_type(ARRAYITEMTYPE,numb.nums[i])
boxes.append(box)
for FIELDTYPE, fieldname in unroll_static_fields_rev:
i -= 1
assert i >= 0
- box = reader.decode_box_of_type(FIELDTYPE, nums[i])
+ box = reader.decode_box_of_type(FIELDTYPE, numb.nums[i])
boxes.append(box)
boxes.reverse()
return boxes
diff --git a/pypy/jit/metainterp/warmspot.py b/pypy/jit/metainterp/warmspot.py
index 819fa79957..a5d36ee7b8 100644
--- a/pypy/jit/metainterp/warmspot.py
+++ b/pypy/jit/metainterp/warmspot.py
@@ -98,8 +98,7 @@ def jittify_and_run(interp, graph, args, repeat=1,
repeat -= 1
return res
-def rpython_ll_meta_interp(function, args, backendopt=True,
- loops='not used right now', **kwds):
+def rpython_ll_meta_interp(function, args, backendopt=True, **kwds):
return ll_meta_interp(function, args, backendopt=backendopt,
translate_support_code=True, **kwds)