pg_query 5.1.0 → 6.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +30 -0
- data/README.md +1 -1
- data/Rakefile +4 -4
- data/ext/pg_query/ext_symbols_freebsd.sym +1 -0
- data/ext/pg_query/ext_symbols_freebsd_with_ruby_abi_version.sym +2 -0
- data/ext/pg_query/ext_symbols_openbsd.sym +1 -0
- data/ext/pg_query/ext_symbols_openbsd_with_ruby_abi_version.sym +2 -0
- data/ext/pg_query/ext_symbols_with_ruby_abi_version.sym +2 -0
- data/ext/pg_query/extconf.rb +20 -6
- data/ext/pg_query/include/pg_query.h +4 -3
- data/ext/pg_query/include/pg_query_enum_defs.c +424 -154
- data/ext/pg_query/include/pg_query_fingerprint_conds.c +68 -4
- data/ext/pg_query/include/pg_query_fingerprint_defs.c +2952 -1845
- data/ext/pg_query/include/pg_query_outfuncs_conds.c +51 -3
- data/ext/pg_query/include/pg_query_outfuncs_defs.c +210 -23
- data/ext/pg_query/include/pg_query_readfuncs_conds.c +17 -1
- data/ext/pg_query/include/pg_query_readfuncs_defs.c +271 -52
- data/ext/pg_query/include/postgres/access/amapi.h +14 -3
- data/ext/pg_query/include/postgres/access/attmap.h +1 -1
- data/ext/pg_query/include/postgres/access/attnum.h +1 -1
- data/ext/pg_query/include/postgres/access/brin_internal.h +116 -0
- data/ext/pg_query/include/postgres/access/brin_tuple.h +112 -0
- data/ext/pg_query/include/postgres/access/clog.h +2 -3
- data/ext/pg_query/include/postgres/access/commit_ts.h +2 -3
- data/ext/pg_query/include/postgres/access/detoast.h +1 -1
- data/ext/pg_query/include/postgres/access/genam.h +17 -4
- data/ext/pg_query/include/postgres/access/gin.h +1 -1
- data/ext/pg_query/include/postgres/access/htup.h +1 -1
- data/ext/pg_query/include/postgres/access/htup_details.h +11 -11
- data/ext/pg_query/include/postgres/access/itup.h +3 -3
- data/ext/pg_query/include/postgres/access/parallel.h +1 -2
- data/ext/pg_query/include/postgres/access/printtup.h +1 -1
- data/ext/pg_query/include/postgres/access/relation.h +1 -1
- data/ext/pg_query/include/postgres/access/relscan.h +1 -1
- data/ext/pg_query/include/postgres/access/rmgrlist.h +1 -1
- data/ext/pg_query/include/postgres/access/sdir.h +1 -1
- data/ext/pg_query/include/postgres/access/skey.h +1 -1
- data/ext/pg_query/include/postgres/access/slru.h +218 -0
- data/ext/pg_query/include/postgres/access/stratnum.h +1 -1
- data/ext/pg_query/include/postgres/access/sysattr.h +1 -1
- data/ext/pg_query/include/postgres/access/table.h +1 -1
- data/ext/pg_query/include/postgres/access/tableam.h +35 -25
- data/ext/pg_query/include/postgres/access/tidstore.h +50 -0
- data/ext/pg_query/include/postgres/access/toast_compression.h +2 -2
- data/ext/pg_query/include/postgres/access/transam.h +50 -7
- data/ext/pg_query/include/postgres/access/tsmapi.h +1 -1
- data/ext/pg_query/include/postgres/access/tupconvert.h +1 -1
- data/ext/pg_query/include/postgres/access/tupdesc.h +5 -5
- data/ext/pg_query/include/postgres/access/tupmacs.h +1 -1
- data/ext/pg_query/include/postgres/access/twophase.h +2 -2
- data/ext/pg_query/include/postgres/access/xact.h +5 -5
- data/ext/pg_query/include/postgres/access/xlog.h +20 -12
- data/ext/pg_query/include/postgres/access/xlog_internal.h +4 -3
- data/ext/pg_query/include/postgres/access/xlogbackup.h +3 -1
- data/ext/pg_query/include/postgres/access/xlogdefs.h +5 -5
- data/ext/pg_query/include/postgres/access/xlogprefetcher.h +2 -2
- data/ext/pg_query/include/postgres/access/xlogreader.h +2 -2
- data/ext/pg_query/include/postgres/access/xlogrecord.h +3 -3
- data/ext/pg_query/include/postgres/access/xlogrecovery.h +4 -4
- data/ext/pg_query/include/postgres/archive/archive_module.h +9 -1
- data/ext/pg_query/include/postgres/c.h +32 -37
- data/ext/pg_query/include/postgres/catalog/catalog.h +3 -1
- data/ext/pg_query/include/postgres/catalog/catversion.h +2 -2
- data/ext/pg_query/include/postgres/catalog/dependency.h +17 -59
- data/ext/pg_query/include/postgres/catalog/genbki.h +12 -6
- data/ext/pg_query/include/postgres/catalog/index.h +22 -18
- data/ext/pg_query/include/postgres/catalog/indexing.h +1 -1
- data/ext/pg_query/include/postgres/catalog/namespace.h +18 -19
- data/ext/pg_query/include/postgres/catalog/objectaccess.h +2 -2
- data/ext/pg_query/include/postgres/catalog/objectaddress.h +5 -1
- data/ext/pg_query/include/postgres/catalog/pg_aggregate.h +4 -2
- data/ext/pg_query/include/postgres/catalog/pg_aggregate_d.h +1 -1
- data/ext/pg_query/include/postgres/catalog/pg_am.h +6 -3
- data/ext/pg_query/include/postgres/catalog/pg_am_d.h +1 -1
- data/ext/pg_query/include/postgres/catalog/pg_attribute.h +31 -14
- data/ext/pg_query/include/postgres/catalog/pg_attribute_d.h +3 -3
- data/ext/pg_query/include/postgres/catalog/pg_authid.h +6 -3
- data/ext/pg_query/include/postgres/catalog/pg_authid_d.h +2 -1
- data/ext/pg_query/include/postgres/catalog/pg_class.h +10 -5
- data/ext/pg_query/include/postgres/catalog/pg_class_d.h +4 -2
- data/ext/pg_query/include/postgres/catalog/pg_collation.h +11 -5
- data/ext/pg_query/include/postgres/catalog/pg_collation_d.h +5 -2
- data/ext/pg_query/include/postgres/catalog/pg_constraint.h +15 -10
- data/ext/pg_query/include/postgres/catalog/pg_constraint_d.h +2 -1
- data/ext/pg_query/include/postgres/catalog/pg_control.h +5 -3
- data/ext/pg_query/include/postgres/catalog/pg_conversion.h +8 -4
- data/ext/pg_query/include/postgres/catalog/pg_conversion_d.h +1 -1
- data/ext/pg_query/include/postgres/catalog/pg_database.h +9 -4
- data/ext/pg_query/include/postgres/catalog/pg_database_d.h +13 -12
- data/ext/pg_query/include/postgres/catalog/pg_depend.h +3 -3
- data/ext/pg_query/include/postgres/catalog/pg_depend_d.h +1 -1
- data/ext/pg_query/include/postgres/catalog/pg_event_trigger.h +6 -3
- data/ext/pg_query/include/postgres/catalog/pg_event_trigger_d.h +1 -1
- data/ext/pg_query/include/postgres/catalog/pg_index.h +5 -3
- data/ext/pg_query/include/postgres/catalog/pg_index_d.h +1 -1
- data/ext/pg_query/include/postgres/catalog/pg_language.h +6 -3
- data/ext/pg_query/include/postgres/catalog/pg_language_d.h +1 -1
- data/ext/pg_query/include/postgres/catalog/pg_namespace.h +6 -3
- data/ext/pg_query/include/postgres/catalog/pg_namespace_d.h +1 -1
- data/ext/pg_query/include/postgres/catalog/pg_opclass.h +6 -3
- data/ext/pg_query/include/postgres/catalog/pg_opclass_d.h +1 -1
- data/ext/pg_query/include/postgres/catalog/pg_operator.h +20 -3
- data/ext/pg_query/include/postgres/catalog/pg_operator_d.h +1 -1
- data/ext/pg_query/include/postgres/catalog/pg_opfamily.h +6 -3
- data/ext/pg_query/include/postgres/catalog/pg_opfamily_d.h +1 -1
- data/ext/pg_query/include/postgres/catalog/pg_partitioned_table.h +4 -2
- data/ext/pg_query/include/postgres/catalog/pg_partitioned_table_d.h +1 -1
- data/ext/pg_query/include/postgres/catalog/pg_proc.h +6 -3
- data/ext/pg_query/include/postgres/catalog/pg_proc_d.h +1 -1
- data/ext/pg_query/include/postgres/catalog/pg_publication.h +6 -3
- data/ext/pg_query/include/postgres/catalog/pg_publication_d.h +1 -1
- data/ext/pg_query/include/postgres/catalog/pg_replication_origin.h +6 -3
- data/ext/pg_query/include/postgres/catalog/pg_replication_origin_d.h +1 -1
- data/ext/pg_query/include/postgres/catalog/pg_statistic.h +10 -4
- data/ext/pg_query/include/postgres/catalog/pg_statistic_d.h +7 -3
- data/ext/pg_query/include/postgres/catalog/pg_statistic_ext.h +10 -7
- data/ext/pg_query/include/postgres/catalog/pg_statistic_ext_d.h +3 -3
- data/ext/pg_query/include/postgres/catalog/pg_transform.h +6 -3
- data/ext/pg_query/include/postgres/catalog/pg_transform_d.h +1 -1
- data/ext/pg_query/include/postgres/catalog/pg_trigger.h +4 -4
- data/ext/pg_query/include/postgres/catalog/pg_trigger_d.h +1 -1
- data/ext/pg_query/include/postgres/catalog/pg_ts_config.h +6 -3
- data/ext/pg_query/include/postgres/catalog/pg_ts_config_d.h +1 -1
- data/ext/pg_query/include/postgres/catalog/pg_ts_dict.h +6 -3
- data/ext/pg_query/include/postgres/catalog/pg_ts_dict_d.h +1 -1
- data/ext/pg_query/include/postgres/catalog/pg_ts_parser.h +6 -3
- data/ext/pg_query/include/postgres/catalog/pg_ts_parser_d.h +1 -1
- data/ext/pg_query/include/postgres/catalog/pg_ts_template.h +6 -3
- data/ext/pg_query/include/postgres/catalog/pg_ts_template_d.h +1 -1
- data/ext/pg_query/include/postgres/catalog/pg_type.h +6 -3
- data/ext/pg_query/include/postgres/catalog/pg_type_d.h +1 -1
- data/ext/pg_query/include/postgres/catalog/storage.h +1 -1
- data/ext/pg_query/include/postgres/catalog/syscache_ids.h +104 -0
- data/ext/pg_query/include/postgres/commands/async.h +2 -6
- data/ext/pg_query/include/postgres/commands/dbcommands.h +1 -1
- data/ext/pg_query/include/postgres/commands/defrem.h +6 -6
- data/ext/pg_query/include/postgres/commands/event_trigger.h +11 -2
- data/ext/pg_query/include/postgres/commands/explain.h +19 -3
- data/ext/pg_query/include/postgres/commands/prepare.h +1 -1
- data/ext/pg_query/include/postgres/commands/tablespace.h +1 -1
- data/ext/pg_query/include/postgres/commands/trigger.h +1 -1
- data/ext/pg_query/include/postgres/commands/vacuum.h +28 -26
- data/ext/pg_query/include/postgres/common/cryptohash.h +2 -2
- data/ext/pg_query/include/postgres/common/file_perm.h +1 -1
- data/ext/pg_query/include/postgres/common/file_utils.h +65 -0
- data/ext/pg_query/include/postgres/common/hashfn.h +16 -1
- data/ext/pg_query/include/postgres/common/hashfn_unstable.h +407 -0
- data/ext/pg_query/include/postgres/common/int.h +79 -4
- data/ext/pg_query/include/postgres/common/keywords.h +1 -1
- data/ext/pg_query/include/postgres/common/kwlookup.h +1 -1
- data/ext/pg_query/include/postgres/common/pg_prng.h +2 -1
- data/ext/pg_query/include/postgres/common/relpath.h +4 -4
- data/ext/pg_query/include/postgres/common/scram-common.h +1 -1
- data/ext/pg_query/include/postgres/common/sha2.h +1 -1
- data/ext/pg_query/include/postgres/common/string.h +1 -1
- data/ext/pg_query/include/postgres/common/unicode_east_asian_fw_table.h +2 -3
- data/ext/pg_query/include/postgres/copyfuncs.funcs.c +278 -30
- data/ext/pg_query/include/postgres/copyfuncs.switch.c +55 -4
- data/ext/pg_query/include/postgres/datatype/timestamp.h +29 -3
- data/ext/pg_query/include/postgres/equalfuncs.funcs.c +239 -26
- data/ext/pg_query/include/postgres/equalfuncs.switch.c +55 -4
- data/ext/pg_query/include/postgres/executor/execdesc.h +2 -2
- data/ext/pg_query/include/postgres/executor/executor.h +6 -5
- data/ext/pg_query/include/postgres/executor/functions.h +2 -1
- data/ext/pg_query/include/postgres/executor/instrument.h +5 -3
- data/ext/pg_query/include/postgres/executor/spi.h +2 -8
- data/ext/pg_query/include/postgres/executor/tablefunc.h +1 -1
- data/ext/pg_query/include/postgres/executor/tuptable.h +31 -2
- data/ext/pg_query/include/postgres/fmgr.h +2 -2
- data/ext/pg_query/include/postgres/foreign/fdwapi.h +1 -1
- data/ext/pg_query/include/postgres/funcapi.h +2 -2
- data/ext/pg_query/include/postgres/gram.h +871 -830
- data/ext/pg_query/include/postgres/gramparse.h +1 -1
- data/ext/pg_query/include/postgres/jit/jit.h +4 -3
- data/ext/pg_query/include/postgres/kwlist_d.h +511 -466
- data/ext/pg_query/include/postgres/lib/dshash.h +25 -10
- data/ext/pg_query/include/postgres/lib/ilist.h +1 -1
- data/ext/pg_query/include/postgres/lib/pairingheap.h +1 -1
- data/ext/pg_query/include/postgres/lib/simplehash.h +40 -18
- data/ext/pg_query/include/postgres/lib/sort_template.h +14 -1
- data/ext/pg_query/include/postgres/lib/stringinfo.h +93 -11
- data/ext/pg_query/include/postgres/libpq/auth.h +1 -1
- data/ext/pg_query/include/postgres/libpq/crypt.h +2 -2
- data/ext/pg_query/include/postgres/libpq/hba.h +4 -4
- data/ext/pg_query/include/postgres/libpq/libpq-be.h +35 -28
- data/ext/pg_query/include/postgres/libpq/libpq.h +6 -7
- data/ext/pg_query/include/postgres/libpq/pqcomm.h +26 -20
- data/ext/pg_query/include/postgres/libpq/pqformat.h +2 -3
- data/ext/pg_query/include/postgres/libpq/pqsignal.h +1 -1
- data/ext/pg_query/include/postgres/libpq/protocol.h +89 -0
- data/ext/pg_query/include/postgres/libpq/sasl.h +1 -1
- data/ext/pg_query/include/postgres/libpq/scram.h +1 -1
- data/ext/pg_query/include/postgres/mb/pg_wchar.h +103 -82
- data/ext/pg_query/include/postgres/mb/stringinfo_mb.h +1 -1
- data/ext/pg_query/include/postgres/miscadmin.h +72 -52
- data/ext/pg_query/include/postgres/nodes/bitmapset.h +17 -3
- data/ext/pg_query/include/postgres/nodes/execnodes.h +112 -25
- data/ext/pg_query/include/postgres/nodes/extensible.h +1 -1
- data/ext/pg_query/include/postgres/nodes/lockoptions.h +4 -4
- data/ext/pg_query/include/postgres/nodes/makefuncs.h +8 -2
- data/ext/pg_query/include/postgres/nodes/memnodes.h +43 -4
- data/ext/pg_query/include/postgres/nodes/miscnodes.h +1 -1
- data/ext/pg_query/include/postgres/nodes/nodeFuncs.h +1 -1
- data/ext/pg_query/include/postgres/nodes/nodes.h +30 -41
- data/ext/pg_query/include/postgres/nodes/nodetags.h +464 -444
- data/ext/pg_query/include/postgres/nodes/params.h +1 -1
- data/ext/pg_query/include/postgres/nodes/parsenodes.h +358 -175
- data/ext/pg_query/include/postgres/nodes/pathnodes.h +64 -10
- data/ext/pg_query/include/postgres/nodes/pg_list.h +62 -11
- data/ext/pg_query/include/postgres/nodes/plannodes.h +11 -10
- data/ext/pg_query/include/postgres/nodes/primnodes.h +352 -54
- data/ext/pg_query/include/postgres/nodes/print.h +1 -1
- data/ext/pg_query/include/postgres/nodes/queryjumble.h +2 -2
- data/ext/pg_query/include/postgres/nodes/replnodes.h +23 -2
- data/ext/pg_query/include/postgres/nodes/supportnodes.h +1 -1
- data/ext/pg_query/include/postgres/nodes/tidbitmap.h +1 -1
- data/ext/pg_query/include/postgres/nodes/value.h +1 -1
- data/ext/pg_query/include/postgres/optimizer/cost.h +5 -4
- data/ext/pg_query/include/postgres/optimizer/geqo.h +1 -1
- data/ext/pg_query/include/postgres/optimizer/geqo_gene.h +1 -1
- data/ext/pg_query/include/postgres/optimizer/optimizer.h +5 -2
- data/ext/pg_query/include/postgres/optimizer/paths.h +13 -8
- data/ext/pg_query/include/postgres/optimizer/planmain.h +7 -1
- data/ext/pg_query/include/postgres/parser/analyze.h +3 -1
- data/ext/pg_query/include/postgres/parser/kwlist.h +22 -2
- data/ext/pg_query/include/postgres/parser/parse_agg.h +1 -1
- data/ext/pg_query/include/postgres/parser/parse_coerce.h +5 -2
- data/ext/pg_query/include/postgres/parser/parse_expr.h +1 -1
- data/ext/pg_query/include/postgres/parser/parse_func.h +2 -2
- data/ext/pg_query/include/postgres/parser/parse_node.h +3 -2
- data/ext/pg_query/include/postgres/parser/parse_oper.h +4 -1
- data/ext/pg_query/include/postgres/parser/parse_relation.h +1 -1
- data/ext/pg_query/include/postgres/parser/parse_type.h +2 -2
- data/ext/pg_query/include/postgres/parser/parser.h +3 -3
- data/ext/pg_query/include/postgres/parser/parsetree.h +1 -1
- data/ext/pg_query/include/postgres/parser/scanner.h +1 -1
- data/ext/pg_query/include/postgres/parser/scansup.h +1 -1
- data/ext/pg_query/include/postgres/partitioning/partdefs.h +1 -1
- data/ext/pg_query/include/postgres/pg_config.h +53 -45
- data/ext/pg_query/include/postgres/pg_config_manual.h +21 -8
- data/ext/pg_query/include/postgres/pg_getopt.h +1 -1
- data/ext/pg_query/include/postgres/pg_trace.h +1 -1
- data/ext/pg_query/include/postgres/pgstat.h +13 -11
- data/ext/pg_query/include/postgres/pgtime.h +1 -1
- data/ext/pg_query/include/postgres/pl_reserved_kwlist.h +1 -1
- data/ext/pg_query/include/postgres/pl_reserved_kwlist_d.h +1 -1
- data/ext/pg_query/include/postgres/pl_unreserved_kwlist.h +1 -1
- data/ext/pg_query/include/postgres/pl_unreserved_kwlist_d.h +1 -1
- data/ext/pg_query/include/postgres/plerrcodes.h +4 -4
- data/ext/pg_query/include/postgres/plpgsql.h +15 -13
- data/ext/pg_query/include/postgres/port/atomics/arch-arm.h +1 -1
- data/ext/pg_query/include/postgres/port/atomics/arch-hppa.h +1 -1
- data/ext/pg_query/include/postgres/port/atomics/arch-ppc.h +3 -1
- data/ext/pg_query/include/postgres/port/atomics/arch-x86.h +3 -1
- data/ext/pg_query/include/postgres/port/atomics/fallback.h +1 -1
- data/ext/pg_query/include/postgres/port/atomics/generic-gcc.h +38 -1
- data/ext/pg_query/include/postgres/port/atomics/generic-msvc.h +19 -1
- data/ext/pg_query/include/postgres/port/atomics/generic-sunpro.h +16 -1
- data/ext/pg_query/include/postgres/port/atomics/generic.h +38 -2
- data/ext/pg_query/include/postgres/port/atomics.h +93 -6
- data/ext/pg_query/include/postgres/port/pg_bitutils.h +91 -9
- data/ext/pg_query/include/postgres/port/pg_bswap.h +1 -1
- data/ext/pg_query/include/postgres/port/pg_crc32c.h +10 -1
- data/ext/pg_query/include/postgres/port/pg_iovec.h +117 -0
- data/ext/pg_query/include/postgres/port/simd.h +48 -1
- data/ext/pg_query/include/postgres/port/win32/sys/socket.h +8 -0
- data/ext/pg_query/include/postgres/port/win32_port.h +1 -13
- data/ext/pg_query/include/postgres/port.h +39 -4
- data/ext/pg_query/include/postgres/portability/instr_time.h +1 -1
- data/ext/pg_query/include/postgres/postgres.h +1 -1
- data/ext/pg_query/include/postgres/postmaster/autovacuum.h +5 -16
- data/ext/pg_query/include/postgres/postmaster/bgworker.h +8 -6
- data/ext/pg_query/include/postgres/postmaster/bgworker_internals.h +3 -7
- data/ext/pg_query/include/postgres/postmaster/bgwriter.h +3 -3
- data/ext/pg_query/include/postgres/postmaster/interrupt.h +1 -1
- data/ext/pg_query/include/postgres/postmaster/pgarch.h +2 -2
- data/ext/pg_query/include/postgres/postmaster/postmaster.h +25 -5
- data/ext/pg_query/include/postgres/postmaster/startup.h +2 -2
- data/ext/pg_query/include/postgres/postmaster/syslogger.h +2 -4
- data/ext/pg_query/include/postgres/postmaster/walsummarizer.h +35 -0
- data/ext/pg_query/include/postgres/postmaster/walwriter.h +2 -2
- data/ext/pg_query/include/postgres/regex/regex.h +92 -9
- data/ext/pg_query/include/postgres/replication/logicallauncher.h +1 -1
- data/ext/pg_query/include/postgres/replication/logicalproto.h +2 -2
- data/ext/pg_query/include/postgres/replication/logicalworker.h +2 -1
- data/ext/pg_query/include/postgres/replication/origin.h +1 -1
- data/ext/pg_query/include/postgres/replication/reorderbuffer.h +27 -46
- data/ext/pg_query/include/postgres/replication/slot.h +45 -5
- data/ext/pg_query/include/postgres/replication/slotsync.h +38 -0
- data/ext/pg_query/include/postgres/replication/syncrep.h +1 -1
- data/ext/pg_query/include/postgres/replication/walreceiver.h +37 -11
- data/ext/pg_query/include/postgres/replication/walsender.h +5 -3
- data/ext/pg_query/include/postgres/rewrite/prs2lock.h +1 -1
- data/ext/pg_query/include/postgres/rewrite/rewriteHandler.h +7 -1
- data/ext/pg_query/include/postgres/rewrite/rewriteManip.h +2 -2
- data/ext/pg_query/include/postgres/rewrite/rewriteSupport.h +1 -1
- data/ext/pg_query/include/postgres/storage/block.h +1 -1
- data/ext/pg_query/include/postgres/storage/buf.h +1 -1
- data/ext/pg_query/include/postgres/storage/bufmgr.h +59 -41
- data/ext/pg_query/include/postgres/storage/bufpage.h +1 -1
- data/ext/pg_query/include/postgres/storage/condition_variable.h +1 -1
- data/ext/pg_query/include/postgres/storage/dsm.h +1 -1
- data/ext/pg_query/include/postgres/storage/dsm_impl.h +2 -2
- data/ext/pg_query/include/postgres/storage/fd.h +30 -13
- data/ext/pg_query/include/postgres/storage/fileset.h +1 -1
- data/ext/pg_query/include/postgres/storage/ipc.h +4 -1
- data/ext/pg_query/include/postgres/storage/item.h +1 -1
- data/ext/pg_query/include/postgres/storage/itemid.h +1 -1
- data/ext/pg_query/include/postgres/storage/itemptr.h +1 -1
- data/ext/pg_query/include/postgres/storage/large_object.h +1 -1
- data/ext/pg_query/include/postgres/storage/latch.h +4 -2
- data/ext/pg_query/include/postgres/storage/lmgr.h +8 -2
- data/ext/pg_query/include/postgres/storage/lock.h +19 -19
- data/ext/pg_query/include/postgres/storage/lockdefs.h +3 -1
- data/ext/pg_query/include/postgres/storage/lwlock.h +17 -9
- data/ext/pg_query/include/postgres/storage/lwlocknames.h +7 -10
- data/ext/pg_query/include/postgres/storage/off.h +1 -1
- data/ext/pg_query/include/postgres/storage/pg_sema.h +1 -1
- data/ext/pg_query/include/postgres/storage/pg_shmem.h +5 -4
- data/ext/pg_query/include/postgres/storage/pmsignal.h +2 -2
- data/ext/pg_query/include/postgres/storage/predicate.h +1 -5
- data/ext/pg_query/include/postgres/storage/proc.h +48 -26
- data/ext/pg_query/include/postgres/storage/procarray.h +5 -1
- data/ext/pg_query/include/postgres/storage/proclist_types.h +11 -9
- data/ext/pg_query/include/postgres/storage/procnumber.h +43 -0
- data/ext/pg_query/include/postgres/storage/procsignal.h +8 -6
- data/ext/pg_query/include/postgres/storage/read_stream.h +65 -0
- data/ext/pg_query/include/postgres/storage/relfilelocator.h +16 -15
- data/ext/pg_query/include/postgres/storage/s_lock.h +7 -27
- data/ext/pg_query/include/postgres/storage/sharedfileset.h +1 -1
- data/ext/pg_query/include/postgres/storage/shm_mq.h +2 -2
- data/ext/pg_query/include/postgres/storage/shm_toc.h +1 -1
- data/ext/pg_query/include/postgres/storage/shmem.h +1 -1
- data/ext/pg_query/include/postgres/storage/sinval.h +3 -3
- data/ext/pg_query/include/postgres/storage/smgr.h +46 -29
- data/ext/pg_query/include/postgres/storage/spin.h +1 -1
- data/ext/pg_query/include/postgres/storage/standby.h +13 -3
- data/ext/pg_query/include/postgres/storage/standbydefs.h +2 -2
- data/ext/pg_query/include/postgres/storage/sync.h +4 -4
- data/ext/pg_query/include/postgres/tcop/cmdtag.h +1 -2
- data/ext/pg_query/include/postgres/tcop/cmdtaglist.h +3 -2
- data/ext/pg_query/include/postgres/tcop/deparse_utility.h +2 -2
- data/ext/pg_query/include/postgres/tcop/dest.h +3 -2
- data/ext/pg_query/include/postgres/tcop/fastpath.h +1 -1
- data/ext/pg_query/include/postgres/tcop/pquery.h +1 -1
- data/ext/pg_query/include/postgres/tcop/tcopprot.h +9 -5
- data/ext/pg_query/include/postgres/tcop/utility.h +2 -2
- data/ext/pg_query/include/postgres/tsearch/ts_cache.h +1 -1
- data/ext/pg_query/include/postgres/utils/acl.h +19 -7
- data/ext/pg_query/include/postgres/utils/aclchk_internal.h +1 -1
- data/ext/pg_query/include/postgres/utils/array.h +1 -2
- data/ext/pg_query/include/postgres/utils/ascii.h +84 -0
- data/ext/pg_query/include/postgres/utils/backend_progress.h +3 -2
- data/ext/pg_query/include/postgres/utils/backend_status.h +8 -10
- data/ext/pg_query/include/postgres/utils/builtins.h +4 -1
- data/ext/pg_query/include/postgres/utils/bytea.h +2 -2
- data/ext/pg_query/include/postgres/utils/catcache.h +6 -6
- data/ext/pg_query/include/postgres/utils/date.h +1 -1
- data/ext/pg_query/include/postgres/utils/datetime.h +4 -1
- data/ext/pg_query/include/postgres/utils/datum.h +1 -1
- data/ext/pg_query/include/postgres/utils/dsa.h +44 -5
- data/ext/pg_query/include/postgres/utils/elog.h +3 -8
- data/ext/pg_query/include/postgres/utils/errcodes.h +1 -3
- data/ext/pg_query/include/postgres/utils/expandeddatum.h +1 -1
- data/ext/pg_query/include/postgres/utils/expandedrecord.h +1 -1
- data/ext/pg_query/include/postgres/utils/float.h +1 -1
- data/ext/pg_query/include/postgres/utils/fmgroids.h +49 -16
- data/ext/pg_query/include/postgres/utils/fmgrprotos.h +47 -14
- data/ext/pg_query/include/postgres/utils/fmgrtab.h +1 -1
- data/ext/pg_query/include/postgres/utils/guc.h +20 -6
- data/ext/pg_query/include/postgres/utils/guc_hooks.h +23 -2
- data/ext/pg_query/include/postgres/utils/guc_tables.h +6 -5
- data/ext/pg_query/include/postgres/utils/hsearch.h +2 -2
- data/ext/pg_query/include/postgres/utils/injection_point.h +44 -0
- data/ext/pg_query/include/postgres/utils/inval.h +1 -1
- data/ext/pg_query/include/postgres/utils/logtape.h +5 -5
- data/ext/pg_query/include/postgres/utils/lsyscache.h +6 -3
- data/ext/pg_query/include/postgres/utils/memdebug.h +1 -1
- data/ext/pg_query/include/postgres/utils/memutils.h +12 -5
- data/ext/pg_query/include/postgres/utils/memutils_internal.h +53 -13
- data/ext/pg_query/include/postgres/utils/memutils_memorychunk.h +25 -9
- data/ext/pg_query/include/postgres/utils/numeric.h +6 -1
- data/ext/pg_query/include/postgres/utils/palloc.h +1 -15
- data/ext/pg_query/include/postgres/utils/partcache.h +1 -1
- data/ext/pg_query/include/postgres/utils/pg_locale.h +8 -7
- data/ext/pg_query/include/postgres/utils/pgstat_internal.h +30 -17
- data/ext/pg_query/include/postgres/utils/plancache.h +5 -3
- data/ext/pg_query/include/postgres/utils/portal.h +10 -10
- data/ext/pg_query/include/postgres/utils/queryenvironment.h +2 -2
- data/ext/pg_query/include/postgres/utils/regproc.h +1 -1
- data/ext/pg_query/include/postgres/utils/rel.h +14 -15
- data/ext/pg_query/include/postgres/utils/relcache.h +2 -5
- data/ext/pg_query/include/postgres/utils/reltrigger.h +1 -1
- data/ext/pg_query/include/postgres/utils/resowner.h +90 -9
- data/ext/pg_query/include/postgres/utils/ruleutils.h +1 -1
- data/ext/pg_query/include/postgres/utils/sharedtuplestore.h +1 -1
- data/ext/pg_query/include/postgres/utils/snapmgr.h +1 -52
- data/ext/pg_query/include/postgres/utils/snapshot.h +2 -2
- data/ext/pg_query/include/postgres/utils/sortsupport.h +1 -1
- data/ext/pg_query/include/postgres/utils/syscache.h +7 -98
- data/ext/pg_query/include/postgres/utils/timeout.h +3 -2
- data/ext/pg_query/include/postgres/utils/timestamp.h +1 -1
- data/ext/pg_query/include/postgres/utils/tuplesort.h +36 -9
- data/ext/pg_query/include/postgres/utils/tuplestore.h +2 -5
- data/ext/pg_query/include/postgres/utils/typcache.h +2 -1
- data/ext/pg_query/include/postgres/utils/varlena.h +1 -1
- data/ext/pg_query/include/postgres/utils/wait_event.h +28 -214
- data/ext/pg_query/include/postgres/utils/wait_event_types.h +218 -0
- data/ext/pg_query/include/postgres/utils/xml.h +4 -4
- data/ext/pg_query/include/postgres/varatt.h +1 -1
- data/ext/pg_query/include/protobuf/pg_query.pb-c.h +1546 -792
- data/ext/pg_query/include/protobuf/pg_query.pb.h +58365 -46595
- data/ext/pg_query/pg_query.pb-c.c +6598 -3739
- data/ext/pg_query/pg_query_normalize.c +42 -1
- data/ext/pg_query/pg_query_outfuncs_json.c +3 -1
- data/ext/pg_query/pg_query_parse_plpgsql.c +12 -13
- data/ext/pg_query/pg_query_readfuncs_protobuf.c +2 -2
- data/ext/pg_query/pg_query_scan.c +1 -1
- data/ext/pg_query/postgres_deparse.c +601 -172
- data/ext/pg_query/src_backend_catalog_namespace.c +241 -66
- data/ext/pg_query/src_backend_catalog_pg_proc.c +1 -3
- data/ext/pg_query/src_backend_commands_define.c +2 -3
- data/ext/pg_query/src_backend_nodes_bitmapset.c +137 -94
- data/ext/pg_query/src_backend_nodes_copyfuncs.c +1 -1
- data/ext/pg_query/src_backend_nodes_equalfuncs.c +1 -1
- data/ext/pg_query/src_backend_nodes_extensible.c +1 -1
- data/ext/pg_query/src_backend_nodes_list.c +3 -7
- data/ext/pg_query/src_backend_nodes_makefuncs.c +59 -20
- data/ext/pg_query/src_backend_nodes_nodeFuncs.c +109 -2
- data/ext/pg_query/src_backend_nodes_value.c +1 -1
- data/ext/pg_query/src_backend_parser_gram.c +34491 -32136
- data/ext/pg_query/src_backend_parser_parser.c +8 -8
- data/ext/pg_query/src_backend_parser_scan.c +5637 -3028
- data/ext/pg_query/src_backend_parser_scansup.c +2 -1
- data/ext/pg_query/src_backend_storage_ipc_ipc.c +1 -1
- data/ext/pg_query/src_backend_tcop_postgres.c +34 -10
- data/ext/pg_query/src_backend_utils_activity_pgstat_database.c +2 -2
- data/ext/pg_query/src_backend_utils_adt_datum.c +8 -6
- data/ext/pg_query/src_backend_utils_adt_expandeddatum.c +1 -1
- data/ext/pg_query/src_backend_utils_adt_format_type.c +1 -1
- data/ext/pg_query/src_backend_utils_adt_numutils.c +4 -5
- data/ext/pg_query/src_backend_utils_adt_ruleutils.c +101 -28
- data/ext/pg_query/src_backend_utils_error_assert.c +1 -1
- data/ext/pg_query/src_backend_utils_error_elog.c +47 -42
- data/ext/pg_query/src_backend_utils_fmgr_fmgr.c +4 -2
- data/ext/pg_query/src_backend_utils_init_globals.c +15 -3
- data/ext/pg_query/src_backend_utils_mb_mbutils.c +11 -18
- data/ext/pg_query/src_backend_utils_misc_guc_tables.c +16 -6
- data/ext/pg_query/src_backend_utils_mmgr_alignedalloc.c +8 -5
- data/ext/pg_query/src_backend_utils_mmgr_aset.c +308 -238
- data/ext/pg_query/src_backend_utils_mmgr_bump.c +728 -0
- data/ext/pg_query/src_backend_utils_mmgr_generation.c +273 -197
- data/ext/pg_query/src_backend_utils_mmgr_mcxt.c +270 -215
- data/ext/pg_query/src_backend_utils_mmgr_slab.c +154 -96
- data/ext/pg_query/src_common_encnames.c +43 -44
- data/ext/pg_query/src_common_hashfn.c +1 -1
- data/ext/pg_query/src_common_keywords.c +1 -1
- data/ext/pg_query/src_common_kwlist_d.h +511 -466
- data/ext/pg_query/src_common_kwlookup.c +1 -1
- data/ext/pg_query/src_common_psprintf.c +3 -3
- data/ext/pg_query/src_common_stringinfo.c +18 -1
- data/ext/pg_query/src_common_wchar.c +92 -109
- data/ext/pg_query/src_pl_plpgsql_src_pl_comp.c +99 -5
- data/ext/pg_query/src_pl_plpgsql_src_pl_funcs.c +1 -1
- data/ext/pg_query/src_pl_plpgsql_src_pl_gram.c +242 -143
- data/ext/pg_query/src_pl_plpgsql_src_pl_handler.c +1 -1
- data/ext/pg_query/src_pl_plpgsql_src_pl_reserved_kwlist_d.h +1 -1
- data/ext/pg_query/src_pl_plpgsql_src_pl_scanner.c +19 -1
- data/ext/pg_query/src_pl_plpgsql_src_pl_unreserved_kwlist_d.h +1 -1
- data/ext/pg_query/src_port_pg_bitutils.c +173 -28
- data/ext/pg_query/src_port_pgstrcasecmp.c +29 -1
- data/ext/pg_query/src_port_snprintf.c +15 -18
- data/ext/pg_query/src_port_strerror.c +1 -3
- data/ext/pg_query/src_port_strlcpy.c +1 -1
- data/lib/pg_query/fingerprint.rb +3 -5
- data/lib/pg_query/param_refs.rb +2 -2
- data/lib/pg_query/parse.rb +5 -7
- data/lib/pg_query/parse_error.rb +1 -0
- data/lib/pg_query/pg_query_pb.rb +27 -25
- data/lib/pg_query/scan.rb +1 -0
- data/lib/pg_query/treewalker.rb +38 -15
- data/lib/pg_query/truncate.rb +18 -20
- data/lib/pg_query/version.rb +1 -1
- metadata +31 -82
- data/ext/pg_query/include/postgres/storage/backendid.h +0 -37
- data/ext/pg_query/include/postgres/storage/sinvaladt.h +0 -45
- data/ext/pg_query/pg_query_ruby_freebsd.sym +0 -2
- data/ext/pg_query/src_backend_nodes_nodes.c +0 -38
- /data/ext/pg_query/{pg_query_ruby.sym → ext_symbols.sym} +0 -0
@@ -0,0 +1,728 @@
|
|
1
|
+
/*--------------------------------------------------------------------
|
2
|
+
* Symbols referenced in this file:
|
3
|
+
* - BumpAlloc
|
4
|
+
* - BumpAllocLarge
|
5
|
+
* - BumpBlockFreeBytes
|
6
|
+
* - BumpAllocFromNewBlock
|
7
|
+
* - BumpBlockInit
|
8
|
+
* - BumpAllocChunkFromBlock
|
9
|
+
* - BumpFree
|
10
|
+
* - BumpRealloc
|
11
|
+
* - BumpReset
|
12
|
+
* - BumpBlockMarkEmpty
|
13
|
+
* - BumpBlockFree
|
14
|
+
* - BumpDelete
|
15
|
+
* - BumpGetChunkContext
|
16
|
+
* - BumpGetChunkSpace
|
17
|
+
* - BumpIsEmpty
|
18
|
+
* - BumpBlockIsEmpty
|
19
|
+
* - BumpStats
|
20
|
+
* - BumpCheck
|
21
|
+
*--------------------------------------------------------------------
|
22
|
+
*/
|
23
|
+
|
24
|
+
/*-------------------------------------------------------------------------
|
25
|
+
*
|
26
|
+
* bump.c
|
27
|
+
* Bump allocator definitions.
|
28
|
+
*
|
29
|
+
* Bump is a MemoryContext implementation designed for memory usages which
|
30
|
+
* require allocating a large number of chunks, none of which ever need to be
|
31
|
+
* pfree'd or realloc'd. Chunks allocated by this context have no chunk header
|
32
|
+
* and operations which ordinarily require looking at the chunk header cannot
|
33
|
+
* be performed. For example, pfree, realloc, GetMemoryChunkSpace and
|
34
|
+
* GetMemoryChunkContext are all not possible with bump allocated chunks. The
|
35
|
+
* only way to release memory allocated by this context type is to reset or
|
36
|
+
* delete the context.
|
37
|
+
*
|
38
|
+
* Portions Copyright (c) 2024, PostgreSQL Global Development Group
|
39
|
+
*
|
40
|
+
* IDENTIFICATION
|
41
|
+
* src/backend/utils/mmgr/bump.c
|
42
|
+
*
|
43
|
+
*
|
44
|
+
* Bump is best suited to cases which require a large number of short-lived
|
45
|
+
* chunks where performance matters. Because bump allocated chunks don't
|
46
|
+
* have a chunk header, it can fit more chunks on each block. This means we
|
47
|
+
* can do more with less memory and fewer cache lines. The reason it's best
|
48
|
+
* suited for short-lived usages of memory is that ideally, pointers to bump
|
49
|
+
* allocated chunks won't be visible to a large amount of code. The more
|
50
|
+
* code that operates on memory allocated by this allocator, the more chances
|
51
|
+
* that some code will try to perform a pfree or one of the other operations
|
52
|
+
* which are made impossible due to the lack of chunk header. In order to
|
53
|
+
* detect accidental usage of the various disallowed operations, we do add a
|
54
|
+
* MemoryChunk chunk header in MEMORY_CONTEXT_CHECKING builds and have the
|
55
|
+
* various disallowed functions raise an ERROR.
|
56
|
+
*
|
57
|
+
* Allocations are MAXALIGNed.
|
58
|
+
*
|
59
|
+
*-------------------------------------------------------------------------
|
60
|
+
*/
|
61
|
+
|
62
|
+
#include "postgres.h"
|
63
|
+
|
64
|
+
#include "lib/ilist.h"
|
65
|
+
#include "port/pg_bitutils.h"
|
66
|
+
#include "utils/memdebug.h"
|
67
|
+
#include "utils/memutils.h"
|
68
|
+
#include "utils/memutils_memorychunk.h"
|
69
|
+
#include "utils/memutils_internal.h"
|
70
|
+
|
71
|
+
#define Bump_BLOCKHDRSZ MAXALIGN(sizeof(BumpBlock))
|
72
|
+
|
73
|
+
/* No chunk header unless built with MEMORY_CONTEXT_CHECKING */
|
74
|
+
#ifdef MEMORY_CONTEXT_CHECKING
|
75
|
+
#define Bump_CHUNKHDRSZ sizeof(MemoryChunk)
|
76
|
+
#else
|
77
|
+
#define Bump_CHUNKHDRSZ 0
|
78
|
+
#endif
|
79
|
+
|
80
|
+
#define Bump_CHUNK_FRACTION 8
|
81
|
+
|
82
|
+
/* The keeper block is allocated in the same allocation as the set */
|
83
|
+
#define KeeperBlock(set) ((BumpBlock *) ((char *) (set) + \
|
84
|
+
MAXALIGN(sizeof(BumpContext))))
|
85
|
+
#define IsKeeperBlock(set, blk) (KeeperBlock(set) == (blk))
|
86
|
+
|
87
|
+
typedef struct BumpBlock BumpBlock; /* forward reference */
|
88
|
+
|
89
|
+
typedef struct BumpContext
|
90
|
+
{
|
91
|
+
MemoryContextData header; /* Standard memory-context fields */
|
92
|
+
|
93
|
+
/* Bump context parameters */
|
94
|
+
uint32 initBlockSize; /* initial block size */
|
95
|
+
uint32 maxBlockSize; /* maximum block size */
|
96
|
+
uint32 nextBlockSize; /* next block size to allocate */
|
97
|
+
uint32 allocChunkLimit; /* effective chunk size limit */
|
98
|
+
|
99
|
+
dlist_head blocks; /* list of blocks with the block currently
|
100
|
+
* being filled at the head */
|
101
|
+
} BumpContext;
|
102
|
+
|
103
|
+
/*
|
104
|
+
* BumpBlock
|
105
|
+
* BumpBlock is the unit of memory that is obtained by bump.c from
|
106
|
+
* malloc(). It contains zero or more allocations, which are the
|
107
|
+
* units requested by palloc().
|
108
|
+
*/
|
109
|
+
struct BumpBlock
|
110
|
+
{
|
111
|
+
dlist_node node; /* doubly-linked list of blocks */
|
112
|
+
#ifdef MEMORY_CONTEXT_CHECKING
|
113
|
+
BumpContext *context; /* pointer back to the owning context */
|
114
|
+
#endif
|
115
|
+
char *freeptr; /* start of free space in this block */
|
116
|
+
char *endptr; /* end of space in this block */
|
117
|
+
};
|
118
|
+
|
119
|
+
/*
|
120
|
+
* BumpIsValid
|
121
|
+
* True iff set is valid bump context.
|
122
|
+
*/
|
123
|
+
#define BumpIsValid(set) \
|
124
|
+
(PointerIsValid(set) && IsA(set, BumpContext))
|
125
|
+
|
126
|
+
/*
|
127
|
+
* We always store external chunks on a dedicated block. This makes fetching
|
128
|
+
* the block from an external chunk easy since it's always the first and only
|
129
|
+
* chunk on the block.
|
130
|
+
*/
|
131
|
+
#define ExternalChunkGetBlock(chunk) \
|
132
|
+
(BumpBlock *) ((char *) chunk - Bump_BLOCKHDRSZ)
|
133
|
+
|
134
|
+
/* Inlined helper functions */
|
135
|
+
static inline void BumpBlockInit(BumpContext *context, BumpBlock *block,
|
136
|
+
Size blksize);
|
137
|
+
static inline bool BumpBlockIsEmpty(BumpBlock *block);
|
138
|
+
static inline void BumpBlockMarkEmpty(BumpBlock *block);
|
139
|
+
static inline Size BumpBlockFreeBytes(BumpBlock *block);
|
140
|
+
static inline void BumpBlockFree(BumpContext *set, BumpBlock *block);
|
141
|
+
|
142
|
+
|
143
|
+
/*
|
144
|
+
* BumpContextCreate
|
145
|
+
* Create a new Bump context.
|
146
|
+
*
|
147
|
+
* parent: parent context, or NULL if top-level context
|
148
|
+
* name: name of context (must be statically allocated)
|
149
|
+
* minContextSize: minimum context size
|
150
|
+
* initBlockSize: initial allocation block size
|
151
|
+
* maxBlockSize: maximum allocation block size
|
152
|
+
*/
|
153
|
+
|
154
|
+
|
155
|
+
/*
|
156
|
+
* BumpReset
|
157
|
+
* Frees all memory which is allocated in the given set.
|
158
|
+
*
|
159
|
+
* The code simply frees all the blocks in the context apart from the keeper
|
160
|
+
* block.
|
161
|
+
*/
|
162
|
+
void
|
163
|
+
BumpReset(MemoryContext context)
|
164
|
+
{
|
165
|
+
BumpContext *set = (BumpContext *) context;
|
166
|
+
dlist_mutable_iter miter;
|
167
|
+
|
168
|
+
Assert(BumpIsValid(set));
|
169
|
+
|
170
|
+
#ifdef MEMORY_CONTEXT_CHECKING
|
171
|
+
/* Check for corruption and leaks before freeing */
|
172
|
+
BumpCheck(context);
|
173
|
+
#endif
|
174
|
+
|
175
|
+
dlist_foreach_modify(miter, &set->blocks)
|
176
|
+
{
|
177
|
+
BumpBlock *block = dlist_container(BumpBlock, node, miter.cur);
|
178
|
+
|
179
|
+
if (IsKeeperBlock(set, block))
|
180
|
+
BumpBlockMarkEmpty(block);
|
181
|
+
else
|
182
|
+
BumpBlockFree(set, block);
|
183
|
+
}
|
184
|
+
|
185
|
+
/* Reset block size allocation sequence, too */
|
186
|
+
set->nextBlockSize = set->initBlockSize;
|
187
|
+
|
188
|
+
/* Ensure there is only 1 item in the dlist */
|
189
|
+
Assert(!dlist_is_empty(&set->blocks));
|
190
|
+
Assert(!dlist_has_next(&set->blocks, dlist_head_node(&set->blocks)));
|
191
|
+
}
|
192
|
+
|
193
|
+
/*
|
194
|
+
* BumpDelete
|
195
|
+
* Free all memory which is allocated in the given context.
|
196
|
+
*/
|
197
|
+
void
|
198
|
+
BumpDelete(MemoryContext context)
|
199
|
+
{
|
200
|
+
/* Reset to release all releasable BumpBlocks */
|
201
|
+
BumpReset(context);
|
202
|
+
/* And free the context header and keeper block */
|
203
|
+
free(context);
|
204
|
+
}
|
205
|
+
|
206
|
+
/*
|
207
|
+
* Helper for BumpAlloc() that allocates an entire block for the chunk.
|
208
|
+
*
|
209
|
+
* BumpAlloc()'s comment explains why this is separate.
|
210
|
+
*/
|
211
|
+
pg_noinline
|
212
|
+
static void *
|
213
|
+
BumpAllocLarge(MemoryContext context, Size size, int flags)
|
214
|
+
{
|
215
|
+
BumpContext *set = (BumpContext *) context;
|
216
|
+
BumpBlock *block;
|
217
|
+
#ifdef MEMORY_CONTEXT_CHECKING
|
218
|
+
MemoryChunk *chunk;
|
219
|
+
#endif
|
220
|
+
Size chunk_size;
|
221
|
+
Size required_size;
|
222
|
+
Size blksize;
|
223
|
+
|
224
|
+
/* validate 'size' is within the limits for the given 'flags' */
|
225
|
+
MemoryContextCheckSize(context, size, flags);
|
226
|
+
|
227
|
+
#ifdef MEMORY_CONTEXT_CHECKING
|
228
|
+
/* ensure there's always space for the sentinel byte */
|
229
|
+
chunk_size = MAXALIGN(size + 1);
|
230
|
+
#else
|
231
|
+
chunk_size = MAXALIGN(size);
|
232
|
+
#endif
|
233
|
+
|
234
|
+
required_size = chunk_size + Bump_CHUNKHDRSZ;
|
235
|
+
blksize = required_size + Bump_BLOCKHDRSZ;
|
236
|
+
|
237
|
+
block = (BumpBlock *) malloc(blksize);
|
238
|
+
if (block == NULL)
|
239
|
+
return NULL;
|
240
|
+
|
241
|
+
context->mem_allocated += blksize;
|
242
|
+
|
243
|
+
/* the block is completely full */
|
244
|
+
block->freeptr = block->endptr = ((char *) block) + blksize;
|
245
|
+
|
246
|
+
#ifdef MEMORY_CONTEXT_CHECKING
|
247
|
+
/* block with a single (used) chunk */
|
248
|
+
block->context = set;
|
249
|
+
|
250
|
+
chunk = (MemoryChunk *) (((char *) block) + Bump_BLOCKHDRSZ);
|
251
|
+
|
252
|
+
/* mark the MemoryChunk as externally managed */
|
253
|
+
MemoryChunkSetHdrMaskExternal(chunk, MCTX_BUMP_ID);
|
254
|
+
|
255
|
+
chunk->requested_size = size;
|
256
|
+
/* set mark to catch clobber of "unused" space */
|
257
|
+
Assert(size < chunk_size);
|
258
|
+
set_sentinel(MemoryChunkGetPointer(chunk), size);
|
259
|
+
#endif
|
260
|
+
#ifdef RANDOMIZE_ALLOCATED_MEMORY
|
261
|
+
/* fill the allocated space with junk */
|
262
|
+
randomize_mem((char *) MemoryChunkGetPointer(chunk), size);
|
263
|
+
#endif
|
264
|
+
|
265
|
+
/*
|
266
|
+
* Add the block to the tail of allocated blocks list. The current block
|
267
|
+
* is left at the head of the list as it may still have space for
|
268
|
+
* non-large allocations.
|
269
|
+
*/
|
270
|
+
dlist_push_tail(&set->blocks, &block->node);
|
271
|
+
|
272
|
+
#ifdef MEMORY_CONTEXT_CHECKING
|
273
|
+
/* Ensure any padding bytes are marked NOACCESS. */
|
274
|
+
VALGRIND_MAKE_MEM_NOACCESS((char *) MemoryChunkGetPointer(chunk) + size,
|
275
|
+
chunk_size - size);
|
276
|
+
|
277
|
+
/* Disallow access to the chunk header. */
|
278
|
+
VALGRIND_MAKE_MEM_NOACCESS(chunk, Bump_CHUNKHDRSZ);
|
279
|
+
|
280
|
+
return MemoryChunkGetPointer(chunk);
|
281
|
+
#else
|
282
|
+
return (void *) (((char *) block) + Bump_BLOCKHDRSZ);
|
283
|
+
#endif
|
284
|
+
}
|
285
|
+
|
286
|
+
/*
|
287
|
+
* Small helper for allocating a new chunk from a chunk, to avoid duplicating
|
288
|
+
* the code between BumpAlloc() and BumpAllocFromNewBlock().
|
289
|
+
*/
|
290
|
+
static inline void *
|
291
|
+
BumpAllocChunkFromBlock(MemoryContext context, BumpBlock *block, Size size,
|
292
|
+
Size chunk_size)
|
293
|
+
{
|
294
|
+
#ifdef MEMORY_CONTEXT_CHECKING
|
295
|
+
MemoryChunk *chunk;
|
296
|
+
#else
|
297
|
+
void *ptr;
|
298
|
+
#endif
|
299
|
+
|
300
|
+
/* validate we've been given a block with enough free space */
|
301
|
+
Assert(block != NULL);
|
302
|
+
Assert((block->endptr - block->freeptr) >= Bump_CHUNKHDRSZ + chunk_size);
|
303
|
+
|
304
|
+
#ifdef MEMORY_CONTEXT_CHECKING
|
305
|
+
chunk = (MemoryChunk *) block->freeptr;
|
306
|
+
#else
|
307
|
+
ptr = (void *) block->freeptr;
|
308
|
+
#endif
|
309
|
+
|
310
|
+
/* point the freeptr beyond this chunk */
|
311
|
+
block->freeptr += (Bump_CHUNKHDRSZ + chunk_size);
|
312
|
+
Assert(block->freeptr <= block->endptr);
|
313
|
+
|
314
|
+
#ifdef MEMORY_CONTEXT_CHECKING
|
315
|
+
/* Prepare to initialize the chunk header. */
|
316
|
+
VALGRIND_MAKE_MEM_UNDEFINED(chunk, Bump_CHUNKHDRSZ);
|
317
|
+
|
318
|
+
MemoryChunkSetHdrMask(chunk, block, chunk_size, MCTX_BUMP_ID);
|
319
|
+
chunk->requested_size = size;
|
320
|
+
/* set mark to catch clobber of "unused" space */
|
321
|
+
Assert(size < chunk_size);
|
322
|
+
set_sentinel(MemoryChunkGetPointer(chunk), size);
|
323
|
+
|
324
|
+
#ifdef RANDOMIZE_ALLOCATED_MEMORY
|
325
|
+
/* fill the allocated space with junk */
|
326
|
+
randomize_mem((char *) MemoryChunkGetPointer(chunk), size);
|
327
|
+
#endif
|
328
|
+
|
329
|
+
/* Ensure any padding bytes are marked NOACCESS. */
|
330
|
+
VALGRIND_MAKE_MEM_NOACCESS((char *) MemoryChunkGetPointer(chunk) + size,
|
331
|
+
chunk_size - size);
|
332
|
+
|
333
|
+
/* Disallow access to the chunk header. */
|
334
|
+
VALGRIND_MAKE_MEM_NOACCESS(chunk, Bump_CHUNKHDRSZ);
|
335
|
+
|
336
|
+
return MemoryChunkGetPointer(chunk);
|
337
|
+
#else
|
338
|
+
return ptr;
|
339
|
+
#endif /* MEMORY_CONTEXT_CHECKING */
|
340
|
+
}
|
341
|
+
|
342
|
+
/*
|
343
|
+
* Helper for BumpAlloc() that allocates a new block and returns a chunk
|
344
|
+
* allocated from it.
|
345
|
+
*
|
346
|
+
* BumpAlloc()'s comment explains why this is separate.
|
347
|
+
*/
|
348
|
+
pg_noinline
|
349
|
+
static void *
|
350
|
+
BumpAllocFromNewBlock(MemoryContext context, Size size, int flags,
|
351
|
+
Size chunk_size)
|
352
|
+
{
|
353
|
+
BumpContext *set = (BumpContext *) context;
|
354
|
+
BumpBlock *block;
|
355
|
+
Size blksize;
|
356
|
+
Size required_size;
|
357
|
+
|
358
|
+
/*
|
359
|
+
* The first such block has size initBlockSize, and we double the space in
|
360
|
+
* each succeeding block, but not more than maxBlockSize.
|
361
|
+
*/
|
362
|
+
blksize = set->nextBlockSize;
|
363
|
+
set->nextBlockSize <<= 1;
|
364
|
+
if (set->nextBlockSize > set->maxBlockSize)
|
365
|
+
set->nextBlockSize = set->maxBlockSize;
|
366
|
+
|
367
|
+
/* we'll need space for the chunk, chunk hdr and block hdr */
|
368
|
+
required_size = chunk_size + Bump_CHUNKHDRSZ + Bump_BLOCKHDRSZ;
|
369
|
+
/* round the size up to the next power of 2 */
|
370
|
+
if (blksize < required_size)
|
371
|
+
blksize = pg_nextpower2_size_t(required_size);
|
372
|
+
|
373
|
+
block = (BumpBlock *) malloc(blksize);
|
374
|
+
|
375
|
+
if (block == NULL)
|
376
|
+
return MemoryContextAllocationFailure(context, size, flags);
|
377
|
+
|
378
|
+
context->mem_allocated += blksize;
|
379
|
+
|
380
|
+
/* initialize the new block */
|
381
|
+
BumpBlockInit(set, block, blksize);
|
382
|
+
|
383
|
+
/* add it to the doubly-linked list of blocks */
|
384
|
+
dlist_push_head(&set->blocks, &block->node);
|
385
|
+
|
386
|
+
return BumpAllocChunkFromBlock(context, block, size, chunk_size);
|
387
|
+
}
|
388
|
+
|
389
|
+
/*
|
390
|
+
* BumpAlloc
|
391
|
+
* Returns a pointer to allocated memory of given size or raises an ERROR
|
392
|
+
* on allocation failure, or returns NULL when flags contains
|
393
|
+
* MCXT_ALLOC_NO_OOM.
|
394
|
+
*
|
395
|
+
* No request may exceed:
|
396
|
+
* MAXALIGN_DOWN(SIZE_MAX) - Bump_BLOCKHDRSZ - Bump_CHUNKHDRSZ
|
397
|
+
* All callers use a much-lower limit.
|
398
|
+
*
|
399
|
+
*
|
400
|
+
* Note: when using valgrind, it doesn't matter how the returned allocation
|
401
|
+
* is marked, as mcxt.c will set it to UNDEFINED.
|
402
|
+
* This function should only contain the most common code paths. Everything
|
403
|
+
* else should be in pg_noinline helper functions, thus avoiding the overhead
|
404
|
+
* of creating a stack frame for the common cases. Allocating memory is often
|
405
|
+
* a bottleneck in many workloads, so avoiding stack frame setup is
|
406
|
+
* worthwhile. Helper functions should always directly return the newly
|
407
|
+
* allocated memory so that we can just return that address directly as a tail
|
408
|
+
* call.
|
409
|
+
*/
|
410
|
+
void *
|
411
|
+
BumpAlloc(MemoryContext context, Size size, int flags)
|
412
|
+
{
|
413
|
+
BumpContext *set = (BumpContext *) context;
|
414
|
+
BumpBlock *block;
|
415
|
+
Size chunk_size;
|
416
|
+
Size required_size;
|
417
|
+
|
418
|
+
Assert(BumpIsValid(set));
|
419
|
+
|
420
|
+
#ifdef MEMORY_CONTEXT_CHECKING
|
421
|
+
/* ensure there's always space for the sentinel byte */
|
422
|
+
chunk_size = MAXALIGN(size + 1);
|
423
|
+
#else
|
424
|
+
chunk_size = MAXALIGN(size);
|
425
|
+
#endif
|
426
|
+
|
427
|
+
/*
|
428
|
+
* If requested size exceeds maximum for chunks we hand the request off to
|
429
|
+
* BumpAllocLarge().
|
430
|
+
*/
|
431
|
+
if (chunk_size > set->allocChunkLimit)
|
432
|
+
return BumpAllocLarge(context, size, flags);
|
433
|
+
|
434
|
+
required_size = chunk_size + Bump_CHUNKHDRSZ;
|
435
|
+
|
436
|
+
/*
|
437
|
+
* Not an oversized chunk. We try to first make use of the latest block,
|
438
|
+
* but if there's not enough space in it we must allocate a new block.
|
439
|
+
*/
|
440
|
+
block = dlist_container(BumpBlock, node, dlist_head_node(&set->blocks));
|
441
|
+
|
442
|
+
if (BumpBlockFreeBytes(block) < required_size)
|
443
|
+
return BumpAllocFromNewBlock(context, size, flags, chunk_size);
|
444
|
+
|
445
|
+
/* The current block has space, so just allocate chunk there. */
|
446
|
+
return BumpAllocChunkFromBlock(context, block, size, chunk_size);
|
447
|
+
}
|
448
|
+
|
449
|
+
/*
|
450
|
+
* BumpBlockInit
|
451
|
+
* Initializes 'block' assuming 'blksize'. Does not update the context's
|
452
|
+
* mem_allocated field.
|
453
|
+
*/
|
454
|
+
static inline void
|
455
|
+
BumpBlockInit(BumpContext *context, BumpBlock *block, Size blksize)
|
456
|
+
{
|
457
|
+
#ifdef MEMORY_CONTEXT_CHECKING
|
458
|
+
block->context = context;
|
459
|
+
#endif
|
460
|
+
block->freeptr = ((char *) block) + Bump_BLOCKHDRSZ;
|
461
|
+
block->endptr = ((char *) block) + blksize;
|
462
|
+
|
463
|
+
/* Mark unallocated space NOACCESS. */
|
464
|
+
VALGRIND_MAKE_MEM_NOACCESS(block->freeptr, blksize - Bump_BLOCKHDRSZ);
|
465
|
+
}
|
466
|
+
|
467
|
+
/*
|
468
|
+
* BumpBlockIsEmpty
|
469
|
+
* Returns true iff 'block' contains no chunks
|
470
|
+
*/
|
471
|
+
static inline bool
|
472
|
+
BumpBlockIsEmpty(BumpBlock *block)
|
473
|
+
{
|
474
|
+
/* it's empty if the freeptr has not moved */
|
475
|
+
return (block->freeptr == ((char *) block + Bump_BLOCKHDRSZ));
|
476
|
+
}
|
477
|
+
|
478
|
+
/*
|
479
|
+
* BumpBlockMarkEmpty
|
480
|
+
* Set a block as empty. Does not free the block.
|
481
|
+
*/
|
482
|
+
static inline void
|
483
|
+
BumpBlockMarkEmpty(BumpBlock *block)
|
484
|
+
{
|
485
|
+
#if defined(USE_VALGRIND) || defined(CLOBBER_FREED_MEMORY)
|
486
|
+
char *datastart = ((char *) block) + Bump_BLOCKHDRSZ;
|
487
|
+
#endif
|
488
|
+
|
489
|
+
#ifdef CLOBBER_FREED_MEMORY
|
490
|
+
wipe_mem(datastart, block->freeptr - datastart);
|
491
|
+
#else
|
492
|
+
/* wipe_mem() would have done this */
|
493
|
+
VALGRIND_MAKE_MEM_NOACCESS(datastart, block->freeptr - datastart);
|
494
|
+
#endif
|
495
|
+
|
496
|
+
/* Reset the block, but don't return it to malloc */
|
497
|
+
block->freeptr = ((char *) block) + Bump_BLOCKHDRSZ;
|
498
|
+
}
|
499
|
+
|
500
|
+
/*
|
501
|
+
* BumpBlockFreeBytes
|
502
|
+
* Returns the number of bytes free in 'block'
|
503
|
+
*/
|
504
|
+
static inline Size
|
505
|
+
BumpBlockFreeBytes(BumpBlock *block)
|
506
|
+
{
|
507
|
+
return (block->endptr - block->freeptr);
|
508
|
+
}
|
509
|
+
|
510
|
+
/*
|
511
|
+
* BumpBlockFree
|
512
|
+
* Remove 'block' from 'set' and release the memory consumed by it.
|
513
|
+
*/
|
514
|
+
static inline void
|
515
|
+
BumpBlockFree(BumpContext *set, BumpBlock *block)
|
516
|
+
{
|
517
|
+
/* Make sure nobody tries to free the keeper block */
|
518
|
+
Assert(!IsKeeperBlock(set, block));
|
519
|
+
|
520
|
+
/* release the block from the list of blocks */
|
521
|
+
dlist_delete(&block->node);
|
522
|
+
|
523
|
+
((MemoryContext) set)->mem_allocated -= ((char *) block->endptr - (char *) block);
|
524
|
+
|
525
|
+
#ifdef CLOBBER_FREED_MEMORY
|
526
|
+
wipe_mem(block, ((char *) block->endptr - (char *) block));
|
527
|
+
#endif
|
528
|
+
|
529
|
+
free(block);
|
530
|
+
}
|
531
|
+
|
532
|
+
/*
|
533
|
+
* BumpFree
|
534
|
+
* Unsupported.
|
535
|
+
*/
|
536
|
+
void
|
537
|
+
BumpFree(void *pointer)
|
538
|
+
{
|
539
|
+
elog(ERROR, "%s is not supported by the bump memory allocator", "pfree");
|
540
|
+
}
|
541
|
+
|
542
|
+
/*
|
543
|
+
* BumpRealloc
|
544
|
+
* Unsupported.
|
545
|
+
*/
|
546
|
+
void *
|
547
|
+
BumpRealloc(void *pointer, Size size, int flags)
|
548
|
+
{
|
549
|
+
elog(ERROR, "%s is not supported by the bump memory allocator", "realloc");
|
550
|
+
return NULL; /* keep compiler quiet */
|
551
|
+
}
|
552
|
+
|
553
|
+
/*
|
554
|
+
* BumpGetChunkContext
|
555
|
+
* Unsupported.
|
556
|
+
*/
|
557
|
+
MemoryContext
|
558
|
+
BumpGetChunkContext(void *pointer)
|
559
|
+
{
|
560
|
+
elog(ERROR, "%s is not supported by the bump memory allocator", "GetMemoryChunkContext");
|
561
|
+
return NULL; /* keep compiler quiet */
|
562
|
+
}
|
563
|
+
|
564
|
+
/*
|
565
|
+
* BumpGetChunkSpace
|
566
|
+
* Unsupported.
|
567
|
+
*/
|
568
|
+
Size
|
569
|
+
BumpGetChunkSpace(void *pointer)
|
570
|
+
{
|
571
|
+
elog(ERROR, "%s is not supported by the bump memory allocator", "GetMemoryChunkSpace");
|
572
|
+
return 0; /* keep compiler quiet */
|
573
|
+
}
|
574
|
+
|
575
|
+
/*
|
576
|
+
* BumpIsEmpty
|
577
|
+
* Is a BumpContext empty of any allocated space?
|
578
|
+
*/
|
579
|
+
bool
|
580
|
+
BumpIsEmpty(MemoryContext context)
|
581
|
+
{
|
582
|
+
BumpContext *set = (BumpContext *) context;
|
583
|
+
dlist_iter iter;
|
584
|
+
|
585
|
+
Assert(BumpIsValid(set));
|
586
|
+
|
587
|
+
dlist_foreach(iter, &set->blocks)
|
588
|
+
{
|
589
|
+
BumpBlock *block = dlist_container(BumpBlock, node, iter.cur);
|
590
|
+
|
591
|
+
if (!BumpBlockIsEmpty(block))
|
592
|
+
return false;
|
593
|
+
}
|
594
|
+
|
595
|
+
return true;
|
596
|
+
}
|
597
|
+
|
598
|
+
/*
|
599
|
+
* BumpStats
|
600
|
+
* Compute stats about memory consumption of a Bump context.
|
601
|
+
*
|
602
|
+
* printfunc: if not NULL, pass a human-readable stats string to this.
|
603
|
+
* passthru: pass this pointer through to printfunc.
|
604
|
+
* totals: if not NULL, add stats about this context into *totals.
|
605
|
+
* print_to_stderr: print stats to stderr if true, elog otherwise.
|
606
|
+
*/
|
607
|
+
void
|
608
|
+
BumpStats(MemoryContext context, MemoryStatsPrintFunc printfunc,
|
609
|
+
void *passthru, MemoryContextCounters *totals, bool print_to_stderr)
|
610
|
+
{
|
611
|
+
BumpContext *set = (BumpContext *) context;
|
612
|
+
Size nblocks = 0;
|
613
|
+
Size totalspace = 0;
|
614
|
+
Size freespace = 0;
|
615
|
+
dlist_iter iter;
|
616
|
+
|
617
|
+
Assert(BumpIsValid(set));
|
618
|
+
|
619
|
+
dlist_foreach(iter, &set->blocks)
|
620
|
+
{
|
621
|
+
BumpBlock *block = dlist_container(BumpBlock, node, iter.cur);
|
622
|
+
|
623
|
+
nblocks++;
|
624
|
+
totalspace += (block->endptr - (char *) block);
|
625
|
+
freespace += (block->endptr - block->freeptr);
|
626
|
+
}
|
627
|
+
|
628
|
+
if (printfunc)
|
629
|
+
{
|
630
|
+
char stats_string[200];
|
631
|
+
|
632
|
+
snprintf(stats_string, sizeof(stats_string),
|
633
|
+
"%zu total in %zu blocks; %zu free; %zu used",
|
634
|
+
totalspace, nblocks, freespace, totalspace - freespace);
|
635
|
+
printfunc(context, passthru, stats_string, print_to_stderr);
|
636
|
+
}
|
637
|
+
|
638
|
+
if (totals)
|
639
|
+
{
|
640
|
+
totals->nblocks += nblocks;
|
641
|
+
totals->totalspace += totalspace;
|
642
|
+
totals->freespace += freespace;
|
643
|
+
}
|
644
|
+
}
|
645
|
+
|
646
|
+
|
647
|
+
#ifdef MEMORY_CONTEXT_CHECKING
|
648
|
+
|
649
|
+
/*
|
650
|
+
* BumpCheck
|
651
|
+
* Walk through chunks and check consistency of memory.
|
652
|
+
*
|
653
|
+
* NOTE: report errors as WARNING, *not* ERROR or FATAL. Otherwise you'll
|
654
|
+
* find yourself in an infinite loop when trouble occurs, because this
|
655
|
+
* routine will be entered again when elog cleanup tries to release memory!
|
656
|
+
*/
|
657
|
+
void
|
658
|
+
BumpCheck(MemoryContext context)
|
659
|
+
{
|
660
|
+
BumpContext *bump = (BumpContext *) context;
|
661
|
+
const char *name = context->name;
|
662
|
+
dlist_iter iter;
|
663
|
+
Size total_allocated = 0;
|
664
|
+
|
665
|
+
/* walk all blocks in this context */
|
666
|
+
dlist_foreach(iter, &bump->blocks)
|
667
|
+
{
|
668
|
+
BumpBlock *block = dlist_container(BumpBlock, node, iter.cur);
|
669
|
+
int nchunks;
|
670
|
+
char *ptr;
|
671
|
+
bool has_external_chunk = false;
|
672
|
+
|
673
|
+
if (IsKeeperBlock(bump, block))
|
674
|
+
total_allocated += block->endptr - (char *) bump;
|
675
|
+
else
|
676
|
+
total_allocated += block->endptr - (char *) block;
|
677
|
+
|
678
|
+
/* check block belongs to the correct context */
|
679
|
+
if (block->context != bump)
|
680
|
+
elog(WARNING, "problem in Bump %s: bogus context link in block %p",
|
681
|
+
name, block);
|
682
|
+
|
683
|
+
/* now walk through the chunks and count them */
|
684
|
+
nchunks = 0;
|
685
|
+
ptr = ((char *) block) + Bump_BLOCKHDRSZ;
|
686
|
+
|
687
|
+
while (ptr < block->freeptr)
|
688
|
+
{
|
689
|
+
MemoryChunk *chunk = (MemoryChunk *) ptr;
|
690
|
+
BumpBlock *chunkblock;
|
691
|
+
Size chunksize;
|
692
|
+
|
693
|
+
/* allow access to the chunk header */
|
694
|
+
VALGRIND_MAKE_MEM_DEFINED(chunk, Bump_CHUNKHDRSZ);
|
695
|
+
|
696
|
+
if (MemoryChunkIsExternal(chunk))
|
697
|
+
{
|
698
|
+
chunkblock = ExternalChunkGetBlock(chunk);
|
699
|
+
chunksize = block->endptr - (char *) MemoryChunkGetPointer(chunk);
|
700
|
+
has_external_chunk = true;
|
701
|
+
}
|
702
|
+
else
|
703
|
+
{
|
704
|
+
chunkblock = MemoryChunkGetBlock(chunk);
|
705
|
+
chunksize = MemoryChunkGetValue(chunk);
|
706
|
+
}
|
707
|
+
|
708
|
+
/* move to the next chunk */
|
709
|
+
ptr += (chunksize + Bump_CHUNKHDRSZ);
|
710
|
+
|
711
|
+
nchunks += 1;
|
712
|
+
|
713
|
+
/* chunks have both block and context pointers, so check both */
|
714
|
+
if (chunkblock != block)
|
715
|
+
elog(WARNING, "problem in Bump %s: bogus block link in block %p, chunk %p",
|
716
|
+
name, block, chunk);
|
717
|
+
}
|
718
|
+
|
719
|
+
if (has_external_chunk && nchunks > 1)
|
720
|
+
elog(WARNING, "problem in Bump %s: external chunk on non-dedicated block %p",
|
721
|
+
name, block);
|
722
|
+
|
723
|
+
}
|
724
|
+
|
725
|
+
Assert(total_allocated == context->mem_allocated);
|
726
|
+
}
|
727
|
+
|
728
|
+
#endif /* MEMORY_CONTEXT_CHECKING */
|