[pypy-commit] pypy optresult: merge recent-ops
fijal
noreply at buildbot.pypy.org
Fri Mar 6 16:22:34 CET 2015
Author: Maciej Fijalkowski <fijall at gmail.com>
Branch: optresult
Changeset: r76255:456f069a2ff4
Date: 2015-03-06 17:22 +0200
http://bitbucket.org/pypy/pypy/changeset/456f069a2ff4/
Log: merge recent-ops
diff --git a/lib_pypy/pyrepl/readline.py b/lib_pypy/pyrepl/readline.py
--- a/lib_pypy/pyrepl/readline.py
+++ b/lib_pypy/pyrepl/readline.py
@@ -73,7 +73,6 @@
assume_immutable_completions = False
use_brackets = False
sort_in_column = True
- tab_insert_spaces_if_stem_is_empty = False
def error(self, msg="none"):
pass # don't show error messages by default
@@ -87,7 +86,7 @@
return ''.join(b[p+1:self.pos])
def get_completions(self, stem):
- if len(stem) == 0 and self.tab_insert_spaces_if_stem_is_empty:
+ if len(stem) == 0 and self.more_lines is not None:
b = self.buffer
p = self.pos
while p > 0 and b[p - 1] != '\n':
@@ -141,12 +140,16 @@
def collect_keymap(self):
return super(ReadlineAlikeReader, self).collect_keymap() + (
- (r'\n', 'maybe-accept'),)
+ (r'\n', 'maybe-accept'),
+ (r'\<backspace>', 'backspace-dedent'),
+ )
def __init__(self, console):
super(ReadlineAlikeReader, self).__init__(console)
self.commands['maybe_accept'] = maybe_accept
self.commands['maybe-accept'] = maybe_accept
+ self.commands['backspace_dedent'] = backspace_dedent
+ self.commands['backspace-dedent'] = backspace_dedent
def after_command(self, cmd):
super(ReadlineAlikeReader, self).after_command(cmd)
@@ -164,6 +167,28 @@
if self.pos > len(self.buffer):
self.pos = len(self.buffer)
+def _get_this_line_indent(buffer, pos):
+ indent = 0
+ while pos > 0 and buffer[pos - 1] in " \t":
+ indent += 1
+ pos -= 1
+ if pos > 0 and buffer[pos - 1] == "\n":
+ return indent
+ return 0
+
+def _get_previous_line_indent(buffer, pos):
+ prevlinestart = pos
+ while prevlinestart > 0 and buffer[prevlinestart - 1] != "\n":
+ prevlinestart -= 1
+ prevlinetext = prevlinestart
+ while prevlinetext < pos and buffer[prevlinetext] in " \t":
+ prevlinetext += 1
+ if prevlinetext == pos:
+ indent = None
+ else:
+ indent = prevlinetext - prevlinestart
+ return prevlinestart, indent
+
class maybe_accept(commands.Command):
def do(self):
r = self.reader
@@ -172,13 +197,39 @@
# if there are already several lines and the cursor
# is not on the last one, always insert a new \n.
text = r.get_unicode()
- if "\n" in r.buffer[r.pos:]:
+ if ("\n" in r.buffer[r.pos:] or
+ (r.more_lines is not None and r.more_lines(text))):
+ #
+ # auto-indent the next line like the previous line
+ prevlinestart, indent = _get_previous_line_indent(r.buffer, r.pos)
r.insert("\n")
- elif r.more_lines is not None and r.more_lines(text):
- r.insert("\n")
+ if indent:
+ for i in range(prevlinestart, prevlinestart + indent):
+ r.insert(r.buffer[i])
else:
self.finish = 1
+class backspace_dedent(commands.Command):
+ def do(self):
+ r = self.reader
+ b = r.buffer
+ if r.pos > 0:
+ repeat = 1
+ if b[r.pos - 1] != "\n":
+ indent = _get_this_line_indent(b, r.pos)
+ if indent > 0:
+ ls = r.pos - indent
+ while ls > 0:
+ ls, pi = _get_previous_line_indent(b, ls - 1)
+ if pi is not None and pi < indent:
+ repeat = indent - pi
+ break
+ r.pos -= repeat
+ del b[r.pos:r.pos + repeat]
+ r.dirty = 1
+ else:
+ self.reader.error("can't backspace at start")
+
# ____________________________________________________________
class _ReadlineWrapper(object):
@@ -212,15 +263,14 @@
boolean value is true.
"""
reader = self.get_reader()
- saved = reader.more_lines, reader.tab_insert_spaces_if_stem_is_empty
+ saved = reader.more_lines
try:
reader.more_lines = more_lines
reader.ps1 = reader.ps2 = ps1
reader.ps3 = reader.ps4 = ps2
- reader.tab_insert_spaces_if_stem_is_empty = True
return reader.readline(returns_unicode=returns_unicode)
finally:
- reader.more_lines, reader.tab_insert_spaces_if_stem_is_empty = saved
+ reader.more_lines = saved
def parse_and_bind(self, string):
pass # XXX we don't support parsing GNU-readline-style init files
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
@@ -211,15 +211,15 @@
# Else, synthesize the non overflowing op for optimize_default to
# reuse, as well as the reverse op
elif opnum == rop.INT_ADD_OVF:
- self.pure(rop.INT_ADD, args[:], result)
+ #self.pure(rop.INT_ADD, args[:], result)
self.pure(rop.INT_SUB, [result, args[1]], args[0])
self.pure(rop.INT_SUB, [result, args[0]], args[1])
elif opnum == rop.INT_SUB_OVF:
- self.pure(rop.INT_SUB, args[:], result)
+ #self.pure(rop.INT_SUB, args[:], result)
self.pure(rop.INT_ADD, [result, args[1]], args[0])
self.pure(rop.INT_SUB, [args[0], result], args[1])
- elif opnum == rop.INT_MUL_OVF:
- self.pure(rop.INT_MUL, args[:], result)
+ #elif opnum == rop.INT_MUL_OVF:
+ # self.pure(rop.INT_MUL, args[:], result)
self.emit_operation(op)
def optimize_GUARD_OVERFLOW(self, 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
@@ -323,6 +323,9 @@
def replace_op_with(self, op, newopnum, args=None, descr=None):
return self.optimizer.replace_op_with(op, newopnum, args, descr)
+ def get_box_replacement(self, box):
+ return self.optimizer.get_box_replacement(box)
+
def make_constant(self, box, constbox):
return self.optimizer.make_constant(box, constbox)
@@ -399,6 +402,7 @@
class Optimizer(Optimization):
exporting_state = False
+ emitting_dissabled = False
def __init__(self, metainterp_sd, jitdriver_sd, loop, optimizations=None):
self.metainterp_sd = metainterp_sd
@@ -609,7 +613,7 @@
if clear:
self.clear_newoperations()
for op in self.loop.operations:
- self._last_emitted_op = None
+ self._really_emitted_operation = None
self.first_optimization.propagate_forward(op)
self.loop.operations = self.get_newoperations()
self.loop.quasi_immutable_deps = self.quasi_immutable_deps
@@ -651,9 +655,12 @@
op = self.store_final_boxes_in_guard(guard_op, pendingfields)
elif op.can_raise():
self.exception_might_have_happened = True
- self._last_emitted_op = op
+ self._really_emitted_operation = op
self._newoperations.append(op)
+ def getlastop(self):
+ return self._really_emitted_operation
+
def replace_guard_op(self, old_op_pos, new_op):
old_op = self._newoperations[old_op_pos]
assert old_op.is_guard()
@@ -705,16 +712,6 @@
descr.make_a_counter_per_value(op)
return op
- def make_args_key(self, opnum, arglist, descr):
- n = len(arglist)
- args = [None] * (n + 2)
- for i in range(n):
- arg = self.get_box_replacement(arglist[i])
- args[i] = arg
- args[n] = ConstInt(opnum)
- args[n + 1] = descr
- return args
-
def optimize_default(self, op):
self.emit_operation(op)
diff --git a/rpython/jit/metainterp/optimizeopt/pure.py b/rpython/jit/metainterp/optimizeopt/pure.py
--- a/rpython/jit/metainterp/optimizeopt/pure.py
+++ b/rpython/jit/metainterp/optimizeopt/pure.py
@@ -1,13 +1,59 @@
from rpython.jit.metainterp.optimizeopt.optimizer import Optimization, REMOVED
-from rpython.jit.metainterp.resoperation import rop, ResOperation, OpHelpers
-from rpython.jit.metainterp.optimizeopt.util import (make_dispatcher_method,
- args_dict)
+from rpython.jit.metainterp.resoperation import rop, ResOperation
+from rpython.jit.metainterp.optimizeopt.util import make_dispatcher_method
+
+
+class RecentPureOps(object):
+ REMEMBER_LIMIT = 16
+
+ def __init__(self):
+ self.lst = [None] * self.REMEMBER_LIMIT
+ self.next_index = 0
+
+ def add(self, op):
+ next_index = self.next_index
+ self.next_index = (next_index + 1) % self.REMEMBER_LIMIT
+ self.lst[next_index] = op
+
+ def lookup1(self, box0, descr):
+ for i in range(self.REMEMBER_LIMIT):
+ op = self.lst[i]
+ if op is None:
+ break
+ if op.getarg(0).same_box(box0) and op.getdescr() is descr:
+ return op
+ return None
+
+ def lookup2(self, box0, box1, descr):
+ for i in range(self.REMEMBER_LIMIT):
+ op = self.lst[i]
+ if op is None:
+ break
+ if (op.getarg(0).same_box(box0) and op.getarg(1).same_box(box1)
+ and op.getdescr() is descr):
+ return op
+ return None
+
+ def lookup(self, optimizer, op):
+ numargs = op.numargs()
+ if numargs == 1:
+ return self.lookup1(optimizer.get_box_replacement(op.getarg(0)),
+ op.getdescr())
+ elif numargs == 2:
+ return self.lookup2(optimizer.get_box_replacement(op.getarg(0)),
+ optimizer.get_box_replacement(op.getarg(1)),
+ op.getdescr())
+ else:
+ assert False
+
class OptPure(Optimization):
def __init__(self):
self.postponed_op = None
- self.pure_operations = args_dict()
+ self._pure_operations = [None] * (rop._ALWAYS_PURE_LAST -
+ rop._ALWAYS_PURE_FIRST)
self.call_pure_positions = []
+ self.extra_call_pure = []
def propagate_forward(self, op):
dispatch_opt(self, op)
@@ -25,7 +71,7 @@
else:
nextop = None
- args = None
+ save = False
if canfold:
for i in range(op.numargs()):
if self.get_constant_box(op.getarg(i)) is None:
@@ -39,22 +85,34 @@
return
# did we do the exact same operation already?
- if 0:
- args = self.optimizer.make_args_key(op.getopnum(),
- op.getarglist(), op.getdescr())
- oldval = self.pure_operations.get(args, None)
- if oldval is not None:
- self.optimizer.make_equal_to(op, oldval)
- return
+ recentops = self.getrecentops(op.getopnum())
+ save = True
+ oldop = recentops.lookup(self.optimizer, op)
+ if oldop is not None:
+ self.optimizer.make_equal_to(op, oldop)
+ return
# otherwise, the operation remains
self.emit_operation(op)
if op.returns_bool_result():
self.getintbound(op).make_bool()
+ if save:
+ realop = self.get_box_replacement(op)
+ recentops = self.getrecentops(realop.getopnum())
+ recentops.add(realop)
if nextop:
self.emit_operation(nextop)
- #if args is not None:
- # self.pure_operations[args] = self.getvalue(op)
+
+ def getrecentops(self, opnum):
+ if rop._OVF_FIRST <= opnum <= rop._OVF_LAST:
+ opnum = opnum - rop._OVF_FIRST
+ else:
+ opnum = opnum - rop._ALWAYS_PURE_FIRST
+ assert 0 <= opnum < len(self._pure_operations)
+ recentops = self._pure_operations[opnum]
+ if recentops is None:
+ self._pure_operations[opnum] = recentops = RecentPureOps()
+ return recentops
def optimize_CALL_PURE_I(self, op):
# Step 1: check if all arguments are constant
@@ -67,28 +125,45 @@
# Step 2: check if all arguments are the same as a previous
# CALL_PURE.
- args = self.optimizer.make_args_key(op.getopnum(), op.getarglist(),
- op.getdescr())
- oldval = self.pure_operations.get(args, None)
- if oldval is not None:
- # this removes a CALL_PURE that has the same (non-constant)
- # arguments as a previous CALL_PURE.
- self.make_equal_to(op, oldval)
- self.last_emitted_operation = REMOVED
- return
- else:
- self.pure_operations[args] = self.getvalue(op)
+ for pos in self.call_pure_positions:
+ old_op = self.optimizer._newoperations[pos]
+ if self.optimize_call_pure(op, old_op):
+ return
+ for old_op in self.extra_call_pure:
+ if self.optimize_call_pure(op, old_op):
+ return
# replace CALL_PURE with just CALL
args = op.getarglist()
opnum = OpHelpers.call_for_descr(op.getdescr())
newop = self.optimizer.replace_op_with(op, opnum)
self.emit_operation(newop)
- self.call_pure_positions.append(len(self.optimizer._newoperations) - 1)
+ if self.optimizer.emitting_dissabled:
+ self.extra_call_pure.append(op) # XXX
+ else:
+ self.call_pure_positions.append(len(self.optimizer._newoperations)
+ - 1)
optimize_CALL_PURE_R = optimize_CALL_PURE_I
optimize_CALL_PURE_F = optimize_CALL_PURE_I
optimize_CALL_PURE_N = optimize_CALL_PURE_I
+ def optimize_call_pure(self, op, old_op):
+ if (op.numargs() != old_op.numargs() or
+ op.getdescr() is not old_op.getdescr()):
+ return False
+ for i, box in enumerate(old_op.getarglist()):
+ if not self.get_box_replacement(op.getarg(i)).same_box(box):
+ break
+ else:
+ # all identical
+ # this removes a CALL_PURE that has the same (non-constant)
+ # arguments as a previous CALL_PURE.
+ oldvalue = self.getvalue(old_op.result)
+ self.make_equal_to(op.result, oldvalue)
+ self.last_emitted_operation = REMOVED
+ return True
+ return False
+
def optimize_GUARD_NO_EXCEPTION(self, op):
if self.last_emitted_operation is REMOVED:
# it was a CALL_PURE that was killed; so we also kill the
@@ -102,18 +177,18 @@
def setup(self):
self.optimizer.optpure = self
- def pure(self, opnum, args, result):
- return # XXX
- key = self.optimizer.make_args_key(opnum, args, None)
- if key not in self.pure_operations:
- self.pure_operations[key] = self.getvalue(result)
+ def pure(self, opnum, args, op):
+ op = self.get_box_replacement(op)
+ recentops = self.getrecentops(opnum)
+ recentops.add(op)
def has_pure_result(self, opnum, args, descr):
- key = self.optimizer.make_args_key(opnum, args, descr)
- return self.pure_operations.get(key, None) is not None
+ return False
+ # XXX
- def get_pure_result(self, key):
- return self.pure_operations.get(key, None)
+ def get_pure_result(self, op):
+ recentops = self.getrecentops(op.getopnum())
+ return recentops.lookup(self.optimizer, op)
def produce_potential_short_preamble_ops(self, sb):
ops = sb.optimizer._newoperations
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
@@ -27,16 +27,15 @@
def propagate_forward(self, op):
if op.boolinverse != -1 or op.boolreflex != -1:
- args = self.optimizer.make_args_key(op.getopnum(),
- op.getarglist(), op.getdescr())
- if self.find_rewritable_bool(op, args):
+ if self.find_rewritable_bool(op):
return
dispatch_opt(self, op)
def try_boolinvers(self, op, targs):
- value = self.get_pure_result(targs)
- if value is not None:
+ oldop = self.get_pure_result(targs)
+ if oldop is not None:
+ value = self.getvalue(oldop.result)
if value.is_constant():
if value.box.same_constant(CONST_1):
self.make_constant(op, CONST_0)
@@ -48,30 +47,30 @@
return False
- def find_rewritable_bool(self, op, args):
+ def find_rewritable_bool(self, op):
oldopnum = op.boolinverse
+ arg0 = op.getarg(0)
+ arg1 = op.getarg(1)
if oldopnum != -1:
- targs = self.optimizer.make_args_key(oldopnum, [args[0], args[1]],
- None)
- if self.try_boolinvers(op, targs):
+ top = ResOperation(oldopnum, [arg0, arg1], None)
+ if self.try_boolinvers(op, top):
return True
oldopnum = op.boolreflex # FIXME: add INT_ADD, INT_MUL
if oldopnum != -1:
- targs = self.optimizer.make_args_key(oldopnum, [args[1], args[0]],
- None)
- oldval = self.get_pure_result(targs)
- if oldval is not None:
- self.make_equal_to(op, oldval)
+ top = ResOperation(oldopnum, [arg1, arg0], None)
+ oldop = self.get_pure_result(top)
+ if oldop is not None:
+ self.optimizer.make_equal_to(op.result,
+ self.getvalue(oldop.result), True)
return True
if op.boolreflex == -1:
return False
oldopnum = opclasses[op.boolreflex].boolinverse
if oldopnum != -1:
- targs = self.optimizer.make_args_key(oldopnum, [args[1], args[0]],
- None)
- if self.try_boolinvers(op, targs):
+ top = ResOperation(oldopnum, [arg1, arg0], None)
+ if self.try_boolinvers(op, top):
return True
return False
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py
@@ -4759,6 +4759,7 @@
self.optimize_loop(ops, expected)
def test_complains_getfieldpure_setfield(self):
+ py.test.skip("disabled for now")
from rpython.jit.metainterp.optimizeopt.heap import BogusPureField
ops = """
[p3]
diff --git a/rpython/jit/metainterp/resoperation.py b/rpython/jit/metainterp/resoperation.py
--- a/rpython/jit/metainterp/resoperation.py
+++ b/rpython/jit/metainterp/resoperation.py
@@ -779,7 +779,7 @@
'_CANRAISE_LAST', # ----- end of can_raise operations -----
'_OVF_FIRST', # ----- start of is_ovf operations -----
- 'INT_ADD_OVF/2/i',
+ 'INT_ADD_OVF/2/i', # note that the orded has to match INT_ADD order
'INT_SUB_OVF/2/i',
'INT_MUL_OVF/2/i',
'_OVF_LAST', # ----- end of is_ovf operations -----
More information about the pypy-commit
mailing list