Skip to content

Commit d3cf0b1

Browse files
committed
return hardcoded __itemsize__ values for builtin types
1 parent a63c3b3 commit d3cf0b1

File tree

13 files changed

+292
-58
lines changed

13 files changed

+292
-58
lines changed

graalpython/com.oracle.graal.python.cext/src/bytesobject.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
// taken from CPython "Objects/bytesobject.c"
4747
#define PyBytesObject_SIZE (offsetof(PyBytesObject, ob_sval) + 1)
4848

49-
PyTypeObject PyBytes_Type = PY_TRUFFLE_TYPE("bytes", &PyType_Type, Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_BYTES_SUBCLASS, PyBytesObject_SIZE);
49+
PyTypeObject PyBytes_Type = PY_TRUFFLE_TYPE_WITH_ITEMSIZE("bytes", &PyType_Type, Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_BYTES_SUBCLASS, PyBytesObject_SIZE, sizeof(char));
5050

5151
typedef PyObject* (*fromStringAndSize_fun_t)(int8_t* str, int64_t sz);
5252

graalpython/com.oracle.graal.python.cext/src/capi.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -315,11 +315,11 @@ void initialize_hashes();
315315
JWRAPPER_O : \
316316
JWRAPPER_UNSUPPORTED)))))))
317317

318-
#define PY_TRUFFLE_TYPE_GENERIC(__TYPE_NAME__, __SUPER_TYPE__, __FLAGS__, __SIZE__, __ALLOC__, __DEALLOC__, __FREE__, __VCALL_OFFSET__) {\
318+
#define PY_TRUFFLE_TYPE_GENERIC(__TYPE_NAME__, __SUPER_TYPE__, __FLAGS__, __SIZE__, __ITEMSIZE__, __ALLOC__, __DEALLOC__, __FREE__, __VCALL_OFFSET__) {\
319319
PyVarObject_HEAD_INIT((__SUPER_TYPE__), 0)\
320320
__TYPE_NAME__, /* tp_name */\
321321
(__SIZE__), /* tp_basicsize */\
322-
0, /* tp_itemsize */\
322+
(__ITEMSIZE__), /* tp_itemsize */\
323323
(__DEALLOC__), /* tp_dealloc */\
324324
(__VCALL_OFFSET__), /* tp_vectorcall_offset */\
325325
0, /* tp_getattr */\
@@ -358,9 +358,10 @@ void initialize_hashes();
358358
0, /* tp_is_gc */\
359359
}
360360

361-
#define PY_TRUFFLE_TYPE_WITH_VECTORCALL(__TYPE_NAME__, __SUPER_TYPE__, __FLAGS__, __SIZE__, __VCALL_OFFSET__) PY_TRUFFLE_TYPE_GENERIC(__TYPE_NAME__, __SUPER_TYPE__, __FLAGS__, __SIZE__, 0, 0, 0, __VCALL_OFFSET__)
362-
#define PY_TRUFFLE_TYPE_WITH_ALLOC(__TYPE_NAME__, __SUPER_TYPE__, __FLAGS__, __SIZE__, __ALLOC__, __DEALLOC__, __FREE__) PY_TRUFFLE_TYPE_GENERIC(__TYPE_NAME__, __SUPER_TYPE__, __FLAGS__, __SIZE__, __ALLOC__, __DEALLOC__, __FREE__, 0)
363-
#define PY_TRUFFLE_TYPE(__TYPE_NAME__, __SUPER_TYPE__, __FLAGS__, __SIZE__) PY_TRUFFLE_TYPE_GENERIC(__TYPE_NAME__, __SUPER_TYPE__, __FLAGS__, __SIZE__, 0, 0, 0, 0)
361+
#define PY_TRUFFLE_TYPE_WITH_VECTORCALL(__TYPE_NAME__, __SUPER_TYPE__, __FLAGS__, __SIZE__, __VCALL_OFFSET__) PY_TRUFFLE_TYPE_GENERIC(__TYPE_NAME__, __SUPER_TYPE__, __FLAGS__, __SIZE__, 0, 0, 0, 0, __VCALL_OFFSET__)
362+
#define PY_TRUFFLE_TYPE_WITH_ALLOC(__TYPE_NAME__, __SUPER_TYPE__, __FLAGS__, __SIZE__, __ALLOC__, __DEALLOC__, __FREE__) PY_TRUFFLE_TYPE_GENERIC(__TYPE_NAME__, __SUPER_TYPE__, __FLAGS__, __SIZE__, 0, __ALLOC__, __DEALLOC__, __FREE__, 0)
363+
#define PY_TRUFFLE_TYPE(__TYPE_NAME__, __SUPER_TYPE__, __FLAGS__, __SIZE__) PY_TRUFFLE_TYPE_GENERIC(__TYPE_NAME__, __SUPER_TYPE__, __FLAGS__, __SIZE__, 0, 0, 0, 0, 0)
364+
#define PY_TRUFFLE_TYPE_WITH_ITEMSIZE(__TYPE_NAME__, __SUPER_TYPE__, __FLAGS__, __SIZE__, __ITEMSIZE__) PY_TRUFFLE_TYPE_GENERIC(__TYPE_NAME__, __SUPER_TYPE__, __FLAGS__, __SIZE__, __ITEMSIZE__, 0, 0, 0, 0)
364365

365366
/** to be used from Java code only; returns a type's basic size */
366367
#define BASICSIZE_GETTER(__typename__)extern Py_ssize_t get_ ## __typename__ ## _basicsize() { \

graalpython/com.oracle.graal.python.cext/src/frameobject.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -41,7 +41,7 @@
4141

4242
#include "capi.h"
4343

44-
PyTypeObject PyFrame_Type = PY_TRUFFLE_TYPE("frame", &PyType_Type, Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, sizeof(PyTypeObject));
44+
PyTypeObject PyFrame_Type = PY_TRUFFLE_TYPE_WITH_ITEMSIZE("frame", &PyType_Type, Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, sizeof(PyTypeObject), sizeof(PyObject *));
4545

4646
UPCALL_ID(PyTruffleFrame_New);
4747
PyFrameObject* PyFrame_New(PyThreadState *tstate, PyCodeObject *code, PyObject *globals, PyObject *locals) {

graalpython/com.oracle.graal.python.cext/src/longobject.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
#include <stdbool.h>
4444
#include <stddef.h>
4545

46-
PyTypeObject PyLong_Type = PY_TRUFFLE_TYPE("int", &PyType_Type, Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_LONG_SUBCLASS, offsetof(PyLongObject, ob_digit));
46+
PyTypeObject PyLong_Type = PY_TRUFFLE_TYPE_WITH_ITEMSIZE("int", &PyType_Type, Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_LONG_SUBCLASS, offsetof(PyLongObject, ob_digit), sizeof(PyObject *));
4747

4848
PyObject * _PyLong_Zero;
4949
PyObject * _PyLong_One;

graalpython/com.oracle.graal.python.cext/src/memoryobject.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -40,7 +40,7 @@
4040
*/
4141
#include "capi.h"
4242

43-
PyTypeObject PyMemoryView_Type = PY_TRUFFLE_TYPE("memoryview", &PyType_Type, Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, offsetof(PyMemoryViewObject, ob_array));
43+
PyTypeObject PyMemoryView_Type = PY_TRUFFLE_TYPE_WITH_ITEMSIZE("memoryview", &PyType_Type, Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, offsetof(PyMemoryViewObject, ob_array), sizeof(Py_ssize_t));
4444
PyTypeObject PyBuffer_Type = PY_TRUFFLE_TYPE("buffer", &PyType_Type, Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, sizeof(PyBufferDecorator));
4545

4646
int bufferdecorator_getbuffer(PyBufferDecorator *self, Py_buffer *view, int flags) {

graalpython/com.oracle.graal.python.cext/src/tupleobject.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
PyObject* PyTruffle_Tuple_Alloc(PyTypeObject* cls, Py_ssize_t nitems);
4545

4646
/* tuple type */
47-
PyTypeObject PyTuple_Type = PY_TRUFFLE_TYPE_WITH_ALLOC("tuple", &PyType_Type, Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_TUPLE_SUBCLASS, sizeof(PyTupleObject) - sizeof(PyObject *), PyTruffle_Tuple_Alloc, 0, 0);
47+
PyTypeObject PyTuple_Type = PY_TRUFFLE_TYPE_GENERIC("tuple", &PyType_Type, Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_TUPLE_SUBCLASS, sizeof(PyTupleObject) - sizeof(PyObject *), sizeof(PyObject *), PyTruffle_Tuple_Alloc, 0, 0, 0);
4848

4949
/* Tuples */
5050
UPCALL_ID(PyTuple_New);

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

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,4 +296,37 @@ class SubSlots(BaseSlots, Base):
296296
str(type(SubSlots.__dict__['__dict__'])) == "<class 'get_set_desc'>"
297297
assert SubSlots().__dict__ == {}
298298

299+
def test_itemsize():
300+
assert object.__itemsize__ == 0
301+
assert list.__itemsize__ == 0
302+
assert type.__itemsize__ == 40
303+
assert tuple.__itemsize__ == 8
304+
305+
class C: pass
306+
assert C.__itemsize__ == 0
307+
308+
class C(tuple): pass
309+
assert C.__itemsize__ == 8
310+
311+
312+
raised = False
313+
try:
314+
object.__itemsize__ = 1
315+
except TypeError:
316+
raised = True
317+
assert raised
318+
319+
raised = False
320+
try:
321+
C.__itemsize__ = 1
322+
except AttributeError:
323+
raised = True
324+
assert raised
299325

326+
class C():
327+
__itemsize__ = 'abc'
328+
assert C.__itemsize__ == 0
329+
330+
class C(tuple):
331+
__itemsize__ = 42
332+
assert C.__itemsize__ == 8

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinConstructors.java

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,6 @@
6868
import static com.oracle.graal.python.nodes.SpecialAttributeNames.__CLASSCELL__;
6969
import static com.oracle.graal.python.nodes.SpecialAttributeNames.__DICTOFFSET__;
7070
import static com.oracle.graal.python.nodes.SpecialAttributeNames.__DICT__;
71-
import static com.oracle.graal.python.nodes.SpecialAttributeNames.__ITEMSIZE__;
7271
import static com.oracle.graal.python.nodes.SpecialAttributeNames.__MODULE__;
7372
import static com.oracle.graal.python.nodes.SpecialAttributeNames.__MRO_ENTRIES__;
7473
import static com.oracle.graal.python.nodes.SpecialAttributeNames.__NAME__;
@@ -169,8 +168,10 @@
169168
import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass;
170169
import com.oracle.graal.python.builtins.objects.type.PythonClass;
171170
import com.oracle.graal.python.builtins.objects.type.PythonManagedClass;
171+
import static com.oracle.graal.python.builtins.objects.type.TypeBuiltins.TYPE_ITEMSIZE;
172172
import com.oracle.graal.python.builtins.objects.type.TypeNodes;
173173
import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetBestBaseClassNode;
174+
import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetItemsizeNode;
174175
import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetMroNode;
175176
import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetNameNode;
176177
import com.oracle.graal.python.builtins.objects.type.TypeNodes.IsAcceptableBaseNode;
@@ -187,6 +188,7 @@
187188
import com.oracle.graal.python.nodes.attributes.LookupInheritedAttributeNode;
188189
import com.oracle.graal.python.nodes.attributes.ReadAttributeFromObjectNode;
189190
import com.oracle.graal.python.nodes.attributes.SetAttributeNode;
191+
import com.oracle.graal.python.nodes.attributes.WriteAttributeToObjectNode;
190192
import com.oracle.graal.python.nodes.builtins.TupleNodes;
191193
import com.oracle.graal.python.nodes.call.CallNode;
192194
import com.oracle.graal.python.nodes.call.special.CallUnaryMethodNode;
@@ -2090,6 +2092,8 @@ Object typeNew(VirtualFrame frame, Object cls, Object wName, PTuple bases, PDict
20902092
@Cached CallNode callNewFuncNode,
20912093
@Cached("create(__DICT__)") LookupAttributeInMRONode getDictAttrNode,
20922094
@Cached("create(__WEAKREF__)") LookupAttributeInMRONode getWeakRefAttrNode,
2095+
@Cached GetItemsizeNode getItemSize,
2096+
@Cached WriteAttributeToObjectNode writeItemSize,
20932097
@Cached GetBestBaseClassNode getBestBaseNode,
20942098
@Cached DictBuiltins.CopyNode copyDict) {
20952099
// Determine the proper metatype to deal with this
@@ -2107,7 +2111,7 @@ Object typeNew(VirtualFrame frame, Object cls, Object wName, PTuple bases, PDict
21072111

21082112
try {
21092113
PDict namespace = (PDict) copyDict.call(frame, namespaceOrig);
2110-
PythonClass newType = typeMetaclass(frame, name, bases, namespace, metaclass, nslib, getDictAttrNode, getWeakRefAttrNode, getBestBaseNode);
2114+
PythonClass newType = typeMetaclass(frame, name, bases, namespace, metaclass, nslib, getDictAttrNode, getWeakRefAttrNode, getBestBaseNode, getItemSize, writeItemSize);
21112115

21122116
for (DictEntry entry : nslib.entries(namespace.getDictStorage())) {
21132117
Object setName = getSetNameNode.execute(entry.value);
@@ -2202,7 +2206,8 @@ private String getModuleNameFromGlobals(PythonObject globals, HashingStorageLibr
22022206
}
22032207

22042208
private PythonClass typeMetaclass(VirtualFrame frame, String name, PTuple bases, PDict namespace, Object metaclass,
2205-
HashingStorageLibrary nslib, LookupAttributeInMRONode getDictAttrNode, LookupAttributeInMRONode getWeakRefAttrNode, GetBestBaseClassNode getBestBaseNode) {
2209+
HashingStorageLibrary nslib, LookupAttributeInMRONode getDictAttrNode, LookupAttributeInMRONode getWeakRefAttrNode, GetBestBaseClassNode getBestBaseNode,
2210+
GetItemsizeNode getItemSize, WriteAttributeToObjectNode writeItemSize) {
22062211
Object[] array = ensureGetObjectArrayNode().execute(bases);
22072212

22082213
PythonAbstractClass[] basesArray;
@@ -2259,12 +2264,12 @@ private PythonClass typeMetaclass(VirtualFrame frame, String name, PTuple bases,
22592264
// may_add_dict = base->tp_dictoffset == 0
22602265
boolean mayAddDict = getDictAttrNode.execute(base) == PNone.NO_VALUE;
22612266
// may_add_weak = base->tp_weaklistoffset == 0 && base->tp_itemsize == 0
2262-
// TODO: maybe also slots size as equivalent of tp_itemsize?
2263-
boolean mayAddWeakRef = getWeakRefAttrNode.execute(base) == PNone.NO_VALUE;
2267+
boolean hasItemSize = getItemSize.execute(base) != 0;
2268+
boolean mayAddWeakRef = getWeakRefAttrNode.execute(base) == PNone.NO_VALUE && !hasItemSize;
22642269

22652270
if (slots[0] == null) {
22662271
// takes care of checking if we may_add_dict and adds it if needed
2267-
addDictIfNative(frame, pythonClass);
2272+
addDictIfNative(frame, pythonClass, getItemSize, writeItemSize);
22682273
addDictDescrAttribute(basesArray, getDictAttrNode, pythonClass);
22692274
addWeakrefDescrAttribute(pythonClass);
22702275
} else {
@@ -2287,8 +2292,6 @@ private PythonClass typeMetaclass(VirtualFrame frame, String name, PTuple bases,
22872292
slotsStorage = ((PList) slotsObject).getSequenceStorage();
22882293
}
22892294
int slotlen = getListLenNode().execute(slotsStorage);
2290-
// TODO: tfel - check if slots are allowed. They are not if the base class is var
2291-
// sized
22922295

22932296
for (int i = 0; i < slotlen; i++) {
22942297
String slotName;
@@ -2300,7 +2303,7 @@ private PythonClass typeMetaclass(VirtualFrame frame, String name, PTuple bases,
23002303
throw raise(TypeError, ErrorMessages.MUST_BE_STRINGS_NOT_P, "__slots__ items", element);
23012304
}
23022305
if (__DICT__.equals(slotName)) {
2303-
if (!mayAddDict || addDict || addDictIfNative(frame, pythonClass)) {
2306+
if (!mayAddDict || addDict || addDictIfNative(frame, pythonClass, getItemSize, writeItemSize)) {
23042307
throw raise(TypeError, ErrorMessages.DICT_SLOT_DISALLOWED_WE_GOT_ONE);
23052308
}
23062309
addDict = true;
@@ -2574,15 +2577,15 @@ private CastToListNode getCastToListNode() {
25742577
/**
25752578
* check that the native base does not already have tp_dictoffset
25762579
*/
2577-
private boolean addDictIfNative(VirtualFrame frame, PythonManagedClass pythonClass) {
2580+
private boolean addDictIfNative(VirtualFrame frame, PythonManagedClass pythonClass, GetItemsizeNode getItemSize, WriteAttributeToObjectNode writeItemSize) {
25782581
boolean addedNewDict = false;
25792582
if (pythonClass.needsNativeAllocation()) {
25802583
for (Object cls : getMro(pythonClass)) {
25812584
if (PGuards.isNativeClass(cls)) {
25822585
// Use GetAnyAttributeNode since these are get-set-descriptors
25832586
long dictoffset = ensureCastToIntNode().execute(ensureGetAttributeNode().executeObject(frame, cls, __DICTOFFSET__));
25842587
long basicsize = ensureCastToIntNode().execute(ensureGetAttributeNode().executeObject(frame, cls, __BASICSIZE__));
2585-
long itemsize = ensureCastToIntNode().execute(ensureGetAttributeNode().executeObject(frame, cls, __ITEMSIZE__));
2588+
long itemsize = ensureCastToIntNode().execute(getItemSize.execute(cls));
25862589
if (dictoffset == 0) {
25872590
addedNewDict = true;
25882591
// add_dict
@@ -2595,7 +2598,7 @@ private boolean addDictIfNative(VirtualFrame frame, PythonManagedClass pythonCla
25952598
}
25962599
ensureWriteAttrNode().execute(frame, pythonClass, __DICTOFFSET__, dictoffset);
25972600
ensureWriteAttrNode().execute(frame, pythonClass, __BASICSIZE__, basicsize);
2598-
ensureWriteAttrNode().execute(frame, pythonClass, __ITEMSIZE__, itemsize);
2601+
writeItemSize.execute(pythonClass, TYPE_ITEMSIZE, itemsize);
25992602
break;
26002603
}
26012604
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/DynamicObjectNativeWrapper.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1054,10 +1054,9 @@ static long doTpBasicsize(Object object, @SuppressWarnings("unused") PythonNativ
10541054
@Specialization(guards = {"isPythonClass(object)", "eq(TP_ITEMSIZE, key)"})
10551055
static long doTpItemsize(Object object, @SuppressWarnings("unused") PythonNativeWrapper nativeWrapper, @SuppressWarnings("unused") String key, long itemsize,
10561056
@Cached WriteAttributeToObjectNode writeAttrNode,
1057-
@Cached IsBuiltinClassProfile profile) {
1058-
if (profile.profileClass(object, PythonBuiltinClassType.PythonClass)) {
1059-
writeAttrNode.execute(object, TypeBuiltins.TYPE_ITEMSIZE, itemsize);
1060-
} else {
1057+
@Cached ConditionProfile profile) {
1058+
if (!profile.profile(object instanceof PythonBuiltinClass)) {
1059+
// not expected to happen ...
10611060
writeAttrNode.execute(object, __ITEMSIZE__, itemsize);
10621061
}
10631062
return itemsize;

0 commit comments

Comments
 (0)