Skip to content

Commit

Permalink
implement wrap_into_resizable_list and use it in listobject.py
Browse files Browse the repository at this point in the history
fix a YYY, add another one
  • Loading branch information
cfbolz committed Dec 19, 2024
1 parent cd52aff commit 2f869c0
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 9 deletions.
17 changes: 9 additions & 8 deletions pypy/objspace/std/listobject.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from rpython.rlib.listsort import make_timsort_class
from rpython.rlib.objectmodel import (
import_from_mixin, instantiate, newlist_hint, resizelist_hint, specialize,
resizable_list_extract_storage, we_are_translated)
resizable_list_extract_storage, wrap_into_resizable_list, we_are_translated)
from rpython.rlib.rarithmetic import ovfcheck, r_uint, intmask
from rpython.rlib import longlong2float
from rpython.tool.sourcetools import func_with_new_name
Expand Down Expand Up @@ -225,6 +225,7 @@ def listrepr(space, w_currently_in_repr, w_list):
def list_unroll_condition(w_list1, space, w_list2):
return (w_list1._unrolling_heuristic() or w_list2._unrolling_heuristic())

# YYY implement iterator_greenkey(!)

class W_ListObject(W_Root):
strategy = None
Expand Down Expand Up @@ -999,9 +1000,9 @@ def extend(self, w_list, w_any):
self._extend_from_list(w_list, w_any)
elif (isinstance(w_any, W_AbstractTupleObject) and
not w_any.user_overridden_class and
w_any.length() < UNROLL_CUTOFF
w_any.length() < UNROLL_CUTOFF and
w_list.length() > 0
):
# YYY should deal with w_list being empty specially
self._extend_from_tuple(w_list, w_any.tolist())
elif space.is_generator(w_any):
w_any.unpack_into_w(w_list)
Expand Down Expand Up @@ -2002,8 +2003,10 @@ def pop(self, w_list, index):
return w_res

def mul(self, w_list, times):
# YYY can be done without the extra copy?
res = self.unerase(w_list.lstorage)[:w_list.length()] * times
l = self.unerase(w_list.lstorage)
rl = wrap_into_resizable_list(l, w_list.length())
resl = rl * times
res = resizable_list_extract_storage(resl)
return W_ListObject.from_storage_and_strategy(
self.space, self.erase(res), self, len(res))

Expand Down Expand Up @@ -2099,9 +2102,7 @@ def find_or_count(self, w_list, w_obj, start, stop, count):
def getitems(self, w_list):
l = self.unerase(w_list.lstorage)
length = w_list.length()
# YYY allow wrapping into a resizable list
l = l[:length]
return l
return wrap_into_resizable_list(l, length)

# no sort() method here: W_ListObject.descr_sort() handles this
# case explicitly
Expand Down
41 changes: 41 additions & 0 deletions rpython/rlib/objectmodel.py
Original file line number Diff line number Diff line change
Expand Up @@ -569,6 +569,47 @@ def __setitem__(self, index, value):
def __repr__(self):
return "<FixedSizeList %r>" % (self._l, )

def wrap_into_resizable_list(l, size):
assert len(l) >= size
if len(l) == size:
if isinstance(l, FixedSizeList):
return l._l
return l
return l[:size]

def ll_wrap_into_resizable_list(cRESLIST, items, size):
from rpython.rtyper.lltypesystem.lltype import malloc
l = malloc(cRESLIST)
l.length = size
l.items = items
return l




class Entry(ExtRegistryEntry):
_about_ = wrap_into_resizable_list

def compute_result_annotation(self, s_l, s_size):
from rpython.annotator import model as annmodel
if annmodel.s_None.contains(s_l):
return s_l # first argument is only None so far, but we
# expect a generalization later
elif not isinstance(s_l, annmodel.SomeList):
raise annmodel.AnnotatorError("First argument must be a list")
s_l.listdef.never_resize()
s_res = s_l.listdef.offspring(self.bookkeeper)
s_res.listdef.resize()
return s_res

def specialize_call(self, hop):
from rpython.rtyper.lltypesystem import lltype
v_list, v_size = hop.inputargs(*hop.args_r)
cRESLIST = hop.inputconst(lltype.Void, hop.r_result.LIST)
hop.exception_cannot_occur()
return hop.gendirectcall(ll_wrap_into_resizable_list, cRESLIST, v_list, v_size)


# ____________________________________________________________
#
# id-like functions. The idea is that calling hash() or id() is not
Expand Down
15 changes: 14 additions & 1 deletion rpython/rlib/test/test_objectmodel.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
setitem_with_hash, getitem_with_hash, delitem_with_hash, import_from_mixin,
fetch_translated_config, try_inline, delitem_if_value_is, move_to_end,
never_allocate, dont_inline, list_get_physical_size,
dict_to_switch, resizable_list_extract_storage)
dict_to_switch, resizable_list_extract_storage, wrap_into_resizable_list)
from rpython.translator.translator import TranslationContext, graphof
from rpython.rtyper.test.tool import BaseRtypingTest
from rpython.rtyper.test.test_llinterp import interpret, LLException, gengraph
Expand Down Expand Up @@ -620,6 +620,19 @@ def f(z):
f(31)
interpret(f, [31])

def test_wrap_into_resizable_list():
def f(z):
l = [z, 0]
l2 = wrap_into_resizable_list(l, 1)
assert len(l2) == 1
assert l2[0] == z
l2[0] += 1
return l[0]
f(31)
res = interpret(f, [31])
assert res == 32


def test_iterkeys_with_hash():
def f(i):
d = {i + .0: 5, i + .5: 6}
Expand Down

0 comments on commit 2f869c0

Please sign in to comment.