Skip to content

Commit 09ce92e

Browse files
committed
Compute correct named/unnamed member count
1 parent f800be6 commit 09ce92e

File tree

2 files changed

+48
-25
lines changed

2 files changed

+48
-25
lines changed

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

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@
4343
#define REAL_SIZE_TP(tp) PyLong_AsSsize_t(PyDict_GetItem((tp)->tp_dict, polyglot_from_string("n_fields", SRC_CS)))
4444
#define REAL_SIZE(op) REAL_SIZE_TP(Py_TYPE(op))
4545

46+
char *PyStructSequence_UnnamedField = "unnamed field";
47+
4648
static void
4749
structseq_dealloc(PyStructSequence *obj)
4850
{
@@ -61,10 +63,23 @@ PyObject* PyStructSequence_New(PyTypeObject* o) {
6163
return UPCALL_CEXT_O(_jls_PyStructSequence_New, native_type_to_java(o));
6264
}
6365

64-
typedef int (*structseq_init_fun_t)(void *, void *, void *, void *, void *);
66+
static Py_ssize_t
67+
count_members(PyStructSequence_Desc *desc, Py_ssize_t *n_unnamed_members) {
68+
Py_ssize_t i;
69+
70+
*n_unnamed_members = 0;
71+
for (i = 0; desc->fields[i].name != NULL; ++i) {
72+
if (desc->fields[i].name == PyStructSequence_UnnamedField) {
73+
(*n_unnamed_members)++;
74+
}
75+
}
76+
return i;
77+
}
78+
79+
typedef int (*structseq_init_fun_t)(void *, void *, void *, void *, void *, int);
6580
UPCALL_TYPED_ID(PyStructSequence_InitType2, structseq_init_fun_t);
6681
int PyStructSequence_InitType2(PyTypeObject *type, PyStructSequence_Desc *desc) {
67-
Py_ssize_t n_members = desc->n_in_sequence;
82+
Py_ssize_t n_members, n_unnamed_members, n_named_members;
6883
Py_ssize_t i;
6984

7085
memset(type, 0, sizeof(PyTypeObject));
@@ -74,36 +89,41 @@ int PyStructSequence_InitType2(PyTypeObject *type, PyStructSequence_Desc *desc)
7489
type->tp_name = desc->name;
7590
type->tp_basicsize = sizeof(PyStructSequence) - sizeof(PyObject *);
7691
type->tp_itemsize = sizeof(PyObject *);
77-
//type->tp_repr = newType->tp_repr;
7892
type->tp_flags = Py_TPFLAGS_DEFAULT;
7993
type->tp_members = NULL;
80-
//type->tp_new = newType->tp_new;
8194
type->tp_doc = desc->doc;
8295
type->tp_base = &PyTuple_Type;
83-
//type->tp_alloc = newType->tp_alloc;
8496
type->tp_dealloc = (destructor)structseq_dealloc;
8597

8698
// now initialize the type
8799
if (PyType_Ready(type) < 0)
88100
return -1;
89101
Py_INCREF(type);
90102

103+
n_members = count_members(desc, &n_unnamed_members);
104+
n_named_members = n_members - n_unnamed_members;
91105
// put field names and doc strings into two lists
92-
void** field_names = (void **) truffle_managed_malloc(n_members * sizeof(void *));
93-
void** field_docs = (void **) truffle_managed_malloc(n_members * sizeof(void *));
106+
void** field_names = (void **) truffle_managed_malloc(n_named_members * sizeof(void *));
107+
void** field_docs = (void **) truffle_managed_malloc(n_named_members * sizeof(void *));
94108
PyStructSequence_Field* fields = desc->fields;
109+
int j = 0;
95110
for (i = 0; i < n_members; i++) {
96-
field_names[i] = polyglot_from_string(fields[i].name, SRC_CS);
97-
field_docs[i] = polyglot_from_string(fields[i].doc, SRC_CS);
111+
if (fields[i].name != PyStructSequence_UnnamedField) {
112+
field_names[j] = polyglot_from_string(fields[i].name, SRC_CS);
113+
field_docs[j] = polyglot_from_string(fields[i].doc, SRC_CS);
114+
j++;
115+
}
98116
}
99117

100118
// this initializes the type dict (adds attributes)
101119
return _jls_PyStructSequence_InitType2(
102120
native_type_to_java(type),
103121
polyglot_from_string(desc->name, SRC_CS),
104122
polyglot_from_string(desc->doc, SRC_CS),
105-
polyglot_from_PyObjectPtr_array(field_names, n_members),
106-
polyglot_from_PyObjectPtr_array(field_docs, n_members)
123+
/* TODO(fa): use polyglot_from_VoidPtr_array once this is visible */
124+
polyglot_from_PyObjectPtr_array((PyObjectPtr *) field_names, (uint64_t) n_members),
125+
polyglot_from_PyObjectPtr_array((PyObjectPtr *) field_docs, (uint64_t) n_members),
126+
desc->n_in_sequence
107127
);
108128
}
109129

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

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4014,31 +4014,34 @@ public void call(@SuppressWarnings("unused") PythonContext context) {
40144014
}
40154015

40164016
// directly called without landing function
4017-
@Builtin(name = "PyStructSequence_InitType2", minNumOfPositionalArgs = 5)
4017+
@Builtin(name = "PyStructSequence_InitType2", minNumOfPositionalArgs = 6)
40184018
@GenerateNodeFactory
40194019
abstract static class PyStructSequenceInitType2 extends NativeBuiltin {
40204020

40214021
@Specialization(limit = "1")
4022-
static int doGeneric(Object klass, String typeName, String typeDoc, Object fieldNamesObj, Object fieldDocsObj,
4022+
static int doGeneric(Object klass, String typeName, String typeDoc, Object fieldNamesObj, Object fieldDocsObj, int nInSequence,
40234023
@CachedLanguage PythonLanguage language,
40244024
@CachedLibrary("fieldNamesObj") InteropLibrary lib,
4025-
@Cached(parameters = "true") WriteAttributeToObjectNode clearNewNode) {
4025+
@Cached(parameters = "true") WriteAttributeToObjectNode clearNewNode,
4026+
@Cached PRaiseNativeNode raiseNode) {
40264027
// 'fieldNames' and 'fieldDocs' must be of same type; they share the interop lib
40274028
assert fieldNamesObj.getClass() == fieldDocsObj.getClass();
40284029

40294030
try {
4030-
if (lib.hasArrayElements(fieldNamesObj) && lib.hasArrayElements(fieldDocsObj)) {
4031-
int n = PInt.intValueExact(lib.getArraySize(fieldNamesObj));
4032-
String[] fieldNames = new String[n];
4033-
String[] fieldDocs = new String[n];
4034-
for (int i = 0; i < n; i++) {
4035-
fieldNames[i] = cast(lib.readArrayElement(fieldNamesObj, i));
4036-
fieldDocs[i] = cast(lib.readArrayElement(fieldDocsObj, i));
4037-
}
4038-
clearNewNode.execute(klass, __NEW__, PNone.NO_VALUE);
4039-
StructSequenceDescriptor d = new StructSequenceDescriptor(typeName, typeDoc, 0, fieldNames, fieldDocs);
4040-
StructSequence.initType(language, klass, d);
4031+
int n = PInt.intValueExact(lib.getArraySize(fieldNamesObj));
4032+
if (n != lib.getArraySize(fieldDocsObj)) {
4033+
// internal error: the C function must type the object correctly
4034+
throw CompilerDirectives.shouldNotReachHere("len(fieldNames) != len(fieldDocs)");
4035+
}
4036+
String[] fieldNames = new String[n];
4037+
String[] fieldDocs = new String[n];
4038+
for (int i = 0; i < n; i++) {
4039+
fieldNames[i] = cast(lib.readArrayElement(fieldNamesObj, i));
4040+
fieldDocs[i] = cast(lib.readArrayElement(fieldDocsObj, i));
40414041
}
4042+
clearNewNode.execute(klass, __NEW__, PNone.NO_VALUE);
4043+
StructSequenceDescriptor d = new StructSequenceDescriptor(typeName, typeDoc, nInSequence, fieldNames, fieldDocs);
4044+
StructSequence.initType(language, klass, d);
40424045
return 0;
40434046
} catch (UnsupportedMessageException | InvalidArrayIndexException e) {
40444047
throw CompilerDirectives.shouldNotReachHere();

0 commit comments

Comments
 (0)