Skip to content

Commit cac7160

Browse files
committed
Migrate to sq_item and mp_item slots
1 parent b79f1af commit cac7160

File tree

60 files changed

+1569
-494
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+1569
-494
lines changed

graalpython/com.oracle.graal.python.annotations/src/com/oracle/graal/python/annotations/Slot.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,9 @@
9494
enum SlotKind {
9595
nb_bool,
9696
sq_length,
97+
sq_item,
9798
mp_length,
99+
mp_subscript,
98100
tp_descr_get,
99101
tp_descr_set,
100102
tp_getattro,

graalpython/com.oracle.graal.python.processor/src/com/oracle/graal/python/processor/SlotsMapping.java

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ static String getSlotBaseClass(Slot s) {
5252
return switch (s.value()) {
5353
case nb_bool -> "TpSlotInquiry.TpSlotInquiryBuiltin";
5454
case sq_length, mp_length -> "TpSlotLen.TpSlotLenBuiltin" + getSuffix(s.isComplex());
55+
case sq_item -> "TpSlotSizeArgFun.TpSlotSizeArgFunBuiltin";
56+
case mp_subscript -> "TpSlotBinaryFunc.TpSlotMpSubscript";
5557
case tp_getattro -> "TpSlotGetAttr.TpSlotGetAttrBuiltin";
5658
case tp_descr_get -> "TpSlotDescrGet.TpSlotDescrGetBuiltin" + getSuffix(s.isComplex());
5759
case tp_descr_set -> "TpSlotDescrSet.TpSlotDescrSetBuiltin";
@@ -64,6 +66,8 @@ static String getSlotNodeBaseClass(Slot s) {
6466
case tp_descr_get -> "com.oracle.graal.python.builtins.objects.type.slots.TpSlotDescrGet.DescrGetBuiltinNode";
6567
case nb_bool -> "com.oracle.graal.python.builtins.objects.type.slots.TpSlotInquiry.NbBoolBuiltinNode";
6668
case sq_length, mp_length -> "com.oracle.graal.python.builtins.objects.type.slots.TpSlotLen.LenBuiltinNode";
69+
case sq_item -> "com.oracle.graal.python.builtins.objects.type.slots.TpSlotSizeArgFun.SqItemBuiltinNode";
70+
case mp_subscript -> "com.oracle.graal.python.builtins.objects.type.slots.TpSlotBinaryFunc.MpSubscriptBuiltinNode";
6771
case tp_getattro -> "com.oracle.graal.python.builtins.objects.type.slots.TpSlotGetAttr.GetAttrBuiltinNode";
6872
case tp_descr_set -> "com.oracle.graal.python.builtins.objects.type.slots.TpSlotDescrSet.DescrSetBuiltinNode";
6973
case tp_setattro -> "com.oracle.graal.python.builtins.objects.type.slots.TpSlotSetAttr.SetAttrBuiltinNode";
@@ -75,22 +79,24 @@ static String getUncachedExecuteSignature(SlotKind s) {
7579
case nb_bool -> "boolean executeUncached(Object self)";
7680
case tp_descr_get -> "Object executeUncached(Object self, Object obj, Object type)";
7781
case sq_length, mp_length -> "int executeUncached(Object self)";
78-
case tp_getattro, tp_descr_set, tp_setattro ->
82+
case tp_getattro, tp_descr_set, tp_setattro, sq_item, mp_subscript ->
7983
throw new AssertionError("Should not reach here: should be always complex");
8084
};
8185
}
8286

8387
static boolean supportsComplex(SlotKind s) {
8488
return switch (s) {
8589
case nb_bool -> false;
86-
case sq_length, mp_length, tp_getattro, tp_descr_get, tp_descr_set, tp_setattro -> true;
90+
case sq_length, mp_length, tp_getattro, tp_descr_get, tp_descr_set,
91+
tp_setattro, sq_item, mp_subscript ->
92+
true;
8793
};
8894
}
8995

9096
static boolean supportsSimple(SlotKind s) {
9197
return switch (s) {
9298
case nb_bool, sq_length, mp_length, tp_descr_get -> true;
93-
case tp_getattro, tp_descr_set, tp_setattro -> false;
99+
case tp_getattro, tp_descr_set, tp_setattro, sq_item, mp_subscript -> false;
94100
};
95101
}
96102

@@ -99,7 +105,7 @@ static String getUncachedExecuteCall(SlotKind s) {
99105
case nb_bool -> "executeBool(null, self)";
100106
case sq_length, mp_length -> "executeInt(null, self)";
101107
case tp_descr_get -> "execute(null, self, obj, type)";
102-
case tp_getattro, tp_descr_set, tp_setattro ->
108+
case tp_getattro, tp_descr_set, tp_setattro, sq_item, mp_subscript ->
103109
throw new AssertionError("Should not reach here: should be always complex");
104110
};
105111
}

graalpython/com.oracle.graal.python.test/src/com/oracle/graal/python/test/builtin/objects/TpSlotsTests.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,14 @@
4040
*/
4141
package com.oracle.graal.python.test.builtin.objects;
4242

43+
import java.util.EnumSet;
44+
4345
import org.junit.Assert;
4446
import org.junit.Test;
4547

4648
import com.oracle.graal.python.builtins.objects.type.TpSlots;
4749
import com.oracle.graal.python.builtins.objects.type.TpSlots.Builder;
50+
import com.oracle.graal.python.builtins.objects.type.TpSlots.TpSlotGroup;
4851
import com.oracle.graal.python.builtins.objects.type.TpSlots.TpSlotMeta;
4952
import com.oracle.graal.python.builtins.objects.type.slots.TpSlot;
5053
import com.oracle.graal.python.builtins.objects.type.slots.TpSlot.TpSlotNative;
@@ -99,14 +102,25 @@ public void testBuilderOptimizations2() {
99102
}
100103

101104
private static void verifySlots(TpSlots slots, Function<TpSlotMeta, Boolean> checkNonNullValue) {
105+
var groupsSeen = EnumSet.noneOf(TpSlotGroup.class);
102106
for (TpSlotMeta def : TpSlotMeta.VALUES) {
103107
TpSlot slotValue = def.getValue(slots);
104108
if (checkNonNullValue.apply(def)) {
105109
checkSlotValue(def, slotValue);
110+
groupsSeen.add(def.getGroup());
106111
} else {
107112
Assert.assertNull(def.name(), slotValue);
108113
}
109114
}
115+
for (TpSlotGroup group : TpSlotGroup.values()) {
116+
switch (group) {
117+
case NO_GROUP -> {
118+
}
119+
case AS_NUMBER -> Assert.assertEquals(slots.has_as_number(), groupsSeen.contains(group));
120+
case AS_SEQUENCE -> Assert.assertEquals(slots.has_as_sequence(), groupsSeen.contains(group));
121+
case AS_MAPPING -> Assert.assertEquals(slots.has_as_mapping(), groupsSeen.contains(group));
122+
}
123+
}
110124
}
111125

112126
private static void checkSlotValue(TpSlotMeta def, TpSlot slotValue) {

graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_abstract.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import array
4141
import collections
4242
import sys
43+
import mmap
4344

4445
from . import CPyExtTestCase, CPyExtFunction, CPyExtType, unhandled_error_compare
4546

@@ -177,6 +178,8 @@ def istypeof(obj, types):
177178
def _reference_getitem(args):
178179
seq = args[0]
179180
idx = args[1]
181+
if isinstanceof(seq, [mmap.mmap]):
182+
return seq[idx:(idx+1)]
180183
if not hasattr(seq, '__getitem__'):
181184
raise TypeError
182185
return seq.__getitem__(idx)
@@ -208,6 +211,13 @@ def wrapped_fun(args):
208211
return fun(args)
209212
return wrapped_fun
210213

214+
215+
def create_anon_mmap(data):
216+
mmap_object = mmap.mmap(-1, len(data) + 1)
217+
mmap_object.write(data)
218+
return mmap_object
219+
220+
211221
class NoNumber():
212222
pass
213223

@@ -1175,13 +1185,14 @@ class TestAbstract(CPyExtTestCase):
11751185
(DummyListSubclass(), 1),
11761186
('hello', 1),
11771187
(DictSubclassWithSequenceMethods(), 1),
1188+
(create_anon_mmap(b'hello world!'), 3),
11781189
),
11791190
resultspec="O",
11801191
argspec='On',
11811192
arguments=["PyObject* sequence", "Py_ssize_t idx"],
11821193
cmpfunc=unhandled_error_compare
11831194
)
1184-
1195+
11851196
test_PySequence_GetSlice = CPyExtFunction(
11861197
_wrap_slice_fun(lambda args: args[0][args[1]:args[2]]),
11871198
lambda: (
@@ -1331,6 +1342,7 @@ def _reference_delslice(args):
13311342
(['a', 'b', 'c'], 2),
13321343
([None], 0),
13331344
('hello', 0),
1345+
(create_anon_mmap(b'hello world!'), 3),
13341346
),
13351347
resultspec="O",
13361348
argspec='On',

graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_bytes.py

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -644,10 +644,7 @@ def test_tp_as_buffer_pickle(self):
644644

645645

646646
class TestNativeSubclass(unittest.TestCase):
647-
def test_builtins(self):
648-
b = BytesSubclass(b"hello")
649-
assert is_native_object(b)
650-
assert type(b) == BytesSubclass
647+
def _verify_common(self, b):
651648
assert b
652649
assert not BytesSubclass(b'')
653650
assert len(b) == 5
@@ -660,13 +657,11 @@ def test_builtins(self):
660657
assert b + b" world" == b"hello world"
661658
assert b * 2 == b"hellohello"
662659
assert list(b) == [ord('h'), ord('e'), ord('l'), ord('l'), ord('o')]
663-
assert repr(b) == "b'hello'"
664660
assert b.index(ord('l')) == 2
665661
assert b.count(ord('l')) == 2
666662
assert b.decode('ascii') == 'hello'
667663
assert BytesSubclass(b'hello ').strip() == b'hello'
668664
assert BytesSubclass(b',').join([b'a', BytesSubclass(b'b')]) == b'a,b'
669-
assert hash(b) == hash(b'hello')
670665
assert BytesSubclass(b'(%s)') % b'a' == b'(a)'
671666
assert b.startswith(b'h')
672667
assert b.endswith(b'o')
@@ -676,8 +671,43 @@ def test_builtins(self):
676671
assert b.upper() == b'HELLO'
677672
assert BytesSubclass(b'a,b').split(BytesSubclass(b',')) == [b'a', b'b']
678673

679-
def test_managed_subclass(self):
674+
def _verify_bytes(self, b):
675+
self._verify_common(b)
676+
assert is_native_object(b)
677+
assert repr(b) == "b'hello'", repr(b)
678+
assert hash(b) == hash(b'hello')
679+
680+
def _verify_bytearray(self, b):
681+
self._verify_common(b)
682+
# assert is_native_object(b) # TODO: BuiltinConstructors.ByteArrayNode doesnt allocate native objects
683+
self.assertRaises(TypeError, lambda: hash(b))
684+
685+
def test_bytes_subclass(self):
686+
b = BytesSubclass(b"hello")
687+
assert type(b) == BytesSubclass
688+
self._verify_bytes(b)
689+
690+
def test_managed_bytes_subclass(self):
680691
class ManagedSubclass(BytesSubclass):
681692
pass
682693

683-
assert is_native_object(ManagedSubclass(b"hello"))
694+
b = ManagedSubclass(b"hello")
695+
assert type(b) == ManagedSubclass
696+
self._verify_bytes(b)
697+
698+
def test_bytearray_subclass(self):
699+
b = ByteArraySubclass(b"hello")
700+
assert type(b) == ByteArraySubclass
701+
# TODO: if TypeNode.GetNameNode is equivalent to _PyType_Name, it should transform tp_name "abc.xzy" to "xyz"
702+
# assert repr(b) == "ByteArraySubclass(b'hello')", repr(b)
703+
self._verify_bytearray(b)
704+
705+
def test_managed_bytearray_subclass(self):
706+
class ArrManagedSubclass(ByteArraySubclass):
707+
pass
708+
709+
b = ArrManagedSubclass(b"hello")
710+
assert type(b) == ArrManagedSubclass
711+
# TODO: if TypeNode.GetNameNode is equivalent to _PyType_Name, it should transform tp_name "abc.xzy" to "xyz"
712+
# assert repr(b) == "ArrManagedSubclass(b'hello')", repr(b)
713+
self._verify_bytearray(b)

graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_object.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1312,7 +1312,8 @@ def test_slot_precedence(self):
13121312
# Note: len(obj) uses 'PyObject_Lenght' which does not use the attribute but first tries
13131313
# 'sq_length' and falls back to 'mp_length'. Therefore, we just look at '__len__' here.
13141314
assert obj.__len__() == 222
1315-
assert obj['hello'] == 'mp_subscript'
1315+
assert len(obj) == 111
1316+
assert obj['hello'] == 'mp_subscript', obj['hello']
13161317
assert obj + 'hello' == 'mas_nb_add'
13171318

13181319
def test_take_ownership(self):

graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_tp_slots.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -391,4 +391,8 @@ def test_sq_len_and_item():
391391
sq_item="my_sq_item")
392392
x = MySqLenItem()
393393
assert x[5] == 5
394+
assert x.__getitem__(5) == 5
394395
assert x[-1] == 9
396+
assert x.__getitem__(-1) == 9
397+
assert x[-20] == -10
398+
assert x.__getitem__(-20) == -10

graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_tuple.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -246,9 +246,7 @@ class TestPyTuple(CPyExtTestCase):
246246

247247

248248
class TestNativeSubclass(unittest.TestCase):
249-
def test_builtins(self):
250-
t = TupleSubclass(1, 2, 3)
251-
assert type(t) == TupleSubclass
249+
def _verify(self, t):
252250
assert is_native_object(t)
253251
assert t
254252
assert len(t) == 3
@@ -265,8 +263,16 @@ def test_builtins(self):
265263
assert t.index(2) == 1
266264
assert t.count(2) == 1
267265

266+
def test_builtins(self):
267+
t = TupleSubclass(1, 2, 3)
268+
assert type(t) == TupleSubclass
269+
self._verify(t)
270+
268271
def test_managed_sublclass(self):
269272
class ManagedSubclass(TupleSubclass):
270273
pass
271274

272-
assert is_native_object(ManagedSubclass(1, 2, 3))
275+
t = ManagedSubclass(1, 2, 3)
276+
assert is_native_object(t)
277+
assert type(t) == ManagedSubclass
278+
self._verify(t)

graalpython/com.oracle.graal.python.test/src/tests/test_mmap.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,3 +88,19 @@ def test_readline():
8888
m[1026] = b'b'[0]
8989
assert m.readline() == (b'\x00' * 1024) + b'\n'
9090
assert m.readline() == b'ab'
91+
92+
def test_iter():
93+
m = mmap.mmap(-1, 3)
94+
for i in range(0, 3):
95+
m[i] = i + 2
96+
97+
it = iter(m)
98+
assert next(it) == b'\x02'
99+
assert next(it) == b'\x03'
100+
assert next(it) == b'\x04'
101+
102+
l = list()
103+
for i in m:
104+
l.append(i)
105+
106+
assert l == [b'\x02', b'\x03', b'\x04']

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/PythonBuiltinClassType.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,8 @@
124124
import com.oracle.graal.python.builtins.modules.functools.LruCacheWrapperBuiltins;
125125
import com.oracle.graal.python.builtins.objects.NoneBuiltins;
126126
import com.oracle.graal.python.builtins.objects.array.ArrayBuiltins;
127+
import com.oracle.graal.python.builtins.objects.bytes.ByteArrayBuiltins;
128+
import com.oracle.graal.python.builtins.objects.bytes.BytesBuiltins;
127129
import com.oracle.graal.python.builtins.objects.bytes.BytesCommonBuiltins;
128130
import com.oracle.graal.python.builtins.objects.complex.ComplexBuiltins;
129131
import com.oracle.graal.python.builtins.objects.contextvars.ContextBuiltins;
@@ -200,8 +202,8 @@ public enum PythonBuiltinClassType implements TruffleObject {
200202
PBuiltinClassMethod("classmethod_descriptor", Flags.PRIVATE_DERIVED_WODICT, ClassmethodBuiltins.SLOTS),
201203
GetSetDescriptor("getset_descriptor", Flags.PRIVATE_DERIVED_WODICT, GetSetDescriptorTypeBuiltins.SLOTS),
202204
MemberDescriptor(J_MEMBER_DESCRIPTOR, Flags.PRIVATE_DERIVED_WODICT, MemberDescriptorBuiltins.SLOTS),
203-
PByteArray("bytearray", J_BUILTINS, BYTE_ARRAY_M_FLAGS, BytesCommonBuiltins.SLOTS),
204-
PBytes("bytes", J_BUILTINS, BYTES_M_FLAGS, BytesCommonBuiltins.SLOTS),
205+
PByteArray("bytearray", J_BUILTINS, BYTE_ARRAY_M_FLAGS, TpSlots.merge(BytesCommonBuiltins.SLOTS, ByteArrayBuiltins.SLOTS)),
206+
PBytes("bytes", J_BUILTINS, BYTES_M_FLAGS, TpSlots.merge(BytesCommonBuiltins.SLOTS, BytesBuiltins.SLOTS)),
205207
PCell("cell", Flags.PRIVATE_DERIVED_WODICT),
206208
PSimpleNamespace("SimpleNamespace", null, "types", Flags.PUBLIC_BASE_WDICT),
207209
PKeyWrapper("KeyWrapper", "_functools", "functools", Flags.PUBLIC_DERIVED_WODICT),

0 commit comments

Comments
 (0)