hamt.c 77 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894
  1. #include "Python.h"
  2. #include "pycore_bitutils.h" // _Py_popcount32
  3. #include "pycore_hamt.h"
  4. #include "pycore_initconfig.h" // _PyStatus_OK()
  5. #include "pycore_object.h" // _PyObject_GC_TRACK()
  6. #include <stddef.h> // offsetof()
  7. /*
  8. This file provides an implementation of an immutable mapping using the
  9. Hash Array Mapped Trie (or HAMT) datastructure.
  10. This design allows to have:
  11. 1. Efficient copy: immutable mappings can be copied by reference,
  12. making it an O(1) operation.
  13. 2. Efficient mutations: due to structural sharing, only a portion of
  14. the trie needs to be copied when the collection is mutated. The
  15. cost of set/delete operations is O(log N).
  16. 3. Efficient lookups: O(log N).
  17. (where N is number of key/value items in the immutable mapping.)
  18. HAMT
  19. ====
  20. The core idea of HAMT is that the shape of the trie is encoded into the
  21. hashes of keys.
  22. Say we want to store a K/V pair in our mapping. First, we calculate the
  23. hash of K, let's say it's 19830128, or in binary:
  24. 0b1001011101001010101110000 = 19830128
  25. Now let's partition this bit representation of the hash into blocks of
  26. 5 bits each:
  27. 0b00_00000_10010_11101_00101_01011_10000 = 19830128
  28. (6) (5) (4) (3) (2) (1)
  29. Each block of 5 bits represents a number between 0 and 31. So if we have
  30. a tree that consists of nodes, each of which is an array of 32 pointers,
  31. those 5-bit blocks will encode a position on a single tree level.
  32. For example, storing the key K with hash 19830128, results in the following
  33. tree structure:
  34. (array of 32 pointers)
  35. +---+ -- +----+----+----+ -- +----+
  36. root node | 0 | .. | 15 | 16 | 17 | .. | 31 | 0b10000 = 16 (1)
  37. (level 1) +---+ -- +----+----+----+ -- +----+
  38. |
  39. +---+ -- +----+----+----+ -- +----+
  40. a 2nd level node | 0 | .. | 10 | 11 | 12 | .. | 31 | 0b01011 = 11 (2)
  41. +---+ -- +----+----+----+ -- +----+
  42. |
  43. +---+ -- +----+----+----+ -- +----+
  44. a 3rd level node | 0 | .. | 04 | 05 | 06 | .. | 31 | 0b00101 = 5 (3)
  45. +---+ -- +----+----+----+ -- +----+
  46. |
  47. +---+ -- +----+----+----+----+
  48. a 4th level node | 0 | .. | 04 | 29 | 30 | 31 | 0b11101 = 29 (4)
  49. +---+ -- +----+----+----+----+
  50. |
  51. +---+ -- +----+----+----+ -- +----+
  52. a 5th level node | 0 | .. | 17 | 18 | 19 | .. | 31 | 0b10010 = 18 (5)
  53. +---+ -- +----+----+----+ -- +----+
  54. |
  55. +--------------+
  56. |
  57. +---+ -- +----+----+----+ -- +----+
  58. a 6th level node | 0 | .. | 15 | 16 | 17 | .. | 31 | 0b00000 = 0 (6)
  59. +---+ -- +----+----+----+ -- +----+
  60. |
  61. V -- our value (or collision)
  62. To rehash: for a K/V pair, the hash of K encodes where in the tree V will
  63. be stored.
  64. To optimize memory footprint and handle hash collisions, our implementation
  65. uses three different types of nodes:
  66. * A Bitmap node;
  67. * An Array node;
  68. * A Collision node.
  69. Because we implement an immutable dictionary, our nodes are also
  70. immutable. Therefore, when we need to modify a node, we copy it, and
  71. do that modification to the copy.
  72. Array Nodes
  73. -----------
  74. These nodes are very simple. Essentially they are arrays of 32 pointers
  75. we used to illustrate the high-level idea in the previous section.
  76. We use Array nodes only when we need to store more than 16 pointers
  77. in a single node.
  78. Array nodes do not store key objects or value objects. They are used
  79. only as an indirection level - their pointers point to other nodes in
  80. the tree.
  81. Bitmap Node
  82. -----------
  83. Allocating a new 32-pointers array for every node of our tree would be
  84. very expensive. Unless we store millions of keys, most of tree nodes would
  85. be very sparse.
  86. When we have less than 16 elements in a node, we don't want to use the
  87. Array node, that would mean that we waste a lot of memory. Instead,
  88. we can use bitmap compression and can have just as many pointers
  89. as we need!
  90. Bitmap nodes consist of two fields:
  91. 1. An array of pointers. If a Bitmap node holds N elements, the
  92. array will be of N pointers.
  93. 2. A 32bit integer -- a bitmap field. If an N-th bit is set in the
  94. bitmap, it means that the node has an N-th element.
  95. For example, say we need to store a 3 elements sparse array:
  96. +---+ -- +---+ -- +----+ -- +----+
  97. | 0 | .. | 4 | .. | 11 | .. | 17 |
  98. +---+ -- +---+ -- +----+ -- +----+
  99. | | |
  100. o1 o2 o3
  101. We allocate a three-pointer Bitmap node. Its bitmap field will be
  102. then set to:
  103. 0b_00100_00010_00000_10000 == (1 << 17) | (1 << 11) | (1 << 4)
  104. To check if our Bitmap node has an I-th element we can do:
  105. bitmap & (1 << I)
  106. And here's a formula to calculate a position in our pointer array
  107. which would correspond to an I-th element:
  108. popcount(bitmap & ((1 << I) - 1))
  109. Let's break it down:
  110. * `popcount` is a function that returns a number of bits set to 1;
  111. * `((1 << I) - 1)` is a mask to filter the bitmask to contain bits
  112. set to the *right* of our bit.
  113. So for our 17, 11, and 4 indexes:
  114. * bitmap & ((1 << 17) - 1) == 0b100000010000 => 2 bits are set => index is 2.
  115. * bitmap & ((1 << 11) - 1) == 0b10000 => 1 bit is set => index is 1.
  116. * bitmap & ((1 << 4) - 1) == 0b0 => 0 bits are set => index is 0.
  117. To conclude: Bitmap nodes are just like Array nodes -- they can store
  118. a number of pointers, but use bitmap compression to eliminate unused
  119. pointers.
  120. Bitmap nodes have two pointers for each item:
  121. +----+----+----+----+ -- +----+----+
  122. | k1 | v1 | k2 | v2 | .. | kN | vN |
  123. +----+----+----+----+ -- +----+----+
  124. When kI == NULL, vI points to another tree level.
  125. When kI != NULL, the actual key object is stored in kI, and its
  126. value is stored in vI.
  127. Collision Nodes
  128. ---------------
  129. Collision nodes are simple arrays of pointers -- two pointers per
  130. key/value. When there's a hash collision, say for k1/v1 and k2/v2
  131. we have `hash(k1)==hash(k2)`. Then our collision node will be:
  132. +----+----+----+----+
  133. | k1 | v1 | k2 | v2 |
  134. +----+----+----+----+
  135. Tree Structure
  136. --------------
  137. All nodes are PyObjects.
  138. The `PyHamtObject` object has a pointer to the root node (h_root),
  139. and has a length field (h_count).
  140. High-level functions accept a PyHamtObject object and dispatch to
  141. lower-level functions depending on what kind of node h_root points to.
  142. Operations
  143. ==========
  144. There are three fundamental operations on an immutable dictionary:
  145. 1. "o.assoc(k, v)" will return a new immutable dictionary, that will be
  146. a copy of "o", but with the "k/v" item set.
  147. Functions in this file:
  148. hamt_node_assoc, hamt_node_bitmap_assoc,
  149. hamt_node_array_assoc, hamt_node_collision_assoc
  150. `hamt_node_assoc` function accepts a node object, and calls
  151. other functions depending on its actual type.
  152. 2. "o.find(k)" will lookup key "k" in "o".
  153. Functions:
  154. hamt_node_find, hamt_node_bitmap_find,
  155. hamt_node_array_find, hamt_node_collision_find
  156. 3. "o.without(k)" will return a new immutable dictionary, that will be
  157. a copy of "o", buth without the "k" key.
  158. Functions:
  159. hamt_node_without, hamt_node_bitmap_without,
  160. hamt_node_array_without, hamt_node_collision_without
  161. Further Reading
  162. ===============
  163. 1. http://blog.higher-order.net/2009/09/08/understanding-clojures-persistenthashmap-deftwice.html
  164. 2. http://blog.higher-order.net/2010/08/16/assoc-and-clojures-persistenthashmap-part-ii.html
  165. 3. Clojure's PersistentHashMap implementation:
  166. https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/PersistentHashMap.java
  167. Debug
  168. =====
  169. The HAMT datatype is accessible for testing purposes under the
  170. `_testcapi` module:
  171. >>> from _testcapi import hamt
  172. >>> h = hamt()
  173. >>> h2 = h.set('a', 2)
  174. >>> h3 = h2.set('b', 3)
  175. >>> list(h3)
  176. ['a', 'b']
  177. When CPython is built in debug mode, a '__dump__()' method is available
  178. to introspect the tree:
  179. >>> print(h3.__dump__())
  180. HAMT(len=2):
  181. BitmapNode(size=4 count=2 bitmap=0b110 id=0x10eb9d9e8):
  182. 'a': 2
  183. 'b': 3
  184. */
  185. #define IS_ARRAY_NODE(node) Py_IS_TYPE(node, &_PyHamt_ArrayNode_Type)
  186. #define IS_BITMAP_NODE(node) Py_IS_TYPE(node, &_PyHamt_BitmapNode_Type)
  187. #define IS_COLLISION_NODE(node) Py_IS_TYPE(node, &_PyHamt_CollisionNode_Type)
  188. /* Return type for 'find' (lookup a key) functions.
  189. * F_ERROR - an error occurred;
  190. * F_NOT_FOUND - the key was not found;
  191. * F_FOUND - the key was found.
  192. */
  193. typedef enum {F_ERROR, F_NOT_FOUND, F_FOUND} hamt_find_t;
  194. /* Return type for 'without' (delete a key) functions.
  195. * W_ERROR - an error occurred;
  196. * W_NOT_FOUND - the key was not found: there's nothing to delete;
  197. * W_EMPTY - the key was found: the node/tree would be empty
  198. if the key is deleted;
  199. * W_NEWNODE - the key was found: a new node/tree is returned
  200. without that key.
  201. */
  202. typedef enum {W_ERROR, W_NOT_FOUND, W_EMPTY, W_NEWNODE} hamt_without_t;
  203. /* Low-level iterator protocol type.
  204. * I_ITEM - a new item has been yielded;
  205. * I_END - the whole tree was visited (similar to StopIteration).
  206. */
  207. typedef enum {I_ITEM, I_END} hamt_iter_t;
  208. #define HAMT_ARRAY_NODE_SIZE 32
  209. typedef struct {
  210. PyObject_HEAD
  211. PyHamtNode *a_array[HAMT_ARRAY_NODE_SIZE];
  212. Py_ssize_t a_count;
  213. } PyHamtNode_Array;
  214. typedef struct {
  215. PyObject_VAR_HEAD
  216. int32_t c_hash;
  217. PyObject *c_array[1];
  218. } PyHamtNode_Collision;
  219. static PyHamtObject *
  220. hamt_alloc(void);
  221. static PyHamtNode *
  222. hamt_node_assoc(PyHamtNode *node,
  223. uint32_t shift, int32_t hash,
  224. PyObject *key, PyObject *val, int* added_leaf);
  225. static hamt_without_t
  226. hamt_node_without(PyHamtNode *node,
  227. uint32_t shift, int32_t hash,
  228. PyObject *key,
  229. PyHamtNode **new_node);
  230. static hamt_find_t
  231. hamt_node_find(PyHamtNode *node,
  232. uint32_t shift, int32_t hash,
  233. PyObject *key, PyObject **val);
  234. #ifdef Py_DEBUG
  235. static int
  236. hamt_node_dump(PyHamtNode *node,
  237. _PyUnicodeWriter *writer, int level);
  238. #endif
  239. static PyHamtNode *
  240. hamt_node_array_new(Py_ssize_t);
  241. static PyHamtNode *
  242. hamt_node_collision_new(int32_t hash, Py_ssize_t size);
  243. static inline Py_ssize_t
  244. hamt_node_collision_count(PyHamtNode_Collision *node);
  245. #ifdef Py_DEBUG
  246. static void
  247. _hamt_node_array_validate(void *obj_raw)
  248. {
  249. PyObject *obj = _PyObject_CAST(obj_raw);
  250. assert(IS_ARRAY_NODE(obj));
  251. PyHamtNode_Array *node = (PyHamtNode_Array*)obj;
  252. Py_ssize_t i = 0, count = 0;
  253. for (; i < HAMT_ARRAY_NODE_SIZE; i++) {
  254. if (node->a_array[i] != NULL) {
  255. count++;
  256. }
  257. }
  258. assert(count == node->a_count);
  259. }
  260. #define VALIDATE_ARRAY_NODE(NODE) \
  261. do { _hamt_node_array_validate(NODE); } while (0);
  262. #else
  263. #define VALIDATE_ARRAY_NODE(NODE)
  264. #endif
  265. /* Returns -1 on error */
  266. static inline int32_t
  267. hamt_hash(PyObject *o)
  268. {
  269. Py_hash_t hash = PyObject_Hash(o);
  270. #if SIZEOF_PY_HASH_T <= 4
  271. return hash;
  272. #else
  273. if (hash == -1) {
  274. /* exception */
  275. return -1;
  276. }
  277. /* While it's somewhat suboptimal to reduce Python's 64 bit hash to
  278. 32 bits via XOR, it seems that the resulting hash function
  279. is good enough (this is also how Long type is hashed in Java.)
  280. Storing 10, 100, 1000 Python strings results in a relatively
  281. shallow and uniform tree structure.
  282. Also it's worth noting that it would be possible to adapt the tree
  283. structure to 64 bit hashes, but that would increase memory pressure
  284. and provide little to no performance benefits for collections with
  285. fewer than billions of key/value pairs.
  286. Important: do not change this hash reducing function. There are many
  287. tests that need an exact tree shape to cover all code paths and
  288. we do that by specifying concrete values for test data's `__hash__`.
  289. If this function is changed most of the regression tests would
  290. become useless.
  291. */
  292. int32_t xored = (int32_t)(hash & 0xffffffffl) ^ (int32_t)(hash >> 32);
  293. return xored == -1 ? -2 : xored;
  294. #endif
  295. }
  296. static inline uint32_t
  297. hamt_mask(int32_t hash, uint32_t shift)
  298. {
  299. return (((uint32_t)hash >> shift) & 0x01f);
  300. }
  301. static inline uint32_t
  302. hamt_bitpos(int32_t hash, uint32_t shift)
  303. {
  304. return (uint32_t)1 << hamt_mask(hash, shift);
  305. }
  306. static inline uint32_t
  307. hamt_bitindex(uint32_t bitmap, uint32_t bit)
  308. {
  309. return (uint32_t)_Py_popcount32(bitmap & (bit - 1));
  310. }
  311. /////////////////////////////////// Dump Helpers
  312. #ifdef Py_DEBUG
  313. static int
  314. _hamt_dump_ident(_PyUnicodeWriter *writer, int level)
  315. {
  316. /* Write `' ' * level` to the `writer` */
  317. PyObject *str = NULL;
  318. PyObject *num = NULL;
  319. PyObject *res = NULL;
  320. int ret = -1;
  321. str = PyUnicode_FromString(" ");
  322. if (str == NULL) {
  323. goto error;
  324. }
  325. num = PyLong_FromLong((long)level);
  326. if (num == NULL) {
  327. goto error;
  328. }
  329. res = PyNumber_Multiply(str, num);
  330. if (res == NULL) {
  331. goto error;
  332. }
  333. ret = _PyUnicodeWriter_WriteStr(writer, res);
  334. error:
  335. Py_XDECREF(res);
  336. Py_XDECREF(str);
  337. Py_XDECREF(num);
  338. return ret;
  339. }
  340. static int
  341. _hamt_dump_format(_PyUnicodeWriter *writer, const char *format, ...)
  342. {
  343. /* A convenient helper combining _PyUnicodeWriter_WriteStr and
  344. PyUnicode_FromFormatV.
  345. */
  346. PyObject* msg;
  347. int ret;
  348. va_list vargs;
  349. va_start(vargs, format);
  350. msg = PyUnicode_FromFormatV(format, vargs);
  351. va_end(vargs);
  352. if (msg == NULL) {
  353. return -1;
  354. }
  355. ret = _PyUnicodeWriter_WriteStr(writer, msg);
  356. Py_DECREF(msg);
  357. return ret;
  358. }
  359. #endif /* Py_DEBUG */
  360. /////////////////////////////////// Bitmap Node
  361. static PyHamtNode *
  362. hamt_node_bitmap_new(Py_ssize_t size)
  363. {
  364. /* Create a new bitmap node of size 'size' */
  365. PyHamtNode_Bitmap *node;
  366. Py_ssize_t i;
  367. if (size == 0) {
  368. /* Since bitmap nodes are immutable, we can cache the instance
  369. for size=0 and reuse it whenever we need an empty bitmap node.
  370. */
  371. return (PyHamtNode *)Py_NewRef(&_Py_SINGLETON(hamt_bitmap_node_empty));
  372. }
  373. assert(size >= 0);
  374. assert(size % 2 == 0);
  375. /* No freelist; allocate a new bitmap node */
  376. node = PyObject_GC_NewVar(
  377. PyHamtNode_Bitmap, &_PyHamt_BitmapNode_Type, size);
  378. if (node == NULL) {
  379. return NULL;
  380. }
  381. Py_SET_SIZE(node, size);
  382. for (i = 0; i < size; i++) {
  383. node->b_array[i] = NULL;
  384. }
  385. node->b_bitmap = 0;
  386. _PyObject_GC_TRACK(node);
  387. return (PyHamtNode *)node;
  388. }
  389. static inline Py_ssize_t
  390. hamt_node_bitmap_count(PyHamtNode_Bitmap *node)
  391. {
  392. return Py_SIZE(node) / 2;
  393. }
  394. static PyHamtNode_Bitmap *
  395. hamt_node_bitmap_clone(PyHamtNode_Bitmap *node)
  396. {
  397. /* Clone a bitmap node; return a new one with the same child notes. */
  398. PyHamtNode_Bitmap *clone;
  399. Py_ssize_t i;
  400. clone = (PyHamtNode_Bitmap *)hamt_node_bitmap_new(Py_SIZE(node));
  401. if (clone == NULL) {
  402. return NULL;
  403. }
  404. for (i = 0; i < Py_SIZE(node); i++) {
  405. clone->b_array[i] = Py_XNewRef(node->b_array[i]);
  406. }
  407. clone->b_bitmap = node->b_bitmap;
  408. return clone;
  409. }
  410. static PyHamtNode_Bitmap *
  411. hamt_node_bitmap_clone_without(PyHamtNode_Bitmap *o, uint32_t bit)
  412. {
  413. assert(bit & o->b_bitmap);
  414. assert(hamt_node_bitmap_count(o) > 1);
  415. PyHamtNode_Bitmap *new = (PyHamtNode_Bitmap *)hamt_node_bitmap_new(
  416. Py_SIZE(o) - 2);
  417. if (new == NULL) {
  418. return NULL;
  419. }
  420. uint32_t idx = hamt_bitindex(o->b_bitmap, bit);
  421. uint32_t key_idx = 2 * idx;
  422. uint32_t val_idx = key_idx + 1;
  423. uint32_t i;
  424. for (i = 0; i < key_idx; i++) {
  425. new->b_array[i] = Py_XNewRef(o->b_array[i]);
  426. }
  427. assert(Py_SIZE(o) >= 0 && Py_SIZE(o) <= 32);
  428. for (i = val_idx + 1; i < (uint32_t)Py_SIZE(o); i++) {
  429. new->b_array[i - 2] = Py_XNewRef(o->b_array[i]);
  430. }
  431. new->b_bitmap = o->b_bitmap & ~bit;
  432. return new;
  433. }
  434. static PyHamtNode *
  435. hamt_node_new_bitmap_or_collision(uint32_t shift,
  436. PyObject *key1, PyObject *val1,
  437. int32_t key2_hash,
  438. PyObject *key2, PyObject *val2)
  439. {
  440. /* Helper method. Creates a new node for key1/val and key2/val2
  441. pairs.
  442. If key1 hash is equal to the hash of key2, a Collision node
  443. will be created. If they are not equal, a Bitmap node is
  444. created.
  445. */
  446. int32_t key1_hash = hamt_hash(key1);
  447. if (key1_hash == -1) {
  448. return NULL;
  449. }
  450. if (key1_hash == key2_hash) {
  451. PyHamtNode_Collision *n;
  452. n = (PyHamtNode_Collision *)hamt_node_collision_new(key1_hash, 4);
  453. if (n == NULL) {
  454. return NULL;
  455. }
  456. n->c_array[0] = Py_NewRef(key1);
  457. n->c_array[1] = Py_NewRef(val1);
  458. n->c_array[2] = Py_NewRef(key2);
  459. n->c_array[3] = Py_NewRef(val2);
  460. return (PyHamtNode *)n;
  461. }
  462. else {
  463. int added_leaf = 0;
  464. PyHamtNode *n = hamt_node_bitmap_new(0);
  465. if (n == NULL) {
  466. return NULL;
  467. }
  468. PyHamtNode *n2 = hamt_node_assoc(
  469. n, shift, key1_hash, key1, val1, &added_leaf);
  470. Py_DECREF(n);
  471. if (n2 == NULL) {
  472. return NULL;
  473. }
  474. n = hamt_node_assoc(n2, shift, key2_hash, key2, val2, &added_leaf);
  475. Py_DECREF(n2);
  476. if (n == NULL) {
  477. return NULL;
  478. }
  479. return n;
  480. }
  481. }
  482. static PyHamtNode *
  483. hamt_node_bitmap_assoc(PyHamtNode_Bitmap *self,
  484. uint32_t shift, int32_t hash,
  485. PyObject *key, PyObject *val, int* added_leaf)
  486. {
  487. /* assoc operation for bitmap nodes.
  488. Return: a new node, or self if key/val already is in the
  489. collection.
  490. 'added_leaf' is later used in '_PyHamt_Assoc' to determine if
  491. `hamt.set(key, val)` increased the size of the collection.
  492. */
  493. uint32_t bit = hamt_bitpos(hash, shift);
  494. uint32_t idx = hamt_bitindex(self->b_bitmap, bit);
  495. /* Bitmap node layout:
  496. +------+------+------+------+ --- +------+------+
  497. | key1 | val1 | key2 | val2 | ... | keyN | valN |
  498. +------+------+------+------+ --- +------+------+
  499. where `N < Py_SIZE(node)`.
  500. The `node->b_bitmap` field is a bitmap. For a given
  501. `(shift, hash)` pair we can determine:
  502. - If this node has the corresponding key/val slots.
  503. - The index of key/val slots.
  504. */
  505. if (self->b_bitmap & bit) {
  506. /* The key is set in this node */
  507. uint32_t key_idx = 2 * idx;
  508. uint32_t val_idx = key_idx + 1;
  509. assert(val_idx < (size_t)Py_SIZE(self));
  510. PyObject *key_or_null = self->b_array[key_idx];
  511. PyObject *val_or_node = self->b_array[val_idx];
  512. if (key_or_null == NULL) {
  513. /* key is NULL. This means that we have a few keys
  514. that have the same (hash, shift) pair. */
  515. assert(val_or_node != NULL);
  516. PyHamtNode *sub_node = hamt_node_assoc(
  517. (PyHamtNode *)val_or_node,
  518. shift + 5, hash, key, val, added_leaf);
  519. if (sub_node == NULL) {
  520. return NULL;
  521. }
  522. if (val_or_node == (PyObject *)sub_node) {
  523. Py_DECREF(sub_node);
  524. return (PyHamtNode *)Py_NewRef(self);
  525. }
  526. PyHamtNode_Bitmap *ret = hamt_node_bitmap_clone(self);
  527. if (ret == NULL) {
  528. return NULL;
  529. }
  530. Py_SETREF(ret->b_array[val_idx], (PyObject*)sub_node);
  531. return (PyHamtNode *)ret;
  532. }
  533. assert(key != NULL);
  534. /* key is not NULL. This means that we have only one other
  535. key in this collection that matches our hash for this shift. */
  536. int comp_err = PyObject_RichCompareBool(key, key_or_null, Py_EQ);
  537. if (comp_err < 0) { /* exception in __eq__ */
  538. return NULL;
  539. }
  540. if (comp_err == 1) { /* key == key_or_null */
  541. if (val == val_or_node) {
  542. /* we already have the same key/val pair; return self. */
  543. return (PyHamtNode *)Py_NewRef(self);
  544. }
  545. /* We're setting a new value for the key we had before.
  546. Make a new bitmap node with a replaced value, and return it. */
  547. PyHamtNode_Bitmap *ret = hamt_node_bitmap_clone(self);
  548. if (ret == NULL) {
  549. return NULL;
  550. }
  551. Py_SETREF(ret->b_array[val_idx], Py_NewRef(val));
  552. return (PyHamtNode *)ret;
  553. }
  554. /* It's a new key, and it has the same index as *one* another key.
  555. We have a collision. We need to create a new node which will
  556. combine the existing key and the key we're adding.
  557. `hamt_node_new_bitmap_or_collision` will either create a new
  558. Collision node if the keys have identical hashes, or
  559. a new Bitmap node.
  560. */
  561. PyHamtNode *sub_node = hamt_node_new_bitmap_or_collision(
  562. shift + 5,
  563. key_or_null, val_or_node, /* existing key/val */
  564. hash,
  565. key, val /* new key/val */
  566. );
  567. if (sub_node == NULL) {
  568. return NULL;
  569. }
  570. PyHamtNode_Bitmap *ret = hamt_node_bitmap_clone(self);
  571. if (ret == NULL) {
  572. Py_DECREF(sub_node);
  573. return NULL;
  574. }
  575. Py_SETREF(ret->b_array[key_idx], NULL);
  576. Py_SETREF(ret->b_array[val_idx], (PyObject *)sub_node);
  577. *added_leaf = 1;
  578. return (PyHamtNode *)ret;
  579. }
  580. else {
  581. /* There was no key before with the same (shift,hash). */
  582. uint32_t n = (uint32_t)_Py_popcount32(self->b_bitmap);
  583. if (n >= 16) {
  584. /* When we have a situation where we want to store more
  585. than 16 nodes at one level of the tree, we no longer
  586. want to use the Bitmap node with bitmap encoding.
  587. Instead we start using an Array node, which has
  588. simpler (faster) implementation at the expense of
  589. having preallocated 32 pointers for its keys/values
  590. pairs.
  591. Small hamt objects (<30 keys) usually don't have any
  592. Array nodes at all. Between ~30 and ~400 keys hamt
  593. objects usually have one Array node, and usually it's
  594. a root node.
  595. */
  596. uint32_t jdx = hamt_mask(hash, shift);
  597. /* 'jdx' is the index of where the new key should be added
  598. in the new Array node we're about to create. */
  599. PyHamtNode *empty = NULL;
  600. PyHamtNode_Array *new_node = NULL;
  601. PyHamtNode *res = NULL;
  602. /* Create a new Array node. */
  603. new_node = (PyHamtNode_Array *)hamt_node_array_new(n + 1);
  604. if (new_node == NULL) {
  605. goto fin;
  606. }
  607. /* Create an empty bitmap node for the next
  608. hamt_node_assoc call. */
  609. empty = hamt_node_bitmap_new(0);
  610. if (empty == NULL) {
  611. goto fin;
  612. }
  613. /* Make a new bitmap node for the key/val we're adding.
  614. Set that bitmap node to new-array-node[jdx]. */
  615. new_node->a_array[jdx] = hamt_node_assoc(
  616. empty, shift + 5, hash, key, val, added_leaf);
  617. if (new_node->a_array[jdx] == NULL) {
  618. goto fin;
  619. }
  620. /* Copy existing key/value pairs from the current Bitmap
  621. node to the new Array node we've just created. */
  622. Py_ssize_t i, j;
  623. for (i = 0, j = 0; i < HAMT_ARRAY_NODE_SIZE; i++) {
  624. if (((self->b_bitmap >> i) & 1) != 0) {
  625. /* Ensure we don't accidentally override `jdx` element
  626. we set few lines above.
  627. */
  628. assert(new_node->a_array[i] == NULL);
  629. if (self->b_array[j] == NULL) {
  630. new_node->a_array[i] =
  631. (PyHamtNode *)Py_NewRef(self->b_array[j + 1]);
  632. }
  633. else {
  634. int32_t rehash = hamt_hash(self->b_array[j]);
  635. if (rehash == -1) {
  636. goto fin;
  637. }
  638. new_node->a_array[i] = hamt_node_assoc(
  639. empty, shift + 5,
  640. rehash,
  641. self->b_array[j],
  642. self->b_array[j + 1],
  643. added_leaf);
  644. if (new_node->a_array[i] == NULL) {
  645. goto fin;
  646. }
  647. }
  648. j += 2;
  649. }
  650. }
  651. VALIDATE_ARRAY_NODE(new_node)
  652. /* That's it! */
  653. res = (PyHamtNode *)new_node;
  654. fin:
  655. Py_XDECREF(empty);
  656. if (res == NULL) {
  657. Py_XDECREF(new_node);
  658. }
  659. return res;
  660. }
  661. else {
  662. /* We have less than 16 keys at this level; let's just
  663. create a new bitmap node out of this node with the
  664. new key/val pair added. */
  665. uint32_t key_idx = 2 * idx;
  666. uint32_t val_idx = key_idx + 1;
  667. uint32_t i;
  668. *added_leaf = 1;
  669. /* Allocate new Bitmap node which can have one more key/val
  670. pair in addition to what we have already. */
  671. PyHamtNode_Bitmap *new_node =
  672. (PyHamtNode_Bitmap *)hamt_node_bitmap_new(2 * (n + 1));
  673. if (new_node == NULL) {
  674. return NULL;
  675. }
  676. /* Copy all keys/values that will be before the new key/value
  677. we are adding. */
  678. for (i = 0; i < key_idx; i++) {
  679. new_node->b_array[i] = Py_XNewRef(self->b_array[i]);
  680. }
  681. /* Set the new key/value to the new Bitmap node. */
  682. new_node->b_array[key_idx] = Py_NewRef(key);
  683. new_node->b_array[val_idx] = Py_NewRef(val);
  684. /* Copy all keys/values that will be after the new key/value
  685. we are adding. */
  686. assert(Py_SIZE(self) >= 0 && Py_SIZE(self) <= 32);
  687. for (i = key_idx; i < (uint32_t)Py_SIZE(self); i++) {
  688. new_node->b_array[i + 2] = Py_XNewRef(self->b_array[i]);
  689. }
  690. new_node->b_bitmap = self->b_bitmap | bit;
  691. return (PyHamtNode *)new_node;
  692. }
  693. }
  694. }
  695. static hamt_without_t
  696. hamt_node_bitmap_without(PyHamtNode_Bitmap *self,
  697. uint32_t shift, int32_t hash,
  698. PyObject *key,
  699. PyHamtNode **new_node)
  700. {
  701. uint32_t bit = hamt_bitpos(hash, shift);
  702. if ((self->b_bitmap & bit) == 0) {
  703. return W_NOT_FOUND;
  704. }
  705. uint32_t idx = hamt_bitindex(self->b_bitmap, bit);
  706. uint32_t key_idx = 2 * idx;
  707. uint32_t val_idx = key_idx + 1;
  708. PyObject *key_or_null = self->b_array[key_idx];
  709. PyObject *val_or_node = self->b_array[val_idx];
  710. if (key_or_null == NULL) {
  711. /* key == NULL means that 'value' is another tree node. */
  712. PyHamtNode *sub_node = NULL;
  713. hamt_without_t res = hamt_node_without(
  714. (PyHamtNode *)val_or_node,
  715. shift + 5, hash, key, &sub_node);
  716. switch (res) {
  717. case W_EMPTY:
  718. /* It's impossible for us to receive a W_EMPTY here:
  719. - Array nodes are converted to Bitmap nodes when
  720. we delete 16th item from them;
  721. - Collision nodes are converted to Bitmap when
  722. there is one item in them;
  723. - Bitmap node's without() inlines single-item
  724. sub-nodes.
  725. So in no situation we can have a single-item
  726. Bitmap child of another Bitmap node.
  727. */
  728. Py_UNREACHABLE();
  729. case W_NEWNODE: {
  730. assert(sub_node != NULL);
  731. if (IS_BITMAP_NODE(sub_node)) {
  732. PyHamtNode_Bitmap *sub_tree = (PyHamtNode_Bitmap *)sub_node;
  733. if (hamt_node_bitmap_count(sub_tree) == 1 &&
  734. sub_tree->b_array[0] != NULL)
  735. {
  736. /* A bitmap node with one key/value pair. Just
  737. merge it into this node.
  738. Note that we don't inline Bitmap nodes that
  739. have a NULL key -- those nodes point to another
  740. tree level, and we cannot simply move tree levels
  741. up or down.
  742. */
  743. PyHamtNode_Bitmap *clone = hamt_node_bitmap_clone(self);
  744. if (clone == NULL) {
  745. Py_DECREF(sub_node);
  746. return W_ERROR;
  747. }
  748. PyObject *key = sub_tree->b_array[0];
  749. PyObject *val = sub_tree->b_array[1];
  750. Py_XSETREF(clone->b_array[key_idx], Py_NewRef(key));
  751. Py_SETREF(clone->b_array[val_idx], Py_NewRef(val));
  752. Py_DECREF(sub_tree);
  753. *new_node = (PyHamtNode *)clone;
  754. return W_NEWNODE;
  755. }
  756. }
  757. #ifdef Py_DEBUG
  758. /* Ensure that Collision.without implementation
  759. converts to Bitmap nodes itself.
  760. */
  761. if (IS_COLLISION_NODE(sub_node)) {
  762. assert(hamt_node_collision_count(
  763. (PyHamtNode_Collision*)sub_node) > 1);
  764. }
  765. #endif
  766. PyHamtNode_Bitmap *clone = hamt_node_bitmap_clone(self);
  767. if (clone == NULL) {
  768. return W_ERROR;
  769. }
  770. Py_SETREF(clone->b_array[val_idx],
  771. (PyObject *)sub_node); /* borrow */
  772. *new_node = (PyHamtNode *)clone;
  773. return W_NEWNODE;
  774. }
  775. case W_ERROR:
  776. case W_NOT_FOUND:
  777. assert(sub_node == NULL);
  778. return res;
  779. default:
  780. Py_UNREACHABLE();
  781. }
  782. }
  783. else {
  784. /* We have a regular key/value pair */
  785. int cmp = PyObject_RichCompareBool(key_or_null, key, Py_EQ);
  786. if (cmp < 0) {
  787. return W_ERROR;
  788. }
  789. if (cmp == 0) {
  790. return W_NOT_FOUND;
  791. }
  792. if (hamt_node_bitmap_count(self) == 1) {
  793. return W_EMPTY;
  794. }
  795. *new_node = (PyHamtNode *)
  796. hamt_node_bitmap_clone_without(self, bit);
  797. if (*new_node == NULL) {
  798. return W_ERROR;
  799. }
  800. return W_NEWNODE;
  801. }
  802. }
  803. static hamt_find_t
  804. hamt_node_bitmap_find(PyHamtNode_Bitmap *self,
  805. uint32_t shift, int32_t hash,
  806. PyObject *key, PyObject **val)
  807. {
  808. /* Lookup a key in a Bitmap node. */
  809. uint32_t bit = hamt_bitpos(hash, shift);
  810. uint32_t idx;
  811. uint32_t key_idx;
  812. uint32_t val_idx;
  813. PyObject *key_or_null;
  814. PyObject *val_or_node;
  815. int comp_err;
  816. if ((self->b_bitmap & bit) == 0) {
  817. return F_NOT_FOUND;
  818. }
  819. idx = hamt_bitindex(self->b_bitmap, bit);
  820. key_idx = idx * 2;
  821. val_idx = key_idx + 1;
  822. assert(val_idx < (size_t)Py_SIZE(self));
  823. key_or_null = self->b_array[key_idx];
  824. val_or_node = self->b_array[val_idx];
  825. if (key_or_null == NULL) {
  826. /* There are a few keys that have the same hash at the current shift
  827. that match our key. Dispatch the lookup further down the tree. */
  828. assert(val_or_node != NULL);
  829. return hamt_node_find((PyHamtNode *)val_or_node,
  830. shift + 5, hash, key, val);
  831. }
  832. /* We have only one key -- a potential match. Let's compare if the
  833. key we are looking at is equal to the key we are looking for. */
  834. assert(key != NULL);
  835. comp_err = PyObject_RichCompareBool(key, key_or_null, Py_EQ);
  836. if (comp_err < 0) { /* exception in __eq__ */
  837. return F_ERROR;
  838. }
  839. if (comp_err == 1) { /* key == key_or_null */
  840. *val = val_or_node;
  841. return F_FOUND;
  842. }
  843. return F_NOT_FOUND;
  844. }
  845. static int
  846. hamt_node_bitmap_traverse(PyHamtNode_Bitmap *self, visitproc visit, void *arg)
  847. {
  848. /* Bitmap's tp_traverse */
  849. Py_ssize_t i;
  850. for (i = Py_SIZE(self); --i >= 0; ) {
  851. Py_VISIT(self->b_array[i]);
  852. }
  853. return 0;
  854. }
  855. static void
  856. hamt_node_bitmap_dealloc(PyHamtNode_Bitmap *self)
  857. {
  858. /* Bitmap's tp_dealloc */
  859. Py_ssize_t len = Py_SIZE(self);
  860. Py_ssize_t i;
  861. if (Py_SIZE(self) == 0) {
  862. /* The empty node is statically allocated. */
  863. assert(self == &_Py_SINGLETON(hamt_bitmap_node_empty));
  864. #ifdef Py_DEBUG
  865. _Py_FatalRefcountError("deallocating the empty hamt node bitmap singleton");
  866. #else
  867. return;
  868. #endif
  869. }
  870. PyObject_GC_UnTrack(self);
  871. Py_TRASHCAN_BEGIN(self, hamt_node_bitmap_dealloc)
  872. if (len > 0) {
  873. i = len;
  874. while (--i >= 0) {
  875. Py_XDECREF(self->b_array[i]);
  876. }
  877. }
  878. Py_TYPE(self)->tp_free((PyObject *)self);
  879. Py_TRASHCAN_END
  880. }
  881. #ifdef Py_DEBUG
  882. static int
  883. hamt_node_bitmap_dump(PyHamtNode_Bitmap *node,
  884. _PyUnicodeWriter *writer, int level)
  885. {
  886. /* Debug build: __dump__() method implementation for Bitmap nodes. */
  887. Py_ssize_t i;
  888. PyObject *tmp1;
  889. PyObject *tmp2;
  890. if (_hamt_dump_ident(writer, level + 1)) {
  891. goto error;
  892. }
  893. if (_hamt_dump_format(writer, "BitmapNode(size=%zd count=%zd ",
  894. Py_SIZE(node), Py_SIZE(node) / 2))
  895. {
  896. goto error;
  897. }
  898. tmp1 = PyLong_FromUnsignedLong(node->b_bitmap);
  899. if (tmp1 == NULL) {
  900. goto error;
  901. }
  902. tmp2 = _PyLong_Format(tmp1, 2);
  903. Py_DECREF(tmp1);
  904. if (tmp2 == NULL) {
  905. goto error;
  906. }
  907. if (_hamt_dump_format(writer, "bitmap=%S id=%p):\n", tmp2, node)) {
  908. Py_DECREF(tmp2);
  909. goto error;
  910. }
  911. Py_DECREF(tmp2);
  912. for (i = 0; i < Py_SIZE(node); i += 2) {
  913. PyObject *key_or_null = node->b_array[i];
  914. PyObject *val_or_node = node->b_array[i + 1];
  915. if (_hamt_dump_ident(writer, level + 2)) {
  916. goto error;
  917. }
  918. if (key_or_null == NULL) {
  919. if (_hamt_dump_format(writer, "NULL:\n")) {
  920. goto error;
  921. }
  922. if (hamt_node_dump((PyHamtNode *)val_or_node,
  923. writer, level + 2))
  924. {
  925. goto error;
  926. }
  927. }
  928. else {
  929. if (_hamt_dump_format(writer, "%R: %R", key_or_null,
  930. val_or_node))
  931. {
  932. goto error;
  933. }
  934. }
  935. if (_hamt_dump_format(writer, "\n")) {
  936. goto error;
  937. }
  938. }
  939. return 0;
  940. error:
  941. return -1;
  942. }
  943. #endif /* Py_DEBUG */
  944. /////////////////////////////////// Collision Node
  945. static PyHamtNode *
  946. hamt_node_collision_new(int32_t hash, Py_ssize_t size)
  947. {
  948. /* Create a new Collision node. */
  949. PyHamtNode_Collision *node;
  950. Py_ssize_t i;
  951. assert(size >= 4);
  952. assert(size % 2 == 0);
  953. node = PyObject_GC_NewVar(
  954. PyHamtNode_Collision, &_PyHamt_CollisionNode_Type, size);
  955. if (node == NULL) {
  956. return NULL;
  957. }
  958. for (i = 0; i < size; i++) {
  959. node->c_array[i] = NULL;
  960. }
  961. Py_SET_SIZE(node, size);
  962. node->c_hash = hash;
  963. _PyObject_GC_TRACK(node);
  964. return (PyHamtNode *)node;
  965. }
  966. static hamt_find_t
  967. hamt_node_collision_find_index(PyHamtNode_Collision *self, PyObject *key,
  968. Py_ssize_t *idx)
  969. {
  970. /* Lookup `key` in the Collision node `self`. Set the index of the
  971. found key to 'idx'. */
  972. Py_ssize_t i;
  973. PyObject *el;
  974. for (i = 0; i < Py_SIZE(self); i += 2) {
  975. el = self->c_array[i];
  976. assert(el != NULL);
  977. int cmp = PyObject_RichCompareBool(key, el, Py_EQ);
  978. if (cmp < 0) {
  979. return F_ERROR;
  980. }
  981. if (cmp == 1) {
  982. *idx = i;
  983. return F_FOUND;
  984. }
  985. }
  986. return F_NOT_FOUND;
  987. }
  988. static PyHamtNode *
  989. hamt_node_collision_assoc(PyHamtNode_Collision *self,
  990. uint32_t shift, int32_t hash,
  991. PyObject *key, PyObject *val, int* added_leaf)
  992. {
  993. /* Set a new key to this level (currently a Collision node)
  994. of the tree. */
  995. if (hash == self->c_hash) {
  996. /* The hash of the 'key' we are adding matches the hash of
  997. other keys in this Collision node. */
  998. Py_ssize_t key_idx = -1;
  999. hamt_find_t found;
  1000. PyHamtNode_Collision *new_node;
  1001. Py_ssize_t i;
  1002. /* Let's try to lookup the new 'key', maybe we already have it. */
  1003. found = hamt_node_collision_find_index(self, key, &key_idx);
  1004. switch (found) {
  1005. case F_ERROR:
  1006. /* Exception. */
  1007. return NULL;
  1008. case F_NOT_FOUND:
  1009. /* This is a totally new key. Clone the current node,
  1010. add a new key/value to the cloned node. */
  1011. new_node = (PyHamtNode_Collision *)hamt_node_collision_new(
  1012. self->c_hash, Py_SIZE(self) + 2);
  1013. if (new_node == NULL) {
  1014. return NULL;
  1015. }
  1016. for (i = 0; i < Py_SIZE(self); i++) {
  1017. new_node->c_array[i] = Py_NewRef(self->c_array[i]);
  1018. }
  1019. new_node->c_array[i] = Py_NewRef(key);
  1020. new_node->c_array[i + 1] = Py_NewRef(val);
  1021. *added_leaf = 1;
  1022. return (PyHamtNode *)new_node;
  1023. case F_FOUND:
  1024. /* There's a key which is equal to the key we are adding. */
  1025. assert(key_idx >= 0);
  1026. assert(key_idx < Py_SIZE(self));
  1027. Py_ssize_t val_idx = key_idx + 1;
  1028. if (self->c_array[val_idx] == val) {
  1029. /* We're setting a key/value pair that's already set. */
  1030. return (PyHamtNode *)Py_NewRef(self);
  1031. }
  1032. /* We need to replace old value for the key
  1033. with a new value. Create a new Collision node.*/
  1034. new_node = (PyHamtNode_Collision *)hamt_node_collision_new(
  1035. self->c_hash, Py_SIZE(self));
  1036. if (new_node == NULL) {
  1037. return NULL;
  1038. }
  1039. /* Copy all elements of the old node to the new one. */
  1040. for (i = 0; i < Py_SIZE(self); i++) {
  1041. new_node->c_array[i] = Py_NewRef(self->c_array[i]);
  1042. }
  1043. /* Replace the old value with the new value for the our key. */
  1044. Py_SETREF(new_node->c_array[val_idx], Py_NewRef(val));
  1045. return (PyHamtNode *)new_node;
  1046. default:
  1047. Py_UNREACHABLE();
  1048. }
  1049. }
  1050. else {
  1051. /* The hash of the new key is different from the hash that
  1052. all keys of this Collision node have.
  1053. Create a Bitmap node inplace with two children:
  1054. key/value pair that we're adding, and the Collision node
  1055. we're replacing on this tree level.
  1056. */
  1057. PyHamtNode_Bitmap *new_node;
  1058. PyHamtNode *assoc_res;
  1059. new_node = (PyHamtNode_Bitmap *)hamt_node_bitmap_new(2);
  1060. if (new_node == NULL) {
  1061. return NULL;
  1062. }
  1063. new_node->b_bitmap = hamt_bitpos(self->c_hash, shift);
  1064. new_node->b_array[1] = Py_NewRef(self);
  1065. assoc_res = hamt_node_bitmap_assoc(
  1066. new_node, shift, hash, key, val, added_leaf);
  1067. Py_DECREF(new_node);
  1068. return assoc_res;
  1069. }
  1070. }
  1071. static inline Py_ssize_t
  1072. hamt_node_collision_count(PyHamtNode_Collision *node)
  1073. {
  1074. return Py_SIZE(node) / 2;
  1075. }
  1076. static hamt_without_t
  1077. hamt_node_collision_without(PyHamtNode_Collision *self,
  1078. uint32_t shift, int32_t hash,
  1079. PyObject *key,
  1080. PyHamtNode **new_node)
  1081. {
  1082. if (hash != self->c_hash) {
  1083. return W_NOT_FOUND;
  1084. }
  1085. Py_ssize_t key_idx = -1;
  1086. hamt_find_t found = hamt_node_collision_find_index(self, key, &key_idx);
  1087. switch (found) {
  1088. case F_ERROR:
  1089. return W_ERROR;
  1090. case F_NOT_FOUND:
  1091. return W_NOT_FOUND;
  1092. case F_FOUND:
  1093. assert(key_idx >= 0);
  1094. assert(key_idx < Py_SIZE(self));
  1095. Py_ssize_t new_count = hamt_node_collision_count(self) - 1;
  1096. if (new_count == 0) {
  1097. /* The node has only one key/value pair and it's for the
  1098. key we're trying to delete. So a new node will be empty
  1099. after the removal.
  1100. */
  1101. return W_EMPTY;
  1102. }
  1103. if (new_count == 1) {
  1104. /* The node has two keys, and after deletion the
  1105. new Collision node would have one. Collision nodes
  1106. with one key shouldn't exist, so convert it to a
  1107. Bitmap node.
  1108. */
  1109. PyHamtNode_Bitmap *node = (PyHamtNode_Bitmap *)
  1110. hamt_node_bitmap_new(2);
  1111. if (node == NULL) {
  1112. return W_ERROR;
  1113. }
  1114. if (key_idx == 0) {
  1115. node->b_array[0] = Py_NewRef(self->c_array[2]);
  1116. node->b_array[1] = Py_NewRef(self->c_array[3]);
  1117. }
  1118. else {
  1119. assert(key_idx == 2);
  1120. node->b_array[0] = Py_NewRef(self->c_array[0]);
  1121. node->b_array[1] = Py_NewRef(self->c_array[1]);
  1122. }
  1123. node->b_bitmap = hamt_bitpos(hash, shift);
  1124. *new_node = (PyHamtNode *)node;
  1125. return W_NEWNODE;
  1126. }
  1127. /* Allocate a new Collision node with capacity for one
  1128. less key/value pair */
  1129. PyHamtNode_Collision *new = (PyHamtNode_Collision *)
  1130. hamt_node_collision_new(
  1131. self->c_hash, Py_SIZE(self) - 2);
  1132. if (new == NULL) {
  1133. return W_ERROR;
  1134. }
  1135. /* Copy all other keys from `self` to `new` */
  1136. Py_ssize_t i;
  1137. for (i = 0; i < key_idx; i++) {
  1138. new->c_array[i] = Py_NewRef(self->c_array[i]);
  1139. }
  1140. for (i = key_idx + 2; i < Py_SIZE(self); i++) {
  1141. new->c_array[i - 2] = Py_NewRef(self->c_array[i]);
  1142. }
  1143. *new_node = (PyHamtNode*)new;
  1144. return W_NEWNODE;
  1145. default:
  1146. Py_UNREACHABLE();
  1147. }
  1148. }
  1149. static hamt_find_t
  1150. hamt_node_collision_find(PyHamtNode_Collision *self,
  1151. uint32_t shift, int32_t hash,
  1152. PyObject *key, PyObject **val)
  1153. {
  1154. /* Lookup `key` in the Collision node `self`. Set the value
  1155. for the found key to 'val'. */
  1156. Py_ssize_t idx = -1;
  1157. hamt_find_t res;
  1158. res = hamt_node_collision_find_index(self, key, &idx);
  1159. if (res == F_ERROR || res == F_NOT_FOUND) {
  1160. return res;
  1161. }
  1162. assert(idx >= 0);
  1163. assert(idx + 1 < Py_SIZE(self));
  1164. *val = self->c_array[idx + 1];
  1165. assert(*val != NULL);
  1166. return F_FOUND;
  1167. }
  1168. static int
  1169. hamt_node_collision_traverse(PyHamtNode_Collision *self,
  1170. visitproc visit, void *arg)
  1171. {
  1172. /* Collision's tp_traverse */
  1173. Py_ssize_t i;
  1174. for (i = Py_SIZE(self); --i >= 0; ) {
  1175. Py_VISIT(self->c_array[i]);
  1176. }
  1177. return 0;
  1178. }
  1179. static void
  1180. hamt_node_collision_dealloc(PyHamtNode_Collision *self)
  1181. {
  1182. /* Collision's tp_dealloc */
  1183. Py_ssize_t len = Py_SIZE(self);
  1184. PyObject_GC_UnTrack(self);
  1185. Py_TRASHCAN_BEGIN(self, hamt_node_collision_dealloc)
  1186. if (len > 0) {
  1187. while (--len >= 0) {
  1188. Py_XDECREF(self->c_array[len]);
  1189. }
  1190. }
  1191. Py_TYPE(self)->tp_free((PyObject *)self);
  1192. Py_TRASHCAN_END
  1193. }
  1194. #ifdef Py_DEBUG
  1195. static int
  1196. hamt_node_collision_dump(PyHamtNode_Collision *node,
  1197. _PyUnicodeWriter *writer, int level)
  1198. {
  1199. /* Debug build: __dump__() method implementation for Collision nodes. */
  1200. Py_ssize_t i;
  1201. if (_hamt_dump_ident(writer, level + 1)) {
  1202. goto error;
  1203. }
  1204. if (_hamt_dump_format(writer, "CollisionNode(size=%zd id=%p):\n",
  1205. Py_SIZE(node), node))
  1206. {
  1207. goto error;
  1208. }
  1209. for (i = 0; i < Py_SIZE(node); i += 2) {
  1210. PyObject *key = node->c_array[i];
  1211. PyObject *val = node->c_array[i + 1];
  1212. if (_hamt_dump_ident(writer, level + 2)) {
  1213. goto error;
  1214. }
  1215. if (_hamt_dump_format(writer, "%R: %R\n", key, val)) {
  1216. goto error;
  1217. }
  1218. }
  1219. return 0;
  1220. error:
  1221. return -1;
  1222. }
  1223. #endif /* Py_DEBUG */
  1224. /////////////////////////////////// Array Node
  1225. static PyHamtNode *
  1226. hamt_node_array_new(Py_ssize_t count)
  1227. {
  1228. Py_ssize_t i;
  1229. PyHamtNode_Array *node = PyObject_GC_New(
  1230. PyHamtNode_Array, &_PyHamt_ArrayNode_Type);
  1231. if (node == NULL) {
  1232. return NULL;
  1233. }
  1234. for (i = 0; i < HAMT_ARRAY_NODE_SIZE; i++) {
  1235. node->a_array[i] = NULL;
  1236. }
  1237. node->a_count = count;
  1238. _PyObject_GC_TRACK(node);
  1239. return (PyHamtNode *)node;
  1240. }
  1241. static PyHamtNode_Array *
  1242. hamt_node_array_clone(PyHamtNode_Array *node)
  1243. {
  1244. PyHamtNode_Array *clone;
  1245. Py_ssize_t i;
  1246. VALIDATE_ARRAY_NODE(node)
  1247. /* Create a new Array node. */
  1248. clone = (PyHamtNode_Array *)hamt_node_array_new(node->a_count);
  1249. if (clone == NULL) {
  1250. return NULL;
  1251. }
  1252. /* Copy all elements from the current Array node to the new one. */
  1253. for (i = 0; i < HAMT_ARRAY_NODE_SIZE; i++) {
  1254. clone->a_array[i] = (PyHamtNode*)Py_XNewRef(node->a_array[i]);
  1255. }
  1256. VALIDATE_ARRAY_NODE(clone)
  1257. return clone;
  1258. }
  1259. static PyHamtNode *
  1260. hamt_node_array_assoc(PyHamtNode_Array *self,
  1261. uint32_t shift, int32_t hash,
  1262. PyObject *key, PyObject *val, int* added_leaf)
  1263. {
  1264. /* Set a new key to this level (currently a Collision node)
  1265. of the tree.
  1266. Array nodes don't store values, they can only point to
  1267. other nodes. They are simple arrays of 32 BaseNode pointers/
  1268. */
  1269. uint32_t idx = hamt_mask(hash, shift);
  1270. PyHamtNode *node = self->a_array[idx];
  1271. PyHamtNode *child_node;
  1272. PyHamtNode_Array *new_node;
  1273. Py_ssize_t i;
  1274. if (node == NULL) {
  1275. /* There's no child node for the given hash. Create a new
  1276. Bitmap node for this key. */
  1277. PyHamtNode_Bitmap *empty = NULL;
  1278. /* Get an empty Bitmap node to work with. */
  1279. empty = (PyHamtNode_Bitmap *)hamt_node_bitmap_new(0);
  1280. if (empty == NULL) {
  1281. return NULL;
  1282. }
  1283. /* Set key/val to the newly created empty Bitmap, thus
  1284. creating a new Bitmap node with our key/value pair. */
  1285. child_node = hamt_node_bitmap_assoc(
  1286. empty,
  1287. shift + 5, hash, key, val, added_leaf);
  1288. Py_DECREF(empty);
  1289. if (child_node == NULL) {
  1290. return NULL;
  1291. }
  1292. /* Create a new Array node. */
  1293. new_node = (PyHamtNode_Array *)hamt_node_array_new(self->a_count + 1);
  1294. if (new_node == NULL) {
  1295. Py_DECREF(child_node);
  1296. return NULL;
  1297. }
  1298. /* Copy all elements from the current Array node to the
  1299. new one. */
  1300. for (i = 0; i < HAMT_ARRAY_NODE_SIZE; i++) {
  1301. new_node->a_array[i] = (PyHamtNode*)Py_XNewRef(self->a_array[i]);
  1302. }
  1303. assert(new_node->a_array[idx] == NULL);
  1304. new_node->a_array[idx] = child_node; /* borrow */
  1305. VALIDATE_ARRAY_NODE(new_node)
  1306. }
  1307. else {
  1308. /* There's a child node for the given hash.
  1309. Set the key to it./ */
  1310. child_node = hamt_node_assoc(
  1311. node, shift + 5, hash, key, val, added_leaf);
  1312. if (child_node == NULL) {
  1313. return NULL;
  1314. }
  1315. else if (child_node == (PyHamtNode *)self) {
  1316. Py_DECREF(child_node);
  1317. return (PyHamtNode *)self;
  1318. }
  1319. new_node = hamt_node_array_clone(self);
  1320. if (new_node == NULL) {
  1321. Py_DECREF(child_node);
  1322. return NULL;
  1323. }
  1324. Py_SETREF(new_node->a_array[idx], child_node); /* borrow */
  1325. VALIDATE_ARRAY_NODE(new_node)
  1326. }
  1327. return (PyHamtNode *)new_node;
  1328. }
  1329. static hamt_without_t
  1330. hamt_node_array_without(PyHamtNode_Array *self,
  1331. uint32_t shift, int32_t hash,
  1332. PyObject *key,
  1333. PyHamtNode **new_node)
  1334. {
  1335. uint32_t idx = hamt_mask(hash, shift);
  1336. PyHamtNode *node = self->a_array[idx];
  1337. if (node == NULL) {
  1338. return W_NOT_FOUND;
  1339. }
  1340. PyHamtNode *sub_node = NULL;
  1341. hamt_without_t res = hamt_node_without(
  1342. (PyHamtNode *)node,
  1343. shift + 5, hash, key, &sub_node);
  1344. switch (res) {
  1345. case W_NOT_FOUND:
  1346. case W_ERROR:
  1347. assert(sub_node == NULL);
  1348. return res;
  1349. case W_NEWNODE: {
  1350. /* We need to replace a node at the `idx` index.
  1351. Clone this node and replace.
  1352. */
  1353. assert(sub_node != NULL);
  1354. PyHamtNode_Array *clone = hamt_node_array_clone(self);
  1355. if (clone == NULL) {
  1356. Py_DECREF(sub_node);
  1357. return W_ERROR;
  1358. }
  1359. Py_SETREF(clone->a_array[idx], sub_node); /* borrow */
  1360. *new_node = (PyHamtNode*)clone; /* borrow */
  1361. return W_NEWNODE;
  1362. }
  1363. case W_EMPTY: {
  1364. assert(sub_node == NULL);
  1365. /* We need to remove a node at the `idx` index.
  1366. Calculate the size of the replacement Array node.
  1367. */
  1368. Py_ssize_t new_count = self->a_count - 1;
  1369. if (new_count == 0) {
  1370. return W_EMPTY;
  1371. }
  1372. if (new_count >= 16) {
  1373. /* We convert Bitmap nodes to Array nodes, when a
  1374. Bitmap node needs to store more than 15 key/value
  1375. pairs. So we will create a new Array node if we
  1376. the number of key/values after deletion is still
  1377. greater than 15.
  1378. */
  1379. PyHamtNode_Array *new = hamt_node_array_clone(self);
  1380. if (new == NULL) {
  1381. return W_ERROR;
  1382. }
  1383. new->a_count = new_count;
  1384. Py_CLEAR(new->a_array[idx]);
  1385. *new_node = (PyHamtNode*)new; /* borrow */
  1386. return W_NEWNODE;
  1387. }
  1388. /* New Array node would have less than 16 key/value
  1389. pairs. We need to create a replacement Bitmap node. */
  1390. Py_ssize_t bitmap_size = new_count * 2;
  1391. uint32_t bitmap = 0;
  1392. PyHamtNode_Bitmap *new = (PyHamtNode_Bitmap *)
  1393. hamt_node_bitmap_new(bitmap_size);
  1394. if (new == NULL) {
  1395. return W_ERROR;
  1396. }
  1397. Py_ssize_t new_i = 0;
  1398. for (uint32_t i = 0; i < HAMT_ARRAY_NODE_SIZE; i++) {
  1399. if (i == idx) {
  1400. /* Skip the node we are deleting. */
  1401. continue;
  1402. }
  1403. PyHamtNode *node = self->a_array[i];
  1404. if (node == NULL) {
  1405. /* Skip any missing nodes. */
  1406. continue;
  1407. }
  1408. bitmap |= 1U << i;
  1409. if (IS_BITMAP_NODE(node)) {
  1410. PyHamtNode_Bitmap *child = (PyHamtNode_Bitmap *)node;
  1411. if (hamt_node_bitmap_count(child) == 1 &&
  1412. child->b_array[0] != NULL)
  1413. {
  1414. /* node is a Bitmap with one key/value pair, just
  1415. merge it into the new Bitmap node we're building.
  1416. Note that we don't inline Bitmap nodes that
  1417. have a NULL key -- those nodes point to another
  1418. tree level, and we cannot simply move tree levels
  1419. up or down.
  1420. */
  1421. PyObject *key = child->b_array[0];
  1422. PyObject *val = child->b_array[1];
  1423. new->b_array[new_i] = Py_NewRef(key);
  1424. new->b_array[new_i + 1] = Py_NewRef(val);
  1425. }
  1426. else {
  1427. new->b_array[new_i] = NULL;
  1428. new->b_array[new_i + 1] = Py_NewRef(node);
  1429. }
  1430. }
  1431. else {
  1432. #ifdef Py_DEBUG
  1433. if (IS_COLLISION_NODE(node)) {
  1434. Py_ssize_t child_count = hamt_node_collision_count(
  1435. (PyHamtNode_Collision*)node);
  1436. assert(child_count > 1);
  1437. }
  1438. else if (IS_ARRAY_NODE(node)) {
  1439. assert(((PyHamtNode_Array*)node)->a_count >= 16);
  1440. }
  1441. #endif
  1442. /* Just copy the node into our new Bitmap */
  1443. new->b_array[new_i] = NULL;
  1444. new->b_array[new_i + 1] = Py_NewRef(node);
  1445. }
  1446. new_i += 2;
  1447. }
  1448. new->b_bitmap = bitmap;
  1449. *new_node = (PyHamtNode*)new; /* borrow */
  1450. return W_NEWNODE;
  1451. }
  1452. default:
  1453. Py_UNREACHABLE();
  1454. }
  1455. }
  1456. static hamt_find_t
  1457. hamt_node_array_find(PyHamtNode_Array *self,
  1458. uint32_t shift, int32_t hash,
  1459. PyObject *key, PyObject **val)
  1460. {
  1461. /* Lookup `key` in the Array node `self`. Set the value
  1462. for the found key to 'val'. */
  1463. uint32_t idx = hamt_mask(hash, shift);
  1464. PyHamtNode *node;
  1465. node = self->a_array[idx];
  1466. if (node == NULL) {
  1467. return F_NOT_FOUND;
  1468. }
  1469. /* Dispatch to the generic hamt_node_find */
  1470. return hamt_node_find(node, shift + 5, hash, key, val);
  1471. }
  1472. static int
  1473. hamt_node_array_traverse(PyHamtNode_Array *self,
  1474. visitproc visit, void *arg)
  1475. {
  1476. /* Array's tp_traverse */
  1477. Py_ssize_t i;
  1478. for (i = 0; i < HAMT_ARRAY_NODE_SIZE; i++) {
  1479. Py_VISIT(self->a_array[i]);
  1480. }
  1481. return 0;
  1482. }
  1483. static void
  1484. hamt_node_array_dealloc(PyHamtNode_Array *self)
  1485. {
  1486. /* Array's tp_dealloc */
  1487. Py_ssize_t i;
  1488. PyObject_GC_UnTrack(self);
  1489. Py_TRASHCAN_BEGIN(self, hamt_node_array_dealloc)
  1490. for (i = 0; i < HAMT_ARRAY_NODE_SIZE; i++) {
  1491. Py_XDECREF(self->a_array[i]);
  1492. }
  1493. Py_TYPE(self)->tp_free((PyObject *)self);
  1494. Py_TRASHCAN_END
  1495. }
  1496. #ifdef Py_DEBUG
  1497. static int
  1498. hamt_node_array_dump(PyHamtNode_Array *node,
  1499. _PyUnicodeWriter *writer, int level)
  1500. {
  1501. /* Debug build: __dump__() method implementation for Array nodes. */
  1502. Py_ssize_t i;
  1503. if (_hamt_dump_ident(writer, level + 1)) {
  1504. goto error;
  1505. }
  1506. if (_hamt_dump_format(writer, "ArrayNode(id=%p):\n", node)) {
  1507. goto error;
  1508. }
  1509. for (i = 0; i < HAMT_ARRAY_NODE_SIZE; i++) {
  1510. if (node->a_array[i] == NULL) {
  1511. continue;
  1512. }
  1513. if (_hamt_dump_ident(writer, level + 2)) {
  1514. goto error;
  1515. }
  1516. if (_hamt_dump_format(writer, "%zd::\n", i)) {
  1517. goto error;
  1518. }
  1519. if (hamt_node_dump(node->a_array[i], writer, level + 1)) {
  1520. goto error;
  1521. }
  1522. if (_hamt_dump_format(writer, "\n")) {
  1523. goto error;
  1524. }
  1525. }
  1526. return 0;
  1527. error:
  1528. return -1;
  1529. }
  1530. #endif /* Py_DEBUG */
  1531. /////////////////////////////////// Node Dispatch
  1532. static PyHamtNode *
  1533. hamt_node_assoc(PyHamtNode *node,
  1534. uint32_t shift, int32_t hash,
  1535. PyObject *key, PyObject *val, int* added_leaf)
  1536. {
  1537. /* Set key/value to the 'node' starting with the given shift/hash.
  1538. Return a new node, or the same node if key/value already
  1539. set.
  1540. added_leaf will be set to 1 if key/value wasn't in the
  1541. tree before.
  1542. This method automatically dispatches to the suitable
  1543. hamt_node_{nodetype}_assoc method.
  1544. */
  1545. if (IS_BITMAP_NODE(node)) {
  1546. return hamt_node_bitmap_assoc(
  1547. (PyHamtNode_Bitmap *)node,
  1548. shift, hash, key, val, added_leaf);
  1549. }
  1550. else if (IS_ARRAY_NODE(node)) {
  1551. return hamt_node_array_assoc(
  1552. (PyHamtNode_Array *)node,
  1553. shift, hash, key, val, added_leaf);
  1554. }
  1555. else {
  1556. assert(IS_COLLISION_NODE(node));
  1557. return hamt_node_collision_assoc(
  1558. (PyHamtNode_Collision *)node,
  1559. shift, hash, key, val, added_leaf);
  1560. }
  1561. }
  1562. static hamt_without_t
  1563. hamt_node_without(PyHamtNode *node,
  1564. uint32_t shift, int32_t hash,
  1565. PyObject *key,
  1566. PyHamtNode **new_node)
  1567. {
  1568. if (IS_BITMAP_NODE(node)) {
  1569. return hamt_node_bitmap_without(
  1570. (PyHamtNode_Bitmap *)node,
  1571. shift, hash, key,
  1572. new_node);
  1573. }
  1574. else if (IS_ARRAY_NODE(node)) {
  1575. return hamt_node_array_without(
  1576. (PyHamtNode_Array *)node,
  1577. shift, hash, key,
  1578. new_node);
  1579. }
  1580. else {
  1581. assert(IS_COLLISION_NODE(node));
  1582. return hamt_node_collision_without(
  1583. (PyHamtNode_Collision *)node,
  1584. shift, hash, key,
  1585. new_node);
  1586. }
  1587. }
  1588. static hamt_find_t
  1589. hamt_node_find(PyHamtNode *node,
  1590. uint32_t shift, int32_t hash,
  1591. PyObject *key, PyObject **val)
  1592. {
  1593. /* Find the key in the node starting with the given shift/hash.
  1594. If a value is found, the result will be set to F_FOUND, and
  1595. *val will point to the found value object.
  1596. If a value wasn't found, the result will be set to F_NOT_FOUND.
  1597. If an exception occurs during the call, the result will be F_ERROR.
  1598. This method automatically dispatches to the suitable
  1599. hamt_node_{nodetype}_find method.
  1600. */
  1601. if (IS_BITMAP_NODE(node)) {
  1602. return hamt_node_bitmap_find(
  1603. (PyHamtNode_Bitmap *)node,
  1604. shift, hash, key, val);
  1605. }
  1606. else if (IS_ARRAY_NODE(node)) {
  1607. return hamt_node_array_find(
  1608. (PyHamtNode_Array *)node,
  1609. shift, hash, key, val);
  1610. }
  1611. else {
  1612. assert(IS_COLLISION_NODE(node));
  1613. return hamt_node_collision_find(
  1614. (PyHamtNode_Collision *)node,
  1615. shift, hash, key, val);
  1616. }
  1617. }
  1618. #ifdef Py_DEBUG
  1619. static int
  1620. hamt_node_dump(PyHamtNode *node,
  1621. _PyUnicodeWriter *writer, int level)
  1622. {
  1623. /* Debug build: __dump__() method implementation for a node.
  1624. This method automatically dispatches to the suitable
  1625. hamt_node_{nodetype})_dump method.
  1626. */
  1627. if (IS_BITMAP_NODE(node)) {
  1628. return hamt_node_bitmap_dump(
  1629. (PyHamtNode_Bitmap *)node, writer, level);
  1630. }
  1631. else if (IS_ARRAY_NODE(node)) {
  1632. return hamt_node_array_dump(
  1633. (PyHamtNode_Array *)node, writer, level);
  1634. }
  1635. else {
  1636. assert(IS_COLLISION_NODE(node));
  1637. return hamt_node_collision_dump(
  1638. (PyHamtNode_Collision *)node, writer, level);
  1639. }
  1640. }
  1641. #endif /* Py_DEBUG */
  1642. /////////////////////////////////// Iterators: Machinery
  1643. static hamt_iter_t
  1644. hamt_iterator_next(PyHamtIteratorState *iter, PyObject **key, PyObject **val);
  1645. static void
  1646. hamt_iterator_init(PyHamtIteratorState *iter, PyHamtNode *root)
  1647. {
  1648. for (uint32_t i = 0; i < _Py_HAMT_MAX_TREE_DEPTH; i++) {
  1649. iter->i_nodes[i] = NULL;
  1650. iter->i_pos[i] = 0;
  1651. }
  1652. iter->i_level = 0;
  1653. /* Note: we don't incref/decref nodes in i_nodes. */
  1654. iter->i_nodes[0] = root;
  1655. }
  1656. static hamt_iter_t
  1657. hamt_iterator_bitmap_next(PyHamtIteratorState *iter,
  1658. PyObject **key, PyObject **val)
  1659. {
  1660. int8_t level = iter->i_level;
  1661. PyHamtNode_Bitmap *node = (PyHamtNode_Bitmap *)(iter->i_nodes[level]);
  1662. Py_ssize_t pos = iter->i_pos[level];
  1663. if (pos + 1 >= Py_SIZE(node)) {
  1664. #ifdef Py_DEBUG
  1665. assert(iter->i_level >= 0);
  1666. iter->i_nodes[iter->i_level] = NULL;
  1667. #endif
  1668. iter->i_level--;
  1669. return hamt_iterator_next(iter, key, val);
  1670. }
  1671. if (node->b_array[pos] == NULL) {
  1672. iter->i_pos[level] = pos + 2;
  1673. int8_t next_level = level + 1;
  1674. assert(next_level < _Py_HAMT_MAX_TREE_DEPTH);
  1675. iter->i_level = next_level;
  1676. iter->i_pos[next_level] = 0;
  1677. iter->i_nodes[next_level] = (PyHamtNode *)
  1678. node->b_array[pos + 1];
  1679. return hamt_iterator_next(iter, key, val);
  1680. }
  1681. *key = node->b_array[pos];
  1682. *val = node->b_array[pos + 1];
  1683. iter->i_pos[level] = pos + 2;
  1684. return I_ITEM;
  1685. }
  1686. static hamt_iter_t
  1687. hamt_iterator_collision_next(PyHamtIteratorState *iter,
  1688. PyObject **key, PyObject **val)
  1689. {
  1690. int8_t level = iter->i_level;
  1691. PyHamtNode_Collision *node = (PyHamtNode_Collision *)(iter->i_nodes[level]);
  1692. Py_ssize_t pos = iter->i_pos[level];
  1693. if (pos + 1 >= Py_SIZE(node)) {
  1694. #ifdef Py_DEBUG
  1695. assert(iter->i_level >= 0);
  1696. iter->i_nodes[iter->i_level] = NULL;
  1697. #endif
  1698. iter->i_level--;
  1699. return hamt_iterator_next(iter, key, val);
  1700. }
  1701. *key = node->c_array[pos];
  1702. *val = node->c_array[pos + 1];
  1703. iter->i_pos[level] = pos + 2;
  1704. return I_ITEM;
  1705. }
  1706. static hamt_iter_t
  1707. hamt_iterator_array_next(PyHamtIteratorState *iter,
  1708. PyObject **key, PyObject **val)
  1709. {
  1710. int8_t level = iter->i_level;
  1711. PyHamtNode_Array *node = (PyHamtNode_Array *)(iter->i_nodes[level]);
  1712. Py_ssize_t pos = iter->i_pos[level];
  1713. if (pos >= HAMT_ARRAY_NODE_SIZE) {
  1714. #ifdef Py_DEBUG
  1715. assert(iter->i_level >= 0);
  1716. iter->i_nodes[iter->i_level] = NULL;
  1717. #endif
  1718. iter->i_level--;
  1719. return hamt_iterator_next(iter, key, val);
  1720. }
  1721. for (Py_ssize_t i = pos; i < HAMT_ARRAY_NODE_SIZE; i++) {
  1722. if (node->a_array[i] != NULL) {
  1723. iter->i_pos[level] = i + 1;
  1724. int8_t next_level = level + 1;
  1725. assert(next_level < _Py_HAMT_MAX_TREE_DEPTH);
  1726. iter->i_pos[next_level] = 0;
  1727. iter->i_nodes[next_level] = node->a_array[i];
  1728. iter->i_level = next_level;
  1729. return hamt_iterator_next(iter, key, val);
  1730. }
  1731. }
  1732. #ifdef Py_DEBUG
  1733. assert(iter->i_level >= 0);
  1734. iter->i_nodes[iter->i_level] = NULL;
  1735. #endif
  1736. iter->i_level--;
  1737. return hamt_iterator_next(iter, key, val);
  1738. }
  1739. static hamt_iter_t
  1740. hamt_iterator_next(PyHamtIteratorState *iter, PyObject **key, PyObject **val)
  1741. {
  1742. if (iter->i_level < 0) {
  1743. return I_END;
  1744. }
  1745. assert(iter->i_level < _Py_HAMT_MAX_TREE_DEPTH);
  1746. PyHamtNode *current = iter->i_nodes[iter->i_level];
  1747. if (IS_BITMAP_NODE(current)) {
  1748. return hamt_iterator_bitmap_next(iter, key, val);
  1749. }
  1750. else if (IS_ARRAY_NODE(current)) {
  1751. return hamt_iterator_array_next(iter, key, val);
  1752. }
  1753. else {
  1754. assert(IS_COLLISION_NODE(current));
  1755. return hamt_iterator_collision_next(iter, key, val);
  1756. }
  1757. }
  1758. /////////////////////////////////// HAMT high-level functions
  1759. PyHamtObject *
  1760. _PyHamt_Assoc(PyHamtObject *o, PyObject *key, PyObject *val)
  1761. {
  1762. int32_t key_hash;
  1763. int added_leaf = 0;
  1764. PyHamtNode *new_root;
  1765. PyHamtObject *new_o;
  1766. key_hash = hamt_hash(key);
  1767. if (key_hash == -1) {
  1768. return NULL;
  1769. }
  1770. new_root = hamt_node_assoc(
  1771. (PyHamtNode *)(o->h_root),
  1772. 0, key_hash, key, val, &added_leaf);
  1773. if (new_root == NULL) {
  1774. return NULL;
  1775. }
  1776. if (new_root == o->h_root) {
  1777. Py_DECREF(new_root);
  1778. return (PyHamtObject*)Py_NewRef(o);
  1779. }
  1780. new_o = hamt_alloc();
  1781. if (new_o == NULL) {
  1782. Py_DECREF(new_root);
  1783. return NULL;
  1784. }
  1785. new_o->h_root = new_root; /* borrow */
  1786. new_o->h_count = added_leaf ? o->h_count + 1 : o->h_count;
  1787. return new_o;
  1788. }
  1789. PyHamtObject *
  1790. _PyHamt_Without(PyHamtObject *o, PyObject *key)
  1791. {
  1792. int32_t key_hash = hamt_hash(key);
  1793. if (key_hash == -1) {
  1794. return NULL;
  1795. }
  1796. PyHamtNode *new_root = NULL;
  1797. hamt_without_t res = hamt_node_without(
  1798. (PyHamtNode *)(o->h_root),
  1799. 0, key_hash, key,
  1800. &new_root);
  1801. switch (res) {
  1802. case W_ERROR:
  1803. return NULL;
  1804. case W_EMPTY:
  1805. return _PyHamt_New();
  1806. case W_NOT_FOUND:
  1807. return (PyHamtObject*)Py_NewRef(o);
  1808. case W_NEWNODE: {
  1809. assert(new_root != NULL);
  1810. PyHamtObject *new_o = hamt_alloc();
  1811. if (new_o == NULL) {
  1812. Py_DECREF(new_root);
  1813. return NULL;
  1814. }
  1815. new_o->h_root = new_root; /* borrow */
  1816. new_o->h_count = o->h_count - 1;
  1817. assert(new_o->h_count >= 0);
  1818. return new_o;
  1819. }
  1820. default:
  1821. Py_UNREACHABLE();
  1822. }
  1823. }
  1824. static hamt_find_t
  1825. hamt_find(PyHamtObject *o, PyObject *key, PyObject **val)
  1826. {
  1827. if (o->h_count == 0) {
  1828. return F_NOT_FOUND;
  1829. }
  1830. int32_t key_hash = hamt_hash(key);
  1831. if (key_hash == -1) {
  1832. return F_ERROR;
  1833. }
  1834. return hamt_node_find(o->h_root, 0, key_hash, key, val);
  1835. }
  1836. int
  1837. _PyHamt_Find(PyHamtObject *o, PyObject *key, PyObject **val)
  1838. {
  1839. hamt_find_t res = hamt_find(o, key, val);
  1840. switch (res) {
  1841. case F_ERROR:
  1842. return -1;
  1843. case F_NOT_FOUND:
  1844. return 0;
  1845. case F_FOUND:
  1846. return 1;
  1847. default:
  1848. Py_UNREACHABLE();
  1849. }
  1850. }
  1851. int
  1852. _PyHamt_Eq(PyHamtObject *v, PyHamtObject *w)
  1853. {
  1854. if (v == w) {
  1855. return 1;
  1856. }
  1857. if (v->h_count != w->h_count) {
  1858. return 0;
  1859. }
  1860. PyHamtIteratorState iter;
  1861. hamt_iter_t iter_res;
  1862. hamt_find_t find_res;
  1863. PyObject *v_key;
  1864. PyObject *v_val;
  1865. PyObject *w_val;
  1866. hamt_iterator_init(&iter, v->h_root);
  1867. do {
  1868. iter_res = hamt_iterator_next(&iter, &v_key, &v_val);
  1869. if (iter_res == I_ITEM) {
  1870. find_res = hamt_find(w, v_key, &w_val);
  1871. switch (find_res) {
  1872. case F_ERROR:
  1873. return -1;
  1874. case F_NOT_FOUND:
  1875. return 0;
  1876. case F_FOUND: {
  1877. int cmp = PyObject_RichCompareBool(v_val, w_val, Py_EQ);
  1878. if (cmp < 0) {
  1879. return -1;
  1880. }
  1881. if (cmp == 0) {
  1882. return 0;
  1883. }
  1884. }
  1885. }
  1886. }
  1887. } while (iter_res != I_END);
  1888. return 1;
  1889. }
  1890. Py_ssize_t
  1891. _PyHamt_Len(PyHamtObject *o)
  1892. {
  1893. return o->h_count;
  1894. }
  1895. static PyHamtObject *
  1896. hamt_alloc(void)
  1897. {
  1898. PyHamtObject *o;
  1899. o = PyObject_GC_New(PyHamtObject, &_PyHamt_Type);
  1900. if (o == NULL) {
  1901. return NULL;
  1902. }
  1903. o->h_count = 0;
  1904. o->h_root = NULL;
  1905. o->h_weakreflist = NULL;
  1906. PyObject_GC_Track(o);
  1907. return o;
  1908. }
  1909. #define _empty_hamt \
  1910. (&_Py_INTERP_SINGLETON(_PyInterpreterState_Get(), hamt_empty))
  1911. PyHamtObject *
  1912. _PyHamt_New(void)
  1913. {
  1914. /* HAMT is an immutable object so we can easily cache an
  1915. empty instance. */
  1916. return (PyHamtObject*)Py_NewRef(_empty_hamt);
  1917. }
  1918. #ifdef Py_DEBUG
  1919. static PyObject *
  1920. hamt_dump(PyHamtObject *self)
  1921. {
  1922. _PyUnicodeWriter writer;
  1923. _PyUnicodeWriter_Init(&writer);
  1924. if (_hamt_dump_format(&writer, "HAMT(len=%zd):\n", self->h_count)) {
  1925. goto error;
  1926. }
  1927. if (hamt_node_dump(self->h_root, &writer, 0)) {
  1928. goto error;
  1929. }
  1930. return _PyUnicodeWriter_Finish(&writer);
  1931. error:
  1932. _PyUnicodeWriter_Dealloc(&writer);
  1933. return NULL;
  1934. }
  1935. #endif /* Py_DEBUG */
  1936. /////////////////////////////////// Iterators: Shared Iterator Implementation
  1937. static int
  1938. hamt_baseiter_tp_clear(PyHamtIterator *it)
  1939. {
  1940. Py_CLEAR(it->hi_obj);
  1941. return 0;
  1942. }
  1943. static void
  1944. hamt_baseiter_tp_dealloc(PyHamtIterator *it)
  1945. {
  1946. PyObject_GC_UnTrack(it);
  1947. (void)hamt_baseiter_tp_clear(it);
  1948. PyObject_GC_Del(it);
  1949. }
  1950. static int
  1951. hamt_baseiter_tp_traverse(PyHamtIterator *it, visitproc visit, void *arg)
  1952. {
  1953. Py_VISIT(it->hi_obj);
  1954. return 0;
  1955. }
  1956. static PyObject *
  1957. hamt_baseiter_tp_iternext(PyHamtIterator *it)
  1958. {
  1959. PyObject *key;
  1960. PyObject *val;
  1961. hamt_iter_t res = hamt_iterator_next(&it->hi_iter, &key, &val);
  1962. switch (res) {
  1963. case I_END:
  1964. PyErr_SetNone(PyExc_StopIteration);
  1965. return NULL;
  1966. case I_ITEM: {
  1967. return (*(it->hi_yield))(key, val);
  1968. }
  1969. default: {
  1970. Py_UNREACHABLE();
  1971. }
  1972. }
  1973. }
  1974. static Py_ssize_t
  1975. hamt_baseiter_tp_len(PyHamtIterator *it)
  1976. {
  1977. return it->hi_obj->h_count;
  1978. }
  1979. static PyMappingMethods PyHamtIterator_as_mapping = {
  1980. (lenfunc)hamt_baseiter_tp_len,
  1981. };
  1982. static PyObject *
  1983. hamt_baseiter_new(PyTypeObject *type, binaryfunc yield, PyHamtObject *o)
  1984. {
  1985. PyHamtIterator *it = PyObject_GC_New(PyHamtIterator, type);
  1986. if (it == NULL) {
  1987. return NULL;
  1988. }
  1989. it->hi_obj = (PyHamtObject*)Py_NewRef(o);
  1990. it->hi_yield = yield;
  1991. hamt_iterator_init(&it->hi_iter, o->h_root);
  1992. return (PyObject*)it;
  1993. }
  1994. #define ITERATOR_TYPE_SHARED_SLOTS \
  1995. .tp_basicsize = sizeof(PyHamtIterator), \
  1996. .tp_itemsize = 0, \
  1997. .tp_as_mapping = &PyHamtIterator_as_mapping, \
  1998. .tp_dealloc = (destructor)hamt_baseiter_tp_dealloc, \
  1999. .tp_getattro = PyObject_GenericGetAttr, \
  2000. .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, \
  2001. .tp_traverse = (traverseproc)hamt_baseiter_tp_traverse, \
  2002. .tp_clear = (inquiry)hamt_baseiter_tp_clear, \
  2003. .tp_iter = PyObject_SelfIter, \
  2004. .tp_iternext = (iternextfunc)hamt_baseiter_tp_iternext,
  2005. /////////////////////////////////// _PyHamtItems_Type
  2006. PyTypeObject _PyHamtItems_Type = {
  2007. PyVarObject_HEAD_INIT(NULL, 0)
  2008. "items",
  2009. ITERATOR_TYPE_SHARED_SLOTS
  2010. };
  2011. static PyObject *
  2012. hamt_iter_yield_items(PyObject *key, PyObject *val)
  2013. {
  2014. return PyTuple_Pack(2, key, val);
  2015. }
  2016. PyObject *
  2017. _PyHamt_NewIterItems(PyHamtObject *o)
  2018. {
  2019. return hamt_baseiter_new(
  2020. &_PyHamtItems_Type, hamt_iter_yield_items, o);
  2021. }
  2022. /////////////////////////////////// _PyHamtKeys_Type
  2023. PyTypeObject _PyHamtKeys_Type = {
  2024. PyVarObject_HEAD_INIT(NULL, 0)
  2025. "keys",
  2026. ITERATOR_TYPE_SHARED_SLOTS
  2027. };
  2028. static PyObject *
  2029. hamt_iter_yield_keys(PyObject *key, PyObject *val)
  2030. {
  2031. return Py_NewRef(key);
  2032. }
  2033. PyObject *
  2034. _PyHamt_NewIterKeys(PyHamtObject *o)
  2035. {
  2036. return hamt_baseiter_new(
  2037. &_PyHamtKeys_Type, hamt_iter_yield_keys, o);
  2038. }
  2039. /////////////////////////////////// _PyHamtValues_Type
  2040. PyTypeObject _PyHamtValues_Type = {
  2041. PyVarObject_HEAD_INIT(NULL, 0)
  2042. "values",
  2043. ITERATOR_TYPE_SHARED_SLOTS
  2044. };
  2045. static PyObject *
  2046. hamt_iter_yield_values(PyObject *key, PyObject *val)
  2047. {
  2048. return Py_NewRef(val);
  2049. }
  2050. PyObject *
  2051. _PyHamt_NewIterValues(PyHamtObject *o)
  2052. {
  2053. return hamt_baseiter_new(
  2054. &_PyHamtValues_Type, hamt_iter_yield_values, o);
  2055. }
  2056. /////////////////////////////////// _PyHamt_Type
  2057. #ifdef Py_DEBUG
  2058. static PyObject *
  2059. hamt_dump(PyHamtObject *self);
  2060. #endif
  2061. static PyObject *
  2062. hamt_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
  2063. {
  2064. return (PyObject*)_PyHamt_New();
  2065. }
  2066. static int
  2067. hamt_tp_clear(PyHamtObject *self)
  2068. {
  2069. Py_CLEAR(self->h_root);
  2070. return 0;
  2071. }
  2072. static int
  2073. hamt_tp_traverse(PyHamtObject *self, visitproc visit, void *arg)
  2074. {
  2075. Py_VISIT(self->h_root);
  2076. return 0;
  2077. }
  2078. static void
  2079. hamt_tp_dealloc(PyHamtObject *self)
  2080. {
  2081. if (self == _empty_hamt) {
  2082. /* The empty one is statically allocated. */
  2083. #ifdef Py_DEBUG
  2084. _Py_FatalRefcountError("deallocating the empty hamt singleton");
  2085. #else
  2086. return;
  2087. #endif
  2088. }
  2089. PyObject_GC_UnTrack(self);
  2090. if (self->h_weakreflist != NULL) {
  2091. PyObject_ClearWeakRefs((PyObject*)self);
  2092. }
  2093. (void)hamt_tp_clear(self);
  2094. Py_TYPE(self)->tp_free(self);
  2095. }
  2096. static PyObject *
  2097. hamt_tp_richcompare(PyObject *v, PyObject *w, int op)
  2098. {
  2099. if (!PyHamt_Check(v) || !PyHamt_Check(w) || (op != Py_EQ && op != Py_NE)) {
  2100. Py_RETURN_NOTIMPLEMENTED;
  2101. }
  2102. int res = _PyHamt_Eq((PyHamtObject *)v, (PyHamtObject *)w);
  2103. if (res < 0) {
  2104. return NULL;
  2105. }
  2106. if (op == Py_NE) {
  2107. res = !res;
  2108. }
  2109. if (res) {
  2110. Py_RETURN_TRUE;
  2111. }
  2112. else {
  2113. Py_RETURN_FALSE;
  2114. }
  2115. }
  2116. static int
  2117. hamt_tp_contains(PyHamtObject *self, PyObject *key)
  2118. {
  2119. PyObject *val;
  2120. return _PyHamt_Find(self, key, &val);
  2121. }
  2122. static PyObject *
  2123. hamt_tp_subscript(PyHamtObject *self, PyObject *key)
  2124. {
  2125. PyObject *val;
  2126. hamt_find_t res = hamt_find(self, key, &val);
  2127. switch (res) {
  2128. case F_ERROR:
  2129. return NULL;
  2130. case F_FOUND:
  2131. return Py_NewRef(val);
  2132. case F_NOT_FOUND:
  2133. PyErr_SetObject(PyExc_KeyError, key);
  2134. return NULL;
  2135. default:
  2136. Py_UNREACHABLE();
  2137. }
  2138. }
  2139. static Py_ssize_t
  2140. hamt_tp_len(PyHamtObject *self)
  2141. {
  2142. return _PyHamt_Len(self);
  2143. }
  2144. static PyObject *
  2145. hamt_tp_iter(PyHamtObject *self)
  2146. {
  2147. return _PyHamt_NewIterKeys(self);
  2148. }
  2149. static PyObject *
  2150. hamt_py_set(PyHamtObject *self, PyObject *args)
  2151. {
  2152. PyObject *key;
  2153. PyObject *val;
  2154. if (!PyArg_UnpackTuple(args, "set", 2, 2, &key, &val)) {
  2155. return NULL;
  2156. }
  2157. return (PyObject *)_PyHamt_Assoc(self, key, val);
  2158. }
  2159. static PyObject *
  2160. hamt_py_get(PyHamtObject *self, PyObject *args)
  2161. {
  2162. PyObject *key;
  2163. PyObject *def = NULL;
  2164. if (!PyArg_UnpackTuple(args, "get", 1, 2, &key, &def)) {
  2165. return NULL;
  2166. }
  2167. PyObject *val = NULL;
  2168. hamt_find_t res = hamt_find(self, key, &val);
  2169. switch (res) {
  2170. case F_ERROR:
  2171. return NULL;
  2172. case F_FOUND:
  2173. return Py_NewRef(val);
  2174. case F_NOT_FOUND:
  2175. if (def == NULL) {
  2176. Py_RETURN_NONE;
  2177. }
  2178. return Py_NewRef(def);
  2179. default:
  2180. Py_UNREACHABLE();
  2181. }
  2182. }
  2183. static PyObject *
  2184. hamt_py_delete(PyHamtObject *self, PyObject *key)
  2185. {
  2186. return (PyObject *)_PyHamt_Without(self, key);
  2187. }
  2188. static PyObject *
  2189. hamt_py_items(PyHamtObject *self, PyObject *args)
  2190. {
  2191. return _PyHamt_NewIterItems(self);
  2192. }
  2193. static PyObject *
  2194. hamt_py_values(PyHamtObject *self, PyObject *args)
  2195. {
  2196. return _PyHamt_NewIterValues(self);
  2197. }
  2198. static PyObject *
  2199. hamt_py_keys(PyHamtObject *self, PyObject *Py_UNUSED(args))
  2200. {
  2201. return _PyHamt_NewIterKeys(self);
  2202. }
  2203. #ifdef Py_DEBUG
  2204. static PyObject *
  2205. hamt_py_dump(PyHamtObject *self, PyObject *Py_UNUSED(args))
  2206. {
  2207. return hamt_dump(self);
  2208. }
  2209. #endif
  2210. static PyMethodDef PyHamt_methods[] = {
  2211. {"set", _PyCFunction_CAST(hamt_py_set), METH_VARARGS, NULL},
  2212. {"get", _PyCFunction_CAST(hamt_py_get), METH_VARARGS, NULL},
  2213. {"delete", _PyCFunction_CAST(hamt_py_delete), METH_O, NULL},
  2214. {"items", _PyCFunction_CAST(hamt_py_items), METH_NOARGS, NULL},
  2215. {"keys", _PyCFunction_CAST(hamt_py_keys), METH_NOARGS, NULL},
  2216. {"values", _PyCFunction_CAST(hamt_py_values), METH_NOARGS, NULL},
  2217. #ifdef Py_DEBUG
  2218. {"__dump__", _PyCFunction_CAST(hamt_py_dump), METH_NOARGS, NULL},
  2219. #endif
  2220. {NULL, NULL}
  2221. };
  2222. static PySequenceMethods PyHamt_as_sequence = {
  2223. 0, /* sq_length */
  2224. 0, /* sq_concat */
  2225. 0, /* sq_repeat */
  2226. 0, /* sq_item */
  2227. 0, /* sq_slice */
  2228. 0, /* sq_ass_item */
  2229. 0, /* sq_ass_slice */
  2230. (objobjproc)hamt_tp_contains, /* sq_contains */
  2231. 0, /* sq_inplace_concat */
  2232. 0, /* sq_inplace_repeat */
  2233. };
  2234. static PyMappingMethods PyHamt_as_mapping = {
  2235. (lenfunc)hamt_tp_len, /* mp_length */
  2236. (binaryfunc)hamt_tp_subscript, /* mp_subscript */
  2237. };
  2238. PyTypeObject _PyHamt_Type = {
  2239. PyVarObject_HEAD_INIT(&PyType_Type, 0)
  2240. "hamt",
  2241. sizeof(PyHamtObject),
  2242. .tp_methods = PyHamt_methods,
  2243. .tp_as_mapping = &PyHamt_as_mapping,
  2244. .tp_as_sequence = &PyHamt_as_sequence,
  2245. .tp_iter = (getiterfunc)hamt_tp_iter,
  2246. .tp_dealloc = (destructor)hamt_tp_dealloc,
  2247. .tp_getattro = PyObject_GenericGetAttr,
  2248. .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
  2249. .tp_richcompare = hamt_tp_richcompare,
  2250. .tp_traverse = (traverseproc)hamt_tp_traverse,
  2251. .tp_clear = (inquiry)hamt_tp_clear,
  2252. .tp_new = hamt_tp_new,
  2253. .tp_weaklistoffset = offsetof(PyHamtObject, h_weakreflist),
  2254. .tp_hash = PyObject_HashNotImplemented,
  2255. };
  2256. /////////////////////////////////// Tree Node Types
  2257. PyTypeObject _PyHamt_ArrayNode_Type = {
  2258. PyVarObject_HEAD_INIT(&PyType_Type, 0)
  2259. "hamt_array_node",
  2260. sizeof(PyHamtNode_Array),
  2261. 0,
  2262. .tp_dealloc = (destructor)hamt_node_array_dealloc,
  2263. .tp_getattro = PyObject_GenericGetAttr,
  2264. .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
  2265. .tp_traverse = (traverseproc)hamt_node_array_traverse,
  2266. .tp_free = PyObject_GC_Del,
  2267. .tp_hash = PyObject_HashNotImplemented,
  2268. };
  2269. PyTypeObject _PyHamt_BitmapNode_Type = {
  2270. PyVarObject_HEAD_INIT(&PyType_Type, 0)
  2271. "hamt_bitmap_node",
  2272. sizeof(PyHamtNode_Bitmap) - sizeof(PyObject *),
  2273. sizeof(PyObject *),
  2274. .tp_dealloc = (destructor)hamt_node_bitmap_dealloc,
  2275. .tp_getattro = PyObject_GenericGetAttr,
  2276. .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
  2277. .tp_traverse = (traverseproc)hamt_node_bitmap_traverse,
  2278. .tp_free = PyObject_GC_Del,
  2279. .tp_hash = PyObject_HashNotImplemented,
  2280. };
  2281. PyTypeObject _PyHamt_CollisionNode_Type = {
  2282. PyVarObject_HEAD_INIT(&PyType_Type, 0)
  2283. "hamt_collision_node",
  2284. sizeof(PyHamtNode_Collision) - sizeof(PyObject *),
  2285. sizeof(PyObject *),
  2286. .tp_dealloc = (destructor)hamt_node_collision_dealloc,
  2287. .tp_getattro = PyObject_GenericGetAttr,
  2288. .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
  2289. .tp_traverse = (traverseproc)hamt_node_collision_traverse,
  2290. .tp_free = PyObject_GC_Del,
  2291. .tp_hash = PyObject_HashNotImplemented,
  2292. };