# HG changeset patch # User Martin von Zweigbergk # Date 1431122968 25200 # Node ID b3a68fb8b859c5907f3d457e9ac444a260ac6134 # Parent 7e5d5160073b1d5e48f30722d389b55d781e674a dirs: back out forward-searching in finddirs() This backs out the changes below. The next patch will implement a faster algorithm based on backward-walking in finddirs(). 67241ee427cf (dirs._addpath: reinstate use of Py_CLEAR, 2015-04-07) 6f0e6fa9fdd7 (dirs._addpath: don't mutate Python strings after exposing them (issue4589), 2015-04-06) 1a9efc312700 (dirs.addpath: rework algorithm to search forward, 2015-03-27) diff -r 7e5d5160073b -r b3a68fb8b859 mercurial/dirs.c --- a/mercurial/dirs.c Wed Apr 15 08:19:36 2015 -0700 +++ b/mercurial/dirs.c Fri May 08 15:09:28 2015 -0700 @@ -9,7 +9,6 @@ #define PY_SSIZE_T_CLEAN #include -#include #include "util.h" /* @@ -33,19 +32,23 @@ { const char *s = PyString_AS_STRING(path); - const char *ret = strchr(s + pos, '/'); - return (ret != NULL) ? (ret - s) : -1; + while (pos != -1) { + if (s[pos] == '/') + break; + pos -= 1; + } + + return pos; } static int _addpath(PyObject *dirs, PyObject *path) { - char *cpath = PyString_AS_STRING(path); - Py_ssize_t len = PyString_GET_SIZE(path); - Py_ssize_t pos = -1; + const char *cpath = PyString_AS_STRING(path); + Py_ssize_t pos = PyString_GET_SIZE(path); PyObject *key = NULL; int ret = -1; - while ((pos = _finddir(path, pos + 1)) != -1) { + while ((pos = _finddir(path, pos - 1)) != -1) { PyObject *val; /* It's likely that every prefix already has an entry @@ -53,18 +56,10 @@ deallocating a string for each prefix we check. */ if (key != NULL) ((PyStringObject *)key)->ob_shash = -1; - else if (pos != 0) { - /* pos >= 1, which means that len >= 2. This is - guaranteed to produce a non-interned string. */ - key = PyString_FromStringAndSize(cpath, len); - if (key == NULL) - goto bail; - } else { - /* pos == 0, which means we need to increment the dir - count for the empty string. We need to make sure we - don't muck around with interned strings, so throw it - away later. */ - key = PyString_FromString(""); + else { + /* Force Python to not reuse a small shared string. */ + key = PyString_FromStringAndSize(cpath, + pos < 2 ? 2 : pos); if (key == NULL) goto bail; } @@ -74,10 +69,6 @@ val = PyDict_GetItem(dirs, key); if (val != NULL) { PyInt_AS_LONG(val) += 1; - if (pos != 0) - PyString_AS_STRING(key)[pos] = '/'; - else - key = NULL; continue; } @@ -92,9 +83,6 @@ Py_DECREF(val); if (ret == -1) goto bail; - - /* Clear the key out since we've already exposed it to Python - and can't mutate it further. */ Py_CLEAR(key); } ret = 0; @@ -107,11 +95,11 @@ static int _delpath(PyObject *dirs, PyObject *path) { - Py_ssize_t pos = -1; + Py_ssize_t pos = PyString_GET_SIZE(path); PyObject *key = NULL; int ret = -1; - while ((pos = _finddir(path, pos + 1)) != -1) { + while ((pos = _finddir(path, pos - 1)) != -1) { PyObject *val; key = PyString_FromStringAndSize(PyString_AS_STRING(path), pos);