index: extract a type for the nodetree
This is a first step towards exposing the nodetree as a Python type.
Differential Revision: https://phab.mercurial-scm.org/D4108
--- a/mercurial/cext/revlog.c Wed Jul 18 17:37:06 2018 -0700
+++ b/mercurial/cext/revlog.c Wed May 16 13:15:36 2018 -0700
@@ -28,6 +28,10 @@
#define PyInt_AsLong PyLong_AsLong
#endif
+typedef struct {
+ int children[16];
+} nodetreenode;
+
/*
* A base-16 trie for fast node->rev mapping.
*
@@ -36,7 +40,7 @@
* Zero is empty
*/
typedef struct {
- int children[16];
+ nodetreenode *nodes;
} nodetree;
/*
@@ -317,7 +321,10 @@
PyMem_Free(self->offsets);
self->offsets = NULL;
}
- free(self->nt);
+ if (self->nt != NULL) {
+ free(self->nt->nodes);
+ free(self->nt);
+ }
self->nt = NULL;
Py_CLEAR(self->headrevs);
}
@@ -984,7 +991,7 @@
for (level = off = 0; level < maxlevel; level++) {
int k = getnybble(node, level);
- nodetree *n = &self->nt[off];
+ nodetreenode *n = &self->nt->nodes[off];
int v = n->children[k];
if (v < 0) {
@@ -1011,20 +1018,20 @@
static int nt_new(indexObject *self)
{
if (self->ntlength == self->ntcapacity) {
- if (self->ntcapacity >= INT_MAX / (sizeof(nodetree) * 2)) {
+ if (self->ntcapacity >= INT_MAX / (sizeof(nodetreenode) * 2)) {
PyErr_SetString(PyExc_MemoryError,
"overflow in nt_new");
return -1;
}
self->ntcapacity *= 2;
- self->nt = realloc(self->nt,
- self->ntcapacity * sizeof(nodetree));
- if (self->nt == NULL) {
+ self->nt->nodes = realloc(self->nt->nodes,
+ self->ntcapacity * sizeof(nodetreenode));
+ if (self->nt->nodes == NULL) {
PyErr_SetString(PyExc_MemoryError, "out of memory");
return -1;
}
- memset(&self->nt[self->ntlength], 0,
- sizeof(nodetree) * (self->ntcapacity - self->ntlength));
+ memset(&self->nt->nodes[self->ntlength], 0,
+ sizeof(nodetreenode) * (self->ntcapacity - self->ntlength));
}
return self->ntlength++;
}
@@ -1036,10 +1043,10 @@
while (level < 40) {
int k = nt_level(node, level);
- nodetree *n;
+ nodetreenode *n;
int v;
- n = &self->nt[off];
+ n = &self->nt->nodes[off];
v = n->children[k];
if (v == 0) {
@@ -1059,10 +1066,10 @@
noff = nt_new(self);
if (noff == -1)
return -1;
- /* self->nt may have been changed by realloc */
- self->nt[off].children[k] = noff;
+ /* self->nt->nodes may have been changed by realloc */
+ self->nt->nodes[off].children[k] = noff;
off = noff;
- n = &self->nt[off];
+ n = &self->nt->nodes[off];
n->children[nt_level(oldnode, ++level)] = v;
if (level > self->ntdepth)
self->ntdepth = level;
@@ -1085,15 +1092,22 @@
static int nt_init(indexObject *self)
{
if (self->nt == NULL) {
- if ((size_t)self->raw_length > INT_MAX / sizeof(nodetree)) {
+ self->nt = PyMem_Malloc(sizeof(nodetree));
+ if (self->nt == NULL) {
+ PyErr_NoMemory();
+ return -1;
+ }
+ if ((size_t)self->raw_length > INT_MAX / sizeof(nodetreenode)) {
PyErr_SetString(PyExc_ValueError, "overflow in nt_init");
return -1;
}
self->ntcapacity = self->raw_length < 4
? 4 : (int)self->raw_length / 2;
- self->nt = calloc(self->ntcapacity, sizeof(nodetree));
- if (self->nt == NULL) {
+ self->nt->nodes = calloc(self->ntcapacity, sizeof(nodetreenode));
+ if (self->nt->nodes == NULL) {
+ free(self->nt);
+ self->nt = NULL;
PyErr_NoMemory();
return -1;
}
@@ -1102,6 +1116,7 @@
self->ntlookups = 1;
self->ntmisses = 0;
if (nt_insert(self, nullid, -1) == -1) {
+ free(self->nt->nodes);
free(self->nt);
self->nt = NULL;
return -1;
@@ -1258,7 +1273,7 @@
for (level = off = 0; level < 40; level++) {
int k, v;
- nodetree *n = &self->nt[off];
+ nodetreenode *n = &self->nt->nodes[off];
k = nt_level(node, level);
v = n->children[k];
if (v < 0) {