Updated some terminology and added comments.

pull/13171/head
Joshua Haberman 3 years ago
parent bf74b3e7fd
commit faac2d8b78
  1. 47
      python/map.c
  2. 21
      python/map.h
  3. 23
      python/message.c
  4. 6
      python/repeated.c
  5. 12
      python/repeated.h

@ -38,11 +38,15 @@
typedef struct { typedef struct {
PyObject_HEAD PyObject_HEAD
PyObject* arena; PyObject* arena;
uintptr_t field; // upb_fielddef*, low bit 1 == unset // The field descriptor (upb_fielddef*).
// The low bit indicates whether the container is reified (see ptr below).
// - low bit set: repeated field is a stub (no underlying data).
// - low bit clear: repeated field is reified (points to upb_array).
uintptr_t field;
union { union {
upb_map* map; // when set, the data for this array. PyObject* parent; // stub: owning pointer to parent message.
PyObject* parent; // when unset owning pointer to parent message. upb_map* map; // reified: the data for this array.
}; } ptr;
int version; int version;
} PyUpb_MapContainer; } PyUpb_MapContainer;
@ -53,7 +57,7 @@ static bool PyUpb_MapContainer_IsUnset(PyUpb_MapContainer* self) {
} }
static upb_map* PyUpb_MapContainer_GetIfWritable(PyUpb_MapContainer* self) { static upb_map* PyUpb_MapContainer_GetIfWritable(PyUpb_MapContainer* self) {
return PyUpb_MapContainer_IsUnset(self) ? NULL : self->map; return PyUpb_MapContainer_IsUnset(self) ? NULL : self->ptr.map;
} }
static const upb_fielddef* PyUpb_MapContainer_GetField( static const upb_fielddef* PyUpb_MapContainer_GetField(
@ -65,10 +69,11 @@ static void PyUpb_MapContainer_Dealloc(void* _self) {
PyUpb_MapContainer* self = _self; PyUpb_MapContainer* self = _self;
Py_DECREF(self->arena); Py_DECREF(self->arena);
if (PyUpb_MapContainer_IsUnset(self)) { if (PyUpb_MapContainer_IsUnset(self)) {
PyUpb_CMessage_CacheDelete(self->parent, PyUpb_MapContainer_GetField(self)); PyUpb_CMessage_CacheDelete(self->ptr.parent,
Py_DECREF(self->parent); PyUpb_MapContainer_GetField(self));
Py_DECREF(self->ptr.parent);
} else { } else {
PyUpb_ObjCache_Delete(self->map); PyUpb_ObjCache_Delete(self->ptr.map);
} }
PyUpb_Dealloc(_self); PyUpb_Dealloc(_self);
} }
@ -80,26 +85,24 @@ PyTypeObject* PyUpb_MapContainer_GetClass(const upb_fielddef* f) {
: state->scalar_map_container_type; : state->scalar_map_container_type;
} }
PyObject* PyUpb_MapContainer_NewUnset(PyObject* parent, const upb_fielddef* f, PyObject* PyUpb_MapContainer_NewStub(PyObject* parent, const upb_fielddef* f,
PyObject* arena) { PyObject* arena) {
PyTypeObject* cls = PyUpb_MapContainer_GetClass(f); PyTypeObject* cls = PyUpb_MapContainer_GetClass(f);
// We are GC because of the MutableMapping base class. Ideally we could
// implement them ourselves so we don't need a base so we don't need to be GC.
PyUpb_MapContainer* map = (void*)PyType_GenericAlloc(cls, 0); PyUpb_MapContainer* map = (void*)PyType_GenericAlloc(cls, 0);
map->arena = arena; map->arena = arena;
map->field = (uintptr_t)f | 1; map->field = (uintptr_t)f | 1;
map->parent = parent; map->ptr.parent = parent;
map->version = 0; map->version = 0;
Py_INCREF(arena); Py_INCREF(arena);
Py_INCREF(parent); Py_INCREF(parent);
return &map->ob_base; return &map->ob_base;
} }
void PyUpb_MapContainer_SwitchToSet(PyObject* _self, upb_map* map) { void PyUpb_MapContainer_Reify(PyObject* _self, upb_map* map) {
PyUpb_MapContainer* self = (PyUpb_MapContainer*)_self; PyUpb_MapContainer* self = (PyUpb_MapContainer*)_self;
PyUpb_ObjCache_Add(map, &self->ob_base); PyUpb_ObjCache_Add(map, &self->ob_base);
Py_DECREF(self->parent); Py_DECREF(self->ptr.parent);
self->map = map; // Overwrites self->parent. self->ptr.map = map; // Overwrites self->ptr.parent.
self->field = self->field & ~(uintptr_t)1; self->field = self->field & ~(uintptr_t)1;
assert(!PyUpb_MapContainer_IsUnset(self)); assert(!PyUpb_MapContainer_IsUnset(self));
} }
@ -121,8 +124,8 @@ static upb_map* PyUpb_MapContainer_AssureWritable(PyUpb_MapContainer* self) {
const upb_fielddef* val_f = upb_msgdef_field(entry_m, 1); const upb_fielddef* val_f = upb_msgdef_field(entry_m, 1);
map = upb_map_new(arena, upb_fielddef_type(key_f), upb_fielddef_type(val_f)); map = upb_map_new(arena, upb_fielddef_type(key_f), upb_fielddef_type(val_f));
upb_msgval msgval = {.map_val = map}; upb_msgval msgval = {.map_val = map};
PyUpb_CMessage_SetConcreteSubobj(self->parent, f, msgval); PyUpb_CMessage_SetConcreteSubobj(self->ptr.parent, f, msgval);
PyUpb_MapContainer_SwitchToSet((PyObject*)self, map); PyUpb_MapContainer_Reify((PyObject*)self, map);
return map; return map;
} }
@ -294,21 +297,21 @@ PyObject* PyUpb_MapContainer_Subscript(PyObject* _self, PyObject* key) {
return PyUpb_UpbToPy(u_val, val_f, self->arena); return PyUpb_UpbToPy(u_val, val_f, self->arena);
} }
PyObject* PyUpb_MapContainer_GetOrCreateWrapper(upb_map* u_map, PyObject* PyUpb_MapContainer_GetOrCreateWrapper(upb_map* map,
const upb_fielddef* f, const upb_fielddef* f,
PyObject* arena) { PyObject* arena) {
PyObject* ret = PyUpb_ObjCache_Get(u_map); PyObject* ret = PyUpb_ObjCache_Get(map);
if (!ret) { if (!ret) {
PyTypeObject* cls = PyUpb_MapContainer_GetClass(f); PyTypeObject* cls = PyUpb_MapContainer_GetClass(f);
PyUpb_MapContainer* map = (void*)PyType_GenericAlloc(cls, 0); PyUpb_MapContainer* map = (void*)PyType_GenericAlloc(cls, 0);
map->arena = arena; map->arena = arena;
map->field = (uintptr_t)f; map->field = (uintptr_t)f;
map->map = u_map; map->ptr.map = map;
map->version = 0; map->version = 0;
ret = &map->ob_base; ret = &map->ob_base;
Py_INCREF(arena); Py_INCREF(arena);
PyUpb_ObjCache_Add(u_map, ret); PyUpb_ObjCache_Add(map, ret);
} }
return ret; return ret;

@ -33,16 +33,29 @@
#include "python/python.h" #include "python/python.h"
#include "upb/def.h" #include "upb/def.h"
PyObject* PyUpb_MapContainer_NewUnset(PyObject* parent, const upb_fielddef* f, // Creates a new repeated field stub for field `f` of message object `parent`.
PyObject* arena); PyObject* PyUpb_MapContainer_NewStub(PyObject* parent, const upb_fielddef* f,
PyObject* PyUpb_MapContainer_GetOrCreateWrapper(upb_map* u_map, PyObject* arena);
// Returns a map object wrapping `map`, of field type `f`, which must be on
// `arena`. If an existing wrapper object exists, it will be returned,
// otherwise a new object will be created. The caller always owns a ref on the
// returned value.
PyObject* PyUpb_MapContainer_GetOrCreateWrapper(upb_map* map,
const upb_fielddef* f, const upb_fielddef* f,
PyObject* arena); PyObject* arena);
void PyUpb_MapContainer_SwitchToSet(PyObject* self, upb_map* map);
// Reifies a map stub to point to the concrete data in `map`.
void PyUpb_MapContainer_Reify(PyObject* self, upb_map* map);
// Assigns `self[key] = val` for the map `self`.
int PyUpb_MapContainer_AssignSubscript(PyObject* self, PyObject* key, int PyUpb_MapContainer_AssignSubscript(PyObject* self, PyObject* key,
PyObject* val); PyObject* val);
// Invalidates any existing iterators for the map `obj`.
void PyUpb_MapContainer_Invalidate(PyObject* obj); void PyUpb_MapContainer_Invalidate(PyObject* obj);
// Module-level init.
bool PyUpb_Map_Init(PyObject* m); bool PyUpb_Map_Init(PyObject* m);
#endif // PYUPB_MAP_H__ #endif // PYUPB_MAP_H__

@ -435,9 +435,8 @@ static int PyUpb_CMessage_Init(PyObject* _self, PyObject* args,
return PyUpb_CMessage_InitAttributes(_self, args, kwargs); return PyUpb_CMessage_InitAttributes(_self, args, kwargs);
} }
static PyObject* PyUpb_CMessage_NewUnset(PyObject* parent, static PyObject* PyUpb_CMessage_NewStub(PyObject* parent, const upb_fielddef* f,
const upb_fielddef* f, PyObject* arena) {
PyObject* arena) {
const upb_msgdef* sub_m = upb_fielddef_msgsubdef(f); const upb_msgdef* sub_m = upb_fielddef_msgsubdef(f);
PyObject* cls = PyUpb_Descriptor_GetClass(sub_m); PyObject* cls = PyUpb_Descriptor_GetClass(sub_m);
@ -539,14 +538,14 @@ void PyUpb_CMessage_AssureWritable(PyUpb_CMessage* self) {
static void PyUpb_CMessage_SyncSubobjs(PyUpb_CMessage* self); static void PyUpb_CMessage_SyncSubobjs(PyUpb_CMessage* self);
/* /*
* PyUpb_CMessage_SwitchToSet() * PyUpb_CMessage_Reify()
* *
* The message equivalent of PyUpb_*Container_SwitchToSet(), this transitions * The message equivalent of PyUpb_*Container_Reify(), this transitions
* the wrapper from the unset state (owning a reference on self->ptr.parent) to the * the wrapper from the unset state (owning a reference on self->ptr.parent) to the
* set state (having a non-owning pointer to self->ptr.msg). * set state (having a non-owning pointer to self->ptr.msg).
*/ */
static void PyUpb_CMessage_SwitchToSet(PyUpb_CMessage* self, static void PyUpb_CMessage_Reify(PyUpb_CMessage* self, const upb_fielddef* f,
const upb_fielddef* f, upb_msg* msg) { upb_msg* msg) {
assert(f == PyUpb_CMessage_GetFieldDef(self)); assert(f == PyUpb_CMessage_GetFieldDef(self));
PyUpb_ObjCache_Add(msg, &self->ob_base); PyUpb_ObjCache_Add(msg, &self->ob_base);
Py_DECREF(&self->ptr.parent->ob_base); Py_DECREF(&self->ptr.parent->ob_base);
@ -596,14 +595,14 @@ static void PyUpb_CMessage_SyncSubobjs(PyUpb_CMessage* self) {
PyUpb_WeakMap_DeleteIter(subobj_map, &iter); PyUpb_WeakMap_DeleteIter(subobj_map, &iter);
if (upb_fielddef_ismap(f)) { if (upb_fielddef_ismap(f)) {
if (!msgval.map_val) continue; if (!msgval.map_val) continue;
PyUpb_MapContainer_SwitchToSet(obj, (upb_map*)msgval.map_val); PyUpb_MapContainer_Reify(obj, (upb_map*)msgval.map_val);
} else if (upb_fielddef_isseq(f)) { } else if (upb_fielddef_isseq(f)) {
if (!msgval.array_val) continue; if (!msgval.array_val) continue;
PyUpb_RepeatedContainer_Reify(obj, (upb_array*)msgval.array_val); PyUpb_RepeatedContainer_Reify(obj, (upb_array*)msgval.array_val);
} else { } else {
PyUpb_CMessage* sub = (void*)obj; PyUpb_CMessage* sub = (void*)obj;
assert(self == sub->ptr.parent); assert(self == sub->ptr.parent);
PyUpb_CMessage_SwitchToSet(sub, f, (upb_msg*)msgval.msg_val); PyUpb_CMessage_Reify(sub, f, (upb_msg*)msgval.msg_val);
} }
} }
@ -727,11 +726,11 @@ PyObject* PyUpb_CMessage_GetUnsetWrapper(PyUpb_CMessage* self,
if (subobj) return subobj; if (subobj) return subobj;
if (upb_fielddef_ismap(field)) { if (upb_fielddef_ismap(field)) {
subobj = PyUpb_MapContainer_NewUnset(_self, field, self->arena); subobj = PyUpb_MapContainer_NewStub(_self, field, self->arena);
} else if (upb_fielddef_isseq(field)) { } else if (upb_fielddef_isseq(field)) {
subobj = PyUpb_RepeatedContainer_NewUnset(_self, field, self->arena); subobj = PyUpb_RepeatedContainer_NewStub(_self, field, self->arena);
} else { } else {
subobj = PyUpb_CMessage_NewUnset(&self->ob_base, field, self->arena); subobj = PyUpb_CMessage_NewStub(&self->ob_base, field, self->arena);
} }
PyUpb_WeakMap_Add(self->unset_subobj_map, field, subobj); PyUpb_WeakMap_Add(self->unset_subobj_map, field, subobj);

@ -155,9 +155,9 @@ static Py_ssize_t PyUpb_RepeatedContainer_Length(PyObject* self) {
return arr ? upb_array_size(arr) : 0; return arr ? upb_array_size(arr) : 0;
} }
PyObject* PyUpb_RepeatedContainer_NewUnset(PyObject* parent, PyObject* PyUpb_RepeatedContainer_NewStub(PyObject* parent,
const upb_fielddef* f, const upb_fielddef* f,
PyObject* arena) { PyObject* arena) {
PyTypeObject* cls = PyUpb_RepeatedContainer_GetClass(f); PyTypeObject* cls = PyUpb_RepeatedContainer_GetClass(f);
PyUpb_RepeatedContainer* repeated = (void*)PyType_GenericAlloc(cls, 0); PyUpb_RepeatedContainer* repeated = (void*)PyType_GenericAlloc(cls, 0);
repeated->arena = arena; repeated->arena = arena;

@ -33,11 +33,10 @@
#include "python/python.h" #include "python/python.h"
#include "upb/def.h" #include "upb/def.h"
// Creates a new repeated field in the unset state for field `f` of message // Creates a new repeated field stub for field `f` of message object `parent`.
// object `parent`. PyObject* PyUpb_RepeatedContainer_NewStub(PyObject* parent,
PyObject* PyUpb_RepeatedContainer_NewUnset(PyObject* parent, const upb_fielddef* f,
const upb_fielddef* f, PyObject* arena);
PyObject* arena);
// Returns a repeated field object wrapping `arr`, of field type `f`, which // Returns a repeated field object wrapping `arr`, of field type `f`, which
// must be on `arena`. If an existing wrapper object exists, it will be // must be on `arena`. If an existing wrapper object exists, it will be
@ -47,8 +46,7 @@ PyObject* PyUpb_RepeatedContainer_GetOrCreateWrapper(upb_array* arr,
const upb_fielddef* f, const upb_fielddef* f,
PyObject* arena); PyObject* arena);
// Switches a repeated field in the unset state to be set, with `arr` as the // Reifies a repeated field stub to point to the concrete data in `arr`.
// data being pointed to.
void PyUpb_RepeatedContainer_Reify(PyObject* self, upb_array* arr); void PyUpb_RepeatedContainer_Reify(PyObject* self, upb_array* arr);
// Implements repeated_field.extend(iterable). `_self` must be a repeated // Implements repeated_field.extend(iterable). `_self` must be a repeated

Loading…
Cancel
Save