pg_query 4.2.1 → 5.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (531) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +31 -0
  3. data/README.md +6 -8
  4. data/Rakefile +5 -6
  5. data/ext/pg_query/extconf.rb +14 -4
  6. data/ext/pg_query/include/pg_query.h +27 -3
  7. data/ext/pg_query/include/pg_query_enum_defs.c +311 -149
  8. data/ext/pg_query/include/pg_query_fingerprint_conds.c +545 -489
  9. data/ext/pg_query/include/pg_query_fingerprint_defs.c +5092 -4432
  10. data/ext/pg_query/include/pg_query_outfuncs_conds.c +385 -343
  11. data/ext/pg_query/include/pg_query_outfuncs_defs.c +1294 -1161
  12. data/ext/pg_query/include/pg_query_readfuncs_conds.c +137 -123
  13. data/ext/pg_query/include/pg_query_readfuncs_defs.c +1657 -1496
  14. data/ext/pg_query/include/{access → postgres/access}/amapi.h +3 -1
  15. data/ext/pg_query/include/{access → postgres/access}/attmap.h +5 -3
  16. data/ext/pg_query/include/{access → postgres/access}/attnum.h +1 -1
  17. data/ext/pg_query/include/{access → postgres/access}/clog.h +1 -1
  18. data/ext/pg_query/include/{access → postgres/access}/commit_ts.h +1 -1
  19. data/ext/pg_query/include/{access → postgres/access}/detoast.h +1 -1
  20. data/ext/pg_query/include/{access → postgres/access}/genam.h +7 -5
  21. data/ext/pg_query/include/{access → postgres/access}/gin.h +16 -3
  22. data/ext/pg_query/include/{access → postgres/access}/htup.h +1 -1
  23. data/ext/pg_query/include/{access → postgres/access}/htup_details.h +6 -2
  24. data/ext/pg_query/include/{access → postgres/access}/itup.h +61 -58
  25. data/ext/pg_query/include/{access → postgres/access}/parallel.h +2 -2
  26. data/ext/pg_query/include/{access → postgres/access}/printtup.h +1 -1
  27. data/ext/pg_query/include/{access → postgres/access}/relation.h +1 -1
  28. data/ext/pg_query/include/{access → postgres/access}/relscan.h +1 -1
  29. data/ext/pg_query/include/{access → postgres/access}/rmgrlist.h +2 -2
  30. data/ext/pg_query/include/{access → postgres/access}/sdir.h +12 -3
  31. data/ext/pg_query/include/{access → postgres/access}/skey.h +1 -1
  32. data/ext/pg_query/include/{access → postgres/access}/stratnum.h +1 -1
  33. data/ext/pg_query/include/{access → postgres/access}/sysattr.h +1 -1
  34. data/ext/pg_query/include/{access → postgres/access}/table.h +1 -1
  35. data/ext/pg_query/include/{access → postgres/access}/tableam.h +68 -45
  36. data/ext/pg_query/include/{access → postgres/access}/toast_compression.h +1 -1
  37. data/ext/pg_query/include/{access → postgres/access}/transam.h +1 -1
  38. data/ext/pg_query/include/postgres/access/tsmapi.h +82 -0
  39. data/ext/pg_query/include/{access → postgres/access}/tupconvert.h +5 -2
  40. data/ext/pg_query/include/{access → postgres/access}/tupdesc.h +2 -2
  41. data/ext/pg_query/include/{access → postgres/access}/tupmacs.h +58 -98
  42. data/ext/pg_query/include/{access → postgres/access}/twophase.h +2 -2
  43. data/ext/pg_query/include/{access → postgres/access}/xact.h +25 -18
  44. data/ext/pg_query/include/{access → postgres/access}/xlog.h +15 -16
  45. data/ext/pg_query/include/{access → postgres/access}/xlog_internal.h +100 -62
  46. data/ext/pg_query/include/postgres/access/xlogbackup.h +41 -0
  47. data/ext/pg_query/include/{access → postgres/access}/xlogdefs.h +6 -25
  48. data/ext/pg_query/include/{access → postgres/access}/xlogprefetcher.h +1 -1
  49. data/ext/pg_query/include/{access → postgres/access}/xlogreader.h +7 -6
  50. data/ext/pg_query/include/{access → postgres/access}/xlogrecord.h +17 -5
  51. data/ext/pg_query/include/{access → postgres/access}/xlogrecovery.h +4 -3
  52. data/ext/pg_query/include/postgres/archive/archive_module.h +59 -0
  53. data/ext/pg_query/include/{c.h → postgres/c.h} +144 -156
  54. data/ext/pg_query/include/{catalog → postgres/catalog}/catalog.h +4 -3
  55. data/ext/pg_query/include/{catalog → postgres/catalog}/catversion.h +6 -2
  56. data/ext/pg_query/include/{catalog → postgres/catalog}/dependency.h +5 -4
  57. data/ext/pg_query/include/{catalog → postgres/catalog}/genbki.h +7 -6
  58. data/ext/pg_query/include/{catalog → postgres/catalog}/index.h +4 -4
  59. data/ext/pg_query/include/{catalog → postgres/catalog}/indexing.h +1 -1
  60. data/ext/pg_query/include/{catalog → postgres/catalog}/namespace.h +2 -2
  61. data/ext/pg_query/include/{catalog → postgres/catalog}/objectaccess.h +10 -8
  62. data/ext/pg_query/include/{catalog → postgres/catalog}/objectaddress.h +3 -3
  63. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_aggregate.h +1 -1
  64. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_aggregate_d.h +1 -1
  65. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_am.h +1 -1
  66. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_am_d.h +1 -1
  67. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_attribute.h +19 -17
  68. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_attribute_d.h +19 -19
  69. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_authid.h +1 -1
  70. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_authid_d.h +3 -1
  71. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_class.h +1 -1
  72. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_class_d.h +1 -1
  73. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_collation.h +3 -1
  74. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_collation_d.h +4 -3
  75. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_constraint.h +2 -2
  76. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_constraint_d.h +1 -1
  77. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_control.h +9 -1
  78. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_conversion.h +2 -2
  79. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_conversion_d.h +1 -1
  80. data/ext/pg_query/include/postgres/catalog/pg_database.h +124 -0
  81. data/ext/pg_query/include/postgres/catalog/pg_database_d.h +52 -0
  82. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_depend.h +1 -1
  83. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_depend_d.h +1 -1
  84. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_event_trigger.h +1 -1
  85. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_event_trigger_d.h +1 -1
  86. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_index.h +1 -1
  87. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_index_d.h +1 -1
  88. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_language.h +1 -1
  89. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_language_d.h +1 -1
  90. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_namespace.h +1 -1
  91. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_namespace_d.h +1 -1
  92. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_opclass.h +1 -1
  93. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_opclass_d.h +1 -1
  94. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_operator.h +1 -1
  95. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_operator_d.h +1 -1
  96. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_opfamily.h +3 -2
  97. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_opfamily_d.h +4 -2
  98. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_partitioned_table.h +1 -1
  99. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_partitioned_table_d.h +1 -1
  100. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_proc.h +1 -1
  101. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_proc_d.h +1 -1
  102. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_publication.h +2 -5
  103. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_publication_d.h +1 -1
  104. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_replication_origin.h +1 -1
  105. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_replication_origin_d.h +1 -1
  106. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_statistic.h +1 -1
  107. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_statistic_d.h +1 -1
  108. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_statistic_ext.h +1 -1
  109. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_statistic_ext_d.h +1 -1
  110. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_transform.h +1 -1
  111. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_transform_d.h +1 -1
  112. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_trigger.h +1 -1
  113. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_trigger_d.h +1 -1
  114. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_ts_config.h +1 -1
  115. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_ts_config_d.h +1 -1
  116. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_ts_dict.h +1 -1
  117. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_ts_dict_d.h +1 -1
  118. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_ts_parser.h +1 -1
  119. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_ts_parser_d.h +1 -1
  120. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_ts_template.h +1 -1
  121. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_ts_template_d.h +1 -1
  122. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_type.h +1 -1
  123. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_type_d.h +1 -1
  124. data/ext/pg_query/include/{catalog → postgres/catalog}/storage.h +6 -6
  125. data/ext/pg_query/include/{commands → postgres/commands}/async.h +1 -1
  126. data/ext/pg_query/include/{commands → postgres/commands}/dbcommands.h +2 -1
  127. data/ext/pg_query/include/{commands → postgres/commands}/defrem.h +2 -1
  128. data/ext/pg_query/include/{commands → postgres/commands}/event_trigger.h +1 -1
  129. data/ext/pg_query/include/{commands → postgres/commands}/explain.h +3 -1
  130. data/ext/pg_query/include/{commands → postgres/commands}/prepare.h +1 -1
  131. data/ext/pg_query/include/{commands → postgres/commands}/tablespace.h +4 -4
  132. data/ext/pg_query/include/{commands → postgres/commands}/trigger.h +15 -14
  133. data/ext/pg_query/include/{commands → postgres/commands}/user.h +9 -3
  134. data/ext/pg_query/include/{commands → postgres/commands}/vacuum.h +60 -14
  135. data/ext/pg_query/include/postgres/common/cryptohash.h +39 -0
  136. data/ext/pg_query/include/{common → postgres/common}/file_perm.h +1 -1
  137. data/ext/pg_query/include/{common → postgres/common}/hashfn.h +1 -1
  138. data/ext/pg_query/include/postgres/common/int.h +437 -0
  139. data/ext/pg_query/include/{common → postgres/common}/keywords.h +1 -1
  140. data/ext/pg_query/include/{common → postgres/common}/kwlookup.h +2 -2
  141. data/ext/pg_query/include/{common → postgres/common}/pg_prng.h +3 -2
  142. data/ext/pg_query/include/{common → postgres/common}/relpath.h +20 -13
  143. data/ext/pg_query/include/postgres/common/scram-common.h +70 -0
  144. data/ext/pg_query/include/postgres/common/sha2.h +32 -0
  145. data/ext/pg_query/include/{common → postgres/common}/string.h +5 -3
  146. data/ext/pg_query/include/{common → postgres/common}/unicode_east_asian_fw_table.h +10 -10
  147. data/ext/pg_query/include/{common/unicode_combining_table.h → postgres/common/unicode_nonspacing_table.h} +31 -13
  148. data/ext/pg_query/include/postgres/copyfuncs.funcs.c +5013 -0
  149. data/ext/pg_query/include/postgres/copyfuncs.switch.c +938 -0
  150. data/ext/pg_query/include/{datatype → postgres/datatype}/timestamp.h +11 -4
  151. data/ext/pg_query/include/postgres/equalfuncs.funcs.c +3097 -0
  152. data/ext/pg_query/include/postgres/equalfuncs.switch.c +785 -0
  153. data/ext/pg_query/include/{executor → postgres/executor}/execdesc.h +1 -1
  154. data/ext/pg_query/include/{executor → postgres/executor}/executor.h +34 -17
  155. data/ext/pg_query/include/{executor → postgres/executor}/functions.h +1 -1
  156. data/ext/pg_query/include/{executor → postgres/executor}/instrument.h +1 -1
  157. data/ext/pg_query/include/{executor → postgres/executor}/spi.h +2 -2
  158. data/ext/pg_query/include/{executor → postgres/executor}/tablefunc.h +1 -1
  159. data/ext/pg_query/include/{executor → postgres/executor}/tuptable.h +18 -11
  160. data/ext/pg_query/include/{fmgr.h → postgres/fmgr.h} +21 -2
  161. data/ext/pg_query/include/postgres/foreign/fdwapi.h +294 -0
  162. data/ext/pg_query/include/{funcapi.h → postgres/funcapi.h} +12 -12
  163. data/ext/pg_query/include/postgres/gram.h +1127 -0
  164. data/ext/pg_query/include/{parser → postgres}/gramparse.h +4 -4
  165. data/ext/pg_query/include/{jit → postgres/jit}/jit.h +2 -2
  166. data/ext/pg_query/include/postgres/kwlist_d.h +1119 -0
  167. data/ext/pg_query/include/{lib → postgres/lib}/dshash.h +4 -1
  168. data/ext/pg_query/include/{lib → postgres/lib}/ilist.h +435 -22
  169. data/ext/pg_query/include/{lib → postgres/lib}/pairingheap.h +1 -1
  170. data/ext/pg_query/include/{lib → postgres/lib}/simplehash.h +9 -9
  171. data/ext/pg_query/include/{lib → postgres/lib}/sort_template.h +1 -1
  172. data/ext/pg_query/include/{lib → postgres/lib}/stringinfo.h +3 -3
  173. data/ext/pg_query/include/{libpq → postgres/libpq}/auth.h +8 -2
  174. data/ext/pg_query/include/{libpq → postgres/libpq}/crypt.h +1 -1
  175. data/ext/pg_query/include/{libpq → postgres/libpq}/hba.h +24 -17
  176. data/ext/pg_query/include/{libpq → postgres/libpq}/libpq-be.h +36 -25
  177. data/ext/pg_query/include/{libpq → postgres/libpq}/libpq.h +1 -1
  178. data/ext/pg_query/include/{libpq → postgres/libpq}/pqcomm.h +10 -41
  179. data/ext/pg_query/include/{libpq → postgres/libpq}/pqformat.h +2 -2
  180. data/ext/pg_query/include/{libpq → postgres/libpq}/pqsignal.h +22 -10
  181. data/ext/pg_query/include/postgres/libpq/sasl.h +136 -0
  182. data/ext/pg_query/include/postgres/libpq/scram.h +37 -0
  183. data/ext/pg_query/include/{mb → postgres/mb}/pg_wchar.h +35 -18
  184. data/ext/pg_query/include/{mb → postgres/mb}/stringinfo_mb.h +1 -1
  185. data/ext/pg_query/include/{miscadmin.h → postgres/miscadmin.h} +27 -15
  186. data/ext/pg_query/include/{nodes → postgres/nodes}/bitmapset.h +11 -7
  187. data/ext/pg_query/include/{nodes → postgres/nodes}/execnodes.h +83 -30
  188. data/ext/pg_query/include/{nodes → postgres/nodes}/extensible.h +5 -3
  189. data/ext/pg_query/include/{nodes → postgres/nodes}/lockoptions.h +1 -1
  190. data/ext/pg_query/include/{nodes → postgres/nodes}/makefuncs.h +14 -2
  191. data/ext/pg_query/include/{nodes → postgres/nodes}/memnodes.h +7 -4
  192. data/ext/pg_query/include/postgres/nodes/miscnodes.h +56 -0
  193. data/ext/pg_query/include/{nodes → postgres/nodes}/nodeFuncs.h +89 -29
  194. data/ext/pg_query/include/{nodes → postgres/nodes}/nodes.h +96 -511
  195. data/ext/pg_query/include/postgres/nodes/nodetags.h +471 -0
  196. data/ext/pg_query/include/{nodes → postgres/nodes}/params.h +3 -3
  197. data/ext/pg_query/include/{nodes → postgres/nodes}/parsenodes.h +377 -139
  198. data/ext/pg_query/include/{nodes → postgres/nodes}/pathnodes.h +1090 -440
  199. data/ext/pg_query/include/{nodes → postgres/nodes}/pg_list.h +30 -7
  200. data/ext/pg_query/include/{nodes → postgres/nodes}/plannodes.h +367 -124
  201. data/ext/pg_query/include/{nodes → postgres/nodes}/primnodes.h +670 -222
  202. data/ext/pg_query/include/{nodes → postgres/nodes}/print.h +1 -1
  203. data/ext/pg_query/include/{utils → postgres/nodes}/queryjumble.h +5 -7
  204. data/ext/pg_query/include/postgres/nodes/replnodes.h +111 -0
  205. data/ext/pg_query/include/postgres/nodes/supportnodes.h +346 -0
  206. data/ext/pg_query/include/{nodes → postgres/nodes}/tidbitmap.h +1 -1
  207. data/ext/pg_query/include/{nodes → postgres/nodes}/value.h +12 -2
  208. data/ext/pg_query/include/{optimizer → postgres/optimizer}/cost.h +6 -4
  209. data/ext/pg_query/include/{optimizer → postgres/optimizer}/geqo.h +1 -1
  210. data/ext/pg_query/include/{optimizer → postgres/optimizer}/geqo_gene.h +1 -1
  211. data/ext/pg_query/include/{optimizer → postgres/optimizer}/optimizer.h +8 -8
  212. data/ext/pg_query/include/{optimizer → postgres/optimizer}/paths.h +16 -7
  213. data/ext/pg_query/include/{optimizer → postgres/optimizer}/planmain.h +3 -6
  214. data/ext/pg_query/include/{parser → postgres/parser}/analyze.h +4 -3
  215. data/ext/pg_query/include/{parser → postgres/parser}/kwlist.h +12 -1
  216. data/ext/pg_query/include/{parser → postgres/parser}/parse_agg.h +4 -2
  217. data/ext/pg_query/include/{parser → postgres/parser}/parse_coerce.h +3 -1
  218. data/ext/pg_query/include/{parser → postgres/parser}/parse_expr.h +1 -1
  219. data/ext/pg_query/include/{parser → postgres/parser}/parse_func.h +1 -1
  220. data/ext/pg_query/include/{parser → postgres/parser}/parse_node.h +22 -4
  221. data/ext/pg_query/include/{parser → postgres/parser}/parse_oper.h +3 -3
  222. data/ext/pg_query/include/{parser → postgres/parser}/parse_relation.h +8 -3
  223. data/ext/pg_query/include/{parser → postgres/parser}/parse_type.h +4 -3
  224. data/ext/pg_query/include/{parser → postgres/parser}/parser.h +4 -4
  225. data/ext/pg_query/include/{parser → postgres/parser}/parsetree.h +1 -1
  226. data/ext/pg_query/include/{parser → postgres/parser}/scanner.h +2 -2
  227. data/ext/pg_query/include/{parser → postgres/parser}/scansup.h +1 -1
  228. data/ext/pg_query/include/{partitioning → postgres/partitioning}/partdefs.h +1 -1
  229. data/ext/pg_query/include/{pg_config.h → postgres/pg_config.h} +158 -218
  230. data/ext/pg_query/include/{pg_config_manual.h → postgres/pg_config_manual.h} +8 -46
  231. data/ext/pg_query/include/postgres/pg_config_os.h +8 -0
  232. data/ext/pg_query/include/{pg_getopt.h → postgres/pg_getopt.h} +1 -1
  233. data/ext/pg_query/include/{pg_trace.h → postgres/pg_trace.h} +1 -1
  234. data/ext/pg_query/include/{pgstat.h → postgres/pgstat.h} +173 -94
  235. data/ext/pg_query/include/{pgtime.h → postgres/pgtime.h} +3 -3
  236. data/ext/pg_query/include/{pl_gram.h → postgres/pl_gram.h} +66 -64
  237. data/ext/pg_query/include/{pl_reserved_kwlist.h → postgres/pl_reserved_kwlist.h} +1 -1
  238. data/ext/pg_query/include/{pl_reserved_kwlist_d.h → postgres/pl_reserved_kwlist_d.h} +1 -1
  239. data/ext/pg_query/include/{pl_unreserved_kwlist.h → postgres/pl_unreserved_kwlist.h} +2 -1
  240. data/ext/pg_query/include/{pl_unreserved_kwlist_d.h → postgres/pl_unreserved_kwlist_d.h} +48 -46
  241. data/ext/pg_query/include/{plpgsql.h → postgres/plpgsql.h} +28 -33
  242. data/ext/pg_query/include/{port → postgres/port}/atomics/arch-arm.h +3 -3
  243. data/ext/pg_query/include/postgres/port/atomics/arch-hppa.h +17 -0
  244. data/ext/pg_query/include/{port → postgres/port}/atomics/arch-ppc.h +21 -21
  245. data/ext/pg_query/include/{port → postgres/port}/atomics/arch-x86.h +2 -2
  246. data/ext/pg_query/include/{port → postgres/port}/atomics/fallback.h +3 -3
  247. data/ext/pg_query/include/{port → postgres/port}/atomics/generic-gcc.h +1 -1
  248. data/ext/pg_query/include/postgres/port/atomics/generic-msvc.h +101 -0
  249. data/ext/pg_query/include/postgres/port/atomics/generic-sunpro.h +106 -0
  250. data/ext/pg_query/include/{port → postgres/port}/atomics/generic.h +1 -1
  251. data/ext/pg_query/include/{port → postgres/port}/atomics.h +2 -7
  252. data/ext/pg_query/include/{port → postgres/port}/pg_bitutils.h +62 -25
  253. data/ext/pg_query/include/{port → postgres/port}/pg_bswap.h +1 -1
  254. data/ext/pg_query/include/{port → postgres/port}/pg_crc32c.h +1 -1
  255. data/ext/pg_query/include/postgres/port/simd.h +375 -0
  256. data/ext/pg_query/include/postgres/port/win32/arpa/inet.h +3 -0
  257. data/ext/pg_query/include/postgres/port/win32/dlfcn.h +1 -0
  258. data/ext/pg_query/include/postgres/port/win32/grp.h +1 -0
  259. data/ext/pg_query/include/postgres/port/win32/netdb.h +7 -0
  260. data/ext/pg_query/include/postgres/port/win32/netinet/in.h +3 -0
  261. data/ext/pg_query/include/postgres/port/win32/netinet/tcp.h +7 -0
  262. data/ext/pg_query/include/postgres/port/win32/pwd.h +3 -0
  263. data/ext/pg_query/include/postgres/port/win32/sys/resource.h +20 -0
  264. data/ext/pg_query/include/postgres/port/win32/sys/select.h +3 -0
  265. data/ext/pg_query/include/postgres/port/win32/sys/socket.h +26 -0
  266. data/ext/pg_query/include/postgres/port/win32/sys/un.h +17 -0
  267. data/ext/pg_query/include/postgres/port/win32/sys/wait.h +3 -0
  268. data/ext/pg_query/include/postgres/port/win32.h +59 -0
  269. data/ext/pg_query/include/postgres/port/win32_msvc/dirent.h +34 -0
  270. data/ext/pg_query/include/postgres/port/win32_msvc/sys/file.h +1 -0
  271. data/ext/pg_query/include/postgres/port/win32_msvc/sys/param.h +1 -0
  272. data/ext/pg_query/include/postgres/port/win32_msvc/sys/time.h +1 -0
  273. data/ext/pg_query/include/postgres/port/win32_msvc/unistd.h +9 -0
  274. data/ext/pg_query/include/postgres/port/win32_msvc/utime.h +3 -0
  275. data/ext/pg_query/include/postgres/port/win32_port.h +594 -0
  276. data/ext/pg_query/include/{port.h → postgres/port.h} +42 -75
  277. data/ext/pg_query/include/postgres/portability/instr_time.h +197 -0
  278. data/ext/pg_query/include/postgres/postgres.h +579 -0
  279. data/ext/pg_query/include/{postgres_ext.h → postgres/postgres_ext.h} +0 -1
  280. data/ext/pg_query/include/{postmaster → postgres/postmaster}/autovacuum.h +1 -4
  281. data/ext/pg_query/include/{postmaster → postgres/postmaster}/bgworker.h +2 -2
  282. data/ext/pg_query/include/{postmaster → postgres/postmaster}/bgworker_internals.h +1 -1
  283. data/ext/pg_query/include/{postmaster → postgres/postmaster}/bgwriter.h +2 -2
  284. data/ext/pg_query/include/{postmaster → postgres/postmaster}/interrupt.h +1 -1
  285. data/ext/pg_query/include/postgres/postmaster/pgarch.h +36 -0
  286. data/ext/pg_query/include/{postmaster → postgres/postmaster}/postmaster.h +6 -3
  287. data/ext/pg_query/include/{postmaster → postgres/postmaster}/startup.h +3 -1
  288. data/ext/pg_query/include/{postmaster → postgres/postmaster}/syslogger.h +2 -2
  289. data/ext/pg_query/include/{postmaster → postgres/postmaster}/walwriter.h +3 -1
  290. data/ext/pg_query/include/{regex → postgres/regex}/regex.h +9 -6
  291. data/ext/pg_query/include/{replication → postgres/replication}/logicallauncher.h +6 -1
  292. data/ext/pg_query/include/{replication → postgres/replication}/logicalproto.h +30 -10
  293. data/ext/pg_query/include/postgres/replication/logicalworker.h +32 -0
  294. data/ext/pg_query/include/{replication → postgres/replication}/origin.h +4 -4
  295. data/ext/pg_query/include/{replication → postgres/replication}/reorderbuffer.h +113 -45
  296. data/ext/pg_query/include/{replication → postgres/replication}/slot.h +25 -6
  297. data/ext/pg_query/include/{replication → postgres/replication}/syncrep.h +2 -8
  298. data/ext/pg_query/include/{replication → postgres/replication}/walreceiver.h +15 -9
  299. data/ext/pg_query/include/{replication → postgres/replication}/walsender.h +13 -13
  300. data/ext/pg_query/include/{rewrite → postgres/rewrite}/prs2lock.h +1 -1
  301. data/ext/pg_query/include/{rewrite → postgres/rewrite}/rewriteHandler.h +1 -4
  302. data/ext/pg_query/include/{rewrite → postgres/rewrite}/rewriteManip.h +11 -2
  303. data/ext/pg_query/include/{rewrite → postgres/rewrite}/rewriteSupport.h +1 -1
  304. data/ext/pg_query/include/{storage → postgres/storage}/backendid.h +1 -1
  305. data/ext/pg_query/include/{storage → postgres/storage}/block.h +24 -31
  306. data/ext/pg_query/include/{storage → postgres/storage}/buf.h +1 -1
  307. data/ext/pg_query/include/{storage → postgres/storage}/bufmgr.h +183 -87
  308. data/ext/pg_query/include/{storage → postgres/storage}/bufpage.h +146 -93
  309. data/ext/pg_query/include/{storage → postgres/storage}/condition_variable.h +2 -2
  310. data/ext/pg_query/include/{storage → postgres/storage}/dsm.h +3 -6
  311. data/ext/pg_query/include/{storage → postgres/storage}/dsm_impl.h +4 -1
  312. data/ext/pg_query/include/{storage → postgres/storage}/fd.h +24 -20
  313. data/ext/pg_query/include/{storage → postgres/storage}/fileset.h +1 -1
  314. data/ext/pg_query/include/{storage → postgres/storage}/ipc.h +2 -2
  315. data/ext/pg_query/include/{storage → postgres/storage}/item.h +1 -1
  316. data/ext/pg_query/include/{storage → postgres/storage}/itemid.h +1 -1
  317. data/ext/pg_query/include/{storage → postgres/storage}/itemptr.h +94 -57
  318. data/ext/pg_query/include/{storage → postgres/storage}/large_object.h +1 -1
  319. data/ext/pg_query/include/{storage → postgres/storage}/latch.h +9 -1
  320. data/ext/pg_query/include/{storage → postgres/storage}/lmgr.h +6 -1
  321. data/ext/pg_query/include/{storage → postgres/storage}/lock.h +21 -13
  322. data/ext/pg_query/include/{storage → postgres/storage}/lockdefs.h +3 -3
  323. data/ext/pg_query/include/{storage → postgres/storage}/lwlock.h +16 -2
  324. data/ext/pg_query/include/{storage → postgres/storage}/off.h +1 -1
  325. data/ext/pg_query/include/{storage → postgres/storage}/pg_sema.h +1 -1
  326. data/ext/pg_query/include/{storage → postgres/storage}/pg_shmem.h +1 -1
  327. data/ext/pg_query/include/{storage → postgres/storage}/pmsignal.h +1 -1
  328. data/ext/pg_query/include/{storage → postgres/storage}/predicate.h +2 -2
  329. data/ext/pg_query/include/{storage → postgres/storage}/proc.h +22 -17
  330. data/ext/pg_query/include/{storage → postgres/storage}/procarray.h +3 -2
  331. data/ext/pg_query/include/{storage → postgres/storage}/proclist_types.h +1 -1
  332. data/ext/pg_query/include/{storage → postgres/storage}/procsignal.h +3 -1
  333. data/ext/pg_query/include/postgres/storage/relfilelocator.h +99 -0
  334. data/ext/pg_query/include/{storage → postgres/storage}/s_lock.h +66 -309
  335. data/ext/pg_query/include/{storage → postgres/storage}/sharedfileset.h +1 -1
  336. data/ext/pg_query/include/{storage → postgres/storage}/shm_mq.h +1 -1
  337. data/ext/pg_query/include/{storage → postgres/storage}/shm_toc.h +1 -1
  338. data/ext/pg_query/include/{storage → postgres/storage}/shmem.h +1 -23
  339. data/ext/pg_query/include/{storage → postgres/storage}/sinval.h +3 -3
  340. data/ext/pg_query/include/{storage → postgres/storage}/sinvaladt.h +4 -2
  341. data/ext/pg_query/include/{storage → postgres/storage}/smgr.h +12 -10
  342. data/ext/pg_query/include/{storage → postgres/storage}/spin.h +1 -1
  343. data/ext/pg_query/include/{storage → postgres/storage}/standby.h +9 -8
  344. data/ext/pg_query/include/{storage → postgres/storage}/standbydefs.h +1 -1
  345. data/ext/pg_query/include/{storage → postgres/storage}/sync.h +3 -3
  346. data/ext/pg_query/include/{tcop → postgres/tcop}/cmdtag.h +7 -2
  347. data/ext/pg_query/include/{tcop → postgres/tcop}/cmdtaglist.h +1 -1
  348. data/ext/pg_query/include/{tcop → postgres/tcop}/deparse_utility.h +1 -1
  349. data/ext/pg_query/include/{tcop → postgres/tcop}/dest.h +1 -3
  350. data/ext/pg_query/include/{tcop → postgres/tcop}/fastpath.h +1 -1
  351. data/ext/pg_query/include/{tcop → postgres/tcop}/pquery.h +1 -1
  352. data/ext/pg_query/include/{tcop → postgres/tcop}/tcopprot.h +3 -6
  353. data/ext/pg_query/include/{tcop → postgres/tcop}/utility.h +1 -1
  354. data/ext/pg_query/include/{tsearch → postgres/tsearch}/ts_cache.h +2 -4
  355. data/ext/pg_query/include/{utils → postgres/utils}/acl.h +26 -81
  356. data/ext/pg_query/include/{utils → postgres/utils}/aclchk_internal.h +1 -1
  357. data/ext/pg_query/include/{utils → postgres/utils}/array.h +19 -1
  358. data/ext/pg_query/include/{utils → postgres/utils}/backend_progress.h +2 -1
  359. data/ext/pg_query/include/{utils → postgres/utils}/backend_status.h +24 -3
  360. data/ext/pg_query/include/{utils → postgres/utils}/builtins.h +15 -6
  361. data/ext/pg_query/include/{utils → postgres/utils}/bytea.h +1 -1
  362. data/ext/pg_query/include/{utils → postgres/utils}/catcache.h +1 -1
  363. data/ext/pg_query/include/{utils → postgres/utils}/date.h +37 -9
  364. data/ext/pg_query/include/{utils → postgres/utils}/datetime.h +41 -21
  365. data/ext/pg_query/include/{utils → postgres/utils}/datum.h +1 -1
  366. data/ext/pg_query/include/{utils → postgres/utils}/dsa.h +5 -1
  367. data/ext/pg_query/include/{utils → postgres/utils}/elog.h +104 -29
  368. data/ext/pg_query/include/{utils → postgres/utils}/expandeddatum.h +14 -3
  369. data/ext/pg_query/include/{utils → postgres/utils}/expandedrecord.h +14 -4
  370. data/ext/pg_query/include/{utils → postgres/utils}/float.h +7 -6
  371. data/ext/pg_query/include/{utils → postgres/utils}/fmgroids.h +54 -1
  372. data/ext/pg_query/include/{utils → postgres/utils}/fmgrprotos.h +45 -3
  373. data/ext/pg_query/include/{utils → postgres/utils}/fmgrtab.h +1 -1
  374. data/ext/pg_query/include/{utils → postgres/utils}/guc.h +59 -86
  375. data/ext/pg_query/include/postgres/utils/guc_hooks.h +163 -0
  376. data/ext/pg_query/include/{utils → postgres/utils}/guc_tables.h +49 -3
  377. data/ext/pg_query/include/{utils → postgres/utils}/hsearch.h +1 -1
  378. data/ext/pg_query/include/{utils → postgres/utils}/inval.h +3 -3
  379. data/ext/pg_query/include/postgres/utils/logtape.h +77 -0
  380. data/ext/pg_query/include/{utils → postgres/utils}/lsyscache.h +5 -1
  381. data/ext/pg_query/include/{utils → postgres/utils}/memdebug.h +1 -1
  382. data/ext/pg_query/include/{utils → postgres/utils}/memutils.h +7 -51
  383. data/ext/pg_query/include/postgres/utils/memutils_internal.h +136 -0
  384. data/ext/pg_query/include/postgres/utils/memutils_memorychunk.h +237 -0
  385. data/ext/pg_query/include/{utils → postgres/utils}/numeric.h +20 -5
  386. data/ext/pg_query/include/{utils → postgres/utils}/palloc.h +9 -2
  387. data/ext/pg_query/include/{utils → postgres/utils}/partcache.h +3 -2
  388. data/ext/pg_query/include/{utils → postgres/utils}/pg_locale.h +22 -14
  389. data/ext/pg_query/include/{utils → postgres/utils}/pgstat_internal.h +37 -7
  390. data/ext/pg_query/include/{utils → postgres/utils}/plancache.h +1 -1
  391. data/ext/pg_query/include/{utils → postgres/utils}/portal.h +1 -1
  392. data/ext/pg_query/include/{utils → postgres/utils}/probes.h +6 -6
  393. data/ext/pg_query/include/postgres/utils/ps_status.h +47 -0
  394. data/ext/pg_query/include/{utils → postgres/utils}/queryenvironment.h +1 -1
  395. data/ext/pg_query/include/{utils → postgres/utils}/regproc.h +3 -3
  396. data/ext/pg_query/include/{utils → postgres/utils}/rel.h +60 -43
  397. data/ext/pg_query/include/{utils → postgres/utils}/relcache.h +13 -8
  398. data/ext/pg_query/include/{utils → postgres/utils}/reltrigger.h +1 -1
  399. data/ext/pg_query/include/{utils → postgres/utils}/resowner.h +1 -1
  400. data/ext/pg_query/include/{utils → postgres/utils}/ruleutils.h +6 -1
  401. data/ext/pg_query/include/{utils → postgres/utils}/sharedtuplestore.h +1 -1
  402. data/ext/pg_query/include/{utils → postgres/utils}/snapmgr.h +4 -2
  403. data/ext/pg_query/include/{utils → postgres/utils}/snapshot.h +1 -1
  404. data/ext/pg_query/include/{utils → postgres/utils}/sortsupport.h +2 -2
  405. data/ext/pg_query/include/{utils → postgres/utils}/syscache.h +4 -1
  406. data/ext/pg_query/include/{utils → postgres/utils}/timeout.h +1 -1
  407. data/ext/pg_query/include/{utils → postgres/utils}/timestamp.h +41 -11
  408. data/ext/pg_query/include/{utils → postgres/utils}/tuplesort.h +189 -35
  409. data/ext/pg_query/include/{utils → postgres/utils}/tuplestore.h +1 -1
  410. data/ext/pg_query/include/{utils → postgres/utils}/typcache.h +1 -1
  411. data/ext/pg_query/include/{utils → postgres/utils}/varlena.h +13 -1
  412. data/ext/pg_query/include/{utils → postgres/utils}/wait_event.h +9 -4
  413. data/ext/pg_query/include/{utils → postgres/utils}/xml.h +15 -5
  414. data/ext/pg_query/include/{postgres.h → postgres/varatt.h} +7 -457
  415. data/ext/pg_query/include/protobuf/pg_query.pb-c.h +6186 -5585
  416. data/ext/pg_query/include/protobuf/pg_query.pb.h +112443 -91222
  417. data/ext/pg_query/pg_query.c +10 -1
  418. data/ext/pg_query/pg_query.pb-c.c +19755 -17757
  419. data/ext/pg_query/pg_query_deparse.c +1 -10635
  420. data/ext/pg_query/pg_query_fingerprint.c +12 -8
  421. data/ext/pg_query/pg_query_fingerprint.h +1 -1
  422. data/ext/pg_query/pg_query_internal.h +1 -1
  423. data/ext/pg_query/pg_query_json_plpgsql.c +1 -0
  424. data/ext/pg_query/pg_query_normalize.c +1 -1
  425. data/ext/pg_query/pg_query_outfuncs_json.c +6 -0
  426. data/ext/pg_query/pg_query_outfuncs_protobuf.c +3 -2
  427. data/ext/pg_query/pg_query_parse.c +47 -5
  428. data/ext/pg_query/pg_query_parse_plpgsql.c +7 -5
  429. data/ext/pg_query/pg_query_readfuncs_protobuf.c +1 -0
  430. data/ext/pg_query/pg_query_ruby.c +5 -0
  431. data/ext/pg_query/pg_query_ruby_freebsd.sym +2 -0
  432. data/ext/pg_query/pg_query_scan.c +1 -1
  433. data/ext/pg_query/pg_query_split.c +3 -3
  434. data/ext/pg_query/postgres_deparse.c +11067 -0
  435. data/ext/pg_query/postgres_deparse.h +9 -0
  436. data/ext/pg_query/src_backend_catalog_namespace.c +7 -2
  437. data/ext/pg_query/src_backend_catalog_pg_proc.c +1 -1
  438. data/ext/pg_query/src_backend_commands_define.c +1 -1
  439. data/ext/pg_query/src_backend_nodes_bitmapset.c +11 -70
  440. data/ext/pg_query/src_backend_nodes_copyfuncs.c +96 -6202
  441. data/ext/pg_query/src_backend_nodes_equalfuncs.c +95 -4068
  442. data/ext/pg_query/src_backend_nodes_extensible.c +6 -29
  443. data/ext/pg_query/src_backend_nodes_list.c +14 -2
  444. data/ext/pg_query/src_backend_nodes_makefuncs.c +95 -1
  445. data/ext/pg_query/src_backend_nodes_nodeFuncs.c +283 -132
  446. data/ext/pg_query/src_backend_nodes_nodes.c +38 -0
  447. data/ext/pg_query/src_backend_nodes_value.c +1 -1
  448. data/ext/pg_query/src_backend_parser_gram.c +33208 -31806
  449. data/ext/pg_query/src_backend_parser_parser.c +28 -2
  450. data/ext/pg_query/src_backend_parser_scan.c +4318 -3329
  451. data/ext/pg_query/src_backend_parser_scansup.c +1 -1
  452. data/ext/pg_query/src_backend_storage_ipc_ipc.c +1 -1
  453. data/ext/pg_query/src_backend_tcop_postgres.c +66 -87
  454. data/ext/pg_query/src_backend_utils_activity_pgstat_database.c +1 -1
  455. data/ext/pg_query/src_backend_utils_adt_datum.c +5 -7
  456. data/ext/pg_query/src_backend_utils_adt_expandeddatum.c +1 -1
  457. data/ext/pg_query/src_backend_utils_adt_format_type.c +1 -1
  458. data/ext/pg_query/src_backend_utils_adt_numutils.c +489 -0
  459. data/ext/pg_query/src_backend_utils_adt_ruleutils.c +79 -5
  460. data/ext/pg_query/src_backend_utils_error_assert.c +4 -7
  461. data/ext/pg_query/src_backend_utils_error_elog.c +371 -249
  462. data/ext/pg_query/src_backend_utils_fmgr_fmgr.c +33 -1
  463. data/ext/pg_query/src_backend_utils_init_globals.c +6 -3
  464. data/ext/pg_query/src_backend_utils_mb_mbutils.c +21 -67
  465. data/ext/pg_query/src_backend_utils_misc_guc_tables.c +492 -0
  466. data/ext/pg_query/src_backend_utils_mmgr_alignedalloc.c +163 -0
  467. data/ext/pg_query/src_backend_utils_mmgr_aset.c +449 -312
  468. data/ext/pg_query/src_backend_utils_mmgr_generation.c +1039 -0
  469. data/ext/pg_query/src_backend_utils_mmgr_mcxt.c +398 -49
  470. data/ext/pg_query/src_backend_utils_mmgr_slab.c +1021 -0
  471. data/ext/pg_query/src_common_encnames.c +4 -1
  472. data/ext/pg_query/src_common_hashfn.c +1 -1
  473. data/ext/pg_query/src_common_keywords.c +1 -1
  474. data/ext/pg_query/src_common_kwlist_d.h +534 -510
  475. data/ext/pg_query/src_common_kwlookup.c +1 -1
  476. data/ext/pg_query/src_common_psprintf.c +1 -1
  477. data/ext/pg_query/src_common_stringinfo.c +4 -4
  478. data/ext/pg_query/src_common_wchar.c +9 -8
  479. data/ext/pg_query/src_pl_plpgsql_src_pl_comp.c +1 -1
  480. data/ext/pg_query/src_pl_plpgsql_src_pl_funcs.c +3 -1
  481. data/ext/pg_query/src_pl_plpgsql_src_pl_gram.c +661 -694
  482. data/ext/pg_query/src_pl_plpgsql_src_pl_handler.c +1 -1
  483. data/ext/pg_query/src_pl_plpgsql_src_pl_reserved_kwlist_d.h +1 -1
  484. data/ext/pg_query/src_pl_plpgsql_src_pl_scanner.c +1 -1
  485. data/ext/pg_query/src_pl_plpgsql_src_pl_unreserved_kwlist_d.h +48 -46
  486. data/ext/pg_query/src_port_pg_bitutils.c +79 -5
  487. data/ext/pg_query/src_port_pgstrcasecmp.c +29 -1
  488. data/ext/pg_query/src_port_snprintf.c +6 -10
  489. data/ext/pg_query/src_port_strerror.c +1 -1
  490. data/ext/pg_query/src_port_strlcpy.c +79 -0
  491. data/lib/pg_query/fingerprint.rb +2 -3
  492. data/lib/pg_query/node.rb +16 -11
  493. data/lib/pg_query/parse.rb +1 -1
  494. data/lib/pg_query/pg_query_pb.rb +166 -3191
  495. data/lib/pg_query/treewalker.rb +23 -5
  496. data/lib/pg_query/version.rb +1 -1
  497. metadata +432 -380
  498. data/ext/pg_query/guc-file.c +0 -0
  499. data/ext/pg_query/include/catalog/pg_parameter_acl.h +0 -60
  500. data/ext/pg_query/include/catalog/pg_parameter_acl_d.h +0 -34
  501. data/ext/pg_query/include/commands/variable.h +0 -38
  502. data/ext/pg_query/include/common/ip.h +0 -31
  503. data/ext/pg_query/include/getaddrinfo.h +0 -162
  504. data/ext/pg_query/include/kwlist_d.h +0 -1095
  505. data/ext/pg_query/include/parser/gram.h +0 -1101
  506. data/ext/pg_query/include/pg_config_os.h +0 -8
  507. data/ext/pg_query/include/portability/instr_time.h +0 -256
  508. data/ext/pg_query/include/postmaster/auxprocess.h +0 -20
  509. data/ext/pg_query/include/postmaster/fork_process.h +0 -17
  510. data/ext/pg_query/include/postmaster/pgarch.h +0 -73
  511. data/ext/pg_query/include/replication/logicalworker.h +0 -19
  512. data/ext/pg_query/include/storage/relfilenode.h +0 -99
  513. data/ext/pg_query/include/utils/dynahash.h +0 -20
  514. data/ext/pg_query/include/utils/pg_lsn.h +0 -29
  515. data/ext/pg_query/include/utils/pidfile.h +0 -56
  516. data/ext/pg_query/include/utils/ps_status.h +0 -25
  517. data/ext/pg_query/include/utils/rls.h +0 -50
  518. data/ext/pg_query/include/utils/tzparser.h +0 -39
  519. data/ext/pg_query/src_backend_postmaster_postmaster.c +0 -2201
  520. data/ext/pg_query/src_backend_storage_lmgr_s_lock.c +0 -371
  521. data/ext/pg_query/src_backend_utils_hash_dynahash.c +0 -1116
  522. data/ext/pg_query/src_backend_utils_misc_guc.c +0 -1993
  523. data/ext/pg_query/src_common_pg_prng.c +0 -152
  524. data/ext/pg_query/src_common_string.c +0 -92
  525. data/ext/pg_query/src_port_pgsleep.c +0 -69
  526. data/ext/pg_query/src_port_strnlen.c +0 -39
  527. /data/ext/pg_query/include/{access → postgres/access}/rmgr.h +0 -0
  528. /data/ext/pg_query/include/{pg_config_ext.h → postgres/pg_config_ext.h} +0 -0
  529. /data/ext/pg_query/include/{plerrcodes.h → postgres/plerrcodes.h} +0 -0
  530. /data/ext/pg_query/include/{storage → postgres/storage}/lwlocknames.h +0 -0
  531. /data/ext/pg_query/include/{utils → postgres/utils}/errcodes.h +0 -0
@@ -1,18 +1,18 @@
1
1
  /*--------------------------------------------------------------------
2
2
  * Symbols referenced in this file:
3
- * - AllocSetContextCreateInternal
4
- * - context_freelists
5
- * - AllocSetMethods
6
3
  * - AllocSetAlloc
7
4
  * - AllocSetFreeIndex
8
5
  * - AllocSetFree
9
6
  * - AllocSetRealloc
10
7
  * - AllocSetReset
11
8
  * - AllocSetDelete
9
+ * - context_freelists
10
+ * - AllocSetGetChunkContext
12
11
  * - AllocSetGetChunkSpace
13
12
  * - AllocSetIsEmpty
14
13
  * - AllocSetStats
15
14
  * - AllocSetCheck
15
+ * - AllocSetContextCreateInternal
16
16
  * - AllocSetDeleteFreeList
17
17
  *--------------------------------------------------------------------
18
18
  */
@@ -26,7 +26,7 @@
26
26
  * type.
27
27
  *
28
28
  *
29
- * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
29
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
30
30
  * Portions Copyright (c) 1994, Regents of the University of California
31
31
  *
32
32
  * IDENTIFICATION
@@ -68,6 +68,8 @@
68
68
  #include "port/pg_bitutils.h"
69
69
  #include "utils/memdebug.h"
70
70
  #include "utils/memutils.h"
71
+ #include "utils/memutils_memorychunk.h"
72
+ #include "utils/memutils_internal.h"
71
73
 
72
74
  /*--------------------
73
75
  * Chunk freelist k holds chunks of size 1 << (k + ALLOC_MINBITS),
@@ -85,7 +87,9 @@
85
87
  * CAUTION: ALLOC_MINBITS must be large enough so that
86
88
  * 1<<ALLOC_MINBITS is at least MAXALIGN,
87
89
  * or we may fail to align the smallest chunks adequately.
88
- * 8-byte alignment is enough on all currently known machines.
90
+ * 8-byte alignment is enough on all currently known machines. This 8-byte
91
+ * minimum also allows us to store a pointer to the next freelist item within
92
+ * the chunk of memory itself.
89
93
  *
90
94
  * With the current parameters, request sizes up to 8K are treated as chunks,
91
95
  * larger requests go into dedicated blocks. Change ALLOCSET_NUM_FREELISTS
@@ -117,10 +121,9 @@
117
121
  */
118
122
 
119
123
  #define ALLOC_BLOCKHDRSZ MAXALIGN(sizeof(AllocBlockData))
120
- #define ALLOC_CHUNKHDRSZ sizeof(struct AllocChunkData)
124
+ #define ALLOC_CHUNKHDRSZ sizeof(MemoryChunk)
121
125
 
122
126
  typedef struct AllocBlockData *AllocBlock; /* forward reference */
123
- typedef struct AllocChunkData *AllocChunk;
124
127
 
125
128
  /*
126
129
  * AllocPointer
@@ -128,6 +131,34 @@ typedef struct AllocChunkData *AllocChunk;
128
131
  */
129
132
  typedef void *AllocPointer;
130
133
 
134
+ /*
135
+ * AllocFreeListLink
136
+ * When pfreeing memory, if we maintain a freelist for the given chunk's
137
+ * size then we use a AllocFreeListLink to point to the current item in
138
+ * the AllocSetContext's freelist and then set the given freelist element
139
+ * to point to the chunk being freed.
140
+ */
141
+ typedef struct AllocFreeListLink
142
+ {
143
+ MemoryChunk *next;
144
+ } AllocFreeListLink;
145
+
146
+ /*
147
+ * Obtain a AllocFreeListLink for the given chunk. Allocation sizes are
148
+ * always at least sizeof(AllocFreeListLink), so we reuse the pointer's memory
149
+ * itself to store the freelist link.
150
+ */
151
+ #define GetFreeListLink(chkptr) \
152
+ (AllocFreeListLink *) ((char *) (chkptr) + ALLOC_CHUNKHDRSZ)
153
+
154
+ /* Validate a freelist index retrieved from a chunk header */
155
+ #define FreeListIdxIsValid(fidx) \
156
+ ((fidx) >= 0 && (fidx) < ALLOCSET_NUM_FREELISTS)
157
+
158
+ /* Determine the size of the chunk based on the freelist index */
159
+ #define GetChunkSizeFromFreeListIdx(fidx) \
160
+ ((((Size) 1) << ALLOC_MINBITS) << (fidx))
161
+
131
162
  /*
132
163
  * AllocSetContext is our standard implementation of MemoryContext.
133
164
  *
@@ -142,7 +173,7 @@ typedef struct AllocSetContext
142
173
  MemoryContextData header; /* Standard memory-context fields */
143
174
  /* Info about storage allocated in this context: */
144
175
  AllocBlock blocks; /* head of list of blocks in this set */
145
- AllocChunk freelist[ALLOCSET_NUM_FREELISTS]; /* free chunk lists */
176
+ MemoryChunk *freelist[ALLOCSET_NUM_FREELISTS]; /* free chunk lists */
146
177
  /* Allocation parameters for this context: */
147
178
  Size initBlockSize; /* initial block size */
148
179
  Size maxBlockSize; /* maximum block size */
@@ -158,8 +189,8 @@ typedef AllocSetContext *AllocSet;
158
189
  /*
159
190
  * AllocBlock
160
191
  * An AllocBlock is the unit of memory that is obtained by aset.c
161
- * from malloc(). It contains one or more AllocChunks, which are
162
- * the units requested by palloc() and freed by pfree(). AllocChunks
192
+ * from malloc(). It contains one or more MemoryChunks, which are
193
+ * the units requested by palloc() and freed by pfree(). MemoryChunks
163
194
  * cannot be returned to malloc() individually, instead they are put
164
195
  * on freelists by pfree() and re-used by the next palloc() that has
165
196
  * a matching request size.
@@ -176,50 +207,6 @@ typedef struct AllocBlockData
176
207
  char *endptr; /* end of space in this block */
177
208
  } AllocBlockData;
178
209
 
179
- /*
180
- * AllocChunk
181
- * The prefix of each piece of memory in an AllocBlock
182
- *
183
- * Note: to meet the memory context APIs, the payload area of the chunk must
184
- * be maxaligned, and the "aset" link must be immediately adjacent to the
185
- * payload area (cf. GetMemoryChunkContext). We simplify matters for this
186
- * module by requiring sizeof(AllocChunkData) to be maxaligned, and then
187
- * we can ensure things work by adding any required alignment padding before
188
- * the "aset" field. There is a static assertion below that the alignment
189
- * is done correctly.
190
- */
191
- typedef struct AllocChunkData
192
- {
193
- /* size is always the size of the usable space in the chunk */
194
- Size size;
195
- #ifdef MEMORY_CONTEXT_CHECKING
196
- /* when debugging memory usage, also store actual requested size */
197
- /* this is zero in a free chunk */
198
- Size requested_size;
199
-
200
- #define ALLOCCHUNK_RAWSIZE (SIZEOF_SIZE_T * 2 + SIZEOF_VOID_P)
201
- #else
202
- #define ALLOCCHUNK_RAWSIZE (SIZEOF_SIZE_T + SIZEOF_VOID_P)
203
- #endif /* MEMORY_CONTEXT_CHECKING */
204
-
205
- /* ensure proper alignment by adding padding if needed */
206
- #if (ALLOCCHUNK_RAWSIZE % MAXIMUM_ALIGNOF) != 0
207
- char padding[MAXIMUM_ALIGNOF - ALLOCCHUNK_RAWSIZE % MAXIMUM_ALIGNOF];
208
- #endif
209
-
210
- /* aset is the owning aset if allocated, or the freelist link if free */
211
- void *aset;
212
- /* there must not be any padding to reach a MAXALIGN boundary here! */
213
- } AllocChunkData;
214
-
215
- /*
216
- * Only the "aset" field should be accessed outside this module.
217
- * We keep the rest of an allocated chunk's header marked NOACCESS when using
218
- * valgrind. But note that chunk headers that are in a freelist are kept
219
- * accessible, for simplicity.
220
- */
221
- #define ALLOCCHUNK_PRIVATE_LEN offsetof(AllocChunkData, aset)
222
-
223
210
  /*
224
211
  * AllocPointerIsValid
225
212
  * True iff pointer is valid allocation pointer.
@@ -230,12 +217,23 @@ typedef struct AllocChunkData
230
217
  * AllocSetIsValid
231
218
  * True iff set is valid allocation set.
232
219
  */
233
- #define AllocSetIsValid(set) PointerIsValid(set)
220
+ #define AllocSetIsValid(set) \
221
+ (PointerIsValid(set) && IsA(set, AllocSetContext))
234
222
 
235
- #define AllocPointerGetChunk(ptr) \
236
- ((AllocChunk)(((char *)(ptr)) - ALLOC_CHUNKHDRSZ))
237
- #define AllocChunkGetPointer(chk) \
238
- ((AllocPointer)(((char *)(chk)) + ALLOC_CHUNKHDRSZ))
223
+ /*
224
+ * AllocBlockIsValid
225
+ * True iff block is valid block of allocation set.
226
+ */
227
+ #define AllocBlockIsValid(block) \
228
+ (PointerIsValid(block) && AllocSetIsValid((block)->aset))
229
+
230
+ /*
231
+ * We always store external chunks on a dedicated block. This makes fetching
232
+ * the block from an external chunk easy since it's always the first and only
233
+ * chunk on the block.
234
+ */
235
+ #define ExternalChunkGetBlock(chunk) \
236
+ (AllocBlock) ((char *) chunk - ALLOC_BLOCKHDRSZ)
239
237
 
240
238
  /*
241
239
  * Rather than repeatedly creating and deleting memory contexts, we keep some
@@ -280,42 +278,6 @@ static __thread AllocSetFreeList context_freelists[2] =
280
278
  };
281
279
 
282
280
 
283
- /*
284
- * These functions implement the MemoryContext API for AllocSet contexts.
285
- */
286
- static void *AllocSetAlloc(MemoryContext context, Size size);
287
- static void AllocSetFree(MemoryContext context, void *pointer);
288
- static void *AllocSetRealloc(MemoryContext context, void *pointer, Size size);
289
- static void AllocSetReset(MemoryContext context);
290
- static void AllocSetDelete(MemoryContext context);
291
- static Size AllocSetGetChunkSpace(MemoryContext context, void *pointer);
292
- static bool AllocSetIsEmpty(MemoryContext context);
293
- static void AllocSetStats(MemoryContext context,
294
- MemoryStatsPrintFunc printfunc, void *passthru,
295
- MemoryContextCounters *totals,
296
- bool print_to_stderr);
297
-
298
- #ifdef MEMORY_CONTEXT_CHECKING
299
- static void AllocSetCheck(MemoryContext context);
300
- #endif
301
-
302
- /*
303
- * This is the virtual function table for AllocSet contexts.
304
- */
305
- static const MemoryContextMethods AllocSetMethods = {
306
- AllocSetAlloc,
307
- AllocSetFree,
308
- AllocSetRealloc,
309
- AllocSetReset,
310
- AllocSetDelete,
311
- AllocSetGetChunkSpace,
312
- AllocSetIsEmpty,
313
- AllocSetStats
314
- #ifdef MEMORY_CONTEXT_CHECKING
315
- ,AllocSetCheck
316
- #endif
317
- };
318
-
319
281
 
320
282
  /* ----------
321
283
  * AllocSetFreeIndex -
@@ -339,7 +301,7 @@ AllocSetFreeIndex(Size size)
339
301
  * or equivalently
340
302
  * pg_leftmost_one_pos32(size - 1) - ALLOC_MINBITS + 1
341
303
  *
342
- * However, rather than just calling that function, we duplicate the
304
+ * However, for platforms without intrinsic support, we duplicate the
343
305
  * logic here, allowing an additional optimization. It's reasonable
344
306
  * to assume that ALLOC_CHUNK_LIMIT fits in 16 bits, so we can unroll
345
307
  * the byte-at-a-time loop in pg_leftmost_one_pos32 and just handle
@@ -349,14 +311,14 @@ AllocSetFreeIndex(Size size)
349
311
  * much trouble.
350
312
  *----------
351
313
  */
352
- #ifdef HAVE__BUILTIN_CLZ
353
- idx = 31 - __builtin_clz((uint32) size - 1) - ALLOC_MINBITS + 1;
314
+ #ifdef HAVE_BITSCAN_REVERSE
315
+ idx = pg_leftmost_one_pos32((uint32) size - 1) - ALLOC_MINBITS + 1;
354
316
  #else
355
317
  uint32 t,
356
318
  tsize;
357
319
 
358
320
  /* Statically assert that we only have a 16-bit input value. */
359
- StaticAssertStmt(ALLOC_CHUNK_LIMIT < (1 << 16),
321
+ StaticAssertDecl(ALLOC_CHUNK_LIMIT < (1 << 16),
360
322
  "ALLOC_CHUNK_LIMIT must be less than 64kB");
361
323
 
362
324
  tsize = size - 1;
@@ -407,18 +369,24 @@ AllocSetContextCreateInternal(MemoryContext parent,
407
369
  AllocSet set;
408
370
  AllocBlock block;
409
371
 
410
- /* Assert we padded AllocChunkData properly */
411
- StaticAssertStmt(ALLOC_CHUNKHDRSZ == MAXALIGN(ALLOC_CHUNKHDRSZ),
412
- "sizeof(AllocChunkData) is not maxaligned");
413
- StaticAssertStmt(offsetof(AllocChunkData, aset) + sizeof(MemoryContext) ==
414
- ALLOC_CHUNKHDRSZ,
415
- "padding calculation in AllocChunkData is wrong");
372
+ /* ensure MemoryChunk's size is properly maxaligned */
373
+ StaticAssertDecl(ALLOC_CHUNKHDRSZ == MAXALIGN(ALLOC_CHUNKHDRSZ),
374
+ "sizeof(MemoryChunk) is not maxaligned");
375
+ /* check we have enough space to store the freelist link */
376
+ StaticAssertDecl(sizeof(AllocFreeListLink) <= (1 << ALLOC_MINBITS),
377
+ "sizeof(AllocFreeListLink) larger than minimum allocation size");
416
378
 
417
379
  /*
418
380
  * First, validate allocation parameters. Once these were regular runtime
419
- * test and elog's, but in practice Asserts seem sufficient because nobody
420
- * varies their parameters at runtime. We somewhat arbitrarily enforce a
421
- * minimum 1K block size.
381
+ * tests and elog's, but in practice Asserts seem sufficient because
382
+ * nobody varies their parameters at runtime. We somewhat arbitrarily
383
+ * enforce a minimum 1K block size. We restrict the maximum block size to
384
+ * MEMORYCHUNK_MAX_BLOCKOFFSET as MemoryChunks are limited to this in
385
+ * regards to addressing the offset between the chunk and the block that
386
+ * the chunk is stored on. We would be unable to store the offset between
387
+ * the chunk and block for any chunks that were beyond
388
+ * MEMORYCHUNK_MAX_BLOCKOFFSET bytes into the block if the block was to be
389
+ * larger than this.
422
390
  */
423
391
  Assert(initBlockSize == MAXALIGN(initBlockSize) &&
424
392
  initBlockSize >= 1024);
@@ -429,6 +397,7 @@ AllocSetContextCreateInternal(MemoryContext parent,
429
397
  (minContextSize == MAXALIGN(minContextSize) &&
430
398
  minContextSize >= 1024 &&
431
399
  minContextSize <= maxBlockSize));
400
+ Assert(maxBlockSize <= MEMORYCHUNK_MAX_BLOCKOFFSET);
432
401
 
433
402
  /*
434
403
  * Check whether the parameters match either available freelist. We do
@@ -463,7 +432,7 @@ AllocSetContextCreateInternal(MemoryContext parent,
463
432
  /* Reinitialize its header, installing correct name and parent */
464
433
  MemoryContextCreate((MemoryContext) set,
465
434
  T_AllocSetContext,
466
- &AllocSetMethods,
435
+ MCTX_ASET_ID,
467
436
  parent,
468
437
  name);
469
438
 
@@ -537,15 +506,20 @@ AllocSetContextCreateInternal(MemoryContext parent,
537
506
  * requests that are all the maximum chunk size we will waste at most
538
507
  * 1/8th of the allocated space.
539
508
  *
540
- * We have to have allocChunkLimit a power of two, because the requested
541
- * and actually-allocated sizes of any chunk must be on the same side of
542
- * the limit, else we get confused about whether the chunk is "big".
543
- *
544
509
  * Also, allocChunkLimit must not exceed ALLOCSET_SEPARATE_THRESHOLD.
545
510
  */
546
511
  StaticAssertStmt(ALLOC_CHUNK_LIMIT == ALLOCSET_SEPARATE_THRESHOLD,
547
512
  "ALLOC_CHUNK_LIMIT != ALLOCSET_SEPARATE_THRESHOLD");
548
513
 
514
+ /*
515
+ * Determine the maximum size that a chunk can be before we allocate an
516
+ * entire AllocBlock dedicated for that chunk. We set the absolute limit
517
+ * of that size as ALLOC_CHUNK_LIMIT but we reduce it further so that we
518
+ * can fit about ALLOC_CHUNK_FRACTION chunks this size on a maximally
519
+ * sized block. (We opt to keep allocChunkLimit a power-of-2 value
520
+ * primarily for legacy reasons rather than calculating it so that exactly
521
+ * ALLOC_CHUNK_FRACTION chunks fit on a maximally sized block.)
522
+ */
549
523
  set->allocChunkLimit = ALLOC_CHUNK_LIMIT;
550
524
  while ((Size) (set->allocChunkLimit + ALLOC_CHUNKHDRSZ) >
551
525
  (Size) ((maxBlockSize - ALLOC_BLOCKHDRSZ) / ALLOC_CHUNK_FRACTION))
@@ -554,7 +528,7 @@ AllocSetContextCreateInternal(MemoryContext parent,
554
528
  /* Finally, do the type-independent part of context creation */
555
529
  MemoryContextCreate((MemoryContext) set,
556
530
  T_AllocSetContext,
557
- &AllocSetMethods,
531
+ MCTX_ASET_ID,
558
532
  parent,
559
533
  name);
560
534
 
@@ -575,21 +549,23 @@ AllocSetContextCreateInternal(MemoryContext parent,
575
549
  * thrash malloc() when a context is repeatedly reset after small allocations,
576
550
  * which is typical behavior for per-tuple contexts.
577
551
  */
578
- static void
552
+ void
579
553
  AllocSetReset(MemoryContext context)
580
554
  {
581
555
  AllocSet set = (AllocSet) context;
582
556
  AllocBlock block;
583
- Size keepersize PG_USED_FOR_ASSERTS_ONLY
584
- = set->keeper->endptr - ((char *) set);
557
+ Size keepersize PG_USED_FOR_ASSERTS_ONLY;
585
558
 
586
- AssertArg(AllocSetIsValid(set));
559
+ Assert(AllocSetIsValid(set));
587
560
 
588
561
  #ifdef MEMORY_CONTEXT_CHECKING
589
562
  /* Check for corruption and leaks before freeing */
590
563
  AllocSetCheck(context);
591
564
  #endif
592
565
 
566
+ /* Remember keeper block size for Assert below */
567
+ keepersize = set->keeper->endptr - ((char *) set);
568
+
593
569
  /* Clear chunk freelists */
594
570
  MemSetAligned(set->freelist, 0, sizeof(set->freelist));
595
571
 
@@ -643,21 +619,23 @@ AllocSetReset(MemoryContext context)
643
619
  *
644
620
  * Unlike AllocSetReset, this *must* free all resources of the set.
645
621
  */
646
- static void
622
+ void
647
623
  AllocSetDelete(MemoryContext context)
648
624
  {
649
625
  AllocSet set = (AllocSet) context;
650
626
  AllocBlock block = set->blocks;
651
- Size keepersize PG_USED_FOR_ASSERTS_ONLY
652
- = set->keeper->endptr - ((char *) set);
627
+ Size keepersize PG_USED_FOR_ASSERTS_ONLY;
653
628
 
654
- AssertArg(AllocSetIsValid(set));
629
+ Assert(AllocSetIsValid(set));
655
630
 
656
631
  #ifdef MEMORY_CONTEXT_CHECKING
657
632
  /* Check for corruption and leaks before freeing */
658
633
  AllocSetCheck(context);
659
634
  #endif
660
635
 
636
+ /* Remember keeper block size for Assert below */
637
+ keepersize = set->keeper->endptr - ((char *) set);
638
+
661
639
  /*
662
640
  * If the context is a candidate for a freelist, put it into that freelist
663
641
  * instead of destroying it.
@@ -737,17 +715,17 @@ AllocSetDelete(MemoryContext context)
737
715
  * is marked, as mcxt.c will set it to UNDEFINED. In some paths we will
738
716
  * return space that is marked NOACCESS - AllocSetRealloc has to beware!
739
717
  */
740
- static void *
718
+ void *
741
719
  AllocSetAlloc(MemoryContext context, Size size)
742
720
  {
743
721
  AllocSet set = (AllocSet) context;
744
722
  AllocBlock block;
745
- AllocChunk chunk;
723
+ MemoryChunk *chunk;
746
724
  int fidx;
747
725
  Size chunk_size;
748
726
  Size blksize;
749
727
 
750
- AssertArg(AllocSetIsValid(set));
728
+ Assert(AllocSetIsValid(set));
751
729
 
752
730
  /*
753
731
  * If requested size exceeds maximum for chunks, allocate an entire block
@@ -755,7 +733,13 @@ AllocSetAlloc(MemoryContext context, Size size)
755
733
  */
756
734
  if (size > set->allocChunkLimit)
757
735
  {
736
+ #ifdef MEMORY_CONTEXT_CHECKING
737
+ /* ensure there's always space for the sentinel byte */
738
+ chunk_size = MAXALIGN(size + 1);
739
+ #else
758
740
  chunk_size = MAXALIGN(size);
741
+ #endif
742
+
759
743
  blksize = chunk_size + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ;
760
744
  block = (AllocBlock) malloc(blksize);
761
745
  if (block == NULL)
@@ -766,18 +750,20 @@ AllocSetAlloc(MemoryContext context, Size size)
766
750
  block->aset = set;
767
751
  block->freeptr = block->endptr = ((char *) block) + blksize;
768
752
 
769
- chunk = (AllocChunk) (((char *) block) + ALLOC_BLOCKHDRSZ);
770
- chunk->aset = set;
771
- chunk->size = chunk_size;
753
+ chunk = (MemoryChunk *) (((char *) block) + ALLOC_BLOCKHDRSZ);
754
+
755
+ /* mark the MemoryChunk as externally managed */
756
+ MemoryChunkSetHdrMaskExternal(chunk, MCTX_ASET_ID);
757
+
772
758
  #ifdef MEMORY_CONTEXT_CHECKING
773
759
  chunk->requested_size = size;
774
760
  /* set mark to catch clobber of "unused" space */
775
- if (size < chunk_size)
776
- set_sentinel(AllocChunkGetPointer(chunk), size);
761
+ Assert(size < chunk_size);
762
+ set_sentinel(MemoryChunkGetPointer(chunk), size);
777
763
  #endif
778
764
  #ifdef RANDOMIZE_ALLOCATED_MEMORY
779
765
  /* fill the allocated space with junk */
780
- randomize_mem((char *) AllocChunkGetPointer(chunk), size);
766
+ randomize_mem((char *) MemoryChunkGetPointer(chunk), size);
781
767
  #endif
782
768
 
783
769
  /*
@@ -800,13 +786,13 @@ AllocSetAlloc(MemoryContext context, Size size)
800
786
  }
801
787
 
802
788
  /* Ensure any padding bytes are marked NOACCESS. */
803
- VALGRIND_MAKE_MEM_NOACCESS((char *) AllocChunkGetPointer(chunk) + size,
789
+ VALGRIND_MAKE_MEM_NOACCESS((char *) MemoryChunkGetPointer(chunk) + size,
804
790
  chunk_size - size);
805
791
 
806
- /* Disallow external access to private part of chunk header. */
807
- VALGRIND_MAKE_MEM_NOACCESS(chunk, ALLOCCHUNK_PRIVATE_LEN);
792
+ /* Disallow access to the chunk header. */
793
+ VALGRIND_MAKE_MEM_NOACCESS(chunk, ALLOC_CHUNKHDRSZ);
808
794
 
809
- return AllocChunkGetPointer(chunk);
795
+ return MemoryChunkGetPointer(chunk);
810
796
  }
811
797
 
812
798
  /*
@@ -814,42 +800,54 @@ AllocSetAlloc(MemoryContext context, Size size)
814
800
  * corresponding free list to see if there is a free chunk we could reuse.
815
801
  * If one is found, remove it from the free list, make it again a member
816
802
  * of the alloc set and return its data address.
803
+ *
804
+ * Note that we don't attempt to ensure there's space for the sentinel
805
+ * byte here. We expect a large proportion of allocations to be for sizes
806
+ * which are already a power of 2. If we were to always make space for a
807
+ * sentinel byte in MEMORY_CONTEXT_CHECKING builds, then we'd end up
808
+ * doubling the memory requirements for such allocations.
817
809
  */
818
810
  fidx = AllocSetFreeIndex(size);
819
811
  chunk = set->freelist[fidx];
820
812
  if (chunk != NULL)
821
813
  {
822
- Assert(chunk->size >= size);
814
+ AllocFreeListLink *link = GetFreeListLink(chunk);
815
+
816
+ /* Allow access to the chunk header. */
817
+ VALGRIND_MAKE_MEM_DEFINED(chunk, ALLOC_CHUNKHDRSZ);
823
818
 
824
- set->freelist[fidx] = (AllocChunk) chunk->aset;
819
+ Assert(fidx == MemoryChunkGetValue(chunk));
825
820
 
826
- chunk->aset = (void *) set;
821
+ /* pop this chunk off the freelist */
822
+ VALGRIND_MAKE_MEM_DEFINED(link, sizeof(AllocFreeListLink));
823
+ set->freelist[fidx] = link->next;
824
+ VALGRIND_MAKE_MEM_NOACCESS(link, sizeof(AllocFreeListLink));
827
825
 
828
826
  #ifdef MEMORY_CONTEXT_CHECKING
829
827
  chunk->requested_size = size;
830
828
  /* set mark to catch clobber of "unused" space */
831
- if (size < chunk->size)
832
- set_sentinel(AllocChunkGetPointer(chunk), size);
829
+ if (size < GetChunkSizeFromFreeListIdx(fidx))
830
+ set_sentinel(MemoryChunkGetPointer(chunk), size);
833
831
  #endif
834
832
  #ifdef RANDOMIZE_ALLOCATED_MEMORY
835
833
  /* fill the allocated space with junk */
836
- randomize_mem((char *) AllocChunkGetPointer(chunk), size);
834
+ randomize_mem((char *) MemoryChunkGetPointer(chunk), size);
837
835
  #endif
838
836
 
839
837
  /* Ensure any padding bytes are marked NOACCESS. */
840
- VALGRIND_MAKE_MEM_NOACCESS((char *) AllocChunkGetPointer(chunk) + size,
841
- chunk->size - size);
838
+ VALGRIND_MAKE_MEM_NOACCESS((char *) MemoryChunkGetPointer(chunk) + size,
839
+ GetChunkSizeFromFreeListIdx(fidx) - size);
842
840
 
843
- /* Disallow external access to private part of chunk header. */
844
- VALGRIND_MAKE_MEM_NOACCESS(chunk, ALLOCCHUNK_PRIVATE_LEN);
841
+ /* Disallow access to the chunk header. */
842
+ VALGRIND_MAKE_MEM_NOACCESS(chunk, ALLOC_CHUNKHDRSZ);
845
843
 
846
- return AllocChunkGetPointer(chunk);
844
+ return MemoryChunkGetPointer(chunk);
847
845
  }
848
846
 
849
847
  /*
850
848
  * Choose the actual chunk size to allocate.
851
849
  */
852
- chunk_size = (1 << ALLOC_MINBITS) << fidx;
850
+ chunk_size = GetChunkSizeFromFreeListIdx(fidx);
853
851
  Assert(chunk_size >= size);
854
852
 
855
853
  /*
@@ -876,6 +874,7 @@ AllocSetAlloc(MemoryContext context, Size size)
876
874
  */
877
875
  while (availspace >= ((1 << ALLOC_MINBITS) + ALLOC_CHUNKHDRSZ))
878
876
  {
877
+ AllocFreeListLink *link;
879
878
  Size availchunk = availspace - ALLOC_CHUNKHDRSZ;
880
879
  int a_fidx = AllocSetFreeIndex(availchunk);
881
880
 
@@ -884,29 +883,34 @@ AllocSetAlloc(MemoryContext context, Size size)
884
883
  * freelist than the one we need to put this chunk on. The
885
884
  * exception is when availchunk is exactly a power of 2.
886
885
  */
887
- if (availchunk != ((Size) 1 << (a_fidx + ALLOC_MINBITS)))
886
+ if (availchunk != GetChunkSizeFromFreeListIdx(a_fidx))
888
887
  {
889
888
  a_fidx--;
890
889
  Assert(a_fidx >= 0);
891
- availchunk = ((Size) 1 << (a_fidx + ALLOC_MINBITS));
890
+ availchunk = GetChunkSizeFromFreeListIdx(a_fidx);
892
891
  }
893
892
 
894
- chunk = (AllocChunk) (block->freeptr);
893
+ chunk = (MemoryChunk *) (block->freeptr);
895
894
 
896
895
  /* Prepare to initialize the chunk header. */
897
896
  VALGRIND_MAKE_MEM_UNDEFINED(chunk, ALLOC_CHUNKHDRSZ);
898
-
899
897
  block->freeptr += (availchunk + ALLOC_CHUNKHDRSZ);
900
898
  availspace -= (availchunk + ALLOC_CHUNKHDRSZ);
901
899
 
902
- chunk->size = availchunk;
900
+ /* store the freelist index in the value field */
901
+ MemoryChunkSetHdrMask(chunk, block, a_fidx, MCTX_ASET_ID);
903
902
  #ifdef MEMORY_CONTEXT_CHECKING
904
- chunk->requested_size = 0; /* mark it free */
903
+ chunk->requested_size = InvalidAllocSize; /* mark it free */
905
904
  #endif
906
- chunk->aset = (void *) set->freelist[a_fidx];
905
+ /* push this chunk onto the free list */
906
+ link = GetFreeListLink(chunk);
907
+
908
+ VALGRIND_MAKE_MEM_DEFINED(link, sizeof(AllocFreeListLink));
909
+ link->next = set->freelist[a_fidx];
910
+ VALGRIND_MAKE_MEM_NOACCESS(link, sizeof(AllocFreeListLink));
911
+
907
912
  set->freelist[a_fidx] = chunk;
908
913
  }
909
-
910
914
  /* Mark that we need to create a new block */
911
915
  block = NULL;
912
916
  }
@@ -974,7 +978,7 @@ AllocSetAlloc(MemoryContext context, Size size)
974
978
  /*
975
979
  * OK, do the allocation
976
980
  */
977
- chunk = (AllocChunk) (block->freeptr);
981
+ chunk = (MemoryChunk *) (block->freeptr);
978
982
 
979
983
  /* Prepare to initialize the chunk header. */
980
984
  VALGRIND_MAKE_MEM_UNDEFINED(chunk, ALLOC_CHUNKHDRSZ);
@@ -982,69 +986,67 @@ AllocSetAlloc(MemoryContext context, Size size)
982
986
  block->freeptr += (chunk_size + ALLOC_CHUNKHDRSZ);
983
987
  Assert(block->freeptr <= block->endptr);
984
988
 
985
- chunk->aset = (void *) set;
986
- chunk->size = chunk_size;
989
+ /* store the free list index in the value field */
990
+ MemoryChunkSetHdrMask(chunk, block, fidx, MCTX_ASET_ID);
991
+
987
992
  #ifdef MEMORY_CONTEXT_CHECKING
988
993
  chunk->requested_size = size;
989
994
  /* set mark to catch clobber of "unused" space */
990
- if (size < chunk->size)
991
- set_sentinel(AllocChunkGetPointer(chunk), size);
995
+ if (size < chunk_size)
996
+ set_sentinel(MemoryChunkGetPointer(chunk), size);
992
997
  #endif
993
998
  #ifdef RANDOMIZE_ALLOCATED_MEMORY
994
999
  /* fill the allocated space with junk */
995
- randomize_mem((char *) AllocChunkGetPointer(chunk), size);
1000
+ randomize_mem((char *) MemoryChunkGetPointer(chunk), size);
996
1001
  #endif
997
1002
 
998
1003
  /* Ensure any padding bytes are marked NOACCESS. */
999
- VALGRIND_MAKE_MEM_NOACCESS((char *) AllocChunkGetPointer(chunk) + size,
1004
+ VALGRIND_MAKE_MEM_NOACCESS((char *) MemoryChunkGetPointer(chunk) + size,
1000
1005
  chunk_size - size);
1001
1006
 
1002
- /* Disallow external access to private part of chunk header. */
1003
- VALGRIND_MAKE_MEM_NOACCESS(chunk, ALLOCCHUNK_PRIVATE_LEN);
1007
+ /* Disallow access to the chunk header. */
1008
+ VALGRIND_MAKE_MEM_NOACCESS(chunk, ALLOC_CHUNKHDRSZ);
1004
1009
 
1005
- return AllocChunkGetPointer(chunk);
1010
+ return MemoryChunkGetPointer(chunk);
1006
1011
  }
1007
1012
 
1008
1013
  /*
1009
1014
  * AllocSetFree
1010
1015
  * Frees allocated memory; memory is removed from the set.
1011
1016
  */
1012
- static void
1013
- AllocSetFree(MemoryContext context, void *pointer)
1017
+ void
1018
+ AllocSetFree(void *pointer)
1014
1019
  {
1015
- AllocSet set = (AllocSet) context;
1016
- AllocChunk chunk = AllocPointerGetChunk(pointer);
1017
-
1018
- /* Allow access to private part of chunk header. */
1019
- VALGRIND_MAKE_MEM_DEFINED(chunk, ALLOCCHUNK_PRIVATE_LEN);
1020
+ AllocSet set;
1021
+ MemoryChunk *chunk = PointerGetMemoryChunk(pointer);
1020
1022
 
1021
- #ifdef MEMORY_CONTEXT_CHECKING
1022
- /* Test for someone scribbling on unused space in chunk */
1023
- if (chunk->requested_size < chunk->size)
1024
- if (!sentinel_ok(pointer, chunk->requested_size))
1025
- elog(WARNING, "detected write past chunk end in %s %p",
1026
- set->header.name, chunk);
1027
- #endif
1023
+ /* Allow access to the chunk header. */
1024
+ VALGRIND_MAKE_MEM_DEFINED(chunk, ALLOC_CHUNKHDRSZ);
1028
1025
 
1029
- if (chunk->size > set->allocChunkLimit)
1026
+ if (MemoryChunkIsExternal(chunk))
1030
1027
  {
1031
- /*
1032
- * Big chunks are certain to have been allocated as single-chunk
1033
- * blocks. Just unlink that block and return it to malloc().
1034
- */
1035
- AllocBlock block = (AllocBlock) (((char *) chunk) - ALLOC_BLOCKHDRSZ);
1028
+ /* Release single-chunk block. */
1029
+ AllocBlock block = ExternalChunkGetBlock(chunk);
1036
1030
 
1037
1031
  /*
1038
- * Try to verify that we have a sane block pointer: it should
1039
- * reference the correct aset, and freeptr and endptr should point
1040
- * just past the chunk.
1032
+ * Try to verify that we have a sane block pointer: the block header
1033
+ * should reference an aset and the freeptr should match the endptr.
1041
1034
  */
1042
- if (block->aset != set ||
1043
- block->freeptr != block->endptr ||
1044
- block->freeptr != ((char *) block) +
1045
- (chunk->size + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ))
1035
+ if (!AllocBlockIsValid(block) || block->freeptr != block->endptr)
1046
1036
  elog(ERROR, "could not find block containing chunk %p", chunk);
1047
1037
 
1038
+ set = block->aset;
1039
+
1040
+ #ifdef MEMORY_CONTEXT_CHECKING
1041
+ {
1042
+ /* Test for someone scribbling on unused space in chunk */
1043
+ Assert(chunk->requested_size < (block->endptr - (char *) pointer));
1044
+ if (!sentinel_ok(pointer, chunk->requested_size))
1045
+ elog(WARNING, "detected write past chunk end in %s %p",
1046
+ set->header.name, chunk);
1047
+ }
1048
+ #endif
1049
+
1048
1050
  /* OK, remove block from aset's list and free it */
1049
1051
  if (block->prev)
1050
1052
  block->prev->next = block->next;
@@ -1053,7 +1055,7 @@ AllocSetFree(MemoryContext context, void *pointer)
1053
1055
  if (block->next)
1054
1056
  block->next->prev = block->prev;
1055
1057
 
1056
- context->mem_allocated -= block->endptr - ((char *) block);
1058
+ set->header.mem_allocated -= block->endptr - ((char *) block);
1057
1059
 
1058
1060
  #ifdef CLOBBER_FREED_MEMORY
1059
1061
  wipe_mem(block, block->freeptr - ((char *) block));
@@ -1062,20 +1064,48 @@ AllocSetFree(MemoryContext context, void *pointer)
1062
1064
  }
1063
1065
  else
1064
1066
  {
1065
- /* Normal case, put the chunk into appropriate freelist */
1066
- int fidx = AllocSetFreeIndex(chunk->size);
1067
+ AllocBlock block = MemoryChunkGetBlock(chunk);
1068
+ int fidx;
1069
+ AllocFreeListLink *link;
1070
+
1071
+ /*
1072
+ * In this path, for speed reasons we just Assert that the referenced
1073
+ * block is good. We can also Assert that the value field is sane.
1074
+ * Future field experience may show that these Asserts had better
1075
+ * become regular runtime test-and-elog checks.
1076
+ */
1077
+ Assert(AllocBlockIsValid(block));
1078
+ set = block->aset;
1067
1079
 
1068
- chunk->aset = (void *) set->freelist[fidx];
1080
+ fidx = MemoryChunkGetValue(chunk);
1081
+ Assert(FreeListIdxIsValid(fidx));
1082
+ link = GetFreeListLink(chunk);
1083
+
1084
+ #ifdef MEMORY_CONTEXT_CHECKING
1085
+ /* Test for someone scribbling on unused space in chunk */
1086
+ if (chunk->requested_size < GetChunkSizeFromFreeListIdx(fidx))
1087
+ if (!sentinel_ok(pointer, chunk->requested_size))
1088
+ elog(WARNING, "detected write past chunk end in %s %p",
1089
+ set->header.name, chunk);
1090
+ #endif
1069
1091
 
1070
1092
  #ifdef CLOBBER_FREED_MEMORY
1071
- wipe_mem(pointer, chunk->size);
1093
+ wipe_mem(pointer, GetChunkSizeFromFreeListIdx(fidx));
1072
1094
  #endif
1095
+ /* push this chunk onto the top of the free list */
1096
+ VALGRIND_MAKE_MEM_DEFINED(link, sizeof(AllocFreeListLink));
1097
+ link->next = set->freelist[fidx];
1098
+ VALGRIND_MAKE_MEM_NOACCESS(link, sizeof(AllocFreeListLink));
1099
+ set->freelist[fidx] = chunk;
1073
1100
 
1074
1101
  #ifdef MEMORY_CONTEXT_CHECKING
1075
- /* Reset requested_size to 0 in chunks that are on freelist */
1076
- chunk->requested_size = 0;
1102
+
1103
+ /*
1104
+ * Reset requested_size to InvalidAllocSize in chunks that are on free
1105
+ * list.
1106
+ */
1107
+ chunk->requested_size = InvalidAllocSize;
1077
1108
  #endif
1078
- set->freelist[fidx] = chunk;
1079
1109
  }
1080
1110
  }
1081
1111
 
@@ -1091,57 +1121,56 @@ AllocSetFree(MemoryContext context, void *pointer)
1091
1121
  * (In principle, we could use VALGRIND_GET_VBITS() to rediscover the old
1092
1122
  * request size.)
1093
1123
  */
1094
- static void *
1095
- AllocSetRealloc(MemoryContext context, void *pointer, Size size)
1124
+ void *
1125
+ AllocSetRealloc(void *pointer, Size size)
1096
1126
  {
1097
- AllocSet set = (AllocSet) context;
1098
- AllocChunk chunk = AllocPointerGetChunk(pointer);
1099
- Size oldsize;
1100
-
1101
- /* Allow access to private part of chunk header. */
1102
- VALGRIND_MAKE_MEM_DEFINED(chunk, ALLOCCHUNK_PRIVATE_LEN);
1103
-
1104
- oldsize = chunk->size;
1127
+ AllocBlock block;
1128
+ AllocSet set;
1129
+ MemoryChunk *chunk = PointerGetMemoryChunk(pointer);
1130
+ Size oldchksize;
1131
+ int fidx;
1105
1132
 
1106
- #ifdef MEMORY_CONTEXT_CHECKING
1107
- /* Test for someone scribbling on unused space in chunk */
1108
- if (chunk->requested_size < oldsize)
1109
- if (!sentinel_ok(pointer, chunk->requested_size))
1110
- elog(WARNING, "detected write past chunk end in %s %p",
1111
- set->header.name, chunk);
1112
- #endif
1133
+ /* Allow access to the chunk header. */
1134
+ VALGRIND_MAKE_MEM_DEFINED(chunk, ALLOC_CHUNKHDRSZ);
1113
1135
 
1114
- if (oldsize > set->allocChunkLimit)
1136
+ if (MemoryChunkIsExternal(chunk))
1115
1137
  {
1116
1138
  /*
1117
1139
  * The chunk must have been allocated as a single-chunk block. Use
1118
1140
  * realloc() to make the containing block bigger, or smaller, with
1119
1141
  * minimum space wastage.
1120
1142
  */
1121
- AllocBlock block = (AllocBlock) (((char *) chunk) - ALLOC_BLOCKHDRSZ);
1122
1143
  Size chksize;
1123
1144
  Size blksize;
1124
1145
  Size oldblksize;
1125
1146
 
1147
+ block = ExternalChunkGetBlock(chunk);
1148
+
1126
1149
  /*
1127
- * Try to verify that we have a sane block pointer: it should
1128
- * reference the correct aset, and freeptr and endptr should point
1129
- * just past the chunk.
1150
+ * Try to verify that we have a sane block pointer: the block header
1151
+ * should reference an aset and the freeptr should match the endptr.
1130
1152
  */
1131
- if (block->aset != set ||
1132
- block->freeptr != block->endptr ||
1133
- block->freeptr != ((char *) block) +
1134
- (oldsize + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ))
1153
+ if (!AllocBlockIsValid(block) || block->freeptr != block->endptr)
1135
1154
  elog(ERROR, "could not find block containing chunk %p", chunk);
1136
1155
 
1137
- /*
1138
- * Even if the new request is less than set->allocChunkLimit, we stick
1139
- * with the single-chunk block approach. Therefore we need
1140
- * chunk->size to be bigger than set->allocChunkLimit, so we don't get
1141
- * confused about the chunk's status in future calls.
1142
- */
1143
- chksize = Max(size, set->allocChunkLimit + 1);
1144
- chksize = MAXALIGN(chksize);
1156
+ set = block->aset;
1157
+
1158
+ oldchksize = block->endptr - (char *) pointer;
1159
+
1160
+ #ifdef MEMORY_CONTEXT_CHECKING
1161
+ /* Test for someone scribbling on unused space in chunk */
1162
+ Assert(chunk->requested_size < oldchksize);
1163
+ if (!sentinel_ok(pointer, chunk->requested_size))
1164
+ elog(WARNING, "detected write past chunk end in %s %p",
1165
+ set->header.name, chunk);
1166
+ #endif
1167
+
1168
+ #ifdef MEMORY_CONTEXT_CHECKING
1169
+ /* ensure there's always space for the sentinel byte */
1170
+ chksize = MAXALIGN(size + 1);
1171
+ #else
1172
+ chksize = MAXALIGN(size);
1173
+ #endif
1145
1174
 
1146
1175
  /* Do the realloc */
1147
1176
  blksize = chksize + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ;
@@ -1150,77 +1179,109 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
1150
1179
  block = (AllocBlock) realloc(block, blksize);
1151
1180
  if (block == NULL)
1152
1181
  {
1153
- /* Disallow external access to private part of chunk header. */
1154
- VALGRIND_MAKE_MEM_NOACCESS(chunk, ALLOCCHUNK_PRIVATE_LEN);
1182
+ /* Disallow access to the chunk header. */
1183
+ VALGRIND_MAKE_MEM_NOACCESS(chunk, ALLOC_CHUNKHDRSZ);
1155
1184
  return NULL;
1156
1185
  }
1157
1186
 
1158
1187
  /* updated separately, not to underflow when (oldblksize > blksize) */
1159
- context->mem_allocated -= oldblksize;
1160
- context->mem_allocated += blksize;
1188
+ set->header.mem_allocated -= oldblksize;
1189
+ set->header.mem_allocated += blksize;
1161
1190
 
1162
1191
  block->freeptr = block->endptr = ((char *) block) + blksize;
1163
1192
 
1164
1193
  /* Update pointers since block has likely been moved */
1165
- chunk = (AllocChunk) (((char *) block) + ALLOC_BLOCKHDRSZ);
1166
- pointer = AllocChunkGetPointer(chunk);
1194
+ chunk = (MemoryChunk *) (((char *) block) + ALLOC_BLOCKHDRSZ);
1195
+ pointer = MemoryChunkGetPointer(chunk);
1167
1196
  if (block->prev)
1168
1197
  block->prev->next = block;
1169
1198
  else
1170
1199
  set->blocks = block;
1171
1200
  if (block->next)
1172
1201
  block->next->prev = block;
1173
- chunk->size = chksize;
1174
1202
 
1175
1203
  #ifdef MEMORY_CONTEXT_CHECKING
1176
1204
  #ifdef RANDOMIZE_ALLOCATED_MEMORY
1177
- /* We can only fill the extra space if we know the prior request */
1205
+
1206
+ /*
1207
+ * We can only randomize the extra space if we know the prior request.
1208
+ * When using Valgrind, randomize_mem() also marks memory UNDEFINED.
1209
+ */
1178
1210
  if (size > chunk->requested_size)
1179
1211
  randomize_mem((char *) pointer + chunk->requested_size,
1180
1212
  size - chunk->requested_size);
1181
- #endif
1213
+ #else
1182
1214
 
1183
1215
  /*
1184
- * realloc() (or randomize_mem()) will have left any newly-allocated
1185
- * part UNDEFINED, but we may need to adjust trailing bytes from the
1186
- * old allocation.
1216
+ * If this is an increase, realloc() will have marked any
1217
+ * newly-allocated part (from oldchksize to chksize) UNDEFINED, but we
1218
+ * also need to adjust trailing bytes from the old allocation (from
1219
+ * chunk->requested_size to oldchksize) as they are marked NOACCESS.
1220
+ * Make sure not to mark too many bytes in case chunk->requested_size
1221
+ * < size < oldchksize.
1187
1222
  */
1188
1223
  #ifdef USE_VALGRIND
1189
- if (oldsize > chunk->requested_size)
1224
+ if (Min(size, oldchksize) > chunk->requested_size)
1190
1225
  VALGRIND_MAKE_MEM_UNDEFINED((char *) pointer + chunk->requested_size,
1191
- oldsize - chunk->requested_size);
1226
+ Min(size, oldchksize) - chunk->requested_size);
1227
+ #endif
1192
1228
  #endif
1193
1229
 
1194
1230
  chunk->requested_size = size;
1195
-
1196
1231
  /* set mark to catch clobber of "unused" space */
1197
- if (size < chunk->size)
1198
- set_sentinel(pointer, size);
1232
+ Assert(size < chksize);
1233
+ set_sentinel(pointer, size);
1199
1234
  #else /* !MEMORY_CONTEXT_CHECKING */
1200
1235
 
1201
1236
  /*
1202
- * We don't know how much of the old chunk size was the actual
1203
- * allocation; it could have been as small as one byte. We have to be
1204
- * conservative and just mark the entire old portion DEFINED.
1237
+ * We may need to adjust marking of bytes from the old allocation as
1238
+ * some of them may be marked NOACCESS. We don't know how much of the
1239
+ * old chunk size was the requested size; it could have been as small
1240
+ * as one byte. We have to be conservative and just mark the entire
1241
+ * old portion DEFINED. Make sure not to mark memory beyond the new
1242
+ * allocation in case it's smaller than the old one.
1205
1243
  */
1206
- VALGRIND_MAKE_MEM_DEFINED(pointer, oldsize);
1244
+ VALGRIND_MAKE_MEM_DEFINED(pointer, Min(size, oldchksize));
1207
1245
  #endif
1208
1246
 
1209
1247
  /* Ensure any padding bytes are marked NOACCESS. */
1210
1248
  VALGRIND_MAKE_MEM_NOACCESS((char *) pointer + size, chksize - size);
1211
1249
 
1212
- /* Disallow external access to private part of chunk header. */
1213
- VALGRIND_MAKE_MEM_NOACCESS(chunk, ALLOCCHUNK_PRIVATE_LEN);
1250
+ /* Disallow access to the chunk header . */
1251
+ VALGRIND_MAKE_MEM_NOACCESS(chunk, ALLOC_CHUNKHDRSZ);
1214
1252
 
1215
1253
  return pointer;
1216
1254
  }
1217
1255
 
1256
+ block = MemoryChunkGetBlock(chunk);
1257
+
1258
+ /*
1259
+ * In this path, for speed reasons we just Assert that the referenced
1260
+ * block is good. We can also Assert that the value field is sane. Future
1261
+ * field experience may show that these Asserts had better become regular
1262
+ * runtime test-and-elog checks.
1263
+ */
1264
+ Assert(AllocBlockIsValid(block));
1265
+ set = block->aset;
1266
+
1267
+ fidx = MemoryChunkGetValue(chunk);
1268
+ Assert(FreeListIdxIsValid(fidx));
1269
+ oldchksize = GetChunkSizeFromFreeListIdx(fidx);
1270
+
1271
+ #ifdef MEMORY_CONTEXT_CHECKING
1272
+ /* Test for someone scribbling on unused space in chunk */
1273
+ if (chunk->requested_size < oldchksize)
1274
+ if (!sentinel_ok(pointer, chunk->requested_size))
1275
+ elog(WARNING, "detected write past chunk end in %s %p",
1276
+ set->header.name, chunk);
1277
+ #endif
1278
+
1218
1279
  /*
1219
1280
  * Chunk sizes are aligned to power of 2 in AllocSetAlloc(). Maybe the
1220
1281
  * allocated area already is >= the new size. (In particular, we will
1221
1282
  * fall out here if the requested size is a decrease.)
1222
1283
  */
1223
- else if (oldsize >= size)
1284
+ if (oldchksize >= size)
1224
1285
  {
1225
1286
  #ifdef MEMORY_CONTEXT_CHECKING
1226
1287
  Size oldrequest = chunk->requested_size;
@@ -1243,10 +1304,10 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
1243
1304
  size - oldrequest);
1244
1305
  else
1245
1306
  VALGRIND_MAKE_MEM_NOACCESS((char *) pointer + size,
1246
- oldsize - size);
1307
+ oldchksize - size);
1247
1308
 
1248
1309
  /* set mark to catch clobber of "unused" space */
1249
- if (size < oldsize)
1310
+ if (size < oldchksize)
1250
1311
  set_sentinel(pointer, size);
1251
1312
  #else /* !MEMORY_CONTEXT_CHECKING */
1252
1313
 
@@ -1255,12 +1316,12 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
1255
1316
  * the old request or shrinking it, so we conservatively mark the
1256
1317
  * entire new allocation DEFINED.
1257
1318
  */
1258
- VALGRIND_MAKE_MEM_NOACCESS(pointer, oldsize);
1319
+ VALGRIND_MAKE_MEM_NOACCESS(pointer, oldchksize);
1259
1320
  VALGRIND_MAKE_MEM_DEFINED(pointer, size);
1260
1321
  #endif
1261
1322
 
1262
- /* Disallow external access to private part of chunk header. */
1263
- VALGRIND_MAKE_MEM_NOACCESS(chunk, ALLOCCHUNK_PRIVATE_LEN);
1323
+ /* Disallow access to the chunk header. */
1324
+ VALGRIND_MAKE_MEM_NOACCESS(chunk, ALLOC_CHUNKHDRSZ);
1264
1325
 
1265
1326
  return pointer;
1266
1327
  }
@@ -1278,6 +1339,7 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
1278
1339
  * memory indefinitely. See pgsql-hackers archives for 2007-08-11.)
1279
1340
  */
1280
1341
  AllocPointer newPointer;
1342
+ Size oldsize;
1281
1343
 
1282
1344
  /* allocate new chunk */
1283
1345
  newPointer = AllocSetAlloc((MemoryContext) set, size);
@@ -1285,8 +1347,8 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
1285
1347
  /* leave immediately if request was not completed */
1286
1348
  if (newPointer == NULL)
1287
1349
  {
1288
- /* Disallow external access to private part of chunk header. */
1289
- VALGRIND_MAKE_MEM_NOACCESS(chunk, ALLOCCHUNK_PRIVATE_LEN);
1350
+ /* Disallow access to the chunk header. */
1351
+ VALGRIND_MAKE_MEM_NOACCESS(chunk, ALLOC_CHUNKHDRSZ);
1290
1352
  return NULL;
1291
1353
  }
1292
1354
 
@@ -1302,6 +1364,7 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
1302
1364
  #ifdef MEMORY_CONTEXT_CHECKING
1303
1365
  oldsize = chunk->requested_size;
1304
1366
  #else
1367
+ oldsize = oldchksize;
1305
1368
  VALGRIND_MAKE_MEM_DEFINED(pointer, oldsize);
1306
1369
  #endif
1307
1370
 
@@ -1309,36 +1372,84 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
1309
1372
  memcpy(newPointer, pointer, oldsize);
1310
1373
 
1311
1374
  /* free old chunk */
1312
- AllocSetFree((MemoryContext) set, pointer);
1375
+ AllocSetFree(pointer);
1313
1376
 
1314
1377
  return newPointer;
1315
1378
  }
1316
1379
  }
1317
1380
 
1381
+ /*
1382
+ * AllocSetGetChunkContext
1383
+ * Return the MemoryContext that 'pointer' belongs to.
1384
+ */
1385
+ MemoryContext
1386
+ AllocSetGetChunkContext(void *pointer)
1387
+ {
1388
+ MemoryChunk *chunk = PointerGetMemoryChunk(pointer);
1389
+ AllocBlock block;
1390
+ AllocSet set;
1391
+
1392
+ /* Allow access to the chunk header. */
1393
+ VALGRIND_MAKE_MEM_DEFINED(chunk, ALLOC_CHUNKHDRSZ);
1394
+
1395
+ if (MemoryChunkIsExternal(chunk))
1396
+ block = ExternalChunkGetBlock(chunk);
1397
+ else
1398
+ block = (AllocBlock) MemoryChunkGetBlock(chunk);
1399
+
1400
+ /* Disallow access to the chunk header. */
1401
+ VALGRIND_MAKE_MEM_NOACCESS(chunk, ALLOC_CHUNKHDRSZ);
1402
+
1403
+ Assert(AllocBlockIsValid(block));
1404
+ set = block->aset;
1405
+
1406
+ return &set->header;
1407
+ }
1408
+
1318
1409
  /*
1319
1410
  * AllocSetGetChunkSpace
1320
1411
  * Given a currently-allocated chunk, determine the total space
1321
1412
  * it occupies (including all memory-allocation overhead).
1322
1413
  */
1323
- static Size
1324
- AllocSetGetChunkSpace(MemoryContext context, void *pointer)
1414
+ Size
1415
+ AllocSetGetChunkSpace(void *pointer)
1325
1416
  {
1326
- AllocChunk chunk = AllocPointerGetChunk(pointer);
1327
- Size result;
1417
+ MemoryChunk *chunk = PointerGetMemoryChunk(pointer);
1418
+ int fidx;
1419
+
1420
+ /* Allow access to the chunk header. */
1421
+ VALGRIND_MAKE_MEM_DEFINED(chunk, ALLOC_CHUNKHDRSZ);
1422
+
1423
+ if (MemoryChunkIsExternal(chunk))
1424
+ {
1425
+ AllocBlock block = ExternalChunkGetBlock(chunk);
1328
1426
 
1329
- VALGRIND_MAKE_MEM_DEFINED(chunk, ALLOCCHUNK_PRIVATE_LEN);
1330
- result = chunk->size + ALLOC_CHUNKHDRSZ;
1331
- VALGRIND_MAKE_MEM_NOACCESS(chunk, ALLOCCHUNK_PRIVATE_LEN);
1332
- return result;
1427
+ /* Disallow access to the chunk header. */
1428
+ VALGRIND_MAKE_MEM_NOACCESS(chunk, ALLOC_CHUNKHDRSZ);
1429
+
1430
+ Assert(AllocBlockIsValid(block));
1431
+
1432
+ return block->endptr - (char *) chunk;
1433
+ }
1434
+
1435
+ fidx = MemoryChunkGetValue(chunk);
1436
+ Assert(FreeListIdxIsValid(fidx));
1437
+
1438
+ /* Disallow access to the chunk header. */
1439
+ VALGRIND_MAKE_MEM_NOACCESS(chunk, ALLOC_CHUNKHDRSZ);
1440
+
1441
+ return GetChunkSizeFromFreeListIdx(fidx) + ALLOC_CHUNKHDRSZ;
1333
1442
  }
1334
1443
 
1335
1444
  /*
1336
1445
  * AllocSetIsEmpty
1337
1446
  * Is an allocset empty of any allocated space?
1338
1447
  */
1339
- static bool
1448
+ bool
1340
1449
  AllocSetIsEmpty(MemoryContext context)
1341
1450
  {
1451
+ Assert(AllocSetIsValid(context));
1452
+
1342
1453
  /*
1343
1454
  * For now, we say "empty" only if the context is new or just reset. We
1344
1455
  * could examine the freelists to determine if all space has been freed,
@@ -1359,7 +1470,7 @@ AllocSetIsEmpty(MemoryContext context)
1359
1470
  * totals: if not NULL, add stats about this context into *totals.
1360
1471
  * print_to_stderr: print stats to stderr if true, elog otherwise.
1361
1472
  */
1362
- static void
1473
+ void
1363
1474
  AllocSetStats(MemoryContext context,
1364
1475
  MemoryStatsPrintFunc printfunc, void *passthru,
1365
1476
  MemoryContextCounters *totals, bool print_to_stderr)
@@ -1372,6 +1483,8 @@ AllocSetStats(MemoryContext context,
1372
1483
  AllocBlock block;
1373
1484
  int fidx;
1374
1485
 
1486
+ Assert(AllocSetIsValid(set));
1487
+
1375
1488
  /* Include context header in totalspace */
1376
1489
  totalspace = MAXALIGN(sizeof(AllocSetContext));
1377
1490
 
@@ -1383,13 +1496,24 @@ AllocSetStats(MemoryContext context,
1383
1496
  }
1384
1497
  for (fidx = 0; fidx < ALLOCSET_NUM_FREELISTS; fidx++)
1385
1498
  {
1386
- AllocChunk chunk;
1499
+ Size chksz = GetChunkSizeFromFreeListIdx(fidx);
1500
+ MemoryChunk *chunk = set->freelist[fidx];
1387
1501
 
1388
- for (chunk = set->freelist[fidx]; chunk != NULL;
1389
- chunk = (AllocChunk) chunk->aset)
1502
+ while (chunk != NULL)
1390
1503
  {
1504
+ AllocFreeListLink *link = GetFreeListLink(chunk);
1505
+
1506
+ /* Allow access to the chunk header. */
1507
+ VALGRIND_MAKE_MEM_DEFINED(chunk, ALLOC_CHUNKHDRSZ);
1508
+ Assert(MemoryChunkGetValue(chunk) == fidx);
1509
+ VALGRIND_MAKE_MEM_NOACCESS(chunk, ALLOC_CHUNKHDRSZ);
1510
+
1391
1511
  freechunks++;
1392
- freespace += chunk->size + ALLOC_CHUNKHDRSZ;
1512
+ freespace += chksz + ALLOC_CHUNKHDRSZ;
1513
+
1514
+ VALGRIND_MAKE_MEM_DEFINED(link, sizeof(AllocFreeListLink));
1515
+ chunk = link->next;
1516
+ VALGRIND_MAKE_MEM_NOACCESS(link, sizeof(AllocFreeListLink));
1393
1517
  }
1394
1518
  }
1395
1519
 
@@ -1424,7 +1548,7 @@ AllocSetStats(MemoryContext context,
1424
1548
  * find yourself in an infinite loop when trouble occurs, because this
1425
1549
  * routine will be entered again when elog cleanup tries to release memory!
1426
1550
  */
1427
- static void
1551
+ void
1428
1552
  AllocSetCheck(MemoryContext context)
1429
1553
  {
1430
1554
  AllocSet set = (AllocSet) context;
@@ -1441,6 +1565,7 @@ AllocSetCheck(MemoryContext context)
1441
1565
  long blk_used = block->freeptr - bpoz;
1442
1566
  long blk_data = 0;
1443
1567
  long nchunks = 0;
1568
+ bool has_external_chunk = false;
1444
1569
 
1445
1570
  if (set->keeper == block)
1446
1571
  total_allocated += block->endptr - ((char *) set);
@@ -1472,56 +1597,64 @@ AllocSetCheck(MemoryContext context)
1472
1597
  */
1473
1598
  while (bpoz < block->freeptr)
1474
1599
  {
1475
- AllocChunk chunk = (AllocChunk) bpoz;
1600
+ MemoryChunk *chunk = (MemoryChunk *) bpoz;
1476
1601
  Size chsize,
1477
1602
  dsize;
1478
1603
 
1479
- /* Allow access to private part of chunk header. */
1480
- VALGRIND_MAKE_MEM_DEFINED(chunk, ALLOCCHUNK_PRIVATE_LEN);
1604
+ /* Allow access to the chunk header. */
1605
+ VALGRIND_MAKE_MEM_DEFINED(chunk, ALLOC_CHUNKHDRSZ);
1606
+
1607
+ if (MemoryChunkIsExternal(chunk))
1608
+ {
1609
+ chsize = block->endptr - (char *) MemoryChunkGetPointer(chunk); /* aligned chunk size */
1610
+ has_external_chunk = true;
1611
+
1612
+ /* make sure this chunk consumes the entire block */
1613
+ if (chsize + ALLOC_CHUNKHDRSZ != blk_used)
1614
+ elog(WARNING, "problem in alloc set %s: bad single-chunk %p in block %p",
1615
+ name, chunk, block);
1616
+ }
1617
+ else
1618
+ {
1619
+ int fidx = MemoryChunkGetValue(chunk);
1620
+
1621
+ if (!FreeListIdxIsValid(fidx))
1622
+ elog(WARNING, "problem in alloc set %s: bad chunk size for chunk %p in block %p",
1623
+ name, chunk, block);
1624
+
1625
+ chsize = GetChunkSizeFromFreeListIdx(fidx); /* aligned chunk size */
1481
1626
 
1482
- chsize = chunk->size; /* aligned chunk size */
1627
+ /*
1628
+ * Check the stored block offset correctly references this
1629
+ * block.
1630
+ */
1631
+ if (block != MemoryChunkGetBlock(chunk))
1632
+ elog(WARNING, "problem in alloc set %s: bad block offset for chunk %p in block %p",
1633
+ name, chunk, block);
1634
+ }
1483
1635
  dsize = chunk->requested_size; /* real data */
1484
1636
 
1485
- /*
1486
- * Check chunk size
1487
- */
1488
- if (dsize > chsize)
1637
+ /* an allocated chunk's requested size must be <= the chsize */
1638
+ if (dsize != InvalidAllocSize && dsize > chsize)
1489
1639
  elog(WARNING, "problem in alloc set %s: req size > alloc size for chunk %p in block %p",
1490
1640
  name, chunk, block);
1641
+
1642
+ /* chsize must not be smaller than the first freelist's size */
1491
1643
  if (chsize < (1 << ALLOC_MINBITS))
1492
1644
  elog(WARNING, "problem in alloc set %s: bad size %zu for chunk %p in block %p",
1493
1645
  name, chsize, chunk, block);
1494
1646
 
1495
- /* single-chunk block? */
1496
- if (chsize > set->allocChunkLimit &&
1497
- chsize + ALLOC_CHUNKHDRSZ != blk_used)
1498
- elog(WARNING, "problem in alloc set %s: bad single-chunk %p in block %p",
1499
- name, chunk, block);
1500
-
1501
- /*
1502
- * If chunk is allocated, check for correct aset pointer. (If it's
1503
- * free, the aset is the freelist pointer, which we can't check as
1504
- * easily...) Note this is an incomplete test, since palloc(0)
1505
- * produces an allocated chunk with requested_size == 0.
1506
- */
1507
- if (dsize > 0 && chunk->aset != (void *) set)
1508
- elog(WARNING, "problem in alloc set %s: bogus aset link in block %p, chunk %p",
1509
- name, block, chunk);
1510
-
1511
1647
  /*
1512
1648
  * Check for overwrite of padding space in an allocated chunk.
1513
1649
  */
1514
- if (chunk->aset == (void *) set && dsize < chsize &&
1650
+ if (dsize != InvalidAllocSize && dsize < chsize &&
1515
1651
  !sentinel_ok(chunk, ALLOC_CHUNKHDRSZ + dsize))
1516
1652
  elog(WARNING, "problem in alloc set %s: detected write past chunk end in block %p, chunk %p",
1517
1653
  name, block, chunk);
1518
1654
 
1519
- /*
1520
- * If chunk is allocated, disallow external access to private part
1521
- * of chunk header.
1522
- */
1523
- if (chunk->aset == (void *) set)
1524
- VALGRIND_MAKE_MEM_NOACCESS(chunk, ALLOCCHUNK_PRIVATE_LEN);
1655
+ /* if chunk is allocated, disallow access to the chunk header */
1656
+ if (dsize != InvalidAllocSize)
1657
+ VALGRIND_MAKE_MEM_NOACCESS(chunk, ALLOC_CHUNKHDRSZ);
1525
1658
 
1526
1659
  blk_data += chsize;
1527
1660
  nchunks++;
@@ -1532,6 +1665,10 @@ AllocSetCheck(MemoryContext context)
1532
1665
  if ((blk_data + (nchunks * ALLOC_CHUNKHDRSZ)) != blk_used)
1533
1666
  elog(WARNING, "problem in alloc set %s: found inconsistent memory block %p",
1534
1667
  name, block);
1668
+
1669
+ if (has_external_chunk && nchunks > 1)
1670
+ elog(WARNING, "problem in alloc set %s: external chunk on non-dedicated block %p",
1671
+ name, block);
1535
1672
  }
1536
1673
 
1537
1674
  Assert(total_allocated == context->mem_allocated);