[pypy-commit] pypy optresult: start fighting with raw buffers
fijal
noreply at buildbot.pypy.org
Wed Jun 3 11:02:51 CEST 2015
Author: Maciej Fijalkowski <fijall at gmail.com>
Branch: optresult
Changeset: r77809:fc54d02f8b1c
Date: 2015-06-03 11:02 +0200
http://bitbucket.org/pypy/pypy/changeset/fc54d02f8b1c/
Log: start fighting with raw buffers
diff --git a/rpython/jit/metainterp/optimizeopt/info.py b/rpython/jit/metainterp/optimizeopt/info.py
--- a/rpython/jit/metainterp/optimizeopt/info.py
+++ b/rpython/jit/metainterp/optimizeopt/info.py
@@ -4,6 +4,7 @@
rop
from rpython.jit.metainterp.history import ConstInt, Const
from rpython.rtyper.lltypesystem import lltype
+from rpython.jit.metainterp.optimizeopt.rawbuffer import RawBuffer, InvalidRawOperation
INFO_NULL = 0
@@ -141,11 +142,10 @@
for box in self._fields])
for i in range(len(lst)):
op = self._fields[i]
- if op and op.type == 'r':
- op = op.get_box_replacement()
- fieldinfo = optimizer.getptrinfo(op)
- if fieldinfo and fieldinfo.is_virtual():
- fieldinfo.visitor_walk_recursive(op, visitor, optimizer)
+ op = op.get_box_replacement()
+ fieldinfo = optimizer.getptrinfo(op)
+ if fieldinfo and fieldinfo.is_virtual():
+ fieldinfo.visitor_walk_recursive(op, visitor, optimizer)
class InstancePtrInfo(AbstractStructPtrInfo):
_attrs_ = ('_known_class',)
@@ -174,8 +174,85 @@
assert self.is_virtual()
return visitor.visit_vstruct(self.vdescr, fielddescrs)
-class RawStructPtrInfo(StructPtrInfo):
- pass
+class AbstractRawPtrInfo(AbstractVirtualPtrInfo):
+ def visitor_walk_recursive(self, op, visitor, optimizer):
+ xxx
+ box = self.rawbuffer_value.get_key_box()
+ visitor.register_virtual_fields(self.keybox, [box])
+ self.rawbuffer_value.visitor_walk_recursive(visitor)
+
+ @specialize.argtype(1)
+ def visitor_dispatch_virtual_type(self, visitor):
+ yyy
+ return visitor.visit_vrawslice(self.offset)
+
+class RawBufferPtrInfo(AbstractRawPtrInfo):
+ buffer = None
+
+ def __init__(self, cpu, size=-1):
+ self.size = size
+ if self.size != -1:
+ self.buffer = RawBuffer(cpu, None)
+
+ def getitem_raw(self, offset, itemsize, descr):
+ if not self.is_virtual():
+ raise InvalidRawOperation
+ # see 'test_virtual_raw_buffer_forced_but_slice_not_forced'
+ # for the test above: it's not enough to check is_virtual()
+ # on the original object, because it might be a VRawSliceValue
+ # instead. If it is a virtual one, then we'll reach here anway.
+ return self.buffer.read_value(offset, itemsize, descr)
+
+ def setitem_raw(self, offset, itemsize, descr, itemop):
+ if not self.is_virtual():
+ raise InvalidRawOperation
+ self.buffer.write_value(offset, itemsize, descr, itemop)
+
+ def is_virtual(self):
+ return self.size != -1
+
+ def _force_elements(self, op, optforce, descr):
+ xxx
+
+ def visitor_walk_recursive(self, op, visitor, optimizer):
+ itemboxes = self.buffer.values
+ visitor.register_virtual_fields(op, itemboxes)
+ #for itembox in itemboxes:
+ # xxx
+ # itemvalue = self.get_item_value(i)
+ # if itemvalue is not None:
+ # itemvalue.visitor_walk_recursive(visitor)
+
+ @specialize.argtype(1)
+ def visitor_dispatch_virtual_type(self, visitor):
+ return visitor.visit_vrawbuffer(self.size,
+ self.buffer.offsets[:],
+ self.buffer.descrs[:])
+
+class RawStructPtrInfo(AbstractRawPtrInfo):
+ def __init__(self):
+ import pdb
+ pdb.set_trace()
+
+ def _force_elements(self, op, optforce, descr):
+ xxx
+
+class RawSlicePtrInfo(AbstractRawPtrInfo):
+ def __init__(self, offset, parent):
+ self.offset = offset
+ self.parent = parent
+
+ def is_virtual(self):
+ return self.parent.is_virtual()
+
+ def getitem_raw(self, offset, itemsize, descr):
+ return self.parent.getitem_raw(self.offset+offset, itemsize, descr)
+
+ def setitem_raw(self, offset, itemsize, descr, itemop):
+ self.parent.setitem_raw(self.offset+offset, itemsize, descr, itemop)
+
+ def _force_elements(self, op, optforce, descr):
+ xxx
class ArrayPtrInfo(AbstractVirtualPtrInfo):
_attrs_ = ('length', '_items', 'lenbound', '_clear')
@@ -242,7 +319,7 @@
visitor.register_virtual_fields(instbox, itemops)
for i in range(self.getlength()):
itemop = self._items[i]
- if (itemop is not None and itemop.type == 'r' and
+ if (itemop is not None and
not isinstance(itemop, Const)):
ptrinfo = optimizer.getptrinfo(itemop)
if ptrinfo and ptrinfo.is_virtual():
@@ -298,7 +375,7 @@
for index in range(self.getlength()):
for flddescr in fielddescrs:
itemop = self._items[i]
- if (itemop is not None and itemop.type == 'r' and
+ if (itemop is not None and
not isinstance(itemop, Const)):
ptrinfo = optimizer.getptrinfo(itemop)
if ptrinfo and ptrinfo.is_virtual():
diff --git a/rpython/jit/metainterp/optimizeopt/intbounds.py b/rpython/jit/metainterp/optimizeopt/intbounds.py
--- a/rpython/jit/metainterp/optimizeopt/intbounds.py
+++ b/rpython/jit/metainterp/optimizeopt/intbounds.py
@@ -117,6 +117,8 @@
def optimize_INT_ADD(self, op):
self.emit_operation(op)
+ if self.is_raw_ptr(op.getarg(0)) or self.is_raw_ptr(op.getarg(1)):
+ return
b1 = self.getintbound(op.getarg(0))
b2 = self.getintbound(op.getarg(1))
r = self.getintbound(op)
@@ -536,6 +538,8 @@
self._propagate_int_is_true_or_zero(op, 0, 1)
def propagate_bounds_INT_ADD(self, op):
+ if self.is_raw_ptr(op.getarg(0)) or self.is_raw_ptr(op.getarg(1)):
+ return
b1 = self.getintbound(op.getarg(0))
b2 = self.getintbound(op.getarg(1))
r = self.getintbound(op)
diff --git a/rpython/jit/metainterp/optimizeopt/optimizer.py b/rpython/jit/metainterp/optimizeopt/optimizer.py
--- a/rpython/jit/metainterp/optimizeopt/optimizer.py
+++ b/rpython/jit/metainterp/optimizeopt/optimizer.py
@@ -316,6 +316,10 @@
return opinfo
def getptrinfo(self, op, create=False, is_object=False):
+ if op.type == 'i':
+ return self.getrawptrinfo(op, create)
+ elif op.type == 'f':
+ return None
assert op.type == 'r'
op = self.get_box_replacement(op)
assert op.type == 'r'
@@ -327,6 +331,12 @@
return fw
return None
+ def is_raw_ptr(self, op):
+ fw = self.get_box_replacement(op).get_forwarded()
+ if isinstance(fw, info.AbstractRawPtrInfo):
+ return True
+ return False
+
def getrawptrinfo(self, op, create=False, is_object=False):
assert op.type == 'i'
op = self.get_box_replacement(op)
@@ -334,11 +344,14 @@
if isinstance(op, ConstInt):
return info.ConstPtrInfo(op)
fw = op.get_forwarded()
+ if isinstance(fw, IntBound) and not create:
+ return None
if fw is not None:
- if isinstance(fw, info.NonNullPtrInfo):
- fw = info.RawStructPtrInfo()
- op.set_forwarded(fw)
- assert isinstance(fw, info.RawStructPtrInfo)
+ if isinstance(fw, info.AbstractRawPtrInfo):
+ return fw
+ fw = info.RawStructPtrInfo()
+ op.set_forwarded(fw)
+ assert isinstance(fw, info.AbstractRawPtrInfo)
return fw
return None
diff --git a/rpython/jit/metainterp/optimizeopt/rewrite.py b/rpython/jit/metainterp/optimizeopt/rewrite.py
--- a/rpython/jit/metainterp/optimizeopt/rewrite.py
+++ b/rpython/jit/metainterp/optimizeopt/rewrite.py
@@ -121,6 +121,9 @@
self.optimizer.pure_reverse(op)
def optimize_INT_ADD(self, op):
+ if self.is_raw_ptr(op.getarg(0)) or self.is_raw_ptr(op.getarg(1)):
+ self.emit_operation(op)
+ return
arg1 = self.get_box_replacement(op.getarg(0))
b1 = self.getintbound(arg1)
arg2 = self.get_box_replacement(op.getarg(1))
diff --git a/rpython/jit/metainterp/optimizeopt/virtualize.py b/rpython/jit/metainterp/optimizeopt/virtualize.py
--- a/rpython/jit/metainterp/optimizeopt/virtualize.py
+++ b/rpython/jit/metainterp/optimizeopt/virtualize.py
@@ -543,17 +543,14 @@
return opinfo
def make_virtual_raw_memory(self, size, source_op):
- raise Exception("unsupported")
- logops = self.optimizer.loop.logops
- vvalue = VRawBufferValue(self.optimizer.cpu, logops, size, source_op)
- self.make_equal_to(source_op, vvalue)
- return vvalue
+ opinfo = info.RawBufferPtrInfo(self.optimizer.cpu, size)
+ source_op.set_forwarded(opinfo)
+ return opinfo
- def make_virtual_raw_slice(self, rawbuffer_value, offset, source_op):
- raise Exception("unsupported")
- vvalue = VRawSliceValue(rawbuffer_value, offset, source_op)
- self.make_equal_to(source_op, vvalue)
- return vvalue
+ def make_virtual_raw_slice(self, offset, parent, source_op):
+ opinfo = info.RawSlicePtrInfo(offset, parent)
+ source_op.set_forwarded(opinfo)
+ return opinfo
def optimize_GUARD_NO_EXCEPTION(self, op):
if self.last_emitted_operation is REMOVED:
@@ -761,23 +758,20 @@
self.emit_operation(op)
def optimize_INT_ADD(self, op):
- if 0:
- XXX
- value = self.getvalue(op.getarg(0))
- offsetbox = self.get_constant_box(op.getarg(1))
- if value.is_virtual() and offsetbox is not None:
- offset = offsetbox.getint()
- # the following check is constant-folded to False if the
- # translation occurs without any VRawXxxValue instance around
- if value.is_about_raw:
- if isinstance(value, VRawBufferValue):
- self.make_virtual_raw_slice(value, offset, op)
- return
- elif isinstance(value, VRawSliceValue):
- offset = offset + value.offset
- self.make_virtual_raw_slice(value.rawbuffer_value, offset,
- op)
- return
+ opinfo = self.getrawptrinfo(op.getarg(0), create=False)
+ offsetbox = self.get_constant_box(op.getarg(1))
+ if opinfo and opinfo.is_virtual() and offsetbox is not None:
+ offset = offsetbox.getint()
+ # the following check is constant-folded to False if the
+ # translation occurs without any VRawXxxValue instance around
+ if isinstance(opinfo, info.RawBufferPtrInfo):
+ self.make_virtual_raw_slice(offset, opinfo, op)
+ return
+ elif isinstance(value, VRawSliceValue):
+ offset = offset + value.offset
+ self.make_virtual_raw_slice(value.rawbuffer_value, offset,
+ op)
+ return
self.emit_operation(op)
def optimize_ARRAYLEN_GC(self, op):
@@ -832,13 +826,12 @@
def optimize_GETARRAYITEM_RAW_I(self, op):
opinfo = self.getrawptrinfo(op.getarg(0))
if opinfo and opinfo.is_virtual():
- raise Exception("implement raw virtuals")
- xxx
indexbox = self.get_constant_box(op.getarg(1))
if indexbox is not None:
- offset, itemsize, descr = self._unpack_arrayitem_raw_op(op, indexbox)
+ offset, itemsize, descr = self._unpack_arrayitem_raw_op(op,
+ indexbox)
try:
- itemvalue = value.getitem_raw(offset, itemsize, descr)
+ itemvalue = opinfo.getitem_raw(offset, itemsize, descr)
except InvalidRawOperation:
pass
else:
@@ -853,11 +846,10 @@
if opinfo and opinfo.is_virtual():
indexbox = self.get_constant_box(op.getarg(1))
if indexbox is not None:
- raise Exception("implement raw virtuals")
offset, itemsize, descr = self._unpack_arrayitem_raw_op(op, indexbox)
- itemvalue = self.getvalue(op.getarg(2))
+ itemop = self.get_box_replacement(op.getarg(2))
try:
- value.setitem_raw(offset, itemsize, descr, itemvalue)
+ opinfo.setitem_raw(offset, itemsize, descr, itemop)
return
except InvalidRawOperation:
pass
diff --git a/rpython/jit/metainterp/pyjitpl.py b/rpython/jit/metainterp/pyjitpl.py
--- a/rpython/jit/metainterp/pyjitpl.py
+++ b/rpython/jit/metainterp/pyjitpl.py
@@ -1573,7 +1573,10 @@
return resbox
self.metainterp.vable_and_vrefs_before_residual_call()
tp = descr.get_result_type()
- if tp == 'i':
+ if effectinfo.oopspecindex == effectinfo.OS_LIBFFI_CALL:
+ resbox = self.metainterp.direct_libffi_call(allboxes, descr,
+ tp)
+ elif tp == 'i':
resbox = self.metainterp.execute_and_record_varargs(
rop.CALL_MAY_FORCE_I, allboxes, descr=descr)
elif tp == 'r':
@@ -1601,11 +1604,6 @@
if vablebox is not None:
self.metainterp.history.record(rop.KEEPALIVE, [vablebox], None)
self.metainterp.handle_possible_exception()
- # XXX refactor: direct_libffi_call() is a hack
- # does not work in the new system
- if effectinfo.oopspecindex == effectinfo.OS_LIBFFI_CALL:
- raise Exception("implement OS_LIBFFI_CALL properly")
- # self.metainterp.direct_libffi_call()
return resbox
else:
effect = effectinfo.extraeffect
@@ -2963,9 +2961,8 @@
else:
return None, op
- def direct_libffi_call(self):
- """Generate a direct call to C code, patching the CALL_MAY_FORCE
- to jit_ffi_call() that occurred just now.
+ def direct_libffi_call(self, argboxes, descr, tp):
+ """Generate a direct call to C code using jit_ffi_call()
"""
# an 'assert' that constant-folds away the rest of this function
# if the codewriter didn't produce any OS_LIBFFI_CALL at all.
@@ -2975,33 +2972,19 @@
from rpython.rlib.jit_libffi import CIF_DESCRIPTION_P
from rpython.jit.backend.llsupport.ffisupport import get_arg_descr
#
- num_extra_guards = 0
- while True:
- op = self.history.operations[-1-num_extra_guards]
- if op.is_call_may_force():
- break
- assert op.is_guard()
- num_extra_guards += 1
- #
- box_cif_description = op.getarg(1)
+ box_cif_description = argboxes[1]
if not isinstance(box_cif_description, ConstInt):
return
cif_description = box_cif_description.getint()
cif_description = llmemory.cast_int_to_adr(cif_description)
cif_description = llmemory.cast_adr_to_ptr(cif_description,
CIF_DESCRIPTION_P)
- extrainfo = op.getdescr().get_extra_info()
+ extrainfo = descr.get_extra_info()
calldescr = self.cpu.calldescrof_dynamic(cif_description, extrainfo)
if calldescr is None:
return
#
- extra_guards = []
- for i in range(num_extra_guards):
- extra_guards.append(self.history.operations.pop())
- extra_guards.reverse()
- #
- box_exchange_buffer = op.getarg(3)
- self.history.operations.pop()
+ box_exchange_buffer = argboxes[3]
arg_boxes = []
for i in range(cif_description.nargs):
@@ -3010,12 +2993,14 @@
ofs = cif_description.exchange_args[i]
assert ofs % itemsize == 0 # alignment check
if kind == 'i':
- box_arg = self.history.record(rop.GETARRAYITEM_RAW_I,
+ box_arg = self.history.record(
+ rop.GETARRAYITEM_RAW_I,
[box_exchange_buffer,
ConstInt(ofs // itemsize)],
0, descr)
elif kind == 'f':
- box_arg = self.history.record(rop.GETARRAYITEM_RAW_F,
+ box_arg = self.history.record(
+ rop.GETARRAYITEM_RAW_F,
[box_exchange_buffer,
ConstInt(ofs // itemsize)],
0.0, descr)
@@ -3028,15 +3013,22 @@
# (that is, errno and SetLastError/GetLastError on Windows)
# Note these flags match the ones in clibffi.ll_callback
c_saveall = ConstInt(rffi.RFFI_ERR_ALL | rffi.RFFI_ALT_ERRNO)
- if op.type == 'i':
- self.history.record(rop.CALL_RELEASE_GIL,
- [c_saveall, op.getarg(2)] + arg_boxes,
- box_result, calldescr)
- #
- self.history.operations.extend(extra_guards)
+ if tp == 'i':
+ value = executor.execute_varargs(self.cpu, self,
+ rop.CALL_MAY_FORCE_I,
+ argboxes, descr)
+ box_result = self.history.record(
+ rop.CALL_RELEASE_GIL_I, [c_saveall, argboxes[2]] + arg_boxes,
+ value, descr=calldescr)
+ elif tp == 'f':
+ xxx
+ box_result = self.history.record(
+ rop.CALL_RELEASE_GIL_F, [c_saveall, argboxes[2]] + arg_boxes,
+ value, descr=calldescr)
#
# note that the result is written back to the exchange_buffer by the
# special op libffi_save_result_{int,float}
+ return box_result
def direct_call_release_gil(self):
op = self.history.operations.pop()
diff --git a/rpython/jit/metainterp/resume.py b/rpython/jit/metainterp/resume.py
--- a/rpython/jit/metainterp/resume.py
+++ b/rpython/jit/metainterp/resume.py
@@ -220,11 +220,13 @@
elif box in liveboxes:
tagged = liveboxes[box]
else:
+ is_virtual = False
if box.type == 'r':
info = optimizer.getptrinfo(box)
- is_virtual = (info is not None and info.is_virtual())
- else:
- is_virtual = False
+ is_virtual = (info and info.is_virtual())
+ if box.type == 'i':
+ info = optimizer.getrawptrinfo(box, create=False)
+ is_virtual = (info and info.is_virtual())
if is_virtual:
tagged = tag(v, TAGVIRTUAL)
v += 1
@@ -390,7 +392,11 @@
liveboxes[i] = box
else:
assert tagbits == TAGVIRTUAL
- info = optimizer.getptrinfo(box)
+ if box.type == 'r':
+ info = optimizer.getptrinfo(box)
+ else:
+ assert box.type == 'i'
+ info = optimizer.getrawptrinfo(box)
info.visitor_walk_recursive(box, self, optimizer)
for setfield_op in pending_setfields:
diff --git a/rpython/jit/metainterp/test/test_executor.py b/rpython/jit/metainterp/test/test_executor.py
--- a/rpython/jit/metainterp/test/test_executor.py
+++ b/rpython/jit/metainterp/test/test_executor.py
@@ -97,38 +97,38 @@
# cases with a descr
# arity == -1
argboxes = [InputArgInt(321), ConstInt(123)]
- box = _execute_nonspec(cpu, FakeMetaInterp(), rop.CALL_F,
+ box = _execute_arglist(cpu, FakeMetaInterp(), rop.CALL_F,
argboxes, FakeCallDescr())
assert box == 42.5
# arity == 0
- box = _execute_nonspec(cpu, None, rop.NEW, [], descr)
+ box = _execute_arglist(cpu, None, rop.NEW, [], descr)
assert box.fakeargs == ('new', descr)
# arity == 1
box1 = InputArgRef()
- box = _execute_nonspec(cpu, None, rop.ARRAYLEN_GC, [box1], descr)
+ box = _execute_arglist(cpu, None, rop.ARRAYLEN_GC, [box1], descr)
assert box == 55
# arity == 2
box2 = boxfloat(222.2)
fielddescr = FakeFieldDescr()
- _execute_nonspec(cpu, None, rop.SETFIELD_GC, [box1, box2], fielddescr)
+ _execute_arglist(cpu, None, rop.SETFIELD_GC, [box1, box2], fielddescr)
assert cpu.fakesetfield == (box1.getref_base(), box2.getfloat(),
fielddescr)
# arity == 3
box3 = InputArgInt(33)
arraydescr = FakeArrayDescr()
- _execute_nonspec(cpu, None, rop.SETARRAYITEM_GC, [box1, box3, box2],
+ _execute_arglist(cpu, None, rop.SETARRAYITEM_GC, [box1, box3, box2],
arraydescr)
assert cpu.fakesetarrayitem == (box1.getref_base(), box3.getint(),
box2.getfloat(), arraydescr)
# cases without descr
# arity == 1
- box = _execute_nonspec(cpu, None, rop.INT_INVERT, [box3])
+ box = _execute_arglist(cpu, None, rop.INT_INVERT, [box3])
assert box == ~33
# arity == 2
- box = _execute_nonspec(cpu, None, rop.INT_LSHIFT, [box3, InputArgInt(3)])
+ box = _execute_arglist(cpu, None, rop.INT_LSHIFT, [box3, InputArgInt(3)])
assert box == 33 << 3
# arity == 3
- _execute_nonspec(cpu, None, rop.STRSETITEM, [box1, InputArgInt(3), box3])
+ _execute_arglist(cpu, None, rop.STRSETITEM, [box1, InputArgInt(3), box3])
assert cpu.fakestrsetitem == (box1.getref_base(), 3, box3.getint())
# ints
@@ -245,7 +245,7 @@
def test_int_ops():
cpu = FakeCPU()
for opnum, boxargs, retvalue in get_int_tests():
- r = _execute_nonspec(cpu, None, opnum, boxargs)
+ r = _execute_arglist(cpu, None, opnum, boxargs)
assert r == retvalue
# floats
@@ -315,7 +315,7 @@
def test_float_ops():
cpu = FakeCPU()
for opnum, boxargs, rettype, retvalue in get_float_tests(cpu):
- res = _execute_nonspec(cpu, None, opnum, boxargs)
+ res = _execute_arglist(cpu, None, opnum, boxargs)
assert res == retvalue
def make_args_for_op(op, a, b):
More information about the pypy-commit
mailing list