[pypy-commit] pypy speedup-list-comprehension: (fijal, arigo) reintroduce oopspecs and optimize newlist_hint correctly
fijal
noreply at buildbot.pypy.org
Fri Mar 9 19:20:59 CET 2012
Author: Maciej Fijalkowski <fijall at gmail.com>
Branch: speedup-list-comprehension
Changeset: r53287:ded3dd394915
Date: 2012-03-09 10:19 -0800
http://bitbucket.org/pypy/pypy/changeset/ded3dd394915/
Log: (fijal, arigo) reintroduce oopspecs and optimize newlist_hint
correctly in the JIT
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -7,7 +7,8 @@
from pypy.interpreter.miscutils import ThreadLocals
from pypy.tool.cache import Cache
from pypy.tool.uid import HUGEVAL_BYTES
-from pypy.rlib.objectmodel import we_are_translated, newlist, compute_unique_id
+from pypy.rlib.objectmodel import we_are_translated, newlist_hint,\
+ compute_unique_id
from pypy.rlib.debug import make_sure_not_resized
from pypy.rlib.timer import DummyTimer, Timer
from pypy.rlib.rarithmetic import r_uint
@@ -833,7 +834,7 @@
items = []
else:
try:
- items = newlist(lgt_estimate)
+ items = newlist_hint(lgt_estimate)
except MemoryError:
items = [] # it might have lied
#
diff --git a/pypy/interpreter/pyopcode.py b/pypy/interpreter/pyopcode.py
--- a/pypy/interpreter/pyopcode.py
+++ b/pypy/interpreter/pyopcode.py
@@ -10,14 +10,13 @@
from pypy.interpreter import gateway, function, eval, pyframe, pytraceback
from pypy.interpreter.pycode import PyCode
from pypy.tool.sourcetools import func_with_new_name
-from pypy.rlib.objectmodel import we_are_translated, newlist
+from pypy.rlib.objectmodel import we_are_translated
from pypy.rlib import jit, rstackovf
from pypy.rlib.rarithmetic import r_uint, intmask
from pypy.rlib.unroll import unrolling_iterable
from pypy.rlib.debug import check_nonneg
-from pypy.tool.stdlib_opcode import (bytecode_spec, host_bytecode_spec,
- unrolling_all_opcode_descs, opmap,
- host_opmap)
+from pypy.tool.stdlib_opcode import (bytecode_spec,
+ unrolling_all_opcode_descs)
def unaryoperation(operationname):
"""NOT_RPYTHON"""
diff --git a/pypy/jit/codewriter/jtransform.py b/pypy/jit/codewriter/jtransform.py
--- a/pypy/jit/codewriter/jtransform.py
+++ b/pypy/jit/codewriter/jtransform.py
@@ -365,7 +365,7 @@
def handle_builtin_call(self, op):
oopspec_name, args = support.decode_builtin_call(op)
# dispatch to various implementations depending on the oopspec_name
- if oopspec_name.startswith('list.') or oopspec_name == 'newlist':
+ if oopspec_name.startswith('list.') or oopspec_name.startswith('newlist'):
prepare = self._handle_list_call
elif oopspec_name.startswith('stroruni.'):
prepare = self._handle_stroruni_call
@@ -1494,6 +1494,14 @@
arraydescr, v_length],
op.result)
+ def do_resizable_newlist_hint(self, op, args, arraydescr, lengthdescr,
+ itemsdescr, structdescr):
+ v_hint = self._get_initial_newlist_length(op, args)
+ return SpaceOperation('newlist_hint',
+ [structdescr, lengthdescr, itemsdescr,
+ arraydescr, v_hint],
+ op.result)
+
def do_resizable_list_getitem(self, op, args, arraydescr, lengthdescr,
itemsdescr, structdescr):
v_index, extraop = self._prepare_list_getset(op, lengthdescr, args,
diff --git a/pypy/jit/codewriter/support.py b/pypy/jit/codewriter/support.py
--- a/pypy/jit/codewriter/support.py
+++ b/pypy/jit/codewriter/support.py
@@ -144,6 +144,10 @@
_ll_1_newlist.need_result_type = True
_ll_2_newlist.need_result_type = True
+def _ll_1_newlist_hint(LIST, hint):
+ return LIST.ll_newlist_hint(hint)
+_ll_1_newlist_hint.need_result_type = True
+
def _ll_1_list_len(l):
return l.ll_length()
def _ll_2_list_getitem(l, index):
diff --git a/pypy/jit/metainterp/blackhole.py b/pypy/jit/metainterp/blackhole.py
--- a/pypy/jit/metainterp/blackhole.py
+++ b/pypy/jit/metainterp/blackhole.py
@@ -982,6 +982,15 @@
cpu.bh_setfield_gc_r(result, itemsdescr, items)
return result
+ @arguments("cpu", "d", "d", "d", "d", "i", returns="r")
+ def bhimpl_newlist_hint(cpu, structdescr, lengthdescr, itemsdescr,
+ arraydescr, lengthhint):
+ result = cpu.bh_new(structdescr)
+ cpu.bh_setfield_gc_i(result, lengthdescr, 0)
+ items = cpu.bh_new_array(arraydescr, lengthhint)
+ cpu.bh_setfield_gc_r(result, itemsdescr, items)
+ return result
+
@arguments("cpu", "r", "d", "d", "i", returns="i")
def bhimpl_getlistitem_gc_i(cpu, lst, itemsdescr, arraydescr, index):
items = cpu.bh_getfield_gc_r(lst, itemsdescr)
diff --git a/pypy/jit/metainterp/pyjitpl.py b/pypy/jit/metainterp/pyjitpl.py
--- a/pypy/jit/metainterp/pyjitpl.py
+++ b/pypy/jit/metainterp/pyjitpl.py
@@ -509,6 +509,15 @@
self._opimpl_setfield_gc_any(sbox, itemsdescr, abox)
return sbox
+ @arguments("descr", "descr", "descr", "descr", "box")
+ def opimpl_newlist_hint(self, structdescr, lengthdescr, itemsdescr,
+ arraydescr, sizehintbox):
+ sbox = self.opimpl_new(structdescr)
+ self._opimpl_setfield_gc_any(sbox, lengthdescr, history.CONST_FALSE)
+ abox = self.opimpl_new_array(arraydescr, sizehintbox)
+ self._opimpl_setfield_gc_any(sbox, itemsdescr, abox)
+ return sbox
+
@arguments("box", "descr", "descr", "box")
def _opimpl_getlistitem_gc_any(self, listbox, itemsdescr, arraydescr,
indexbox):
diff --git a/pypy/jit/metainterp/test/test_list.py b/pypy/jit/metainterp/test/test_list.py
--- a/pypy/jit/metainterp/test/test_list.py
+++ b/pypy/jit/metainterp/test/test_list.py
@@ -1,4 +1,5 @@
import py
+from pypy.rlib.objectmodel import newlist_hint
from pypy.rlib.jit import JitDriver
from pypy.jit.metainterp.test.support import LLJitMixin, OOJitMixin
@@ -228,6 +229,27 @@
self.check_resops({'jump': 1, 'int_gt': 2, 'int_add': 2,
'guard_true': 2, 'int_sub': 2})
+ def test_newlist_hint(self):
+ def f(i):
+ l = newlist_hint(i)
+ return len(l)
+
+ r = self.interp_operations(f, [3])
+ assert r == 0
+
+ def test_newlist_hint_optimized(self):
+ driver = JitDriver(greens = [], reds = ['i'])
+
+ def f(i):
+ while i > 0:
+ driver.jit_merge_point(i=i)
+ l = newlist_hint(5)
+ l.append(1)
+ i -= l[0]
+
+ self.meta_interp(f, [10], listops=True)
+ self.check_resops(new_array=0, call=0)
+
class TestOOtype(ListTests, OOJitMixin):
pass
diff --git a/pypy/objspace/std/listobject.py b/pypy/objspace/std/listobject.py
--- a/pypy/objspace/std/listobject.py
+++ b/pypy/objspace/std/listobject.py
@@ -7,7 +7,7 @@
from pypy.objspace.std.sliceobject import W_SliceObject, normalize_simple_slice
from pypy.objspace.std import slicetype
from pypy.interpreter import gateway, baseobjspace
-from pypy.rlib.objectmodel import instantiate, specialize, newlist
+from pypy.rlib.objectmodel import instantiate, specialize, newlist_hint
from pypy.rlib.listsort import make_timsort_class
from pypy.rlib import rerased, jit, debug
from pypy.interpreter.argument import Signature
@@ -676,7 +676,7 @@
def get_empty_storage(self, sizehint):
if sizehint == -1:
return self.erase([])
- return self.erase(newlist(sizehint))
+ return self.erase(newlist_hint(sizehint))
def clone(self, w_list):
l = self.unerase(w_list.lstorage)
diff --git a/pypy/rlib/objectmodel.py b/pypy/rlib/objectmodel.py
--- a/pypy/rlib/objectmodel.py
+++ b/pypy/rlib/objectmodel.py
@@ -233,20 +233,22 @@
# ____________________________________________________________
-def newlist(sizehint=0):
+def newlist_hint(sizehint=0):
""" Create a new list, but pass a hint how big the size should be
preallocated
"""
return []
class Entry(ExtRegistryEntry):
- _about_ = newlist
+ _about_ = newlist_hint
def compute_result_annotation(self, s_sizehint):
from pypy.annotation.model import SomeInteger
assert isinstance(s_sizehint, SomeInteger)
- return self.bookkeeper.newlist()
+ s_l = self.bookkeeper.newlist()
+ s_l.listdef.listitem.resize()
+ return s_l
def specialize_call(self, orig_hop, i_sizehint=None):
from pypy.rpython.rlist import rtype_newlist
diff --git a/pypy/rpython/lltypesystem/rlist.py b/pypy/rpython/lltypesystem/rlist.py
--- a/pypy/rpython/lltypesystem/rlist.py
+++ b/pypy/rpython/lltypesystem/rlist.py
@@ -60,7 +60,6 @@
ITEMARRAY = GcArray(ITEM,
adtmeths = ADTIFixedList({
"ll_newlist": ll_fixed_newlist,
- "ll_newlist_hint": ll_fixed_newlist,
"ll_newemptylist": ll_fixed_newemptylist,
"ll_length": ll_fixed_length,
"ll_items": ll_fixed_items,
@@ -262,6 +261,7 @@
l.items = malloc(LIST.items.TO, length)
return l
ll_newlist = typeMethod(ll_newlist)
+ll_newlist.oopspec = 'newlist(length)'
def ll_newlist_hint(LIST, lengthhint):
ll_assert(lengthhint >= 0, "negative list length")
@@ -270,6 +270,7 @@
l.items = malloc(LIST.items.TO, lengthhint)
return l
ll_newlist_hint = typeMethod(ll_newlist_hint)
+ll_newlist_hint.oopspec = 'newlist_hint(lengthhint)'
# should empty lists start with no allocated memory, or with a preallocated
# minimal number of entries? XXX compare memory usage versus speed, and
@@ -292,9 +293,11 @@
l.items = _ll_new_empty_item_array(LIST)
return l
ll_newemptylist = typeMethod(ll_newemptylist)
+ll_newemptylist.oopspec = 'newlist(0)'
def ll_length(l):
return l.length
+ll_length.oopspec = 'list.len(l)'
def ll_items(l):
return l.items
@@ -302,10 +305,12 @@
def ll_getitem_fast(l, index):
ll_assert(index < l.length, "getitem out of bounds")
return l.ll_items()[index]
+ll_getitem_fast.oopspec = 'list.getitem(l, index)'
def ll_setitem_fast(l, index, item):
ll_assert(index < l.length, "setitem out of bounds")
l.ll_items()[index] = item
+ll_setitem_fast.oopspec = 'list.setitem(l, index, item)'
# fixed size versions
@@ -314,13 +319,17 @@
ll_assert(length >= 0, "negative fixed list length")
l = malloc(LIST, length)
return l
+ll_fixed_newlist = typeMethod(ll_fixed_newlist)
+ll_fixed_newlist.oopspec = 'newlist(length)'
@typeMethod
def ll_fixed_newemptylist(LIST):
return ll_fixed_newlist(LIST, 0)
+ll_fixed_newemptylist = typeMethod(ll_fixed_newemptylist)
def ll_fixed_length(l):
return len(l)
+ll_fixed_length.oopspec = 'list.len(l)'
ll_fixed_length._always_inline_ = True
def ll_fixed_items(l):
@@ -329,12 +338,12 @@
def ll_fixed_getitem_fast(l, index):
ll_assert(index < len(l), "fixed getitem out of bounds")
return l[index]
-ll_fixed_getitem_fast._always_inline_ = True
+ll_fixed_getitem_fast.oopspec = 'list.getitem(l, index)'
def ll_fixed_setitem_fast(l, index, item):
ll_assert(index < len(l), "fixed setitem out of bounds")
l[index] = item
-ll_fixed_setitem_fast._always_inline_ = True
+ll_fixed_setitem_fast.oopspec = 'list.setitem(l, index, item)'
def newlist(llops, r_list, items_v, v_sizehint=None):
LIST = r_list.LIST
diff --git a/pypy/rpython/test/test_rlist.py b/pypy/rpython/test/test_rlist.py
--- a/pypy/rpython/test/test_rlist.py
+++ b/pypy/rpython/test/test_rlist.py
@@ -1361,13 +1361,12 @@
("y[*]" in immutable_fields)
def test_hints(self):
- from pypy.rlib.objectmodel import newlist
- from pypy.rpython.annlowlevel import hlstr
+ from pypy.rlib.objectmodel import newlist_hint
strings = ['abc', 'def']
def f(i):
z = strings[i]
- x = newlist(sizehint=13)
+ x = newlist_hint(sizehint=13)
x += z
return ''.join(x)
More information about the pypy-commit
mailing list